@axzydev/axzy_ui_system 1.4.3 → 1.4.5
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.
- package/dist/index.cjs +548 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +57 -3
- package/dist/index.d.ts +57 -3
- package/dist/index.js +511 -342
- package/dist/index.js.map +1 -1
- package/dist/layered.css +3 -0
- package/package.json +1 -1
- package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +28 -0
- package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +169 -0
- package/src/components/organisms/sidebar/sidebar.doc.mdx +1 -0
- package/src/components/organisms/sidebar/sidebar.props.ts +12 -1
- package/src/components/organisms/sidebar/sidebar.tsx +53 -22
- package/src/components/organisms/topbar/topbar.props.ts +6 -0
- package/src/components/organisms/topbar/topbar.tsx +4 -1
- package/src/components/templates/layout/layout.tsx +13 -3
- package/src/index.ts +4 -2
|
@@ -68,6 +68,8 @@ export default function ITSidebar({
|
|
|
68
68
|
header,
|
|
69
69
|
notification,
|
|
70
70
|
brand,
|
|
71
|
+
onToggleCollapse,
|
|
72
|
+
expandOnHover = true,
|
|
71
73
|
}: ITSidebarProps) {
|
|
72
74
|
// Flat appearance: plain surface, no glow/accent bar, narrower panel.
|
|
73
75
|
const flat = useITFlatAppearance();
|
|
@@ -132,6 +134,13 @@ export default function ITSidebar({
|
|
|
132
134
|
}
|
|
133
135
|
}, [navigationItems]);
|
|
134
136
|
|
|
137
|
+
const isSidebarCollapsed = visibleOnMobile ? false : isCollapsed && !(expandOnHover && isHovering);
|
|
138
|
+
const sidebarWidth = isSidebarCollapsed
|
|
139
|
+
? flat ? "w-[72px]" : "w-[88px]"
|
|
140
|
+
: flat ? "w-[248px]" : "w-[280px]";
|
|
141
|
+
// Icon-only rail that never expands on hover: names show in a tooltip.
|
|
142
|
+
const fixedRail = isSidebarCollapsed && !expandOnHover;
|
|
143
|
+
|
|
135
144
|
const toggleExpanded = (itemId: string) => {
|
|
136
145
|
const newExpanded = new Set(expandedItems);
|
|
137
146
|
if (newExpanded.has(itemId)) newExpanded.delete(itemId);
|
|
@@ -141,15 +150,20 @@ export default function ITSidebar({
|
|
|
141
150
|
|
|
142
151
|
const handleItemClick = (item: ITNavigationItem) => {
|
|
143
152
|
if (item.subitems && item.subitems.length > 0) {
|
|
144
|
-
|
|
153
|
+
if (isSidebarCollapsed && !expandOnHover) {
|
|
154
|
+
// Icon-only rail: there is no room for the submenu, so open the
|
|
155
|
+
// sidebar with this group expanded.
|
|
156
|
+
setExpandedItems((prev) => new Set(prev).add(item.id));
|
|
157
|
+
onToggleCollapse?.();
|
|
158
|
+
} else {
|
|
159
|
+
toggleExpanded(item.id);
|
|
160
|
+
}
|
|
145
161
|
} else {
|
|
146
162
|
if (item.action) item.action();
|
|
147
163
|
if (onItemClick) onItemClick(item);
|
|
148
164
|
}
|
|
149
165
|
};
|
|
150
166
|
|
|
151
|
-
const isSidebarCollapsed = visibleOnMobile ? false : (!isHovering && isCollapsed);
|
|
152
|
-
const sidebarWidth = isSidebarCollapsed ? "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
|
|
153
167
|
|
|
154
168
|
const renderSubItem = (subitem: ITNavigationSubItem) => (
|
|
155
169
|
<li key={subitem.id} className="relative">
|
|
@@ -163,7 +177,7 @@ export default function ITSidebar({
|
|
|
163
177
|
style={{
|
|
164
178
|
color: subitem.isActive ? "var(--it-sidebar-active-color, var(--color-secondary-900))" : "var(--it-sidebar-label-color, var(--color-secondary-600))",
|
|
165
179
|
backgroundColor: subitem.isActive ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : 'transparent',
|
|
166
|
-
fontSize: '0.78rem',
|
|
180
|
+
fontSize: flat ? '0.84rem' : '0.78rem',
|
|
167
181
|
fontWeight: subitem.isActive ? 600 : 500,
|
|
168
182
|
letterSpacing: '0.01em',
|
|
169
183
|
marginLeft: subitemConnector === '|' ? '-1px' : '0',
|
|
@@ -181,7 +195,7 @@ export default function ITSidebar({
|
|
|
181
195
|
}
|
|
182
196
|
}}
|
|
183
197
|
>
|
|
184
|
-
{subitem.isActive && subitemConnector === '|' && (
|
|
198
|
+
{subitem.isActive && subitemConnector === '|' && !flat && (
|
|
185
199
|
<div
|
|
186
200
|
className="absolute left-0 top-1/3 bottom-1/3 w-[2.5px] rounded-r-full transition-all"
|
|
187
201
|
style={{
|
|
@@ -357,12 +371,15 @@ export default function ITSidebar({
|
|
|
357
371
|
)}
|
|
358
372
|
|
|
359
373
|
{/* Navigation Items */}
|
|
360
|
-
<nav aria-label="Componentes de la librería" className=
|
|
374
|
+
<nav aria-label="Componentes de la librería" className={`flex-1 py-4 custom-scrollbar ${fixedRail ? "overflow-visible" : "overflow-y-auto overflow-x-hidden"} ${flat && isSidebarCollapsed ? "px-3" : "px-4"}`}>
|
|
361
375
|
<ul className="space-y-1">
|
|
362
376
|
{navigationItems.map((item) => {
|
|
363
377
|
const hasSubmenu = !!item.subitems && item.subitems.length > 0;
|
|
364
378
|
const submenuId = `it-sidebar-submenu-${item.id}`;
|
|
365
379
|
const { className: badgeClassName, ...badgeRest } = item.badgeProps ?? {};
|
|
380
|
+
// Flat + expanded: a parent whose subitem is active stays plain; the
|
|
381
|
+
// subitem carries the highlight. Collapsed, the parent icon shows it.
|
|
382
|
+
const active = !!item.isActive && !(flat && hasSubmenu && !isSidebarCollapsed);
|
|
366
383
|
return (
|
|
367
384
|
<li key={item.id} className="relative group/navitem">
|
|
368
385
|
<div
|
|
@@ -374,18 +391,18 @@ export default function ITSidebar({
|
|
|
374
391
|
className={`flex items-center cursor-pointer
|
|
375
392
|
transition-all duration-300 ease-[cubic-bezier(0.2,0,0,1)]
|
|
376
393
|
rounded-xl relative overflow-visible
|
|
377
|
-
${isSidebarCollapsed ? "justify-center p-2 mb-1" : "justify-between px-3 py-2 mb-0.5"}
|
|
394
|
+
${isSidebarCollapsed ? (flat ? "justify-center h-10 mb-1" : "justify-center p-2 mb-1") : "justify-between px-3 py-2 mb-0.5"}
|
|
378
395
|
`}
|
|
379
396
|
style={{
|
|
380
|
-
backgroundColor:
|
|
381
|
-
boxShadow:
|
|
382
|
-
border:
|
|
397
|
+
backgroundColor: active ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : 'transparent',
|
|
398
|
+
boxShadow: active && !flat ? 'var(--shadow-xs)' : 'none',
|
|
399
|
+
border: active && !flat ? "1px solid var(--it-sidebar-border, var(--color-secondary-200))" : '1px solid transparent'
|
|
383
400
|
}}
|
|
384
401
|
onMouseEnter={(e) => {
|
|
385
|
-
if (!
|
|
402
|
+
if (!active) e.currentTarget.style.backgroundColor = "var(--it-sidebar-hover-bg, var(--color-secondary-100))";
|
|
386
403
|
}}
|
|
387
404
|
onMouseLeave={(e) => {
|
|
388
|
-
if (!
|
|
405
|
+
if (!active) e.currentTarget.style.backgroundColor = 'transparent';
|
|
389
406
|
}}
|
|
390
407
|
onClick={() => handleItemClick(item)}
|
|
391
408
|
onKeyDown={(e) => {
|
|
@@ -395,7 +412,7 @@ export default function ITSidebar({
|
|
|
395
412
|
}
|
|
396
413
|
}}
|
|
397
414
|
>
|
|
398
|
-
{
|
|
415
|
+
{active && !isSidebarCollapsed && !flat && (
|
|
399
416
|
<div
|
|
400
417
|
className="absolute left-0 top-1/4 bottom-1/4 w-[3px] rounded-r-full transition-all"
|
|
401
418
|
style={{ backgroundColor: "var(--it-sidebar-active-icon, var(--color-primary-500))", boxShadow: "0 0 10px var(--it-sidebar-active-icon, var(--color-primary-500))" }}
|
|
@@ -407,10 +424,10 @@ export default function ITSidebar({
|
|
|
407
424
|
<div
|
|
408
425
|
className={`transition-all duration-300 flex-shrink-0 flex items-center justify-center`}
|
|
409
426
|
style={{
|
|
410
|
-
color:
|
|
411
|
-
opacity:
|
|
412
|
-
fontSize: flat ? '1rem' :
|
|
413
|
-
filter:
|
|
427
|
+
color: active ? "var(--it-sidebar-active-icon, var(--color-primary-500))" : "var(--it-sidebar-icon-color, #9ca3af)",
|
|
428
|
+
opacity: active ? 1 : 0.8,
|
|
429
|
+
fontSize: flat ? '1rem' : active ? '1.12rem' : '1.05rem',
|
|
430
|
+
filter: active && !flat ? 'drop-shadow(0 0 8px rgba(255,255,255,0.2))' : 'none'
|
|
414
431
|
}}
|
|
415
432
|
>
|
|
416
433
|
{item.icon}
|
|
@@ -421,9 +438,9 @@ export default function ITSidebar({
|
|
|
421
438
|
<ITText as="span"
|
|
422
439
|
className={`transition-all duration-300 truncate tracking-wide`}
|
|
423
440
|
style={{
|
|
424
|
-
color:
|
|
441
|
+
color: active ? "var(--it-sidebar-active-color, #ffffff)" : "var(--it-sidebar-label-color, var(--color-secondary-300))",
|
|
425
442
|
fontSize: flat ? '0.875rem' : '0.8rem',
|
|
426
|
-
fontWeight:
|
|
443
|
+
fontWeight: active ? '600' : '500'
|
|
427
444
|
}}
|
|
428
445
|
>
|
|
429
446
|
{item.label}
|
|
@@ -433,7 +450,7 @@ export default function ITSidebar({
|
|
|
433
450
|
|
|
434
451
|
{!isSidebarCollapsed && item.subitems && item.subitems.length > 0 && (
|
|
435
452
|
<div className={`flex-shrink-0 transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)] ${expandedItems.has(item.id) ? "rotate-180" : ""}`}
|
|
436
|
-
style={{ color:
|
|
453
|
+
style={{ color: active ? "var(--it-sidebar-active-color, var(--color-secondary-900))" : "var(--it-sidebar-icon-color, var(--color-secondary-500))", opacity: 0.7 }}>
|
|
437
454
|
<FaChevronDown className="w-3 h-3" />
|
|
438
455
|
</div>
|
|
439
456
|
)}
|
|
@@ -457,7 +474,21 @@ export default function ITSidebar({
|
|
|
457
474
|
</div>
|
|
458
475
|
|
|
459
476
|
{/* Glassmorphism Collapsed Tooltip / Submenu */}
|
|
460
|
-
{isSidebarCollapsed && (
|
|
477
|
+
{isSidebarCollapsed && flat && (
|
|
478
|
+
<div
|
|
479
|
+
role="tooltip"
|
|
480
|
+
className="absolute left-full top-1/2 -translate-y-1/2 ml-3 px-2.5 py-1.5 rounded-lg whitespace-nowrap opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-opacity duration-150 pointer-events-none z-[70]"
|
|
481
|
+
style={{
|
|
482
|
+
backgroundColor: "var(--it-sidebar-tooltip-bg, var(--color-secondary-900))",
|
|
483
|
+
color: "var(--it-sidebar-tooltip-color, #ffffff)",
|
|
484
|
+
fontSize: "0.78rem",
|
|
485
|
+
fontWeight: 500,
|
|
486
|
+
}}
|
|
487
|
+
>
|
|
488
|
+
{item.label}
|
|
489
|
+
</div>
|
|
490
|
+
)}
|
|
491
|
+
{isSidebarCollapsed && !flat && (
|
|
461
492
|
<div
|
|
462
493
|
className="absolute left-full top-0 ml-4 rounded-2xl opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-all duration-300 pointer-events-none z-[70] min-w-[220px] overflow-hidden -translate-x-2 group-hover/navitem:translate-x-0 shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)]"
|
|
463
494
|
style={{
|
|
@@ -503,7 +534,7 @@ export default function ITSidebar({
|
|
|
503
534
|
{!isSidebarCollapsed && item.subitems && item.subitems.length > 0 && (
|
|
504
535
|
<div id={submenuId} role="group" aria-label={item.label} className={`overflow-hidden transition-all duration-400 ease-[cubic-bezier(0.2,0,0,1)] ${expandedItems.has(item.id) ? "max-h-[1000px] opacity-100 mt-1" : "max-h-0 opacity-0"}`}>
|
|
505
536
|
<ul
|
|
506
|
-
className="ml-4 flex flex-col gap-0 py-0.5
|
|
537
|
+
className={`${flat && subitemConnector === '|' ? "ml-[21px] pl-2" : "ml-4"} flex flex-col gap-0 py-0.5`}
|
|
507
538
|
style={{
|
|
508
539
|
borderLeft: subitemConnector === '|'
|
|
509
540
|
? "1px solid var(--it-sidebar-border, var(--color-secondary-200))"
|
|
@@ -49,6 +49,12 @@ export interface ITTopBarProps {
|
|
|
49
49
|
showMobileMenuButton?: boolean;
|
|
50
50
|
/** Callback fired when the mobile menu toggle button is clicked. */
|
|
51
51
|
onToggleMobileMenu?: () => void;
|
|
52
|
+
/**
|
|
53
|
+
* Keeps the menu toggle button visible from the `lg` breakpoint up as well
|
|
54
|
+
* (it is mobile-only by default). `ITLayout` turns it on when the sidebar
|
|
55
|
+
* collapses by button instead of hover (`sidebar.expandOnHover === false`). @default false
|
|
56
|
+
*/
|
|
57
|
+
showDesktopMenuButton?: boolean;
|
|
52
58
|
/**
|
|
53
59
|
* Hides the logo and `logoText` from the `lg` breakpoint up and left-aligns
|
|
54
60
|
* `centerContent`. Use it when the brand already lives somewhere else (e.g.
|
|
@@ -69,6 +69,7 @@ export default function ITTopBar({
|
|
|
69
69
|
navItems,
|
|
70
70
|
onNavItemClick,
|
|
71
71
|
hideBrandOnDesktop = false,
|
|
72
|
+
showDesktopMenuButton = false,
|
|
72
73
|
}: ITTopBarProps) {
|
|
73
74
|
// Flat appearance: plain bar (no shadow/blur), initials avatar, name before it.
|
|
74
75
|
const flat = useITFlatAppearance();
|
|
@@ -100,7 +101,9 @@ export default function ITTopBar({
|
|
|
100
101
|
{/* Mobile Sidebar Toggle */}
|
|
101
102
|
{showMobileMenuButton && (
|
|
102
103
|
<button
|
|
103
|
-
|
|
104
|
+
type="button"
|
|
105
|
+
aria-label="Menú"
|
|
106
|
+
className={`${showDesktopMenuButton ? "" : "lg:hidden"} p-2.5 -ml-2.5 rounded-xl transition-colors duration-200`}
|
|
104
107
|
style={{
|
|
105
108
|
color: "var(--it-topbar-icon, #64748b)",
|
|
106
109
|
}}
|
|
@@ -56,8 +56,17 @@ export default function ITLayout({
|
|
|
56
56
|
const handleToggleCollapse = isControlled ? (sidebar.onToggleCollapse ?? (() => {})) : () => setInternalCollapsed(v => !v);
|
|
57
57
|
|
|
58
58
|
const layoutTokens = theme.layout;
|
|
59
|
-
// Must match ITSidebar's own at-rest width (88px rail / 280px
|
|
60
|
-
const reservedWidth = desktopCollapsed
|
|
59
|
+
// Must match ITSidebar's own at-rest width (88px rail / 280px; 72px / 248px when flat).
|
|
60
|
+
const reservedWidth = desktopCollapsed
|
|
61
|
+
? flat ? "w-[72px]" : "w-[88px]"
|
|
62
|
+
: flat ? "w-[248px]" : "w-[280px]";
|
|
63
|
+
// The sidebar collapses by button instead of hover: the top bar's menu
|
|
64
|
+
// button toggles the rail on desktop and still opens the drawer on mobile.
|
|
65
|
+
const toggleByButton = sidebar.expandOnHover === false;
|
|
66
|
+
const handleMenuButton = () => {
|
|
67
|
+
if (toggleByButton && window.matchMedia("(min-width: 1024px)").matches) handleToggleCollapse();
|
|
68
|
+
else setMobileSidebarOpen(v => !v);
|
|
69
|
+
};
|
|
61
70
|
// With a full-height sidebar the brand moves from the top bar to the sidebar.
|
|
62
71
|
const brand = sidebarFullHeight
|
|
63
72
|
? (sidebar.brand ?? { logo: topBar.logo, text: topBar.logoText })
|
|
@@ -68,7 +77,8 @@ export default function ITLayout({
|
|
|
68
77
|
{...topBar}
|
|
69
78
|
hideBrandOnDesktop={sidebarFullHeight || topBar.hideBrandOnDesktop}
|
|
70
79
|
showMobileMenuButton
|
|
71
|
-
|
|
80
|
+
showDesktopMenuButton={toggleByButton || topBar.showDesktopMenuButton}
|
|
81
|
+
onToggleMobileMenu={handleMenuButton}
|
|
72
82
|
/>
|
|
73
83
|
);
|
|
74
84
|
|
package/src/index.ts
CHANGED
|
@@ -54,6 +54,7 @@ import ITSlideToggle from "./components/atoms/slide/slide";
|
|
|
54
54
|
import ITSlider from "./components/atoms/slider/slider";
|
|
55
55
|
import ITStack from "./components/atoms/stack/stack";
|
|
56
56
|
import ITStatCard from "./components/molecules/stat-card/stat-card";
|
|
57
|
+
import ITLineBarChart from "./components/molecules/line-bar-chart/line-bar-chart";
|
|
57
58
|
import ITTable from "./components/molecules/table/table";
|
|
58
59
|
import ITText from "./components/atoms/text/text";
|
|
59
60
|
import ITTextarea from "./components/atoms/textarea/textarea";
|
|
@@ -109,6 +110,7 @@ import type { ITSlideToggleProps } from "./components/atoms/slide/slide.props";
|
|
|
109
110
|
import type { ITSliderProps } from "./components/atoms/slider/slider.props";
|
|
110
111
|
import type { ITStackProps } from "./components/atoms/stack/stack.props";
|
|
111
112
|
import type { ITStatCardProps } from "./components/molecules/stat-card/stat-card.props";
|
|
113
|
+
import type { ITLineBarChartProps, ITLineBarDatum } from "./components/molecules/line-bar-chart/line-bar-chart.props";
|
|
112
114
|
import type { ITTableProps, Column, ColumnFilterMode } from "./components/molecules/table/table.props";
|
|
113
115
|
import type { ITTextProps } from "./components/atoms/text/text.props";
|
|
114
116
|
import type { ITTextareaProps } from "./components/atoms/textarea/textarea.props";
|
|
@@ -151,7 +153,7 @@ export {
|
|
|
151
153
|
ITLoader, ITNavbar, ITPage, ITPageHeader, ITPagination, ITPopover, ITProgress,
|
|
152
154
|
ITRadioGroup, ITSelect, ITSearchSelect,
|
|
153
155
|
ITSearchTable,
|
|
154
|
-
ITSegmentedControl, ITSidebar, ITSkeleton, ITSlideToggle, ITSlider, ITStack, ITStatCard, ITStepper,
|
|
156
|
+
ITSegmentedControl, ITSidebar, ITSkeleton, ITSlideToggle, ITSlider, ITStack, ITStatCard, ITStepper, ITLineBarChart,
|
|
155
157
|
ITTable, ITTabs, ITText, ITTextarea, ITTripleFilter, ITThemeProvider,
|
|
156
158
|
useITTheme, useITThemeSafe, useITFlatAppearance, ITTimePicker, ITToast, ITWysiwyg,
|
|
157
159
|
UploadStatus, FileTypeEnum,
|
|
@@ -181,7 +183,7 @@ export {
|
|
|
181
183
|
ITRadioGroupProps, ITRadioOption, ITSelectProps, ITSearchSelectProps,
|
|
182
184
|
ITSearchTableProps,
|
|
183
185
|
ITSegmentedControlProps, ITSidebarProps, ITSkeletonProps, ITSlideToggleProps, ITSliderProps,
|
|
184
|
-
ITStackProps, ITStatCardProps, ITStepperProps,
|
|
186
|
+
ITStackProps, ITStatCardProps, ITStepperProps, ITLineBarChartProps, ITLineBarDatum,
|
|
185
187
|
ITTableProps, ITTabsProps, ITTabItem, ITTextProps, ITTextareaProps,
|
|
186
188
|
TableDensity,
|
|
187
189
|
ITTripleFilterProps, ITTripleFilterOption, ITThemeConfig, ITThemeProviderProps, ITThemePalette, ITThemeAppearance,
|