@axzydev/axzy_ui_system 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/dist/index.css +82 -1
  2. package/dist/index.css.map +1 -1
  3. package/package.json +2 -2
  4. package/src/App.tsx +354 -0
  5. package/src/assets/logo.png +0 -0
  6. package/src/assets/react.svg +1 -0
  7. package/src/components/alert/alert.props.ts +13 -0
  8. package/src/components/alert/alert.stories.tsx +41 -0
  9. package/src/components/alert/alert.tsx +53 -0
  10. package/src/components/avatar/avatar.props.ts +14 -0
  11. package/src/components/avatar/avatar.stories.tsx +46 -0
  12. package/src/components/avatar/avatar.tsx +53 -0
  13. package/src/components/badget/badget.props.ts +12 -0
  14. package/src/components/badget/badget.stories.tsx +76 -0
  15. package/src/components/badget/badget.tsx +61 -0
  16. package/src/components/breadcrumbs/breadcrumbs.props.ts +13 -0
  17. package/src/components/breadcrumbs/breadcrumbs.stories.tsx +21 -0
  18. package/src/components/breadcrumbs/breadcrumbs.tsx +34 -0
  19. package/src/components/button/button.props.ts +18 -0
  20. package/src/components/button/button.stories.tsx +174 -0
  21. package/src/components/button/button.tsx +117 -0
  22. package/src/components/calendar/calendar.props.ts +33 -0
  23. package/src/components/calendar/calendar.stories.tsx +91 -0
  24. package/src/components/calendar/calendar.tsx +608 -0
  25. package/src/components/calendar/index.ts +3 -0
  26. package/src/components/card/card.props.ts +13 -0
  27. package/src/components/card/card.stories.tsx +58 -0
  28. package/src/components/card/card.tsx +79 -0
  29. package/src/components/checkbox/checkbox.props.ts +11 -0
  30. package/src/components/checkbox/checkbox.stories.tsx +54 -0
  31. package/src/components/checkbox/checkbox.tsx +52 -0
  32. package/src/components/confirm-dialog/confirm-dialog.props.ts +14 -0
  33. package/src/components/confirm-dialog/confirm-dialog.stories.tsx +33 -0
  34. package/src/components/confirm-dialog/confirm-dialog.tsx +45 -0
  35. package/src/components/data-table/ITDataTable.stories.tsx +213 -0
  36. package/src/components/data-table/dataTable.props.ts +69 -0
  37. package/src/components/data-table/dataTable.tsx +313 -0
  38. package/src/components/date-picker/date-picker.props.ts +30 -0
  39. package/src/components/date-picker/date-picker.stories.tsx +90 -0
  40. package/src/components/date-picker/datePicker.tsx +307 -0
  41. package/src/components/dialog/dialog.props.ts +9 -0
  42. package/src/components/dialog/dialog.stories.tsx +80 -0
  43. package/src/components/dialog/dialog.tsx +88 -0
  44. package/src/components/divider/divider.props.ts +8 -0
  45. package/src/components/divider/divider.stories.tsx +34 -0
  46. package/src/components/divider/divider.tsx +21 -0
  47. package/src/components/drawer/drawer.props.ts +14 -0
  48. package/src/components/drawer/drawer.stories.tsx +41 -0
  49. package/src/components/drawer/drawer.tsx +53 -0
  50. package/src/components/dropfile/dropfile.stories.tsx +75 -0
  51. package/src/components/dropfile/dropfile.tsx +407 -0
  52. package/src/components/empty-state/empty-state.props.ts +9 -0
  53. package/src/components/empty-state/empty-state.stories.tsx +20 -0
  54. package/src/components/empty-state/empty-state.tsx +21 -0
  55. package/src/components/flex/flex.props.ts +22 -0
  56. package/src/components/flex/flex.stories.tsx +71 -0
  57. package/src/components/flex/flex.tsx +79 -0
  58. package/src/components/form-builder/fieldRenderer.tsx +218 -0
  59. package/src/components/form-builder/formBuilder.context.tsx +70 -0
  60. package/src/components/form-builder/formBuilder.props.ts +43 -0
  61. package/src/components/form-builder/formBuilder.stories.tsx +317 -0
  62. package/src/components/form-builder/formBuilder.tsx +186 -0
  63. package/src/components/form-builder/useFormBuilder.ts +80 -0
  64. package/src/components/form-header/form-header.props.ts +5 -0
  65. package/src/components/form-header/form-header.tsx +38 -0
  66. package/src/components/grid/grid.props.ts +17 -0
  67. package/src/components/grid/grid.stories.tsx +72 -0
  68. package/src/components/grid/grid.tsx +69 -0
  69. package/src/components/image/image.props.ts +7 -0
  70. package/src/components/image/image.tsx +38 -0
  71. package/src/components/input/input.props.ts +49 -0
  72. package/src/components/input/input.stories.tsx +115 -0
  73. package/src/components/input/input.tsx +615 -0
  74. package/src/components/layout/layout.props.ts +10 -0
  75. package/src/components/layout/layout.stories.tsx +114 -0
  76. package/src/components/layout/layout.tsx +80 -0
  77. package/src/components/loader/loader.props.ts +8 -0
  78. package/src/components/loader/loader.stories.tsx +105 -0
  79. package/src/components/loader/loader.tsx +108 -0
  80. package/src/components/navbar/navbar.props.ts +37 -0
  81. package/src/components/navbar/navbar.tsx +328 -0
  82. package/src/components/page/page.props.ts +19 -0
  83. package/src/components/page/page.stories.tsx +98 -0
  84. package/src/components/page/page.tsx +90 -0
  85. package/src/components/page-header/page-header.props.ts +11 -0
  86. package/src/components/page-header/page-header.stories.tsx +61 -0
  87. package/src/components/page-header/page-header.tsx +62 -0
  88. package/src/components/pagination/pagination.props.ts +53 -0
  89. package/src/components/pagination/pagination.stories.tsx +111 -0
  90. package/src/components/pagination/pagination.tsx +241 -0
  91. package/src/components/popover/popover.props.ts +12 -0
  92. package/src/components/popover/popover.stories.tsx +25 -0
  93. package/src/components/popover/popover.tsx +45 -0
  94. package/src/components/progress/progress.props.ts +12 -0
  95. package/src/components/progress/progress.stories.tsx +40 -0
  96. package/src/components/progress/progress.tsx +52 -0
  97. package/src/components/radio/radio.props.ts +16 -0
  98. package/src/components/radio/radio.stories.tsx +50 -0
  99. package/src/components/radio/radio.tsx +58 -0
  100. package/src/components/search-select/index.ts +2 -0
  101. package/src/components/search-select/search-select.props.ts +46 -0
  102. package/src/components/search-select/search-select.stories.tsx +129 -0
  103. package/src/components/search-select/search-select.tsx +229 -0
  104. package/src/components/searchTable/components/EditableCell.tsx +149 -0
  105. package/src/components/searchTable/components/PaginationControls.tsx +86 -0
  106. package/src/components/searchTable/components/PaginationInfo.tsx +20 -0
  107. package/src/components/searchTable/components/SearchAndSortBar.tsx +53 -0
  108. package/src/components/searchTable/components/SearchInput.tsx +33 -0
  109. package/src/components/searchTable/components/SortButton.tsx +50 -0
  110. package/src/components/searchTable/components/TableEmptyState.tsx +22 -0
  111. package/src/components/searchTable/components/TableHeader.tsx +35 -0
  112. package/src/components/searchTable/components/TableHeaderCell.tsx +43 -0
  113. package/src/components/searchTable/components/TableRow.tsx +144 -0
  114. package/src/components/searchTable/searchTable.props.ts +56 -0
  115. package/src/components/searchTable/searchTable.tsx +187 -0
  116. package/src/components/segmented-control/segmented-control.props.ts +18 -0
  117. package/src/components/segmented-control/segmented-control.stories.tsx +63 -0
  118. package/src/components/segmented-control/segmented-control.tsx +52 -0
  119. package/src/components/select/select.props.ts +25 -0
  120. package/src/components/select/select.stories.tsx +86 -0
  121. package/src/components/select/select.tsx +150 -0
  122. package/src/components/sidebar/sidebar.props.ts +28 -0
  123. package/src/components/sidebar/sidebar.stories.tsx +117 -0
  124. package/src/components/sidebar/sidebar.tsx +313 -0
  125. package/src/components/skeleton/skeleton.props.ts +12 -0
  126. package/src/components/skeleton/skeleton.stories.tsx +30 -0
  127. package/src/components/skeleton/skeleton.tsx +45 -0
  128. package/src/components/slide/slide.props.ts +45 -0
  129. package/src/components/slide/slide.stories.tsx +121 -0
  130. package/src/components/slide/slide.tsx +109 -0
  131. package/src/components/slider/slider.props.ts +10 -0
  132. package/src/components/slider/slider.stories.tsx +30 -0
  133. package/src/components/slider/slider.tsx +49 -0
  134. package/src/components/stack/stack.props.ts +19 -0
  135. package/src/components/stack/stack.stories.tsx +79 -0
  136. package/src/components/stack/stack.tsx +79 -0
  137. package/src/components/stat-card/stat-card.props.ts +13 -0
  138. package/src/components/stat-card/stat-card.stories.tsx +41 -0
  139. package/src/components/stat-card/stat-card.tsx +44 -0
  140. package/src/components/stepper/stepper.css +26 -0
  141. package/src/components/stepper/stepper.props.ts +29 -0
  142. package/src/components/stepper/stepper.stories.tsx +155 -0
  143. package/src/components/stepper/stepper.tsx +227 -0
  144. package/src/components/table/table.props.ts +43 -0
  145. package/src/components/table/table.stories.tsx +189 -0
  146. package/src/components/table/table.tsx +376 -0
  147. package/src/components/tabs/tabs.props.ts +18 -0
  148. package/src/components/tabs/tabs.stories.tsx +32 -0
  149. package/src/components/tabs/tabs.tsx +74 -0
  150. package/src/components/text/text.props.ts +9 -0
  151. package/src/components/text/text.tsx +20 -0
  152. package/src/components/textarea/textarea.props.ts +15 -0
  153. package/src/components/textarea/textarea.stories.tsx +27 -0
  154. package/src/components/textarea/textarea.tsx +55 -0
  155. package/src/components/theme-provider/themeProvider.props.ts +28 -0
  156. package/src/components/theme-provider/themeProvider.tsx +1854 -0
  157. package/src/components/time-picker/timePicker.props.ts +16 -0
  158. package/src/components/time-picker/timePicker.stories.tsx +131 -0
  159. package/src/components/time-picker/timePicker.tsx +317 -0
  160. package/src/components/toast/toast.css +32 -0
  161. package/src/components/toast/toast.props.ts +13 -0
  162. package/src/components/toast/toast.stories.tsx +138 -0
  163. package/src/components/toast/toast.tsx +87 -0
  164. package/src/components/tooltip/tooltip.props.ts +11 -0
  165. package/src/components/tooltip/tooltip.stories.tsx +20 -0
  166. package/src/components/tooltip/tooltip.tsx +55 -0
  167. package/src/components/topbar/topbar.props.ts +21 -0
  168. package/src/components/topbar/topbar.stories.tsx +80 -0
  169. package/src/components/topbar/topbar.tsx +205 -0
  170. package/src/components/triple-filter/tripleFilter.props.ts +15 -0
  171. package/src/components/triple-filter/tripleFilter.stories.tsx +32 -0
  172. package/src/components/triple-filter/tripleFilter.tsx +50 -0
  173. package/src/hooks/useClickOutside.ts +21 -0
  174. package/src/hooks/useDebouncedSearch.ts +55 -0
  175. package/src/hooks/useEditableRow.ts +157 -0
  176. package/src/hooks/useTableState.ts +122 -0
  177. package/src/index.css +168 -0
  178. package/src/index.ts +165 -0
  179. package/src/main.tsx +9 -0
  180. package/src/showcases/DataShowcases.tsx +260 -0
  181. package/src/showcases/FeedbackShowcases.tsx +268 -0
  182. package/src/showcases/FormShowcases.tsx +1159 -0
  183. package/src/showcases/HomeShowcase.tsx +324 -0
  184. package/src/showcases/LayoutPrimitivesShowcases.tsx +569 -0
  185. package/src/showcases/NavigationShowcases.tsx +193 -0
  186. package/src/showcases/PageShowcases.tsx +207 -0
  187. package/src/showcases/ShowcaseLayout.tsx +139 -0
  188. package/src/showcases/StructureShowcases.tsx +152 -0
  189. package/src/types/badget.types.ts +37 -0
  190. package/src/types/button.types.ts +16 -0
  191. package/src/types/colors.types.ts +3 -0
  192. package/src/types/field.types.ts +103 -0
  193. package/src/types/formik.types.ts +15 -0
  194. package/src/types/input.types.ts +14 -0
  195. package/src/types/loader.types.ts +9 -0
  196. package/src/types/sizes.types.ts +1 -0
  197. package/src/types/table.types.ts +15 -0
  198. package/src/types/toast.types.ts +8 -0
  199. package/src/types/yup.types.ts +11 -0
  200. package/src/utils/color.utils.ts +99 -0
  201. package/src/utils/styles.ts +120 -0
  202. package/src/utils/table.utils.ts +10 -0
@@ -0,0 +1,46 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import ITAvatar from "./avatar";
3
+ import { FaCircle } from "react-icons/fa";
4
+
5
+ const meta: Meta<typeof ITAvatar> = {
6
+ title: "Components/Data Display/ITAvatar",
7
+ component: ITAvatar,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+ type Story = StoryObj<typeof ITAvatar>;
13
+
14
+ export const WithImage: Story = {
15
+ args: {
16
+ src: "https://i.pravatar.cc/150?u=test",
17
+ alt: "User",
18
+ size: "md",
19
+ },
20
+ };
21
+
22
+ export const WithInitials: Story = {
23
+ args: {
24
+ initials: "JD",
25
+ size: "md",
26
+ color: "bg-primary-500",
27
+ },
28
+ };
29
+
30
+ export const WithBadge: Story = {
31
+ args: {
32
+ initials: "AG",
33
+ size: "lg",
34
+ badge: <FaCircle className="text-emerald-500 text-[10px]" />,
35
+ },
36
+ };
37
+
38
+ export const Sizes: Story = {
39
+ render: () => (
40
+ <div className="flex items-end gap-4">
41
+ {(["xs", "sm", "md", "lg", "xl"] as const).map((s) => (
42
+ <ITAvatar key={s} initials="A" size={s} />
43
+ ))}
44
+ </div>
45
+ ),
46
+ };
@@ -0,0 +1,53 @@
1
+ import clsx from "clsx";
2
+ import { ITAvatarProps, AvatarSize } from "./avatar.props";
3
+ import ITText from "@/components/text/text";
4
+
5
+ const sizeMap: Record<AvatarSize, { container: string; text: string }> = {
6
+ xs: { container: "w-6 h-6", text: "text-[10px]" },
7
+ sm: { container: "w-8 h-8", text: "text-xs" },
8
+ md: { container: "w-10 h-10", text: "text-sm" },
9
+ lg: { container: "w-12 h-12", text: "text-base" },
10
+ xl: { container: "w-16 h-16", text: "text-xl" },
11
+ };
12
+
13
+ export default function ITAvatar({
14
+ src,
15
+ alt = "",
16
+ initials,
17
+ size = "md",
18
+ color = "bg-primary-500",
19
+ className,
20
+ badge,
21
+ onClick,
22
+ }: ITAvatarProps) {
23
+ const { container, text } = sizeMap[size];
24
+
25
+ return (
26
+ <div
27
+ className={clsx("relative inline-flex items-center justify-center rounded-full flex-shrink-0", container, className)}
28
+ onClick={onClick}
29
+ role={onClick ? "button" : undefined}
30
+ tabIndex={onClick ? 0 : undefined}
31
+ >
32
+ {src ? (
33
+ <img
34
+ src={src}
35
+ alt={alt}
36
+ className="w-full h-full rounded-full object-cover"
37
+ onError={(e) => {
38
+ e.currentTarget.style.display = "none";
39
+ }}
40
+ />
41
+ ) : (
42
+ <div className={clsx("w-full h-full rounded-full flex items-center justify-center text-white font-semibold", text, color)}>
43
+ <ITText as="span">{initials || alt.charAt(0).toUpperCase() || "?"}</ITText>
44
+ </div>
45
+ )}
46
+ {badge && (
47
+ <div className="absolute -bottom-0.5 -right-0.5">
48
+ {badge}
49
+ </div>
50
+ )}
51
+ </div>
52
+ );
53
+ }
@@ -0,0 +1,12 @@
1
+ import { badgeVariants } from "@/types/badget.types";
2
+ import { ColorsTypes } from "@/types/colors.types";
3
+ import { SizesTypes } from "@/types/sizes.types";
4
+
5
+ export interface ITBadgetProps {
6
+ label?: string;
7
+ children?: React.ReactNode;
8
+ color?: ColorsTypes;
9
+ size?: SizesTypes;
10
+ variant?: keyof typeof badgeVariants;
11
+ className?: string;
12
+ }
@@ -0,0 +1,76 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import ITBadget from './badget';
3
+
4
+ const meta = {
5
+ title: 'Components/Data Display/ITBadge',
6
+ component: ITBadget,
7
+ parameters: {
8
+ layout: 'centered',
9
+ },
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ color: {
13
+ control: 'select',
14
+ options: ['primary', 'secondary', 'success', 'danger', 'warning', 'purple', 'info'],
15
+ },
16
+ variant: {
17
+ control: 'select',
18
+ options: ['filled', 'outlined'],
19
+ },
20
+ size: {
21
+ control: 'select',
22
+ options: ['small', 'medium', 'large'],
23
+ },
24
+ },
25
+ } satisfies Meta<typeof ITBadget>;
26
+
27
+ export default meta;
28
+ type Story = StoryObj<typeof meta>;
29
+
30
+ // 1. Filled (Default)
31
+ export const Filled: Story = {
32
+ args: {
33
+ label: 'Filled Badge',
34
+ color: 'primary',
35
+ variant: 'filled',
36
+ },
37
+ };
38
+
39
+ // 2. Outlined
40
+ export const Outlined: Story = {
41
+ args: {
42
+ label: 'Outlined Badge',
43
+ color: 'primary',
44
+ variant: 'outlined',
45
+ },
46
+ };
47
+
48
+ // 3. All Combinations (Matrix)
49
+ export const AllCombinations: Story = {
50
+ render: (args) => {
51
+ const colors = ['primary', 'secondary', 'success', 'danger', 'warning', 'purple', 'info'];
52
+ const variants = ['filled', 'outlined'];
53
+
54
+ return (
55
+ <div className="flex flex-col gap-8">
56
+ {variants.map((variant) => (
57
+ <div key={variant} className="flex flex-col gap-2">
58
+ <h3 className="text-sm font-bold uppercase text-gray-400">{variant}</h3>
59
+ <div className="flex flex-wrap gap-4 items-center">
60
+ {colors.map((color) => (
61
+ <ITBadget
62
+ key={`${variant}-${color}`}
63
+ {...args}
64
+ color={color as any}
65
+ variant={variant as any}
66
+ label={color.charAt(0).toUpperCase() + color.slice(1)}
67
+ />
68
+ ))}
69
+ </div>
70
+ </div>
71
+ ))}
72
+ </div>
73
+ );
74
+ },
75
+ args: {},
76
+ };
@@ -0,0 +1,61 @@
1
+ // components/ITBadge.tsx
2
+ import clsx from "clsx";
3
+ import { ITBadgetProps } from "./badget.props";
4
+ import {
5
+ badgeSizes,
6
+ } from "@/types/badget.types";
7
+ import { theme } from "@/theme/theme";
8
+ import ITText from "@/components/text/text";
9
+
10
+ export default function ITBadget({
11
+ children,
12
+ label,
13
+ color = "primary",
14
+ size = "medium",
15
+ variant = "filled",
16
+ className,
17
+ }: ITBadgetProps) {
18
+ // Access theme configuration
19
+ const themeBadge = (theme as any).badge || {};
20
+ const config = themeBadge[color] || themeBadge.primary || {};
21
+
22
+ const getStyle = () => {
23
+ const style: React.CSSProperties = {
24
+ fontSize: config.fontSize,
25
+ fontWeight: config.fontWeight,
26
+ padding: config.padding,
27
+ borderRadius: config.borderRadius, // '9999px' in theme
28
+ borderWidth: '1px', // Default border width for consistency
29
+ borderStyle: 'solid',
30
+ borderColor: 'transparent', // Default transparent
31
+ transition: 'all 0.2s',
32
+ };
33
+
34
+ if (variant === "filled") {
35
+ style.backgroundColor = config.backgroundColor;
36
+ style.color = config.color;
37
+ style.borderColor = config.borderColor || 'transparent'; // Some filled badges might have subtle borders
38
+ } else if (variant === "outlined") {
39
+ style.backgroundColor = "transparent";
40
+ // Use the dark text color for both text and border to ensure high contrast
41
+ style.color = config.color;
42
+ style.borderColor = config.color;
43
+ }
44
+
45
+ return style;
46
+ };
47
+
48
+ return (
49
+ <span
50
+ className={clsx(
51
+ "inline-flex items-center justify-center",
52
+ // Fallback size if theme doesn't have it (though theme does have it for primary)
53
+ !config.padding ? badgeSizes[size] : "",
54
+ className
55
+ )}
56
+ style={getStyle()}
57
+ >
58
+ {children || <ITText as="span" className={clsx("font-semibold")}>{label}</ITText>}
59
+ </span>
60
+ );
61
+ }
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from "react";
2
+
3
+ export interface ITBreadcrumbItem {
4
+ label: string;
5
+ href?: string;
6
+ onClick?: () => void;
7
+ }
8
+
9
+ export interface ITBreadcrumbsProps {
10
+ items: ITBreadcrumbItem[];
11
+ separator?: ReactNode;
12
+ className?: string;
13
+ }
@@ -0,0 +1,21 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import ITBreadcrumbs from "./breadcrumbs";
3
+
4
+ const meta: Meta<typeof ITBreadcrumbs> = {
5
+ title: "Components/Navigation/ITBreadcrumbs",
6
+ component: ITBreadcrumbs,
7
+ tags: ["autodocs"],
8
+ };
9
+
10
+ export default meta;
11
+ type Story = StoryObj<typeof ITBreadcrumbs>;
12
+
13
+ export const Default: Story = {
14
+ args: {
15
+ items: [
16
+ { label: "Inicio", href: "#" },
17
+ { label: "Usuarios", href: "#" },
18
+ { label: "Editar Perfil" },
19
+ ],
20
+ },
21
+ };
@@ -0,0 +1,34 @@
1
+ import clsx from "clsx";
2
+ import { ITBreadcrumbsProps } from "./breadcrumbs.props";
3
+ import { FaChevronRight } from "react-icons/fa";
4
+ import ITText from "@/components/text/text";
5
+
6
+ export default function ITBreadcrumbs({
7
+ items,
8
+ separator = <FaChevronRight size={10} />,
9
+ className,
10
+ }: ITBreadcrumbsProps) {
11
+ return (
12
+ <nav className={clsx("flex items-center gap-1.5 text-sm", className)} aria-label="Breadcrumb">
13
+ {items.map((item, i) => {
14
+ const isLast = i === items.length - 1;
15
+ return (
16
+ <span key={i} className="flex items-center gap-1.5">
17
+ {i > 0 && <span className="text-slate-300 dark:text-slate-600">{separator}</span>}
18
+ {isLast ? (
19
+ <ITText as="span" className="text-slate-800 dark:text-white font-semibold">{item.label}</ITText>
20
+ ) : item.href ? (
21
+ <a href={item.href} className="text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 transition-colors">
22
+ <ITText as="span">{item.label}</ITText>
23
+ </a>
24
+ ) : (
25
+ <button onClick={item.onClick} className="text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 transition-colors">
26
+ <ITText as="span">{item.label}</ITText>
27
+ </button>
28
+ )}
29
+ </span>
30
+ );
31
+ })}
32
+ </nav>
33
+ );
34
+ }
@@ -0,0 +1,18 @@
1
+ import { buttonVariants } from "@/types/button.types";
2
+ import { ColorsTypes } from "@app/types/colors.types";
3
+ import { SizesTypes } from "@app/types/sizes.types";
4
+
5
+ export interface ITButtonProps {
6
+ label?: string
7
+ children?: React.ReactNode;
8
+ icon?: React.ReactNode;
9
+ onClick?: () => void;
10
+ color?: ColorsTypes;
11
+ size?: SizesTypes;
12
+ variant?: keyof typeof buttonVariants;
13
+ disabled?: boolean;
14
+ className?: string;
15
+ type?: "submit" | "reset" | "button" | undefined;
16
+ ariaLabel?: string;
17
+ title?: string;
18
+ }
@@ -0,0 +1,174 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import ITButton from './button';
3
+
4
+ const meta = {
5
+ title: 'Components/Actions/ITButton',
6
+ component: ITButton,
7
+ parameters: {
8
+ layout: 'centered',
9
+ },
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ color: {
13
+ control: 'select',
14
+ options: ['primary', 'secondary', 'success', 'danger', 'warning', 'purple', 'info'],
15
+ description: 'The semantic color of the button',
16
+ },
17
+ variant: {
18
+ control: 'select',
19
+ options: ['filled', 'outlined', 'raised', 'rounded', 'text', 'raised-text', 'icon-only', 'link'],
20
+ description: 'The visual style variant',
21
+ },
22
+ size: {
23
+ control: 'select',
24
+ options: ['small', 'medium', 'large'],
25
+ description: 'Button size (padding/font)',
26
+ },
27
+ label: { control: 'text' },
28
+ disabled: { control: 'boolean' },
29
+ },
30
+ } satisfies Meta<typeof ITButton>;
31
+
32
+ export default meta;
33
+ type Story = StoryObj<typeof meta>;
34
+
35
+ // 1. Filled (Default)
36
+ export const Filled: Story = {
37
+ args: {
38
+ label: 'Filled Button',
39
+ color: 'primary',
40
+ variant: 'filled',
41
+ },
42
+ };
43
+
44
+ // 2. Outlined
45
+ export const Outlined: Story = {
46
+ args: {
47
+ label: 'Outlined Button',
48
+ color: 'primary',
49
+ variant: 'outlined',
50
+ },
51
+ };
52
+
53
+ // 3. Raised (Shadow)
54
+ export const Raised: Story = {
55
+ args: {
56
+ label: 'Raised Button',
57
+ color: 'primary',
58
+ variant: 'raised',
59
+ },
60
+ };
61
+
62
+ // 4. Rounded (Pill)
63
+ export const Rounded: Story = {
64
+ args: {
65
+ label: 'Rounded Button',
66
+ color: 'success',
67
+ variant: 'rounded',
68
+ },
69
+ };
70
+
71
+ // 5. Text (Ghost)
72
+ export const Text: Story = {
73
+ args: {
74
+ label: 'Text Button',
75
+ color: 'info',
76
+ variant: 'text',
77
+ },
78
+ };
79
+
80
+ // 6. Raised Text (Elevated White)
81
+ export const RaisedText: Story = {
82
+ args: {
83
+ label: 'Raised Text',
84
+ color: 'warning',
85
+ variant: 'raised-text',
86
+ },
87
+ };
88
+
89
+ // 7. With Icon (icon prop + label)
90
+ export const WithIcon: Story = {
91
+ args: {
92
+ label: 'Guardar',
93
+ color: 'primary',
94
+ variant: 'filled',
95
+ icon: <span style={{ fontSize: '1em' }}>💾</span>,
96
+ },
97
+ };
98
+
99
+ // 8. Icon Only
100
+ export const IconOnly: Story = {
101
+ args: {
102
+ color: 'danger',
103
+ variant: 'icon-only',
104
+ children: <span style={{ fontSize: '1.2em' }}>★</span>,
105
+ ariaLabel: 'Favorite',
106
+ },
107
+ };
108
+
109
+ // 8. Link
110
+ export const Link: Story = {
111
+ args: {
112
+ label: 'Link Button',
113
+ color: 'primary',
114
+ variant: 'link',
115
+ },
116
+ };
117
+
118
+ // 9. All Colors Showcase (Kitchen Sink for colors)
119
+ export const AllColors: Story = {
120
+ render: (args) => (
121
+ <div className="flex flex-wrap gap-4">
122
+ {['primary', 'secondary', 'success', 'danger', 'warning', 'purple', 'info'].map((color) => (
123
+ <ITButton key={color} {...args} color={color as any} label={color.charAt(0).toUpperCase() + color.slice(1)} />
124
+ ))}
125
+ </div>
126
+ ),
127
+ args: {
128
+ variant: 'filled',
129
+ },
130
+ };
131
+
132
+ // 9. Disabled
133
+ export const Disabled: Story = {
134
+ args: {
135
+ label: 'Disabled Button',
136
+ disabled: true,
137
+ color: 'primary',
138
+ variant: 'filled',
139
+ },
140
+ };
141
+
142
+ // 10. All Combinations (Matrix)
143
+ export const AllCombinations: Story = {
144
+ render: (args) => {
145
+ const colors = ['primary', 'secondary', 'success', 'danger', 'warning', 'purple', 'info'];
146
+ const variants = ['filled', 'outlined', 'raised', 'rounded', 'text', 'raised-text', 'icon-only', 'link'];
147
+
148
+ return (
149
+ <div className="flex flex-col gap-8">
150
+ {variants.map((variant) => (
151
+ <div key={variant} className="flex flex-col gap-2">
152
+ <h3 className="text-sm font-bold uppercase text-gray-400">{variant}</h3>
153
+ <div className="flex flex-wrap gap-4 items-center">
154
+ {colors.map((color) => (
155
+ <ITButton
156
+ key={`${variant}-${color}`}
157
+ {...args}
158
+ color={color as any}
159
+ variant={variant as any}
160
+ label={variant === 'icon-only' ? undefined : (color.charAt(0).toUpperCase() + color.slice(1))}
161
+ ariaLabel={variant === 'icon-only' ? color : undefined}
162
+ >
163
+ {variant === 'icon-only' ? <span style={{ fontSize: '1.2em' }}>★</span> : undefined}
164
+ </ITButton>
165
+ ))}
166
+ </div>
167
+ </div>
168
+ ))}
169
+ </div>
170
+ );
171
+ },
172
+ args: {},
173
+ };
174
+
@@ -0,0 +1,117 @@
1
+ import {
2
+ buttonSizes,
3
+ buttonVariants,
4
+ } from "@app/types/button.types";
5
+ import clsx from "clsx";
6
+ import { useState } from "react";
7
+ import { theme } from "@/theme/theme";
8
+ import { ITButtonProps } from "./button.props";
9
+ import ITText from "@/components/text/text";
10
+
11
+ export default function ITButton({
12
+ children,
13
+ label,
14
+ icon,
15
+ onClick,
16
+ type = "button",
17
+ color = "primary",
18
+ size = "medium",
19
+ disabled = false,
20
+ className,
21
+ variant = "filled",
22
+ ariaLabel,
23
+ title,
24
+ }: ITButtonProps) {
25
+ const [isHovered, setIsHovered] = useState(false);
26
+ const [isFocused, setIsFocused] = useState(false);
27
+
28
+ // Get specific button config from theme
29
+ const themeBtn = theme.button as any;
30
+ const themeConfig = themeBtn[color] || themeBtn.primary;
31
+
32
+ // Determine if the button should look "filled" (solid bg) or "outlined/text" (transparent/white bg)
33
+ const isSolid = ["filled", "raised", "rounded", "icon-only"].includes(variant || "filled");
34
+ const isOutlined = variant === "outlined";
35
+ const isText = variant === "text" || variant === "link";
36
+ const isRaisedText = variant === "raised-text";
37
+
38
+ const getStyle = () => {
39
+ // if (disabled) return {}; // Removed to allow styles to render with opacity
40
+
41
+ const mainColor = themeConfig.backgroundColor; // The vibrant color
42
+ const textColor = themeConfig.color; // Usually white for filled
43
+
44
+ let style: React.CSSProperties = {
45
+ // fontSize: themeConfig.fontSize, // Removed to allow size prop to control font size
46
+ fontWeight: themeConfig.fontWeight,
47
+ // padding: themeConfig.padding, // Removed to allow size prop to control padding
48
+ borderRadius: themeConfig.borderRadius, // Default from theme
49
+ transition: themeConfig.transition || 'all 0.2s',
50
+ };
51
+
52
+ if (variant === "rounded") {
53
+ style.borderRadius = "9999px";
54
+ }
55
+
56
+ if (variant === "icon-only") {
57
+ style.padding = "0.5rem"; // Square padding override
58
+ }
59
+
60
+ if (isSolid) {
61
+ style.backgroundColor = (isHovered && !disabled) ? themeConfig.hover : mainColor;
62
+ style.color = textColor;
63
+ } else if (isOutlined) {
64
+ style.backgroundColor = "transparent";
65
+ style.color = mainColor;
66
+ style.borderColor = mainColor;
67
+ if (isHovered && !disabled) {
68
+ style.backgroundColor = `${mainColor}10`; // 10% opacity
69
+ }
70
+ } else if (isText) {
71
+ style.backgroundColor = (isHovered && !disabled) ? `${mainColor}10` : "transparent";
72
+ style.color = mainColor;
73
+ } else if (isRaisedText) {
74
+ style.backgroundColor = "var(--card-bg, #ffffff)";
75
+ style.color = mainColor;
76
+ if (isHovered && !disabled) style.backgroundColor = "var(--card-header-bg, #f8fafc)";
77
+ }
78
+
79
+ // Apply focus style from theme (box-shadow ring)
80
+ if (isFocused && themeConfig.focus && !disabled) {
81
+ style.boxShadow = themeConfig.focus;
82
+ }
83
+
84
+ return style;
85
+ };
86
+
87
+ return (
88
+ <button
89
+ type={type}
90
+ className={clsx(
91
+ "focus:outline-none", // Removed focus:ring-2 focus:ring-offset-2 to use theme style
92
+ // Apply variant base styles (border, shadow, rounded-full)
93
+ buttonVariants[variant || "filled"],
94
+ // Apply size classes (padding/font-size)
95
+ buttonSizes[size],
96
+ className,
97
+ { "opacity-50 cursor-not-allowed": disabled }
98
+ )}
99
+ style={getStyle()}
100
+ onMouseEnter={() => setIsHovered(true)}
101
+ onMouseLeave={() => setIsHovered(false)}
102
+ onFocus={() => setIsFocused(true)}
103
+ onBlur={() => setIsFocused(false)}
104
+ onClick={onClick}
105
+ disabled={disabled}
106
+ aria-label={ariaLabel || label}
107
+ title={title || ariaLabel || label}
108
+ >
109
+ {children || (
110
+ <span className={clsx("inline-flex items-center gap-1.5 font-semibold", { "opacity-50": disabled })}>
111
+ {icon && <span className="flex-shrink-0">{icon}</span>}
112
+ <ITText as="span">{label}</ITText>
113
+ </span>
114
+ )}
115
+ </button>
116
+ );
117
+ }
@@ -0,0 +1,33 @@
1
+ import { ColorsTypes } from "@/types/colors.types";
2
+
3
+ export interface CalendarEvent {
4
+ id: string;
5
+ title: string;
6
+ start: Date | string; // Date object or ISO string
7
+ end: Date | string;
8
+ color?: string; // Hex or tailwind class
9
+ data?: any; // Extra data for callbacks
10
+ }
11
+
12
+ export interface ITCalendarProps {
13
+ // Scheduler Props
14
+ events?: CalendarEvent[];
15
+ mode?: 'week' | 'day' | 'month'; // 'month' for picker
16
+ onEventClick?: (event: CalendarEvent) => void;
17
+ onSlotClick?: (date: Date) => void;
18
+ onSlotHover?: (date: Date) => void;
19
+ onSelectRange?: (start: Date, end: Date) => void;
20
+
21
+ // Picker Props (Legacy/DatePicker support)
22
+ value?: Date;
23
+ onChange?: (date: Date) => void;
24
+ selectionMode?: 'single' | 'range';
25
+ startDate?: Date;
26
+ endDate?: Date;
27
+ minDate?: Date;
28
+ maxDate?: Date;
29
+
30
+ className?: string;
31
+ disabled?: boolean;
32
+ variant?: ColorsTypes;
33
+ }