@axzydev/axzy_ui_system 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -636,15 +636,15 @@ interface ITButtonProps {
636
636
  label?: string;
637
637
  /** Custom content to render inside the button. Takes precedence over `label`. */
638
638
  children?: React.ReactNode;
639
- /** Icon element rendered before the label. */
639
+ /** Icon element rendered before the label. With `variant="icon-only"` and no `label`/`children` it becomes the only content and is centered in the square button. */
640
640
  icon?: React.ReactNode;
641
641
  /** Click handler for the button. */
642
642
  onClick?: () => void;
643
643
  /** Color theme key. Values come from the semantic color palette (e.g. `"primary"`, `"secondary"`, `"success"`, `"danger"`, `"warning"`, `"info"`, `"purple"`, `"error"`, `"gray"`). @default "primary" */
644
644
  color?: ColorsTypes;
645
- /** Button size. Valid values: `"sm"`, `"md"`, `"lg"`. @default "md" */
645
+ /** Button size. Valid values: `"sm"`, `"md"`, `"lg"`. In `variant="icon-only"` it also scales the square padding (`buttonIconPadding`: `sm` 0.5rem, `md` 0.625rem, `lg` 0.75rem). @default "md" */
646
646
  size?: SizesTypes;
647
- /** Button visual style. Valid values: `"filled"`, `"outlined"`, `"raised"`, `"rounded"`, `"text"`, `"raised-text"`, `"icon-only"`, `"link"`. @default "filled" */
647
+ /** Button visual style. Valid values: `"filled"`, `"outlined"`, `"raised"`, `"rounded"`, `"text"`, `"raised-text"`, `"icon-only"`, `"link"`. `"icon-only"` renders a centered square icon button; combine it with `icon` and `ariaLabel`. @default "filled" */
648
648
  variant?: keyof typeof buttonVariants;
649
649
  /** Disables the button interaction and applies reduced opacity. @default false */
650
650
  disabled?: boolean;
package/dist/index.d.ts CHANGED
@@ -636,15 +636,15 @@ interface ITButtonProps {
636
636
  label?: string;
637
637
  /** Custom content to render inside the button. Takes precedence over `label`. */
638
638
  children?: React.ReactNode;
639
- /** Icon element rendered before the label. */
639
+ /** Icon element rendered before the label. With `variant="icon-only"` and no `label`/`children` it becomes the only content and is centered in the square button. */
640
640
  icon?: React.ReactNode;
641
641
  /** Click handler for the button. */
642
642
  onClick?: () => void;
643
643
  /** Color theme key. Values come from the semantic color palette (e.g. `"primary"`, `"secondary"`, `"success"`, `"danger"`, `"warning"`, `"info"`, `"purple"`, `"error"`, `"gray"`). @default "primary" */
644
644
  color?: ColorsTypes;
645
- /** Button size. Valid values: `"sm"`, `"md"`, `"lg"`. @default "md" */
645
+ /** Button size. Valid values: `"sm"`, `"md"`, `"lg"`. In `variant="icon-only"` it also scales the square padding (`buttonIconPadding`: `sm` 0.5rem, `md` 0.625rem, `lg` 0.75rem). @default "md" */
646
646
  size?: SizesTypes;
647
- /** Button visual style. Valid values: `"filled"`, `"outlined"`, `"raised"`, `"rounded"`, `"text"`, `"raised-text"`, `"icon-only"`, `"link"`. @default "filled" */
647
+ /** Button visual style. Valid values: `"filled"`, `"outlined"`, `"raised"`, `"rounded"`, `"text"`, `"raised-text"`, `"icon-only"`, `"link"`. `"icon-only"` renders a centered square icon button; combine it with `icon` and `ariaLabel`. @default "filled" */
648
648
  variant?: keyof typeof buttonVariants;
649
649
  /** Disables the button interaction and applies reduced opacity. @default false */
650
650
  disabled?: boolean;
package/dist/index.js CHANGED
@@ -1513,7 +1513,8 @@ var buttonVariants = {
1513
1513
  rounded: "border-transparent shadow-sm rounded-full",
1514
1514
  text: "bg-transparent border-transparent shadow-none hover:bg-black/5 dark:hover:bg-white/10",
1515
1515
  "raised-text": "bg-white border border-gray-200 shadow-sm hover:shadow-md",
1516
- "icon-only": "p-2 aspect-square flex items-center justify-center border-transparent shadow-sm",
1516
+ // No lleva utilidades de padding: el cuadrado lo define `buttonIconPadding` por tamaño.
1517
+ "icon-only": "aspect-square flex items-center justify-center border-transparent shadow-sm",
1517
1518
  link: "bg-transparent border-transparent shadow-none hover:underline px-0"
1518
1519
  };
1519
1520
  var buttonSizes = {
@@ -1521,6 +1522,16 @@ var buttonSizes = {
1521
1522
  md: "text-[13px] px-3.5 py-1.5",
1522
1523
  lg: "text-sm px-4 py-2"
1523
1524
  };
1525
+ var buttonIconSizes = {
1526
+ sm: "text-xs",
1527
+ md: "text-[13px]",
1528
+ lg: "text-sm"
1529
+ };
1530
+ var buttonIconPadding = {
1531
+ sm: "0.5rem",
1532
+ md: "0.625rem",
1533
+ lg: "0.75rem"
1534
+ };
1524
1535
 
1525
1536
  // src/components/atoms/button/button.tsx
1526
1537
  import clsx6 from "clsx";
@@ -1542,6 +1553,8 @@ function ITButton({
1542
1553
  }) {
1543
1554
  const [isHovered, setIsHovered] = useState6(false);
1544
1555
  const [isFocused, setIsFocused] = useState6(false);
1556
+ const isIconOnly = variant === "icon-only";
1557
+ const isIconOnlyContent = isIconOnly && Boolean(icon) && !children;
1545
1558
  const themeBtn = theme.button;
1546
1559
  const themeConfig = themeBtn[color] || themeBtn.primary;
1547
1560
  const isSolid = ["filled", "raised", "rounded", "icon-only"].includes(variant || "filled");
@@ -1562,8 +1575,9 @@ function ITButton({
1562
1575
  if (variant === "rounded") {
1563
1576
  style.borderRadius = "9999px";
1564
1577
  }
1565
- if (variant === "icon-only") {
1566
- style.padding = "0.5rem";
1578
+ if (isIconOnly) {
1579
+ style.padding = buttonIconPadding[size] ?? "0.5rem";
1580
+ style.lineHeight = 1;
1567
1581
  }
1568
1582
  if (isSolid) {
1569
1583
  style.backgroundColor = isHovered && !disabled ? themeConfig.hover : mainColor;
@@ -1598,7 +1612,7 @@ function ITButton({
1598
1612
  // Apply variant base styles (border, shadow, rounded-full)
1599
1613
  buttonVariants[variant || "filled"],
1600
1614
  // Apply size classes (padding/font-size)
1601
- buttonSizes[size],
1615
+ isIconOnly ? buttonIconSizes[size] : buttonSizes[size],
1602
1616
  className,
1603
1617
  { "opacity-50 cursor-not-allowed": disabled }
1604
1618
  ),
@@ -1611,10 +1625,13 @@ function ITButton({
1611
1625
  disabled,
1612
1626
  "aria-label": ariaLabel || label,
1613
1627
  title: title || ariaLabel || label,
1614
- children: children || /* @__PURE__ */ jsxs5("span", { className: clsx6("inline-flex items-center gap-1.5 font-semibold", { "opacity-50": disabled }), children: [
1628
+ children: children || (isIconOnlyContent ? (
1629
+ // Icono solo: sin wrapper con `gap` ni `ITText` vacío, que lo desplazaban a la izquierda.
1630
+ /* @__PURE__ */ jsx8("span", { className: "inline-flex items-center justify-center leading-none", children: icon })
1631
+ ) : /* @__PURE__ */ jsxs5("span", { className: clsx6("inline-flex items-center gap-1.5 font-semibold", { "opacity-50": disabled }), children: [
1615
1632
  icon && /* @__PURE__ */ jsx8("span", { className: "flex-shrink-0", children: icon }),
1616
1633
  /* @__PURE__ */ jsx8(ITText, { as: "span", children: label })
1617
- ] })
1634
+ ] }))
1618
1635
  }
1619
1636
  );
1620
1637
  }
@@ -8096,7 +8113,7 @@ function ITSegmentedControl({
8096
8113
  import { useEffect as useEffect13, useRef as useRef20, useState as useState27 } from "react";
8097
8114
  import clsx40 from "clsx";
8098
8115
  import { FaChevronDown as FaChevronDown4 } from "react-icons/fa";
8099
- import { jsx as jsx58, jsxs as jsxs42 } from "react/jsx-runtime";
8116
+ import { Fragment as Fragment9, jsx as jsx58, jsxs as jsxs42 } from "react/jsx-runtime";
8100
8117
  function isSubItemGroup(entry) {
8101
8118
  return "items" in entry;
8102
8119
  }
@@ -8105,6 +8122,19 @@ function flattenSubItems(entries) {
8105
8122
  (entry) => isSubItemGroup(entry) ? entry.items : [entry]
8106
8123
  );
8107
8124
  }
8125
+ var RAIL_BADGE_MAX_CHARS = 3;
8126
+ function RailBadge({ value }) {
8127
+ const text = String(value);
8128
+ if (text.length <= RAIL_BADGE_MAX_CHARS) return /* @__PURE__ */ jsx58(Fragment9, { children: text });
8129
+ return /* @__PURE__ */ jsx58(
8130
+ "span",
8131
+ {
8132
+ "aria-hidden": "true",
8133
+ className: "block w-1.5 h-1.5 rounded-full",
8134
+ style: { backgroundColor: "currentColor" }
8135
+ }
8136
+ );
8137
+ }
8108
8138
  function ITSidebar({
8109
8139
  navigationItems = [],
8110
8140
  isCollapsed = false,
@@ -8175,7 +8205,9 @@ function ITSidebar({
8175
8205
  }
8176
8206
  }, [navigationItems]);
8177
8207
  const isSidebarCollapsed = visibleOnMobile ? false : isCollapsed && !(expandOnHover && isHovering);
8178
- const sidebarWidth = isSidebarCollapsed ? flat ? "w-[72px]" : "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
8208
+ const collapsedWidth = flat ? "w-[72px]" : "w-[88px]";
8209
+ const expandedWidth = flat ? "w-[248px]" : "w-[280px]";
8210
+ const sidebarWidth = isSidebarCollapsed ? collapsedWidth : expandedWidth;
8179
8211
  const fixedRail = isSidebarCollapsed && !expandOnHover;
8180
8212
  const toggleExpanded = (itemId) => {
8181
8213
  const newExpanded = new Set(expandedItems);
@@ -8287,7 +8319,7 @@ function ITSidebar({
8287
8319
  size: "sm",
8288
8320
  ...badgeRest,
8289
8321
  className: clsx40("shadow-md", badgeClassName),
8290
- children: String(count)
8322
+ children: isSidebarCollapsed ? /* @__PURE__ */ jsx58(RailBadge, { value: count }) : String(count)
8291
8323
  }
8292
8324
  );
8293
8325
  if (isSidebarCollapsed) {
@@ -8298,7 +8330,7 @@ function ITSidebar({
8298
8330
  "aria-label": label,
8299
8331
  title: label,
8300
8332
  onClick,
8301
- className: "relative flex items-center justify-center w-full p-2 mb-1 rounded-xl transition-all duration-300",
8333
+ className: `relative flex items-center w-full h-10 mb-1 rounded-xl transition-all duration-300 ${flat ? "px-3" : "px-5"}`,
8302
8334
  style: { color: "var(--it-sidebar-icon-color, var(--color-secondary-500))" },
8303
8335
  onMouseEnter: (e) => {
8304
8336
  e.currentTarget.style.backgroundColor = "var(--it-sidebar-hover-bg, var(--color-secondary-100))";
@@ -8308,7 +8340,7 @@ function ITSidebar({
8308
8340
  },
8309
8341
  children: [
8310
8342
  icon && /* @__PURE__ */ jsx58("span", { className: "flex items-center justify-center text-[1.05rem]", children: icon }),
8311
- /* @__PURE__ */ jsx58("span", { className: "absolute top-0.5 right-0.5 pointer-events-none", children: badge })
8343
+ /* @__PURE__ */ jsx58("span", { className: "absolute top-0.5 right-0.5 max-w-[2.1rem] overflow-hidden pointer-events-none", children: badge })
8312
8344
  ]
8313
8345
  }
8314
8346
  );
@@ -8320,7 +8352,7 @@ function ITSidebar({
8320
8352
  "aria-label": label,
8321
8353
  title: label,
8322
8354
  onClick,
8323
- className: "flex items-center gap-2.5 w-full text-left px-3 py-2 mb-1 rounded-xl transition-all duration-300",
8355
+ className: `flex items-center gap-2.5 w-full text-left h-10 mb-1 rounded-xl transition-all duration-300 ${flat ? "px-3" : "px-5"}`,
8324
8356
  style: { color: "var(--it-sidebar-label-color, var(--color-secondary-600))" },
8325
8357
  onMouseEnter: (e) => {
8326
8358
  e.currentTarget.style.backgroundColor = "var(--it-sidebar-hover-bg, var(--color-secondary-100))";
@@ -8388,9 +8420,9 @@ function ITSidebar({
8388
8420
  ]
8389
8421
  }
8390
8422
  ),
8391
- header && !isSidebarCollapsed && /* @__PURE__ */ jsx58("div", { className: "px-4 pt-4 pb-1 flex-shrink-0", children: header }),
8423
+ header && /* @__PURE__ */ jsx58("div", { className: `px-4 pt-4 pb-1 flex-shrink-0 ${isSidebarCollapsed ? "overflow-hidden" : ""}`, children: isSidebarCollapsed ? /* @__PURE__ */ jsx58("div", { className: `${expandedWidth} invisible`, "aria-hidden": "true", children: header }) : header }),
8392
8424
  notification && /* @__PURE__ */ jsx58("div", { className: "px-4 pt-3 flex-shrink-0", children: renderNotification() }),
8393
- /* @__PURE__ */ jsx58("nav", { "aria-label": t("sidebar.navAria"), className: `flex-1 py-4 custom-scrollbar ${fixedRail ? "overflow-visible" : "overflow-y-auto overflow-x-hidden"} ${flat && isSidebarCollapsed ? "px-3" : "px-4"}`, children: /* @__PURE__ */ jsx58("ul", { className: "space-y-1", children: navigationItems.map((item) => {
8425
+ /* @__PURE__ */ jsx58("nav", { "aria-label": t("sidebar.navAria"), className: `flex-1 py-4 px-4 custom-scrollbar ${fixedRail ? "overflow-visible" : "overflow-y-auto overflow-x-hidden"}`, children: /* @__PURE__ */ jsx58("ul", { className: "space-y-1", children: navigationItems.map((item) => {
8394
8426
  const hasSubmenu = !!item.subitems && item.subitems.length > 0;
8395
8427
  const submenuId = `it-sidebar-submenu-${item.id}`;
8396
8428
  const hasRenderedSubmenu = hasSubmenu && !isSidebarCollapsed;
@@ -8408,7 +8440,9 @@ function ITSidebar({
8408
8440
  className: `flex items-center cursor-pointer
8409
8441
  transition-all duration-300 ease-[cubic-bezier(0.2,0,0,1)]
8410
8442
  rounded-xl relative overflow-visible
8411
- ${isSidebarCollapsed ? flat ? "justify-center h-10 mb-1" : "justify-center p-2 mb-1" : "justify-between px-3 py-2 mb-0.5"}
8443
+ h-10
8444
+ ${flat ? "px-3" : "px-5"}
8445
+ ${isSidebarCollapsed ? "justify-start" : "justify-between"}
8412
8446
  `,
8413
8447
  style: {
8414
8448
  backgroundColor: active ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : "transparent",
@@ -8436,7 +8470,7 @@ function ITSidebar({
8436
8470
  style: { backgroundColor: "var(--it-sidebar-active-icon, var(--color-primary-500))", boxShadow: "0 0 10px var(--it-sidebar-active-icon, var(--color-primary-500))" }
8437
8471
  }
8438
8472
  ),
8439
- /* @__PURE__ */ jsxs42("div", { className: `flex items-center ${!isSidebarCollapsed ? "gap-2.5" : "justify-center"} relative z-10 w-full`, children: [
8473
+ /* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-2.5 relative z-10 w-full", children: [
8440
8474
  item.icon && /* @__PURE__ */ jsx58(
8441
8475
  "div",
8442
8476
  {
@@ -8480,10 +8514,12 @@ function ITSidebar({
8480
8514
  ...badgeRest,
8481
8515
  className: clsx40(
8482
8516
  "absolute shadow-md",
8483
- isSidebarCollapsed ? "top-0.5 right-0.5" : "right-3 top-1/2 -translate-y-1/2",
8517
+ // En el riel no hay ancho para una etiqueta larga: el badge se
8518
+ // ancla a la esquina y se recorta, así nunca desborda ni tapa el icono.
8519
+ isSidebarCollapsed ? "top-0.5 right-0.5 max-w-[2.1rem] overflow-hidden" : "right-3 top-1/2 -translate-y-1/2",
8484
8520
  badgeClassName
8485
8521
  ),
8486
- children: String(item.badge)
8522
+ children: isSidebarCollapsed ? /* @__PURE__ */ jsx58(RailBadge, { value: item.badge }) : String(item.badge)
8487
8523
  }
8488
8524
  )
8489
8525
  ]
@@ -8906,7 +8942,7 @@ import {
8906
8942
  } from "react-icons/fa";
8907
8943
  import { MdOutlineSwapVert as MdOutlineSwapVert2 } from "react-icons/md";
8908
8944
  import { isSameDay as isSameDay2, startOfDay as startOfDay2, endOfDay } from "date-fns";
8909
- import { Fragment as Fragment9, jsx as jsx63, jsxs as jsxs46 } from "react/jsx-runtime";
8945
+ import { Fragment as Fragment10, jsx as jsx63, jsxs as jsxs46 } from "react/jsx-runtime";
8910
8946
  function ITTable({
8911
8947
  columns,
8912
8948
  data = [],
@@ -9444,7 +9480,7 @@ function ITTable({
9444
9480
  })
9445
9481
  }
9446
9482
  ) }),
9447
- /* @__PURE__ */ jsx63("tbody", { className: clsx44(tableBody, "dark:divide-slate-700/30"), children: currentData.length > 0 ? /* @__PURE__ */ jsxs46(Fragment9, { children: [
9483
+ /* @__PURE__ */ jsx63("tbody", { className: clsx44(tableBody, "dark:divide-slate-700/30"), children: currentData.length > 0 ? /* @__PURE__ */ jsxs46(Fragment10, { children: [
9448
9484
  isTableVirtual && topSpacerHeight > 0 && /* @__PURE__ */ jsx63("tr", { "aria-hidden": "true", style: { height: topSpacerHeight }, children: /* @__PURE__ */ jsx63("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) }),
9449
9485
  windowData.map((row, windowIndex) => {
9450
9486
  const absoluteIndex = isTableVirtual ? startIndex + windowIndex : windowIndex;
@@ -10396,7 +10432,7 @@ var UploadStatus = /* @__PURE__ */ ((UploadStatus2) => {
10396
10432
  })(UploadStatus || {});
10397
10433
 
10398
10434
  // src/components/organisms/dropfile/dropfile.tsx
10399
- import { Fragment as Fragment10, jsx as jsx70, jsxs as jsxs52 } from "react/jsx-runtime";
10435
+ import { Fragment as Fragment11, jsx as jsx70, jsxs as jsxs52 } from "react/jsx-runtime";
10400
10436
  var ITDropfile = ({
10401
10437
  onFileSelect,
10402
10438
  onCancel,
@@ -10643,7 +10679,7 @@ var ITDropfile = ({
10643
10679
  ] }),
10644
10680
  showStatusBadge && selectedFile && /* @__PURE__ */ jsx70(StatusBadge, { status: uploadStatus })
10645
10681
  ] });
10646
- const dropZoneOrPreview = /* @__PURE__ */ jsx70(Fragment10, { children: !selectedFile && !imagePreview ? /* @__PURE__ */ jsxs52(
10682
+ const dropZoneOrPreview = /* @__PURE__ */ jsx70(Fragment11, { children: !selectedFile && !imagePreview ? /* @__PURE__ */ jsxs52(
10647
10683
  "div",
10648
10684
  {
10649
10685
  ...getRootProps(),
@@ -10686,7 +10722,7 @@ var ITDropfile = ({
10686
10722
  /* @__PURE__ */ jsx70("svg", { className: "w-10 h-10 mb-2 opacity-50", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx70("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) }),
10687
10723
  /* @__PURE__ */ jsx70(ITText, { as: "span", className: "text-xs", children: t("dropfile.noPreview") })
10688
10724
  ] }) }),
10689
- /* @__PURE__ */ jsx70("div", { className: "px-3 py-2 bg-white border-t border-secondary-100 flex justify-end gap-2", children: !isConfirmed ? /* @__PURE__ */ jsxs52(Fragment10, { children: [
10725
+ /* @__PURE__ */ jsx70("div", { className: "px-3 py-2 bg-white border-t border-secondary-100 flex justify-end gap-2", children: !isConfirmed ? /* @__PURE__ */ jsxs52(Fragment11, { children: [
10690
10726
  /* @__PURE__ */ jsx70(
10691
10727
  ITButton,
10692
10728
  {