feat: add tab

This commit is contained in:
mozzie 2024-07-16 22:19:43 +08:00
parent 3c5c93e422
commit c0ab592944
5 changed files with 153 additions and 18 deletions

View File

@ -15,6 +15,7 @@
"@radix-ui/react-menubar": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-tooltip": "^1.1.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",

View File

@ -20,6 +20,9 @@ importers:
'@radix-ui/react-toast':
specifier: ^1.2.1
version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-tooltip':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@ -851,6 +854,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-tooltip@1.1.2':
resolution: {integrity: sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-use-callback-ref@1.0.1':
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
peerDependencies:
@ -3617,6 +3633,26 @@ snapshots:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-tooltip@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1)
'@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.24.8
@ -3975,7 +4011,7 @@ snapshots:
app-builder-bin@4.0.0: {}
app-builder-lib@24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)):
app-builder-lib@24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)):
dependencies:
'@develar/schema-utils': 2.6.5
'@electron/notarize': 2.2.1
@ -3989,7 +4025,7 @@ snapshots:
builder-util-runtime: 9.2.4
chromium-pickle-js: 0.2.0
debug: 4.3.5
dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3)
ejs: 3.1.10
electron-builder-squirrel-windows: 24.13.3(dmg-builder@24.13.3)
electron-publish: 24.13.1
@ -4361,9 +4397,9 @@ snapshots:
dlv@1.1.3: {}
dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)):
dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3):
dependencies:
app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
builder-util: 24.13.1
builder-util-runtime: 9.2.4
fs-extra: 10.1.0
@ -4403,7 +4439,7 @@ snapshots:
electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3):
dependencies:
app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
archiver: 5.3.2
builder-util: 24.13.1
fs-extra: 10.1.0
@ -4413,11 +4449,11 @@ snapshots:
electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)):
dependencies:
app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
builder-util: 24.13.1
builder-util-runtime: 9.2.4
chalk: 4.1.2
dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3))
dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3)
fs-extra: 10.1.0
is-ci: 3.0.1
lazy-val: 1.0.5

View File

@ -0,0 +1,30 @@
"use client"
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import { cn } from "@/lib/utils"
const TooltipProvider = TooltipPrimitive.Provider
const Tooltip = TooltipPrimitive.Root
const TooltipTrigger = TooltipPrimitive.Trigger
const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }

View File

@ -1,14 +1,23 @@
import React from "react";
import { IJsonModel, Layout, Model, TabNode } from "flexlayout-react";
import { Actions, BorderNode, DockLocation, IJsonModel, ITabRenderValues, ITabSetRenderValues, Layout, Model, TabNode, TabSetNode } from "flexlayout-react";
import "flexlayout-react/style/light.css";
import "./Layout.css";
import { Button } from "@/components/ui/button"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
const json: IJsonModel = {
global: {
tabEnableFloat: false,
tabSetMinWidth: 100,
tabSetMinHeight: 100,
tabSetMinHeight: 200,
tabSetTabStripHeight: 48,//tab栏高度
borderMinSize: 100,
splitterSize: 2,
},
borders: [],
layout: {
@ -21,8 +30,10 @@ const json: IJsonModel = {
children: [
{
type: "tab",
id: 'tab1',
name: "One",
component: "button",
component: "tabComponent",
config: { icon: "📘" }
},
],
},
@ -32,8 +43,10 @@ const json: IJsonModel = {
children: [
{
type: "tab",
id: 'tab2',
name: "Two",
component: "button",
component: "tabComponent",
config: { icon: "📘" }
},
],
},
@ -41,22 +54,68 @@ const json: IJsonModel = {
},
};
const model = Model.fromJson(json);
const FlexLayoutComponent: React.FC = () => {
const model = Model.fromJson(json);
const factory = (node: TabNode) => {
const component = node.getComponent();
if (component === "button") {
return <button>{node.getName()}</button>;
if (component === "tabComponent") {
return <div>{node.getName()}11</div>;
}
};
const renderTab = (node: TabNode, renderValues: ITabRenderValues) => {
renderValues.content = (
<div style={{ display: "flex", alignItems: "center" }}>
<span style={{ marginRight: 5 }}>{node.getConfig().icon}</span>
{renderValues.content}
</div>
);
};
const addTab = (node: TabSetNode | BorderNode) => {
// 创建一个新的 tab 对象
const newTab = {
type: "tab",
name: "New Tab",
component: "tabComponent",
config: { icon: '' }
};
// 使用 FlexLayout 的 addAction 执行添加 tab 的动作
const addAction = Actions.addNode(newTab, node.getId(), DockLocation.CENTER, -1);
node.getModel().doAction(addAction);
};
const onRenderTabSet = (node: TabSetNode | BorderNode, renderValues: ITabSetRenderValues) => {
const createTabButton = <TooltipProvider>
<Tooltip>
<TooltipTrigger>
<span
onClick={() => addTab(node)}
key={node.getId() + 'create'}>
+</span>
</TooltipTrigger>
<TooltipContent side="bottom">
<p></p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
renderValues.stickyButtons.push(createTabButton)
};
return (
<Layout
model={model}
realtimeResize
factory={factory}
classNameMapper={(defaultClass) => `${defaultClass} custom-layout-class`}
onRenderTab={renderTab}
onRenderTabSet={onRenderTabSet}
/>
);
};

View File

@ -1,9 +1,7 @@
/* Layout.css */
.custom-layout-class .flexlayout__tab_button {
background-color: #4caf50;
color: white;
border-radius: 5px;
border-radius: 10px 10px 0 0;
padding: 5px;
margin-right: 5px;
cursor: pointer;
@ -11,4 +9,15 @@
.custom-layout-class .flexlayout__tab_button:hover {
background-color: #45a049;
}
/* 覆盖默认的 FlexLayout 分割线选中颜色 */
.custom-layout-class .flexlayout__splitter_drag {
background-color: blue;
/* 选中时的颜色 */
}
.custom-layout-class .flexlayout__splitter:hover {
background-color: lightblue;
/* 鼠标悬停时的颜色 */
}