@js-empire/emperor-ui 1.2.2 → 1.2.4

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 (157) hide show
  1. package/.cursor/rules/code-conventions.mdc +50 -0
  2. package/README.md +0 -15
  3. package/dist/emperor-ui.js +119 -71
  4. package/dist/emperor-ui.umd.cjs +27 -13
  5. package/dist/globals.css +1 -1
  6. package/dist/index-BXtdEByK.js +5 -0
  7. package/dist/index-CDB93OLO.js +55965 -0
  8. package/dist/index-CYORMghp.js +290 -0
  9. package/dist/index.d.ts +338 -36
  10. package/dist/src-UW24ZMRV-C1Pn8-w8.js +5 -0
  11. package/package.json +32 -2
  12. package/src/animations/blink.ts +26 -0
  13. package/src/animations/floating.ts +12 -0
  14. package/src/animations/index.ts +2 -0
  15. package/src/components/atoms/brand/brand.tsx +1 -1
  16. package/src/components/atoms/color-picker/color-picker.tsx +13 -0
  17. package/src/components/atoms/color-picker/free-color-picker.tsx +60 -0
  18. package/src/components/atoms/color-picker/index.ts +3 -0
  19. package/src/components/atoms/color-picker/preset-color-picker.tsx +64 -0
  20. package/src/components/atoms/color-picker/stories/color-picker.stories.tsx +49 -0
  21. package/src/components/atoms/color-picker/styles/color-picker.css +23 -0
  22. package/src/components/atoms/copy-button/copy-button.tsx +73 -0
  23. package/src/components/atoms/copy-button/index.ts +1 -0
  24. package/src/components/atoms/copy-button/stories/copy-button.stories.tsx +21 -0
  25. package/src/components/atoms/field/field.stories.tsx +27 -0
  26. package/src/components/atoms/field/field.tsx +11 -0
  27. package/src/components/atoms/field/index.ts +1 -0
  28. package/src/components/atoms/field/styles/classes.ts +9 -0
  29. package/src/components/atoms/field/styles/index.ts +1 -0
  30. package/src/components/atoms/filter/filter.tsx +92 -0
  31. package/src/components/atoms/filter/index.ts +3 -0
  32. package/src/components/atoms/filter/stories/filter.stories.tsx +97 -0
  33. package/src/components/atoms/filter/styles/classes.ts +20 -0
  34. package/src/components/atoms/filter/styles/index.ts +1 -0
  35. package/src/components/atoms/filter/units/autocomplete-filter.tsx +39 -0
  36. package/src/components/atoms/filter/units/checkbox-filter.tsx +32 -0
  37. package/src/components/atoms/filter/units/checkbox-group-filter.tsx +37 -0
  38. package/src/components/atoms/filter/units/date-filter.tsx +50 -0
  39. package/src/components/atoms/filter/units/index.ts +9 -0
  40. package/src/components/atoms/filter/units/numeric-filter.tsx +36 -0
  41. package/src/components/atoms/filter/units/range-filter.tsx +36 -0
  42. package/src/components/atoms/filter/units/search-filter.tsx +52 -0
  43. package/src/components/atoms/filter/units/select-filter.tsx +49 -0
  44. package/src/components/atoms/filter/units/switch-filter.tsx +33 -0
  45. package/src/components/atoms/index.ts +5 -0
  46. package/src/components/atoms/theme-switch/index.ts +1 -0
  47. package/src/components/atoms/theme-switch/styles/classes.ts +16 -0
  48. package/src/components/atoms/theme-switch/styles/index.ts +1 -0
  49. package/src/components/atoms/theme-switch/theme-switch.stories.tsx +26 -0
  50. package/src/components/atoms/theme-switch/theme-switch.tsx +54 -0
  51. package/src/components/atoms/uploader/avatar-label.tsx +8 -1
  52. package/src/components/atoms/uploader/stories/uploader.stories.tsx +3 -3
  53. package/src/components/atoms/uploader/upload-file-error-box.tsx +1 -1
  54. package/src/components/atoms/uploader/upload-file-input.tsx +1 -1
  55. package/src/components/atoms/uploader/upload-file-label.tsx +8 -1
  56. package/src/components/atoms/uploader/upload-file-listing.tsx +46 -37
  57. package/src/components/atoms/uploader/view-image-modal.tsx +2 -1
  58. package/src/components/molecules/index.ts +0 -1
  59. package/src/components/molecules/item-card/index.ts +6 -0
  60. package/src/components/molecules/item-card/item-actions-dropdown.tsx +57 -0
  61. package/src/components/molecules/item-card/item-banner.tsx +22 -0
  62. package/src/components/molecules/item-card/item-card-body.tsx +68 -0
  63. package/src/components/molecules/item-card/item-card-footer.tsx +55 -0
  64. package/src/components/molecules/item-card/item-card-header.tsx +61 -0
  65. package/src/components/molecules/item-card/item-card.tsx +83 -3
  66. package/src/components/molecules/item-card/loading-item.tsx +88 -0
  67. package/src/components/molecules/item-card/stories/item-card.stories.tsx +182 -0
  68. package/src/components/molecules/item-card/styles/classes.ts +138 -0
  69. package/src/components/molecules/item-card/styles/index.ts +1 -0
  70. package/src/components/molecules/nav-bar/sub-items-box.tsx +2 -1
  71. package/src/components/molecules/scaffold/index.ts +1 -0
  72. package/src/components/molecules/scaffold/scaffold.tsx +4 -17
  73. package/src/components/molecules/scaffold/styles/index.ts +1 -0
  74. package/src/components/molecules/scaffold/styles/scaffold-classes.ts +10 -0
  75. package/src/components/molecules/side-bar/compact-side-bar.tsx +3 -1
  76. package/src/components/molecules/side-bar/side-bar-drawer.tsx +6 -17
  77. package/src/components/molecules/side-bar/side-bar.stories.tsx +1 -1
  78. package/src/components/organisms/filters/filters.stories.tsx +32 -0
  79. package/src/components/organisms/filters/filters.tsx +36 -0
  80. package/src/components/organisms/filters/index.ts +1 -0
  81. package/src/components/organisms/filters/styles/classes.ts +9 -0
  82. package/src/components/organisms/filters/styles/index.ts +1 -0
  83. package/src/components/organisms/footer/copy-rights-box.tsx +1 -1
  84. package/src/components/organisms/footer/footer.tsx +1 -1
  85. package/src/components/organisms/footer/policies-box.tsx +2 -1
  86. package/src/components/organisms/footer/quick-links-box.tsx +2 -1
  87. package/src/components/organisms/footer/social-links-box.tsx +2 -1
  88. package/src/components/organisms/footer/stories/footer.stories.tsx +1 -1
  89. package/src/components/organisms/header/header.tsx +1 -8
  90. package/src/components/organisms/index.ts +1 -0
  91. package/src/components/organisms/listings/empty-listings.tsx +80 -0
  92. package/src/components/organisms/listings/index.ts +2 -0
  93. package/src/components/organisms/listings/listings.tsx +90 -9
  94. package/src/components/organisms/listings/stories/grid-listings.stories.tsx +153 -0
  95. package/src/components/organisms/listings/stories/list-listings.stories.tsx +171 -0
  96. package/src/components/organisms/listings/styles/classes.ts +41 -3
  97. package/src/constants/animations.ts +14 -0
  98. package/src/constants/card.tsx +26 -0
  99. package/src/constants/defaults.ts +1 -16
  100. package/src/constants/index.ts +2 -0
  101. package/src/hooks/index.ts +3 -0
  102. package/src/hooks/use-filters.ts +20 -0
  103. package/src/hooks/use-search-params-handler.tsx +186 -0
  104. package/src/hooks/use-uploader.tsx +1 -1
  105. package/src/hooks/use-window-size.tsx +53 -0
  106. package/src/i18n/locales/atoms/ar.ts +3 -0
  107. package/src/i18n/locales/atoms/en.ts +3 -0
  108. package/src/i18n/locales/organisms/ar.ts +7 -1
  109. package/src/i18n/locales/organisms/en.ts +7 -1
  110. package/src/mocks/constants.ts +103 -0
  111. package/src/mocks/index.ts +2 -0
  112. package/src/mocks/listings.tsx +154 -0
  113. package/src/mocks/types.ts +64 -0
  114. package/src/providers/config-provider.tsx +0 -8
  115. package/src/providers/emperor-ui-provider.tsx +16 -5
  116. package/src/providers/index.ts +1 -0
  117. package/src/providers/theme-provider.tsx +16 -0
  118. package/src/providers/uploader-provider.tsx +1 -1
  119. package/src/styles/hero.ts +1 -1
  120. package/src/styles/index.css +23 -0
  121. package/src/types/components/atoms/color-picker/color-picker.ts +12 -0
  122. package/src/types/components/atoms/color-picker/index.ts +1 -0
  123. package/src/types/components/atoms/field/field.ts +9 -0
  124. package/src/types/components/atoms/field/index.ts +1 -0
  125. package/src/types/components/atoms/filter/filter.ts +43 -0
  126. package/src/types/components/atoms/filter/index.ts +2 -0
  127. package/src/types/components/atoms/filter/select-filter.ts +8 -0
  128. package/src/types/components/atoms/index.ts +3 -0
  129. package/src/types/components/atoms/uploader.ts +2 -1
  130. package/src/types/components/index.ts +1 -0
  131. package/src/types/components/molecules/index.ts +1 -1
  132. package/src/types/components/molecules/item-card/item-card.ts +50 -0
  133. package/src/types/components/molecules/listings/listings.ts +21 -5
  134. package/src/types/components/molecules/side-bar/side-bar.ts +1 -1
  135. package/src/types/components/molecules/theme-switch/index.ts +1 -0
  136. package/src/types/components/molecules/theme-switch/theme-switch.ts +9 -0
  137. package/src/types/components/organisms/filters/filters.ts +11 -0
  138. package/src/types/components/organisms/filters/index.ts +1 -0
  139. package/src/types/components/organisms/index.ts +1 -0
  140. package/src/types/context/config.ts +3 -4
  141. package/src/types/context/index.ts +0 -1
  142. package/src/types/context/localization.ts +1 -0
  143. package/src/types/shared/components.ts +3 -0
  144. package/src/utils/uploader.ts +1 -1
  145. package/dist/features-animation-uyo1KMg-.js +0 -1938
  146. package/dist/index-B3d8-vnJ.js +0 -1630
  147. package/dist/index-DOwkJus4.js +0 -26528
  148. package/dist/index-DrkA25TM.js +0 -5
  149. package/dist/src-UW24ZMRV-D6kiVea5.js +0 -5
  150. package/src/components/molecules/filter/filter.tsx +0 -6
  151. package/src/components/molecules/filter/index.ts +0 -1
  152. package/src/components/organisms/listings/stories/listings.stories.tsx +0 -30
  153. package/src/main.tsx +0 -3
  154. package/src/mocks/listings.ts +0 -200
  155. package/src/types/components/molecules/filter/filter.ts +0 -9
  156. package/src/types/components/molecules/filter/index.ts +0 -1
  157. package/src/types/context/theme.ts +0 -17
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
- import { Button, cn } from "@heroui/react";
3
+ import { Button } from "@heroui/button";
4
+ import { cn } from "@/utils";
4
5
  import { useUploaderContext } from "@/hooks";
5
6
  import { Eye, Trash2 } from "lucide-react";
6
7
 
@@ -8,48 +9,56 @@ export function UploadFileListing() {
8
9
  const { files, setSelectedFile, handleClearFile, classNames, modal } =
9
10
  useUploaderContext();
10
11
 
11
- return files?.map((file) => {
12
- const isFileViewable =
13
- modal?.onOpen && file?.view && file?.file?.name && file?.type === "image";
12
+ return (
13
+ <ul className={cn("w-full flex flex-col gap-2", classNames?.listing)}>
14
+ {files?.map((file) => {
15
+ const isFileViewable =
16
+ modal?.onOpen &&
17
+ file?.view &&
18
+ file?.file?.name &&
19
+ file?.type === "image";
14
20
 
15
- if (file)
16
- return (
17
- <div
18
- key={file?.file?.name}
19
- className={cn(
20
- "flex justify-between items-center p-2 gap-2 w-full border border-black/30 rounded-lg",
21
- classNames?.listing,
22
- )}
23
- >
24
- <p className="w-full line-clamp-1 text-xs max-w-60">
25
- {file?.file?.name}
26
- </p>
21
+ if (!file) return null;
27
22
 
28
- <Button
29
- isIconOnly
30
- variant="flat"
31
- className="size-8 min-w-8 rounded-full"
32
- color="danger"
33
- onPress={() => handleClearFile(file?.file?.name)}
34
- startContent={<Trash2 className="rounded-lg size-4" />}
35
- />
23
+ return (
24
+ <li
25
+ key={file?.file?.name}
26
+ className={cn(
27
+ "flex justify-between items-center p-2 gap-2 w-full border border-black/30 rounded-lg",
28
+ classNames?.listingItem,
29
+ )}
30
+ >
31
+ <p className="w-full line-clamp-1 text-xs max-w-60">
32
+ {file?.file?.name}
33
+ </p>
36
34
 
37
- {isFileViewable && (
38
35
  <Button
39
36
  isIconOnly
40
37
  variant="flat"
41
- className="size-8 min-w-8 rounded-full"
42
- color="primary"
43
- onPress={() => {
44
- setSelectedFile?.(file);
45
- modal?.onOpen?.();
46
- }}
47
- startContent={<Eye className="rounded-lg size-4" />}
38
+ radius="full"
39
+ className="size-6 min-w-6"
40
+ color="danger"
41
+ onPress={() => handleClearFile(file?.file?.name)}
42
+ startContent={<Trash2 className="rounded-lg size-3" />}
48
43
  />
49
- )}
50
- </div>
51
- );
52
44
 
53
- return null;
54
- });
45
+ {isFileViewable && (
46
+ <Button
47
+ isIconOnly
48
+ variant="flat"
49
+ radius="full"
50
+ className="size-6 min-w-6"
51
+ color="primary"
52
+ onPress={() => {
53
+ setSelectedFile?.(file);
54
+ modal?.onOpen?.();
55
+ }}
56
+ startContent={<Eye className="rounded-lg size-3" />}
57
+ />
58
+ )}
59
+ </li>
60
+ );
61
+ })}
62
+ </ul>
63
+ );
55
64
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
- import { Image, Modal, ModalBody, ModalContent } from "@heroui/react";
3
+ import { Image } from "@heroui/image";
4
+ import { Modal, ModalBody, ModalContent } from "@heroui/modal";
4
5
  import { useEmperorUI, useUploaderContext } from "@/hooks";
5
6
 
6
7
  export function ViewImageModal() {
@@ -1,4 +1,3 @@
1
- export * from "./filter";
2
1
  export * from "./item-card";
3
2
  export * from "./nav-bar";
4
3
  export * from "./side-bar";
@@ -1 +1,7 @@
1
1
  export * from "./item-card";
2
+ export * from "./loading-item";
3
+ export * from "./item-banner";
4
+ export * from "./item-actions-dropdown";
5
+ export * from "./item-card-header";
6
+ export * from "./item-card-body";
7
+ export * from "./item-card-footer";
@@ -0,0 +1,57 @@
1
+ "use client";
2
+
3
+ import { ItemCardProps } from "@/types";
4
+ import { cn } from "@/utils";
5
+ import { Button } from "@heroui/button";
6
+ import {
7
+ Dropdown,
8
+ DropdownTrigger,
9
+ DropdownMenu,
10
+ DropdownItem,
11
+ } from "@heroui/dropdown";
12
+ import { EllipsisVertical } from "lucide-react";
13
+
14
+ export function ItemActionsDropdown({
15
+ actions,
16
+ classNames,
17
+ onActionClick,
18
+ }: Pick<ItemCardProps, "actions" | "classNames" | "onActionClick">) {
19
+ if (!actions || actions?.length === 0) return null;
20
+
21
+ return (
22
+ <Dropdown placement="bottom-end">
23
+ <DropdownTrigger data-slot="emperor-ui-item-card-actions-dropdown-trigger">
24
+ <Button
25
+ isIconOnly
26
+ size="sm"
27
+ variant="flat"
28
+ radius="full"
29
+ className={cn(
30
+ "absolute right-2 top-2 z-10 size-7 min-w-7 backdrop-blur-lg",
31
+ "border border-default-300",
32
+ classNames?.dropdown,
33
+ )}
34
+ >
35
+ <EllipsisVertical className="size-4" />
36
+ </Button>
37
+ </DropdownTrigger>
38
+
39
+ <DropdownMenu
40
+ data-slot="emperor-ui-item-card-actions-dropdown-menu"
41
+ aria-label="Card actions"
42
+ onAction={(key) => onActionClick?.(String(key))}
43
+ items={actions}
44
+ >
45
+ {({ key, label, ...props }) => (
46
+ <DropdownItem
47
+ key={key}
48
+ data-slot="emperor-ui-item-card-actions-dropdown-item"
49
+ textValue={label}
50
+ title={label}
51
+ {...props}
52
+ />
53
+ )}
54
+ </DropdownMenu>
55
+ </Dropdown>
56
+ );
57
+ }
@@ -0,0 +1,22 @@
1
+ "use client";
2
+
3
+ import { ItemCardProps } from "@/types";
4
+ import { cn } from "@/utils";
5
+ import { itemBannerClasses } from "./styles";
6
+
7
+ export function ItemBanner({
8
+ item,
9
+ orientation,
10
+ classNames,
11
+ }: Pick<ItemCardProps, "item" | "orientation" | "classNames">) {
12
+ if (!item?.banner) return null;
13
+
14
+ return (
15
+ <div
16
+ data-slot="emperor-ui-item-card-banner"
17
+ className={cn(itemBannerClasses({ orientation }), classNames?.banner)}
18
+ >
19
+ {item?.banner}
20
+ </div>
21
+ );
22
+ }
@@ -0,0 +1,68 @@
1
+ "use client";
2
+
3
+ import type { ItemCardProps } from "@/types";
4
+ import { cn } from "@/utils";
5
+ import {
6
+ itemBodyClasses,
7
+ itemDescriptionClasses,
8
+ itemPriceClasses,
9
+ itemTitleClasses,
10
+ } from "./styles";
11
+ import { CardBody } from "@heroui/card";
12
+ import { ItemActionsDropdown } from "./item-actions-dropdown";
13
+
14
+ export function ItemCardBody({
15
+ item,
16
+ orientation,
17
+ classNames,
18
+ actions,
19
+ onActionClick,
20
+ }: Pick<
21
+ ItemCardProps,
22
+ "item" | "orientation" | "classNames" | "actions" | "onActionClick"
23
+ >) {
24
+ return (
25
+ <CardBody
26
+ data-slot="emperor-ui-item-card-body"
27
+ className={cn(itemBodyClasses({ orientation }), classNames?.body)}
28
+ >
29
+ {item?.title && (
30
+ <h3
31
+ data-slot="emperor-ui-item-card-title"
32
+ className={cn(itemTitleClasses({ orientation }), classNames?.title)}
33
+ >
34
+ {item?.title}
35
+ </h3>
36
+ )}
37
+
38
+ {item?.description && (
39
+ <p
40
+ data-slot="emperor-ui-item-card-description"
41
+ className={cn(
42
+ itemDescriptionClasses({ orientation }),
43
+ classNames?.description,
44
+ )}
45
+ >
46
+ {item?.description}
47
+ </p>
48
+ )}
49
+
50
+ {item?.price && (
51
+ <p
52
+ data-slot="emperor-ui-item-card-price"
53
+ className={cn(itemPriceClasses({ orientation }), classNames?.price)}
54
+ >
55
+ {item?.price}
56
+ </p>
57
+ )}
58
+
59
+ {orientation === "horizontal" && (
60
+ <ItemActionsDropdown
61
+ actions={actions}
62
+ classNames={classNames}
63
+ onActionClick={onActionClick}
64
+ />
65
+ )}
66
+ </CardBody>
67
+ );
68
+ }
@@ -0,0 +1,55 @@
1
+ "use client";
2
+
3
+ import type { ItemCardProps } from "@/types";
4
+ import { cn } from "@/utils";
5
+ import { itemFooterClasses, itemChipsClasses } from "./styles";
6
+ import { CardFooter } from "@heroui/card";
7
+ import { Chip } from "@heroui/chip";
8
+
9
+ export function ItemCardFooter({
10
+ item,
11
+ orientation,
12
+ classNames,
13
+ }: Pick<ItemCardProps, "item" | "orientation" | "classNames">) {
14
+ return (
15
+ <CardFooter
16
+ data-slot="emperor-ui-item-card-footer"
17
+ className={cn(itemFooterClasses({ orientation }), classNames?.footer)}
18
+ >
19
+ {item?.chips && item?.chips?.length > 0 && (
20
+ <menu
21
+ data-slot="emperor-ui-item-card-chips"
22
+ className={cn(itemChipsClasses({ orientation }), classNames?.chips)}
23
+ >
24
+ {item?.chips?.map(
25
+ (
26
+ {
27
+ label,
28
+ className: chipClassName,
29
+ classNames: chipClassNames,
30
+ ...props
31
+ },
32
+ index,
33
+ ) => (
34
+ <Chip
35
+ key={index}
36
+ data-slot="emperor-ui-item-card-chip"
37
+ className={cn(chipClassName, classNames?.chip)}
38
+ classNames={{
39
+ content: "text-xs mx-1",
40
+ ...chipClassNames,
41
+ }}
42
+ size="sm"
43
+ variant="flat"
44
+ color="primary"
45
+ {...props}
46
+ >
47
+ {label}
48
+ </Chip>
49
+ ),
50
+ )}
51
+ </menu>
52
+ )}
53
+ </CardFooter>
54
+ );
55
+ }
@@ -0,0 +1,61 @@
1
+ "use client";
2
+
3
+ import { CardHeader } from "@heroui/card";
4
+ import { cn } from "@/utils";
5
+ import { itemHeaderClasses } from "./styles";
6
+ import { itemImageWrapperClasses } from "./styles";
7
+ import { Image } from "@heroui/image";
8
+ import { ItemBanner } from "@/components";
9
+ import { ItemActionsDropdown } from "./item-actions-dropdown";
10
+ import type { ItemCardProps } from "@/types";
11
+
12
+ export function ItemCardHeader({
13
+ item,
14
+ orientation,
15
+ classNames,
16
+ actions,
17
+ onActionClick,
18
+ }: Pick<
19
+ ItemCardProps,
20
+ "item" | "orientation" | "classNames" | "actions" | "onActionClick"
21
+ >) {
22
+ return (
23
+ <CardHeader
24
+ data-slot="emperor-ui-item-card-header"
25
+ className={cn(itemHeaderClasses({ orientation }), classNames?.header)}
26
+ >
27
+ {item?.image && (
28
+ <div
29
+ data-slot="emperor-ui-item-card-image-wrapper"
30
+ className={cn(
31
+ itemImageWrapperClasses({ orientation }),
32
+ classNames?.imageWrapper,
33
+ )}
34
+ >
35
+ <Image
36
+ data-slot="emperor-ui-item-card-image"
37
+ src={item?.image?.src}
38
+ alt={item?.image?.alt}
39
+ className={cn("size-full object-cover", classNames?.image)}
40
+ radius="none"
41
+ removeWrapper
42
+ />
43
+ </div>
44
+ )}
45
+
46
+ <ItemBanner
47
+ item={item}
48
+ orientation={orientation}
49
+ classNames={classNames}
50
+ />
51
+
52
+ {orientation === "vertical" && (
53
+ <ItemActionsDropdown
54
+ actions={actions}
55
+ classNames={classNames}
56
+ onActionClick={onActionClick}
57
+ />
58
+ )}
59
+ </CardHeader>
60
+ );
61
+ }
@@ -1,6 +1,86 @@
1
- import type { ItemCardProps } from "@/types";
1
+ "use client";
2
+
3
+ import type { ItemCardOrientation, ItemCardProps } from "@/types";
2
4
  import { cn } from "@/utils";
5
+ import { Card } from "@heroui/card";
6
+ import { motion } from "framer-motion";
7
+ import { itemMainWrapperClasses, itemCardMotionClasses } from "./styles";
8
+ import { getCardMotion } from "@/constants";
9
+ import {
10
+ LoadingItem,
11
+ ItemCardHeader,
12
+ ItemCardBody,
13
+ ItemCardFooter,
14
+ } from "@/components";
15
+ import { useWindowSize } from "@/hooks";
16
+
17
+ export function ItemCard({
18
+ variants,
19
+ isLoading = false,
20
+ className,
21
+ classNames,
22
+ item,
23
+ actions = [],
24
+ hoverEffect = "none",
25
+ onActionClick,
26
+ orientation: defaultOrientation = "vertical",
27
+ }: ItemCardProps) {
28
+ const { isExtraSmallDevice } = useWindowSize();
29
+
30
+ const orientation: ItemCardOrientation = isExtraSmallDevice
31
+ ? "vertical"
32
+ : defaultOrientation;
33
+
34
+ if (isLoading)
35
+ return (
36
+ <LoadingItem
37
+ className={className}
38
+ classNames={classNames}
39
+ orientation={orientation}
40
+ />
41
+ );
42
+
43
+ return (
44
+ <motion.div
45
+ data-slot="emperor-ui-item-card"
46
+ className={cn(
47
+ itemCardMotionClasses({ orientation }),
48
+ classNames?.base,
49
+ className,
50
+ )}
51
+ variants={variants}
52
+ {...getCardMotion({ hoverEffect })}
53
+ >
54
+ <Card
55
+ shadow="sm"
56
+ data-slot="emperor-ui-item-card-main-wrapper"
57
+ className={cn(
58
+ itemMainWrapperClasses({ orientation }),
59
+ classNames?.mainWrapper,
60
+ )}
61
+ >
62
+ <ItemCardHeader
63
+ item={item}
64
+ orientation={orientation}
65
+ classNames={classNames}
66
+ actions={actions}
67
+ onActionClick={onActionClick}
68
+ />
69
+
70
+ <ItemCardBody
71
+ item={item}
72
+ orientation={orientation}
73
+ classNames={classNames}
74
+ actions={actions}
75
+ onActionClick={onActionClick}
76
+ />
3
77
 
4
- export function ItemCard({ className }: ItemCardProps) {
5
- return <div className={cn("", className)}>Item Card Component</div>;
78
+ <ItemCardFooter
79
+ item={item}
80
+ orientation={orientation}
81
+ classNames={classNames}
82
+ />
83
+ </Card>
84
+ </motion.div>
85
+ );
6
86
  }
@@ -0,0 +1,88 @@
1
+ "use client";
2
+
3
+ import { cn } from "@/utils";
4
+ import { Card, CardBody, CardFooter, CardHeader } from "@heroui/card";
5
+ import { Skeleton } from "@heroui/skeleton";
6
+ import { motion } from "framer-motion";
7
+ import {
8
+ itemMainWrapperClasses,
9
+ itemCardMotionClasses,
10
+ itemImageWrapperClasses,
11
+ itemHeaderClasses,
12
+ itemBodyClasses,
13
+ itemFooterClasses,
14
+ itemChipsClasses,
15
+ } from "./styles";
16
+ import { getCardMotion } from "@/constants";
17
+ import type { ItemCardProps } from "@/types";
18
+
19
+ export function LoadingItem({
20
+ className,
21
+ classNames,
22
+ hoverEffect = "none",
23
+ orientation = "vertical",
24
+ }: Pick<
25
+ ItemCardProps,
26
+ "className" | "classNames" | "hoverEffect" | "orientation"
27
+ >) {
28
+ return (
29
+ <motion.div
30
+ {...getCardMotion({ hoverEffect })}
31
+ data-slot="emperor-ui-item-card"
32
+ className={cn(
33
+ itemCardMotionClasses({ orientation }),
34
+ classNames?.base,
35
+ className,
36
+ )}
37
+ >
38
+ <Card
39
+ shadow="sm"
40
+ data-slot="emperor-ui-item-card-main-wrapper"
41
+ className={cn(
42
+ itemMainWrapperClasses({ orientation }),
43
+ classNames?.mainWrapper,
44
+ )}
45
+ >
46
+ <CardHeader
47
+ data-slot="emperor-ui-item-card-header"
48
+ className={cn(itemHeaderClasses({ orientation }), classNames?.header)}
49
+ >
50
+ <Skeleton
51
+ className={cn(
52
+ itemImageWrapperClasses({ orientation }),
53
+ classNames?.imageWrapper,
54
+ )}
55
+ />
56
+ </CardHeader>
57
+
58
+ <CardBody
59
+ data-slot="emperor-ui-item-card-body"
60
+ className={cn(itemBodyClasses({ orientation }), classNames?.body)}
61
+ >
62
+ <div className="flex items-start justify-between gap-2">
63
+ <Skeleton className="h-5 flex-1 rounded-lg" />
64
+ <Skeleton className="size-8 shrink-0 rounded-lg" />
65
+ </div>
66
+
67
+ <Skeleton className="h-4 w-4/5 rounded-lg" />
68
+ <Skeleton className="h-4 w-full rounded-lg" />
69
+ </CardBody>
70
+
71
+ <CardFooter
72
+ data-slot="emperor-ui-item-card-footer"
73
+ className={cn(itemFooterClasses({ orientation }), classNames?.footer)}
74
+ >
75
+ <menu
76
+ data-slot="emperor-ui-item-card-chips"
77
+ className={cn(itemChipsClasses({ orientation }), classNames?.chips)}
78
+ >
79
+ {" "}
80
+ <Skeleton className="h-6 w-16 rounded-full" />
81
+ <Skeleton className="h-6 w-20 rounded-full" />
82
+ <Skeleton className="h-6 w-14 rounded-full" />
83
+ </menu>
84
+ </CardFooter>
85
+ </Card>
86
+ </motion.div>
87
+ );
88
+ }