@humain/ui 2.1.63 → 2.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/dist/components/organisms/ai/AIToolCall/AIToolCall.d.ts +9 -3
  2. package/dist/components/organisms/ai/AIToolRun/index.d.ts +1 -1
  3. package/dist/components/organisms/ai/AIToolRun/validation.d.ts +24 -3
  4. package/dist/components/organisms/ai/_shared/format-ai-duration.d.ts +1 -0
  5. package/dist/components/organisms/ai/_shared/workflow-step-renderer.d.ts +1 -0
  6. package/dist/index.js +52 -52
  7. package/dist/index151.js +1 -1
  8. package/dist/index174.js +7 -339
  9. package/dist/index174.js.map +1 -1
  10. package/dist/index175.js +310 -137
  11. package/dist/index175.js.map +1 -1
  12. package/dist/index176.js +148 -174
  13. package/dist/index176.js.map +1 -1
  14. package/dist/index177.js +186 -78
  15. package/dist/index177.js.map +1 -1
  16. package/dist/index178.js +74 -124
  17. package/dist/index178.js.map +1 -1
  18. package/dist/index179.js +133 -1
  19. package/dist/index179.js.map +1 -0
  20. package/dist/index180.js +2 -201
  21. package/dist/index181.js +201 -0
  22. package/dist/{index180.js.map → index181.js.map} +1 -1
  23. package/dist/index183.js +130 -166
  24. package/dist/index183.js.map +1 -1
  25. package/dist/index184.js +195 -983
  26. package/dist/index184.js.map +1 -1
  27. package/dist/index185.js +1069 -369
  28. package/dist/index185.js.map +1 -1
  29. package/dist/index186.js +395 -197
  30. package/dist/index186.js.map +1 -1
  31. package/dist/index187.js +198 -243
  32. package/dist/index187.js.map +1 -1
  33. package/dist/index188.js +263 -3
  34. package/dist/index188.js.map +1 -1
  35. package/dist/index189.js +3 -209
  36. package/dist/index189.js.map +1 -1
  37. package/dist/index190.js +190 -777
  38. package/dist/index190.js.map +1 -1
  39. package/dist/index191.js +771 -252
  40. package/dist/index191.js.map +1 -1
  41. package/dist/index192.js +250 -65
  42. package/dist/index192.js.map +1 -1
  43. package/dist/index193.js +72 -523
  44. package/dist/index193.js.map +1 -1
  45. package/dist/index194.js +537 -144
  46. package/dist/index194.js.map +1 -1
  47. package/dist/index195.js +139 -720
  48. package/dist/index195.js.map +1 -1
  49. package/dist/index196.js +707 -167
  50. package/dist/index196.js.map +1 -1
  51. package/dist/index197.js +175 -151
  52. package/dist/index197.js.map +1 -1
  53. package/dist/index198.js +152 -487
  54. package/dist/index198.js.map +1 -1
  55. package/dist/index199.js +472 -225
  56. package/dist/index199.js.map +1 -1
  57. package/dist/index200.js +236 -260
  58. package/dist/index200.js.map +1 -1
  59. package/dist/index201.js +265 -215
  60. package/dist/index201.js.map +1 -1
  61. package/dist/index202.js +207 -307
  62. package/dist/index202.js.map +1 -1
  63. package/dist/index203.js +302 -135
  64. package/dist/index203.js.map +1 -1
  65. package/dist/index204.js +140 -271
  66. package/dist/index204.js.map +1 -1
  67. package/dist/index205.js +263 -253
  68. package/dist/index205.js.map +1 -1
  69. package/dist/index206.js +244 -137
  70. package/dist/index206.js.map +1 -1
  71. package/dist/index207.js +100 -238
  72. package/dist/index207.js.map +1 -1
  73. package/dist/index208.js +278 -74
  74. package/dist/index208.js.map +1 -1
  75. package/dist/index209.js +56 -97
  76. package/dist/index209.js.map +1 -1
  77. package/dist/index210.js +142 -47
  78. package/dist/index210.js.map +1 -1
  79. package/dist/index211.js +38 -84
  80. package/dist/index211.js.map +1 -1
  81. package/dist/index212.js +72 -252
  82. package/dist/index212.js.map +1 -1
  83. package/dist/index213.js +274 -26
  84. package/dist/index213.js.map +1 -1
  85. package/dist/index214.js +29 -94
  86. package/dist/index214.js.map +1 -1
  87. package/dist/index215.js +98 -25
  88. package/dist/index215.js.map +1 -1
  89. package/dist/index216.js +20 -565
  90. package/dist/index216.js.map +1 -1
  91. package/dist/index217.js +564 -17
  92. package/dist/index217.js.map +1 -1
  93. package/dist/index218.js +20 -23
  94. package/dist/index218.js.map +1 -1
  95. package/dist/index219.js +20 -95
  96. package/dist/index219.js.map +1 -1
  97. package/dist/index220.js +92 -88
  98. package/dist/index220.js.map +1 -1
  99. package/dist/index221.js +97 -29
  100. package/dist/index221.js.map +1 -1
  101. package/dist/index222.js +24 -470
  102. package/dist/index222.js.map +1 -1
  103. package/dist/index223.js +446 -196
  104. package/dist/index223.js.map +1 -1
  105. package/dist/index224.js +199 -729
  106. package/dist/index224.js.map +1 -1
  107. package/dist/index225.js +750 -61
  108. package/dist/index225.js.map +1 -1
  109. package/dist/index226.js +58 -181
  110. package/dist/index226.js.map +1 -1
  111. package/dist/index227.js +175 -259
  112. package/dist/index227.js.map +1 -1
  113. package/dist/index228.js +246 -172
  114. package/dist/index228.js.map +1 -1
  115. package/dist/index229.js +195 -32
  116. package/dist/index229.js.map +1 -1
  117. package/dist/index230.js +12 -40
  118. package/dist/index230.js.map +1 -1
  119. package/dist/index231.js +23 -26
  120. package/dist/index231.js.map +1 -1
  121. package/dist/index232.js +45 -22
  122. package/dist/index232.js.map +1 -1
  123. package/dist/index233.js +27 -48
  124. package/dist/index233.js.map +1 -1
  125. package/dist/index234.js +52 -26
  126. package/dist/index234.js.map +1 -1
  127. package/dist/index235.js +40 -225
  128. package/dist/index235.js.map +1 -1
  129. package/dist/index236.js +217 -39
  130. package/dist/index236.js.map +1 -1
  131. package/dist/index237.js +50 -0
  132. package/dist/index237.js.map +1 -0
  133. package/dist/styles.css +1 -1
  134. package/dist/wc/AIToolCall.js +218 -0
  135. package/dist/wc/AIToolCall.js.map +1 -0
  136. package/dist/wc/hf-ai-tool-call.js +34 -219
  137. package/dist/wc/hf-ai-tool-call.js.map +1 -1
  138. package/dist/wc/hf-ai-tool-run.js +673 -576
  139. package/dist/wc/hf-ai-tool-run.js.map +1 -1
  140. package/dist/wc/workflow-step-renderer.js +79 -78
  141. package/dist/wc/workflow-step-renderer.js.map +1 -1
  142. package/dist/wc-react/AIToolCall.js +218 -0
  143. package/dist/wc-react/AIToolCall.js.map +1 -0
  144. package/dist/wc-react/hf-ai-tool-call.js +32 -217
  145. package/dist/wc-react/hf-ai-tool-call.js.map +1 -1
  146. package/dist/wc-react/hf-ai-tool-run.js +698 -601
  147. package/dist/wc-react/hf-ai-tool-run.js.map +1 -1
  148. package/dist/wc-react/workflow-step-renderer.js +58 -57
  149. package/dist/wc-react/workflow-step-renderer.js.map +1 -1
  150. package/package.json +1 -1
  151. package/skills/humain-ui/SKILL.md +1 -1
  152. package/skills/humain-ui-wc/SKILL.md +1 -1
  153. package/skills/humain-ui-wc.skill +0 -0
  154. package/skills/humain-ui.skill +0 -0
  155. package/dist/index182.js +0 -143
  156. package/dist/index182.js.map +0 -1
  157. package/dist/wc/wrench.js +0 -10
  158. package/dist/wc/wrench.js.map +0 -1
  159. package/dist/wc-react/wrench.js +0 -10
  160. package/dist/wc-react/wrench.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index203.js","names":[],"sources":["../src/components/organisms/layout/SectionHeader/SectionHeader.tsx"],"sourcesContent":["'use client';\n\nimport { Search } from 'lucide-react';\nimport * as React from 'react';\nimport { Button, type ButtonProps } from '@/components/atoms/buttons/Button';\nimport { ButtonGroup } from '@/components/atoms/buttons/ButtonGroup';\nimport { Input, type InputProps } from '@/components/atoms/forms/Input';\nimport { Separator } from '@/components/atoms/layout/Separator';\nimport { Tabs } from '@/components/molecules/navigation/Tabs';\nimport { cn } from '@/lib/utils';\n\nexport type SectionHeaderSize = 'sm' | 'md';\nexport type SectionHeaderHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\ntype SectionHeaderHeadingTag = `h${SectionHeaderHeadingLevel}`;\n\nexport interface SectionHeaderAction\n extends Omit<ButtonProps, 'children' | 'render'> {\n label: React.ReactNode;\n}\n\nexport interface SectionHeaderTab {\n label: React.ReactNode;\n value?: string;\n active?: boolean;\n leadingIcon?: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n}\n\nexport interface SectionHeaderSearchProps\n extends Omit<\n InputProps,\n 'size' | 'shape' | 'startIcon' | 'endIcon' | 'appearance'\n > {\n placeholder?: string;\n ariaLabel?: string;\n /** Optional interactive filter control rendered beside the search input */\n filterButton?: React.ReactNode;\n}\n\nexport interface SectionHeaderProps\n extends Omit<React.ComponentPropsWithoutRef<'header'>, 'title'> {\n /** Section title */\n title: React.ReactNode;\n /** Supporting text below the title */\n supportingText?: React.ReactNode;\n /** Heading/text size from the Figma variants */\n size?: SectionHeaderSize;\n /** Semantic heading level for the section title */\n headingLevel?: SectionHeaderHeadingLevel;\n /** Action buttons rendered to the right of the title block */\n actions?: SectionHeaderAction[];\n /** Optional grouped actions rendered as a segmented control */\n buttonGroup?: SectionHeaderAction[];\n /** Optional search input rendered to the right of the title block */\n search?: SectionHeaderSearchProps;\n /** Optional tabs row rendered below the header controls */\n tabs?: SectionHeaderTab[];\n /** Trailing menu control rendered after the action buttons */\n menuButton?: React.ReactNode;\n /** Show the bottom divider */\n showDivider?: boolean;\n}\n\ntype SectionHeaderControlProps = Pick<\n SectionHeaderProps,\n 'actions' | 'buttonGroup' | 'search'\n>;\n\nconst controlTouchTargetClassName = 'min-h-11 min-w-11 shrink-0';\n\nfunction getHeadingTag(\n headingLevel: SectionHeaderHeadingLevel,\n): SectionHeaderHeadingTag {\n return `h${headingLevel}` as SectionHeaderHeadingTag;\n}\n\nfunction SectionHeaderTouchTargetControl({\n control,\n}: {\n control: React.ReactNode;\n}): React.ReactNode {\n if (React.isValidElement<{ className?: string }>(control)) {\n return React.cloneElement(control, {\n className: cn(control.props.className, controlTouchTargetClassName),\n });\n }\n\n return (\n <span\n className={cn(\n 'inline-flex items-center justify-center',\n controlTouchTargetClassName,\n )}\n >\n {control}\n </span>\n );\n}\n\nfunction getSectionHeaderActionKey(\n action: SectionHeaderAction,\n index: number,\n prefix = 'section-header-action',\n): React.Key {\n return typeof action.label === 'string'\n ? `${action.label}-${index}`\n : `${prefix}-${index}`;\n}\n\nfunction SectionHeaderActionButton({\n action,\n className,\n}: {\n action: SectionHeaderAction;\n className?: string;\n}): React.JSX.Element {\n const { label, className: actionClassName, ...buttonProps } = action;\n\n return (\n <Button\n appearance=\"solid\"\n size=\"default\"\n shape=\"rounded\"\n className={cn(\n 'h-10 rounded-xl px-2 text-xs font-medium',\n actionClassName,\n className,\n )}\n {...buttonProps}\n >\n {label}\n </Button>\n );\n}\n\nfunction SectionHeaderButtonGroup({\n actions,\n}: {\n actions: SectionHeaderAction[];\n}): React.JSX.Element {\n return (\n <ButtonGroup\n aria-label=\"Section header controls\"\n shape=\"rounded\"\n className=\"overflow-hidden rounded-xl\"\n >\n {actions.map((action, index) => {\n const { label, className, ...buttonProps } = action;\n\n return (\n <Button\n key={getSectionHeaderActionKey(\n action,\n index,\n 'section-header-group-action',\n )}\n appearance={\n (buttonProps.appearance as ButtonProps['appearance']) ?? 'soft'\n }\n variant={\n (buttonProps.variant as ButtonProps['variant']) ?? 'primary'\n }\n size=\"md\"\n shape=\"rounded\"\n className={cn(\n 'border-transparent px-3 text-xs font-medium shadow-none',\n className,\n )}\n {...buttonProps}\n >\n {label}\n </Button>\n );\n })}\n </ButtonGroup>\n );\n}\n\nfunction getTabValue(tab: SectionHeaderTab, index: number): string {\n if (tab.value !== undefined) {\n return tab.value;\n }\n\n if (typeof tab.label === 'string') {\n return `${tab.label}-${index}`;\n }\n\n return `section-header-tab-${index}`;\n}\n\nfunction SectionHeaderTabs({\n tabs,\n}: {\n tabs: SectionHeaderTab[];\n}): React.JSX.Element {\n const tabValues = tabs.map((tab, index) => getTabValue(tab, index));\n const tabListKey = JSON.stringify(tabValues);\n const activeIndex = tabs.findIndex((tab) => tab.active);\n const activeValue = activeIndex >= 0 ? tabValues[activeIndex] : undefined;\n\n return (\n <Tabs\n key={tabListKey}\n value={activeValue}\n defaultValue={activeValue ?? tabValues[0]}\n className=\"w-full\"\n >\n <Tabs.List\n variant=\"boxed\"\n size=\"sm\"\n align=\"stretch\"\n aria-label=\"Section header tabs\"\n className=\"w-full overflow-x-auto overflow-y-hidden rounded-[8px] border border-border bg-card p-1 shadow-sm\"\n >\n {tabs.map((tab, index) => {\n const value = tabValues[index];\n return (\n <Tabs.Trigger\n key={value}\n value={value}\n icon={tab.leadingIcon}\n className=\"min-w-max flex-1 rounded-[10px] px-3 py-1\"\n onClick={tab.onClick}\n >\n <span className=\"whitespace-nowrap\">{tab.label}</span>\n </Tabs.Trigger>\n );\n })}\n </Tabs.List>\n </Tabs>\n );\n}\n\nfunction SectionHeaderControls({\n actions,\n buttonGroup,\n search,\n}: SectionHeaderControlProps): React.JSX.Element {\n return (\n <React.Fragment>\n {search ? <SectionHeaderSearchField search={search} /> : null}\n {buttonGroup?.length ? (\n <SectionHeaderButtonGroup actions={buttonGroup} />\n ) : null}\n {actions?.length ? (\n <div className=\"flex flex-wrap items-center gap-3 md:flex-nowrap\">\n {actions.map((action, index) => (\n <SectionHeaderActionButton\n key={getSectionHeaderActionKey(action, index)}\n action={action}\n />\n ))}\n </div>\n ) : null}\n </React.Fragment>\n );\n}\n\nfunction SectionHeaderSearchField({\n search,\n}: {\n search: SectionHeaderSearchProps;\n}): React.JSX.Element {\n const {\n className: searchClassName,\n placeholder,\n ariaLabel,\n filterButton,\n ...searchProps\n } = search;\n const searchInput = (\n <Input\n size=\"md\"\n shape=\"rounded\"\n aria-label={ariaLabel ?? 'Search'}\n placeholder={placeholder ?? 'Search'}\n startIcon={<Search className=\"size-4\" />}\n className={cn(\n filterButton ? 'min-w-0 flex-1' : 'w-full max-w-[320px]',\n searchClassName,\n )}\n {...searchProps}\n />\n );\n\n if (filterButton) {\n return (\n <div\n data-slot=\"section-header-search\"\n className=\"flex w-full max-w-[376px] items-center gap-2\"\n >\n {searchInput}\n <SectionHeaderTouchTargetControl control={filterButton} />\n </div>\n );\n }\n\n return searchInput;\n}\n\nconst SectionHeader = React.forwardRef<HTMLElement, SectionHeaderProps>(\n (\n {\n title,\n supportingText,\n size = 'md',\n headingLevel = 2,\n actions,\n buttonGroup,\n search,\n tabs,\n menuButton = null,\n showDivider = true,\n className,\n ...props\n },\n ref,\n ) => {\n const hasSearch = Boolean(search);\n const hasButtonGroup = Boolean(buttonGroup?.length);\n const hasActions = Boolean(actions?.length);\n const hasInlineControls = hasSearch || hasButtonGroup || hasActions;\n const hasHeaderControls = hasInlineControls || Boolean(menuButton);\n const HeadingTag = getHeadingTag(headingLevel);\n\n return (\n <header\n ref={ref}\n data-slot=\"section-header\"\n className={cn('relative flex w-full flex-col gap-4', className)}\n {...props}\n >\n <div className=\"grid w-full grid-cols-[minmax(0,1fr)_auto] items-start gap-x-4 gap-y-3\">\n <div\n className={cn(\n 'col-start-1 row-start-1 flex min-w-0 flex-col justify-center gap-0.5',\n menuButton ? 'pe-8 md:pe-0' : null,\n )}\n >\n <HeadingTag\n className={cn(\n 'line-clamp-2 w-full break-words font-semibold text-foreground',\n size === 'sm'\n ? 'text-[14px] leading-5'\n : 'text-[18px] leading-7',\n )}\n >\n {title}\n </HeadingTag>\n {supportingText ? (\n <p className=\"line-clamp-2 w-full break-words text-sm leading-5 text-secondary-foreground\">\n {supportingText}\n </p>\n ) : null}\n </div>\n\n {hasHeaderControls ? (\n <div\n className={cn(\n 'col-span-2 row-start-2 flex flex-wrap items-center gap-3 md:col-span-1 md:col-start-2 md:row-start-1 md:flex-nowrap md:justify-end',\n !hasInlineControls && 'contents md:flex',\n )}\n >\n <SectionHeaderControls\n actions={actions}\n buttonGroup={buttonGroup}\n search={search}\n />\n {menuButton ? (\n <div className=\"absolute end-0 top-0 md:static\">\n <SectionHeaderTouchTargetControl control={menuButton} />\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {tabs?.length ? <SectionHeaderTabs tabs={tabs} /> : null}\n\n {showDivider ? <Separator aria-hidden=\"true\" /> : null}\n </header>\n );\n },\n);\n\nSectionHeader.displayName = 'SectionHeader';\n\nexport { SectionHeader };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index203.js","names":[],"sources":["../src/components/organisms/layout/PageHeader/PageHeader.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { ArrowLeft, MoreHorizontal, Search } from 'lucide-react';\nimport * as React from 'react';\nimport { Button, type ButtonProps } from '@/components/atoms/buttons/Button';\nimport { Separator } from '@/components/atoms/layout/Separator';\nimport { Avatar, type AvatarProps } from '@/components/molecules/data/Avatar';\nimport { Kbd } from '@/components/molecules/data/Kbd';\nimport {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbHomeLink,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from '@/components/molecules/navigation/Breadcrumb';\nimport {\n DropdownMenu,\n type DropdownMenuItemProps,\n} from '@/components/organisms/menus/DropdownMenu';\nimport { cn } from '@/lib/utils';\n\n/* -----------------------------------------------------------------------------\n * Types\n * -------------------------------------------------------------------------- */\n\nexport interface BreadcrumbItemType {\n /** Display label for the breadcrumb */\n label: string;\n /** URL for the breadcrumb link */\n href?: string;\n /** Whether this is the current/active page */\n isCurrent?: boolean;\n}\n\nexport type PageHeaderActionButtonProps = Omit<\n ButtonProps,\n 'variant' | 'onClick' | 'children'\n>;\n\nexport type PageHeaderOverflowActionProps = Pick<\n DropdownMenuItemProps,\n | 'aria-describedby'\n | 'aria-label'\n | 'className'\n | 'disabled'\n | 'icon'\n | 'id'\n | 'title'\n> &\n Partial<Record<`data-${string}`, unknown>>;\n\nexport interface PageHeaderAction {\n /** Button label */\n label: string;\n /** Button variant */\n variant?: ButtonProps['variant'];\n /** Click handler */\n onClick?: () => void;\n /**\n * Additional props applied only when the action renders as a visible Button.\n * Use overflowProps for actions that move into the More actions menu.\n */\n buttonProps?: PageHeaderActionButtonProps;\n /**\n * Additional props applied only when the action renders as an overflow menu item.\n * Menu icons are intentionally explicit so button endIcon values do not become\n * misleading leading menu icons.\n */\n overflowProps?: PageHeaderOverflowActionProps;\n}\n\n/* -----------------------------------------------------------------------------\n * Variants\n * -------------------------------------------------------------------------- */\n\nconst pageHeaderVariants = cva('flex flex-col w-full', {\n variants: {\n variant: {\n simple: 'gap-5',\n avatar: 'gap-5',\n 'banner-avatar': 'gap-0',\n 'banner-simple': 'gap-0',\n 'banner-avatar-centered': 'gap-0',\n 'banner-simple-centered': 'gap-0',\n },\n },\n defaultVariants: {\n variant: 'simple',\n },\n});\n\nconst contentVariants = cva('flex flex-wrap items-start w-full', {\n variants: {\n variant: {\n simple: 'gap-4',\n avatar: 'gap-4 md:gap-5',\n 'banner-avatar': 'gap-4 md:gap-6',\n 'banner-simple': 'gap-4 md:gap-6',\n 'banner-avatar-centered':\n 'flex-col items-center text-center gap-4 md:gap-6',\n 'banner-simple-centered':\n 'flex-col items-center text-center gap-4 md:gap-6',\n },\n },\n defaultVariants: {\n variant: 'simple',\n },\n});\n\nconst bannerVariants = cva(\n 'relative w-full overflow-hidden bg-gradient-to-br from-secondary to-muted',\n {\n variants: {\n variant: {\n default: 'h-40 md:h-60', // 160px mobile, 240px desktop\n centered: 'h-40 md:h-60',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nconst MAX_VISIBLE_HEADER_ACTIONS = 2;\n\ntype IndexedPageHeaderAction = PageHeaderAction & {\n originalIndex: number;\n};\n\nfunction getPageHeaderActionVariant(\n action: PageHeaderAction,\n index: number,\n actionCount: number,\n): ButtonProps['variant'] {\n return (\n action.variant ?? (index === actionCount - 1 ? 'primary' : 'secondary')\n );\n}\n\nfunction isPriorityHeaderAction(\n action: IndexedPageHeaderAction,\n actionCount: number,\n): boolean {\n return (\n getPageHeaderActionVariant(action, action.originalIndex, actionCount) ===\n 'primary'\n );\n}\n\nfunction splitPageHeaderActions(actions: PageHeaderAction[]): {\n visibleActions: IndexedPageHeaderAction[];\n overflowActions: IndexedPageHeaderAction[];\n} {\n const indexedActions = actions.map((action, originalIndex) => ({\n ...action,\n originalIndex,\n }));\n\n if (indexedActions.length <= MAX_VISIBLE_HEADER_ACTIONS) {\n return {\n visibleActions: indexedActions,\n overflowActions: [],\n };\n }\n\n const defaultVisibleActions = indexedActions.slice(\n 0,\n MAX_VISIBLE_HEADER_ACTIONS,\n );\n\n if (\n defaultVisibleActions.some((action) =>\n isPriorityHeaderAction(action, indexedActions.length),\n )\n ) {\n return {\n visibleActions: defaultVisibleActions,\n overflowActions: indexedActions.slice(MAX_VISIBLE_HEADER_ACTIONS),\n };\n }\n\n const priorityAction = [...indexedActions]\n .reverse()\n .find((action) => isPriorityHeaderAction(action, indexedActions.length));\n\n if (!priorityAction) {\n return {\n visibleActions: defaultVisibleActions,\n overflowActions: indexedActions.slice(MAX_VISIBLE_HEADER_ACTIONS),\n };\n }\n\n const visibleActions = [indexedActions[0], priorityAction].sort(\n (left, right) => left.originalIndex - right.originalIndex,\n );\n const visibleIndexes = new Set(\n visibleActions.map((action) => action.originalIndex),\n );\n\n return {\n visibleActions,\n overflowActions: indexedActions.filter(\n (action) => !visibleIndexes.has(action.originalIndex),\n ),\n };\n}\n\nfunction getOverflowActionItemProps(\n action: PageHeaderAction,\n): Partial<PageHeaderOverflowActionProps> {\n const disabled = Boolean(\n action.overflowProps?.disabled ||\n action.buttonProps?.disabled ||\n action.buttonProps?.loading,\n );\n\n return {\n ...action.overflowProps,\n disabled,\n };\n}\n\n/* -----------------------------------------------------------------------------\n * PageHeader Component\n * -------------------------------------------------------------------------- */\n\nexport interface PageHeaderProps\n extends VariantProps<typeof pageHeaderVariants> {\n /** Page title */\n title: string;\n /** Supporting text/description */\n supportingText?: string;\n /** Breadcrumb items for desktop navigation */\n breadcrumbs?: BreadcrumbItemType[];\n /** Action buttons */\n actions?: PageHeaderAction[];\n /** Search placeholder text - enables search input when provided */\n searchPlaceholder?: string;\n /** Keyboard shortcut to display in search input */\n searchShortcut?: string;\n /** Search callback */\n onSearch?: (value: string) => void;\n /** Show bottom divider */\n showDivider?: boolean;\n /** Avatar props for avatar variants */\n avatarSrc?: string;\n /** Avatar fallback text (e.g., name for initials) */\n avatarFallback?: string;\n /** Avatar indicator */\n avatarStatusIcon?: AvatarProps['indicator'];\n /** Back button click handler (mobile) */\n onBackClick?: () => void;\n /** Back button label (mobile) */\n backLabel?: string;\n /** Additional className */\n className?: string;\n}\n\nfunction PageHeaderBreadcrumbs({\n breadcrumbs,\n}: {\n breadcrumbs: PageHeaderProps['breadcrumbs'];\n}) {\n if (!breadcrumbs || breadcrumbs.length === 0) return null;\n\n return (\n <Breadcrumb className=\"hidden md:flex delight-fade-in motion-reduce:!animate-none\">\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbHomeLink href=\"/\" />\n </BreadcrumbItem>\n {breadcrumbs.map((item, index) => {\n const isLast = index === breadcrumbs.length - 1;\n const hasEllipsis = breadcrumbs.length > 3;\n\n if (hasEllipsis && index === 1) {\n return (\n <React.Fragment key={`ellipsis-${index}`}>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbEllipsis />\n </BreadcrumbItem>\n </React.Fragment>\n );\n }\n\n if (hasEllipsis && index > 1 && !isLast) {\n return null;\n }\n\n return (\n <React.Fragment key={item.label}>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n {isLast || item.isCurrent ? (\n <BreadcrumbPage>{item.label}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink href={item.href}>{item.label}</BreadcrumbLink>\n )}\n </BreadcrumbItem>\n </React.Fragment>\n );\n })}\n </BreadcrumbList>\n </Breadcrumb>\n );\n}\n\nfunction PageHeaderBackButton({\n breadcrumbs,\n onBackClick,\n backLabel,\n}: {\n breadcrumbs: PageHeaderProps['breadcrumbs'];\n onBackClick?: () => void;\n backLabel: string;\n}) {\n if (!onBackClick || !breadcrumbs || breadcrumbs.length === 0) return null;\n\n return (\n <Button\n appearance=\"link\"\n variant=\"primary\"\n size=\"sm\"\n startIcon={<ArrowLeft className=\"size-5\" />}\n onClick={onBackClick}\n aria-label={`Go back: ${backLabel}`}\n className=\"md:hidden text-secondary-foreground px-0 hover:no-underline\"\n >\n {backLabel}\n </Button>\n );\n}\n\nfunction PageHeaderActions({\n actions,\n}: {\n actions: PageHeaderProps['actions'];\n}) {\n if (!actions || actions.length === 0) return null;\n\n const { visibleActions, overflowActions } = splitPageHeaderActions(actions);\n\n return (\n <div\n className=\"flex items-center gap-3 delight-stagger motion-reduce:!animate-none\"\n style={{ '--delight-delay': '120ms' } as React.CSSProperties}\n >\n {visibleActions.map((action) => (\n <Button\n key={`${action.label}-${action.originalIndex}`}\n variant={\n action.variant ??\n getPageHeaderActionVariant(\n action,\n action.originalIndex,\n actions.length,\n )\n }\n onClick={action.onClick}\n {...action.buttonProps}\n >\n {action.label}\n </Button>\n ))}\n {overflowActions.length > 0 && (\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button appearance=\"ghost\" size=\"icon\" aria-label=\"More actions\">\n <MoreHorizontal className=\"size-5\" />\n </Button>\n }\n />\n <DropdownMenu.Popup align=\"end\" sideOffset={4}>\n <DropdownMenu.Items>\n {overflowActions.map((action) => (\n <DropdownMenu.Item\n key={`${action.label}-${action.originalIndex}`}\n {...getOverflowActionItemProps(action)}\n onClick={action.onClick}\n variant={\n action.variant === 'destructive' ? 'destructive' : 'default'\n }\n >\n {action.label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Items>\n </DropdownMenu.Popup>\n </DropdownMenu>\n )}\n </div>\n );\n}\n\nfunction PageHeaderSearch({\n searchId,\n searchPlaceholder,\n searchShortcut,\n onSearch,\n}: {\n searchId: string;\n searchPlaceholder?: string;\n searchShortcut?: string;\n onSearch?: (query: string) => void;\n}) {\n if (!searchPlaceholder) return null;\n\n return (\n <search\n className=\"relative flex-1 min-w-0 max-w-xs delight-stagger motion-reduce:!animate-none\"\n style={{ '--delight-delay': '180ms' } as React.CSSProperties}\n >\n <div className=\"group/search relative\">\n <Search\n className=\"absolute start-3 top-1/2 -translate-y-1/2 size-5 text-text-quaternary pointer-events-none transition-colors duration-150 group-focus-within/search:text-primary motion-reduce:transition-none\"\n aria-hidden=\"true\"\n />\n <input\n id={searchId}\n type=\"text\"\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n onChange={(e) => onSearch?.(e.target.value)}\n className={cn(\n 'peer w-full rounded-lg border border-border bg-background py-2.5 pe-10 ps-10',\n 'text-base text-foreground placeholder:text-muted-foreground',\n 'shadow-xs transition-[border-color,box-shadow] duration-150 motion-reduce:transition-none',\n 'focus-visible:border-primary focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary',\n )}\n />\n {searchShortcut && (\n <Kbd\n variant=\"outline\"\n size=\"xs\"\n className=\"absolute end-3 top-1/2 -translate-y-1/2 transition-opacity duration-150 peer-focus-visible:opacity-0 motion-reduce:transition-none\"\n aria-hidden=\"true\"\n >\n {searchShortcut}\n </Kbd>\n )}\n </div>\n </search>\n );\n}\n\nfunction getPageHeaderInitials(name?: string) {\n if (!name) return '';\n const words = name.split(' ').filter(Boolean);\n if (words.length >= 2) {\n return `${words[0][0]}${words[1][0]}`.toUpperCase();\n }\n return name.slice(0, 2).toUpperCase();\n}\n\nfunction PageHeaderAvatar({\n hasAvatar,\n isBanner,\n avatarSrc,\n avatarFallback,\n avatarStatusIcon,\n}: {\n hasAvatar: boolean;\n isBanner: boolean;\n avatarSrc?: string;\n avatarFallback?: string;\n avatarStatusIcon: PageHeaderProps['avatarStatusIcon'];\n}) {\n if (!hasAvatar) return null;\n\n if (isBanner) {\n return (\n <div\n className={cn(\n 'relative shrink-0 rounded-full ring-4 ring-bg-primary shadow-lg',\n 'size-24 md:size-40',\n 'delight-fade-in motion-reduce:!animate-none',\n )}\n >\n {avatarSrc ? (\n <img\n src={avatarSrc}\n alt={avatarFallback || ''}\n className=\"size-full rounded-full object-cover\"\n />\n ) : (\n <div className=\"flex size-full items-center justify-center rounded-full bg-accent text-2xl font-semibold text-muted-foreground md:text-4xl\">\n {getPageHeaderInitials(avatarFallback)}\n </div>\n )}\n {avatarStatusIcon === 'verified' && (\n <div className=\"absolute bottom-0 end-0 flex size-6 items-center justify-center rounded-full border-2 border-primary bg-primary/10 md:size-10\">\n <svg\n className=\"size-3 text-primary md:size-5\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n aria-hidden=\"true\"\n >\n <title>Verified</title>\n <path\n fillRule=\"evenodd\"\n d=\"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <Avatar\n src={avatarSrc}\n fallback={avatarFallback}\n alt={avatarFallback}\n size=\"xl\"\n indicator={avatarStatusIcon}\n />\n );\n}\n\nfunction PageHeaderTextContent({\n title,\n supportingText,\n isCentered,\n}: {\n title: React.ReactNode;\n supportingText?: string;\n isCentered: boolean;\n}) {\n return (\n <div\n className={cn(\n 'flex flex-col min-w-0',\n isCentered ? 'items-center' : 'flex-1',\n )}\n >\n <h1\n className=\"text-xl font-semibold text-foreground leading-relaxed delight-stagger motion-reduce:!animate-none\"\n style={{ '--delight-delay': '0ms' } as React.CSSProperties}\n >\n {title}\n </h1>\n {supportingText && (\n <p\n className=\"text-base text-muted-foreground leading-6 max-w-prose delight-stagger motion-reduce:!animate-none\"\n style={{ '--delight-delay': '60ms' } as React.CSSProperties}\n >\n {supportingText}\n </p>\n )}\n </div>\n );\n}\n\nconst PageHeader = React.forwardRef<HTMLElement, PageHeaderProps>(\n (\n {\n variant = 'simple',\n title,\n supportingText,\n breadcrumbs,\n actions,\n searchPlaceholder,\n searchShortcut = '⌘K',\n onSearch,\n showDivider = true,\n avatarSrc,\n avatarFallback,\n avatarStatusIcon = 'verified',\n onBackClick,\n backLabel = 'Back',\n className,\n },\n ref,\n ) => {\n const searchId = React.useId();\n const resolvedVariant = variant ?? 'simple';\n const isBanner = resolvedVariant.startsWith('banner');\n const isCentered = resolvedVariant.includes('centered');\n const hasAvatar = resolvedVariant.includes('avatar');\n\n // Banner variants\n if (isBanner) {\n return (\n <header\n ref={ref}\n data-slot=\"page-header\"\n className={cn(\n pageHeaderVariants({ variant: resolvedVariant }),\n className,\n )}\n >\n {/* Banner image area with avatar overlap */}\n <div className=\"relative\">\n <div\n className={bannerVariants({\n variant: isCentered ? 'centered' : 'default',\n })}\n aria-hidden=\"true\"\n />\n\n {/* Avatar positioned to overlap banner bottom */}\n {hasAvatar && (\n <div\n className={cn(\n 'absolute inset-x-0 px-4 md:px-8',\n // Position avatar to overlap banner: -48px mobile, -40px desktop from bottom\n '-bottom-12 md:-bottom-20',\n isCentered && 'flex justify-center',\n )}\n >\n <PageHeaderAvatar\n hasAvatar={hasAvatar}\n isBanner={isBanner}\n avatarSrc={avatarSrc}\n avatarFallback={avatarFallback}\n avatarStatusIcon={avatarStatusIcon}\n />\n </div>\n )}\n </div>\n\n {/* Main content below banner */}\n <div\n className={cn(\n 'px-4 md:px-8',\n // Padding top to account for avatar overlap: 64px mobile, 96px desktop\n hasAvatar ? 'pt-16 md:pt-24' : 'pt-6',\n isCentered && 'flex flex-col items-center',\n )}\n >\n {/* Back button for mobile */}\n <div className=\"md:hidden mb-4\">\n <PageHeaderBackButton\n breadcrumbs={breadcrumbs}\n onBackClick={onBackClick}\n backLabel={backLabel}\n />\n </div>\n\n {/* Breadcrumbs for desktop */}\n {!isCentered && (\n <div className=\"hidden md:block\">\n <PageHeaderBreadcrumbs breadcrumbs={breadcrumbs} />\n </div>\n )}\n\n <div\n className={cn(\n contentVariants({ variant: resolvedVariant }),\n 'mt-4 md:mt-6',\n )}\n >\n {/* Text content */}\n <PageHeaderTextContent\n title={title}\n supportingText={supportingText}\n isCentered={isCentered}\n />\n\n {/* Actions */}\n <PageHeaderActions actions={actions} />\n\n {/* Search */}\n <PageHeaderSearch\n searchId={searchId}\n searchPlaceholder={searchPlaceholder}\n searchShortcut={searchShortcut}\n onSearch={onSearch}\n />\n </div>\n </div>\n\n {/* Divider */}\n {showDivider && (\n <Separator className=\"mt-5 delight-connector-fill motion-reduce:!animate-none\" />\n )}\n </header>\n );\n }\n\n // Non-banner variants (simple, avatar)\n return (\n <header\n ref={ref}\n data-slot=\"page-header\"\n className={cn(\n pageHeaderVariants({ variant: resolvedVariant }),\n className,\n )}\n >\n {/* Navigation: Breadcrumbs (desktop) / Back button (mobile) */}\n {breadcrumbs && breadcrumbs.length > 0 && (\n <div>\n <PageHeaderBreadcrumbs breadcrumbs={breadcrumbs} />\n <PageHeaderBackButton\n breadcrumbs={breadcrumbs}\n onBackClick={onBackClick}\n backLabel={backLabel}\n />\n </div>\n )}\n\n {/* Main content */}\n <div className={cn(contentVariants({ variant: resolvedVariant }))}>\n {/* Avatar + Text group */}\n <div\n className={cn(\n 'flex gap-4 items-center flex-1 min-w-0',\n hasAvatar && 'flex-row',\n )}\n >\n <PageHeaderAvatar\n hasAvatar={hasAvatar}\n isBanner={isBanner}\n avatarSrc={avatarSrc}\n avatarFallback={avatarFallback}\n avatarStatusIcon={avatarStatusIcon}\n />\n <PageHeaderTextContent\n title={title}\n supportingText={supportingText}\n isCentered={isCentered}\n />\n </div>\n\n {/* Actions */}\n <PageHeaderActions actions={actions} />\n\n {/* Search */}\n <PageHeaderSearch\n searchId={searchId}\n searchPlaceholder={searchPlaceholder}\n searchShortcut={searchShortcut}\n onSearch={onSearch}\n />\n </div>\n\n {/* Divider */}\n {showDivider && (\n <Separator className=\"delight-connector-fill motion-reduce:!animate-none\" />\n )}\n </header>\n );\n },\n);\n\nPageHeader.displayName = 'PageHeader';\n\nexport { bannerVariants, contentVariants, PageHeader, pageHeaderVariants };\n"],"mappings":";;;;;;;;;;;;AA6EA,IAAM,qBAAqB,IAAI,wBAAwB;CACrD,UAAU,EACR,SAAS;EACP,QAAQ;EACR,QAAQ;EACR,iBAAiB;EACjB,iBAAiB;EACjB,0BAA0B;EAC1B,0BAA0B;CAC5B,EACF;CACA,iBAAiB,EACf,SAAS,SACX;AACF,CAAC;AAED,IAAM,kBAAkB,IAAI,qCAAqC;CAC/D,UAAU,EACR,SAAS;EACP,QAAQ;EACR,QAAQ;EACR,iBAAiB;EACjB,iBAAiB;EACjB,0BACE;EACF,0BACE;CACJ,EACF;CACA,iBAAiB,EACf,SAAS,SACX;AACF,CAAC;AAED,IAAM,iBAAiB,IACrB,6EACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,UAAU;CACZ,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,IAAM,6BAA6B;AAMnC,SAAS,2BACP,QACA,OACA,aACwB;CACxB,OACE,OAAO,YAAY,UAAU,cAAc,IAAI,YAAY;AAE/D;AAEA,SAAS,uBACP,QACA,aACS;CACT,OACE,2BAA2B,QAAQ,OAAO,eAAe,WAAW,MACpE;AAEJ;AAEA,SAAS,uBAAuB,SAG9B;CACA,MAAM,iBAAiB,QAAQ,KAAK,QAAQ,mBAAmB;EAC7D,GAAG;EACH;CACF,EAAE;CAEF,IAAI,eAAe,UAAU,4BAC3B,OAAO;EACL,gBAAgB;EAChB,iBAAiB,CAAC;CACpB;CAGF,MAAM,wBAAwB,eAAe,MAC3C,GACA,0BACF;CAEA,IACE,sBAAsB,MAAM,WAC1B,uBAAuB,QAAQ,eAAe,MAAM,CACtD,GAEA,OAAO;EACL,gBAAgB;EAChB,iBAAiB,eAAe,MAAM,0BAA0B;CAClE;CAGF,MAAM,iBAAiB,CAAC,GAAG,cAAc,CAAC,CACvC,QAAQ,CAAC,CACT,MAAM,WAAW,uBAAuB,QAAQ,eAAe,MAAM,CAAC;CAEzE,IAAI,CAAC,gBACH,OAAO;EACL,gBAAgB;EAChB,iBAAiB,eAAe,MAAM,0BAA0B;CAClE;CAGF,MAAM,iBAAiB,CAAC,eAAe,IAAI,cAAc,CAAC,CAAC,MACxD,MAAM,UAAU,KAAK,gBAAgB,MAAM,aAC9C;CACA,MAAM,iBAAiB,IAAI,IACzB,eAAe,KAAK,WAAW,OAAO,aAAa,CACrD;CAEA,OAAO;EACL;EACA,iBAAiB,eAAe,QAC7B,WAAW,CAAC,eAAe,IAAI,OAAO,aAAa,CACtD;CACF;AACF;AAEA,SAAS,2BACP,QACwC;CACxC,MAAM,WAAW,QACf,OAAO,eAAe,YACpB,OAAO,aAAa,YACpB,OAAO,aAAa,OACxB;CAEA,OAAO;EACL,GAAG,OAAO;EACV;CACF;AACF;AAsCA,SAAS,sBAAsB,EAC7B,eAGC;CACD,IAAI,CAAC,eAAe,YAAY,WAAW,GAAG,OAAO;CAErD,OACE,oBAAC,oBAAD;EAAY,WAAU;YACpB,qBAAC,gBAAD,EAAA,UAAA,CACE,oBAAC,gBAAD,EAAA,UACE,oBAAC,oBAAD,EAAoB,MAAK,IAAK,CAAA,EAChB,CAAA,GACf,YAAY,KAAK,MAAM,UAAU;GAChC,MAAM,SAAS,UAAU,YAAY,SAAS;GAC9C,MAAM,cAAc,YAAY,SAAS;GAEzC,IAAI,eAAe,UAAU,GAC3B,OACE,qBAAC,MAAM,UAAP,EAAA,UAAA,CACE,oBAAC,qBAAD,CAAsB,CAAA,GACtB,oBAAC,gBAAD,EAAA,UACE,oBAAC,oBAAD,CAAqB,CAAA,EACP,CAAA,CACF,EAAA,GALK,YAAY,OAKjB;GAIpB,IAAI,eAAe,QAAQ,KAAK,CAAC,QAC/B,OAAO;GAGT,OACE,qBAAC,MAAM,UAAP,EAAA,UAAA,CACE,oBAAC,qBAAD,CAAsB,CAAA,GACtB,oBAAC,gBAAD,EAAA,UACG,UAAU,KAAK,YACd,oBAAC,gBAAD,EAAA,UAAiB,KAAK,MAAsB,CAAA,IAE5C,oBAAC,gBAAD;IAAgB,MAAM,KAAK;cAAO,KAAK;GAAsB,CAAA,EAEjD,CAAA,CACF,EAAA,GATK,KAAK,KASV;EAEpB,CAAC,CACa,EAAA,CAAA;CACN,CAAA;AAEhB;AAEA,SAAS,qBAAqB,EAC5B,aACA,aACA,aAKC;CACD,IAAI,CAAC,eAAe,CAAC,eAAe,YAAY,WAAW,GAAG,OAAO;CAErE,OACE,oBAAC,QAAD;EACE,YAAW;EACX,SAAQ;EACR,MAAK;EACL,WAAW,oBAAC,WAAD,EAAW,WAAU,SAAU,CAAA;EAC1C,SAAS;EACT,cAAY,YAAY;EACxB,WAAU;YAET;CACK,CAAA;AAEZ;AAEA,SAAS,kBAAkB,EACzB,WAGC;CACD,IAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,OAAO;CAE7C,MAAM,EAAE,gBAAgB,oBAAoB,uBAAuB,OAAO;CAE1E,OACE,qBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,mBAAmB,QAAQ;YAFtC,CAIG,eAAe,KAAK,WACnB,oBAAC,QAAD;GAEE,SACE,OAAO,WACP,2BACE,QACA,OAAO,eACP,QAAQ,MACV;GAEF,SAAS,OAAO;GAChB,GAAI,OAAO;aAEV,OAAO;EACF,GAbD,GAAG,OAAO,MAAM,GAAG,OAAO,eAazB,CACT,GACA,gBAAgB,SAAS,KACxB,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,aAAa,SAAd,EACE,QACE,oBAAC,QAAD;GAAQ,YAAW;GAAQ,MAAK;GAAO,cAAW;aAChD,oBAAC,gBAAD,EAAgB,WAAU,SAAU,CAAA;EAC9B,CAAA,EAEX,CAAA,GACD,oBAAC,aAAa,OAAd;GAAoB,OAAM;GAAM,YAAY;aAC1C,oBAAC,aAAa,OAAd,EAAA,UACG,gBAAgB,KAAK,WACpB,oBAAC,aAAa,MAAd;IAEE,GAAI,2BAA2B,MAAM;IACrC,SAAS,OAAO;IAChB,SACE,OAAO,YAAY,gBAAgB,gBAAgB;cAGpD,OAAO;GACS,GARZ,GAAG,OAAO,MAAM,GAAG,OAAO,eAQd,CACpB,EACiB,CAAA;EACF,CAAA,CACR,EAAA,CAAA,CAEb;;AAET;AAEA,SAAS,iBAAiB,EACxB,UACA,mBACA,gBACA,YAMC;CACD,IAAI,CAAC,mBAAmB,OAAO;CAE/B,OACE,oBAAC,UAAD;EACE,WAAU;EACV,OAAO,EAAE,mBAAmB,QAAQ;YAEpC,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,QAAD;KACE,WAAU;KACV,eAAY;IACb,CAAA;IACD,oBAAC,SAAD;KACE,IAAI;KACJ,MAAK;KACL,aAAa;KACb,cAAY;KACZ,WAAW,MAAM,WAAW,EAAE,OAAO,KAAK;KAC1C,WAAW,GACT,gFACA,+DACA,6FACA,yGACF;IACD,CAAA;IACA,kBACC,oBAAC,KAAD;KACE,SAAQ;KACR,MAAK;KACL,WAAU;KACV,eAAY;eAEX;IACE,CAAA;GAEJ;;CACC,CAAA;AAEZ;AAEA,SAAS,sBAAsB,MAAe;CAC5C,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,QAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;CAC5C,IAAI,MAAM,UAAU,GAClB,OAAO,GAAG,MAAM,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,KAAK,YAAY;CAEpD,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY;AACtC;AAEA,SAAS,iBAAiB,EACxB,WACA,UACA,WACA,gBACA,oBAOC;CACD,IAAI,CAAC,WAAW,OAAO;CAEvB,IAAI,UACF,OACE,qBAAC,OAAD;EACE,WAAW,GACT,mEACA,sBACA,6CACF;YALF,CAOG,YACC,oBAAC,OAAD;GACE,KAAK;GACL,KAAK,kBAAkB;GACvB,WAAU;EACX,CAAA,IAED,oBAAC,OAAD;GAAK,WAAU;aACZ,sBAAsB,cAAc;EAClC,CAAA,GAEN,qBAAqB,cACpB,oBAAC,OAAD;GAAK,WAAU;aACb,qBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,SAAQ;IACR,eAAY;cAJd,CAME,oBAAC,SAAD,EAAA,UAAO,WAAe,CAAA,GACtB,oBAAC,QAAD;KACE,UAAS;KACT,GAAE;KACF,UAAS;IACV,CAAA,CACE;;EACF,CAAA,CAEJ;;CAIT,OACE,oBAAC,QAAD;EACE,KAAK;EACL,UAAU;EACV,KAAK;EACL,MAAK;EACL,WAAW;CACZ,CAAA;AAEL;AAEA,SAAS,sBAAsB,EAC7B,OACA,gBACA,cAKC;CACD,OACE,qBAAC,OAAD;EACE,WAAW,GACT,yBACA,aAAa,iBAAiB,QAChC;YAJF,CAME,oBAAC,MAAD;GACE,WAAU;GACV,OAAO,EAAE,mBAAmB,MAAM;aAEjC;EACC,CAAA,GACH,kBACC,oBAAC,KAAD;GACE,WAAU;GACV,OAAO,EAAE,mBAAmB,OAAO;aAElC;EACA,CAAA,CAEF;;AAET;AAEA,IAAM,aAAa,MAAM,YAErB,EACE,UAAU,UACV,OACA,gBACA,aACA,SACA,mBACA,iBAAiB,MACjB,UACA,cAAc,MACd,WACA,gBACA,mBAAmB,YACnB,aACA,YAAY,QACZ,aAEF,QACG;CACH,MAAM,WAAW,MAAM,MAAM;CAC7B,MAAM,kBAAkB,WAAW;CACnC,MAAM,WAAW,gBAAgB,WAAW,QAAQ;CACpD,MAAM,aAAa,gBAAgB,SAAS,UAAU;CACtD,MAAM,YAAY,gBAAgB,SAAS,QAAQ;CAGnD,IAAI,UACF,OACE,qBAAC,UAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,mBAAmB,EAAE,SAAS,gBAAgB,CAAC,GAC/C,SACF;YANF;GASE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,OAAD;KACE,WAAW,eAAe,EACxB,SAAS,aAAa,aAAa,UACrC,CAAC;KACD,eAAY;IACb,CAAA,GAGA,aACC,oBAAC,OAAD;KACE,WAAW,GACT,mCAEA,4BACA,cAAc,qBAChB;eAEA,oBAAC,kBAAD;MACa;MACD;MACC;MACK;MACE;KACnB,CAAA;IACE,CAAA,CAEJ;;GAGL,qBAAC,OAAD;IACE,WAAW,GACT,gBAEA,YAAY,mBAAmB,QAC/B,cAAc,4BAChB;cANF;KASE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,sBAAD;OACe;OACA;OACF;MACZ,CAAA;KACE,CAAA;KAGJ,CAAC,cACA,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,uBAAD,EAAoC,YAAc,CAAA;KAC/C,CAAA;KAGP,qBAAC,OAAD;MACE,WAAW,GACT,gBAAgB,EAAE,SAAS,gBAAgB,CAAC,GAC5C,cACF;gBAJF;OAOE,oBAAC,uBAAD;QACS;QACS;QACJ;OACb,CAAA;OAGD,oBAAC,mBAAD,EAA4B,QAAU,CAAA;OAGtC,oBAAC,kBAAD;QACY;QACS;QACH;QACN;OACX,CAAA;MACE;;IACF;;GAGJ,eACC,oBAAC,WAAD,EAAW,WAAU,0DAA2D,CAAA;EAE5E;;CAKZ,OACE,qBAAC,UAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,mBAAmB,EAAE,SAAS,gBAAgB,CAAC,GAC/C,SACF;YANF;GASG,eAAe,YAAY,SAAS,KACnC,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,uBAAD,EAAoC,YAAc,CAAA,GAClD,oBAAC,sBAAD;IACe;IACA;IACF;GACZ,CAAA,CACE,EAAA,CAAA;GAIP,qBAAC,OAAD;IAAK,WAAW,GAAG,gBAAgB,EAAE,SAAS,gBAAgB,CAAC,CAAC;cAAhE;KAEE,qBAAC,OAAD;MACE,WAAW,GACT,0CACA,aAAa,UACf;gBAJF,CAME,oBAAC,kBAAD;OACa;OACD;OACC;OACK;OACE;MACnB,CAAA,GACD,oBAAC,uBAAD;OACS;OACS;OACJ;MACb,CAAA,CACE;;KAGL,oBAAC,mBAAD,EAA4B,QAAU,CAAA;KAGtC,oBAAC,kBAAD;MACY;MACS;MACH;MACN;KACX,CAAA;IACE;;GAGJ,eACC,oBAAC,WAAD,EAAW,WAAU,qDAAsD,CAAA;EAEvE;;AAEZ,CACF;AAEA,WAAW,cAAc"}
package/dist/index204.js CHANGED
@@ -1,296 +1,165 @@
1
1
  "use client";
2
2
  import { cn } from "./index2.js";
3
- import { Button, ClearButton } from "./index5.js";
4
- import { Avatar } from "./index70.js";
5
- import { Kbd } from "./index106.js";
6
- import { Command as CommandNamespace, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "./index120.js";
7
- import { ArrowDown, ArrowUp, CornerDownLeft, Search, Settings } from "lucide-react";
3
+ import { Button } from "./index5.js";
4
+ import { ButtonGroup as ButtonGroupCompound } from "./index8.js";
5
+ import { Input } from "./index33.js";
6
+ import { Separator } from "./index51.js";
7
+ import { Tabs } from "./index137.js";
8
+ import { Search } from "lucide-react";
8
9
  import * as React from "react";
9
10
  import { jsx, jsxs } from "react/jsx-runtime";
10
- //#region src/components/organisms/menus/CommandMenu/CommandMenu.tsx
11
- var DEFAULT_COMMAND_MENU_MAX_HEIGHT = 336;
12
- var DEFAULT_COMMAND_MENU_PLACEHOLDER = "Type a command or search...";
13
- var COMMAND_MENU_SHELL_CLASS_NAME = "w-full max-w-[508px] overflow-hidden rounded-xl border border-input bg-background shadow-lg";
14
- function getCommandMenuMaxHeight(maxHeight) {
15
- return Number.isFinite(maxHeight) && maxHeight >= 0 ? maxHeight : DEFAULT_COMMAND_MENU_MAX_HEIGHT;
11
+ //#region src/components/organisms/layout/SectionHeader/SectionHeader.tsx
12
+ var controlTouchTargetClassName = "min-h-11 min-w-11 shrink-0";
13
+ function getHeadingTag(headingLevel) {
14
+ return `h${headingLevel}`;
16
15
  }
17
- function usePlatformShortcut() {
18
- const [shortcut, setShortcut] = React.useState("⌘/");
19
- React.useEffect(() => {
20
- if (!/Mac|iPhone|iPad/i.test(navigator.userAgent)) setShortcut("Ctrl /");
21
- }, []);
22
- return shortcut;
23
- }
24
- function CommandShortcutBadge({ children, className }) {
25
- return /* @__PURE__ */ jsx(Kbd, {
26
- variant: "solid",
27
- size: "sm",
28
- className: cn("shadow-xs", className),
29
- children
16
+ function SectionHeaderTouchTargetControl({ control }) {
17
+ if (React.isValidElement(control)) return React.cloneElement(control, { className: cn(control.props.className, controlTouchTargetClassName) });
18
+ return /* @__PURE__ */ jsx("span", {
19
+ className: cn("inline-flex items-center justify-center", controlTouchTargetClassName),
20
+ children: control
30
21
  });
31
22
  }
32
- CommandShortcutBadge.displayName = "CommandMenu.ShortcutBadge";
33
- function FooterNavIcon({ children, className }) {
34
- return /* @__PURE__ */ jsx(Kbd, {
35
- variant: "footer",
36
- size: "sm",
37
- className: cn("p-1.5", className),
38
- children
39
- });
23
+ function getSectionHeaderActionKey(action, index, prefix = "section-header-action") {
24
+ return typeof action.label === "string" ? `${action.label}-${index}` : `${prefix}-${index}`;
40
25
  }
41
- FooterNavIcon.displayName = "CommandMenu.FooterNavIcon";
42
- function FooterNavText({ children, className }) {
43
- return /* @__PURE__ */ jsx("span", {
44
- className: cn("text-sm font-semibold text-text-quaternary", className),
45
- children
26
+ function SectionHeaderActionButton({ action, className }) {
27
+ const { label, className: actionClassName, ...buttonProps } = action;
28
+ return /* @__PURE__ */ jsx(Button, {
29
+ appearance: "solid",
30
+ size: "default",
31
+ shape: "rounded",
32
+ className: cn("h-10 rounded-xl px-2 text-xs font-medium", actionClassName, className),
33
+ ...buttonProps,
34
+ children: label
46
35
  });
47
36
  }
48
- FooterNavText.displayName = "CommandMenu.FooterNavText";
49
- var defaultFooterHints = [
50
- {
51
- keys: /* @__PURE__ */ jsxs("div", {
52
- className: "flex items-center gap-1",
53
- children: [/* @__PURE__ */ jsx(FooterNavIcon, { children: /* @__PURE__ */ jsx(ArrowUp, { className: "size-2.5 text-text-quaternary" }) }), /* @__PURE__ */ jsx(FooterNavIcon, { children: /* @__PURE__ */ jsx(ArrowDown, { className: "size-2.5 text-text-quaternary" }) })]
54
- }),
55
- label: "to navigate"
56
- },
57
- {
58
- keys: /* @__PURE__ */ jsx(FooterNavIcon, { children: /* @__PURE__ */ jsx(CornerDownLeft, { className: "size-2.5 text-text-quaternary" }) }),
59
- label: "to select"
60
- },
61
- {
62
- keys: /* @__PURE__ */ jsx(FooterNavIcon, {
63
- className: "px-1.5 py-1",
64
- children: /* @__PURE__ */ jsx("span", {
65
- className: "text-xs font-semibold text-text-quaternary",
66
- children: "esc"
67
- })
68
- }),
69
- label: "to close"
70
- }
71
- ];
72
- function CommandMenuFooter({ hints = defaultFooterHints, showSettingsButton = false, onSettingsClick, className }) {
73
- return /* @__PURE__ */ jsxs("div", {
74
- "data-slot": "command-menu-footer",
75
- className: cn("flex items-center gap-3 border-t border-border bg-card/80 py-2 pe-2 ps-[18px] supports-backdrop-filter:backdrop-blur", className),
76
- children: [/* @__PURE__ */ jsx("div", {
77
- className: "hidden flex-1 items-start gap-4 [@media(hover:hover)]:flex",
78
- children: hints.map((hint) => /* @__PURE__ */ jsxs("div", {
79
- className: "flex items-center gap-2",
80
- children: [hint.keys, /* @__PURE__ */ jsx(FooterNavText, { children: hint.label })]
81
- }, hint.label))
82
- }), showSettingsButton && /* @__PURE__ */ jsx(Button, {
83
- appearance: "ghost",
84
- variant: "secondary",
85
- size: "icon",
86
- className: "group ms-auto rounded-full bg-muted",
87
- onClick: onSettingsClick,
88
- "aria-label": "Settings",
89
- children: /* @__PURE__ */ jsx(Settings, { className: "size-5 text-muted-foreground transition-transform duration-300 ease-out group-hover:rotate-90 motion-reduce:transition-none" })
90
- })]
37
+ function SectionHeaderButtonGroup({ actions }) {
38
+ return /* @__PURE__ */ jsx(ButtonGroupCompound, {
39
+ "aria-label": "Section header controls",
40
+ shape: "rounded",
41
+ className: "overflow-hidden rounded-xl",
42
+ children: actions.map((action, index) => {
43
+ const { label, className, ...buttonProps } = action;
44
+ return /* @__PURE__ */ jsx(Button, {
45
+ appearance: buttonProps.appearance ?? "soft",
46
+ variant: buttonProps.variant ?? "primary",
47
+ size: "md",
48
+ shape: "rounded",
49
+ className: cn("border-transparent px-3 text-xs font-medium shadow-none", className),
50
+ ...buttonProps,
51
+ children: label
52
+ }, getSectionHeaderActionKey(action, index, "section-header-group-action"));
53
+ })
91
54
  });
92
55
  }
93
- CommandMenuFooter.displayName = "CommandMenu.Footer";
94
- function CommandMenuItem({ option, onSelect, className, ...props }) {
95
- return /* @__PURE__ */ jsxs(CommandItem, {
96
- value: option.id,
97
- disabled: option.disabled,
98
- showCheckIndicator: false,
99
- onSelect: () => onSelect?.(option.id, option),
100
- className: cn("flex cursor-pointer items-center gap-2 transition-colors duration-150 motion-reduce:transition-none", className),
101
- ...props,
102
- children: [
103
- option.avatar && /* @__PURE__ */ jsx(Avatar, {
104
- src: option.avatar.src,
105
- fallback: option.avatar.fallback || option.label.charAt(0),
106
- size: "sm",
107
- className: "size-6 shrink-0"
108
- }),
109
- option.icon && !option.avatar && /* @__PURE__ */ jsx("span", {
110
- className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-4",
111
- children: option.icon
112
- }),
113
- /* @__PURE__ */ jsxs("div", {
114
- className: "flex min-w-0 flex-1 items-center gap-2 text-sm leading-5",
115
- children: [/* @__PURE__ */ jsx("span", {
116
- className: "min-w-0 truncate font-normal text-foreground",
117
- children: option.label
118
- }), option.subtitle && /* @__PURE__ */ jsx("span", {
119
- className: "min-w-0 truncate font-normal text-muted-foreground",
120
- children: option.subtitle
121
- })]
122
- }),
123
- option.shortcut && /* @__PURE__ */ jsx(CommandShortcutBadge, {
124
- className: "transition-colors duration-150 group-data-[selected=true]/command-item:bg-primary/10 group-data-[selected=true]/command-item:text-primary",
125
- children: option.shortcut
56
+ function getTabValue(tab, index) {
57
+ if (tab.value !== void 0) return tab.value;
58
+ if (typeof tab.label === "string") return `${tab.label}-${index}`;
59
+ return `section-header-tab-${index}`;
60
+ }
61
+ function SectionHeaderTabs({ tabs }) {
62
+ const tabValues = tabs.map((tab, index) => getTabValue(tab, index));
63
+ const tabListKey = JSON.stringify(tabValues);
64
+ const activeIndex = tabs.findIndex((tab) => tab.active);
65
+ const activeValue = activeIndex >= 0 ? tabValues[activeIndex] : void 0;
66
+ return /* @__PURE__ */ jsx(Tabs, {
67
+ value: activeValue,
68
+ defaultValue: activeValue ?? tabValues[0],
69
+ className: "w-full",
70
+ children: /* @__PURE__ */ jsx(Tabs.List, {
71
+ variant: "boxed",
72
+ size: "sm",
73
+ align: "stretch",
74
+ "aria-label": "Section header tabs",
75
+ className: "w-full overflow-x-auto overflow-y-hidden rounded-[8px] border border-border bg-card p-1 shadow-sm",
76
+ children: tabs.map((tab, index) => {
77
+ const value = tabValues[index];
78
+ return /* @__PURE__ */ jsx(Tabs.Trigger, {
79
+ value,
80
+ icon: tab.leadingIcon,
81
+ className: "min-w-max flex-1 rounded-[10px] px-3 py-1",
82
+ onClick: tab.onClick,
83
+ children: /* @__PURE__ */ jsx("span", {
84
+ className: "whitespace-nowrap",
85
+ children: tab.label
86
+ })
87
+ }, value);
126
88
  })
127
- ]
128
- });
89
+ })
90
+ }, tabListKey);
129
91
  }
130
- CommandMenuItem.displayName = "CommandMenu.Item";
131
- function CommandMenuGroupHeader({ children, className, ...props }) {
132
- return /* @__PURE__ */ jsx("h3", {
133
- "data-slot": "command-menu-group-header",
134
- className: cn("px-2 py-1.5 text-xs font-medium text-muted-foreground", className),
135
- ...props,
136
- children
137
- });
92
+ function SectionHeaderControls({ actions, buttonGroup, search }) {
93
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
94
+ search ? /* @__PURE__ */ jsx(SectionHeaderSearchField, { search }) : null,
95
+ buttonGroup?.length ? /* @__PURE__ */ jsx(SectionHeaderButtonGroup, { actions: buttonGroup }) : null,
96
+ actions?.length ? /* @__PURE__ */ jsx("div", {
97
+ className: "flex flex-wrap items-center gap-3 md:flex-nowrap",
98
+ children: actions.map((action, index) => /* @__PURE__ */ jsx(SectionHeaderActionButton, { action }, getSectionHeaderActionKey(action, index)))
99
+ }) : null
100
+ ] });
138
101
  }
139
- CommandMenuGroupHeader.displayName = "CommandMenu.GroupHeader";
140
- function CommandMenuGroupSection({ group, optionRenderer }) {
141
- const headingId = React.useId();
142
- return /* @__PURE__ */ jsxs(CommandGroup, {
143
- "aria-labelledby": headingId,
144
- className: "px-2 py-1",
145
- children: [/* @__PURE__ */ jsx(CommandMenuGroupHeader, {
146
- id: headingId,
147
- children: group.label
148
- }), /* @__PURE__ */ jsx("div", {
149
- className: "flex flex-col",
150
- children: group.options.map(optionRenderer)
151
- })]
102
+ function SectionHeaderSearchField({ search }) {
103
+ const { className: searchClassName, placeholder, ariaLabel, filterButton, ...searchProps } = search;
104
+ const searchInput = /* @__PURE__ */ jsx(Input, {
105
+ size: "md",
106
+ shape: "rounded",
107
+ "aria-label": ariaLabel ?? "Search",
108
+ placeholder: placeholder ?? "Search",
109
+ startIcon: /* @__PURE__ */ jsx(Search, { className: "size-4" }),
110
+ className: cn(filterButton ? "min-w-0 flex-1" : "w-full max-w-[320px]", searchClassName),
111
+ ...searchProps
152
112
  });
153
- }
154
- CommandMenuGroupSection.displayName = "CommandMenu.GroupSection";
155
- function CommandMenuBodyContent({ children, groups, options, optionRenderer }) {
156
- if (children) return children;
157
- if (groups.length > 0) return groups.map((group, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 && /* @__PURE__ */ jsx(CommandSeparator, { className: "mx-0" }), /* @__PURE__ */ jsx(CommandMenuGroupSection, {
158
- group,
159
- optionRenderer
160
- })] }, group.id));
161
- return /* @__PURE__ */ jsx("div", {
162
- className: "flex flex-col p-2",
163
- children: options.map(optionRenderer)
113
+ if (filterButton) return /* @__PURE__ */ jsxs("div", {
114
+ "data-slot": "section-header-search",
115
+ className: "flex w-full max-w-[376px] items-center gap-2",
116
+ children: [searchInput, /* @__PURE__ */ jsx(SectionHeaderTouchTargetControl, { control: filterButton })]
164
117
  });
118
+ return searchInput;
165
119
  }
166
- function CommandMenuBody({ children, groups, options, onSelect, onClose, placeholder, emptyText, emptyState, showShortcut, shortcutText, showFooter, footerHints, showSettingsButton, onSettingsClick, maxHeight, filter }) {
167
- const safeMaxHeight = getCommandMenuMaxHeight(maxHeight);
168
- const renderOption = (option) => /* @__PURE__ */ jsx(CommandMenuItem, {
169
- option,
170
- onSelect
171
- }, option.id);
172
- return /* @__PURE__ */ jsxs(CommandNamespace, {
173
- filter,
174
- className: "rounded-none border-0 shadow-none",
175
- "data-slot": "command-menu",
120
+ var SectionHeader = React.forwardRef(({ title, supportingText, size = "md", headingLevel = 2, actions, buttonGroup, search, tabs, menuButton = null, showDivider = true, className, ...props }, ref) => {
121
+ const hasSearch = Boolean(search);
122
+ const hasButtonGroup = Boolean(buttonGroup?.length);
123
+ const hasActions = Boolean(actions?.length);
124
+ const hasInlineControls = hasSearch || hasButtonGroup || hasActions;
125
+ const hasHeaderControls = hasInlineControls || Boolean(menuButton);
126
+ const HeadingTag = getHeadingTag(headingLevel);
127
+ return /* @__PURE__ */ jsxs("header", {
128
+ ref,
129
+ "data-slot": "section-header",
130
+ className: cn("relative flex w-full flex-col gap-4", className),
131
+ ...props,
176
132
  children: [
177
- /* @__PURE__ */ jsx("search", {
178
- "aria-label": "Command menu search",
179
- className: "block border-b border-input bg-background",
180
- children: /* @__PURE__ */ jsx(CommandInput, { render: ({ clearSearch, value, ...inputProps }) => {
181
- const canClose = typeof onClose === "function";
182
- const clearOrClose = () => {
183
- if (value) {
184
- clearSearch();
185
- return;
186
- }
187
- onClose?.();
188
- };
189
- return /* @__PURE__ */ jsxs("div", {
190
- "data-slot": "command-menu-input",
191
- "cmdk-input-wrapper": "",
192
- className: "flex h-11 items-center gap-2 px-3",
193
- children: [
194
- /* @__PURE__ */ jsx(Search, {
195
- className: "size-4 shrink-0 text-muted-foreground opacity-50",
196
- "aria-hidden": "true"
197
- }),
198
- /* @__PURE__ */ jsx("input", {
199
- ...inputProps,
200
- value,
201
- placeholder,
202
- "aria-label": placeholder,
203
- className: "min-w-0 flex-1 bg-transparent text-sm leading-5 text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
204
- }),
205
- showShortcut && /* @__PURE__ */ jsx(CommandShortcutBadge, { children: shortcutText }),
206
- /* @__PURE__ */ jsx(ClearButton, {
207
- size: "icon-xs",
208
- className: "-me-1 rounded-sm p-0 opacity-50 hover:opacity-80 focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4",
209
- disabled: !value && !canClose,
210
- "aria-label": value ? "Clear search" : canClose ? "Close command menu" : "Clear search",
211
- onClick: clearOrClose
212
- })
213
- ]
214
- });
215
- } })
216
- }),
217
- /* @__PURE__ */ jsxs(CommandList, {
218
- style: { maxHeight: safeMaxHeight },
219
- className: "overflow-y-auto p-0",
220
- children: [/* @__PURE__ */ jsx(CommandEmpty, {
221
- className: "py-6 text-center text-sm text-muted-foreground animate-in fade-in-0 duration-200 motion-reduce:animate-none",
222
- children: emptyState || emptyText
223
- }), /* @__PURE__ */ jsx(CommandMenuBodyContent, {
224
- groups,
225
- options,
226
- optionRenderer: renderOption,
227
- children
228
- })]
133
+ /* @__PURE__ */ jsxs("div", {
134
+ className: "grid w-full grid-cols-[minmax(0,1fr)_auto] items-start gap-x-4 gap-y-3",
135
+ children: [/* @__PURE__ */ jsxs("div", {
136
+ className: cn("col-start-1 row-start-1 flex min-w-0 flex-col justify-center gap-0.5", menuButton ? "pe-8 md:pe-0" : null),
137
+ children: [/* @__PURE__ */ jsx(HeadingTag, {
138
+ className: cn("line-clamp-2 w-full break-words font-semibold text-foreground", size === "sm" ? "text-[14px] leading-5" : "text-[18px] leading-7"),
139
+ children: title
140
+ }), supportingText ? /* @__PURE__ */ jsx("p", {
141
+ className: "line-clamp-2 w-full break-words text-sm leading-5 text-secondary-foreground",
142
+ children: supportingText
143
+ }) : null]
144
+ }), hasHeaderControls ? /* @__PURE__ */ jsxs("div", {
145
+ className: cn("col-span-2 row-start-2 flex flex-wrap items-center gap-3 md:col-span-1 md:col-start-2 md:row-start-1 md:flex-nowrap md:justify-end", !hasInlineControls && "contents md:flex"),
146
+ children: [/* @__PURE__ */ jsx(SectionHeaderControls, {
147
+ actions,
148
+ buttonGroup,
149
+ search
150
+ }), menuButton ? /* @__PURE__ */ jsx("div", {
151
+ className: "absolute end-0 top-0 md:static",
152
+ children: /* @__PURE__ */ jsx(SectionHeaderTouchTargetControl, { control: menuButton })
153
+ }) : null]
154
+ }) : null]
229
155
  }),
230
- showFooter && /* @__PURE__ */ jsx(CommandMenuFooter, {
231
- hints: footerHints,
232
- showSettingsButton,
233
- onSettingsClick
234
- })
156
+ tabs?.length ? /* @__PURE__ */ jsx(SectionHeaderTabs, { tabs }) : null,
157
+ showDivider ? /* @__PURE__ */ jsx(Separator, { "aria-hidden": "true" }) : null
235
158
  ]
236
159
  });
237
- }
238
- CommandMenuBody.displayName = "CommandMenu.Body";
239
- function CommandMenu({ open, onOpenChange, placeholder = DEFAULT_COMMAND_MENU_PLACEHOLDER, emptyText = "No results found.", emptyState, options = [], groups = [], onSelect, showShortcut = false, shortcutText, showFooter = false, footerHints, showSettingsButton = false, onSettingsClick, className, maxHeight = DEFAULT_COMMAND_MENU_MAX_HEIGHT, filter, children }) {
240
- const platformShortcut = usePlatformShortcut();
241
- const resolvedShortcut = shortcutText ?? platformShortcut;
242
- return /* @__PURE__ */ jsx(CommandDialog, {
243
- open,
244
- onOpenChange,
245
- className: cn("max-w-[508px] sm:max-w-[508px]", className),
246
- children: /* @__PURE__ */ jsx(CommandMenuBody, {
247
- placeholder,
248
- emptyText,
249
- emptyState,
250
- options,
251
- groups,
252
- onSelect,
253
- onClose: () => onOpenChange?.(false),
254
- showShortcut,
255
- shortcutText: resolvedShortcut,
256
- showFooter,
257
- footerHints,
258
- showSettingsButton,
259
- onSettingsClick,
260
- maxHeight,
261
- filter,
262
- children
263
- })
264
- });
265
- }
266
- CommandMenu.displayName = "CommandMenu";
267
- function CommandMenuPanel({ placeholder = DEFAULT_COMMAND_MENU_PLACEHOLDER, emptyText = "No results found.", emptyState, options = [], groups = [], onSelect, showShortcut = false, shortcutText, showFooter = false, footerHints, showSettingsButton = false, onSettingsClick, className, maxHeight = DEFAULT_COMMAND_MENU_MAX_HEIGHT, filter, children }) {
268
- const platformShortcut = usePlatformShortcut();
269
- const resolvedShortcut = shortcutText ?? platformShortcut;
270
- return /* @__PURE__ */ jsx("div", {
271
- "data-slot": "command-menu-panel",
272
- className: cn(COMMAND_MENU_SHELL_CLASS_NAME, className),
273
- children: /* @__PURE__ */ jsx(CommandMenuBody, {
274
- placeholder,
275
- emptyText,
276
- emptyState,
277
- options,
278
- groups,
279
- onSelect,
280
- showShortcut,
281
- shortcutText: resolvedShortcut,
282
- showFooter,
283
- footerHints,
284
- showSettingsButton,
285
- onSettingsClick,
286
- maxHeight,
287
- filter,
288
- children
289
- })
290
- });
291
- }
292
- CommandMenuPanel.displayName = "CommandMenu.Panel";
160
+ });
161
+ SectionHeader.displayName = "SectionHeader";
293
162
  //#endregion
294
- export { CommandMenu, CommandMenuFooter, CommandMenuGroupHeader, CommandMenuItem, CommandMenuPanel, CommandShortcutBadge, FooterNavIcon, FooterNavText, defaultFooterHints };
163
+ export { SectionHeader };
295
164
 
296
165
  //# sourceMappingURL=index204.js.map