flowcloudai-ui 0.1.5 → 0.1.6

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,8 +1846,6 @@
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;
1851
1849
  --tab-bar-radius-tl: var(--fc-radius-md);
1852
1850
  --tab-bar-radius-tr: var(--fc-radius-md);
1853
1851
  --tab-bar-radius-br: 0px;
@@ -1893,23 +1891,26 @@
1893
1891
  .fc-tab-bar__nav-outer {
1894
1892
  display: flex;
1895
1893
  align-items: stretch;
1894
+ flex: 1;
1895
+ min-width: 0;
1896
1896
  }
1897
1897
  .fc-tab-bar__nav-wrap {
1898
1898
  display: flex;
1899
1899
  align-items: stretch;
1900
- }
1901
- .fc-tab-bar__nav-wrap--scroll {
1902
1900
  flex: 1;
1903
1901
  min-width: 0;
1904
1902
  overflow-x: auto;
1905
1903
  scrollbar-width: none;
1906
1904
  }
1907
- .fc-tab-bar__nav-wrap--scroll::-webkit-scrollbar {
1905
+ .fc-tab-bar__nav-wrap::-webkit-scrollbar {
1908
1906
  display: none;
1909
1907
  }
1910
1908
  .fc-tab-bar__tab {
1909
+ flex: 1 1 0;
1910
+ min-width: var(--tab-min-width, 80px);
1911
+ max-width: var(--tab-max-width, 200px);
1911
1912
  position: relative;
1912
- display: inline-flex;
1913
+ display: flex;
1913
1914
  align-items: center;
1914
1915
  gap: var(--fc-space-sm, 8px);
1915
1916
  padding: var(--fc-space-sm, 8px) var(--fc-space-lg, 16px);
@@ -1921,14 +1922,11 @@
1921
1922
  white-space: nowrap;
1922
1923
  border: none;
1923
1924
  user-select: none;
1925
+ box-sizing: border-box;
1924
1926
  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
1927
  overflow: hidden;
1929
- box-sizing: border-box;
1930
1928
  }
1931
- .fc-tab-bar__tab:hover:not(.fc-tab-bar__tab--disabled):not(.fc-tab-bar__tab--dragging):not(.fc-tab-bar__tab--active) {
1929
+ .fc-tab-bar__tab:hover:not(.fc-tab-bar__tab--disabled):not(.fc-tab-bar__tab--dragging) {
1932
1930
  color: var(--tab-hover-color);
1933
1931
  background-color: var(--tab-hover-bg);
1934
1932
  }
@@ -1946,7 +1944,18 @@
1946
1944
  min-width: 0;
1947
1945
  overflow: hidden;
1948
1946
  white-space: nowrap;
1949
- text-overflow: ellipsis;
1947
+ -webkit-mask-image:
1948
+ linear-gradient(
1949
+ to right,
1950
+ black 0%,
1951
+ black calc(100% - 20px),
1952
+ transparent 100%);
1953
+ mask-image:
1954
+ linear-gradient(
1955
+ to right,
1956
+ black 0%,
1957
+ black calc(100% - 20px),
1958
+ transparent 100%);
1950
1959
  }
1951
1960
  .fc-tab-bar--attached {
1952
1961
  border-bottom: 2px solid var(--fc-color-border);
@@ -2024,11 +2033,6 @@
2024
2033
  .fc-tab-bar__add-btn {
2025
2034
  -webkit-app-region: no-drag;
2026
2035
  }
2027
- .fc-tab-bar__drag-handle {
2028
- flex: 0 0 0px;
2029
- overflow: hidden;
2030
- -webkit-app-region: drag;
2031
- }
2032
2036
  .fc-tab-bar__tab--draggable {
2033
2037
  cursor: default;
2034
2038
  }
@@ -2053,11 +2057,13 @@
2053
2057
  background-color: var(--fc-color-border-light);
2054
2058
  }
2055
2059
  .fc-tab-bar__add-btn {
2060
+ position: sticky;
2061
+ right: 0;
2062
+ flex-shrink: 0;
2056
2063
  display: inline-flex;
2057
2064
  align-items: center;
2058
2065
  justify-content: center;
2059
2066
  width: 32px;
2060
- flex-shrink: 0;
2061
2067
  margin: 0 var(--fc-space-sm, 8px);
2062
2068
  font-size: 20px;
2063
2069
  font-weight: bold;
@@ -2066,6 +2072,7 @@
2066
2072
  cursor: pointer;
2067
2073
  transition: all var(--fc-transition, 150ms ease);
2068
2074
  border-radius: var(--fc-radius-sm, 4px);
2075
+ background-color: var(--tab-bar-bg);
2069
2076
  }
2070
2077
  .fc-tab-bar__add-btn:hover {
2071
2078
  color: var(--fc-color-primary);
@@ -2074,9 +2081,24 @@
2074
2081
  .fc-tab-bar--floating .fc-tab-bar__add-btn {
2075
2082
  border-radius: var(--fc-radius-full, 9999px);
2076
2083
  }
2084
+ [data-theme=dark] .fc-tab-bar--attached {
2085
+ border-bottom-color: var(--fc-color-border);
2086
+ }
2087
+ [data-theme=dark] .fc-tab-bar__tab--active {
2088
+ background-color: var(--tab-active-bg);
2089
+ }
2090
+ [data-theme=dark] .fc-tab-bar__tab:hover:not(.fc-tab-bar__tab--disabled) {
2091
+ background-color: var(--tab-hover-bg);
2092
+ }
2077
2093
  [data-theme=dark] .fc-tab-bar--floating .fc-tab-bar__tab--active {
2078
2094
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
2079
2095
  }
2096
+ [data-theme=dark] .fc-tab-bar__add-btn:hover {
2097
+ background-color: var(--fc-color-bg-tertiary);
2098
+ }
2099
+ [data-theme=dark] .fc-tab-bar__tab-close:hover {
2100
+ background-color: var(--fc-color-border-light);
2101
+ }
2080
2102
  @media (max-width: 768px) {
2081
2103
  .fc-tab-bar__tab {
2082
2104
  padding: var(--fc-space-xs, 6px) var(--fc-space-md, 12px);
package/dist/index.d.ts CHANGED
@@ -423,41 +423,87 @@ 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
+ /** 唯一标识 */
426
427
  key: string;
428
+ /** 标签显示内容 */
427
429
  label: React__default.ReactNode;
430
+ /** 是否禁用 */
428
431
  disabled?: boolean;
432
+ /** 是否可关闭(覆盖全局 closable) */
429
433
  closable?: boolean;
430
434
  }
431
435
  interface TabBarProps {
436
+ /** Tab 列表(受控) */
432
437
  items: TabItem[];
438
+ /** 当前激活的 Tab key(受控) */
433
439
  activeKey: string;
440
+ /**
441
+ * 布局变体
442
+ * - attached: 贴合模式 — 标签底部紧贴导航栏下边缘,底部线条作为激活指示器
443
+ * - floating: 悬浮模式 — 标签垂直居中悬浮,胶囊形态,背景填充作为激活指示器
444
+ * @default 'attached'
445
+ */
434
446
  variant?: 'attached' | 'floating';
447
+ /** TabBar 容器圆角 */
435
448
  radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
449
+ /** 单个 Tab 项的圆角(仅在 floating 模式下或需要四周圆角时使用) */
436
450
  tabRadius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
451
+ /** 是否显示关闭按钮 */
437
452
  closable?: boolean;
453
+ /** 是否显示添加按钮 */
438
454
  addable?: boolean;
455
+ /** 是否启用拖拽排序 */
439
456
  draggable?: boolean;
440
- minTabWidth?: number;
441
- maxTabWidth?: number;
457
+ /**
458
+ * Tab 最小宽度(rem 单位)。
459
+ * Tab 压缩至此宽度后触发横向滚动。
460
+ * @default '7rem'
461
+ */
462
+ minWidth?: string;
463
+ /**
464
+ * Tab 最大宽度(rem 单位)。
465
+ * Tab 较少时不超过此宽度。
466
+ * @default '15rem'
467
+ */
468
+ maxTabWidth?: string;
442
469
  onChange: (activeKey: string) => void;
443
470
  onClose?: (key: string) => void;
444
471
  onAdd?: () => void;
445
472
  onReorder?: (reorderedItems: TabItem[]) => void;
473
+ /** 每个 Tab 的自定义 className */
446
474
  tabClassName?: string;
475
+ /** 激活态 Tab 的额外 className */
447
476
  activeTabClassName?: string;
477
+ /** 每个 Tab 的自定义 inline style */
448
478
  tabStyle?: React__default.CSSProperties;
479
+ /** 激活态 Tab 的自定义 inline style(会合并到 tabStyle 之上) */
449
480
  activeTabStyle?: React__default.CSSProperties;
481
+ /** 自定义关闭图标渲染 */
450
482
  renderCloseIcon?: (key: string) => React__default.ReactNode;
483
+ /** 自定义添加按钮渲染 */
451
484
  renderAddButton?: () => React__default.ReactNode;
452
485
  className?: string;
453
486
  style?: React__default.CSSProperties;
487
+ /** 容器背景色 */
454
488
  background?: string;
489
+ /** 标签默认文字色 */
455
490
  tabColor?: string;
491
+ /** 标签 hover 文字色 */
456
492
  tabHoverColor?: string;
493
+ /** 标签 hover 背景色 */
457
494
  tabHoverBackground?: string;
495
+ /** 激活态文字色 */
458
496
  tabActiveColor?: string;
497
+ /** 激活态背景色 */
459
498
  tabActiveBackground?: string;
499
+ /** 激活态指示器颜色(attached 模式底线 / floating 模式无效) */
460
500
  activeIndicatorColor?: string;
501
+ /**
502
+ * 将 TabBar 空白区域标记为 Tauri 窗口拖拽区域。
503
+ * 开启后,标签之外的空白处可拖动窗口;标签、关闭、添加按钮已内置 no-drag 保护。
504
+ * @default false
505
+ */
506
+ tauriDragRegion?: boolean;
461
507
  }
462
508
  declare const TabBar: React__default.NamedExoticComponent<TabBarProps>;
463
509
 
package/dist/index.js CHANGED
@@ -2098,8 +2098,8 @@ var TabBar = memo4(({
2098
2098
  closable = false,
2099
2099
  addable = false,
2100
2100
  draggable = false,
2101
- minTabWidth = 8,
2102
- maxTabWidth = 18,
2101
+ minWidth = "7rem",
2102
+ maxTabWidth = "15rem",
2103
2103
  onChange,
2104
2104
  onClose,
2105
2105
  onAdd,
@@ -2112,6 +2112,7 @@ var TabBar = memo4(({
2112
2112
  renderAddButton,
2113
2113
  className = "",
2114
2114
  style,
2115
+ tauriDragRegion = false,
2115
2116
  background,
2116
2117
  tabColor,
2117
2118
  tabHoverColor,
@@ -2120,75 +2121,85 @@ var TabBar = memo4(({
2120
2121
  tabActiveBackground,
2121
2122
  activeIndicatorColor
2122
2123
  }) => {
2123
- const cssVarMap = {
2124
+ const colorVars = {
2124
2125
  "--tab-bar-bg": background,
2125
2126
  "--tab-color": tabColor,
2126
2127
  "--tab-hover-color": tabHoverColor,
2127
2128
  "--tab-hover-bg": tabHoverBackground,
2128
2129
  "--tab-active-color": tabActiveColor,
2129
2130
  "--tab-active-bg": tabActiveBackground,
2130
- "--tab-active-indicator": activeIndicatorColor,
2131
- "--tab-min-width": `${minTabWidth}rem`,
2132
- "--tab-max-width": `${maxTabWidth}rem`
2131
+ "--tab-active-indicator": activeIndicatorColor
2133
2132
  };
2134
- const cssVars = {};
2135
- for (const [k, v] of Object.entries(cssVarMap)) {
2136
- if (v !== void 0) cssVars[k] = v;
2133
+ const overrideStyle = {};
2134
+ for (const [key, value] of Object.entries(colorVars)) {
2135
+ if (value !== void 0) {
2136
+ overrideStyle[key] = value;
2137
+ }
2137
2138
  }
2138
- const mergedStyle = { ...cssVars, ...style };
2139
- const navOuterRef = useRef7(null);
2140
- const addBtnRef = useRef7(null);
2141
- const navWrapRef = useRef7(null);
2139
+ const mergedStyle = { ...overrideStyle, ...style };
2142
2140
  const dragKeyRef = useRef7(null);
2141
+ const navRef = useRef7(null);
2142
+ const prevItemsLengthRef = useRef7(items.length);
2143
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;
2144
+ const prev = prevItemsLengthRef.current;
2145
+ prevItemsLengthRef.current = items.length;
2158
2146
  if (items.length <= prev) return;
2159
- const el = navWrapRef.current;
2160
- if (!el) return;
2147
+ const nav = navRef.current;
2148
+ if (!nav) return;
2161
2149
  requestAnimationFrame(() => {
2162
- el.scrollLeft = el.scrollWidth;
2150
+ nav.scrollLeft = nav.scrollWidth;
2163
2151
  });
2164
2152
  }, [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"));
2153
+ useEffect8(() => {
2154
+ const nav = navRef.current;
2155
+ if (!nav) return;
2156
+ const handleWheel = (e) => {
2157
+ if (e.deltaY === 0) return;
2158
+ e.preventDefault();
2159
+ nav.scrollLeft += Number(e.deltaY);
2160
+ };
2161
+ nav.addEventListener("wheel", handleWheel, { passive: false });
2162
+ return () => nav.removeEventListener("wheel", handleWheel);
2175
2163
  }, []);
2164
+ const handleClick = useCallback8(
2165
+ (key) => onChange(key),
2166
+ [onChange]
2167
+ );
2168
+ const handleClose = useCallback8(
2169
+ (e, key) => {
2170
+ e.stopPropagation();
2171
+ onClose?.(key);
2172
+ },
2173
+ [onClose]
2174
+ );
2175
+ const handleDragStart = useCallback8(
2176
+ (e, key) => {
2177
+ dragKeyRef.current = key;
2178
+ e.dataTransfer.effectAllowed = "move";
2179
+ const target = e.currentTarget;
2180
+ requestAnimationFrame(() => target.classList.add("fc-tab-bar__tab--dragging"));
2181
+ },
2182
+ []
2183
+ );
2176
2184
  const handleDragOver = useCallback8((e) => {
2177
2185
  e.preventDefault();
2178
2186
  e.dataTransfer.dropEffect = "move";
2179
2187
  }, []);
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]);
2188
+ const handleDrop = useCallback8(
2189
+ (e, targetKey) => {
2190
+ e.preventDefault();
2191
+ const dragKey = dragKeyRef.current;
2192
+ if (!dragKey || dragKey === targetKey || !onReorder) return;
2193
+ const fromIndex = items.findIndex((i) => i.key === dragKey);
2194
+ const toIndex = items.findIndex((i) => i.key === targetKey);
2195
+ if (fromIndex === -1 || toIndex === -1) return;
2196
+ const reordered = [...items];
2197
+ const [moved] = reordered.splice(fromIndex, 1);
2198
+ reordered.splice(toIndex, 0, moved);
2199
+ onReorder(reordered);
2200
+ },
2201
+ [items, onReorder]
2202
+ );
2192
2203
  const handleDragEnd = useCallback8((e) => {
2193
2204
  dragKeyRef.current = null;
2194
2205
  e.currentTarget.classList.remove("fc-tab-bar__tab--dragging");
@@ -2200,13 +2211,13 @@ var TabBar = memo4(({
2200
2211
  tabRadius && `fc-tab-bar--tab-radius-${tabRadius}`,
2201
2212
  className
2202
2213
  ].filter(Boolean).join(" ");
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(
2214
+ const navWrapStyle = {
2215
+ "--tab-min-width": minWidth,
2216
+ "--tab-max-width": maxTabWidth
2217
+ };
2218
+ const dragRegion = tauriDragRegion ? { "data-tauri-drag-region": "" } : {};
2219
+ return /* @__PURE__ */ jsx18("div", { className: rootClasses, style: mergedStyle, role: "tablist", ...dragRegion, children: /* @__PURE__ */ jsx18("div", { className: "fc-tab-bar__nav-outer", ...dragRegion, children: /* @__PURE__ */ jsxs13("div", { className: "fc-tab-bar__nav-wrap", ref: navRef, style: navWrapStyle, children: [
2220
+ items.map((item) => /* @__PURE__ */ jsx18(
2210
2221
  TabItemView,
2211
2222
  {
2212
2223
  item,
@@ -2226,20 +2237,18 @@ var TabBar = memo4(({
2226
2237
  onDragEnd: handleDragEnd
2227
2238
  },
2228
2239
  item.key
2229
- )) }),
2240
+ )),
2230
2241
  addable && /* @__PURE__ */ jsx18(
2231
2242
  "div",
2232
2243
  {
2233
2244
  className: "fc-tab-bar__add-btn",
2234
- ref: addBtnRef,
2235
2245
  onClick: onAdd,
2236
2246
  role: "button",
2237
2247
  "aria-label": "\u6DFB\u52A0\u6807\u7B7E",
2238
2248
  children: renderAddButton ? renderAddButton() : "+"
2239
2249
  }
2240
- ),
2241
- /* @__PURE__ */ jsx18("div", { className: "fc-tab-bar__drag-handle", "data-tauri-drag-region": true })
2242
- ] }) });
2250
+ )
2251
+ ] }) }) });
2243
2252
  });
2244
2253
  TabBar.displayName = "TabBar";
2245
2254
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowcloudai-ui",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "author": "flowcloudai",
6
6
  "module": "dist/index.js",