@devalok/shilp-sutra 0.43.0 → 0.44.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/MIGRATION.md +46 -0
- package/dist/_chunks/chat.js +163 -162
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js +34 -32
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/oauth-button.js +102 -97
- package/dist/_chunks/oauth-button.js.map +1 -1
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/composed/command-palette.js +3 -3
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.d.ts +6 -0
- package/dist/composed/content-card.d.ts.map +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/extensions/file-attachment.d.ts.map +1 -1
- package/dist/composed/file-preview/audio-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +146 -142
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.js +5 -2
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/page-header.js +1 -1
- package/dist/composed/page-header.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/audio-player.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +595 -586
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.js +164 -162
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/shell/notification-center.d.ts.map +1 -1
- package/dist/shell/notification-center.js +101 -97
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/sidebar.d.ts.map +1 -1
- package/dist/shell/sidebar.js +137 -122
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/top-bar.d.ts.map +1 -1
- package/dist/shell/top-bar.js +86 -83
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/semantic.css +1 -0
- package/dist/ui/avatar.js +1 -1
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/breadcrumb.js +2 -2
- package/dist/ui/breadcrumb.js.map +1 -1
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts +82 -7
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +74 -108
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/combobox.js +2 -2
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/dropdown-menu.js +9 -3
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/index.d.ts +2 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +58 -57
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/menubar.js +9 -3
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -1
- package/dist/ui/select.js +5 -2
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sidebar.js +73 -73
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/stat-card.d.ts +8 -5
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +168 -150
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +5 -2
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/truncated-text.d.ts +37 -0
- package/dist/ui/truncated-text.d.ts.map +1 -0
- package/dist/ui/truncated-text.js +53 -0
- package/dist/ui/truncated-text.js.map +1 -0
- package/docs/components/ui/card.md +13 -4
- package/docs/components/ui/stat-card.md +7 -2
- package/docs/components/ui/truncated-text.md +49 -0
- package/llms-full.txt +70 -7
- package/make-kit/components/card.md +14 -4
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/references/components-full.md +70 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.js","names":[],"sources":["../../src/shell/sidebar.tsx"],"sourcesContent":["'use client'\n\n/**\n * AppSidebar -- Application-layer sidebar built on the Sidebar primitive.\n *\n * Design-system token migration (2026-02-28):\n * All V1 colour tokens have been replaced with semantic design-system tokens.\n * Typography classes replaced with Tailwind equivalents.\n *\n * Props-driven: accepts user info, currentPath, and navItems instead of\n * reading from Remix hooks or Zustand stores.\n */\nimport * as React from 'react'\n\nimport { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from '../ui/collapsible'\nimport { cn } from '../ui/lib/utils'\nimport {\n Sidebar as ShadcnSidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarMenu,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarSeparator,\n} from '../ui/sidebar'\nimport { useLink } from './link-context'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface NavSubItem {\n title: string\n href: string\n /** Optional icon. Accepts any `IconInput`. */\n icon?: IconInput\n exact?: boolean\n}\n\nexport interface NavItem {\n title: string\n href: string\n /** Icon for this nav item. Accepts any `IconInput`. */\n icon: IconInput\n /** When true, the route matches only when the path is exactly equal */\n exact?: boolean\n /** Badge rendered on the right side of the nav item */\n badge?: string | number\n /** Optional child items — renders as collapsible sub-list with chevron */\n children?: NavSubItem[]\n /** Whether the collapsible is open by default. Auto-opens when a child is active. */\n defaultOpen?: boolean\n}\n\nexport interface NavGroup {\n label: string\n items: NavItem[]\n /** Action rendered next to the group label (e.g., a \"+\" button) */\n action?: React.ReactNode\n}\n\nexport interface SidebarUser {\n name: string\n email?: string\n image?: string | null\n designation?: string\n role?: string\n}\n\nexport interface SidebarPromo {\n /** Promo message text */\n text: string\n /** Optional icon rendered before the text. Accepts any `IconInput`. */\n icon?: IconInput\n /** Action button rendered in the promo banner */\n action?: { label: string; href?: string; onClick?: () => void }\n /** When provided, renders a dismiss (X) button that calls this handler */\n onDismiss?: () => void\n}\n\nexport interface SidebarFooterConfig {\n /** Legal/utility links rendered as a row separated by dividers */\n links?: Array<{ label: string; href: string }>\n /** Version or build info text (or link) rendered inline after links */\n version?: string | { label: string; href: string }\n /** Custom content rendered above the links row */\n slot?: React.ReactNode\n /** Promo/upsell banner rendered above the links row */\n promo?: SidebarPromo\n}\n\nexport interface AppSidebarProps\n extends React.HTMLAttributes<HTMLDivElement> {\n /** Currently active pathname -- used to highlight the active nav item */\n currentPath?: string\n /** User information displayed in the sidebar header */\n user?: SidebarUser | null\n /** Primary navigation groups rendered in the main content area */\n navGroups?: NavGroup[]\n /** Optional logo element. Falls back to a text placeholder. */\n logo?: React.ReactNode\n /** Footer links rendered at the bottom of the sidebar */\n footerLinks?: Array<{ label: string; href: string }>\n /** Structured footer config (takes precedence over footerLinks) */\n footer?: SidebarFooterConfig\n /** Content rendered between user header and navigation */\n headerSlot?: React.ReactNode\n /** Content rendered between navigation and footer */\n preFooterSlot?: React.ReactNode\n /** className applied to the wrapper div around preFooterSlot */\n preFooterClassName?: string\n /** Override rendering for specific nav items. Return null to use default rendering. */\n renderItem?: (item: NavItem, defaultRender: () => React.ReactNode) => React.ReactNode | null\n /** Additional className for the root sidebar element */\n className?: string\n /**\n * Corner radius of nav items (composable). @default 'md' (control radius, ~6px).\n * `'lg'` restores the previous rounder look; `'sm'` is tighter; `'pill'` is fully rounded.\n * Sets the `--ds-sidebar-item-radius` CSS var, so you can also override it via `className`/`style`.\n */\n navItemRadius?: 'sm' | 'md' | 'lg' | 'pill'\n}\n\n// -----------------------------------------------------------------------\n// ChevronRight (inline SVG icon for collapsible toggle)\n// -----------------------------------------------------------------------\n\nfunction ChevronRight({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n )\n}\n\nfunction CloseIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n )\n}\n\n// -----------------------------------------------------------------------\n// Shared styles\n// -----------------------------------------------------------------------\n\n// Radius is composable via the `navItemRadius` prop (sets --ds-sidebar-item-radius).\n// Default is the control radius (~6px) — surface (10px) read as over-rounded blobs.\nconst navItemBase =\n 'relative gap-ds-04 rounded-[var(--ds-sidebar-item-radius,var(--radius-control))] px-ds-04 py-ds-03 transition-colors duration-fast-02'\nconst NAV_ITEM_RADIUS = {\n sm: 'var(--radius-control-inner)',\n md: 'var(--radius-control)',\n lg: 'var(--radius-surface)',\n pill: 'var(--radius-pill)',\n} as const\n// Active = tinted surface + accent text + weight. No accent rail — the tint and\n// colour already signal \"you are here\"; a stripe on top is doubled accent (AI tell).\nconst navItemActive = 'bg-accent-2 text-accent-11 font-medium'\nconst navItemInactive = 'text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg'\n\n// -----------------------------------------------------------------------\n// NavLink (internal)\n// -----------------------------------------------------------------------\n\nfunction NavLink({\n item,\n isActive,\n isPathActive,\n}: {\n item: NavItem\n isActive: boolean\n isPathActive: (path: string, exact?: boolean) => boolean\n}) {\n const Link = useLink()\n const badgeContent =\n item.badge != null\n ? typeof item.badge === 'number' && item.badge > 99\n ? '99+'\n : String(item.badge)\n : null\n\n // S9: Collapsible children\n if (item.children && item.children.length > 0) {\n const hasActiveChild = item.children.some((child) =>\n isPathActive(child.href, child.exact),\n )\n const shouldOpen = hasActiveChild || isActive || (item.defaultOpen ?? false)\n\n return (\n <Collapsible defaultOpen={shouldOpen} className=\"group/collapsible\">\n <SidebarMenuItem>\n {/* Button row — chevron is anchored here, not on the full <li> */}\n <div className=\"relative\">\n <SidebarMenuButton\n asChild\n isActive={isActive || hasActiveChild}\n tooltip={item.title}\n className={cn(\n navItemBase,\n isActive || hasActiveChild ? navItemActive : navItemInactive,\n )}\n >\n <Link\n href={item.href}\n aria-label={item.title}\n aria-current={isActive ? 'page' : undefined}\n >\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md shrink-0\" aria-hidden=\"true\">\n <IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n <span className=\"text-ds-base\">{item.title}</span>\n </Link>\n </SidebarMenuButton>\n {badgeContent && <SidebarMenuBadge>{badgeContent}</SidebarMenuBadge>}\n <CollapsibleTrigger asChild>\n <button\n className=\"absolute right-ds-02 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded-control text-surface-fg-subtle transition-colors hover:bg-surface-raised-hover hover:text-surface-fg group-data-[collapsible=icon]:hidden\"\n aria-label={`Toggle ${item.title}`}\n >\n <ChevronRight className=\"h-4 w-4 transition-transform duration-fast-02 ease-productive-standard group-data-[state=open]/collapsible:rotate-90\" />\n </button>\n </CollapsibleTrigger>\n </div>\n <CollapsibleContent>\n <SidebarMenuSub>\n {item.children.map((child) => {\n const childActive = isPathActive(child.href, child.exact)\n return (\n <SidebarMenuSubItem key={child.href}>\n <SidebarMenuSubButton\n asChild\n isActive={childActive}\n >\n <Link\n href={child.href}\n aria-current={childActive ? 'page' : undefined}\n >\n {child.icon && (\n <span className=\"[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0\" aria-hidden=\"true\">\n <IconProvider size=\"sm\">{normalizeIcon(child.icon)}</IconProvider>\n </span>\n )}\n <span>{child.title}</span>\n </Link>\n </SidebarMenuSubButton>\n </SidebarMenuSubItem>\n )\n })}\n </SidebarMenuSub>\n </CollapsibleContent>\n </SidebarMenuItem>\n </Collapsible>\n )\n }\n\n // Default: flat nav item\n return (\n <SidebarMenuItem>\n <SidebarMenuButton\n asChild\n isActive={isActive}\n tooltip={item.title}\n className={cn(\n navItemBase,\n isActive ? navItemActive : navItemInactive,\n )}\n >\n <Link\n href={item.href}\n aria-label={item.title}\n aria-current={isActive ? 'page' : undefined}\n >\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md shrink-0\" aria-hidden=\"true\"><IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider></span>\n <span className=\"text-ds-base\">{item.title}</span>\n </Link>\n </SidebarMenuButton>\n {badgeContent && <SidebarMenuBadge>{badgeContent}</SidebarMenuBadge>}\n </SidebarMenuItem>\n )\n}\n\n// -----------------------------------------------------------------------\n// AppSidebar\n// -----------------------------------------------------------------------\n\nconst AppSidebar = React.forwardRef<HTMLDivElement, AppSidebarProps>(\n (\n {\n currentPath = '/',\n user,\n navGroups = [],\n logo,\n headerSlot,\n preFooterSlot,\n preFooterClassName,\n footerLinks = [],\n footer,\n renderItem,\n className,\n navItemRadius,\n style,\n ...props\n },\n ref,\n ) => {\n const Link = useLink()\n const isActive = (path: string, exact = false) => {\n if (exact || path === '/') {\n return currentPath === path\n }\n return currentPath.startsWith(path)\n }\n\n return (\n <ShadcnSidebar\n {...props}\n ref={ref}\n aria-label=\"Main navigation\"\n style={\n navItemRadius\n ? ({ '--ds-sidebar-item-radius': NAV_ITEM_RADIUS[navItemRadius], ...style } as React.CSSProperties)\n : style\n }\n className={cn(\n 'z-raised hidden h-full flex-col border-r border-surface-border-strong bg-surface-raised md:flex',\n className,\n )}\n >\n {/* Logo Header */}\n <SidebarHeader className=\"px-ds-06 py-ds-06\">\n {logo ?? (\n <span className=\"text-ds-lg font-semibold text-surface-fg\">\n Logo\n </span>\n )}\n </SidebarHeader>\n\n {/* User Info */}\n {user && (\n <div className=\"flex items-center gap-ds-04 px-ds-06 pb-ds-05\">\n <Avatar className=\"h-ds-sm-plus w-ds-sm-plus\">\n {user.image ? (\n <AvatarImage src={user.image} alt={user.name} />\n ) : null}\n <AvatarFallback className=\"bg-surface-raised-hover text-surface-fg\">\n {user.name?.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"truncate text-ds-md text-surface-fg\">\n {user.name}\n </span>\n <span className=\"truncate text-ds-sm text-surface-fg-subtle\">\n {user.designation || user.role}\n </span>\n </div>\n </div>\n )}\n\n <SidebarSeparator />\n\n {/* Header Slot (S13) */}\n {headerSlot && (\n <>\n {headerSlot}\n <SidebarSeparator />\n </>\n )}\n\n {/* Navigation Groups */}\n <SidebarContent className=\"no-scrollbar px-ds-04\">\n {navGroups.map((group, idx) => (\n <div key={group.label}>\n {idx > 0 && <SidebarSeparator />}\n <SidebarGroup>\n <SidebarGroupLabel className=\"px-ds-04 text-ds-sm text-surface-fg-subtle\">\n {group.label}\n </SidebarGroupLabel>\n {group.action && (\n <SidebarGroupAction asChild>{group.action}</SidebarGroupAction>\n )}\n <SidebarGroupContent>\n <SidebarMenu>\n {group.items.map((item) => {\n const defaultRender = () => (\n <NavLink\n item={item}\n isActive={isActive(item.href, item.exact)}\n isPathActive={isActive}\n />\n )\n\n if (renderItem) {\n const custom = renderItem(item, defaultRender)\n if (custom !== null) {\n return <React.Fragment key={item.href}>{custom}</React.Fragment>\n }\n }\n\n return <React.Fragment key={item.href}>{defaultRender()}</React.Fragment>\n })}\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n </div>\n ))}\n </SidebarContent>\n\n {/* Pre-Footer Slot (S13) */}\n {preFooterSlot && (\n <>\n <SidebarSeparator />\n <div className={preFooterClassName}>\n {preFooterSlot}\n </div>\n </>\n )}\n\n {/* Footer */}\n {footer ? (\n <SidebarFooter className=\"gap-ds-03 px-ds-06 py-ds-05\">\n {footer.slot && <div>{footer.slot}</div>}\n\n {/* Promo banner */}\n {footer.promo && (\n <div className=\"relative rounded-surface bg-surface-raised p-ds-04 shadow-raised\">\n {footer.promo.onDismiss && (\n <button\n onClick={footer.promo.onDismiss}\n aria-label=\"Dismiss\"\n className=\"absolute right-ds-02 top-ds-02 flex h-5 w-5 items-center justify-center rounded-control text-surface-fg-subtle transition-colors hover:bg-surface-raised-hover hover:text-surface-fg\"\n >\n <CloseIcon className=\"h-3.5 w-3.5\" />\n </button>\n )}\n <div className=\"flex flex-col gap-ds-03\">\n {footer.promo.icon && (\n <span className=\"text-accent-11 [&>svg]:h-ico-md [&>svg]:w-ico-md\" aria-hidden=\"true\">\n <IconProvider size=\"md\">{normalizeIcon(footer.promo.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-col gap-ds-03\">\n <p className=\"text-ds-sm text-surface-fg\">{footer.promo.text}</p>\n {footer.promo.action && (\n footer.promo.action.href ? (\n <Link\n href={footer.promo.action.href}\n onClick={footer.promo.action.onClick}\n className=\"inline-flex self-start rounded-control bg-accent-9 px-ds-04 py-ds-02 text-ds-sm font-medium text-accent-fg transition-colors hover:bg-accent-10\"\n >\n {footer.promo.action.label}\n </Link>\n ) : (\n <button\n onClick={footer.promo.action.onClick}\n className=\"inline-flex self-start rounded-control bg-accent-9 px-ds-04 py-ds-02 text-ds-sm font-medium text-accent-fg transition-colors hover:bg-accent-10\"\n >\n {footer.promo.action.label}\n </button>\n )\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* Links + version on same line */}\n {(footer.links?.length || footer.version) && (\n <div className=\"flex items-center gap-ds-03 text-ds-sm text-surface-fg-subtle\">\n {footer.links?.map((link, i) => (\n <React.Fragment key={link.href}>\n {i > 0 && <span>·</span>}\n <Link\n className=\"transition-colors hover:text-accent-11\"\n href={link.href}\n >\n {link.label}\n </Link>\n </React.Fragment>\n ))}\n {footer.links?.length && footer.version && <span>·</span>}\n {footer.version && (\n typeof footer.version === 'string'\n ? <span>{footer.version}</span>\n : <Link className=\"transition-colors hover:text-accent-11\" href={footer.version.href}>{footer.version.label}</Link>\n )}\n </div>\n )}\n </SidebarFooter>\n ) : footerLinks.length > 0 ? (\n <SidebarFooter className=\"px-ds-06 py-ds-05\">\n <div className=\"flex items-center gap-ds-03 text-ds-sm text-surface-fg-subtle\">\n {footerLinks.map((link, i) => (\n <React.Fragment key={link.href}>\n {i > 0 && <span>·</span>}\n <Link\n className=\"transition-colors hover:text-accent-11\"\n href={link.href}\n >\n {link.label}\n </Link>\n </React.Fragment>\n ))}\n </div>\n </SidebarFooter>\n ) : null}\n </ShadcnSidebar>\n )\n },\n)\nAppSidebar.displayName = 'AppSidebar'\n\nexport { AppSidebar }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sidebar.js","names":[],"sources":["../../src/shell/sidebar.tsx"],"sourcesContent":["'use client'\n\n/**\n * AppSidebar -- Application-layer sidebar built on the Sidebar primitive.\n *\n * Design-system token migration (2026-02-28):\n * All V1 colour tokens have been replaced with semantic design-system tokens.\n * Typography classes replaced with Tailwind equivalents.\n *\n * Props-driven: accepts user info, currentPath, and navItems instead of\n * reading from Remix hooks or Zustand stores.\n */\nimport * as React from 'react'\n\nimport { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar'\nimport { Button } from '../ui/button'\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from '../ui/collapsible'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport {\n Sidebar as ShadcnSidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarMenu,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarSeparator,\n} from '../ui/sidebar'\nimport { TruncatedText } from '../ui/truncated-text'\nimport { useLink } from './link-context'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface NavSubItem {\n title: string\n href: string\n /** Optional icon. Accepts any `IconInput`. */\n icon?: IconInput\n exact?: boolean\n}\n\nexport interface NavItem {\n title: string\n href: string\n /** Icon for this nav item. Accepts any `IconInput`. */\n icon: IconInput\n /** When true, the route matches only when the path is exactly equal */\n exact?: boolean\n /** Badge rendered on the right side of the nav item */\n badge?: string | number\n /** Optional child items — renders as collapsible sub-list with chevron */\n children?: NavSubItem[]\n /** Whether the collapsible is open by default. Auto-opens when a child is active. */\n defaultOpen?: boolean\n}\n\nexport interface NavGroup {\n label: string\n items: NavItem[]\n /** Action rendered next to the group label (e.g., a \"+\" button) */\n action?: React.ReactNode\n}\n\nexport interface SidebarUser {\n name: string\n email?: string\n image?: string | null\n designation?: string\n role?: string\n}\n\nexport interface SidebarPromo {\n /** Promo message text */\n text: string\n /** Optional icon rendered before the text. Accepts any `IconInput`. */\n icon?: IconInput\n /** Action button rendered in the promo banner */\n action?: { label: string; href?: string; onClick?: () => void }\n /** When provided, renders a dismiss (X) button that calls this handler */\n onDismiss?: () => void\n}\n\nexport interface SidebarFooterConfig {\n /** Legal/utility links rendered as a row separated by dividers */\n links?: Array<{ label: string; href: string }>\n /** Version or build info text (or link) rendered inline after links */\n version?: string | { label: string; href: string }\n /** Custom content rendered above the links row */\n slot?: React.ReactNode\n /** Promo/upsell banner rendered above the links row */\n promo?: SidebarPromo\n}\n\nexport interface AppSidebarProps\n extends React.HTMLAttributes<HTMLDivElement> {\n /** Currently active pathname -- used to highlight the active nav item */\n currentPath?: string\n /** User information displayed in the sidebar header */\n user?: SidebarUser | null\n /** Primary navigation groups rendered in the main content area */\n navGroups?: NavGroup[]\n /** Optional logo element. Falls back to a text placeholder. */\n logo?: React.ReactNode\n /** Footer links rendered at the bottom of the sidebar */\n footerLinks?: Array<{ label: string; href: string }>\n /** Structured footer config (takes precedence over footerLinks) */\n footer?: SidebarFooterConfig\n /** Content rendered between user header and navigation */\n headerSlot?: React.ReactNode\n /** Content rendered between navigation and footer */\n preFooterSlot?: React.ReactNode\n /** className applied to the wrapper div around preFooterSlot */\n preFooterClassName?: string\n /** Override rendering for specific nav items. Return null to use default rendering. */\n renderItem?: (item: NavItem, defaultRender: () => React.ReactNode) => React.ReactNode | null\n /** Additional className for the root sidebar element */\n className?: string\n /**\n * Corner radius of nav items (composable). @default 'md' (control radius, ~6px).\n * `'lg'` restores the previous rounder look; `'sm'` is tighter; `'pill'` is fully rounded.\n * Sets the `--ds-sidebar-item-radius` CSS var, so you can also override it via `className`/`style`.\n */\n navItemRadius?: 'sm' | 'md' | 'lg' | 'pill'\n}\n\n// -----------------------------------------------------------------------\n// ChevronRight (inline SVG icon for collapsible toggle)\n// -----------------------------------------------------------------------\n\nfunction ChevronRight({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n )\n}\n\nfunction CloseIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n )\n}\n\n// -----------------------------------------------------------------------\n// Shared styles\n// -----------------------------------------------------------------------\n\n// Radius is composable via the `navItemRadius` prop (sets --ds-sidebar-item-radius).\n// Default is the control radius (~6px) — surface (10px) read as over-rounded blobs.\nconst navItemBase =\n 'relative gap-ds-04 rounded-[var(--ds-sidebar-item-radius,var(--radius-control))] px-ds-04 py-ds-03 transition-colors duration-fast-02'\nconst NAV_ITEM_RADIUS = {\n sm: 'var(--radius-control-inner)',\n md: 'var(--radius-control)',\n lg: 'var(--radius-surface)',\n pill: 'var(--radius-pill)',\n} as const\n// Active = tinted surface + accent text + weight. No accent rail — the tint and\n// colour already signal \"you are here\"; a stripe on top is doubled accent (AI tell).\nconst navItemActive = 'bg-accent-2 text-accent-11 font-medium'\nconst navItemInactive = 'text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg'\n\n// -----------------------------------------------------------------------\n// NavLink (internal)\n// -----------------------------------------------------------------------\n\nfunction NavLink({\n item,\n isActive,\n isPathActive,\n}: {\n item: NavItem\n isActive: boolean\n isPathActive: (path: string, exact?: boolean) => boolean\n}) {\n const Link = useLink()\n const badgeContent =\n item.badge != null\n ? typeof item.badge === 'number' && item.badge > 99\n ? '99+'\n : String(item.badge)\n : null\n\n // S9: Collapsible children\n if (item.children && item.children.length > 0) {\n const hasActiveChild = item.children.some((child) =>\n isPathActive(child.href, child.exact),\n )\n const shouldOpen = hasActiveChild || isActive || (item.defaultOpen ?? false)\n\n return (\n <Collapsible defaultOpen={shouldOpen} className=\"group/collapsible\">\n <SidebarMenuItem>\n {/* Button row — chevron is anchored here, not on the full <li> */}\n <div className=\"relative\">\n <SidebarMenuButton\n asChild\n isActive={isActive || hasActiveChild}\n tooltip={item.title}\n className={cn(\n navItemBase,\n isActive || hasActiveChild ? navItemActive : navItemInactive,\n )}\n >\n <Link\n href={item.href}\n aria-label={item.title}\n aria-current={isActive ? 'page' : undefined}\n className=\"min-w-0\"\n >\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md shrink-0\" aria-hidden=\"true\">\n <IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n <span className=\"text-ds-base truncate\">{item.title}</span>\n </Link>\n </SidebarMenuButton>\n {badgeContent && <SidebarMenuBadge>{badgeContent}</SidebarMenuBadge>}\n <CollapsibleTrigger asChild>\n <button\n className=\"absolute right-ds-02 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded-control text-surface-fg-subtle transition-colors hover:bg-surface-raised-hover hover:text-surface-fg group-data-[collapsible=icon]:hidden\"\n aria-label={`Toggle ${item.title}`}\n >\n <ChevronRight className=\"h-4 w-4 transition-transform duration-fast-02 ease-productive-standard group-data-[state=open]/collapsible:rotate-90\" />\n </button>\n </CollapsibleTrigger>\n </div>\n <CollapsibleContent>\n <SidebarMenuSub>\n {item.children.map((child) => {\n const childActive = isPathActive(child.href, child.exact)\n return (\n <SidebarMenuSubItem key={child.href}>\n <SidebarMenuSubButton\n asChild\n isActive={childActive}\n >\n <Link\n href={child.href}\n aria-current={childActive ? 'page' : undefined}\n className=\"min-w-0\"\n >\n {child.icon && (\n <span className=\"[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0\" aria-hidden=\"true\">\n <IconProvider size=\"sm\">{normalizeIcon(child.icon)}</IconProvider>\n </span>\n )}\n <span className=\"truncate\">{child.title}</span>\n </Link>\n </SidebarMenuSubButton>\n </SidebarMenuSubItem>\n )\n })}\n </SidebarMenuSub>\n </CollapsibleContent>\n </SidebarMenuItem>\n </Collapsible>\n )\n }\n\n // Default: flat nav item\n return (\n <SidebarMenuItem>\n <SidebarMenuButton\n asChild\n isActive={isActive}\n tooltip={item.title}\n className={cn(\n navItemBase,\n isActive ? navItemActive : navItemInactive,\n )}\n >\n <Link\n href={item.href}\n aria-label={item.title}\n aria-current={isActive ? 'page' : undefined}\n className=\"min-w-0\"\n >\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md shrink-0\" aria-hidden=\"true\"><IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider></span>\n <span className=\"text-ds-base truncate\">{item.title}</span>\n </Link>\n </SidebarMenuButton>\n {badgeContent && <SidebarMenuBadge>{badgeContent}</SidebarMenuBadge>}\n </SidebarMenuItem>\n )\n}\n\n// -----------------------------------------------------------------------\n// AppSidebar\n// -----------------------------------------------------------------------\n\nconst AppSidebar = React.forwardRef<HTMLDivElement, AppSidebarProps>(\n (\n {\n currentPath = '/',\n user,\n navGroups = [],\n logo,\n headerSlot,\n preFooterSlot,\n preFooterClassName,\n footerLinks = [],\n footer,\n renderItem,\n className,\n navItemRadius,\n style,\n ...props\n },\n ref,\n ) => {\n const Link = useLink()\n const isActive = (path: string, exact = false) => {\n if (exact || path === '/') {\n return currentPath === path\n }\n return currentPath.startsWith(path)\n }\n\n return (\n <ShadcnSidebar\n {...props}\n ref={ref}\n aria-label=\"Main navigation\"\n style={\n navItemRadius\n ? ({ '--ds-sidebar-item-radius': NAV_ITEM_RADIUS[navItemRadius], ...style } as React.CSSProperties)\n : style\n }\n className={cn(\n 'z-raised hidden h-full flex-col border-r border-surface-border-strong bg-surface-raised md:flex',\n className,\n )}\n >\n {/* Logo Header */}\n <SidebarHeader className=\"px-ds-06 py-ds-06\">\n {logo ?? (\n <span className=\"text-ds-lg font-semibold text-surface-fg\">\n Logo\n </span>\n )}\n </SidebarHeader>\n\n {/* User Info */}\n {user && (\n <div className=\"flex items-center gap-ds-04 px-ds-06 pb-ds-05\">\n <Avatar className=\"h-ds-sm-plus w-ds-sm-plus\">\n {user.image ? (\n <AvatarImage src={user.image} alt={user.name} />\n ) : null}\n <AvatarFallback className=\"bg-surface-raised-hover text-surface-fg\">\n {user.name?.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n <div className=\"flex min-w-0 flex-col\">\n <TruncatedText className=\"text-ds-md text-surface-fg\">\n {user.name ?? ''}\n </TruncatedText>\n <TruncatedText className=\"text-ds-sm text-surface-fg-subtle\">\n {user.designation || user.role || ''}\n </TruncatedText>\n </div>\n </div>\n )}\n\n <SidebarSeparator />\n\n {/* Header Slot (S13) */}\n {headerSlot && (\n <>\n {headerSlot}\n <SidebarSeparator />\n </>\n )}\n\n {/* Navigation Groups */}\n <SidebarContent className=\"no-scrollbar px-ds-04\">\n {navGroups.map((group, idx) => (\n <div key={group.label}>\n {idx > 0 && <SidebarSeparator />}\n <SidebarGroup>\n <SidebarGroupLabel className=\"px-ds-04 text-ds-sm text-surface-fg-subtle\">\n {group.label}\n </SidebarGroupLabel>\n {group.action && (\n <SidebarGroupAction asChild>{group.action}</SidebarGroupAction>\n )}\n <SidebarGroupContent>\n <SidebarMenu>\n {group.items.map((item) => {\n const defaultRender = () => (\n <NavLink\n item={item}\n isActive={isActive(item.href, item.exact)}\n isPathActive={isActive}\n />\n )\n\n if (renderItem) {\n const custom = renderItem(item, defaultRender)\n if (custom !== null) {\n return <React.Fragment key={item.href}>{custom}</React.Fragment>\n }\n }\n\n return <React.Fragment key={item.href}>{defaultRender()}</React.Fragment>\n })}\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n </div>\n ))}\n </SidebarContent>\n\n {/* Pre-Footer Slot (S13) */}\n {preFooterSlot && (\n <>\n <SidebarSeparator />\n <div className={preFooterClassName}>\n {preFooterSlot}\n </div>\n </>\n )}\n\n {/* Footer */}\n {footer ? (\n <SidebarFooter className=\"gap-ds-03 px-ds-06 py-ds-05\">\n {footer.slot && <div>{footer.slot}</div>}\n\n {/* Promo banner */}\n {footer.promo && (\n <div className=\"relative rounded-surface bg-surface-raised p-ds-04 shadow-raised\">\n {footer.promo.onDismiss && (\n <button\n onClick={footer.promo.onDismiss}\n aria-label=\"Dismiss\"\n className=\"absolute right-ds-02 top-ds-02 flex h-5 w-5 items-center justify-center rounded-control text-surface-fg-subtle transition-colors hover:bg-surface-raised-hover hover:text-surface-fg\"\n >\n <CloseIcon className=\"h-3.5 w-3.5\" />\n </button>\n )}\n <div className=\"flex flex-col gap-ds-03\">\n {footer.promo.icon && (\n <span className=\"text-accent-11 [&>svg]:h-ico-md [&>svg]:w-ico-md\" aria-hidden=\"true\">\n <IconProvider size=\"md\">{normalizeIcon(footer.promo.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-col gap-ds-03\">\n <p className=\"text-ds-sm text-surface-fg line-clamp-2\">{footer.promo.text}</p>\n {footer.promo.action && (\n footer.promo.action.href ? (\n <Button asChild variant=\"solid\" size=\"sm\" className=\"self-start\">\n <Link\n href={footer.promo.action.href}\n onClick={footer.promo.action.onClick}\n >\n {footer.promo.action.label}\n </Link>\n </Button>\n ) : (\n <Button\n variant=\"solid\"\n size=\"sm\"\n className=\"self-start\"\n onClick={footer.promo.action.onClick}\n >\n {footer.promo.action.label}\n </Button>\n )\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* Links + version on same line */}\n {(footer.links?.length || footer.version) && (\n <div className=\"flex items-center gap-ds-03 text-ds-sm text-surface-fg-subtle\">\n {footer.links?.map((link, i) => (\n <React.Fragment key={link.href}>\n {i > 0 && <span>·</span>}\n <Link\n className=\"transition-colors hover:text-accent-11\"\n href={link.href}\n >\n {link.label}\n </Link>\n </React.Fragment>\n ))}\n {footer.links?.length && footer.version && <span>·</span>}\n {footer.version && (\n typeof footer.version === 'string'\n ? <span>{footer.version}</span>\n : <Link className=\"transition-colors hover:text-accent-11\" href={footer.version.href}>{footer.version.label}</Link>\n )}\n </div>\n )}\n </SidebarFooter>\n ) : footerLinks.length > 0 ? (\n <SidebarFooter className=\"px-ds-06 py-ds-05\">\n <div className=\"flex items-center gap-ds-03 text-ds-sm text-surface-fg-subtle\">\n {footerLinks.map((link, i) => (\n <React.Fragment key={link.href}>\n {i > 0 && <span>·</span>}\n <Link\n className=\"transition-colors hover:text-accent-11\"\n href={link.href}\n >\n {link.label}\n </Link>\n </React.Fragment>\n ))}\n </div>\n </SidebarFooter>\n ) : null}\n </ShadcnSidebar>\n )\n },\n)\nAppSidebar.displayName = 'AppSidebar'\n\nexport { AppSidebar }\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../src/shell/top-bar.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../src/shell/top-bar.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAcrD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAMD,UAAU,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC;IACjE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAgCD,UAAU,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACpE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAmBD,UAAU,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACtE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAmBD,UAAU,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACrE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAmBD,QAAA,MAAM,MAAM;;;;CAIF,CAAA;AAEV,UAAU,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACvE,GAAG,CAAC,EAAE,MAAM,OAAO,MAAM,CAAA;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAmBD,UAAU,qBACR,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACrD,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAkCD,UAAU,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC;IACzE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAsBD,UAAU,mBAAmB;IAC3B,IAAI,EAAE,UAAU,CAAA;IAChB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmJD,MAAM,MAAM,WAAW,GAAG,eAAe,CAAA;AAEzC,QAAA,MAAM,MAAM;;;;;;;;CAQV,CAAA;AAEF,OAAO,EAAE,MAAM,EAAE,CAAA"}
|
package/dist/shell/top-bar.js
CHANGED
|
@@ -6,192 +6,195 @@ import { Avatar as r, AvatarFallback as i, AvatarImage as a } from "../ui/avatar
|
|
|
6
6
|
import { t as o } from "../_chunks/normalize-icon.js";
|
|
7
7
|
import { DropdownMenu as s, DropdownMenuContent as c, DropdownMenuItem as l, DropdownMenuSeparator as u, DropdownMenuTrigger as d } from "../ui/dropdown-menu.js";
|
|
8
8
|
import { Tooltip as f, TooltipContent as p, TooltipTrigger as m } from "../ui/tooltip.js";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
9
|
+
import { TruncatedText as h } from "../ui/truncated-text.js";
|
|
10
|
+
import { useColorMode as g } from "../hooks/use-color-mode.js";
|
|
11
|
+
import * as _ from "react";
|
|
12
|
+
import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
13
|
+
import { IconLogout as x, IconMoon as S, IconSun as C, IconUser as w } from "@tabler/icons-react";
|
|
13
14
|
//#region src/shell/top-bar.tsx
|
|
14
|
-
var
|
|
15
|
-
let a =
|
|
16
|
-
return /* @__PURE__ */
|
|
15
|
+
var T = _.forwardRef(({ className: e, children: n, ...r }, i) => {
|
|
16
|
+
let a = _.Children.toArray(n).some((e) => _.isValidElement(e) && e.type === D);
|
|
17
|
+
return /* @__PURE__ */ y("header", {
|
|
17
18
|
...r,
|
|
18
19
|
ref: i,
|
|
19
20
|
className: t("z-sticky w-full border-b border-surface-border-strong bg-surface-raised px-ds-05 py-ds-04 md:px-ds-06", a ? "grid grid-cols-[1fr_auto_1fr] items-center" : "flex items-center", e),
|
|
20
21
|
children: n
|
|
21
22
|
});
|
|
22
23
|
});
|
|
23
|
-
|
|
24
|
-
var
|
|
24
|
+
T.displayName = "TopBar";
|
|
25
|
+
var E = _.forwardRef(({ className: e, children: n, ...r }, i) => /* @__PURE__ */ y("div", {
|
|
25
26
|
ref: i,
|
|
26
27
|
className: t("flex items-center gap-ds-04", e),
|
|
27
28
|
...r,
|
|
28
29
|
children: n
|
|
29
30
|
}));
|
|
30
|
-
|
|
31
|
-
var
|
|
31
|
+
E.displayName = "TopBar.Left";
|
|
32
|
+
var D = _.forwardRef(({ className: e, children: n, ...r }, i) => /* @__PURE__ */ y("div", {
|
|
32
33
|
ref: i,
|
|
33
34
|
className: t("flex items-center justify-center px-ds-04", e),
|
|
34
35
|
...r,
|
|
35
36
|
children: n
|
|
36
37
|
}));
|
|
37
|
-
|
|
38
|
-
var
|
|
38
|
+
D.displayName = "TopBar.Center";
|
|
39
|
+
var O = _.forwardRef(({ className: e, children: n, ...r }, i) => /* @__PURE__ */ y("div", {
|
|
39
40
|
ref: i,
|
|
40
41
|
className: t("ml-auto flex items-center gap-ds-04", e),
|
|
41
42
|
...r,
|
|
42
43
|
children: n
|
|
43
44
|
}));
|
|
44
|
-
|
|
45
|
-
var
|
|
45
|
+
O.displayName = "TopBar.Right";
|
|
46
|
+
var k = {
|
|
46
47
|
tight: "gap-ds-02",
|
|
47
48
|
default: "gap-ds-04",
|
|
48
49
|
loose: "gap-ds-06"
|
|
49
|
-
},
|
|
50
|
+
}, A = _.forwardRef(({ gap: e = "default", className: n, children: r, ...i }, a) => /* @__PURE__ */ y("div", {
|
|
50
51
|
ref: a,
|
|
51
|
-
className: t("flex items-center",
|
|
52
|
+
className: t("flex items-center", k[e], n),
|
|
52
53
|
...i,
|
|
53
54
|
children: r
|
|
54
55
|
}));
|
|
55
|
-
|
|
56
|
-
var
|
|
56
|
+
A.displayName = "TopBar.Section";
|
|
57
|
+
var j = _.forwardRef(({ icon: n, tooltip: r, className: i, ...a }, s) => /* @__PURE__ */ b(f, { children: [/* @__PURE__ */ y(m, {
|
|
57
58
|
asChild: !0,
|
|
58
|
-
children: /* @__PURE__ */
|
|
59
|
+
children: /* @__PURE__ */ y("button", {
|
|
59
60
|
ref: s,
|
|
60
61
|
type: "button",
|
|
61
62
|
"aria-label": r,
|
|
62
63
|
className: t("flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-surface-border-strong bg-surface-raised-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-raised-active active:scale-90 duration-fast-01 ease-productive-standard", i),
|
|
63
64
|
...a,
|
|
64
|
-
children: /* @__PURE__ */
|
|
65
|
+
children: /* @__PURE__ */ y("span", {
|
|
65
66
|
className: "[&>svg]:h-ico-sm [&>svg]:w-ico-sm",
|
|
66
67
|
"aria-hidden": "true",
|
|
67
|
-
children: /* @__PURE__ */
|
|
68
|
+
children: /* @__PURE__ */ y(e, {
|
|
68
69
|
size: "sm",
|
|
69
70
|
children: o(n)
|
|
70
71
|
})
|
|
71
72
|
})
|
|
72
73
|
})
|
|
73
|
-
}), /* @__PURE__ */
|
|
74
|
+
}), /* @__PURE__ */ y(p, {
|
|
74
75
|
side: "bottom",
|
|
75
76
|
align: "center",
|
|
76
77
|
children: r
|
|
77
78
|
})] }));
|
|
78
|
-
|
|
79
|
-
var
|
|
79
|
+
j.displayName = "TopBar.IconButton";
|
|
80
|
+
var M = _.forwardRef(({ className: e, children: n, ...r }, i) => /* @__PURE__ */ y("h2", {
|
|
80
81
|
ref: i,
|
|
81
82
|
className: t("hidden text-ds-lg text-surface-fg md:block", e),
|
|
82
83
|
...r,
|
|
83
84
|
children: n
|
|
84
85
|
}));
|
|
85
|
-
|
|
86
|
-
var
|
|
87
|
-
let { colorMode:
|
|
88
|
-
return /* @__PURE__ */
|
|
86
|
+
M.displayName = "TopBar.Title";
|
|
87
|
+
var N = _.forwardRef(({ user: T, onNavigate: E, onLogout: D, userMenuItems: O, className: k }, A) => {
|
|
88
|
+
let { colorMode: j, toggleColorMode: M } = g();
|
|
89
|
+
return /* @__PURE__ */ b(s, { children: [/* @__PURE__ */ b(f, { children: [/* @__PURE__ */ y(m, {
|
|
89
90
|
asChild: !0,
|
|
90
|
-
children: /* @__PURE__ */
|
|
91
|
+
children: /* @__PURE__ */ y(d, {
|
|
91
92
|
asChild: !0,
|
|
92
|
-
children: /* @__PURE__ */
|
|
93
|
-
ref:
|
|
93
|
+
children: /* @__PURE__ */ y("button", {
|
|
94
|
+
ref: A,
|
|
94
95
|
type: "button",
|
|
95
|
-
className: t("flex items-center gap-ds-03 outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2",
|
|
96
|
-
children: /* @__PURE__ */
|
|
96
|
+
className: t("flex items-center gap-ds-03 outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", k),
|
|
97
|
+
children: /* @__PURE__ */ b(r, {
|
|
97
98
|
className: "h-ds-sm-plus w-ds-sm-plus cursor-pointer",
|
|
98
|
-
children: [
|
|
99
|
-
src:
|
|
100
|
-
alt:
|
|
101
|
-
}) : null, /* @__PURE__ */
|
|
99
|
+
children: [T.image ? /* @__PURE__ */ y(a, {
|
|
100
|
+
src: T.image,
|
|
101
|
+
alt: T.name
|
|
102
|
+
}) : null, /* @__PURE__ */ y(i, {
|
|
102
103
|
className: "bg-surface-raised-hover text-surface-fg",
|
|
103
|
-
children:
|
|
104
|
+
children: T.name?.charAt(0).toUpperCase()
|
|
104
105
|
})]
|
|
105
106
|
})
|
|
106
107
|
})
|
|
107
108
|
})
|
|
108
|
-
}), /* @__PURE__ */
|
|
109
|
+
}), /* @__PURE__ */ y(p, {
|
|
109
110
|
side: "bottom",
|
|
110
111
|
align: "center",
|
|
111
112
|
children: "User Menu"
|
|
112
|
-
})] }), /* @__PURE__ */
|
|
113
|
+
})] }), /* @__PURE__ */ b(c, {
|
|
113
114
|
className: "w-[200px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating",
|
|
114
115
|
sideOffset: 8,
|
|
115
116
|
align: "end",
|
|
116
117
|
children: [
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ b("div", {
|
|
118
119
|
className: "border-b border-surface-border-strong px-ds-05 py-ds-04",
|
|
119
|
-
children: [/* @__PURE__ */
|
|
120
|
+
children: [/* @__PURE__ */ y("p", {
|
|
120
121
|
className: "text-ds-md text-surface-fg",
|
|
121
|
-
children:
|
|
122
|
-
}),
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
children: T.name
|
|
123
|
+
}), T.email && /* @__PURE__ */ y(h, {
|
|
124
|
+
as: "p",
|
|
125
|
+
mode: "middle",
|
|
126
|
+
className: "text-ds-sm text-surface-fg-subtle",
|
|
127
|
+
children: T.email
|
|
125
128
|
})]
|
|
126
129
|
}),
|
|
127
|
-
/* @__PURE__ */
|
|
130
|
+
/* @__PURE__ */ b(l, {
|
|
128
131
|
className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised",
|
|
129
|
-
onClick: () =>
|
|
130
|
-
children: [/* @__PURE__ */
|
|
131
|
-
icon:
|
|
132
|
+
onClick: () => E?.("/profile"),
|
|
133
|
+
children: [/* @__PURE__ */ y(n, {
|
|
134
|
+
icon: w,
|
|
132
135
|
size: "sm",
|
|
133
136
|
className: "text-surface-fg-muted"
|
|
134
|
-
}), /* @__PURE__ */
|
|
137
|
+
}), /* @__PURE__ */ y("span", {
|
|
135
138
|
className: "text-ds-md text-surface-fg-muted",
|
|
136
139
|
children: "Profile"
|
|
137
140
|
})]
|
|
138
141
|
}),
|
|
139
|
-
|
|
142
|
+
O?.map((n, r) => {
|
|
140
143
|
let i = n.color ? {
|
|
141
144
|
error: "text-error-11",
|
|
142
145
|
success: "text-success-11",
|
|
143
146
|
warning: "text-warning-11",
|
|
144
147
|
info: "text-info-11"
|
|
145
148
|
}[n.color] ?? "text-surface-fg-muted" : "text-surface-fg-muted";
|
|
146
|
-
return /* @__PURE__ */
|
|
149
|
+
return /* @__PURE__ */ b(_.Fragment, { children: [n.separator && /* @__PURE__ */ y(u, { className: "bg-surface-border" }), /* @__PURE__ */ b(l, {
|
|
147
150
|
className: t("flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised", n.disabled && "pointer-events-none opacity-action-disabled"),
|
|
148
151
|
disabled: n.disabled,
|
|
149
152
|
onClick: () => {
|
|
150
|
-
n.disabled || (n.onClick ? n.onClick() : n.href &&
|
|
153
|
+
n.disabled || (n.onClick ? n.onClick() : n.href && E?.(n.href));
|
|
151
154
|
},
|
|
152
155
|
children: [
|
|
153
|
-
n.icon && /* @__PURE__ */
|
|
156
|
+
n.icon && /* @__PURE__ */ y("span", {
|
|
154
157
|
className: t("[&>svg]:h-ico-sm [&>svg]:w-ico-sm", i),
|
|
155
|
-
children: /* @__PURE__ */
|
|
158
|
+
children: /* @__PURE__ */ y(e, {
|
|
156
159
|
size: "sm",
|
|
157
160
|
children: o(n.icon)
|
|
158
161
|
})
|
|
159
162
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
163
|
+
/* @__PURE__ */ y("span", {
|
|
161
164
|
className: t("text-ds-md", i),
|
|
162
165
|
children: n.label
|
|
163
166
|
}),
|
|
164
|
-
n.badge != null && n.badge !== !1 && (typeof n.badge == "string" ? /* @__PURE__ */
|
|
167
|
+
n.badge != null && n.badge !== !1 && (typeof n.badge == "string" ? /* @__PURE__ */ y("span", {
|
|
165
168
|
className: "ml-auto inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-pill bg-error-9 px-ds-02 text-[10px] font-semibold leading-none text-error-fg",
|
|
166
169
|
children: n.badge
|
|
167
|
-
}) : /* @__PURE__ */
|
|
170
|
+
}) : /* @__PURE__ */ y("span", { className: "ml-auto h-[8px] w-[8px] rounded-pill bg-error-9" }))
|
|
168
171
|
]
|
|
169
172
|
})] }, n.label + r);
|
|
170
173
|
}),
|
|
171
|
-
/* @__PURE__ */
|
|
174
|
+
/* @__PURE__ */ b(l, {
|
|
172
175
|
className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised",
|
|
173
|
-
onClick:
|
|
174
|
-
children: [
|
|
175
|
-
icon:
|
|
176
|
+
onClick: M,
|
|
177
|
+
children: [j === "dark" ? /* @__PURE__ */ y(n, {
|
|
178
|
+
icon: C,
|
|
176
179
|
size: "sm",
|
|
177
180
|
className: "text-surface-fg-muted"
|
|
178
|
-
}) : /* @__PURE__ */
|
|
179
|
-
icon:
|
|
181
|
+
}) : /* @__PURE__ */ y(n, {
|
|
182
|
+
icon: S,
|
|
180
183
|
size: "sm",
|
|
181
184
|
className: "text-surface-fg-muted"
|
|
182
|
-
}), /* @__PURE__ */
|
|
185
|
+
}), /* @__PURE__ */ y("span", {
|
|
183
186
|
className: "text-ds-md text-surface-fg-muted",
|
|
184
|
-
children:
|
|
187
|
+
children: j === "dark" ? "Light Mode" : "Dark Mode"
|
|
185
188
|
})]
|
|
186
189
|
}),
|
|
187
|
-
|
|
190
|
+
D && /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(u, { className: "bg-surface-border" }), /* @__PURE__ */ b(l, {
|
|
188
191
|
className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised",
|
|
189
|
-
onClick:
|
|
190
|
-
children: [/* @__PURE__ */
|
|
191
|
-
icon:
|
|
192
|
+
onClick: D,
|
|
193
|
+
children: [/* @__PURE__ */ y(n, {
|
|
194
|
+
icon: x,
|
|
192
195
|
size: "sm",
|
|
193
196
|
className: "text-error-11"
|
|
194
|
-
}), /* @__PURE__ */
|
|
197
|
+
}), /* @__PURE__ */ y("span", {
|
|
195
198
|
className: "text-ds-md text-error-11",
|
|
196
199
|
children: "Logout"
|
|
197
200
|
})]
|
|
@@ -199,15 +202,15 @@ var M = g.forwardRef(({ user: w, onNavigate: T, onLogout: E, userMenuItems: D, c
|
|
|
199
202
|
]
|
|
200
203
|
})] });
|
|
201
204
|
});
|
|
202
|
-
|
|
203
|
-
var
|
|
204
|
-
Left:
|
|
205
|
-
Center:
|
|
206
|
-
Right:
|
|
207
|
-
Section:
|
|
208
|
-
IconButton:
|
|
209
|
-
Title:
|
|
210
|
-
UserMenu:
|
|
205
|
+
N.displayName = "TopBar.UserMenu";
|
|
206
|
+
var P = Object.assign(T, {
|
|
207
|
+
Left: E,
|
|
208
|
+
Center: D,
|
|
209
|
+
Right: O,
|
|
210
|
+
Section: A,
|
|
211
|
+
IconButton: j,
|
|
212
|
+
Title: M,
|
|
213
|
+
UserMenu: N
|
|
211
214
|
});
|
|
212
215
|
//#endregion
|
|
213
|
-
export {
|
|
216
|
+
export { P as TopBar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-bar.js","names":[],"sources":["../../src/shell/top-bar.tsx"],"sourcesContent":["'use client'\n\n/**\n * TopBar v2 — Composition-based application top bar.\n *\n * Subcomponents: TopBar.Left, TopBar.Center, TopBar.Right,\n * TopBar.Section, TopBar.IconButton, TopBar.Title, TopBar.UserMenu.\n */\nimport { IconLogout, IconMoon, IconSun,IconUser } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { useColorMode } from '../hooks/use-color-mode'\nimport { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '../ui/tooltip'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface TopBarUser {\n name: string\n email?: string\n image?: string | null\n}\n\nexport interface UserMenuItem {\n /** Display label */\n label: string\n /** Optional icon. Accepts any `IconInput`. */\n icon?: IconInput\n /** Navigate via onNavigate when clicked */\n href?: string\n /** Custom click handler */\n onClick?: () => void\n /** Render a separator before this item */\n separator?: boolean\n /** Text color semantic token (e.g. \"error\") — maps to text-{color} */\n color?: string\n /** Badge content — string for count, true for dot indicator */\n badge?: string | boolean\n /** Whether the item is disabled */\n disabled?: boolean\n}\n\n// -----------------------------------------------------------------------\n// TopBar (root)\n// -----------------------------------------------------------------------\n\ninterface TopBarRootProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n className?: string\n}\n\nconst TopBarRoot = React.forwardRef<HTMLElement, TopBarRootProps>(\n ({ className, children, ...props }, ref) => {\n // Detect if a Center zone is present to switch to grid layout\n const hasCenter = React.Children.toArray(children).some(\n (child) => React.isValidElement(child) && child.type === TopBarCenter,\n )\n\n return (\n <header\n {...props}\n ref={ref}\n className={cn(\n 'z-sticky w-full border-b border-surface-border-strong bg-surface-raised px-ds-05 py-ds-04 md:px-ds-06',\n hasCenter\n ? 'grid grid-cols-[1fr_auto_1fr] items-center'\n : 'flex items-center',\n className,\n )}\n >\n {children}\n </header>\n )\n },\n)\nTopBarRoot.displayName = 'TopBar'\n\n// -----------------------------------------------------------------------\n// TopBar.Left\n// -----------------------------------------------------------------------\n\ninterface TopBarLeftProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarLeft = React.forwardRef<HTMLDivElement, TopBarLeftProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarLeft.displayName = 'TopBar.Left'\n\n// -----------------------------------------------------------------------\n// TopBar.Center\n// -----------------------------------------------------------------------\n\ninterface TopBarCenterProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarCenter = React.forwardRef<HTMLDivElement, TopBarCenterProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center justify-center px-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarCenter.displayName = 'TopBar.Center'\n\n// -----------------------------------------------------------------------\n// TopBar.Right\n// -----------------------------------------------------------------------\n\ninterface TopBarRightProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarRight = React.forwardRef<HTMLDivElement, TopBarRightProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('ml-auto flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarRight.displayName = 'TopBar.Right'\n\n// -----------------------------------------------------------------------\n// TopBar.Section\n// -----------------------------------------------------------------------\n\nconst gapMap = {\n tight: 'gap-ds-02',\n default: 'gap-ds-04',\n loose: 'gap-ds-06',\n} as const\n\ninterface TopBarSectionProps extends React.HTMLAttributes<HTMLDivElement> {\n gap?: keyof typeof gapMap\n children: React.ReactNode\n}\n\nconst TopBarSection = React.forwardRef<HTMLDivElement, TopBarSectionProps>(\n ({ gap = 'default', className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center', gapMap[gap], className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarSection.displayName = 'TopBar.Section'\n\n// -----------------------------------------------------------------------\n// TopBar.IconButton\n// -----------------------------------------------------------------------\n\ninterface TopBarIconButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n icon: IconInput\n tooltip: string\n}\n\nconst TopBarIconButton = React.forwardRef<\n HTMLButtonElement,\n TopBarIconButtonProps\n>(({ icon, tooltip, className, ...props }, ref) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n aria-label={tooltip}\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-surface-border-strong bg-surface-raised-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-raised-active active:scale-90 duration-fast-01 ease-productive-standard',\n className,\n )}\n {...props}\n >\n <span className=\"[&>svg]:h-ico-sm [&>svg]:w-ico-sm\" aria-hidden=\"true\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n))\nTopBarIconButton.displayName = 'TopBar.IconButton'\n\n// -----------------------------------------------------------------------\n// TopBar.Title\n// -----------------------------------------------------------------------\n\ninterface TopBarTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n children: React.ReactNode\n}\n\nconst TopBarTitle = React.forwardRef<HTMLHeadingElement, TopBarTitleProps>(\n ({ className, children, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn(\n 'hidden text-ds-lg text-surface-fg md:block',\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n ),\n)\nTopBarTitle.displayName = 'TopBar.Title'\n\n// -----------------------------------------------------------------------\n// TopBar.UserMenu\n// -----------------------------------------------------------------------\n\ninterface TopBarUserMenuProps {\n user: TopBarUser\n onNavigate?: (path: string) => void\n onLogout?: () => void\n userMenuItems?: UserMenuItem[]\n className?: string\n}\n\nconst TopBarUserMenu = React.forwardRef<HTMLButtonElement, TopBarUserMenuProps>(\n ({ user, onNavigate, onLogout, userMenuItems, className }, ref) => {\n const { colorMode, toggleColorMode } = useColorMode()\n\n return (\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n className={cn('flex items-center gap-ds-03 outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2', className)}\n >\n <Avatar className=\"h-ds-sm-plus w-ds-sm-plus cursor-pointer\">\n {user.image ? (\n <AvatarImage src={user.image} alt={user.name} />\n ) : null}\n <AvatarFallback className=\"bg-surface-raised-hover text-surface-fg\">\n {user.name?.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n User Menu\n </TooltipContent>\n </Tooltip>\n\n <DropdownMenuContent\n className=\"w-[200px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n sideOffset={8}\n align=\"end\"\n >\n {/* User Info */}\n <div className=\"border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <p className=\"text-ds-md text-surface-fg\">{user.name}</p>\n {user.email && (\n <p className=\"text-ds-sm text-surface-fg-subtle truncate\">{user.email}</p>\n )}\n </div>\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={() => onNavigate?.('/profile')}\n >\n <Icon icon={IconUser} size=\"sm\" className=\"text-surface-fg-muted\" />\n <span className=\"text-ds-md text-surface-fg-muted\">Profile</span>\n </DropdownMenuItem>\n\n {/* Custom user menu items */}\n {userMenuItems?.map((item, index) => {\n const colorMap: Record<string, string> = {\n error: 'text-error-11',\n success: 'text-success-11',\n warning: 'text-warning-11',\n info: 'text-info-11',\n }\n const textColor = item.color\n ? (colorMap[item.color] ?? 'text-surface-fg-muted')\n : 'text-surface-fg-muted'\n return (\n <React.Fragment key={item.label + index}>\n {item.separator && (\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n )}\n <DropdownMenuItem\n className={cn(\n 'flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised',\n item.disabled && 'pointer-events-none opacity-action-disabled',\n )}\n disabled={item.disabled}\n onClick={() => {\n if (item.disabled) return\n if (item.onClick) item.onClick()\n else if (item.href) onNavigate?.(item.href)\n }}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm',\n textColor,\n )}\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <span className={cn('text-ds-md', textColor)}>\n {item.label}\n </span>\n {item.badge != null &&\n item.badge !== false &&\n (typeof item.badge === 'string' ? (\n <span className=\"ml-auto inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-pill bg-error-9 px-ds-02 text-[10px] font-semibold leading-none text-error-fg\">\n {item.badge}\n </span>\n ) : (\n <span className=\"ml-auto h-[8px] w-[8px] rounded-pill bg-error-9\" />\n ))}\n </DropdownMenuItem>\n </React.Fragment>\n )\n })}\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={toggleColorMode}\n >\n {colorMode === 'dark' ? (\n <Icon icon={IconSun} size=\"sm\" className=\"text-surface-fg-muted\" />\n ) : (\n <Icon icon={IconMoon} size=\"sm\" className=\"text-surface-fg-muted\" />\n )}\n <span className=\"text-ds-md text-surface-fg-muted\">\n {colorMode === 'dark' ? 'Light Mode' : 'Dark Mode'}\n </span>\n </DropdownMenuItem>\n\n {onLogout && (\n <>\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={onLogout}\n >\n <Icon icon={IconLogout} size=\"sm\" className=\"text-error-11\" />\n <span className=\"text-ds-md text-error-11\">Logout</span>\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n },\n)\nTopBarUserMenu.displayName = 'TopBar.UserMenu'\n\n// -----------------------------------------------------------------------\n// Compound export\n// -----------------------------------------------------------------------\n\nexport type TopBarProps = TopBarRootProps\n\nconst TopBar = Object.assign(TopBarRoot, {\n Left: TopBarLeft,\n Center: TopBarCenter,\n Right: TopBarRight,\n Section: TopBarSection,\n IconButton: TopBarIconButton,\n Title: TopBarTitle,\n UserMenu: TopBarUserMenu,\n})\n\nexport { TopBar }\n"],"mappings":";;;;;;;;;;;;;AAqEA,IAAM,IAAa,EAAM,YACtB,EAAE,cAAW,aAAU,GAAG,KAAS,MAAQ;CAE1C,IAAM,IAAY,EAAM,SAAS,QAAQ,EAAS,CAAC,MAChD,MAAU,EAAM,eAAe,EAAM,IAAI,EAAM,SAAS,EAC1D;AAED,QACE,kBAAC,UAAD;EACE,GAAI;EACC;EACL,WAAW,EACT,yGACA,IACI,+CACA,qBACJ,EACD;EAEA;EACM,CAAA;EAGd;AACD,EAAW,cAAc;AAUzB,IAAM,IAAa,EAAM,YACtB,EAAE,cAAW,aAAU,GAAG,KAAS,MAClC,kBAAC,OAAD;CACO;CACL,WAAW,EAAG,+BAA+B,EAAU;CACvD,GAAI;CAEH;CACG,CAAA,CAET;AACD,EAAW,cAAc;AAUzB,IAAM,IAAe,EAAM,YACxB,EAAE,cAAW,aAAU,GAAG,KAAS,MAClC,kBAAC,OAAD;CACO;CACL,WAAW,EAAG,6CAA6C,EAAU;CACrE,GAAI;CAEH;CACG,CAAA,CAET;AACD,EAAa,cAAc;AAU3B,IAAM,IAAc,EAAM,YACvB,EAAE,cAAW,aAAU,GAAG,KAAS,MAClC,kBAAC,OAAD;CACO;CACL,WAAW,EAAG,uCAAuC,EAAU;CAC/D,GAAI;CAEH;CACG,CAAA,CAET;AACD,EAAY,cAAc;AAM1B,IAAM,IAAS;CACb,OAAO;CACP,SAAS;CACT,OAAO;CACR,EAOK,IAAgB,EAAM,YACzB,EAAE,SAAM,WAAW,cAAW,aAAU,GAAG,KAAS,MACnD,kBAAC,OAAD;CACO;CACL,WAAW,EAAG,qBAAqB,EAAO,IAAM,EAAU;CAC1D,GAAI;CAEH;CACG,CAAA,CAET;AACD,EAAc,cAAc;AAY5B,IAAM,IAAmB,EAAM,YAG5B,EAAE,SAAM,YAAS,cAAW,GAAG,KAAS,MACzC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;CAAgB,SAAA;WACd,kBAAC,UAAD;EACO;EACL,MAAK;EACL,cAAY;EACZ,WAAW,EACT,iTACA,EACD;EACD,GAAI;YAEJ,kBAAC,QAAD;GAAM,WAAU;GAAoC,eAAY;aAC9D,kBAAC,GAAD;IAAc,MAAK;cAAM,EAAc,EAAK;IAAgB,CAAA;GACvD,CAAA;EACA,CAAA;CACM,CAAA,EACjB,kBAAC,GAAD;CAAgB,MAAK;CAAS,OAAM;WACjC;CACc,CAAA,CACT,EAAA,CAAA,CACV;AACF,EAAiB,cAAc;AAU/B,IAAM,IAAc,EAAM,YACvB,EAAE,cAAW,aAAU,GAAG,KAAS,MAClC,kBAAC,MAAD;CACO;CACL,WAAW,EACT,8CACA,EACD;CACD,GAAI;CAEH;CACE,CAAA,CAER;AACD,EAAY,cAAc;AAc1B,IAAM,IAAiB,EAAM,YAC1B,EAAE,SAAM,eAAY,aAAU,kBAAe,gBAAa,MAAQ;CACjE,IAAM,EAAE,cAAW,uBAAoB,GAAc;AAErD,QACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EAAgB,SAAA;YACd,kBAAC,GAAD;GAAqB,SAAA;aACnB,kBAAC,UAAD;IACO;IACL,MAAK;IACL,WAAW,EAAG,2HAA2H,EAAU;cAEnJ,kBAAC,GAAD;KAAQ,WAAU;eAAlB,CACG,EAAK,QACJ,kBAAC,GAAD;MAAa,KAAK,EAAK;MAAO,KAAK,EAAK;MAAQ,CAAA,GAC9C,MACJ,kBAAC,GAAD;MAAgB,WAAU;gBACvB,EAAK,MAAM,OAAO,EAAE,CAAC,aAAa;MACpB,CAAA,CACV;;IACF,CAAA;GACW,CAAA;EACP,CAAA,EACjB,kBAAC,GAAD;EAAgB,MAAK;EAAS,OAAM;YAAS;EAE5B,CAAA,CACT,EAAA,CAAA,EAEV,kBAAC,GAAD;EACE,WAAU;EACV,YAAY;EACZ,OAAM;YAHR;GAME,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAA8B,EAAK;KAAS,CAAA,EACxD,EAAK,SACJ,kBAAC,KAAD;KAAG,WAAU;eAA8C,EAAK;KAAU,CAAA,CAExE;;GAEN,kBAAC,GAAD;IACE,WAAU;IACV,eAAe,IAAa,WAAW;cAFzC,CAIE,kBAAC,GAAD;KAAM,MAAM;KAAU,MAAK;KAAK,WAAU;KAA0B,CAAA,EACpE,kBAAC,QAAD;KAAM,WAAU;eAAmC;KAAc,CAAA,CAChD;;GAGlB,GAAe,KAAK,GAAM,MAAU;IAOnC,IAAM,IAAY,EAAK,QANkB;KACvC,OAAO;KACP,SAAS;KACT,SAAS;KACT,MAAM;KACP,CAEa,EAAK,UAAU,0BACzB;AACJ,WACE,kBAAC,EAAM,UAAP,EAAA,UAAA,CACG,EAAK,aACJ,kBAAC,GAAD,EAAuB,WAAU,qBAAsB,CAAA,EAEzD,kBAAC,GAAD;KACE,WAAW,EACT,+FACA,EAAK,YAAY,8CAClB;KACD,UAAU,EAAK;KACf,eAAe;AACT,QAAK,aACL,EAAK,UAAS,EAAK,SAAS,GACvB,EAAK,QAAM,IAAa,EAAK,KAAK;;eAT/C;MAYG,EAAK,QACJ,kBAAC,QAAD;OACE,WAAW,EACT,qCACA,EACD;iBAED,kBAAC,GAAD;QAAc,MAAK;kBAAM,EAAc,EAAK,KAAK;QAAgB,CAAA;OAC5D,CAAA;MAET,kBAAC,QAAD;OAAM,WAAW,EAAG,cAAc,EAAU;iBACzC,EAAK;OACD,CAAA;MACN,EAAK,SAAS,QACb,EAAK,UAAU,OACd,OAAO,EAAK,SAAU,WACrB,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAK;OACD,CAAA,GAEP,kBAAC,QAAD,EAAM,WAAU,mDAAoD,CAAA;MAEvD;OACJ,EAAA,EAvCI,EAAK,QAAQ,EAuCjB;KAEnB;GAEF,kBAAC,GAAD;IACE,WAAU;IACV,SAAS;cAFX,CAIG,MAAc,SACb,kBAAC,GAAD;KAAM,MAAM;KAAS,MAAK;KAAK,WAAU;KAA0B,CAAA,GAEnE,kBAAC,GAAD;KAAM,MAAM;KAAU,MAAK;KAAK,WAAU;KAA0B,CAAA,EAEtE,kBAAC,QAAD;KAAM,WAAU;eACb,MAAc,SAAS,eAAe;KAClC,CAAA,CACU;;GAElB,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAuB,WAAU,qBAAsB,CAAA,EACvD,kBAAC,GAAD;IACE,WAAU;IACV,SAAS;cAFX,CAIE,kBAAC,GAAD;KAAM,MAAM;KAAY,MAAK;KAAK,WAAU;KAAkB,CAAA,EAC9D,kBAAC,QAAD;KAAM,WAAU;eAA2B;KAAa,CAAA,CACvC;MAClB,EAAA,CAAA;GAEe;IACT,EAAA,CAAA;EAGpB;AACD,EAAe,cAAc;AAQ7B,IAAM,IAAS,OAAO,OAAO,GAAY;CACvC,MAAM;CACN,QAAQ;CACR,OAAO;CACP,SAAS;CACT,YAAY;CACZ,OAAO;CACP,UAAU;CACX,CAAC"}
|
|
1
|
+
{"version":3,"file":"top-bar.js","names":[],"sources":["../../src/shell/top-bar.tsx"],"sourcesContent":["'use client'\n\n/**\n * TopBar v2 — Composition-based application top bar.\n *\n * Subcomponents: TopBar.Left, TopBar.Center, TopBar.Right,\n * TopBar.Section, TopBar.IconButton, TopBar.Title, TopBar.UserMenu.\n */\nimport { IconLogout, IconMoon, IconSun,IconUser } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { useColorMode } from '../hooks/use-color-mode'\nimport { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '../ui/tooltip'\nimport { TruncatedText } from '../ui/truncated-text'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface TopBarUser {\n name: string\n email?: string\n image?: string | null\n}\n\nexport interface UserMenuItem {\n /** Display label */\n label: string\n /** Optional icon. Accepts any `IconInput`. */\n icon?: IconInput\n /** Navigate via onNavigate when clicked */\n href?: string\n /** Custom click handler */\n onClick?: () => void\n /** Render a separator before this item */\n separator?: boolean\n /** Text color semantic token (e.g. \"error\") — maps to text-{color} */\n color?: string\n /** Badge content — string for count, true for dot indicator */\n badge?: string | boolean\n /** Whether the item is disabled */\n disabled?: boolean\n}\n\n// -----------------------------------------------------------------------\n// TopBar (root)\n// -----------------------------------------------------------------------\n\ninterface TopBarRootProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n className?: string\n}\n\nconst TopBarRoot = React.forwardRef<HTMLElement, TopBarRootProps>(\n ({ className, children, ...props }, ref) => {\n // Detect if a Center zone is present to switch to grid layout\n const hasCenter = React.Children.toArray(children).some(\n (child) => React.isValidElement(child) && child.type === TopBarCenter,\n )\n\n return (\n <header\n {...props}\n ref={ref}\n className={cn(\n 'z-sticky w-full border-b border-surface-border-strong bg-surface-raised px-ds-05 py-ds-04 md:px-ds-06',\n hasCenter\n ? 'grid grid-cols-[1fr_auto_1fr] items-center'\n : 'flex items-center',\n className,\n )}\n >\n {children}\n </header>\n )\n },\n)\nTopBarRoot.displayName = 'TopBar'\n\n// -----------------------------------------------------------------------\n// TopBar.Left\n// -----------------------------------------------------------------------\n\ninterface TopBarLeftProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarLeft = React.forwardRef<HTMLDivElement, TopBarLeftProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarLeft.displayName = 'TopBar.Left'\n\n// -----------------------------------------------------------------------\n// TopBar.Center\n// -----------------------------------------------------------------------\n\ninterface TopBarCenterProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarCenter = React.forwardRef<HTMLDivElement, TopBarCenterProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center justify-center px-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarCenter.displayName = 'TopBar.Center'\n\n// -----------------------------------------------------------------------\n// TopBar.Right\n// -----------------------------------------------------------------------\n\ninterface TopBarRightProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarRight = React.forwardRef<HTMLDivElement, TopBarRightProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('ml-auto flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarRight.displayName = 'TopBar.Right'\n\n// -----------------------------------------------------------------------\n// TopBar.Section\n// -----------------------------------------------------------------------\n\nconst gapMap = {\n tight: 'gap-ds-02',\n default: 'gap-ds-04',\n loose: 'gap-ds-06',\n} as const\n\ninterface TopBarSectionProps extends React.HTMLAttributes<HTMLDivElement> {\n gap?: keyof typeof gapMap\n children: React.ReactNode\n}\n\nconst TopBarSection = React.forwardRef<HTMLDivElement, TopBarSectionProps>(\n ({ gap = 'default', className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center', gapMap[gap], className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarSection.displayName = 'TopBar.Section'\n\n// -----------------------------------------------------------------------\n// TopBar.IconButton\n// -----------------------------------------------------------------------\n\ninterface TopBarIconButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n icon: IconInput\n tooltip: string\n}\n\nconst TopBarIconButton = React.forwardRef<\n HTMLButtonElement,\n TopBarIconButtonProps\n>(({ icon, tooltip, className, ...props }, ref) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n aria-label={tooltip}\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-surface-border-strong bg-surface-raised-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-raised-active active:scale-90 duration-fast-01 ease-productive-standard',\n className,\n )}\n {...props}\n >\n <span className=\"[&>svg]:h-ico-sm [&>svg]:w-ico-sm\" aria-hidden=\"true\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n))\nTopBarIconButton.displayName = 'TopBar.IconButton'\n\n// -----------------------------------------------------------------------\n// TopBar.Title\n// -----------------------------------------------------------------------\n\ninterface TopBarTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n children: React.ReactNode\n}\n\nconst TopBarTitle = React.forwardRef<HTMLHeadingElement, TopBarTitleProps>(\n ({ className, children, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn(\n 'hidden text-ds-lg text-surface-fg md:block',\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n ),\n)\nTopBarTitle.displayName = 'TopBar.Title'\n\n// -----------------------------------------------------------------------\n// TopBar.UserMenu\n// -----------------------------------------------------------------------\n\ninterface TopBarUserMenuProps {\n user: TopBarUser\n onNavigate?: (path: string) => void\n onLogout?: () => void\n userMenuItems?: UserMenuItem[]\n className?: string\n}\n\nconst TopBarUserMenu = React.forwardRef<HTMLButtonElement, TopBarUserMenuProps>(\n ({ user, onNavigate, onLogout, userMenuItems, className }, ref) => {\n const { colorMode, toggleColorMode } = useColorMode()\n\n return (\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n className={cn('flex items-center gap-ds-03 outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2', className)}\n >\n <Avatar className=\"h-ds-sm-plus w-ds-sm-plus cursor-pointer\">\n {user.image ? (\n <AvatarImage src={user.image} alt={user.name} />\n ) : null}\n <AvatarFallback className=\"bg-surface-raised-hover text-surface-fg\">\n {user.name?.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n User Menu\n </TooltipContent>\n </Tooltip>\n\n <DropdownMenuContent\n className=\"w-[200px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n sideOffset={8}\n align=\"end\"\n >\n {/* User Info */}\n <div className=\"border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <p className=\"text-ds-md text-surface-fg\">{user.name}</p>\n {user.email && (\n <TruncatedText as=\"p\" mode=\"middle\" className=\"text-ds-sm text-surface-fg-subtle\">\n {user.email}\n </TruncatedText>\n )}\n </div>\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={() => onNavigate?.('/profile')}\n >\n <Icon icon={IconUser} size=\"sm\" className=\"text-surface-fg-muted\" />\n <span className=\"text-ds-md text-surface-fg-muted\">Profile</span>\n </DropdownMenuItem>\n\n {/* Custom user menu items */}\n {userMenuItems?.map((item, index) => {\n const colorMap: Record<string, string> = {\n error: 'text-error-11',\n success: 'text-success-11',\n warning: 'text-warning-11',\n info: 'text-info-11',\n }\n const textColor = item.color\n ? (colorMap[item.color] ?? 'text-surface-fg-muted')\n : 'text-surface-fg-muted'\n return (\n <React.Fragment key={item.label + index}>\n {item.separator && (\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n )}\n <DropdownMenuItem\n className={cn(\n 'flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised',\n item.disabled && 'pointer-events-none opacity-action-disabled',\n )}\n disabled={item.disabled}\n onClick={() => {\n if (item.disabled) return\n if (item.onClick) item.onClick()\n else if (item.href) onNavigate?.(item.href)\n }}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm',\n textColor,\n )}\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <span className={cn('text-ds-md', textColor)}>\n {item.label}\n </span>\n {item.badge != null &&\n item.badge !== false &&\n (typeof item.badge === 'string' ? (\n <span className=\"ml-auto inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-pill bg-error-9 px-ds-02 text-[10px] font-semibold leading-none text-error-fg\">\n {item.badge}\n </span>\n ) : (\n <span className=\"ml-auto h-[8px] w-[8px] rounded-pill bg-error-9\" />\n ))}\n </DropdownMenuItem>\n </React.Fragment>\n )\n })}\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={toggleColorMode}\n >\n {colorMode === 'dark' ? (\n <Icon icon={IconSun} size=\"sm\" className=\"text-surface-fg-muted\" />\n ) : (\n <Icon icon={IconMoon} size=\"sm\" className=\"text-surface-fg-muted\" />\n )}\n <span className=\"text-ds-md text-surface-fg-muted\">\n {colorMode === 'dark' ? 'Light Mode' : 'Dark Mode'}\n </span>\n </DropdownMenuItem>\n\n {onLogout && (\n <>\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={onLogout}\n >\n <Icon icon={IconLogout} size=\"sm\" className=\"text-error-11\" />\n <span className=\"text-ds-md text-error-11\">Logout</span>\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n },\n)\nTopBarUserMenu.displayName = 'TopBar.UserMenu'\n\n// -----------------------------------------------------------------------\n// Compound export\n// -----------------------------------------------------------------------\n\nexport type TopBarProps = TopBarRootProps\n\nconst TopBar = Object.assign(TopBarRoot, {\n Left: TopBarLeft,\n Center: TopBarCenter,\n Right: TopBarRight,\n Section: TopBarSection,\n IconButton: TopBarIconButton,\n Title: TopBarTitle,\n UserMenu: TopBarUserMenu,\n})\n\nexport { TopBar }\n"],"mappings":"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"}
|
package/dist/tokens/semantic.css
CHANGED
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
TW4 namespace: --text-* → text-* utility.
|
|
68
68
|
We use the `ds-` prefix to avoid collision with consumer's own
|
|
69
69
|
text sizes (TW4 default supplies text-xs, text-sm, etc.). */
|
|
70
|
+
--text-ds-2xs: 0.5625rem; /* 9px — micro labels (avatar xs, corner pills); below xs */
|
|
70
71
|
--text-ds-xs: 0.625rem; /* 10px */
|
|
71
72
|
--text-ds-sm: 0.75rem; /* 12px */
|
|
72
73
|
--text-ds-md: 0.875rem; /* 14px */
|
package/dist/ui/avatar.js
CHANGED