flowcloudai-ui 0.1.4 → 0.1.5

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.css CHANGED
@@ -1846,6 +1846,8 @@
1846
1846
  --tab-active-color: var(--fc-color-primary);
1847
1847
  --tab-active-bg: var(--fc-color-bg);
1848
1848
  --tab-active-indicator: var(--fc-color-primary);
1849
+ --tab-min-width: 8rem;
1850
+ --tab-max-width: 18rem;
1849
1851
  --tab-bar-radius-tl: var(--fc-radius-md);
1850
1852
  --tab-bar-radius-tr: var(--fc-radius-md);
1851
1853
  --tab-bar-radius-br: 0px;
@@ -1892,27 +1894,18 @@
1892
1894
  display: flex;
1893
1895
  align-items: stretch;
1894
1896
  }
1895
- .fc-tab-bar__nav-outer--scroll {
1896
- overflow: hidden;
1897
- }
1898
- .fc-tab-bar__nav {
1899
- flex: 1;
1900
- min-width: 0;
1897
+ .fc-tab-bar__nav-wrap {
1901
1898
  display: flex;
1902
1899
  align-items: stretch;
1903
- position: relative;
1904
- z-index: 0;
1905
1900
  }
1906
- .fc-tab-bar__nav--scroll {
1907
- overflow: hidden;
1908
- flex-shrink: 0;
1901
+ .fc-tab-bar__nav-wrap--scroll {
1902
+ flex: 1;
1903
+ min-width: 0;
1904
+ overflow-x: auto;
1905
+ scrollbar-width: none;
1909
1906
  }
1910
- .fc-tab-bar__nav-wrap {
1911
- display: flex;
1912
- gap: 0;
1913
- align-items: stretch;
1914
- max-width: 100%;
1915
- box-sizing: border-box;
1907
+ .fc-tab-bar__nav-wrap--scroll::-webkit-scrollbar {
1908
+ display: none;
1916
1909
  }
1917
1910
  .fc-tab-bar__tab {
1918
1911
  position: relative;
@@ -1929,11 +1922,13 @@
1929
1922
  border: none;
1930
1923
  user-select: none;
1931
1924
  border-radius: var(--tab-item-radius-tl) var(--tab-item-radius-tr) var(--tab-item-radius-br) var(--tab-item-radius-bl);
1925
+ flex: 1 1 var(--tab-max-width);
1926
+ min-width: var(--tab-min-width);
1927
+ max-width: var(--tab-max-width);
1928
+ overflow: hidden;
1929
+ box-sizing: border-box;
1932
1930
  }
1933
- .fc-tab-bar__nav--scroll .fc-tab-bar__tab {
1934
- justify-content: space-between;
1935
- }
1936
- .fc-tab-bar__tab:hover:not(.fc-tab-bar__tab--disabled):not(.fc-tab-bar__tab--dragging) {
1931
+ .fc-tab-bar__tab:hover:not(.fc-tab-bar__tab--disabled):not(.fc-tab-bar__tab--dragging):not(.fc-tab-bar__tab--active) {
1937
1932
  color: var(--tab-hover-color);
1938
1933
  background-color: var(--tab-hover-bg);
1939
1934
  }
@@ -1946,6 +1941,13 @@
1946
1941
  cursor: not-allowed;
1947
1942
  opacity: 0.6;
1948
1943
  }
1944
+ .fc-tab-bar__tab-label {
1945
+ flex: 1;
1946
+ min-width: 0;
1947
+ overflow: hidden;
1948
+ white-space: nowrap;
1949
+ text-overflow: ellipsis;
1950
+ }
1949
1951
  .fc-tab-bar--attached {
1950
1952
  border-bottom: 2px solid var(--fc-color-border);
1951
1953
  }
@@ -2022,31 +2024,10 @@
2022
2024
  .fc-tab-bar__add-btn {
2023
2025
  -webkit-app-region: no-drag;
2024
2026
  }
2025
- .fc-tab-bar--shrink .fc-tab-bar__tab {
2026
- overflow: hidden;
2027
- min-width: 0;
2028
- }
2029
- .fc-tab-bar--shrink .fc-tab-bar__tab[data-compact=true] {
2030
- padding-left: var(--fc-space-xs, 6px);
2031
- padding-right: var(--fc-space-xs, 6px);
2032
- }
2033
- .fc-tab-bar--shrink .fc-tab-bar__tab-label {
2034
- flex: 1;
2035
- min-width: 0;
2027
+ .fc-tab-bar__drag-handle {
2028
+ flex: 0 0 0px;
2036
2029
  overflow: hidden;
2037
- white-space: nowrap;
2038
- -webkit-mask-image:
2039
- linear-gradient(
2040
- to right,
2041
- black 0%,
2042
- black calc(100% - 20px),
2043
- transparent 100%);
2044
- mask-image:
2045
- linear-gradient(
2046
- to right,
2047
- black 0%,
2048
- black calc(100% - 20px),
2049
- transparent 100%);
2030
+ -webkit-app-region: drag;
2050
2031
  }
2051
2032
  .fc-tab-bar__tab--draggable {
2052
2033
  cursor: default;
@@ -2076,6 +2057,7 @@
2076
2057
  align-items: center;
2077
2058
  justify-content: center;
2078
2059
  width: 32px;
2060
+ flex-shrink: 0;
2079
2061
  margin: 0 var(--fc-space-sm, 8px);
2080
2062
  font-size: 20px;
2081
2063
  font-weight: bold;
@@ -2092,24 +2074,9 @@
2092
2074
  .fc-tab-bar--floating .fc-tab-bar__add-btn {
2093
2075
  border-radius: var(--fc-radius-full, 9999px);
2094
2076
  }
2095
- [data-theme=dark] .fc-tab-bar--attached {
2096
- border-bottom-color: var(--fc-color-border);
2097
- }
2098
- [data-theme=dark] .fc-tab-bar__tab--active {
2099
- background-color: var(--tab-active-bg);
2100
- }
2101
- [data-theme=dark] .fc-tab-bar__tab:hover:not(.fc-tab-bar__tab--disabled) {
2102
- background-color: var(--tab-hover-bg);
2103
- }
2104
2077
  [data-theme=dark] .fc-tab-bar--floating .fc-tab-bar__tab--active {
2105
2078
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
2106
2079
  }
2107
- [data-theme=dark] .fc-tab-bar__add-btn:hover {
2108
- background-color: var(--fc-color-bg-tertiary);
2109
- }
2110
- [data-theme=dark] .fc-tab-bar__tab-close:hover {
2111
- background-color: var(--fc-color-border-light);
2112
- }
2113
2080
  @media (max-width: 768px) {
2114
2081
  .fc-tab-bar__tab {
2115
2082
  padding: var(--fc-space-xs, 6px) var(--fc-space-md, 12px);
package/dist/index.d.ts CHANGED
@@ -423,87 +423,41 @@ interface CardProps {
423
423
  declare const Card: ({ image, imageSlot, imageHeight, title, description, actions, extraInfo, variant, hoverable, disabled, className, style, onClick, }: CardProps) => react_jsx_runtime.JSX.Element;
424
424
 
425
425
  interface TabItem {
426
- /** 唯一标识 */
427
426
  key: string;
428
- /** 标签显示内容 */
429
427
  label: React__default.ReactNode;
430
- /** 是否禁用 */
431
428
  disabled?: boolean;
432
- /** 是否可关闭(覆盖全局 closable) */
433
429
  closable?: boolean;
434
430
  }
435
431
  interface TabBarProps {
436
- /** Tab 列表(受控) */
437
432
  items: TabItem[];
438
- /** 当前激活的 Tab key(受控) */
439
433
  activeKey: string;
440
- /**
441
- * 布局变体
442
- * - attached: 贴合模式 — 标签底部紧贴导航栏下边缘,底部线条作为激活指示器
443
- * - floating: 悬浮模式 — 标签垂直居中悬浮,胶囊形态,背景填充作为激活指示器
444
- * @default 'attached'
445
- */
446
434
  variant?: 'attached' | 'floating';
447
- /** TabBar 容器圆角 */
448
435
  radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
449
- /** 单个 Tab 项的圆角(仅在 floating 模式下或需要四周圆角时使用) */
450
436
  tabRadius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
451
- /** 是否显示关闭按钮 */
452
437
  closable?: boolean;
453
- /** 是否显示添加按钮 */
454
438
  addable?: boolean;
455
- /** 是否启用拖拽排序 */
456
439
  draggable?: boolean;
457
- /**
458
- * Tab 最小宽度比例(相对 window.innerWidth)。
459
- * 当均分后每个 Tab 宽度 < window.innerWidth * minWidthRatio 时,切换为横向滚动模式。
460
- * @default 0.07
461
- */
462
- minWidthRatio?: number;
463
- /**
464
- * Tab 最大宽度比例(相对 window.innerWidth)。
465
- * 在固定模式下,单个 Tab 的宽度不会超过此值,防止子项很少时占满过多空间。
466
- * @default 0.15
467
- */
468
- maxTabWidthRatio?: number;
440
+ minTabWidth?: number;
441
+ maxTabWidth?: number;
469
442
  onChange: (activeKey: string) => void;
470
443
  onClose?: (key: string) => void;
471
444
  onAdd?: () => void;
472
445
  onReorder?: (reorderedItems: TabItem[]) => void;
473
- /** 每个 Tab 的自定义 className */
474
446
  tabClassName?: string;
475
- /** 激活态 Tab 的额外 className */
476
447
  activeTabClassName?: string;
477
- /** 每个 Tab 的自定义 inline style */
478
448
  tabStyle?: React__default.CSSProperties;
479
- /** 激活态 Tab 的自定义 inline style(会合并到 tabStyle 之上) */
480
449
  activeTabStyle?: React__default.CSSProperties;
481
- /** 自定义关闭图标渲染 */
482
450
  renderCloseIcon?: (key: string) => React__default.ReactNode;
483
- /** 自定义添加按钮渲染 */
484
451
  renderAddButton?: () => React__default.ReactNode;
485
452
  className?: string;
486
453
  style?: React__default.CSSProperties;
487
- /** 容器背景色 */
488
454
  background?: string;
489
- /** 标签默认文字色 */
490
455
  tabColor?: string;
491
- /** 标签 hover 文字色 */
492
456
  tabHoverColor?: string;
493
- /** 标签 hover 背景色 */
494
457
  tabHoverBackground?: string;
495
- /** 激活态文字色 */
496
458
  tabActiveColor?: string;
497
- /** 激活态背景色 */
498
459
  tabActiveBackground?: string;
499
- /** 激活态指示器颜色(attached 模式底线 / floating 模式无效) */
500
460
  activeIndicatorColor?: string;
501
- /**
502
- * 将 TabBar 空白区域标记为 Tauri 窗口拖拽区域。
503
- * 开启后,标签之外的空白处可拖动窗口;标签、关闭、添加按钮已内置 no-drag 保护。
504
- * @default false
505
- */
506
- tauriDragRegion?: boolean;
507
461
  }
508
462
  declare const TabBar: React__default.NamedExoticComponent<TabBarProps>;
509
463
 
package/dist/index.js CHANGED
@@ -2025,113 +2025,13 @@ var Card = ({
2025
2025
  };
2026
2026
 
2027
2027
  // src/components/Bar/TabBar.tsx
2028
- import { useRef as useRef8, useCallback as useCallback9, memo as memo4, useEffect as useEffect9 } from "react";
2029
-
2030
- // src/components/Bar/useAdaptiveTabLayout.ts
2031
- import { useState as useState13, useRef as useRef7, useCallback as useCallback8, useEffect as useEffect8 } from "react";
2032
- function useAdaptiveTabLayout(navRef, options) {
2033
- const { itemsLength, addable, minWidthRatio, maxTabWidthRatio } = options;
2034
- const itemsLengthRef = useRef7(itemsLength);
2035
- itemsLengthRef.current = itemsLength;
2036
- const addableRef = useRef7(addable);
2037
- addableRef.current = addable;
2038
- const minWidthRatioRef = useRef7(minWidthRatio);
2039
- minWidthRatioRef.current = minWidthRatio;
2040
- const maxTabWidthRatioRef = useRef7(maxTabWidthRatio);
2041
- maxTabWidthRatioRef.current = maxTabWidthRatio;
2042
- const [layout, setLayout] = useState13({ scrollMode: false, tabWidth: void 0 });
2043
- const rafRef = useRef7(null);
2044
- const lastLayoutRef = useRef7({ scrollMode: false, tabWidth: void 0 });
2045
- const addBtnWidthRef = useRef7(0);
2046
- const lastAddableRef = useRef7(void 0);
2047
- const calculate = useCallback8(() => {
2048
- const navOuter = navRef.current?.parentElement;
2049
- const nav = navRef.current;
2050
- const currentItemsLength = itemsLengthRef.current;
2051
- const currentAddable = addableRef.current;
2052
- const currentMinWidthRatio = minWidthRatioRef.current;
2053
- const currentMaxTabWidthRatio = maxTabWidthRatioRef.current;
2054
- if (!nav || !navOuter || currentItemsLength === 0) return;
2055
- if (currentAddable !== lastAddableRef.current) {
2056
- lastAddableRef.current = currentAddable;
2057
- if (currentAddable) {
2058
- const addBtnElement = navOuter.querySelector(".fc-tab-bar__add-btn");
2059
- if (addBtnElement) {
2060
- const btnStyle = getComputedStyle(addBtnElement);
2061
- const marginL = parseFloat(btnStyle.marginLeft) || 0;
2062
- const marginR = parseFloat(btnStyle.marginRight) || 0;
2063
- addBtnWidthRef.current = addBtnElement.getBoundingClientRect().width + marginL + marginR;
2064
- }
2065
- } else {
2066
- addBtnWidthRef.current = 0;
2067
- }
2068
- }
2069
- const navOuterCS = getComputedStyle(navOuter);
2070
- const navWrap = nav.querySelector(".fc-tab-bar__nav-wrap");
2071
- const navOuterW = navOuter.clientWidth - parseFloat(navOuterCS.paddingLeft) - parseFloat(navOuterCS.paddingRight);
2072
- const navW = navOuterW - addBtnWidthRef.current;
2073
- const tabGap = navWrap ? parseFloat(getComputedStyle(navWrap).gap) : 0;
2074
- const totalGapWidth = (currentItemsLength - 1) * tabGap;
2075
- const idealW = (navW - totalGapWidth) / currentItemsLength;
2076
- const threshold = screen.width * currentMinWidthRatio;
2077
- const maxAllowedWidth = screen.width * currentMaxTabWidthRatio;
2078
- const minAllowedWidth = 42;
2079
- const prev = lastLayoutRef.current;
2080
- const hysteresisFactor = 1.1;
2081
- let newScrollMode;
2082
- let newTabWidth;
2083
- if (idealW < threshold) {
2084
- newScrollMode = true;
2085
- newTabWidth = Math.max(threshold, minAllowedWidth);
2086
- } else if (prev.scrollMode && idealW < threshold * hysteresisFactor) {
2087
- newScrollMode = true;
2088
- newTabWidth = Math.max(threshold, minAllowedWidth);
2089
- } else {
2090
- newScrollMode = false;
2091
- newTabWidth = Math.min(Math.max(idealW, minAllowedWidth), maxAllowedWidth);
2092
- }
2093
- if (prev.tabWidth !== newTabWidth || prev.scrollMode !== newScrollMode) {
2094
- const newLayout = { scrollMode: newScrollMode, tabWidth: newTabWidth };
2095
- lastLayoutRef.current = newLayout;
2096
- setLayout(newLayout);
2097
- }
2098
- }, [navRef]);
2099
- const calculateRef = useRef7(calculate);
2100
- calculateRef.current = calculate;
2101
- useEffect8(() => {
2102
- const navOuter = navRef.current?.parentElement;
2103
- if (!navOuter) return;
2104
- const ro = new ResizeObserver(() => {
2105
- if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
2106
- rafRef.current = requestAnimationFrame(() => {
2107
- rafRef.current = null;
2108
- calculateRef.current();
2109
- });
2110
- });
2111
- ro.observe(navOuter);
2112
- rafRef.current = requestAnimationFrame(() => {
2113
- rafRef.current = null;
2114
- calculateRef.current();
2115
- });
2116
- return () => {
2117
- ro.disconnect();
2118
- if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
2119
- };
2120
- }, []);
2121
- useEffect8(() => {
2122
- calculate();
2123
- }, [itemsLength, calculate]);
2124
- return layout;
2125
- }
2126
-
2127
- // src/components/Bar/TabBar.tsx
2028
+ import { useRef as useRef7, useCallback as useCallback8, memo as memo4, useEffect as useEffect8 } from "react";
2128
2029
  import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2129
2030
  var TabItemView = memo4(({
2130
2031
  item,
2131
2032
  isActive,
2132
2033
  closable,
2133
2034
  draggable,
2134
- tabWidth,
2135
2035
  tabClassName,
2136
2036
  activeTabClassName,
2137
2037
  tabStyle,
@@ -2145,7 +2045,6 @@ var TabItemView = memo4(({
2145
2045
  onDragEnd
2146
2046
  }) => {
2147
2047
  const showClose = item.closable !== void 0 ? item.closable : closable;
2148
- const isCompact = tabWidth !== void 0 && tabWidth < 42;
2149
2048
  const classes = [
2150
2049
  "fc-tab-bar__tab",
2151
2050
  isActive && "fc-tab-bar__tab--active",
@@ -2155,7 +2054,6 @@ var TabItemView = memo4(({
2155
2054
  isActive && activeTabClassName
2156
2055
  ].filter(Boolean).join(" ");
2157
2056
  const mergedStyle = {
2158
- ...tabWidth !== void 0 ? { width: tabWidth, boxSizing: "border-box", flexShrink: 0 } : void 0,
2159
2057
  ...tabStyle,
2160
2058
  ...isActive ? activeTabStyle : void 0
2161
2059
  };
@@ -2164,7 +2062,6 @@ var TabItemView = memo4(({
2164
2062
  {
2165
2063
  className: classes,
2166
2064
  style: mergedStyle,
2167
- "data-compact": isCompact || void 0,
2168
2065
  onClick: () => !item.disabled && onClick(item.key),
2169
2066
  draggable: draggable && !item.disabled,
2170
2067
  onDragStart: (e) => onDragStart(e, item.key),
@@ -2183,7 +2080,7 @@ var TabItemView = memo4(({
2183
2080
  className: "fc-tab-bar__tab-close",
2184
2081
  onClick: (e) => onClose(e, item.key),
2185
2082
  role: "button",
2186
- "aria-label": `\u5173\u95ED`,
2083
+ "aria-label": "\u5173\u95ED",
2187
2084
  children: renderCloseIcon ? renderCloseIcon(item.key) : "\xD7"
2188
2085
  }
2189
2086
  )
@@ -2201,8 +2098,8 @@ var TabBar = memo4(({
2201
2098
  closable = false,
2202
2099
  addable = false,
2203
2100
  draggable = false,
2204
- minWidthRatio = 0.07,
2205
- maxTabWidthRatio = 0.15,
2101
+ minTabWidth = 8,
2102
+ maxTabWidth = 18,
2206
2103
  onChange,
2207
2104
  onClose,
2208
2105
  onAdd,
@@ -2215,7 +2112,6 @@ var TabBar = memo4(({
2215
2112
  renderAddButton,
2216
2113
  className = "",
2217
2114
  style,
2218
- tauriDragRegion = false,
2219
2115
  background,
2220
2116
  tabColor,
2221
2117
  tabHoverColor,
@@ -2224,135 +2120,131 @@ var TabBar = memo4(({
2224
2120
  tabActiveBackground,
2225
2121
  activeIndicatorColor
2226
2122
  }) => {
2227
- const colorVars = {
2123
+ const cssVarMap = {
2228
2124
  "--tab-bar-bg": background,
2229
2125
  "--tab-color": tabColor,
2230
2126
  "--tab-hover-color": tabHoverColor,
2231
2127
  "--tab-hover-bg": tabHoverBackground,
2232
2128
  "--tab-active-color": tabActiveColor,
2233
2129
  "--tab-active-bg": tabActiveBackground,
2234
- "--tab-active-indicator": activeIndicatorColor
2130
+ "--tab-active-indicator": activeIndicatorColor,
2131
+ "--tab-min-width": `${minTabWidth}rem`,
2132
+ "--tab-max-width": `${maxTabWidth}rem`
2235
2133
  };
2236
- const overrideStyle = {};
2237
- for (const [key, value] of Object.entries(colorVars)) {
2238
- if (value !== void 0) {
2239
- overrideStyle[key] = value;
2240
- }
2134
+ const cssVars = {};
2135
+ for (const [k, v] of Object.entries(cssVarMap)) {
2136
+ if (v !== void 0) cssVars[k] = v;
2241
2137
  }
2242
- const mergedStyle = { ...overrideStyle, ...style };
2243
- const dragKeyRef = useRef8(null);
2244
- const navRef = useRef8(null);
2245
- const layout = useAdaptiveTabLayout(navRef, {
2246
- itemsLength: items.length,
2247
- addable,
2248
- minWidthRatio,
2249
- maxTabWidthRatio
2250
- });
2251
- const prevItemsLengthRef = useRef8(items.length);
2252
- useEffect9(() => {
2253
- const prev = prevItemsLengthRef.current;
2254
- prevItemsLengthRef.current = items.length;
2255
- if (items.length <= prev || !layout.scrollMode) return;
2256
- const roll = navRef.current?.querySelector(".fc-roll");
2257
- if (!roll) return;
2138
+ const mergedStyle = { ...cssVars, ...style };
2139
+ const navOuterRef = useRef7(null);
2140
+ const addBtnRef = useRef7(null);
2141
+ const navWrapRef = useRef7(null);
2142
+ const dragKeyRef = useRef7(null);
2143
+ useEffect8(() => {
2144
+ const el = navWrapRef.current;
2145
+ if (!el) return;
2146
+ const handler = (e) => {
2147
+ if (e.deltaY === 0 || e.deltaX !== 0) return;
2148
+ el.scrollLeft += e.deltaY;
2149
+ e.preventDefault();
2150
+ };
2151
+ el.addEventListener("wheel", handler, { passive: false });
2152
+ return () => el.removeEventListener("wheel", handler);
2153
+ }, []);
2154
+ const prevLenRef = useRef7(items.length);
2155
+ useEffect8(() => {
2156
+ const prev = prevLenRef.current;
2157
+ prevLenRef.current = items.length;
2158
+ if (items.length <= prev) return;
2159
+ const el = navWrapRef.current;
2160
+ if (!el) return;
2258
2161
  requestAnimationFrame(() => {
2259
- roll.scrollLeft = roll.scrollWidth;
2162
+ el.scrollLeft = el.scrollWidth;
2260
2163
  });
2261
- }, [items.length, layout.scrollMode]);
2262
- const handleClick = useCallback9(
2263
- (key) => onChange(key),
2264
- [onChange]
2265
- );
2266
- const handleClose = useCallback9(
2267
- (e, key) => {
2268
- e.stopPropagation();
2269
- onClose?.(key);
2270
- },
2271
- [onClose]
2272
- );
2273
- const handleDragStart = useCallback9(
2274
- (e, key) => {
2275
- dragKeyRef.current = key;
2276
- e.dataTransfer.effectAllowed = "move";
2277
- const target = e.currentTarget;
2278
- requestAnimationFrame(() => target.classList.add("fc-tab-bar__tab--dragging"));
2279
- },
2280
- []
2281
- );
2282
- const handleDragOver = useCallback9((e) => {
2164
+ }, [items.length]);
2165
+ const handleClick = useCallback8((key) => onChange(key), [onChange]);
2166
+ const handleClose = useCallback8((e, key) => {
2167
+ e.stopPropagation();
2168
+ onClose?.(key);
2169
+ }, [onClose]);
2170
+ const handleDragStart = useCallback8((e, key) => {
2171
+ dragKeyRef.current = key;
2172
+ e.dataTransfer.effectAllowed = "move";
2173
+ const target = e.currentTarget;
2174
+ requestAnimationFrame(() => target.classList.add("fc-tab-bar__tab--dragging"));
2175
+ }, []);
2176
+ const handleDragOver = useCallback8((e) => {
2283
2177
  e.preventDefault();
2284
2178
  e.dataTransfer.dropEffect = "move";
2285
2179
  }, []);
2286
- const handleDrop = useCallback9(
2287
- (e, targetKey) => {
2288
- e.preventDefault();
2289
- const dragKey = dragKeyRef.current;
2290
- if (!dragKey || dragKey === targetKey || !onReorder) return;
2291
- const fromIndex = items.findIndex((i) => i.key === dragKey);
2292
- const toIndex = items.findIndex((i) => i.key === targetKey);
2293
- if (fromIndex === -1 || toIndex === -1) return;
2294
- const reordered = [...items];
2295
- const [moved] = reordered.splice(fromIndex, 1);
2296
- reordered.splice(toIndex, 0, moved);
2297
- onReorder(reordered);
2298
- },
2299
- [items, onReorder]
2300
- );
2301
- const handleDragEnd = useCallback9((e) => {
2180
+ const handleDrop = useCallback8((e, targetKey) => {
2181
+ e.preventDefault();
2182
+ const dragKey = dragKeyRef.current;
2183
+ if (!dragKey || dragKey === targetKey || !onReorder) return;
2184
+ const from = items.findIndex((i) => i.key === dragKey);
2185
+ const to = items.findIndex((i) => i.key === targetKey);
2186
+ if (from === -1 || to === -1) return;
2187
+ const reordered = [...items];
2188
+ const [moved] = reordered.splice(from, 1);
2189
+ reordered.splice(to, 0, moved);
2190
+ onReorder(reordered);
2191
+ }, [items, onReorder]);
2192
+ const handleDragEnd = useCallback8((e) => {
2302
2193
  dragKeyRef.current = null;
2303
2194
  e.currentTarget.classList.remove("fc-tab-bar__tab--dragging");
2304
2195
  }, []);
2305
- const { scrollMode, tabWidth } = layout;
2306
2196
  const rootClasses = [
2307
2197
  "fc-tab-bar",
2308
2198
  `fc-tab-bar--${variant}`,
2309
2199
  `fc-tab-bar--radius-${radius}`,
2310
2200
  tabRadius && `fc-tab-bar--tab-radius-${tabRadius}`,
2311
- !scrollMode && tabWidth !== void 0 && "fc-tab-bar--shrink",
2312
2201
  className
2313
2202
  ].filter(Boolean).join(" ");
2314
- const tabList = /* @__PURE__ */ jsx18("div", { className: "fc-tab-bar__nav-wrap", children: items.map((item) => /* @__PURE__ */ jsx18(
2315
- TabItemView,
2316
- {
2317
- item,
2318
- isActive: activeKey === item.key,
2319
- closable,
2320
- draggable,
2321
- tabWidth,
2322
- tabClassName,
2323
- activeTabClassName,
2324
- tabStyle,
2325
- activeTabStyle,
2326
- renderCloseIcon,
2327
- onClick: handleClick,
2328
- onClose: handleClose,
2329
- onDragStart: handleDragStart,
2330
- onDragOver: handleDragOver,
2331
- onDrop: handleDrop,
2332
- onDragEnd: handleDragEnd
2333
- },
2334
- item.key
2335
- )) });
2336
- const addBtn = addable && /* @__PURE__ */ jsx18(
2337
- "div",
2338
- {
2339
- className: "fc-tab-bar__add-btn",
2340
- onClick: onAdd,
2341
- role: "button",
2342
- "aria-label": "\u6DFB\u52A0\u6807\u7B7E",
2343
- children: renderAddButton ? renderAddButton() : "+"
2344
- }
2345
- );
2346
- const dragRegion = tauriDragRegion ? { "data-tauri-drag-region": "" } : {};
2347
- return /* @__PURE__ */ jsx18("div", { className: rootClasses, style: mergedStyle, role: "tablist", ...dragRegion, children: /* @__PURE__ */ jsxs13("div", { className: `fc-tab-bar__nav-outer${scrollMode ? " fc-tab-bar__nav-outer--scroll" : ""}`, ...dragRegion, children: [
2348
- /* @__PURE__ */ jsx18("div", { className: `fc-tab-bar__nav${scrollMode ? " fc-tab-bar__nav--scroll" : ""}`, ref: navRef, children: scrollMode ? /* @__PURE__ */ jsx18(RollingBox, { horizontal: true, showThumb: "hide", style: { flex: 1, minWidth: 0, height: "auto" }, children: tabList }) : tabList }),
2349
- addBtn
2203
+ const navWrapClasses = [
2204
+ "fc-tab-bar__nav-wrap",
2205
+ "fc-tab-bar__nav-wrap--scroll"
2206
+ // 始终启用滚动模式,由 CSS 控制
2207
+ ].filter(Boolean).join(" ");
2208
+ return /* @__PURE__ */ jsx18("div", { className: rootClasses, style: mergedStyle, role: "tablist", children: /* @__PURE__ */ jsxs13("div", { className: "fc-tab-bar__nav-outer", ref: navOuterRef, children: [
2209
+ /* @__PURE__ */ jsx18("div", { className: navWrapClasses, ref: navWrapRef, children: items.map((item) => /* @__PURE__ */ jsx18(
2210
+ TabItemView,
2211
+ {
2212
+ item,
2213
+ isActive: activeKey === item.key,
2214
+ closable,
2215
+ draggable,
2216
+ tabClassName,
2217
+ activeTabClassName,
2218
+ tabStyle,
2219
+ activeTabStyle,
2220
+ renderCloseIcon,
2221
+ onClick: handleClick,
2222
+ onClose: handleClose,
2223
+ onDragStart: handleDragStart,
2224
+ onDragOver: handleDragOver,
2225
+ onDrop: handleDrop,
2226
+ onDragEnd: handleDragEnd
2227
+ },
2228
+ item.key
2229
+ )) }),
2230
+ addable && /* @__PURE__ */ jsx18(
2231
+ "div",
2232
+ {
2233
+ className: "fc-tab-bar__add-btn",
2234
+ ref: addBtnRef,
2235
+ onClick: onAdd,
2236
+ role: "button",
2237
+ "aria-label": "\u6DFB\u52A0\u6807\u7B7E",
2238
+ children: renderAddButton ? renderAddButton() : "+"
2239
+ }
2240
+ ),
2241
+ /* @__PURE__ */ jsx18("div", { className: "fc-tab-bar__drag-handle", "data-tauri-drag-region": true })
2350
2242
  ] }) });
2351
2243
  });
2352
2244
  TabBar.displayName = "TabBar";
2353
2245
 
2354
2246
  // src/components/Tag/TagItem.tsx
2355
- import { useEffect as useEffect10, useRef as useRef9, useState as useState14 } from "react";
2247
+ import { useEffect as useEffect9, useRef as useRef8, useState as useState13 } from "react";
2356
2248
  import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2357
2249
  function TagItem({
2358
2250
  schema,
@@ -2363,10 +2255,10 @@ function TagItem({
2363
2255
  color,
2364
2256
  borderColor
2365
2257
  }) {
2366
- const [editing, setEditing] = useState14(false);
2367
- const [draft, setDraft] = useState14(() => value !== void 0 ? String(value) : "");
2368
- const inputRef = useRef9(null);
2369
- useEffect10(() => {
2258
+ const [editing, setEditing] = useState13(false);
2259
+ const [draft, setDraft] = useState13(() => value !== void 0 ? String(value) : "");
2260
+ const inputRef = useRef8(null);
2261
+ useEffect9(() => {
2370
2262
  if (!editing) setDraft(value !== void 0 ? String(value) : "");
2371
2263
  }, [value, editing]);
2372
2264
  const colorVars = {
@@ -2465,7 +2357,7 @@ function TagItem({
2465
2357
  }
2466
2358
 
2467
2359
  // src/components/MarkdownEditor/MarkdownEditor.tsx
2468
- import { useState as useState15 } from "react";
2360
+ import { useState as useState14 } from "react";
2469
2361
  import MDEditor, { commands } from "@uiw/react-md-editor";
2470
2362
  import { jsx as jsx20 } from "react/jsx-runtime";
2471
2363
  function withTitle(cmd, title) {
@@ -2501,7 +2393,7 @@ function MarkdownEditor({
2501
2393
  borderColor
2502
2394
  }) {
2503
2395
  const { resolvedTheme } = useTheme();
2504
- const [showSplit, setShowSplit] = useState15(false);
2396
+ const [showSplit, setShowSplit] = useState14(false);
2505
2397
  const colorVars = {
2506
2398
  "--md-bg": background,
2507
2399
  "--md-toolbar-bg": toolbarBackground,
@@ -2560,7 +2452,7 @@ function MarkdownEditor({
2560
2452
  }
2561
2453
 
2562
2454
  // src/components/ContextMenu/ContextMenuContext.tsx
2563
- import { createContext as createContext4, useContext as useContext4, useEffect as useEffect11, useRef as useRef10, useState as useState16 } from "react";
2455
+ import { createContext as createContext4, useContext as useContext4, useEffect as useEffect10, useRef as useRef9, useState as useState15 } from "react";
2564
2456
  import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
2565
2457
  var ContextMenuContext = createContext4(null);
2566
2458
  function ContextMenuProvider({
@@ -2569,13 +2461,13 @@ function ContextMenuProvider({
2569
2461
  borderColor,
2570
2462
  hoverBackground
2571
2463
  }) {
2572
- const [menu, setMenu] = useState16({
2464
+ const [menu, setMenu] = useState15({
2573
2465
  visible: false,
2574
2466
  x: 0,
2575
2467
  y: 0,
2576
2468
  items: []
2577
2469
  });
2578
- const menuRef = useRef10(null);
2470
+ const menuRef = useRef9(null);
2579
2471
  const showContextMenu = (e, items) => {
2580
2472
  e.preventDefault();
2581
2473
  e.stopPropagation();
@@ -2583,7 +2475,7 @@ function ContextMenuProvider({
2583
2475
  };
2584
2476
  const hide = () => setMenu((s) => ({ ...s, visible: false }));
2585
2477
  useClickOutside(menuRef, hide, menu.visible);
2586
- useEffect11(() => {
2478
+ useEffect10(() => {
2587
2479
  if (!menu.visible) return;
2588
2480
  const onKeyDown = (e) => {
2589
2481
  if (e.key === "Escape") hide();
@@ -2652,10 +2544,10 @@ function ContextMenuProvider({
2652
2544
  var useContextMenu = () => useContext4(ContextMenuContext);
2653
2545
 
2654
2546
  // src/components/Chat/Chat.tsx
2655
- import { useState as useState18, useRef as useRef11, useEffect as useEffect12, useCallback as useCallback11, useMemo as useMemo5 } from "react";
2547
+ import { useState as useState17, useRef as useRef10, useEffect as useEffect11, useCallback as useCallback10, useMemo as useMemo5 } from "react";
2656
2548
 
2657
2549
  // src/components/SmartMessage/SmartMessage.tsx
2658
- import { useState as useState17, useCallback as useCallback10 } from "react";
2550
+ import { useState as useState16, useCallback as useCallback9 } from "react";
2659
2551
  import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2660
2552
  var SmartMessage = ({
2661
2553
  id,
@@ -2668,8 +2560,8 @@ var SmartMessage = ({
2668
2560
  className = "",
2669
2561
  style = {}
2670
2562
  }) => {
2671
- const [copied, setCopied] = useState17(false);
2672
- const handleCopy = useCallback10(async () => {
2563
+ const [copied, setCopied] = useState16(false);
2564
+ const handleCopy = useCallback9(async () => {
2673
2565
  try {
2674
2566
  await navigator.clipboard.writeText(content);
2675
2567
  setCopied(true);
@@ -2757,34 +2649,34 @@ var Chat = ({
2757
2649
  height = "600px",
2758
2650
  width
2759
2651
  }) => {
2760
- const [showHistory, setShowHistory] = useState18(false);
2761
- const [isMinimized, setIsMinimized] = useState18(false);
2762
- const messagesContainerRef = useRef11(null);
2763
- const messagesEndRef = useRef11(null);
2764
- const historyPanelRef = useRef11(null);
2652
+ const [showHistory, setShowHistory] = useState17(false);
2653
+ const [isMinimized, setIsMinimized] = useState17(false);
2654
+ const messagesContainerRef = useRef10(null);
2655
+ const messagesEndRef = useRef10(null);
2656
+ const historyPanelRef = useRef10(null);
2765
2657
  const currentConversation = useMemo5(
2766
2658
  () => conversations.find((c) => c.id === currentConversationId),
2767
2659
  [conversations, currentConversationId]
2768
2660
  );
2769
2661
  const currentTitle = currentConversation?.title || title;
2770
- useEffect12(() => {
2662
+ useEffect11(() => {
2771
2663
  if (autoScroll && messagesContainerRef.current && !showHistory && !isMinimized) {
2772
2664
  messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
2773
2665
  }
2774
2666
  }, [messages, loading, showHistory, isMinimized, autoScroll]);
2775
2667
  useClickOutside(historyPanelRef, () => setShowHistory(false), showHistory);
2776
- const handleDeleteConversation = useCallback11((conversationId) => {
2668
+ const handleDeleteConversation = useCallback10((conversationId) => {
2777
2669
  onDeleteConversation?.(conversationId);
2778
2670
  }, [onDeleteConversation]);
2779
- const handleMinimize = useCallback11(() => {
2671
+ const handleMinimize = useCallback10(() => {
2780
2672
  setIsMinimized(true);
2781
2673
  onMinimize?.();
2782
2674
  }, [onMinimize]);
2783
- const handleRestore = useCallback11(() => {
2675
+ const handleRestore = useCallback10(() => {
2784
2676
  setIsMinimized(false);
2785
2677
  onRestore?.();
2786
2678
  }, [onRestore]);
2787
- const handleCopy = useCallback11((content) => {
2679
+ const handleCopy = useCallback10((content) => {
2788
2680
  const message = messages.find((m) => m.content === content);
2789
2681
  if (message) {
2790
2682
  onMessageCopy?.(message);
@@ -2962,7 +2854,7 @@ var Chat = ({
2962
2854
  };
2963
2855
 
2964
2856
  // src/components/Relation/Relation.tsx
2965
- import React13, { useCallback as useCallback12, useEffect as useEffect13, memo as memo5 } from "react";
2857
+ import React13, { useCallback as useCallback11, useEffect as useEffect12, memo as memo5 } from "react";
2966
2858
  import {
2967
2859
  ReactFlow,
2968
2860
  useNodesState,
@@ -3184,7 +3076,7 @@ var RelationContent = ({
3184
3076
  const theme = propTheme;
3185
3077
  const isDark = theme === "dark";
3186
3078
  const bgColor = isDark ? "#0f172a" : "#f5f7fa";
3187
- useEffect13(() => {
3079
+ useEffect12(() => {
3188
3080
  if (fitView && fitViewFn && (propNodes?.length || 0) > 0) {
3189
3081
  const timer = setTimeout(() => {
3190
3082
  fitViewFn({ duration: 300, padding: 0.2, ...fitViewOptions }).catch((error) => {
@@ -3194,17 +3086,17 @@ var RelationContent = ({
3194
3086
  return () => clearTimeout(timer);
3195
3087
  }
3196
3088
  }, [fitView, fitViewFn, fitViewOptions, propNodes]);
3197
- useEffect13(() => {
3089
+ useEffect12(() => {
3198
3090
  if (propNodes) {
3199
3091
  setNodes(propNodes);
3200
3092
  }
3201
3093
  }, [propNodes, setNodes]);
3202
- useEffect13(() => {
3094
+ useEffect12(() => {
3203
3095
  if (propEdges) {
3204
3096
  setEdges(propEdges);
3205
3097
  }
3206
3098
  }, [propEdges, setEdges]);
3207
- const handleNodesChange = useCallback12(
3099
+ const handleNodesChange = useCallback11(
3208
3100
  (changes) => {
3209
3101
  onNodesChange(changes);
3210
3102
  if (onNodesChangeProp) {
@@ -3215,7 +3107,7 @@ var RelationContent = ({
3215
3107
  },
3216
3108
  [onNodesChange, onNodesChangeProp, nodes]
3217
3109
  );
3218
- const handleEdgesChange = useCallback12(
3110
+ const handleEdgesChange = useCallback11(
3219
3111
  (changes) => {
3220
3112
  onEdgesChange(changes);
3221
3113
  if (onEdgesChangeProp) {
@@ -3226,7 +3118,7 @@ var RelationContent = ({
3226
3118
  },
3227
3119
  [onEdgesChange, onEdgesChangeProp, edges]
3228
3120
  );
3229
- const onConnect = useCallback12(
3121
+ const onConnect = useCallback11(
3230
3122
  (params) => {
3231
3123
  const newEdge = {
3232
3124
  ...params,
@@ -3250,7 +3142,7 @@ var RelationContent = ({
3250
3142
  },
3251
3143
  [setEdges, onConnectProp, edgeStyles.defaultColor, isDark]
3252
3144
  );
3253
- const handleNodeClick = useCallback12(
3145
+ const handleNodeClick = useCallback11(
3254
3146
  (_event, node) => {
3255
3147
  if (onNodeClick && node.data) {
3256
3148
  onNodeClick(node.id, node.data, _event);
@@ -3258,7 +3150,7 @@ var RelationContent = ({
3258
3150
  },
3259
3151
  [onNodeClick]
3260
3152
  );
3261
- const handleNodeDoubleClick = useCallback12(
3153
+ const handleNodeDoubleClick = useCallback11(
3262
3154
  (_event, node) => {
3263
3155
  if (onNodeDoubleClick && node.data) {
3264
3156
  onNodeDoubleClick(node.id, node.data);
@@ -3266,7 +3158,7 @@ var RelationContent = ({
3266
3158
  },
3267
3159
  [onNodeDoubleClick]
3268
3160
  );
3269
- const handleNodeContextMenu = useCallback12(
3161
+ const handleNodeContextMenu = useCallback11(
3270
3162
  (event, node) => {
3271
3163
  event.preventDefault();
3272
3164
  if (onNodeContextMenu && node.data) {
@@ -3275,7 +3167,7 @@ var RelationContent = ({
3275
3167
  },
3276
3168
  [onNodeContextMenu]
3277
3169
  );
3278
- const handleEdgeClick = useCallback12(
3170
+ const handleEdgeClick = useCallback11(
3279
3171
  (_event, edge) => {
3280
3172
  if (onEdgeClick) {
3281
3173
  onEdgeClick(edge.id, edge.data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowcloudai-ui",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "author": "flowcloudai",
6
6
  "module": "dist/index.js",