@pagamio/frontend-commons-lib 0.8.232 → 0.8.233

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.
@@ -132,6 +132,7 @@ import type { IconResolver, SidebarMenuGroup, SidebarMenuItemConfig, SidebarV2Pr
132
132
  */
133
133
  interface ComingSoonBadgeProps {
134
134
  className?: string;
135
+ button?: React.ReactNode;
135
136
  }
136
137
  /**
137
138
  * Professional "Coming Soon" indicator with subtle yellow styling
@@ -141,6 +142,10 @@ interface MenuItemRendererProps {
141
142
  item: SidebarMenuItemConfig;
142
143
  depth?: number;
143
144
  iconResolver?: IconResolver;
145
+ comingSoonBadgeClassName?: string;
146
+ comingSoonButtonClassName?: string;
147
+ comingSoonIconClassName?: string;
148
+ comingSoonTextClassName?: string;
144
149
  }
145
150
  /**
146
151
  * Recursive menu item renderer
@@ -149,6 +154,10 @@ declare const MenuItemRenderer: React.FC<MenuItemRendererProps>;
149
154
  interface MenuGroupRendererProps {
150
155
  group: SidebarMenuGroup;
151
156
  iconResolver?: IconResolver;
157
+ comingSoonBadgeClassName?: string;
158
+ comingSoonButtonClassName?: string;
159
+ comingSoonIconClassName?: string;
160
+ comingSoonTextClassName?: string;
152
161
  }
153
162
  /**
154
163
  * Render a menu group
@@ -10,7 +10,7 @@
10
10
  */
11
11
  'use client';
12
12
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
- import { IconChevronDown, IconChevronRight, IconClock } from '@tabler/icons-react';
13
+ import { IconChevronDown, IconChevronRight } from '@tabler/icons-react';
14
14
  import React, { useMemo, useState } from 'react';
15
15
  import { cn } from '../../helpers/utils';
16
16
  import { useTranslation } from '../../translations';
@@ -20,13 +20,13 @@ import { defaultIconResolver, resolveIcon } from './iconResolver';
20
20
  /**
21
21
  * Professional "Coming Soon" indicator with subtle yellow styling
22
22
  */
23
- const ComingSoonBadge = ({ className }) => {
24
- return (_jsxs("span", { className: cn('ml-auto inline-flex items-center gap-1 rounded px-2 py-0.5', 'bg-yellow-50 dark:bg-yellow-900/20', 'text-[10px] font-medium text-yellow-600 dark:text-yellow-500', 'border border-yellow-200 dark:border-yellow-800', className), children: [_jsx(IconClock, { className: "h-3 w-3 stroke-[1.5]" }), "Soon"] }));
23
+ const ComingSoonBadge = ({ className, button }) => {
24
+ return (_jsxs("div", { className: "ml-auto inline-flex items-center gap-2", children: [_jsx("span", { className: cn('inline-flex items-center gap-1 rounded px-2 py-0.5', 'bg-yellow-200 dark:bg-yellow-900/20', 'text-[10px] font-medium text-yellow-600 dark:text-yellow-500', 'border border-yellow-200 rounded-full dark:border-yellow-800', className), children: "Soon" }), button] }));
25
25
  };
26
26
  /**
27
27
  * Recursive menu item renderer
28
28
  */
29
- const MenuItemRenderer = ({ item, depth = 0, iconResolver = defaultIconResolver }) => {
29
+ const MenuItemRenderer = ({ item, depth = 0, iconResolver = defaultIconResolver, comingSoonBadgeClassName, comingSoonButtonClassName, comingSoonIconClassName, comingSoonTextClassName, }) => {
30
30
  const { open, isMobile, pathname, LinkComponent } = useSidebarV2();
31
31
  const { t } = useTranslation();
32
32
  const [isExpanded, setIsExpanded] = useState(false);
@@ -59,7 +59,7 @@ const MenuItemRenderer = ({ item, depth = 0, iconResolver = defaultIconResolver
59
59
  }
60
60
  // Handle coming soon items
61
61
  if (item.comingSoon) {
62
- return (_jsx(SidebarMenuItem, { children: _jsxs(SidebarMenuButton, { disabled: true, className: "cursor-not-allowed bg-yellow-50/50 hover:bg-yellow-50/50 dark:bg-yellow-900/10 dark:hover:bg-yellow-900/10", tooltip: item.tooltip || t(item.label), children: [IconComponent && _jsx(IconComponent, { className: "h-4 w-4 shrink-0 text-yellow-600 dark:text-yellow-500" }), (open || isMobile) && (_jsxs(_Fragment, { children: [_jsx("span", { className: "truncate text-yellow-700 dark:text-yellow-400", children: t(item.label) }), _jsx(ComingSoonBadge, {})] }))] }) }, itemKey));
62
+ return (_jsx(SidebarMenuItem, { children: _jsxs(SidebarMenuButton, { disabled: true, className: cn("cursor-not-allowed bg-yellow-50/50 hover:bg-yellow-50/50 dark:bg-yellow-900/10 dark:hover:bg-yellow-900/10", comingSoonButtonClassName), tooltip: item.tooltip || t(item.label), children: [IconComponent && (_jsx(IconComponent, { className: cn("h-4 w-4 shrink-0 text-yellow-600 dark:text-yellow-500", comingSoonIconClassName) })), (open || isMobile) && (_jsxs(_Fragment, { children: [_jsx("span", { className: cn("truncate text-yellow-700 dark:text-yellow-400", comingSoonTextClassName), children: t(item.label) }), _jsx(ComingSoonBadge, { className: comingSoonBadgeClassName, button: item.comingSoonButton })] }))] }) }, itemKey));
63
63
  }
64
64
  // Handle items with children (collapsible)
65
65
  if (item.items && item.items.length > 0) {
@@ -70,10 +70,10 @@ const MenuItemRenderer = ({ item, depth = 0, iconResolver = defaultIconResolver
70
70
  }
71
71
  // Non-collapsible sections (always visible children)
72
72
  if (item.collapsible === false) {
73
- return (_jsxs("div", { className: item.className, children: [item.showSeparator && _jsx(SidebarSeparator, {}), _jsxs(SidebarGroupLabel, { children: [IconComponent && _jsx(IconComponent, { className: "h-4 w-4" }), (open || isMobile) && t(item.label)] }), _jsx(SidebarMenu, { children: item.items.map((child, index) => (_jsx(MenuItemRenderer, { item: child, depth: depth + 1, iconResolver: iconResolver }, child.key || child.href || `${child.label}-${index}`))) })] }, itemKey));
73
+ return (_jsxs("div", { className: item.className, children: [item.showSeparator && _jsx(SidebarSeparator, {}), _jsxs(SidebarGroupLabel, { children: [IconComponent && _jsx(IconComponent, { className: "h-4 w-4" }), (open || isMobile) && t(item.label)] }), _jsx(SidebarMenu, { children: item.items.map((child, index) => (_jsx(MenuItemRenderer, { item: child, depth: depth + 1, iconResolver: iconResolver, comingSoonBadgeClassName: comingSoonBadgeClassName, comingSoonButtonClassName: comingSoonButtonClassName, comingSoonIconClassName: comingSoonIconClassName, comingSoonTextClassName: comingSoonTextClassName }, child.key || child.href || `${child.label}-${index}`))) })] }, itemKey));
74
74
  }
75
75
  // Regular collapsible menu
76
- return (_jsxs(SidebarMenuItem, { children: [_jsxs(SidebarMenuButton, { onClick: () => setIsExpanded(!shouldBeExpanded), isActive: isActive && !hasActiveChild, tooltip: item.tooltip || t(item.label), className: cn(hasActiveChild && 'text-sidebar-accent-foreground'), children: [IconComponent && _jsx(IconComponent, { className: "h-4 w-4 shrink-0" }), (open || isMobile) && (_jsxs(_Fragment, { children: [_jsx("span", { className: "truncate", children: t(item.label) }), shouldBeExpanded ? (_jsx(IconChevronDown, { className: "ml-auto h-4 w-4 shrink-0 transition-transform" })) : (_jsx(IconChevronRight, { className: "ml-auto h-4 w-4 shrink-0 transition-transform" }))] }))] }), shouldBeExpanded && (open || isMobile) && (_jsx(SidebarMenuSub, { children: item.items.map((child, index) => (_jsx(SidebarMenuItem, { children: child.items ? (_jsx(MenuItemRenderer, { item: child, depth: depth + 1, iconResolver: iconResolver })) : child.href ? (_jsx(SidebarMenuSubButton, { asChild: true, isActive: pathname === child.href, children: _jsxs(LinkComponent, { href: child.href, target: child.target, className: "flex items-center gap-2 w-full", children: [resolveIcon(child.icon, iconResolver) &&
76
+ return (_jsxs(SidebarMenuItem, { children: [_jsxs(SidebarMenuButton, { onClick: () => setIsExpanded(!shouldBeExpanded), isActive: isActive && !hasActiveChild, tooltip: item.tooltip || t(item.label), className: cn(hasActiveChild && 'text-sidebar-accent-foreground'), children: [IconComponent && _jsx(IconComponent, { className: "h-4 w-4 shrink-0" }), (open || isMobile) && (_jsxs(_Fragment, { children: [_jsx("span", { className: "truncate", children: t(item.label) }), shouldBeExpanded ? (_jsx(IconChevronDown, { className: "ml-auto h-4 w-4 shrink-0 transition-transform" })) : (_jsx(IconChevronRight, { className: "ml-auto h-4 w-4 shrink-0 transition-transform" }))] }))] }), shouldBeExpanded && (open || isMobile) && (_jsx(SidebarMenuSub, { children: item.items.map((child, index) => (_jsx(SidebarMenuItem, { children: child.items ? (_jsx(MenuItemRenderer, { item: child, depth: depth + 1, iconResolver: iconResolver, comingSoonBadgeClassName: comingSoonBadgeClassName, comingSoonButtonClassName: comingSoonButtonClassName, comingSoonIconClassName: comingSoonIconClassName, comingSoonTextClassName: comingSoonTextClassName })) : child.href ? (_jsx(SidebarMenuSubButton, { asChild: true, isActive: pathname === child.href, children: _jsxs(LinkComponent, { href: child.href, target: child.target, className: "flex items-center gap-2 w-full", children: [resolveIcon(child.icon, iconResolver) &&
77
77
  React.createElement(resolveIcon(child.icon, iconResolver), {
78
78
  className: 'h-3.5 w-3.5 shrink-0',
79
79
  }), _jsx("span", { className: "truncate", children: t(child.label) }), renderBadge(child.badge, t)] }) })) : (_jsx(SidebarMenuSubButton, { className: "cursor-default", children: _jsx("span", { className: "truncate", children: t(child.label) }) })) }, child.key || child.href || `${child.label}-${index}`))) }))] }, itemKey));
@@ -102,13 +102,13 @@ const renderBadge = (badge, t) => {
102
102
  /**
103
103
  * Render a menu group
104
104
  */
105
- const MenuGroupRenderer = ({ group, iconResolver = defaultIconResolver }) => {
105
+ const MenuGroupRenderer = ({ group, iconResolver = defaultIconResolver, comingSoonBadgeClassName, comingSoonButtonClassName, comingSoonIconClassName, comingSoonTextClassName, }) => {
106
106
  const { t } = useTranslation();
107
107
  const { open, isMobile } = useSidebarV2();
108
108
  return (_jsxs(SidebarGroup, { className: group.className, children: [group.label && (open || isMobile) && (_jsxs(SidebarGroupLabel, { children: [resolveIcon(group.icon, iconResolver) &&
109
109
  React.createElement(resolveIcon(group.icon, iconResolver), {
110
110
  className: 'h-4 w-4',
111
- }), t(group.label)] })), _jsx(SidebarMenu, { children: group.items.map((item, index) => (_jsx(MenuItemRenderer, { item: item, iconResolver: iconResolver }, item.key || item.href || `${item.label}-${index}`))) })] }));
111
+ }), t(group.label)] })), _jsx(SidebarMenu, { children: group.items.map((item, index) => (_jsx(MenuItemRenderer, { item: item, iconResolver: iconResolver, comingSoonBadgeClassName: comingSoonBadgeClassName, comingSoonButtonClassName: comingSoonButtonClassName, comingSoonIconClassName: comingSoonIconClassName, comingSoonTextClassName: comingSoonTextClassName }, item.key || item.href || `${item.label}-${index}`))) })] }));
112
112
  };
113
113
  /**
114
114
  * SidebarV2 - Complete sidebar component
@@ -132,9 +132,9 @@ const MenuGroupRenderer = ({ group, iconResolver = defaultIconResolver }) => {
132
132
  * </SidebarV2Provider>
133
133
  * ```
134
134
  */
135
- const SidebarV2 = ({ header, footer, groups, items, showRail = false, iconResolver = defaultIconResolver, className, contentClassName, headerClassName, footerClassName, }) => {
135
+ const SidebarV2 = ({ header, footer, groups, items, showRail = false, iconResolver = defaultIconResolver, className, contentClassName, headerClassName, footerClassName, comingSoonBadgeClassName, comingSoonButtonClassName, comingSoonIconClassName, comingSoonTextClassName, }) => {
136
136
  const { isMobile } = useSidebarV2();
137
- return (_jsxs(SidebarContainer, { className: className, children: [header && _jsx(SidebarHeader, { className: headerClassName, children: header }), _jsxs(SidebarContent, { className: contentClassName, children: [groups?.map((group, index) => (_jsxs(React.Fragment, { children: [index > 0 && _jsx(SidebarSeparator, {}), _jsx(MenuGroupRenderer, { group: group, iconResolver: iconResolver })] }, group.key || group.label || `group-${index}`))), items && !groups && (_jsx(SidebarGroup, { children: _jsx(SidebarMenu, { children: items.map((item, index) => (_jsx(MenuItemRenderer, { item: item, iconResolver: iconResolver }, item.key || item.href || `${item.label}-${index}`))) }) }))] }), footer && _jsx(SidebarFooter, { className: footerClassName, children: footer }), showRail && _jsx(SidebarRail, {})] }));
137
+ return (_jsxs(SidebarContainer, { className: className, children: [header && _jsx(SidebarHeader, { className: headerClassName, children: header }), _jsxs(SidebarContent, { className: contentClassName, children: [groups?.map((group, index) => (_jsxs(React.Fragment, { children: [index > 0 && _jsx(SidebarSeparator, {}), _jsx(MenuGroupRenderer, { group: group, iconResolver: iconResolver, comingSoonBadgeClassName: comingSoonBadgeClassName, comingSoonButtonClassName: comingSoonButtonClassName, comingSoonIconClassName: comingSoonIconClassName, comingSoonTextClassName: comingSoonTextClassName })] }, group.key || group.label || `group-${index}`))), items && !groups && (_jsx(SidebarGroup, { children: _jsx(SidebarMenu, { children: items.map((item, index) => (_jsx(MenuItemRenderer, { item: item, iconResolver: iconResolver, comingSoonBadgeClassName: comingSoonBadgeClassName, comingSoonButtonClassName: comingSoonButtonClassName, comingSoonIconClassName: comingSoonIconClassName, comingSoonTextClassName: comingSoonTextClassName }, item.key || item.href || `${item.label}-${index}`))) }) }))] }), footer && _jsx(SidebarFooter, { className: footerClassName, children: footer }), showRail && _jsx(SidebarRail, {})] }));
138
138
  };
139
139
  export default SidebarV2;
140
140
  export { SidebarV2, ComingSoonBadge, MenuItemRenderer, MenuGroupRenderer };
@@ -56,6 +56,8 @@ export interface SidebarMenuItemConfig {
56
56
  isSectionHeader?: boolean;
57
57
  /** Show "Coming Soon" badge and disable navigation */
58
58
  comingSoon?: boolean;
59
+ /** Optional button/action to display in coming soon items */
60
+ comingSoonButton?: ReactNode;
59
61
  /** Custom tooltip for collapsed state */
60
62
  tooltip?: string;
61
63
  /** Additional CSS classes */
@@ -177,6 +179,14 @@ export interface SidebarV2Props {
177
179
  headerClassName?: string;
178
180
  /** Footer className */
179
181
  footerClassName?: string;
182
+ /** Custom className for coming soon badge */
183
+ comingSoonBadgeClassName?: string;
184
+ /** Custom className for coming soon menu button */
185
+ comingSoonButtonClassName?: string;
186
+ /** Custom className for coming soon icon */
187
+ comingSoonIconClassName?: string;
188
+ /** Custom className for coming soon text span */
189
+ comingSoonTextClassName?: string;
180
190
  }
181
191
  /**
182
192
  * Props for internal menu item components
package/lib/styles.css CHANGED
@@ -2862,6 +2862,10 @@ input[type="range"]::-ms-fill-lower {
2862
2862
  --tw-bg-opacity: 1;
2863
2863
  background-color: rgb(253 246 178 / var(--tw-bg-opacity, 1));
2864
2864
  }
2865
+ .bg-yellow-200 {
2866
+ --tw-bg-opacity: 1;
2867
+ background-color: rgb(252 233 106 / var(--tw-bg-opacity, 1));
2868
+ }
2865
2869
  .bg-yellow-400 {
2866
2870
  --tw-bg-opacity: 1;
2867
2871
  background-color: rgb(227 160 8 / var(--tw-bg-opacity, 1));
@@ -3082,9 +3086,6 @@ input[type="range"]::-ms-fill-lower {
3082
3086
  .fill-yellow-400 {
3083
3087
  fill: #E3A008;
3084
3088
  }
3085
- .stroke-\[1\.5\] {
3086
- stroke-width: 1.5;
3087
- }
3088
3089
  .object-contain {
3089
3090
  -o-object-fit: contain;
3090
3091
  object-fit: contain;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pagamio/frontend-commons-lib",
3
3
  "description": "Pagamio library for Frontend reusable components like the form engine and table container",
4
- "version": "0.8.232",
4
+ "version": "0.8.233",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "provenance": false