mirror of
https://github.com/stackrender/stackrender.git
synced 2026-09-10 19:25:44 +00:00
dark theme implemented
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@heroui/react": "^2.7.6",
|
||||
"@nextui-org/react": "^2.6.11",
|
||||
"@powersync/drizzle-driver": "^0.4.0",
|
||||
"@powersync/react": "^1.5.3",
|
||||
"@powersync/web": "^1.20.0",
|
||||
@@ -25,6 +26,7 @@
|
||||
"framer-motion": "11.15.0",
|
||||
"i18next-browser-languagedetector": "^8.0.5",
|
||||
"lucide-react": "^0.501.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-i18next": "^15.5.1",
|
||||
|
||||
+24
-12
@@ -1,4 +1,5 @@
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
|
||||
|
||||
import "@/styles/globals.css"
|
||||
import { TooltipProvider } from "./components/tooltip/tooltip";
|
||||
import { ReactFlowProvider } from "@xyflow/react";
|
||||
@@ -6,21 +7,32 @@ import useAppRoutes from "./routes/app-route";
|
||||
import { SyncProvider } from "./providers/sync-provider/sync-provider";
|
||||
import DatabaseProvider from "./providers/database-provider/database-provider";
|
||||
import DiagramProvider from "./providers/diagram-provider/diagram-provider";
|
||||
import { NextUIProvider } from "@nextui-org/react";
|
||||
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
||||
|
||||
|
||||
function App() {
|
||||
|
||||
const appRoutes = useAppRoutes();
|
||||
return (
|
||||
<SyncProvider>
|
||||
<ReactFlowProvider>
|
||||
<DatabaseProvider>
|
||||
<DiagramProvider>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
{appRoutes}
|
||||
</TooltipProvider>
|
||||
</DiagramProvider>
|
||||
</DatabaseProvider>
|
||||
</ReactFlowProvider>
|
||||
</SyncProvider>
|
||||
<NextUIProvider>
|
||||
<NextThemesProvider
|
||||
defaultTheme='system'
|
||||
attribute='class'
|
||||
>
|
||||
<SyncProvider>
|
||||
<ReactFlowProvider>
|
||||
<DatabaseProvider>
|
||||
<DiagramProvider>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
{appRoutes}
|
||||
</TooltipProvider>
|
||||
</DiagramProvider>
|
||||
</DatabaseProvider>
|
||||
</ReactFlowProvider>
|
||||
</SyncProvider>
|
||||
</NextThemesProvider>
|
||||
</NextUIProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ const CardinalityMarker: React.FC<CardinalityMarkerProps> = ({ selected = false,
|
||||
>
|
||||
<svg
|
||||
fill="transparent"
|
||||
className={selected ? "stroke-primary" : "stroke-slate-300"}
|
||||
className={selected ? "stroke-primary" : "stroke-slate-300 dark:stroke-default-400"}
|
||||
strokeWidth="8"
|
||||
width="24"
|
||||
height="24"
|
||||
|
||||
@@ -27,7 +27,7 @@ const ColorPicker: React.FC<ColorPickerProps> = ({ defaultColor, onChange }) =>
|
||||
<Popover placement="bottom" radius="sm" isOpen={isOpen} onOpenChange={(open) => setIsOpen(open)}>
|
||||
<PopoverTrigger>
|
||||
<Button size="sm"
|
||||
className="size-8 cursor-pointer rounded-md border-2 border-muted transition-shadow hover:shadow-md"
|
||||
className="size-8 cursor-pointer rounded-md border-2 border-muted transition-shadow hover:shadow-md dark:border-default-100"
|
||||
isIconOnly
|
||||
style={{
|
||||
backgroundColor: color ? color : undefined
|
||||
@@ -41,7 +41,7 @@ const ColorPicker: React.FC<ColorPickerProps> = ({ defaultColor, onChange }) =>
|
||||
{colorOptions.map(color => (
|
||||
<div
|
||||
key={color}
|
||||
className="size-8 cursor-pointer rounded-md border-2 border-muted transition-shadow hover:shadow-md"
|
||||
className="size-8 cursor-pointer rounded-md border-2 border-muted transition-shadow hover:shadow-md dark:border-default-100"
|
||||
style={{
|
||||
backgroundColor: color
|
||||
}}
|
||||
@@ -54,7 +54,7 @@ const ColorPicker: React.FC<ColorPickerProps> = ({ defaultColor, onChange }) =>
|
||||
<TooltipTrigger>
|
||||
<div
|
||||
key={undefined}
|
||||
className="size-8 cursor-pointer rounded-md border-2 border-muted transition-shadow hover:shadow-md"
|
||||
className="size-8 cursor-pointer rounded-md border-2 border-muted transition-shadow hover:shadow-md dark:border-default-100"
|
||||
style={{
|
||||
backgroundColor: "white"
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Dropdown, DropdownMenu as HeroDropdownMenu, DropdownItem, DropdownTrigger, Button, useDisclosure, Popover, PopoverTrigger, PopoverContent, Divider, DropdownSection } from "@heroui/react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import SubmenuDropdown from "./submenu-dropdown";
|
||||
|
||||
|
||||
@@ -19,24 +19,26 @@ export interface MenuDropdownProps {
|
||||
isDisabled?: boolean,
|
||||
divide?: boolean,
|
||||
shortcut?: string,
|
||||
isOpen?: boolean
|
||||
isOpen?: boolean ,
|
||||
clickHandler? : () => void
|
||||
}
|
||||
|
||||
|
||||
|
||||
const DropdownMenu: React.FC<MenuDropdownProps> = ({ title, children, isOpen }) => {
|
||||
|
||||
const DropdownMenu: React.FC<MenuDropdownProps> = ({ title, children, isOpen , clickHandler }) => {
|
||||
|
||||
|
||||
|
||||
|
||||
const disabledChilds: string[] = useMemo(() => {
|
||||
return children ? children?.filter((child: MenuDropdownProps) => child.isDisabled && child.title).map((child: MenuDropdownProps) => child.title as string) : []
|
||||
}, [children]);
|
||||
|
||||
|
||||
|
||||
return <Dropdown radius="sm" >
|
||||
{
|
||||
title &&
|
||||
<DropdownTrigger >
|
||||
<DropdownTrigger onPressEnd={clickHandler}>
|
||||
<Button size="sm" variant="light" >
|
||||
<span className=" text-left flex justify-between text-small font-semibold">
|
||||
{title}
|
||||
@@ -54,8 +56,10 @@ const DropdownMenu: React.FC<MenuDropdownProps> = ({ title, children, isOpen })
|
||||
className={child.theme == "danger" ? "text-danger" : ""}
|
||||
color={child.theme}
|
||||
shortcut={child.shortcut}
|
||||
>
|
||||
onPressEnd={ child.clickHandler }
|
||||
>
|
||||
{
|
||||
|
||||
!child.children ?
|
||||
<div>
|
||||
{child.title}
|
||||
@@ -66,7 +70,7 @@ const DropdownMenu: React.FC<MenuDropdownProps> = ({ title, children, isOpen })
|
||||
</div>
|
||||
:
|
||||
<div >
|
||||
<SubmenuDropdown {...child} />
|
||||
<SubmenuDropdown {...child} />
|
||||
{
|
||||
child.divide &&
|
||||
<div className="w-full h-[0.5px] absolute bottom-[-0.5px] left-0 bg-default-200"></div>
|
||||
|
||||
+115
-96
@@ -1,115 +1,134 @@
|
||||
|
||||
import { useTheme } from "next-themes";
|
||||
import DropdownMenu, { MenuDropdownProps } from "./menu-dropdown";
|
||||
import { useMemo } from "react";
|
||||
import { menuItem } from "@heroui/react";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const menu: MenuDropdownProps[] = [
|
||||
{
|
||||
title: "File",
|
||||
|
||||
children: [{
|
||||
title: "New"
|
||||
},
|
||||
{
|
||||
title: "Open",
|
||||
shortcut: "Ctnl + O"
|
||||
}, {
|
||||
title: "Save",
|
||||
shortcut: "Ctnl + S",
|
||||
divide: true
|
||||
}, {
|
||||
title: "Import",
|
||||
divide: true,
|
||||
children: [{
|
||||
title: ".json",
|
||||
}, {
|
||||
title: ".dbml"
|
||||
}, {
|
||||
title: "MySql"
|
||||
}, {
|
||||
title: "Postgresql"
|
||||
}]
|
||||
}, {
|
||||
title: "Export SQL",
|
||||
children: [{
|
||||
title: "Generic",
|
||||
}, {
|
||||
title: "MySql"
|
||||
}, {
|
||||
title: "Postgresql"
|
||||
}]
|
||||
}, {
|
||||
title: "Export ORM Models",
|
||||
divide: true
|
||||
}, {
|
||||
title: "Delete Project",
|
||||
theme: "danger"
|
||||
}]
|
||||
}, {
|
||||
title: "Edit",
|
||||
|
||||
children: [{
|
||||
title: "Undo",
|
||||
isDisabled: true,
|
||||
},
|
||||
{
|
||||
title: "Redo",
|
||||
|
||||
isDisabled: true,
|
||||
}, {
|
||||
title: "Clear",
|
||||
|
||||
}]
|
||||
} , {
|
||||
title : "View" ,
|
||||
children : [{
|
||||
title : "Hide Controller" ,
|
||||
shortcut : "Ctnl + B" ,
|
||||
divide : true
|
||||
} , {
|
||||
title : "Zoom on scroll" ,
|
||||
divide : true ,
|
||||
children : [{
|
||||
title : "On"
|
||||
} , {
|
||||
title : "Off"
|
||||
}] ,
|
||||
|
||||
} , {
|
||||
title : "Theme" ,
|
||||
|
||||
children : [{
|
||||
title : "Light"
|
||||
} , {
|
||||
title : "Dark"
|
||||
}]
|
||||
}]
|
||||
} , {
|
||||
title : "Help" ,
|
||||
children : [{
|
||||
title : "Show Docs" ,
|
||||
} , {
|
||||
title : "Join Discord"
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
interface MenuProps {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Menu: React.FC<MenuProps> = ({ }) => {
|
||||
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
|
||||
|
||||
|
||||
|
||||
const menu: MenuDropdownProps[] = useMemo(() => [
|
||||
{
|
||||
title: "File",
|
||||
|
||||
children: [{
|
||||
title: "New"
|
||||
},
|
||||
{
|
||||
title: "Open",
|
||||
shortcut: "Ctnl + O"
|
||||
}, {
|
||||
title: "Save",
|
||||
shortcut: "Ctnl + S",
|
||||
divide: true
|
||||
}, {
|
||||
title: "Import",
|
||||
divide: true,
|
||||
children: [{
|
||||
title: ".json",
|
||||
}, {
|
||||
title: ".dbml"
|
||||
}, {
|
||||
title: "MySql"
|
||||
}, {
|
||||
title: "Postgresql"
|
||||
}]
|
||||
}, {
|
||||
title: "Export SQL",
|
||||
children: [{
|
||||
title: "Generic",
|
||||
}, {
|
||||
title: "MySql"
|
||||
}, {
|
||||
title: "Postgresql"
|
||||
}]
|
||||
}, {
|
||||
title: "Export ORM Models",
|
||||
divide: true
|
||||
}, {
|
||||
title: "Delete Project",
|
||||
theme: "danger"
|
||||
}]
|
||||
}, {
|
||||
title: "Edit",
|
||||
clickHandler: () => {
|
||||
console.log("hello wo")
|
||||
},
|
||||
|
||||
children: [{
|
||||
title: "Undo",
|
||||
isDisabled: true,
|
||||
},
|
||||
{
|
||||
title: "Redo",
|
||||
|
||||
isDisabled: true,
|
||||
}, {
|
||||
title: "Clear",
|
||||
|
||||
}]
|
||||
}, {
|
||||
title: "View",
|
||||
children: [{
|
||||
title: "Hide Controller",
|
||||
shortcut: "Ctnl + B",
|
||||
divide: true
|
||||
}, {
|
||||
title: "Zoom on scroll",
|
||||
divide: true,
|
||||
children: [{
|
||||
title: "On"
|
||||
}, {
|
||||
title: "Off"
|
||||
}],
|
||||
|
||||
}, {
|
||||
title: "Theme",
|
||||
clickHandler: () => {
|
||||
console.log("hello wo")
|
||||
},
|
||||
children: [{
|
||||
title: "Light",
|
||||
clickHandler: () => {
|
||||
|
||||
setTheme("light") ;
|
||||
}
|
||||
}, {
|
||||
title: "Dark",
|
||||
clickHandler: () => {
|
||||
|
||||
setTheme("dark") ;
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
title: "Help",
|
||||
children: [{
|
||||
title: "Show Docs",
|
||||
}, {
|
||||
title: "Join Discord"
|
||||
}]
|
||||
}
|
||||
], []);
|
||||
|
||||
|
||||
return menu.map(menuItem => (
|
||||
<DropdownMenu {...menuItem} />
|
||||
<DropdownMenu {...menuItem} />
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NavbarBrand, NavbarContent, Navbar as NavbarContainer, Image, Dropdown, DropdownTrigger, Button, DropdownMenu, DropdownItem } from "@heroui/react";
|
||||
import Menu from "../menu/menu";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -7,17 +8,19 @@ interface Props {
|
||||
|
||||
|
||||
const Navbar: React.FC<Props> = ({ }) => {
|
||||
const {resolvedTheme} = useTheme() ;
|
||||
|
||||
return (
|
||||
|
||||
<nav className="h-12 fixed z-50 bg-background w-full flex items-center p-4 border-b border-default-200">
|
||||
<img
|
||||
src="/stackrender.png"
|
||||
src={`/stackrender.png`}
|
||||
width={22}
|
||||
alt="logo"
|
||||
|
||||
|
||||
/>
|
||||
<h3 className="font-semibold ml-2 text-slate-900 text-sm">StackRender</h3>
|
||||
<h3 className="font-semibold ml-2 text-slate-900 text-sm dark:text-white">StackRender</h3>
|
||||
<div className="ml-4">
|
||||
<Menu/>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ const SidebarItem: React.FC<SidebarItemProps> = ({ title, icon, href , type = "i
|
||||
return (
|
||||
<Tooltip delayDuration={0} >
|
||||
<TooltipTrigger asChild>
|
||||
<Link to={href as string} className="p-2 rounded-md hover:bg-default-200 sidebar-item" data-active={isActive}>
|
||||
<Link to={href as string} className="p-2 rounded-md hover:bg-default-200 sidebar-item " data-active={isActive}>
|
||||
{icon}
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
@@ -36,7 +36,7 @@ const SidebarItem: React.FC<SidebarItemProps> = ({ title, icon, href , type = "i
|
||||
|
||||
)
|
||||
else {
|
||||
return <Divider className="bg-default-200" />
|
||||
return <Divider className="bg-default-200 dark:bg-default-100" />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,12 @@ interface SidebarProps {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const sidebarItemClass : string = "text-gray-700 size-4 data-[active=true]:text-primary" ;
|
||||
const sidebarItemClass : string = "text-gray-700 dark:text-default-500 size-4 data-[active=true]:text-primary" ;
|
||||
|
||||
const Sidebar: React.FC<SidebarProps> = ({ }) => {
|
||||
const { t , i18n } = useTranslation() ;
|
||||
|
||||
|
||||
const { t } = useTranslation() ;
|
||||
|
||||
|
||||
const location = useLocation() ;
|
||||
|
||||
const sidebarItems: SidebarItemProps[] = useMemo(() => [
|
||||
@@ -88,7 +87,7 @@ const Sidebar: React.FC<SidebarProps> = ({ }) => {
|
||||
|
||||
return (
|
||||
|
||||
<aside className="h-full z-[20] flex flex-col items-between py-2 justify-between sticky top-0 duration-500 w-12 bg-sidebar border-r pt-[56px]">
|
||||
<aside className="h-full z-[20] flex flex-col items-between py-2 justify-between sticky top-0 duration-500 w-12 bg-sidebar dark:bg-background border-r pt-[56px] dark:border-default-100">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
{
|
||||
sidebarItems.map((item: SidebarItemProps) => (
|
||||
|
||||
@@ -20,10 +20,10 @@ const ToggleButton: React.FC<ToggleProps> = ({ active = false, children, onToggl
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button className={
|
||||
cn("p-1 px-2 transition-all hover:bg-default rounded duration-200 ",
|
||||
cn("p-1 px-2 transition-all hover:bg-default rounded duration-200 dark:text-default-400",
|
||||
className ? className : "",
|
||||
active ?
|
||||
"text-slate-700 bg-default/80 " :
|
||||
"text-slate-700 bg-default/80 dark:text-white dark:bg-default/50" :
|
||||
"text-icon"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ const TooltipContent = React.forwardRef<
|
||||
<TooltipPrimitive.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
|
||||
|
||||
className={cn(
|
||||
'z-50 overflow-hidden rounded-md bg-foreground 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',
|
||||
'z-50 overflow-hidden rounded-md bg-foreground dark:bg-default-50 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}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/tooltip/to
|
||||
import { Button } from "@heroui/react";
|
||||
import { LayoutGrid } from "lucide-react";
|
||||
import { adjustTablesPositions } from "@/utils/tables";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +30,8 @@ const DatabasePage: React.FC<never> = () => {
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||
const { setIsConnectionInProgress } = useDiagram();
|
||||
const [selectedNodeIds, setSelectedNodeIds] = useState<string[]>([]);
|
||||
|
||||
|
||||
const { fitView } = useReactFlow();
|
||||
|
||||
const nodeTypes = useMemo(() => ({ table: Table }), []);
|
||||
@@ -157,7 +160,7 @@ const DatabasePage: React.FC<never> = () => {
|
||||
<div className="absolute top-[160px]">
|
||||
|
||||
</div>
|
||||
<Controls>
|
||||
<Controls >
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
@@ -179,7 +182,7 @@ const DatabasePage: React.FC<never> = () => {
|
||||
</Tooltip>
|
||||
|
||||
</Controls>
|
||||
<Background className="bg-default/30" />
|
||||
<Background className="bg-default/30 dark:bg-black" />
|
||||
</ReactFlow>
|
||||
|
||||
<svg style={{ position: 'absolute', width: 0, height: 0 }}>
|
||||
|
||||
@@ -9,7 +9,7 @@ interface Props {
|
||||
|
||||
const DBController : React.FC<Props> = ({ }) => {
|
||||
return(
|
||||
<div className="w-[640px] h-full bg-background border-r p-2 pt-[52px] ">
|
||||
<div className="w-[640px] h-full bg-background border-r p-2 pt-[52px] border-default-100">
|
||||
<Outlet/>
|
||||
</div>
|
||||
)
|
||||
|
||||
+6
-6
@@ -44,13 +44,13 @@ const RelationshipAccordionBody: React.FC<RelationshipAccordionBodyProps> = ({ r
|
||||
<div className="w-full p-2 space-y-4">
|
||||
<div className="flex">
|
||||
<div className="w-full space-y-1">
|
||||
<label className="font-medium flex text-slate-700 flex items-center gap-1 text-sm">
|
||||
<FileOutput className="size-4" />
|
||||
<label className="font-medium flex text-slate-700 flex items-center gap-1 text-sm dark:text-default-600">
|
||||
<FileOutput className="size-4 " />
|
||||
{t("db_controller.source_table")}
|
||||
</label>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<span className="truncate text-left text-sm">
|
||||
<span className="truncate text-left text-sm dark:text-default-500">
|
||||
{relationship.sourceTable?.name}({relationship.sourceField?.name})
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
@@ -61,7 +61,7 @@ const RelationshipAccordionBody: React.FC<RelationshipAccordionBodyProps> = ({ r
|
||||
</div>
|
||||
|
||||
<div className="w-full space-y-1">
|
||||
<label className="font-medium flex text-slate-700 flex items-center gap-1 text-sm">
|
||||
<label className="font-medium flex text-slate-700 flex items-center gap-1 text-sm dark:text-default-600">
|
||||
<FileMinus2 className="size-4" />
|
||||
{t("db_controller.target_table")}
|
||||
|
||||
@@ -69,7 +69,7 @@ const RelationshipAccordionBody: React.FC<RelationshipAccordionBodyProps> = ({ r
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<span className="truncate text-left text-sm ">
|
||||
<span className="truncate text-left text-sm dark:text-default-500 ">
|
||||
{relationship.targetTable?.name}({relationship.targetField?.name})
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
@@ -80,7 +80,7 @@ const RelationshipAccordionBody: React.FC<RelationshipAccordionBodyProps> = ({ r
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="flex text-sm font-medium flex text-slate-700 items-center gap-1">
|
||||
<label className="flex text-sm font-medium flex text-slate-700 items-center gap-1 dark:text-default-600">
|
||||
<ChevronsLeftRightEllipsis className="size-4 " />
|
||||
{t('db_controller.cardinality.name')}
|
||||
</label>
|
||||
|
||||
+7
-7
@@ -59,16 +59,16 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
onValueChange={setName}
|
||||
onBlur={editRelationshipName}
|
||||
type="text"
|
||||
className="rounded-md px-2 py-0.5 w-full border-blue-400 focus-visible:ring-0 dark:bg-slate-900 text-sm "
|
||||
className="rounded-md px-2 py-0.5 w-full border-blue-400 focus-visible:ring-0 text-sm "
|
||||
/>
|
||||
<Button
|
||||
variant="light"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-200"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 "
|
||||
size="sm"
|
||||
onPress={editRelationshipName}
|
||||
isIconOnly
|
||||
>
|
||||
<Check className="size-4 text-icon" />
|
||||
<Check className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
@@ -77,7 +77,7 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
!editMode && <>
|
||||
|
||||
<label
|
||||
className="w-full truncate px-2 py-1 text-sm font-semibold text-black"
|
||||
className="w-full truncate px-2 py-1 text-sm font-semibold text-black dark:text-white"
|
||||
>
|
||||
{relationship.name ? relationship.name : defaultName}
|
||||
</label>
|
||||
@@ -89,7 +89,7 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
variant="light"
|
||||
onPressEnd={() => focusOnRelationship(relationship.id, true)}
|
||||
>
|
||||
<Focus className="size-4 text-icon" />
|
||||
<Focus className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -97,7 +97,7 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
variant="light"
|
||||
onPress={() => setEditMode(true)}
|
||||
>
|
||||
<Pencil className="size-4 text-icon" />
|
||||
<Pencil className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -110,7 +110,7 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
isIconOnly
|
||||
variant="light"
|
||||
>
|
||||
<EllipsisVertical className="size-4 text-slate-500" />
|
||||
<EllipsisVertical className="size-4 text-slate-500 dark:text-white" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[160px]" >
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ const RelationshipController: React.FC<Props> = ({ }) => {
|
||||
aria-label={relationship.id}
|
||||
|
||||
classNames={{
|
||||
trigger: "w-full hover:bg-default transition-all duration-200 h-12",
|
||||
trigger: "w-full hover:bg-default transition-all duration-200 h-12 dark:bg-background dark:hover:bg-default-50",
|
||||
base: "rounded-md p-0 overflow-hidden",
|
||||
}}
|
||||
subtitle={
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ const FieldItem: React.FC<Props> = ({ field }) => {
|
||||
<div className="flex w-full gap-1 items-center " style={style} ref={setNodeRef} {...attributes}>
|
||||
|
||||
<div {...listeners}>
|
||||
<GripVertical className="size-4 text-icon cursor-move" />
|
||||
<GripVertical className="size-4 text-icon cursor-move dark:text-default-400 dark:hover:text-white" />
|
||||
</div>
|
||||
<Input
|
||||
variant="bordered"
|
||||
@@ -130,7 +130,7 @@ const FieldItem: React.FC<Props> = ({ field }) => {
|
||||
isIconOnly
|
||||
variant="light"
|
||||
>
|
||||
<EllipsisVertical className="size-4 text-slate-500" />
|
||||
<EllipsisVertical className="size-4 text-slate-500 dark:text-default-600" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[210px]" >
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ const FieldList: React.FC<Props> = ({ table }) => {
|
||||
radius="sm"
|
||||
|
||||
startContent={
|
||||
<Plus className="size-4 text-icon" />
|
||||
<Plus className="size-4 text-icon dark:text-white" />
|
||||
}
|
||||
className="h-8 p-2 text-xs bg-transparent hover:bg-default text-gray font-semibold"
|
||||
onPressEnd={addField}
|
||||
|
||||
+17
-19
@@ -25,7 +25,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
const { editTable, createField } = useDatabase();
|
||||
|
||||
const onColorChange = useCallback((color: string | undefined) => {
|
||||
|
||||
|
||||
editTable({ id: table.id, color: color ? color : null } as TableType);
|
||||
}, [table]);
|
||||
|
||||
@@ -49,7 +49,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full dark:bg-background">
|
||||
<Accordion
|
||||
isCompact
|
||||
variant={"light"} selectionMode="multiple" selectedKeys={selectedKeys} onSelectionChange={setSelectedKeys as any}>
|
||||
@@ -59,17 +59,15 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
'tarnsition-all duration-200 ',
|
||||
isOpen ? "rotate-[-90deg]" : ""
|
||||
)}>
|
||||
|
||||
<ChevronLeft className="size-4 text-icon" />
|
||||
|
||||
<ChevronLeft className="size-4 text-icon dark:text-default-600" />
|
||||
</div>
|
||||
)}
|
||||
classNames={{
|
||||
trigger: "hover:bg-default h-6 "
|
||||
trigger: "hover:bg-default h-6 dark:hover:bg-background"
|
||||
}}
|
||||
subtitle={
|
||||
<div className="group flex gap-2 items-center font-medium p-1 w-full hover:underline text-slate-500 hover:text-slate-600 transition-all duration-200">
|
||||
<FileType className="size-4" />
|
||||
<div className="group dark:text-default-600 flex gap-2 items-center font-medium p-1 w-full hover:underline text-slate-500 hover:text-slate-600 transition-all duration-200 dark:hover:text-white">
|
||||
<FileType className="size-4 " />
|
||||
<label className="text-sm w-full cursor-pointer">
|
||||
{t("db_controller.fields")}
|
||||
</label>
|
||||
@@ -77,7 +75,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
className="size-4 p-0 text-xs opacity-0 group-hover:opacity-100 transition-all duration-200 hover:text-slate-700 text-icon"
|
||||
onClick={addField}
|
||||
>
|
||||
<Plus className="size-4 " />
|
||||
<Plus className="size-4 dark:text-default-600" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@@ -90,14 +88,14 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
'tarnsition-all duration-200',
|
||||
isOpen ? "rotate-[-90deg]" : ""
|
||||
)}>
|
||||
<ChevronLeft className="size-4 text-icon" />
|
||||
<ChevronLeft className="size-4 text-icon dark:text-default-600" />
|
||||
</div>
|
||||
)}
|
||||
classNames={{
|
||||
trigger: "hover:bg-default h-6"
|
||||
trigger: "hover:bg-default h-6 dark:hover:bg-background"
|
||||
}}
|
||||
subtitle={
|
||||
<div className="flex gap-2 items-center font-medium p-1 w-full hover:underline text-slate-500 hover:text-slate-600 transition-all duration-200">
|
||||
<div className="flex gap-2 dark:text-default-600 items-center font-medium p-1 w-full hover:underline text-slate-500 hover:text-slate-600 transition-all duration-200 dark:hover:text-white">
|
||||
<FileKey className="size-4 " />
|
||||
<label className="text-sm w-full cursor-pointer">
|
||||
{t("db_controller.indexes")}
|
||||
@@ -112,14 +110,14 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
'tarnsition-all duration-200',
|
||||
isOpen ? "rotate-[-90deg]" : ""
|
||||
)}>
|
||||
<ChevronLeft className="size-4 text-icon" />
|
||||
<ChevronLeft className="size-4 text-icon dark:text-default-600" />
|
||||
</div>
|
||||
)}
|
||||
classNames={{
|
||||
trigger: "hover:bg-default h-6"
|
||||
trigger: "hover:bg-default h-6 dark:hover:bg-background"
|
||||
}}
|
||||
subtitle={
|
||||
<div className="flex gap-2 items-center font-medium p-1 w-full hover:underline text-slate-500 hover:text-slate-600 transition-all duration-200">
|
||||
<div className="flex gap-2 dark:text-default-600 items-center font-medium p-1 w-full hover:underline text-slate-500 hover:text-slate-600 transition-all duration-200 dark:hover:text-white">
|
||||
<MessageSquareQuote className="size-4" />
|
||||
<label className="text-sm w-full cursor-pointer">
|
||||
{t("db_controller.note")}
|
||||
@@ -128,7 +126,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
}>
|
||||
<Textarea variant="bordered" className="w-full " label={t("db_controller.table_note")}
|
||||
classNames={{
|
||||
inputWrapper: "bg-default/80",
|
||||
inputWrapper: "bg-default/80 ",
|
||||
}}
|
||||
value={note}
|
||||
onValueChange={setNote}
|
||||
@@ -137,7 +135,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
/>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
<hr className="bg-default-200" />
|
||||
<hr className="bg-default-200 dark:invisible" />
|
||||
<div className="flex p-2 pb-0 items-start">
|
||||
<div className="w-full">
|
||||
<ColorPicker
|
||||
@@ -150,7 +148,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="font-semibold p-4"
|
||||
className="font-semibold p-4 border-default-50"
|
||||
startContent={
|
||||
<FileKey className="size-4 " />
|
||||
}
|
||||
@@ -161,7 +159,7 @@ const TableAccordionBody: React.FC<TableAccordionBodyProps> = ({ table }) => {
|
||||
onPressEnd={addField}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="font-semibold p-4"
|
||||
className="font-semibold p-4 border-default-50"
|
||||
startContent={
|
||||
<FileType className="size-4 " />
|
||||
}
|
||||
|
||||
+12
-15
@@ -40,8 +40,6 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
setPopOverOpen(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const addField = () => {
|
||||
setPopOverOpen(false)
|
||||
createField({
|
||||
@@ -54,7 +52,7 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="group w-full flex h-12 gap-1 border-l-4 flex p-2 items-center border-l-[6px] "
|
||||
<div className="group w-full flex h-12 gap-1 border-l-4 flex p-2 items-center border-l-[6px] border-default"
|
||||
style={{
|
||||
borderColor: table.color as string | undefined
|
||||
}}
|
||||
@@ -63,10 +61,9 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
'tarnsition-all duration-200',
|
||||
isOpen ? "rotate-[90deg]" : ""
|
||||
)}>
|
||||
<ChevronRight className="size-4 text-icon" />
|
||||
<ChevronRight className="size-4 text-icon dark:text-white" />
|
||||
</div>
|
||||
<div className=" w-[1px] h-full bg-default-200">
|
||||
|
||||
<div className=" w-[1px] h-full bg-default-200 dark:bg-default-100">
|
||||
</div>
|
||||
{
|
||||
!editMode &&
|
||||
@@ -74,7 +71,7 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<label
|
||||
className="w-full text-editable truncate px-2 py-1 text-sm font-semibold text-black"
|
||||
className="w-full text-editable truncate px-2 py-1 text-sm font-semibold text-black dark:text-white"
|
||||
onDoubleClick={() => setEditMode(true)}
|
||||
>
|
||||
{table.name}
|
||||
@@ -97,16 +94,16 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
variant="bordered"
|
||||
onBlur={saveTableName}
|
||||
type="text"
|
||||
className="rounded-md px-2 py-0.5 w-full border-primary-700 focus-visible:ring-0 dark:bg-slate-900 text-sm "
|
||||
className="rounded-md px-2 py-0.5 w-full border-primary-700 focus-visible:ring-0 text-sm "
|
||||
/>
|
||||
<Button
|
||||
variant="light"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-200"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-white"
|
||||
size="sm"
|
||||
onPressEnd={saveTableName}
|
||||
isIconOnly
|
||||
>
|
||||
<Check className="size-4 text-icon" />
|
||||
<Check className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
@@ -122,7 +119,7 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
variant="light"
|
||||
onPress={() => setEditMode(true)}
|
||||
>
|
||||
<Pencil className="size-4 text-icon" />
|
||||
<Pencil className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -130,7 +127,7 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
variant="light"
|
||||
onPressEnd={() => focusOnTable(table.id , true)}
|
||||
>
|
||||
<Focus className="size-4 text-icon" />
|
||||
<Focus className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -141,7 +138,7 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
isIconOnly
|
||||
variant="light"
|
||||
>
|
||||
<EllipsisVertical className="size-4 text-slate-500" />
|
||||
<EllipsisVertical className="size-4 text-slate-500 dark:text-white" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[160px]" >
|
||||
@@ -156,14 +153,14 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
key="add_field"
|
||||
onPressEnd={addField}
|
||||
endContent={
|
||||
<FileType className="size-4 text-icon" />
|
||||
<FileType className="size-4 text-icon dark:text-white" />
|
||||
|
||||
}>
|
||||
Add Field
|
||||
</ListboxItem>
|
||||
<ListboxItem
|
||||
key="add_index"
|
||||
endContent={<FileKey className="size-4 text-icon " />}
|
||||
endContent={<FileKey className="size-4 text-icon dark:text-white" />}
|
||||
showDivider>
|
||||
Add Index
|
||||
</ListboxItem>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useDatabase } from "@/providers/database-provider/database-provider";
|
||||
import { TableType } from "@/lib/schemas/table-schema";
|
||||
import { v4 } from "uuid";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
|
||||
interface Props { }
|
||||
@@ -42,8 +43,9 @@ const TablesController: React.FC<Props> = ({ }) => {
|
||||
}
|
||||
} , [focusedTableId]) ;
|
||||
|
||||
const selectedTableId = selectedTable.values().next().value;
|
||||
const selectedTableId = selectedTable.values().next().value;
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-full h-full flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between gap-4 py-1">
|
||||
@@ -103,7 +105,7 @@ const TablesController: React.FC<Props> = ({ }) => {
|
||||
|
||||
<Accordion
|
||||
hideIndicator
|
||||
variant="splitted"
|
||||
variant={ "splitted"}
|
||||
selectedKeys={selectedTable}
|
||||
onSelectionChange={setSelectedTable as any}
|
||||
isCompact
|
||||
@@ -114,8 +116,8 @@ const TablesController: React.FC<Props> = ({ }) => {
|
||||
key={table.id}
|
||||
aria-label={table.name}
|
||||
classNames={{
|
||||
trigger: "w-full h-12 hover:bg-default transition-all duration-200",
|
||||
base: "rounded-md shadow p-0 overflow-hidden",
|
||||
trigger: "w-full h-12 hover:bg-default transition-all duration-200 dark:bg-background dark:hover:bg-default-50",
|
||||
base: "rounded-md shadow p-0 overflow-hidden dark:border-1 dark:border-default-100",
|
||||
}}
|
||||
subtitle={
|
||||
<TableAccordionHeader
|
||||
|
||||
@@ -52,7 +52,7 @@ const Field: React.FC<Props> = ({ field, showHandles, highlight }) => {
|
||||
|
||||
return (
|
||||
<div className={cn(
|
||||
"group relative flex h-8 items-center justify-between gap-1 border-t border-default px-3 text-sm last:rounded-b-[6px] hover:bg-slate-100 dark:hover:bg-slate-800 transition-all duration-200 ease-in-out" ,
|
||||
"group relative flex h-8 items-center justify-between gap-1 border-t border-default dark:border-default/5 px-3 text-sm last:rounded-b-[6px] hover:bg-slate-100 dark:hover:bg-primary-500 transition-all duration-200 ease-in-out" ,
|
||||
highlight ? "bg-primary/5" : ""
|
||||
)}>
|
||||
{
|
||||
@@ -60,14 +60,14 @@ const Field: React.FC<Props> = ({ field, showHandles, highlight }) => {
|
||||
<>
|
||||
<label
|
||||
className={cn(
|
||||
"truncate text-xs text-slate-900",
|
||||
"truncate text-xs text-slate-900 dark:text-default-200",
|
||||
field.isPrimary ? "font-semibold" : ""
|
||||
)}
|
||||
onDoubleClick={() => setEditMode(true)}
|
||||
>
|
||||
{field.name}
|
||||
</label>
|
||||
<span className={cn("content-center truncate flex items-center h-full gap-1 text-right text-xs text-default-600 group-hover:hidden font-semibold text-icon",
|
||||
<span className={cn("content-center truncate flex items-center h-full gap-1 text-right text-xs text-default-600 group-hover:hidden font-semibold text-icon dark:text-default-200",
|
||||
field.isPrimary ? "font-semibold text-slate-700" : ""
|
||||
)}>
|
||||
{field.isPrimary && <KeyRound className="size-3" />} {field.type?.name?.split(' ')[0]}{field.nullable ? "?" : ""}
|
||||
@@ -101,12 +101,12 @@ const Field: React.FC<Props> = ({ field, showHandles, highlight }) => {
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onChange={(e) => setFieldName(e.target.value)}
|
||||
|
||||
className="rounded-md outline-none px-2 py-0.5 w-full border-[0.5px] border-primary-700 bg-slate-100 focus-visible:ring-0 dark:bg-slate-900 text-sm "
|
||||
className="rounded-md outline-none px-2 py-0.5 w-full border-[0.5px] border-primary-700 bg-slate-100 focus-visible:ring-0 text-sm dark:bg-transparent dark:text-white"
|
||||
|
||||
/>
|
||||
<Button
|
||||
variant="light"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-200"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-white"
|
||||
size="sm"
|
||||
isIconOnly
|
||||
onPress={saveFieldName}
|
||||
@@ -125,12 +125,12 @@ const Field: React.FC<Props> = ({ field, showHandles, highlight }) => {
|
||||
type="source"
|
||||
position={Position.Left}
|
||||
id={LEFT_PREFIX + field.id}
|
||||
className="w-4 h-4 border-4 bg-primary"
|
||||
className="w-4 h-4 border-4 bg-primary dark:border-default-900"
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
className="w-4 h-4 border-4 bg-primary"
|
||||
className="w-4 h-4 border-4 bg-primary dark:border-default-900"
|
||||
id={RIGHT_PREFIX + field.id}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +125,7 @@ const Relationship: React.FC<EdgeProps<RelationshipProps>> = (props) => {
|
||||
fill="none"
|
||||
className={cn([
|
||||
|
||||
`!stroke-2 ${selected ? '!stroke-primary' : 'stroke-slate-300'}`,
|
||||
`!stroke-2 ${selected ? '!stroke-primary' : 'stroke-slate-300 dark:stroke-default-500'}`,
|
||||
|
||||
])}
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -16,7 +16,7 @@ import { FieldType } from "@/lib/schemas/field-schema";
|
||||
import { TableType } from "@/lib/schemas/table-schema";
|
||||
import { useDatabase } from "@/providers/database-provider/database-provider";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
|
||||
|
||||
@@ -65,90 +65,86 @@ const Table: React.FC<NodeProps<TableProps>> = ({ selected, data: { table } }) =
|
||||
highlight={highlight}
|
||||
/>)
|
||||
})
|
||||
}, [table.fields, selected, highlightedEdges]);
|
||||
|
||||
}, [table.fields, selected, highlightedEdges]);
|
||||
|
||||
|
||||
|
||||
|
||||
// console.log ("re-render" , table.name)
|
||||
|
||||
return (
|
||||
|
||||
<Card className={cn(
|
||||
"w-full h-full bg-background rounded-lg entity-card noselect overflow-visible ",
|
||||
selected
|
||||
? 'ring-1 ring-primary'
|
||||
: '',
|
||||
)}
|
||||
shadow="sm"
|
||||
>
|
||||
<div className="px-[2px] ">
|
||||
<div
|
||||
className=" border-t-[4px] rounded-t-[6px] border-primary"
|
||||
style={{ borderColor: table.color as string }}
|
||||
></div>
|
||||
</div>
|
||||
<div className="group gap-2 flex h-9 items-center justify-between bg-default/50 px-2 dark:bg-default ">
|
||||
<Table2 className="size-4 shrink-0 text-icon dark:text-primary" />
|
||||
{
|
||||
editMode && <>
|
||||
<input
|
||||
placeholder={table.name}
|
||||
autoFocus
|
||||
onChange={(event: any) => setTableName(event.target.value)}
|
||||
value={tableName}
|
||||
onBlur={saveTableName}
|
||||
type="text"
|
||||
className="rounded-md outline-none px-2 py-0.5 w-full border-[0.5px] border-primary-700 font-bold bg-slate-100 focus-visible:ring-0 dark:bg-slate-900 text-sm "
|
||||
/>
|
||||
<Button
|
||||
variant="light"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-200"
|
||||
size="sm"
|
||||
onPressEnd={saveTableName}
|
||||
isIconOnly
|
||||
>
|
||||
<Check className="size-3" />
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
{
|
||||
!editMode &&
|
||||
<>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<label
|
||||
className=" w-full text-editable truncate px-2 py-0.5 text-sm font-bold"
|
||||
onDoubleClick={() => setEditMode(true)}
|
||||
>
|
||||
{table.name}
|
||||
</label>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t("table.double_click")}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<div className="hidden shrink-0 flex-row group-hover:flex">
|
||||
|
||||
|
||||
<Card className={cn(
|
||||
"w-full h-full bg-background rounded-lg entity-card noselect overflow-visible dark:bg-default-900",
|
||||
selected
|
||||
? 'ring-2 ring-primary'
|
||||
: '',
|
||||
)}
|
||||
shadow="sm"
|
||||
>
|
||||
<div className="px-[2px] ">
|
||||
<div
|
||||
className=" border-t-[4px] rounded-t-[6px] border-primary"
|
||||
style={{ borderColor: table.color as string }}
|
||||
></div>
|
||||
</div>
|
||||
<div className="group gap-2 flex h-9 items-center justify-between bg-default/50 px-2 dark:bg-black/20">
|
||||
<Table2 className="size-4 shrink-0 text-icon dark:text-white" />
|
||||
{
|
||||
editMode && <>
|
||||
<input
|
||||
placeholder={table.name}
|
||||
autoFocus
|
||||
onChange={(event: any) => setTableName(event.target.value)}
|
||||
value={tableName}
|
||||
onBlur={saveTableName}
|
||||
type="text"
|
||||
className="rounded-md outline-none px-2 py-0.5 w-full border-[0.5px] border-primary-700 font-bold bg-slate-100 focus-visible:ring-0 text-sm dark:bg-transparent dark:text-white"
|
||||
/>
|
||||
<Button
|
||||
variant="light"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-white"
|
||||
size="sm"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-200"
|
||||
onPressEnd={saveTableName}
|
||||
isIconOnly
|
||||
onPressEnd={focus}
|
||||
>
|
||||
<Focus className="size-4 text-icon" />
|
||||
<Check className="size-3" />
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
<div className="transition-[max-height] duration-200 ease-in-out">
|
||||
{fields}
|
||||
</div>
|
||||
</Card>
|
||||
</>
|
||||
}
|
||||
{
|
||||
!editMode &&
|
||||
<>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<label
|
||||
className=" w-full text-editable truncate px-2 py-0.5 text-sm font-bold dark:text-white dark:group-hover:bg-default-900"
|
||||
onDoubleClick={() => setEditMode(true)}
|
||||
>
|
||||
{table.name}
|
||||
</label>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="dark:bg-default-900">
|
||||
{t("table.double_click")}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<div className="hidden shrink-0 flex-row group-hover:flex">
|
||||
|
||||
<Button
|
||||
variant="light"
|
||||
size="sm"
|
||||
className="size-6 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:hover:bg-default-800 "
|
||||
isIconOnly
|
||||
onPressEnd={focus}
|
||||
>
|
||||
<Focus className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
<div className="transition-[max-height] duration-200 ease-in-out">
|
||||
{fields}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
|
||||
)
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
.text-editable {
|
||||
@apply dark:group-hover:bg-slate-900 group-hover:bg-slate-100 group-hover:ring-[0.5px] group-hover:ring-primary-700 rounded-md cursor-pointer;
|
||||
@apply dark:group-hover:bg-default-50 group-hover:bg-slate-100 group-hover:ring-[0.5px] group-hover:ring-primary-700 dark:group-hover:ring-white rounded-md cursor-pointer ;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,23 +72,19 @@ div[data-slot="content"] hr[role="separator"] {
|
||||
}
|
||||
|
||||
/* Track (background of the scrollbar) */
|
||||
::-webkit-scrollbar-track {
|
||||
background: hsl(210 40% 96.1%) ; /* Light gray background */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Handle (the scroll thumb) */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: hsl(var(--heroui-default-300)); /* Darker gray */
|
||||
background: hsl(var(--heroui-default-100)); /* Darker gray */
|
||||
border-radius: 6px; /* Rounded corners */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
|
||||
background: hsl(var(--nextui-default-400)); /* Darker on hover */
|
||||
background: hsl(var(--heroui-default-300)); /* Darker on hover */
|
||||
}
|
||||
|
||||
+4
-8
@@ -14,10 +14,6 @@ export default {
|
||||
themes: {
|
||||
dark: {
|
||||
colors: {
|
||||
sidebar: {
|
||||
DEFAULT: 'hsl(0 0% 98%)',
|
||||
foreground: 'hsl(240 5.3% 26.1%)',
|
||||
},
|
||||
primary: {
|
||||
DEFAULT: "#9822ff",
|
||||
50: '#9822ff0D', // 5% opacity
|
||||
@@ -31,7 +27,7 @@ export default {
|
||||
800: '#961FFFCC', // 80% opacity
|
||||
900: '#9822ffE6', // 90% opacity
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
light: {
|
||||
colors: {
|
||||
@@ -45,9 +41,9 @@ export default {
|
||||
foreground: 'hsl(222.2 47.4% 11.2%)'
|
||||
},
|
||||
|
||||
icon : {
|
||||
DEFAULT : "hsl(215.4 16.3% 46.9%)"
|
||||
} ,
|
||||
icon: {
|
||||
DEFAULT: "hsl(215.4 16.3% 46.9%)"
|
||||
},
|
||||
|
||||
primary: {
|
||||
DEFAULT: "#9822ff",
|
||||
|
||||
Reference in New Issue
Block a user