feat: 布局
This commit is contained in:
parent
c0ab592944
commit
d9e8ff195c
|
@ -16,6 +16,7 @@
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
"@radix-ui/react-toast": "^1.2.1",
|
"@radix-ui/react-toast": "^1.2.1",
|
||||||
"@radix-ui/react-tooltip": "^1.1.2",
|
"@radix-ui/react-tooltip": "^1.1.2",
|
||||||
|
"@types/react-icons": "^3.0.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
"react-day-picker": "^8.10.1",
|
"react-day-picker": "^8.10.1",
|
||||||
"react-desktop": "^0.3.9",
|
"react-desktop": "^0.3.9",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-icons": "^5.2.1",
|
||||||
"react-resizable-panels": "^2.0.20",
|
"react-resizable-panels": "^2.0.20",
|
||||||
"tailwind-merge": "^2.4.0",
|
"tailwind-merge": "^2.4.0",
|
||||||
"tailwindcss-animate": "^1.0.7"
|
"tailwindcss-animate": "^1.0.7"
|
||||||
|
|
|
@ -23,6 +23,9 @@ importers:
|
||||||
'@radix-ui/react-tooltip':
|
'@radix-ui/react-tooltip':
|
||||||
specifier: ^1.1.2
|
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)
|
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)
|
||||||
|
'@types/react-icons':
|
||||||
|
specifier: ^3.0.0
|
||||||
|
version: 3.0.0(react@18.3.1)
|
||||||
class-variance-authority:
|
class-variance-authority:
|
||||||
specifier: ^0.7.0
|
specifier: ^0.7.0
|
||||||
version: 0.7.0
|
version: 0.7.0
|
||||||
|
@ -56,6 +59,9 @@ importers:
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
version: 18.3.1(react@18.3.1)
|
version: 18.3.1(react@18.3.1)
|
||||||
|
react-icons:
|
||||||
|
specifier: ^5.2.1
|
||||||
|
version: 5.2.1(react@18.3.1)
|
||||||
react-resizable-panels:
|
react-resizable-panels:
|
||||||
specifier: ^2.0.20
|
specifier: ^2.0.20
|
||||||
version: 2.0.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 2.0.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
@ -1110,6 +1116,10 @@ packages:
|
||||||
'@types/react-dom@18.3.0':
|
'@types/react-dom@18.3.0':
|
||||||
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
||||||
|
|
||||||
|
'@types/react-icons@3.0.0':
|
||||||
|
resolution: {integrity: sha512-Vefs6LkLqF61vfV7AiAqls+vpR94q67gunhMueDznG+msAkrYgRxl7gYjNem/kZ+as2l2mNChmF1jRZzzQQtMg==}
|
||||||
|
deprecated: This is a stub types definition. react-icons provides its own type definitions, so you do not need this installed.
|
||||||
|
|
||||||
'@types/react@18.3.3':
|
'@types/react@18.3.3':
|
||||||
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
|
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
|
||||||
|
|
||||||
|
@ -2403,6 +2413,11 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^18.3.1
|
react: ^18.3.1
|
||||||
|
|
||||||
|
react-icons@5.2.1:
|
||||||
|
resolution: {integrity: sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '*'
|
||||||
|
|
||||||
react-is@16.13.1:
|
react-is@16.13.1:
|
||||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||||
|
|
||||||
|
@ -3852,6 +3867,12 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
|
|
||||||
|
'@types/react-icons@3.0.0(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
react-icons: 5.2.1(react@18.3.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- react
|
||||||
|
|
||||||
'@types/react@18.3.3':
|
'@types/react@18.3.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/prop-types': 15.7.12
|
'@types/prop-types': 15.7.12
|
||||||
|
@ -4011,7 +4032,7 @@ snapshots:
|
||||||
|
|
||||||
app-builder-bin@4.0.0: {}
|
app-builder-bin@4.0.0: {}
|
||||||
|
|
||||||
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)):
|
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)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@develar/schema-utils': 2.6.5
|
'@develar/schema-utils': 2.6.5
|
||||||
'@electron/notarize': 2.2.1
|
'@electron/notarize': 2.2.1
|
||||||
|
@ -4025,7 +4046,7 @@ snapshots:
|
||||||
builder-util-runtime: 9.2.4
|
builder-util-runtime: 9.2.4
|
||||||
chromium-pickle-js: 0.2.0
|
chromium-pickle-js: 0.2.0
|
||||||
debug: 4.3.5
|
debug: 4.3.5
|
||||||
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))
|
||||||
ejs: 3.1.10
|
ejs: 3.1.10
|
||||||
electron-builder-squirrel-windows: 24.13.3(dmg-builder@24.13.3)
|
electron-builder-squirrel-windows: 24.13.3(dmg-builder@24.13.3)
|
||||||
electron-publish: 24.13.1
|
electron-publish: 24.13.1
|
||||||
|
@ -4397,9 +4418,9 @@ snapshots:
|
||||||
|
|
||||||
dlv@1.1.3: {}
|
dlv@1.1.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)):
|
||||||
dependencies:
|
dependencies:
|
||||||
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))
|
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))
|
||||||
builder-util: 24.13.1
|
builder-util: 24.13.1
|
||||||
builder-util-runtime: 9.2.4
|
builder-util-runtime: 9.2.4
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
|
@ -4439,7 +4460,7 @@ snapshots:
|
||||||
|
|
||||||
electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3):
|
electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
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))
|
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))
|
||||||
archiver: 5.3.2
|
archiver: 5.3.2
|
||||||
builder-util: 24.13.1
|
builder-util: 24.13.1
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
|
@ -4449,11 +4470,11 @@ snapshots:
|
||||||
|
|
||||||
electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)):
|
electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
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))
|
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))
|
||||||
builder-util: 24.13.1
|
builder-util: 24.13.1
|
||||||
builder-util-runtime: 9.2.4
|
builder-util-runtime: 9.2.4
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
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))
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
is-ci: 3.0.1
|
is-ci: 3.0.1
|
||||||
lazy-val: 1.0.5
|
lazy-val: 1.0.5
|
||||||
|
@ -5281,6 +5302,10 @@ snapshots:
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
scheduler: 0.23.2
|
scheduler: 0.23.2
|
||||||
|
|
||||||
|
react-icons@5.2.1(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
|
||||||
react-is@16.13.1: {}
|
react-is@16.13.1: {}
|
||||||
|
|
||||||
react-refresh@0.14.2: {}
|
react-refresh@0.14.2: {}
|
||||||
|
|
|
@ -1,23 +1,43 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Actions, BorderNode, DockLocation, IJsonModel, ITabRenderValues, ITabSetRenderValues, Layout, Model, TabNode, TabSetNode } from "flexlayout-react";
|
import {
|
||||||
|
Actions,
|
||||||
|
BorderNode,
|
||||||
|
DockLocation,
|
||||||
|
IJsonModel,
|
||||||
|
ITabRenderValues,
|
||||||
|
ITabSetRenderValues,
|
||||||
|
Layout,
|
||||||
|
Model,
|
||||||
|
TabNode,
|
||||||
|
TabSetNode,
|
||||||
|
} from "flexlayout-react";
|
||||||
import "flexlayout-react/style/light.css";
|
import "flexlayout-react/style/light.css";
|
||||||
import "./Layout.css";
|
import "./Layout.css";
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip"
|
} from "@/components/ui/tooltip";
|
||||||
|
import { VscAdd } from "react-icons/vsc";
|
||||||
|
|
||||||
const json: IJsonModel = {
|
const json: IJsonModel = {
|
||||||
global: {
|
global: {
|
||||||
tabEnableFloat: false,
|
tabEnableFloat: false,
|
||||||
tabSetMinWidth: 100,
|
tabSetMinWidth: 150,
|
||||||
tabSetMinHeight: 200,
|
tabSetMinHeight: 200,
|
||||||
tabSetTabStripHeight: 48,//tab栏高度
|
/**
|
||||||
|
* 选项卡栏高度
|
||||||
|
*/
|
||||||
|
tabSetTabStripHeight: 32, //tab栏高度
|
||||||
|
/**
|
||||||
|
* 四周边缘定位
|
||||||
|
*/
|
||||||
|
enableEdgeDock: false,
|
||||||
borderMinSize: 100,
|
borderMinSize: 100,
|
||||||
splitterSize: 2,
|
splitterSize: 2,
|
||||||
|
tabSetClassNameTabStrip: "custom-tab-strip",
|
||||||
},
|
},
|
||||||
borders: [],
|
borders: [],
|
||||||
layout: {
|
layout: {
|
||||||
|
@ -30,10 +50,10 @@ const json: IJsonModel = {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: "tab",
|
type: "tab",
|
||||||
id: 'tab1',
|
id: "tab1",
|
||||||
name: "One",
|
name: "测试22222222222",
|
||||||
component: "tabComponent",
|
component: "tabComponent",
|
||||||
config: { icon: "📘" }
|
config: { icon: "📘" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -43,10 +63,10 @@ const json: IJsonModel = {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: "tab",
|
type: "tab",
|
||||||
id: 'tab2',
|
id: "tab2",
|
||||||
name: "Two",
|
name: "Two",
|
||||||
component: "tabComponent",
|
component: "tabComponent",
|
||||||
config: { icon: "📘" }
|
config: { icon: "📘" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -54,10 +74,7 @@ const json: IJsonModel = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const FlexLayoutComponent: React.FC = () => {
|
const FlexLayoutComponent: React.FC = () => {
|
||||||
|
|
||||||
const model = Model.fromJson(json);
|
const model = Model.fromJson(json);
|
||||||
|
|
||||||
const factory = (node: TabNode) => {
|
const factory = (node: TabNode) => {
|
||||||
|
@ -69,8 +86,8 @@ const FlexLayoutComponent: React.FC = () => {
|
||||||
|
|
||||||
const renderTab = (node: TabNode, renderValues: ITabRenderValues) => {
|
const renderTab = (node: TabNode, renderValues: ITabRenderValues) => {
|
||||||
renderValues.content = (
|
renderValues.content = (
|
||||||
<div style={{ display: "flex", alignItems: "center" }}>
|
<div className="text-xs">
|
||||||
<span style={{ marginRight: 5 }}>{node.getConfig().icon}</span>
|
<span>{node.getConfig().icon}</span>
|
||||||
{renderValues.content}
|
{renderValues.content}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -82,30 +99,41 @@ const FlexLayoutComponent: React.FC = () => {
|
||||||
type: "tab",
|
type: "tab",
|
||||||
name: "New Tab",
|
name: "New Tab",
|
||||||
component: "tabComponent",
|
component: "tabComponent",
|
||||||
config: { icon: '' }
|
config: { icon: "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
// 使用 FlexLayout 的 addAction 执行添加 tab 的动作
|
// 使用 FlexLayout 的 addAction 执行添加 tab 的动作
|
||||||
const addAction = Actions.addNode(newTab, node.getId(), DockLocation.CENTER, -1);
|
const addAction = Actions.addNode(
|
||||||
|
newTab,
|
||||||
|
node.getId(),
|
||||||
|
DockLocation.CENTER,
|
||||||
|
-1
|
||||||
|
);
|
||||||
node.getModel().doAction(addAction);
|
node.getModel().doAction(addAction);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRenderTabSet = (node: TabSetNode | BorderNode, renderValues: ITabSetRenderValues) => {
|
const onRenderTabSet = (
|
||||||
|
node: TabSetNode | BorderNode,
|
||||||
const createTabButton = <TooltipProvider>
|
renderValues: ITabSetRenderValues
|
||||||
<Tooltip>
|
) => {
|
||||||
<TooltipTrigger>
|
const createTabButton = (
|
||||||
<span
|
<TooltipProvider key={node.getId() + "create"}>
|
||||||
onClick={() => addTab(node)}
|
<Tooltip>
|
||||||
key={node.getId() + 'create'}>
|
<TooltipTrigger asChild>
|
||||||
+</span>
|
<button
|
||||||
</TooltipTrigger>
|
className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground h-6 w-6"
|
||||||
<TooltipContent side="bottom">
|
onClick={() => addTab(node)}
|
||||||
<p>新建标签页</p>
|
>
|
||||||
</TooltipContent>
|
<VscAdd />
|
||||||
</Tooltip>
|
</button>
|
||||||
</TooltipProvider>
|
</TooltipTrigger>
|
||||||
renderValues.stickyButtons.push(createTabButton)
|
<TooltipContent side="bottom">
|
||||||
|
<p>新建标签页</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
renderValues.stickyButtons.push(createTabButton);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
/* Layout.css */
|
/* Layout.css */
|
||||||
|
.custom-tab-strip{
|
||||||
.custom-layout-class .flexlayout__tab_button {
|
border-bottom-color: hsl(var(--border));
|
||||||
border-radius: 10px 10px 0 0;
|
|
||||||
padding: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-layout-class .flexlayout__tab_button:hover {
|
|
||||||
background-color: #45a049;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 覆盖默认的 FlexLayout 分割线选中颜色 */
|
/* 覆盖默认的 FlexLayout 分割线选中颜色 */
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import { CommandDialogDemo } from "./CommandDialogDemo";
|
import { CommandDialogDemo } from "./CommandDialogDemo";
|
||||||
import FlexLayoutComponent from "./FlexLayoutDemo";
|
import FlexLayoutComponent from "./FlexLayoutDemo";
|
||||||
|
import { VscLayoutSidebarLeftOff } from "react-icons/vsc";
|
||||||
|
|
||||||
const LayoutMain = () => {
|
const LayoutMain = () => {
|
||||||
return (
|
return (
|
||||||
<div className="h-screen items-center">
|
<div className="h-screen">
|
||||||
{/* 此处height和 new BrowserWindow的titleBar设置一致 */}
|
{/* 此处height和 new BrowserWindow的titleBar设置一致 */}
|
||||||
<div
|
<div
|
||||||
className="drag bg-slate-50 px-20 flex items-center"
|
className="drag bg px-20 flex items-center justify-between"
|
||||||
style={{ height: 36 }}
|
style={{ height: 36 }}
|
||||||
>
|
>
|
||||||
<div className="no-drag w-screen inline-flex">
|
<div className="left">1</div>
|
||||||
|
<div className="no-drag inline-flex">
|
||||||
<CommandDialogDemo />
|
<CommandDialogDemo />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="right no-drag">
|
||||||
|
<button className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground h-6 w-6">
|
||||||
|
<VscLayoutSidebarLeftOff />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-[calc(100%-36px)] relative">
|
<div className="h-[calc(100%-36px)] relative">
|
||||||
<FlexLayoutComponent />
|
<FlexLayoutComponent />
|
||||||
|
|
|
@ -11,7 +11,7 @@ body,
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 97.25%;
|
||||||
--foreground: 240 10% 3.9%;
|
--foreground: 240 10% 3.9%;
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 240 10% 3.9%;
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user