@neuctra/ui 0.2.2 → 0.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 (105) hide show
  1. package/dist/components/basic/Accordation.d.ts +27 -18
  2. package/dist/components/basic/Alert.d.ts +14 -2
  3. package/dist/components/basic/Avatar.d.ts +5 -3
  4. package/dist/components/basic/Badge.d.ts +3 -3
  5. package/dist/components/basic/Button.d.ts +15 -17
  6. package/dist/components/basic/Card.d.ts +7 -49
  7. package/dist/components/basic/{CheckRadioInput.d.ts → CheckboxGroup.d.ts} +4 -5
  8. package/dist/components/basic/Container.d.ts +28 -26
  9. package/dist/components/basic/Drawer.d.ts +20 -11
  10. package/dist/components/basic/DropDown.d.ts +24 -34
  11. package/dist/components/basic/Flexbox.d.ts +18 -10
  12. package/dist/components/basic/GridView.d.ts +7 -5
  13. package/dist/components/basic/Image.d.ts +31 -6
  14. package/dist/components/basic/Input.d.ts +18 -10
  15. package/dist/components/basic/List.d.ts +11 -3
  16. package/dist/components/basic/Modal.d.ts +8 -2
  17. package/dist/components/basic/RadioGroup.d.ts +25 -0
  18. package/dist/components/basic/Section.d.ts +36 -0
  19. package/dist/components/basic/Stack.d.ts +27 -0
  20. package/dist/components/basic/SwitchGroup.d.ts +25 -0
  21. package/dist/components/basic/Table.d.ts +18 -54
  22. package/dist/components/basic/Tabs.d.ts +28 -28
  23. package/dist/components/basic/Text.d.ts +19 -32
  24. package/dist/index.cjs.js +55 -176
  25. package/dist/index.cjs.js.map +1 -0
  26. package/dist/index.d.ts +19 -18
  27. package/dist/index.es.js +3501 -4738
  28. package/dist/index.es.js.map +1 -0
  29. package/dist/src/components/avatar/AvatarGroup.js +9 -0
  30. package/dist/src/components/avatar/AvatarWithStatus.js +18 -0
  31. package/dist/src/components/basic/Accordation.js +74 -0
  32. package/dist/src/components/basic/Alert.js +141 -0
  33. package/dist/src/components/basic/AudioGallery.js +425 -0
  34. package/dist/src/components/basic/AudioPlayer.js +116 -0
  35. package/dist/src/components/basic/Avatar.js +181 -0
  36. package/dist/src/components/basic/Badge.js +66 -0
  37. package/dist/src/components/basic/Button.js +101 -0
  38. package/dist/src/components/basic/Card.js +47 -0
  39. package/dist/src/components/basic/CheckboxGroup.js +40 -0
  40. package/dist/src/components/basic/Container.js +45 -0
  41. package/dist/src/components/basic/Drawer.js +94 -0
  42. package/dist/src/components/basic/DropDown.js +162 -0
  43. package/dist/src/components/basic/Flexbox.js +67 -0
  44. package/dist/src/components/basic/GridView.js +51 -0
  45. package/dist/src/components/basic/Image.js +95 -0
  46. package/dist/src/components/basic/Input.js +123 -0
  47. package/dist/src/components/basic/List.js +71 -0
  48. package/dist/src/components/basic/Modal.js +86 -0
  49. package/dist/src/components/basic/RadioGroup.js +37 -0
  50. package/dist/src/components/basic/Section.js +100 -0
  51. package/dist/src/components/basic/Stack.js +75 -0
  52. package/dist/src/components/basic/SwitchGroup.js +50 -0
  53. package/dist/src/components/basic/Table.js +32 -0
  54. package/dist/src/components/basic/Tabs.js +149 -0
  55. package/dist/src/components/basic/Text.js +117 -0
  56. package/dist/src/index.js +46 -0
  57. package/dist/types/src/components/basic/Accordation.d.ts +44 -0
  58. package/dist/types/{components → src/components}/basic/Alert.d.ts +14 -2
  59. package/dist/types/{components → src/components}/basic/Avatar.d.ts +5 -3
  60. package/dist/types/{components → src/components}/basic/Badge.d.ts +3 -3
  61. package/dist/types/src/components/basic/Button.d.ts +26 -0
  62. package/dist/types/src/components/basic/Card.d.ts +28 -0
  63. package/dist/types/{components/basic/CheckRadioInput.d.ts → src/components/basic/CheckboxGroup.d.ts} +4 -5
  64. package/dist/types/src/components/basic/Container.d.ts +32 -0
  65. package/dist/types/src/components/basic/Drawer.d.ts +33 -0
  66. package/dist/types/src/components/basic/DropDown.d.ts +53 -0
  67. package/dist/types/src/components/basic/Flexbox.d.ts +25 -0
  68. package/dist/types/{components → src/components}/basic/GridView.d.ts +7 -5
  69. package/dist/types/src/components/basic/Image.d.ts +58 -0
  70. package/dist/types/{components → src/components}/basic/Input.d.ts +18 -10
  71. package/dist/types/{components → src/components}/basic/List.d.ts +11 -3
  72. package/dist/types/{components → src/components}/basic/Modal.d.ts +8 -2
  73. package/dist/types/src/components/basic/RadioGroup.d.ts +25 -0
  74. package/dist/types/src/components/basic/Section.d.ts +36 -0
  75. package/dist/types/src/components/basic/Stack.d.ts +27 -0
  76. package/dist/types/src/components/basic/SwitchGroup.d.ts +25 -0
  77. package/dist/types/src/components/basic/Table.d.ts +23 -0
  78. package/dist/types/src/components/basic/Tabs.d.ts +47 -0
  79. package/dist/types/src/components/basic/Text.d.ts +26 -0
  80. package/dist/types/{index.d.ts → src/index.d.ts} +19 -18
  81. package/dist/types/vite.config.d.ts +2 -0
  82. package/dist/ui.css +1 -1
  83. package/dist/vite.config.js +34 -0
  84. package/package.json +2 -1
  85. package/dist/components/basic/ImageGallery.d.ts +0 -21
  86. package/dist/components/basic/VideoGallery.d.ts +0 -136
  87. package/dist/components/basic/VideoPlayer.d.ts +0 -36
  88. package/dist/types/components/basic/Accordation.d.ts +0 -35
  89. package/dist/types/components/basic/Button.d.ts +0 -28
  90. package/dist/types/components/basic/Card.d.ts +0 -70
  91. package/dist/types/components/basic/Container.d.ts +0 -30
  92. package/dist/types/components/basic/Drawer.d.ts +0 -24
  93. package/dist/types/components/basic/DropDown.d.ts +0 -63
  94. package/dist/types/components/basic/Flexbox.d.ts +0 -17
  95. package/dist/types/components/basic/Image.d.ts +0 -33
  96. package/dist/types/components/basic/ImageGallery.d.ts +0 -21
  97. package/dist/types/components/basic/Table.d.ts +0 -59
  98. package/dist/types/components/basic/Tabs.d.ts +0 -47
  99. package/dist/types/components/basic/Text.d.ts +0 -39
  100. package/dist/types/components/basic/VideoGallery.d.ts +0 -136
  101. package/dist/types/components/basic/VideoPlayer.d.ts +0 -36
  102. /package/dist/types/{components → src/components}/avatar/AvatarGroup.d.ts +0 -0
  103. /package/dist/types/{components → src/components}/avatar/AvatarWithStatus.d.ts +0 -0
  104. /package/dist/types/{components → src/components}/basic/AudioGallery.d.ts +0 -0
  105. /package/dist/types/{components → src/components}/basic/AudioPlayer.d.ts +0 -0
@@ -0,0 +1,37 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export const RadioGroup = ({ name, options, selectedValue, onChange, disabled = false, readOnly = false, required = false, error, className = "", style, labelStyle, iconSize = 20, iconCheckedBgColor = "#2563eb", iconUncheckedBorderColor = "#9ca3af", textColor = "#374151", errorStyle, }) => {
4
+ return (_jsxs("div", { className: className, style: { display: "flex", flexDirection: "column", gap: 8, ...style }, role: "radiogroup", "aria-disabled": disabled, children: [options.map((option) => {
5
+ const isChecked = selectedValue === option.value;
6
+ return (_jsxs("label", { style: {
7
+ display: "flex",
8
+ alignItems: "center",
9
+ justifyContent: "space-between",
10
+ cursor: disabled ? "not-allowed" : "pointer",
11
+ opacity: disabled ? 0.6 : 1,
12
+ gap: 8,
13
+ userSelect: "none",
14
+ ...labelStyle,
15
+ }, children: [_jsx("span", { style: { color: textColor, fontSize: 14 }, children: option.label }), _jsx("input", { type: "radio", name: name, value: option.value, checked: isChecked, disabled: disabled || readOnly, required: required, onChange: () => onChange && onChange(option.value), style: { display: "none" } }), _jsx("span", { style: {
16
+ display: "inline-flex",
17
+ justifyContent: "center",
18
+ alignItems: "center",
19
+ width: iconSize,
20
+ height: iconSize,
21
+ borderRadius: "50%",
22
+ border: `2px solid ${isChecked ? iconCheckedBgColor : iconUncheckedBorderColor}`,
23
+ backgroundColor: isChecked ? iconCheckedBgColor : "transparent",
24
+ transition: "all 0.25s ease",
25
+ }, children: isChecked && (_jsx("span", { style: {
26
+ width: iconSize / 2,
27
+ height: iconSize / 2,
28
+ borderRadius: "50%",
29
+ backgroundColor: "white",
30
+ } })) })] }, option.value));
31
+ }), error && (_jsx("p", { role: "alert", style: {
32
+ color: "#dc2626",
33
+ fontSize: 12,
34
+ marginTop: 4,
35
+ ...errorStyle,
36
+ }, children: error }))] }));
37
+ };
@@ -0,0 +1,100 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useMemo } from "react";
3
+ import { Container } from "./Container";
4
+ /** 🎨 Preset Variants */
5
+ const variantStyles = {
6
+ light: { background: "#ffffff", color: "#111827" },
7
+ dark: { background: "#0f172a", color: "#f9fafb" },
8
+ gradient: {
9
+ background: "linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)",
10
+ color: "#ffffff",
11
+ },
12
+ transparent: { background: "transparent", color: "#111827" },
13
+ primary: { background: "#3b82f6", color: "#ffffff" },
14
+ };
15
+ /** 🧩 Utility: Resolve responsive props safely */
16
+ function resolveResponsive(prop, screen, fallback) {
17
+ if (prop == null)
18
+ return fallback;
19
+ if (typeof prop !== "object")
20
+ return prop;
21
+ return prop[screen] ?? fallback;
22
+ }
23
+ /** 📱 Determine current breakpoint */
24
+ function getScreenSize(width) {
25
+ if (width < 768)
26
+ return "sm";
27
+ if (width < 1024)
28
+ return "md";
29
+ return "lg";
30
+ }
31
+ /**
32
+ * 🧱 Section Component
33
+ * A flexible layout wrapper that supports responsive backgrounds,
34
+ * adaptive padding, and variant-based theming.
35
+ */
36
+ export const Section = ({ title, subtitle, variant = "light", background, overlay, color, paddingY = 60, paddingX = 20, size = "xl", height = "auto", align = "center", borderRadius = 0, className = "", style, children, }) => {
37
+ const [screenSize, setScreenSize] = useState("lg");
38
+ useEffect(() => {
39
+ const updateSize = () => setScreenSize(getScreenSize(window.innerWidth));
40
+ updateSize();
41
+ window.addEventListener("resize", updateSize);
42
+ return () => window.removeEventListener("resize", updateSize);
43
+ }, []);
44
+ const resolvedVariant = resolveResponsive(variant, screenSize, "light");
45
+ const theme = variantStyles[resolvedVariant];
46
+ const resolvedStyles = useMemo(() => {
47
+ const bg = resolveResponsive(background, screenSize, theme.background);
48
+ const textColor = resolveResponsive(color, screenSize, theme.color);
49
+ const overlayColor = resolveResponsive(overlay, screenSize);
50
+ const py = resolveResponsive(paddingY, screenSize, 60);
51
+ const px = resolveResponsive(paddingX, screenSize, 20);
52
+ const alignText = resolveResponsive(align, screenSize, "center");
53
+ const h = resolveResponsive(height, screenSize, "auto");
54
+ const radius = resolveResponsive(borderRadius, screenSize, 0);
55
+ return {
56
+ position: "relative",
57
+ background: bg,
58
+ color: textColor,
59
+ paddingTop: typeof py === "number" ? `${py}px` : py,
60
+ paddingBottom: typeof py === "number" ? `${py}px` : py,
61
+ paddingLeft: typeof px === "number" ? `${px}px` : px,
62
+ paddingRight: typeof px === "number" ? `${px}px` : px,
63
+ textAlign: alignText,
64
+ height: h,
65
+ borderRadius: typeof radius === "number" ? `${radius}px` : radius,
66
+ boxSizing: "border-box",
67
+ overflow: "hidden",
68
+ ...style,
69
+ };
70
+ }, [
71
+ background,
72
+ color,
73
+ overlay,
74
+ paddingY,
75
+ paddingX,
76
+ align,
77
+ height,
78
+ borderRadius,
79
+ theme,
80
+ screenSize,
81
+ style,
82
+ ]);
83
+ const resolvedOverlay = resolveResponsive(overlay, screenSize);
84
+ return (_jsxs("section", { style: resolvedStyles, className: className, children: [resolvedOverlay && (_jsx("div", { style: {
85
+ position: "absolute",
86
+ inset: 0,
87
+ background: resolvedOverlay,
88
+ pointerEvents: "none",
89
+ } })), _jsxs(Container, { size: resolveResponsive(size, screenSize, "xl"), className: "relative z-10", children: [(title || subtitle) && (_jsxs("header", { style: { marginBottom: 32 }, children: [title && (_jsx("h2", { style: {
90
+ fontSize: "2rem",
91
+ fontWeight: 700,
92
+ marginBottom: subtitle ? 8 : 0,
93
+ }, children: title })), subtitle && (_jsx("p", { style: {
94
+ fontSize: "1.125rem",
95
+ color: resolvedVariant === "dark"
96
+ ? "rgba(255,255,255,0.7)"
97
+ : "rgba(0,0,0,0.6)",
98
+ }, children: subtitle }))] })), children] })] }));
99
+ };
100
+ export default Section;
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState, useEffect, useMemo } from "react";
3
+ const getScreenSize = (width) => {
4
+ if (width < 768)
5
+ return "sm";
6
+ if (width < 1024)
7
+ return "md";
8
+ return "lg";
9
+ };
10
+ const resolveResponsive = (prop, screen, fallback) => {
11
+ if (prop == null)
12
+ return fallback;
13
+ if (typeof prop !== "object")
14
+ return prop;
15
+ return prop[screen] ?? fallback;
16
+ };
17
+ export const Stack = ({ direction = { sm: "vertical", md: "horizontal", lg: "horizontal" }, gap = 12, align = "center", justify = "flex-start", wrap = "nowrap", padding, margin, width = "100%", maxWidth, height = "auto", backgroundColor = "transparent", borderRadius, border, boxShadow, overflow, className, style, children, }) => {
18
+ const [screen, setScreen] = useState("lg");
19
+ useEffect(() => {
20
+ const updateScreen = () => setScreen(getScreenSize(window.innerWidth));
21
+ updateScreen();
22
+ window.addEventListener("resize", updateScreen);
23
+ return () => window.removeEventListener("resize", updateScreen);
24
+ }, []);
25
+ const computedStyle = useMemo(() => {
26
+ const toCssValue = (val) => typeof val === "number" ? `${val}px` : val;
27
+ const resolvedDir = resolveResponsive(direction, screen, "vertical");
28
+ const flexDir = resolvedDir === "vertical" ? "column" : "row";
29
+ return {
30
+ display: "flex",
31
+ flexDirection: flexDir,
32
+ alignItems: resolveResponsive(align, screen, "center"),
33
+ justifyContent: resolveResponsive(justify, screen, "flex-start"),
34
+ flexWrap: resolveResponsive(wrap, screen, "nowrap"),
35
+ gap: toCssValue(resolveResponsive(gap, screen, 12)),
36
+ padding: toCssValue(resolveResponsive(padding, screen, undefined)),
37
+ margin: toCssValue(resolveResponsive(margin, screen, undefined)),
38
+ width: resolveResponsive(width, screen, "100%"),
39
+ maxWidth: resolveResponsive(maxWidth, screen, undefined),
40
+ height: resolveResponsive(height, screen, undefined),
41
+ backgroundColor: resolveResponsive(backgroundColor, screen, undefined),
42
+ borderRadius: resolveResponsive(borderRadius, screen, undefined),
43
+ border: resolveResponsive(border, screen, undefined),
44
+ boxShadow: resolveResponsive(boxShadow, screen, undefined),
45
+ overflow: resolveResponsive(overflow, screen, undefined),
46
+ boxSizing: "border-box",
47
+ ...style,
48
+ };
49
+ }, [
50
+ direction,
51
+ gap,
52
+ align,
53
+ justify,
54
+ wrap,
55
+ padding,
56
+ margin,
57
+ width,
58
+ maxWidth,
59
+ height,
60
+ backgroundColor,
61
+ borderRadius,
62
+ border,
63
+ boxShadow,
64
+ overflow,
65
+ style,
66
+ screen,
67
+ ]);
68
+ return (_jsx("div", { className: className, style: computedStyle, children: children }));
69
+ };
70
+ export const HStack = (props) => {
71
+ return _jsx(Stack, { direction: "horizontal", ...props });
72
+ };
73
+ export const VStack = (props) => {
74
+ return _jsx(Stack, { direction: "vertical", ...props });
75
+ };
@@ -0,0 +1,50 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export const SwitchGroup = ({ name, options, selectedValues = [], onChange, disabled = false, readOnly = false, required = false, error, className = "", style, labelStyle, iconSize = 20, iconCheckedBgColor = "#2563eb", switchBgColor = "#d1d5db", textColor = "#374151", errorStyle, }) => {
4
+ const handleChange = (value) => {
5
+ if (!onChange)
6
+ return;
7
+ const updatedValues = selectedValues.includes(value)
8
+ ? selectedValues.filter((v) => v !== value)
9
+ : [...selectedValues, value];
10
+ onChange(updatedValues);
11
+ };
12
+ return (_jsxs("div", { className: className, style: { display: "flex", flexDirection: "column", gap: 8, ...style }, role: "group", "aria-disabled": disabled, children: [options.map((option) => {
13
+ const isChecked = selectedValues.includes(option.value);
14
+ return (_jsxs("label", { style: {
15
+ display: "flex",
16
+ alignItems: "center",
17
+ justifyContent: "space-between",
18
+ cursor: disabled ? "not-allowed" : "pointer",
19
+ opacity: disabled ? 0.6 : 1,
20
+ gap: 8,
21
+ userSelect: "none",
22
+ ...labelStyle,
23
+ }, children: [_jsx("span", { style: { color: textColor, fontSize: 14 }, children: option.label }), _jsx("input", { type: "checkbox", name: name, value: option.value, checked: isChecked, disabled: disabled || readOnly, required: required, onChange: () => handleChange(option.value), style: { display: "none" } }), _jsx("span", { style: {
24
+ position: "relative",
25
+ width: iconSize * 2,
26
+ height: iconSize * 1.1,
27
+ borderRadius: 9999,
28
+ backgroundColor: isChecked ? iconCheckedBgColor : switchBgColor,
29
+ transition: "background-color 0.25s ease",
30
+ }, children: _jsx("span", { style: {
31
+ position: "absolute",
32
+ top: "50%",
33
+ left: isChecked
34
+ ? `calc(100% - ${iconSize - 4}px - 2px)`
35
+ : "2px",
36
+ transform: "translateY(-50%)",
37
+ width: iconSize - 4,
38
+ height: iconSize - 4,
39
+ borderRadius: "50%",
40
+ backgroundColor: "#fff",
41
+ boxShadow: "0 1px 2px rgba(0,0,0,0.3)",
42
+ transition: "left 0.25s ease",
43
+ } }) })] }, option.value));
44
+ }), error && (_jsx("p", { role: "alert", style: {
45
+ color: "#dc2626",
46
+ fontSize: 12,
47
+ marginTop: 4,
48
+ ...errorStyle,
49
+ }, children: error }))] }));
50
+ };
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const Table = ({ children, style, className }) => (_jsx("table", { className: className, style: {
3
+ width: "100%",
4
+ borderCollapse: "collapse",
5
+ borderSpacing: 0,
6
+ ...style,
7
+ }, children: children }));
8
+ export const THead = ({ children, style, className }) => (_jsx("thead", { className: className, style: {
9
+ backgroundColor: "#f9fafb",
10
+ borderBottom: "2px solid #e5e7eb",
11
+ ...style,
12
+ }, children: children }));
13
+ export const TBody = ({ children, style, className }) => (_jsx("tbody", { className: className, style: style, children: children }));
14
+ export const TRow = ({ children, style, className }) => (_jsx("tr", { className: className, style: {
15
+ borderBottom: "1px solid #e5e7eb",
16
+ transition: "background 0.2s ease",
17
+ ...style,
18
+ }, children: children }));
19
+ export const TH = ({ children, style, className }) => (_jsx("th", { className: className, style: {
20
+ textAlign: "left",
21
+ padding: "12px 16px",
22
+ fontWeight: 600,
23
+ fontSize: "0.875rem",
24
+ color: "#374151",
25
+ ...style,
26
+ }, children: children }));
27
+ export const TD = ({ children, style, className }) => (_jsx("td", { className: className, style: {
28
+ padding: "12px 16px",
29
+ fontSize: "0.875rem",
30
+ color: "#4b5563",
31
+ ...style,
32
+ }, children: children }));
@@ -0,0 +1,149 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect, useRef } from "react";
4
+ /** 💎 Modern, Fully Customizable Tabs */
5
+ export const Tabs = ({ tabs, defaultActive = 0, position = "top", variant = "solid", fullWidth = false, gap = 8, radius = 8, padding = "12px 18px", transitionDuration = 200, elevation = 1, bordered = false, primaryColor = "#2563eb", backgroundColor = "transparent", textColor = "#374151", hoverColor = "#1d4ed8", activeColor = "#ffffff", borderColor = "#e5e7eb", disabledColor = "#9ca3af", responsiveBreakpoint = 768, showDrawerLabel = "Select Tab", drawerIcon = "☰", onTabChange, className = "", style, tabClassName = "", contentClassName = "", activeTabStyle, inactiveTabStyle, contentStyle, }) => {
6
+ const [active, setActive] = useState(defaultActive);
7
+ const [hovered, setHovered] = useState(null);
8
+ const [isMobile, setIsMobile] = useState(false);
9
+ const [drawerOpen, setDrawerOpen] = useState(false);
10
+ const containerRef = useRef(null);
11
+ /** 📱 Responsive detection */
12
+ useEffect(() => {
13
+ const check = () => setIsMobile(window.innerWidth <= responsiveBreakpoint);
14
+ check();
15
+ window.addEventListener("resize", check);
16
+ return () => window.removeEventListener("resize", check);
17
+ }, [responsiveBreakpoint]);
18
+ /** 🎛 Handle tab change */
19
+ const handleChange = (i) => {
20
+ if (tabs[i].disabled)
21
+ return;
22
+ setActive(i);
23
+ onTabChange?.(i);
24
+ if (isMobile)
25
+ setDrawerOpen(false);
26
+ };
27
+ /** ⚡ Keyboard navigation */
28
+ const handleKeyDown = (e, i) => {
29
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
30
+ e.preventDefault();
31
+ handleChange((i + 1) % tabs.length);
32
+ }
33
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
34
+ e.preventDefault();
35
+ handleChange((i - 1 + tabs.length) % tabs.length);
36
+ }
37
+ };
38
+ /** 🎨 Base styles */
39
+ const baseTab = {
40
+ padding,
41
+ borderRadius: radius,
42
+ cursor: "pointer",
43
+ display: "flex",
44
+ alignItems: "center",
45
+ gap: 8,
46
+ justifyContent: "center",
47
+ fontWeight: 500,
48
+ transition: `all ${transitionDuration}ms ease`,
49
+ background: "transparent",
50
+ border: variant === "outline" ? `1px solid ${borderColor}` : "none",
51
+ borderBottom: variant === "underline" ? `2px solid transparent` : undefined,
52
+ color: textColor,
53
+ width: fullWidth ? "100%" : "auto",
54
+ userSelect: "none",
55
+ };
56
+ const activeTab = {
57
+ background: variant === "solid" ? primaryColor : "transparent",
58
+ color: activeColor,
59
+ borderBottom: variant === "underline" ? `2px solid ${primaryColor}` : undefined,
60
+ boxShadow: elevation > 0 ? `0 ${elevation}px ${elevation * 4}px ${primaryColor}33` : undefined,
61
+ ...activeTabStyle,
62
+ };
63
+ const inactiveTab = {
64
+ ...(variant === "outline"
65
+ ? { borderColor }
66
+ : variant === "underline"
67
+ ? { borderBottomColor: "transparent" }
68
+ : {}),
69
+ ...inactiveTabStyle,
70
+ };
71
+ const hoverTab = {
72
+ color: hoverColor,
73
+ background: variant === "solid"
74
+ ? `${primaryColor}11`
75
+ : variant === "outline"
76
+ ? `${primaryColor}11`
77
+ : "transparent",
78
+ };
79
+ const disabledTab = {
80
+ color: disabledColor,
81
+ cursor: "not-allowed",
82
+ opacity: 0.6,
83
+ };
84
+ const contentBox = {
85
+ flexGrow: 1,
86
+ borderTop: bordered && position === "top" ? `1px solid ${borderColor}` : undefined,
87
+ borderLeft: bordered && position === "left" ? `1px solid ${borderColor}` : undefined,
88
+ borderRight: bordered && position === "right" ? `1px solid ${borderColor}` : undefined,
89
+ borderRadius: radius,
90
+ ...contentStyle,
91
+ };
92
+ /** 🧱 Layout */
93
+ const isVertical = position === "left" || position === "right";
94
+ const layoutDir = isVertical ? "row" : "column";
95
+ return (_jsxs("div", { ref: containerRef, className: `modern-tabs ${className}`, style: {
96
+ display: "flex",
97
+ flexDirection: isVertical ? (position === "right" ? "row-reverse" : "row") : "column",
98
+ background: backgroundColor,
99
+ border: bordered ? `1px solid ${borderColor}` : undefined,
100
+ borderRadius: radius,
101
+ overflow: "hidden",
102
+ ...style,
103
+ }, children: [_jsx("style", { children: `
104
+ @keyframes tab-fade {
105
+ from { opacity: 0; transform: translateY(5px); }
106
+ to { opacity: 1; transform: translateY(0); }
107
+ }
108
+ .modern-tabs__content {
109
+ animation: tab-fade ${transitionDuration}ms ease;
110
+ }
111
+ ` }), isMobile ? (_jsxs("div", { style: { width: "100%", padding: 8 }, children: [_jsxs("button", { onClick: () => setDrawerOpen(!drawerOpen), style: {
112
+ ...baseTab,
113
+ ...activeTab,
114
+ justifyContent: "space-between",
115
+ width: "100%",
116
+ fontSize: 16,
117
+ }, children: [showDrawerLabel, _jsx("span", { children: drawerIcon })] }), drawerOpen && (_jsx("div", { style: {
118
+ display: "flex",
119
+ flexDirection: "column",
120
+ marginTop: 8,
121
+ gap,
122
+ }, children: tabs.map((tab, i) => {
123
+ const isActive = i === active;
124
+ const isHovered = hovered === i;
125
+ const isDisabled = tab.disabled;
126
+ return (_jsxs("button", { disabled: isDisabled, onClick: () => handleChange(i), onKeyDown: (e) => handleKeyDown(e, i), onMouseEnter: () => setHovered(i), onMouseLeave: () => setHovered(null), className: tabClassName, style: {
127
+ ...baseTab,
128
+ ...(isActive ? activeTab : inactiveTab),
129
+ ...(isHovered && !isActive && !isDisabled ? hoverTab : {}),
130
+ ...(isDisabled ? disabledTab : {}),
131
+ }, children: [tab.icon && _jsx("span", { children: tab.icon }), tab.label] }, i));
132
+ }) }))] })) : (_jsx("div", { style: {
133
+ display: "flex",
134
+ flexDirection: isVertical ? "column" : "row",
135
+ gap,
136
+ padding: 8,
137
+ minWidth: isVertical ? 200 : undefined,
138
+ }, children: tabs.map((tab, i) => {
139
+ const isActive = i === active;
140
+ const isHovered = hovered === i;
141
+ const isDisabled = tab.disabled;
142
+ return (_jsxs("button", { disabled: isDisabled, onClick: () => handleChange(i), onKeyDown: (e) => handleKeyDown(e, i), onMouseEnter: () => setHovered(i), onMouseLeave: () => setHovered(null), className: tabClassName, style: {
143
+ ...baseTab,
144
+ ...(isActive ? activeTab : inactiveTab),
145
+ ...(isHovered && !isActive && !isDisabled ? hoverTab : {}),
146
+ ...(isDisabled ? disabledTab : {}),
147
+ }, role: "tab", "aria-selected": isActive, children: [tab.icon && _jsx("span", { children: tab.icon }), tab.label] }, i));
148
+ }) })), _jsx("div", { className: `modern-tabs__content ${contentClassName}`, style: contentBox, role: "tabpanel", children: tabs[active]?.content })] }));
149
+ };
@@ -0,0 +1,117 @@
1
+ import React, { useMemo } from "react";
2
+ /** 🎨 Utility: generate lighter/darker shades */
3
+ function adjustColor(color, amount) {
4
+ return ("#" +
5
+ color
6
+ .replace(/^#/, "")
7
+ .replace(/../g, (hex) => ("0" +
8
+ Math.min(255, Math.max(0, parseInt(hex, 16) + amount)).toString(16)).slice(-2)));
9
+ }
10
+ /** 🌈 Default color palettes */
11
+ const defaultColors = {
12
+ light: {
13
+ default: "#111",
14
+ primary: "#2563eb",
15
+ secondary: "#64748b",
16
+ success: "#16a34a",
17
+ danger: "#dc2626",
18
+ white: "#ffffff",
19
+ muted: "#6b7280",
20
+ },
21
+ dark: {
22
+ default: "#f8fafc",
23
+ primary: "#60a5fa",
24
+ secondary: "#94a3b8",
25
+ success: "#22c55e",
26
+ danger: "#f87171",
27
+ white: "#ffffff",
28
+ muted: "#9ca3af",
29
+ },
30
+ };
31
+ /** 💬 Main Component (HTML-only tags) */
32
+ export function Text({ as, children, color = "default", size = "md", weight = "normal", align = "left", transform = "none", italic = false, underline = false, strikethrough = false, truncate = false, selectable = true, hoverable = false, onClick, darkMode = false, baseColor, className = "", style = {}, ...rest }) {
33
+ // element type as provided (constrained to HTML tags)
34
+ const Element = (as || "p");
35
+ /** 🎨 Dynamic color palette generation */
36
+ const theme = useMemo(() => {
37
+ if (!baseColor)
38
+ return defaultColors[darkMode ? "dark" : "light"];
39
+ const lightMode = {
40
+ default: "#111",
41
+ primary: baseColor,
42
+ secondary: adjustColor(baseColor, -50),
43
+ success: adjustColor(baseColor, -30),
44
+ danger: "#dc2626",
45
+ white: "#ffffff",
46
+ muted: "#6b7280",
47
+ };
48
+ const darkModeTheme = {
49
+ default: "#f8fafc",
50
+ primary: adjustColor(baseColor, 80),
51
+ secondary: adjustColor(baseColor, 120),
52
+ success: adjustColor(baseColor, 100),
53
+ danger: "#f87171",
54
+ white: "#ffffff",
55
+ muted: "#9ca3af",
56
+ };
57
+ return darkMode ? darkModeTheme : lightMode;
58
+ }, [baseColor, darkMode]);
59
+ /** 📏 Font sizes */
60
+ const sizes = {
61
+ xs: "0.75rem",
62
+ sm: "0.875rem",
63
+ md: "1rem",
64
+ lg: "1.25rem",
65
+ xl: "1.5rem",
66
+ "2xl": "2rem",
67
+ };
68
+ /** 💅 Computed styles */
69
+ const computedStyle = {
70
+ color: theme[color] || color,
71
+ fontSize: sizes[size] || size,
72
+ fontWeight: weight,
73
+ textAlign: align,
74
+ textTransform: transform,
75
+ fontStyle: italic ? "italic" : "normal",
76
+ textDecoration: underline ? "underline" : strikethrough ? "line-through" : "none",
77
+ userSelect: selectable ? "text" : "none",
78
+ overflow: truncate ? "hidden" : undefined,
79
+ whiteSpace: truncate ? "nowrap" : undefined,
80
+ textOverflow: truncate ? "ellipsis" : undefined,
81
+ cursor: onClick ? "pointer" : "default",
82
+ transition: "all 0.25s ease-in-out",
83
+ ...style,
84
+ };
85
+ /** 🧠 Hover events (narrow to HTMLElement at runtime) */
86
+ const handleMouseEnter = (e) => {
87
+ if (!hoverable)
88
+ return;
89
+ const target = e.currentTarget;
90
+ if (target instanceof HTMLElement) {
91
+ target.style.opacity = "0.8";
92
+ }
93
+ };
94
+ const handleMouseLeave = (e) => {
95
+ if (!hoverable)
96
+ return;
97
+ const target = e.currentTarget;
98
+ if (target instanceof HTMLElement) {
99
+ target.style.opacity = "1";
100
+ }
101
+ };
102
+ /**
103
+ * Build props object. We cast only once to the correct intrinsic props type.
104
+ * This prevents TypeScript from having to compute giant unions for event types.
105
+ */
106
+ const props = {
107
+ className,
108
+ style: computedStyle,
109
+ onClick,
110
+ onMouseEnter: handleMouseEnter,
111
+ onMouseLeave: handleMouseLeave,
112
+ ...rest,
113
+ };
114
+ // Use React.createElement to avoid JSX generic complexity
115
+ return React.createElement(Element, props, children);
116
+ }
117
+ export default Text;
@@ -0,0 +1,46 @@
1
+ import "./style.css"; // 🔹 Global styles import (keep this as the only CSS import)
2
+ // ==============================
3
+ // ✅ BASIC COMPONENT EXPORTS
4
+ // ==============================
5
+ // Alerts & Notifications
6
+ export { Alert } from "./components/basic/Alert"; // ✅ Finalized
7
+ // Accordions
8
+ export { Accordion } from "./components/basic/Accordation"; // ✅ Finalized
9
+ // Avatars
10
+ export { Avatar, AvatarGroup } from "./components/basic/Avatar"; // ✅ Finalized
11
+ // Audio Components
12
+ export { AudioPlayer } from "./components/basic/AudioPlayer"; // ✅ Finalized
13
+ export { AudioGallery } from "./components/basic/AudioGallery"; // ✅ Finalized
14
+ // Badges
15
+ export { Badge } from "./components/basic/Badge"; // ✅ Finalized
16
+ // Buttons
17
+ export { Button } from "./components/basic/Button"; // ✅ Finalized
18
+ // Cards
19
+ export { Card } from "./components/basic/Card"; // ✅ Finalized
20
+ // ✅ Checkbox, Radio & Switch Components
21
+ export { CheckboxGroup } from "./components/basic/CheckboxGroup";
22
+ export { RadioGroup } from "./components/basic/RadioGroup";
23
+ export { SwitchGroup } from "./components/basic/SwitchGroup";
24
+ // Containers & Layout
25
+ export { Container } from "./components/basic/Container"; // ✅ Finalized
26
+ export { Flexbox } from "./components/basic/Flexbox"; // ✅ Finalized
27
+ export { Stack, HStack, VStack } from "./components/basic/Stack"; // ✅ Finalized
28
+ export { GridView } from "./components/basic/GridView"; // ✅ Finalized
29
+ // Drawers
30
+ export { Drawer, DrawerButton } from "./components/basic/Drawer"; // ✅ Finalized
31
+ // Dropdowns
32
+ export { Dropdown } from "./components/basic/DropDown"; // ✅ Finalized
33
+ // Forms & Inputs
34
+ export { Input } from "./components/basic/Input"; // ✅ Finalized
35
+ // Images
36
+ export { Image } from "./components/basic/Image"; // ✅ Finalized
37
+ // Lists
38
+ export { List } from "./components/basic/List"; // ✅ Finalized
39
+ // Modals
40
+ export { Modal } from "./components/basic/Modal"; // ✅ Finalized
41
+ // Tables
42
+ export { Table, TBody, TD, THead, TH, TRow } from "./components/basic/Table"; // ✅ Finalized
43
+ // Tabs
44
+ export { Tabs } from "./components/basic/Tabs"; // ✅ Finalized
45
+ // Text
46
+ export { Text } from "./components/basic/Text"; // ✅ Finalized
@@ -0,0 +1,44 @@
1
+ import React from "react";
2
+ export interface AccordionItem {
3
+ title: string;
4
+ content: React.ReactNode;
5
+ }
6
+ export interface AccordionProps {
7
+ items: AccordionItem[];
8
+ /** Allow multiple open items */
9
+ allowMultiple?: boolean;
10
+ /** Default open indexes */
11
+ defaultOpen?: number[];
12
+ /** Appearance */
13
+ borderColor?: string;
14
+ backgroundColor?: string;
15
+ textColor?: string;
16
+ hoverBgColor?: string;
17
+ hoverTextColor?: string;
18
+ contentBgColor?: string;
19
+ contentTextColor?: string;
20
+ /** Layout & spacing */
21
+ paddingY?: string | number;
22
+ paddingX?: string | number;
23
+ marginY?: string | number;
24
+ borderRadius?: string | number;
25
+ contentPadding?: string | number;
26
+ /** Typography */
27
+ fontSize?: string | number;
28
+ fontWeight?: string | number;
29
+ contentFontSize?: string | number;
30
+ contentFontWeight?: string | number;
31
+ /** Icon customization */
32
+ iconOpen?: React.ReactNode;
33
+ iconClose?: React.ReactNode;
34
+ iconSize?: string | number;
35
+ /** Motion & style */
36
+ transitionDuration?: string;
37
+ shadow?: string;
38
+ className?: string;
39
+ style?: React.CSSProperties;
40
+ }
41
+ /**
42
+ * 🧠 Industry-standard, minimal, and fully customizable Accordion
43
+ */
44
+ export declare const Accordion: React.FC<AccordionProps>;