@farmzone/fz-react-ui 1.1.6 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1096,18 +1096,42 @@ interface MultiTabBarProps {
1096
1096
  * 전달하지 않으면(undefined) 기존과 완전히 동일한 평면(flat) 탭 목록으로 렌더링됩니다.
1097
1097
  *
1098
1098
  * 전달하면: 같은 key를 가진 탭들이 배열 안에서 서로 떨어져 있어도(다른 그룹 탭 사이에 끼어
1099
- * 있어도) 항상 그 그룹이 처음 등장한 위치의 칩 하나로 합쳐져서 색상 칩(그룹 헤더) + 그 아래
1100
- * 탭들로 렌더링됩니다 — 지금 fizza 프로젝트가 쓰던 커스텀 그룹 탭바와 동일한 형태이고, 이미
1099
+ * 있어도) 항상 그 그룹이 처음 등장한 위치의 칩 하나로 합쳐져서 Chrome 탭 그룹처럼 색상 칩(그룹
1100
+ * 라벨) + 그 옆 탭들 + 탭들 바닥을 잇는 그룹 색 하단선으로 렌더링됩니다. 이미
1101
1101
  * 열려 있는 그룹에 새 탭이 추가될 때 중복 칩이 생기지 않습니다.
1102
1102
  * 그룹 색상은 고정된 팔레트(파랑/주황/빨강/초록 + 보조 6색)에서 등장 순서대로 할당되고,
1103
- * 배경은 12% 투명도 틴트, 테두리는 40% 투명도로 렌더링됩니다 — fizza 프로젝트가 쓰던
1104
- * GroupedTabBar와 동일한 색상 스펙입니다.
1103
+ * 칩 배경·하단선·활성 탭 테두리에 같은 그룹 색이 쓰입니다.
1105
1104
  *
1106
1105
  * onTabsReorder를 같이 전달하면 그룹 모드에서도 드래그 앤 드롭 재정렬이 됩니다. 탭이 어느
1107
1106
  * 그룹에 속하는지는 getTabGroup이 반환하는 값으로만 정해지고 배열 위치와는 무관하므로,
1108
1107
  * 자유롭게 순서를 바꿔도 그룹 소속은 항상 그대로 유지됩니다.
1109
1108
  */
1110
1109
  getTabGroup?: (tab: MultiTab) => MultiTabGroupInfo | null | undefined;
1110
+ /**
1111
+ * 탭 라벨 왼쪽에 표시할 아이콘. null/undefined면 아이콘 없이 렌더링됩니다.
1112
+ */
1113
+ getTabIcon?: (tab: MultiTab) => ReactNode;
1114
+ /**
1115
+ * 탭의 더보기 메뉴 항목 — 더보기(⋯) 버튼을 줄지는 탭마다 이 함수의 반환값으로 정합니다.
1116
+ *
1117
+ * - 항목 배열을 반환한 탭: 아이콘에 마우스를 올리면 더보기 아이콘으로 바뀌고, 클릭하면 항목들이
1118
+ * Popover 메뉴로 열립니다(아이콘이 없는 탭이면 더보기 아이콘이 항상 보입니다).
1119
+ * - null/undefined/빈 배열을 반환한 탭: 더보기 버튼 없이 아이콘만 표시됩니다.
1120
+ *
1121
+ * 예) 특정 탭에만 메뉴 제공: `getTabMenuItems={(tab) => (tab.id === "settings" ? items : null)}`
1122
+ *
1123
+ * 아이콘·메뉴 영역의 클릭·포인터 이벤트는 탭 전환이나 드래그로 이어지지 않습니다.
1124
+ */
1125
+ getTabMenuItems?: (tab: MultiTab) => Array<MultiTabMenuItem> | null | undefined;
1126
+ }
1127
+ interface MultiTabMenuItem {
1128
+ key: string;
1129
+ label: ReactNode;
1130
+ /** 라벨 앞에 표시할 아이콘 (예: <Settings size={14} />) */
1131
+ icon?: ReactNode;
1132
+ /** 현재 화면에 해당하는 항목이면 true — 배경으로 강조됩니다 */
1133
+ selected?: boolean;
1134
+ onSelect: () => void;
1111
1135
  }
1112
1136
  declare function MultiTabBar(props: MultiTabBarProps): react.JSX.Element | null;
1113
1137
 
@@ -1609,4 +1633,4 @@ declare const Z_INDEX: {
1609
1633
  };
1610
1634
  type ZIndexKey = keyof typeof Z_INDEX;
1611
1635
 
1612
- export { ArrowIcon, Badge, type BadgeProps, type BaseParams, BaseUploader, type BaseUploaderProps, BreadCrumb, type BreadCrumbItem, type BreadCrumbMenuItem, type BreadCrumbProps, type BreadCrumbRoot, Button, type ButtonProps, type ButtonSize, type ButtonVariant, type CalendarYearRange, Carousel, type CarouselProps, type CarouselRef, Checkbox, type CheckboxProps, type Column, type ConfirmOptions, DatePicker, DebouncedButton, type DebouncedButtonProps, DetailContent, type DetailContentProps, type DetailField, type DetailFieldOrSection, DetailModalFrame, type DetailMode, DetailPageFrame, Empty, ExcelUploader, FilePreviewViewer, FileUploader, type FilterRow, type FormFieldConfig, Input, type InputProps, Loading, LoadingOverlay, type LoadingOverlayProps, type LoadingProps, type MentionItem, type MenuChild, type MenuGrandchild, type MenuItem, type MenuSection, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalIconHeader, type ModalIconHeaderProps, ModalOverlay, type ModalProps, type ModalType, MultiTabBar as MultiTab, type MultiTabGroupInfo, type MultiTab as MultiTabItem, PageFilter, type PageParams, Pagination, type PaginationProps, Popover, type PopoverAlign, PopoverAnchor, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverFooter, PopoverHeader, type PopoverPosition, PopoverTitle, PopoverTrigger, Radio, RadioGroup, type RadioGroupProps, type RadioOptionType, type RadioProps, RichEditor, RichEditorContent, type RichEditorContentProps, type RichEditorHeadingLevel, type RichEditorProps, type RichEditorThemeOverride, RichEditorToolbar, type RichEditorToolbarConfig, type RichEditorToolbarProps, ScrollArea, ScrollBar, SearchAddress, type SearchAddressProps, SearchBar, type SearchBarProps, Select, Select$1 as SelectBase, SelectContent, SelectGroup, SelectItem, SelectLabel, type SelectOptionType, type SelectProps, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Sidebar, type SidebarHeaderRenderProps, type SidebarProps, SimplePopover, type SimplePopoverProps, Skeleton, type SkeletonProps, Slider, type SliderProps, type SortOption, type SortOrder, type SortParams, Spinner, type SpinnerColor, type SpinnerProps, type SpinnerSize, SubmitForm, Switch, type SwitchProps, Tab, type TabItem, type TabProps, Table, Textarea, type TextareaProps, type ToastPosition, type ToastProps, ToastProvider, type ToastType, ToggleSwitch, Tooltip, type TooltipProps, type UseParams, type UseRichEditorOptions, type UseRichEditorReturn, type YmdDateString, type ZIndexKey, Z_INDEX, buildBreadCrumbItems, buttonVariants, cn, confirmModal, findParentMenuItem, findParentMenuName, formatDate, getFileLabel, getPreviewFileType, isCalendarDayAfterMax, isDateInRange, switchTrackSizes, textVariants, toast, useBlockModalConfirm, useBreadCrumbItems, useCustomBlocker, useDetailController, useFilePreviewViewer, useModal, useMultiTabStore, useParams, useRichEditor, useScrollToTop, useStableImageSrc, useToast, validateAndFormatInput };
1636
+ export { ArrowIcon, Badge, type BadgeProps, type BaseParams, BaseUploader, type BaseUploaderProps, BreadCrumb, type BreadCrumbItem, type BreadCrumbMenuItem, type BreadCrumbProps, type BreadCrumbRoot, Button, type ButtonProps, type ButtonSize, type ButtonVariant, type CalendarYearRange, Carousel, type CarouselProps, type CarouselRef, Checkbox, type CheckboxProps, type Column, type ConfirmOptions, DatePicker, DebouncedButton, type DebouncedButtonProps, DetailContent, type DetailContentProps, type DetailField, type DetailFieldOrSection, DetailModalFrame, type DetailMode, DetailPageFrame, Empty, ExcelUploader, FilePreviewViewer, FileUploader, type FilterRow, type FormFieldConfig, Input, type InputProps, Loading, LoadingOverlay, type LoadingOverlayProps, type LoadingProps, type MentionItem, type MenuChild, type MenuGrandchild, type MenuItem, type MenuSection, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalIconHeader, type ModalIconHeaderProps, ModalOverlay, type ModalProps, type ModalType, MultiTabBar as MultiTab, type MultiTabGroupInfo, type MultiTab as MultiTabItem, type MultiTabMenuItem, PageFilter, type PageParams, Pagination, type PaginationProps, Popover, type PopoverAlign, PopoverAnchor, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverFooter, PopoverHeader, type PopoverPosition, PopoverTitle, PopoverTrigger, Radio, RadioGroup, type RadioGroupProps, type RadioOptionType, type RadioProps, RichEditor, RichEditorContent, type RichEditorContentProps, type RichEditorHeadingLevel, type RichEditorProps, type RichEditorThemeOverride, RichEditorToolbar, type RichEditorToolbarConfig, type RichEditorToolbarProps, ScrollArea, ScrollBar, SearchAddress, type SearchAddressProps, SearchBar, type SearchBarProps, Select, Select$1 as SelectBase, SelectContent, SelectGroup, SelectItem, SelectLabel, type SelectOptionType, type SelectProps, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Sidebar, type SidebarHeaderRenderProps, type SidebarProps, SimplePopover, type SimplePopoverProps, Skeleton, type SkeletonProps, Slider, type SliderProps, type SortOption, type SortOrder, type SortParams, Spinner, type SpinnerColor, type SpinnerProps, type SpinnerSize, SubmitForm, Switch, type SwitchProps, Tab, type TabItem, type TabProps, Table, Textarea, type TextareaProps, type ToastPosition, type ToastProps, ToastProvider, type ToastType, ToggleSwitch, Tooltip, type TooltipProps, type UseParams, type UseRichEditorOptions, type UseRichEditorReturn, type YmdDateString, type ZIndexKey, Z_INDEX, buildBreadCrumbItems, buttonVariants, cn, confirmModal, findParentMenuItem, findParentMenuName, formatDate, getFileLabel, getPreviewFileType, isCalendarDayAfterMax, isDateInRange, switchTrackSizes, textVariants, toast, useBlockModalConfirm, useBreadCrumbItems, useCustomBlocker, useDetailController, useFilePreviewViewer, useModal, useMultiTabStore, useParams, useRichEditor, useScrollToTop, useStableImageSrc, useToast, validateAndFormatInput };
package/dist/index.d.ts CHANGED
@@ -1096,18 +1096,42 @@ interface MultiTabBarProps {
1096
1096
  * 전달하지 않으면(undefined) 기존과 완전히 동일한 평면(flat) 탭 목록으로 렌더링됩니다.
1097
1097
  *
1098
1098
  * 전달하면: 같은 key를 가진 탭들이 배열 안에서 서로 떨어져 있어도(다른 그룹 탭 사이에 끼어
1099
- * 있어도) 항상 그 그룹이 처음 등장한 위치의 칩 하나로 합쳐져서 색상 칩(그룹 헤더) + 그 아래
1100
- * 탭들로 렌더링됩니다 — 지금 fizza 프로젝트가 쓰던 커스텀 그룹 탭바와 동일한 형태이고, 이미
1099
+ * 있어도) 항상 그 그룹이 처음 등장한 위치의 칩 하나로 합쳐져서 Chrome 탭 그룹처럼 색상 칩(그룹
1100
+ * 라벨) + 그 옆 탭들 + 탭들 바닥을 잇는 그룹 색 하단선으로 렌더링됩니다. 이미
1101
1101
  * 열려 있는 그룹에 새 탭이 추가될 때 중복 칩이 생기지 않습니다.
1102
1102
  * 그룹 색상은 고정된 팔레트(파랑/주황/빨강/초록 + 보조 6색)에서 등장 순서대로 할당되고,
1103
- * 배경은 12% 투명도 틴트, 테두리는 40% 투명도로 렌더링됩니다 — fizza 프로젝트가 쓰던
1104
- * GroupedTabBar와 동일한 색상 스펙입니다.
1103
+ * 칩 배경·하단선·활성 탭 테두리에 같은 그룹 색이 쓰입니다.
1105
1104
  *
1106
1105
  * onTabsReorder를 같이 전달하면 그룹 모드에서도 드래그 앤 드롭 재정렬이 됩니다. 탭이 어느
1107
1106
  * 그룹에 속하는지는 getTabGroup이 반환하는 값으로만 정해지고 배열 위치와는 무관하므로,
1108
1107
  * 자유롭게 순서를 바꿔도 그룹 소속은 항상 그대로 유지됩니다.
1109
1108
  */
1110
1109
  getTabGroup?: (tab: MultiTab) => MultiTabGroupInfo | null | undefined;
1110
+ /**
1111
+ * 탭 라벨 왼쪽에 표시할 아이콘. null/undefined면 아이콘 없이 렌더링됩니다.
1112
+ */
1113
+ getTabIcon?: (tab: MultiTab) => ReactNode;
1114
+ /**
1115
+ * 탭의 더보기 메뉴 항목 — 더보기(⋯) 버튼을 줄지는 탭마다 이 함수의 반환값으로 정합니다.
1116
+ *
1117
+ * - 항목 배열을 반환한 탭: 아이콘에 마우스를 올리면 더보기 아이콘으로 바뀌고, 클릭하면 항목들이
1118
+ * Popover 메뉴로 열립니다(아이콘이 없는 탭이면 더보기 아이콘이 항상 보입니다).
1119
+ * - null/undefined/빈 배열을 반환한 탭: 더보기 버튼 없이 아이콘만 표시됩니다.
1120
+ *
1121
+ * 예) 특정 탭에만 메뉴 제공: `getTabMenuItems={(tab) => (tab.id === "settings" ? items : null)}`
1122
+ *
1123
+ * 아이콘·메뉴 영역의 클릭·포인터 이벤트는 탭 전환이나 드래그로 이어지지 않습니다.
1124
+ */
1125
+ getTabMenuItems?: (tab: MultiTab) => Array<MultiTabMenuItem> | null | undefined;
1126
+ }
1127
+ interface MultiTabMenuItem {
1128
+ key: string;
1129
+ label: ReactNode;
1130
+ /** 라벨 앞에 표시할 아이콘 (예: <Settings size={14} />) */
1131
+ icon?: ReactNode;
1132
+ /** 현재 화면에 해당하는 항목이면 true — 배경으로 강조됩니다 */
1133
+ selected?: boolean;
1134
+ onSelect: () => void;
1111
1135
  }
1112
1136
  declare function MultiTabBar(props: MultiTabBarProps): react.JSX.Element | null;
1113
1137
 
@@ -1609,4 +1633,4 @@ declare const Z_INDEX: {
1609
1633
  };
1610
1634
  type ZIndexKey = keyof typeof Z_INDEX;
1611
1635
 
1612
- export { ArrowIcon, Badge, type BadgeProps, type BaseParams, BaseUploader, type BaseUploaderProps, BreadCrumb, type BreadCrumbItem, type BreadCrumbMenuItem, type BreadCrumbProps, type BreadCrumbRoot, Button, type ButtonProps, type ButtonSize, type ButtonVariant, type CalendarYearRange, Carousel, type CarouselProps, type CarouselRef, Checkbox, type CheckboxProps, type Column, type ConfirmOptions, DatePicker, DebouncedButton, type DebouncedButtonProps, DetailContent, type DetailContentProps, type DetailField, type DetailFieldOrSection, DetailModalFrame, type DetailMode, DetailPageFrame, Empty, ExcelUploader, FilePreviewViewer, FileUploader, type FilterRow, type FormFieldConfig, Input, type InputProps, Loading, LoadingOverlay, type LoadingOverlayProps, type LoadingProps, type MentionItem, type MenuChild, type MenuGrandchild, type MenuItem, type MenuSection, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalIconHeader, type ModalIconHeaderProps, ModalOverlay, type ModalProps, type ModalType, MultiTabBar as MultiTab, type MultiTabGroupInfo, type MultiTab as MultiTabItem, PageFilter, type PageParams, Pagination, type PaginationProps, Popover, type PopoverAlign, PopoverAnchor, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverFooter, PopoverHeader, type PopoverPosition, PopoverTitle, PopoverTrigger, Radio, RadioGroup, type RadioGroupProps, type RadioOptionType, type RadioProps, RichEditor, RichEditorContent, type RichEditorContentProps, type RichEditorHeadingLevel, type RichEditorProps, type RichEditorThemeOverride, RichEditorToolbar, type RichEditorToolbarConfig, type RichEditorToolbarProps, ScrollArea, ScrollBar, SearchAddress, type SearchAddressProps, SearchBar, type SearchBarProps, Select, Select$1 as SelectBase, SelectContent, SelectGroup, SelectItem, SelectLabel, type SelectOptionType, type SelectProps, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Sidebar, type SidebarHeaderRenderProps, type SidebarProps, SimplePopover, type SimplePopoverProps, Skeleton, type SkeletonProps, Slider, type SliderProps, type SortOption, type SortOrder, type SortParams, Spinner, type SpinnerColor, type SpinnerProps, type SpinnerSize, SubmitForm, Switch, type SwitchProps, Tab, type TabItem, type TabProps, Table, Textarea, type TextareaProps, type ToastPosition, type ToastProps, ToastProvider, type ToastType, ToggleSwitch, Tooltip, type TooltipProps, type UseParams, type UseRichEditorOptions, type UseRichEditorReturn, type YmdDateString, type ZIndexKey, Z_INDEX, buildBreadCrumbItems, buttonVariants, cn, confirmModal, findParentMenuItem, findParentMenuName, formatDate, getFileLabel, getPreviewFileType, isCalendarDayAfterMax, isDateInRange, switchTrackSizes, textVariants, toast, useBlockModalConfirm, useBreadCrumbItems, useCustomBlocker, useDetailController, useFilePreviewViewer, useModal, useMultiTabStore, useParams, useRichEditor, useScrollToTop, useStableImageSrc, useToast, validateAndFormatInput };
1636
+ export { ArrowIcon, Badge, type BadgeProps, type BaseParams, BaseUploader, type BaseUploaderProps, BreadCrumb, type BreadCrumbItem, type BreadCrumbMenuItem, type BreadCrumbProps, type BreadCrumbRoot, Button, type ButtonProps, type ButtonSize, type ButtonVariant, type CalendarYearRange, Carousel, type CarouselProps, type CarouselRef, Checkbox, type CheckboxProps, type Column, type ConfirmOptions, DatePicker, DebouncedButton, type DebouncedButtonProps, DetailContent, type DetailContentProps, type DetailField, type DetailFieldOrSection, DetailModalFrame, type DetailMode, DetailPageFrame, Empty, ExcelUploader, FilePreviewViewer, FileUploader, type FilterRow, type FormFieldConfig, Input, type InputProps, Loading, LoadingOverlay, type LoadingOverlayProps, type LoadingProps, type MentionItem, type MenuChild, type MenuGrandchild, type MenuItem, type MenuSection, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalIconHeader, type ModalIconHeaderProps, ModalOverlay, type ModalProps, type ModalType, MultiTabBar as MultiTab, type MultiTabGroupInfo, type MultiTab as MultiTabItem, type MultiTabMenuItem, PageFilter, type PageParams, Pagination, type PaginationProps, Popover, type PopoverAlign, PopoverAnchor, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverFooter, PopoverHeader, type PopoverPosition, PopoverTitle, PopoverTrigger, Radio, RadioGroup, type RadioGroupProps, type RadioOptionType, type RadioProps, RichEditor, RichEditorContent, type RichEditorContentProps, type RichEditorHeadingLevel, type RichEditorProps, type RichEditorThemeOverride, RichEditorToolbar, type RichEditorToolbarConfig, type RichEditorToolbarProps, ScrollArea, ScrollBar, SearchAddress, type SearchAddressProps, SearchBar, type SearchBarProps, Select, Select$1 as SelectBase, SelectContent, SelectGroup, SelectItem, SelectLabel, type SelectOptionType, type SelectProps, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Sidebar, type SidebarHeaderRenderProps, type SidebarProps, SimplePopover, type SimplePopoverProps, Skeleton, type SkeletonProps, Slider, type SliderProps, type SortOption, type SortOrder, type SortParams, Spinner, type SpinnerColor, type SpinnerProps, type SpinnerSize, SubmitForm, Switch, type SwitchProps, Tab, type TabItem, type TabProps, Table, Textarea, type TextareaProps, type ToastPosition, type ToastProps, ToastProvider, type ToastType, ToggleSwitch, Tooltip, type TooltipProps, type UseParams, type UseRichEditorOptions, type UseRichEditorReturn, type YmdDateString, type ZIndexKey, Z_INDEX, buildBreadCrumbItems, buttonVariants, cn, confirmModal, findParentMenuItem, findParentMenuName, formatDate, getFileLabel, getPreviewFileType, isCalendarDayAfterMax, isDateInRange, switchTrackSizes, textVariants, toast, useBlockModalConfirm, useBreadCrumbItems, useCustomBlocker, useDetailController, useFilePreviewViewer, useModal, useMultiTabStore, useParams, useRichEditor, useScrollToTop, useStableImageSrc, useToast, validateAndFormatInput };
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import * as React6 from 'react';
6
6
  import React6__default, { forwardRef, useState, useRef, useEffect, useImperativeHandle, useCallback, memo, createContext, useContext, useMemo, useId, useLayoutEffect, useDeferredValue, Fragment as Fragment$1 } from 'react';
7
7
  import { Slot } from '@radix-ui/react-slot';
8
8
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
9
- import { ChevronLeft, ChevronRight, FileText, ZoomIn, ZoomOut, RotateCcw, RotateCw, Download, X, Heading1, Heading2, Heading3, Heading4, Bold, Italic, Strikethrough, Code, AlignLeft, AlignCenter, AlignRight, List, ListOrdered, Quote, FileCode, Table as Table$1, Plus, Minus, Trash2, CircleX, EyeOff, Eye, Check, ChevronDown, Calendar, CircleIcon, ChevronUp, Search, TriangleAlert, Info, Pencil, BadgePlus, FileSearch2, Upload, FileUp, PanelRightClose, PanelLeftClose, ChevronFirst, ChevronLast } from 'lucide-react';
9
+ import { ChevronLeft, ChevronRight, FileText, ZoomIn, ZoomOut, RotateCcw, RotateCw, Download, X, Heading1, Heading2, Heading3, Heading4, Bold, Italic, Strikethrough, Code, AlignLeft, AlignCenter, AlignRight, List, ListOrdered, Quote, FileCode, Table as Table$1, Plus, Minus, Trash2, CircleX, EyeOff, Eye, Check, ChevronDown, Calendar, CircleIcon, ChevronUp, Search, TriangleAlert, Info, Pencil, BadgePlus, FileSearch2, Upload, FileUp, PanelRightClose, PanelLeftClose, ChevronFirst, ChevronLast, MoreHorizontal } from 'lucide-react';
10
10
  import * as SwitchPrimitive from '@radix-ui/react-switch';
11
11
  import * as RadixSlider from '@radix-ui/react-slider';
12
12
  import * as SelectPrimitive from '@radix-ui/react-select';
@@ -8036,15 +8036,15 @@ var VARIANT_STYLES = {
8036
8036
  inactiveText: "font-normal",
8037
8037
  indicator: "bg-blue-500",
8038
8038
  closeBtn: "rounded hover:bg-gray-300/60",
8039
- closeBtnWH: "w-3.5 h-3.5",
8040
- closeBtnSize: 10,
8039
+ closeBtnWH: "w-4 h-4",
8040
+ closeBtnSize: 12,
8041
8041
  plusBtnArea: "border-l border-gray-100 bg-white",
8042
8042
  plusBtn: "text-gray-400 hover:text-gray-600 hover:bg-gray-100",
8043
8043
  fadeOpacity: 0.12,
8044
- tabPy: "py-1.5",
8045
- tabPx: "px-3",
8046
- tabTextSize: "text-xs",
8047
- scrollPadding: "px-3 pt-1.5",
8044
+ tabHeight: "h-[38px]",
8045
+ tabPx: "px-4",
8046
+ tabTextSize: "text-sm",
8047
+ scrollPadding: "px-3 pt-2",
8048
8048
  rounded: "rounded-t-md"
8049
8049
  },
8050
8050
  dark: {
@@ -8055,15 +8055,15 @@ var VARIANT_STYLES = {
8055
8055
  inactiveText: "font-normal",
8056
8056
  indicator: "bg-indigo-400",
8057
8057
  closeBtn: "rounded hover:bg-gray-600/60",
8058
- closeBtnWH: "w-3.5 h-3.5",
8059
- closeBtnSize: 10,
8058
+ closeBtnWH: "w-4 h-4",
8059
+ closeBtnSize: 12,
8060
8060
  plusBtnArea: "border-l border-gray-700 bg-gray-900",
8061
8061
  plusBtn: "text-gray-500 hover:text-gray-300 hover:bg-gray-700",
8062
8062
  fadeOpacity: 0.4,
8063
- tabPy: "py-1.5",
8064
- tabPx: "px-3",
8065
- tabTextSize: "text-xs",
8066
- scrollPadding: "px-3 pt-1.5",
8063
+ tabHeight: "h-[38px]",
8064
+ tabPx: "px-4",
8065
+ tabTextSize: "text-sm",
8066
+ scrollPadding: "px-3 pt-2",
8067
8067
  rounded: "rounded-t-md"
8068
8068
  },
8069
8069
  "system-light": {
@@ -8079,7 +8079,7 @@ var VARIANT_STYLES = {
8079
8079
  plusBtnArea: "border-l border-gray-300 bg-gray-200",
8080
8080
  plusBtn: "text-slate-400 hover:text-slate-600 hover:bg-gray-300",
8081
8081
  fadeOpacity: 0.15,
8082
- tabPy: "py-2.5",
8082
+ tabHeight: "h-[38px]",
8083
8083
  tabPx: "px-5",
8084
8084
  tabTextSize: "text-sm",
8085
8085
  scrollPadding: "px-3 pt-2",
@@ -8098,7 +8098,7 @@ var VARIANT_STYLES = {
8098
8098
  plusBtnArea: "border-l border-slate-700 bg-slate-900",
8099
8099
  plusBtn: "text-slate-400 hover:text-slate-200 hover:bg-slate-700",
8100
8100
  fadeOpacity: 0.45,
8101
- tabPy: "py-2.5",
8101
+ tabHeight: "h-[38px]",
8102
8102
  tabPx: "px-5",
8103
8103
  tabTextSize: "text-sm",
8104
8104
  scrollPadding: "px-4 pt-2",
@@ -8110,6 +8110,65 @@ function easedFade(dir, opacity) {
8110
8110
  const c = (t) => `rgba(0,0,0,${(opacity * t).toFixed(3)})`;
8111
8111
  return `linear-gradient(${dir}, ${c(1)} 0%, ${c(0.72)} 20%, ${c(0.38)} 45%, ${c(0.1)} 70%, transparent 100%)`;
8112
8112
  }
8113
+ var MENU_ITEM_CLASSNAME = "flex w-full cursor-pointer items-center gap-2 rounded-md border-none bg-transparent px-2 py-1.5 text-left text-[13px] whitespace-nowrap text-gray-900 hover:bg-gray-100";
8114
+ function TabIconMenu(props) {
8115
+ const { icon, items, label } = props;
8116
+ const [open, setOpen] = useState(false);
8117
+ if (items.length === 0) {
8118
+ return /* @__PURE__ */ jsx("span", { className: "flex h-4.5 w-4.5 items-center justify-center", children: icon });
8119
+ }
8120
+ const showMore = (base) => open ? "flex" : base;
8121
+ return /* @__PURE__ */ jsx(
8122
+ SimplePopover,
8123
+ {
8124
+ open,
8125
+ onOpenChange: setOpen,
8126
+ align: "start",
8127
+ contentClassName: "w-auto min-w-28 p-1",
8128
+ trigger: /* @__PURE__ */ jsxs(
8129
+ "button",
8130
+ {
8131
+ type: "button",
8132
+ "aria-label": `${label} \uBA54\uB274`,
8133
+ className: "group/tab-menu relative flex h-4.5 w-4.5 cursor-pointer items-center justify-center rounded border-none bg-transparent p-0",
8134
+ children: [
8135
+ icon != null && /* @__PURE__ */ jsx(
8136
+ "span",
8137
+ {
8138
+ className: `flex items-center justify-center ${open ? "invisible" : "group-hover/tab-menu:invisible"}`,
8139
+ children: icon
8140
+ }
8141
+ ),
8142
+ /* @__PURE__ */ jsx(
8143
+ "span",
8144
+ {
8145
+ className: `absolute inset-0 items-center justify-center rounded bg-gray-200 text-gray-700 ${icon != null ? showMore("hidden group-hover/tab-menu:flex") : "flex"}`,
8146
+ children: /* @__PURE__ */ jsx(MoreHorizontal, { size: 14 })
8147
+ }
8148
+ )
8149
+ ]
8150
+ }
8151
+ ),
8152
+ children: items.map((item) => /* @__PURE__ */ jsxs(
8153
+ "button",
8154
+ {
8155
+ type: "button",
8156
+ onClick: () => {
8157
+ setOpen(false);
8158
+ item.onSelect();
8159
+ },
8160
+ className: MENU_ITEM_CLASSNAME,
8161
+ style: item.selected ? { backgroundColor: "#F3F4F6" } : void 0,
8162
+ children: [
8163
+ item.icon != null && /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center text-gray-500", children: item.icon }),
8164
+ item.label
8165
+ ]
8166
+ },
8167
+ item.key
8168
+ ))
8169
+ }
8170
+ );
8171
+ }
8113
8172
  function clusterTabs(tabs, getTabGroup) {
8114
8173
  const clusters = [];
8115
8174
  const clusterByGroupKey = /* @__PURE__ */ new Map();
@@ -8177,8 +8236,13 @@ function MultiTabPill(props) {
8177
8236
  draggable = false,
8178
8237
  onPointerDown,
8179
8238
  dropIndicator = null,
8180
- isDraggingThis = false
8239
+ isDraggingThis = false,
8240
+ icon,
8241
+ menuItems,
8242
+ groupColor
8181
8243
  } = props;
8244
+ const hasPrefix = icon != null || (menuItems?.length ?? 0) > 0;
8245
+ const outlinedByGroup = isActive && !!groupColor;
8182
8246
  return /* @__PURE__ */ jsxs(
8183
8247
  "div",
8184
8248
  {
@@ -8188,7 +8252,7 @@ function MultiTabPill(props) {
8188
8252
  if (!isActive) onClick();
8189
8253
  },
8190
8254
  className: `
8191
- group relative flex items-center gap-1.5 ${s.tabPx} ${s.tabPy} flex-shrink-0
8255
+ group relative flex items-center gap-1.5 ${s.tabPx} ${s.tabHeight} flex-shrink-0
8192
8256
  ${s.rounded} border border-b-0 select-none
8193
8257
  transition-colors duration-100
8194
8258
  ${isActive ? s.activeTab : s.inactiveTab}
@@ -8196,7 +8260,9 @@ function MultiTabPill(props) {
8196
8260
  ${isDraggingThis ? "opacity-40" : ""}
8197
8261
  ${dropIndicator === "before" ? "[box-shadow:inset_2px_0_0_0_#3b82f6]" : ""}
8198
8262
  ${dropIndicator === "after" ? "[box-shadow:inset_-2px_0_0_0_#3b82f6]" : ""}
8263
+ ${outlinedByGroup ? "z-[2]" : ""}
8199
8264
  `,
8265
+ style: outlinedByGroup ? { borderColor: groupColor } : void 0,
8200
8266
  children: [
8201
8267
  isActive && /* @__PURE__ */ jsx(
8202
8268
  "div",
@@ -8205,6 +8271,15 @@ function MultiTabPill(props) {
8205
8271
  style: accentColor ? { backgroundColor: accentColor } : void 0
8206
8272
  }
8207
8273
  ),
8274
+ hasPrefix && /* @__PURE__ */ jsx(
8275
+ "span",
8276
+ {
8277
+ className: "flex flex-shrink-0 items-center",
8278
+ onPointerDown: (e) => e.stopPropagation(),
8279
+ onClick: (e) => e.stopPropagation(),
8280
+ children: /* @__PURE__ */ jsx(TabIconMenu, { icon, items: menuItems ?? [], label: tab.label })
8281
+ }
8282
+ ),
8208
8283
  /* @__PURE__ */ jsx("span", { className: `${s.tabTextSize} max-w-35 truncate leading-none ${isActive ? s.activeText : s.inactiveText}`, children: tab.label }),
8209
8284
  showClose && /* @__PURE__ */ jsx(
8210
8285
  "button",
@@ -8236,7 +8311,9 @@ function MultiTabBar(props) {
8236
8311
  onTabsReorder,
8237
8312
  variant = "light",
8238
8313
  primaryColor,
8239
- getTabGroup
8314
+ getTabGroup,
8315
+ getTabIcon,
8316
+ getTabMenuItems
8240
8317
  } = props;
8241
8318
  const s = VARIANT_STYLES[variant];
8242
8319
  const scrollRef = useRef(null);
@@ -8499,9 +8576,9 @@ function MultiTabBar(props) {
8499
8576
  const draggingGroupColor = draggingGroupKey ? groupColors.get(draggingGroupKey) : void 0;
8500
8577
  const ghost = draggingGroupKey && draggingGroupCluster?.group ? {
8501
8578
  label: draggingGroupCluster.group.label,
8502
- bg: (draggingGroupColor ?? TAB_PALETTE[0]).bg,
8503
- border: (draggingGroupColor ?? TAB_PALETTE[0]).border,
8504
- color: (draggingGroupColor ?? TAB_PALETTE[0]).base
8579
+ bg: (draggingGroupColor ?? TAB_PALETTE[0]).base,
8580
+ border: (draggingGroupColor ?? TAB_PALETTE[0]).base,
8581
+ color: "white"
8505
8582
  } : draggingTab ? { label: draggingTab.label, bg: "white", border: draggingColor ?? "#e5e7eb", color: "#111827" } : null;
8506
8583
  if (tabs.length === 0) return null;
8507
8584
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -8552,7 +8629,9 @@ function MultiTabBar(props) {
8552
8629
  draggable: reorderEnabled,
8553
8630
  isDraggingThis: tab.id === draggingId,
8554
8631
  dropIndicator: isDropTarget ? dropSide : isGroupDropTarget2 ? groupDropSide : null,
8555
- onPointerDown: (e) => handlePointerDown(e, tab.id)
8632
+ onPointerDown: (e) => handlePointerDown(e, tab.id),
8633
+ icon: getTabIcon?.(tab),
8634
+ menuItems: getTabMenuItems?.(tab)
8556
8635
  },
8557
8636
  tab.id
8558
8637
  );
@@ -8561,76 +8640,76 @@ function MultiTabBar(props) {
8561
8640
  const { key, label } = cluster.group;
8562
8641
  const color = groupColors.get(key) ?? TAB_PALETTE[0];
8563
8642
  const collapsed = collapsedGroups.has(key);
8564
- const groupHasActiveTab = cluster.tabs.some((t) => t.id === activeTabId);
8565
8643
  const isGroupDropTarget = groupDropTargetKey === `group:${key}`;
8566
8644
  const isDraggingThisGroup = draggingGroupKey === key;
8567
8645
  return /* @__PURE__ */ jsxs(
8568
8646
  "div",
8569
8647
  {
8570
8648
  ref: (el) => registerGroupRef(key, el),
8571
- className: "flex shrink-0 flex-col items-stretch",
8649
+ className: `relative flex shrink-0 items-end gap-0.5 ${isDraggingThisGroup ? "opacity-40" : ""} ${isGroupDropTarget && groupDropSide === "before" ? "[box-shadow:inset_2px_0_0_0_#3b82f6]" : ""} ${isGroupDropTarget && groupDropSide === "after" ? "[box-shadow:inset_-2px_0_0_0_#3b82f6]" : ""}`,
8572
8650
  children: [
8573
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
8574
- /* @__PURE__ */ jsxs(
8575
- "button",
8651
+ /* @__PURE__ */ jsx("div", { className: `flex ${s.tabHeight} shrink-0 items-center px-1`, children: /* @__PURE__ */ jsxs(
8652
+ "button",
8653
+ {
8654
+ type: "button",
8655
+ onClick: () => {
8656
+ if (suppressClickRef.current) return;
8657
+ toggleGroupCollapsed(key);
8658
+ },
8659
+ onPointerDown: reorderEnabled ? (e) => handleGroupPointerDown(e, key) : void 0,
8660
+ "aria-expanded": !collapsed,
8661
+ title: collapsed ? "\uD558\uC704 \uD0ED \uD3BC\uCE58\uAE30" : "\uD558\uC704 \uD0ED \uC811\uAE30",
8662
+ className: `flex h-6.5 items-center gap-1 rounded-lg px-2.5 text-sm font-semibold whitespace-nowrap text-white select-none ${reorderEnabled ? isDraggingThisGroup ? "cursor-grabbing" : "cursor-grab" : "cursor-pointer"}`,
8663
+ style: { backgroundColor: color.base },
8664
+ children: [
8665
+ collapsed ? /* @__PURE__ */ jsx(ChevronRight, { size: 14 }) : /* @__PURE__ */ jsx(ChevronDown, { size: 14 }),
8666
+ label,
8667
+ canClose && /* @__PURE__ */ jsx(
8668
+ X,
8669
+ {
8670
+ size: 14,
8671
+ onClick: (e) => {
8672
+ e.stopPropagation();
8673
+ cluster.tabs.forEach((t) => onTabClose(t.id));
8674
+ }
8675
+ }
8676
+ )
8677
+ ]
8678
+ }
8679
+ ) }),
8680
+ !collapsed && cluster.tabs.map((tab) => {
8681
+ const isDropTarget = dropTargetId === tab.id;
8682
+ const isTabGroupDropTarget = groupDropTargetKey === `tab:${tab.id}`;
8683
+ return /* @__PURE__ */ jsx(
8684
+ MultiTabPill,
8576
8685
  {
8577
- type: "button",
8686
+ tab,
8687
+ isActive: tab.id === activeTabId,
8688
+ showClose: canClose,
8689
+ accentColor: color.base,
8690
+ style: s,
8578
8691
  onClick: () => {
8579
8692
  if (suppressClickRef.current) return;
8580
- toggleGroupCollapsed(key);
8581
- },
8582
- onPointerDown: reorderEnabled ? (e) => handleGroupPointerDown(e, key) : void 0,
8583
- "aria-expanded": !collapsed,
8584
- title: collapsed ? "\uD558\uC704 \uD0ED \uD3BC\uCE58\uAE30" : "\uD558\uC704 \uD0ED \uC811\uAE30",
8585
- className: `flex items-center gap-1 rounded-md border px-2.5 py-1 text-xs font-bold whitespace-nowrap select-none ${reorderEnabled ? isDraggingThisGroup ? "cursor-grabbing" : "cursor-grab" : "cursor-pointer"} ${isDraggingThisGroup ? "opacity-40" : ""} ${isGroupDropTarget && groupDropSide === "before" ? "[box-shadow:inset_2px_0_0_0_#3b82f6]" : ""} ${isGroupDropTarget && groupDropSide === "after" ? "[box-shadow:inset_-2px_0_0_0_#3b82f6]" : ""}`,
8586
- style: { backgroundColor: color.bg, borderColor: color.border, color: color.base },
8587
- children: [
8588
- collapsed ? /* @__PURE__ */ jsx(ChevronRight, { size: 12 }) : /* @__PURE__ */ jsx(ChevronDown, { size: 12 }),
8589
- label,
8590
- canClose && /* @__PURE__ */ jsx(
8591
- X,
8592
- {
8593
- size: 12,
8594
- onClick: (e) => {
8595
- e.stopPropagation();
8596
- cluster.tabs.forEach((t) => onTabClose(t.id));
8597
- }
8598
- }
8599
- )
8600
- ]
8601
- }
8602
- ),
8603
- !collapsed && cluster.tabs.map((tab) => {
8604
- const isDropTarget = dropTargetId === tab.id;
8605
- const isTabGroupDropTarget = groupDropTargetKey === `tab:${tab.id}`;
8606
- return /* @__PURE__ */ jsx(
8607
- MultiTabPill,
8608
- {
8609
- tab,
8610
- isActive: tab.id === activeTabId,
8611
- showClose: canClose,
8612
- accentColor: color.base,
8613
- style: s,
8614
- onClick: () => {
8615
- if (suppressClickRef.current) return;
8616
- onTabClick(tab.id);
8617
- },
8618
- onClose: () => onTabClose(tab.id),
8619
- registerRef: registerTabRef,
8620
- draggable: reorderEnabled,
8621
- isDraggingThis: tab.id === draggingId,
8622
- dropIndicator: isDropTarget ? dropSide : isTabGroupDropTarget ? groupDropSide : null,
8623
- onPointerDown: (e) => handlePointerDown(e, tab.id)
8693
+ onTabClick(tab.id);
8624
8694
  },
8625
- tab.id
8626
- );
8627
- })
8628
- ] }),
8629
- /* @__PURE__ */ jsx(
8695
+ onClose: () => onTabClose(tab.id),
8696
+ registerRef: registerTabRef,
8697
+ draggable: reorderEnabled,
8698
+ isDraggingThis: tab.id === draggingId,
8699
+ dropIndicator: isDropTarget ? dropSide : isTabGroupDropTarget ? groupDropSide : null,
8700
+ onPointerDown: (e) => handlePointerDown(e, tab.id),
8701
+ icon: getTabIcon?.(tab),
8702
+ menuItems: getTabMenuItems?.(tab),
8703
+ groupColor: color.base
8704
+ },
8705
+ tab.id
8706
+ );
8707
+ }),
8708
+ !collapsed && /* @__PURE__ */ jsx(
8630
8709
  "div",
8631
8710
  {
8632
- className: "mt-1 h-0.75 rounded-full",
8633
- style: { backgroundColor: color.base, opacity: groupHasActiveTab ? 1 : 0.35 }
8711
+ className: "pointer-events-none absolute right-0 bottom-0 left-1 z-[1] h-0.5 rounded-l-full",
8712
+ style: { backgroundColor: color.base }
8634
8713
  }
8635
8714
  )
8636
8715
  ]
@@ -8656,7 +8735,9 @@ function MultiTabBar(props) {
8656
8735
  draggable: reorderEnabled,
8657
8736
  isDraggingThis: tab.id === draggingId,
8658
8737
  dropIndicator: isDropTarget ? dropSide : null,
8659
- onPointerDown: (e) => handlePointerDown(e, tab.id)
8738
+ onPointerDown: (e) => handlePointerDown(e, tab.id),
8739
+ icon: getTabIcon?.(tab),
8740
+ menuItems: getTabMenuItems?.(tab)
8660
8741
  },
8661
8742
  tab.id
8662
8743
  );
@@ -8684,7 +8765,7 @@ function MultiTabBar(props) {
8684
8765
  /* @__PURE__ */ jsx(
8685
8766
  "div",
8686
8767
  {
8687
- className: "pointer-events-none fixed z-50 flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-bold whitespace-nowrap shadow-lg",
8768
+ className: "pointer-events-none fixed z-50 flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-bold whitespace-nowrap shadow-lg",
8688
8769
  style: {
8689
8770
  left: dragPos.x + 12,
8690
8771
  top: dragPos.y + 12,