UNPKG

@wener/console

Version:

Base console UI toolkit

203 lines (202 loc) 9.87 kB
import React, { memo, useMemo } from "react"; import { HiOutlineLogout } from "react-icons/hi"; import { HiLockClosed, HiMiniArrowsPointingIn, HiOutlineIdentification, HiQuestionMarkCircle } from "react-icons/hi2"; import { PiBrowser, PiBrowsersLight } from "react-icons/pi"; import { VscClose, VscCloseAll, VscPrimitiveSquare } from "react-icons/vsc"; import { Link } from "react-router-dom"; import { FloatingFocusManager, FloatingPortal, useTransitionStyles } from "@floating-ui/react"; import { getUserStore } from "@wener/console/console"; import { getUserAction } from "@wener/console/console/user"; import { usePopover } from "@wener/console/floating"; import { cn } from "@wener/console/tw"; import { getRootWindow, Window } from "@wener/console/web/window"; import clsx from "clsx"; import { useStore } from "zustand"; import { shallow } from "zustand/shallow"; import { useStoreWithEqualityFn } from "zustand/traditional"; import { isDev } from "../../../const.js"; import { DockClock } from "./DockClock.js"; import { DockUserAvatar } from "./DockUserAvatar.js"; export const DockLayout = ({ children, dock = /*#__PURE__*/ React.createElement(Dock, null) }) => { return /*#__PURE__*/ React.createElement("div", { className: clsx("flex h-screen w-full overflow-hidden", "flex-col md:flex-row") }, /*#__PURE__*/ React.createElement("main", { className: "relative order-5 h-full flex-1 overflow-auto" }, /*#__PURE__*/ React.createElement("div", { className: "scrollbar-thin absolute inset-0" }, children)), /*#__PURE__*/ React.createElement("aside", { className: clsx("border-color flex items-center", "order-1 w-full border-b px-2", "md:order-6 md:w-[57px] md:w-auto md:flex-col md:border-b-0 md:border-l md:px-0") }, dock)); }; const UserAvatar = () => { const { id, loginName, fullName, photoUrl, avatarUrl = photoUrl } = useStore(getUserStore()); const hasNotification = false; const { signOut, signIn, lock, refreshProfile } = getUserAction(); return /*#__PURE__*/ React.createElement(DockUserAvatar, { loginName, fullName, avatarUrl, hasNotification, onSignIn: signIn, onSignOut: signOut }, /*#__PURE__*/ React.createElement(Link, { to: `/user/${id}`, type: "button", className: "btn btn-ghost flex h-auto w-full flex-col items-start py-2" }, /*#__PURE__*/ React.createElement("div", { className: "text-lg font-medium" }, fullName), /*#__PURE__*/ React.createElement("div", { className: "flex items-baseline justify-between gap-4" }, loginName && /*#__PURE__*/ React.createElement("small", { title: "\u767B\u5F55\u540D", className: "opacity-75" }, "@", loginName))), /*#__PURE__*/ React.createElement("hr", { className: "my-2 border-base-200" }), /*#__PURE__*/ React.createElement("ul", { className: "menu p-2" }, /*#__PURE__*/ React.createElement("li", { key: "refreshProfile" }, /*#__PURE__*/ React.createElement("button", { type: "button", onClick: refreshProfile }, /*#__PURE__*/ React.createElement(HiOutlineIdentification, null), "\u5237\u65B0\u4E2A\u4EBA\u4FE1\u606F")), /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("button", { type: "button", onClick: lock }, /*#__PURE__*/ React.createElement(HiLockClosed, null), "\u9501\u5B9A")), /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("button", { type: "button", onClick: signOut }, /*#__PURE__*/ React.createElement(HiOutlineLogout, null), "\u9000\u51FA\u767B\u5F55")), isDev() && /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("button", { type: "button", onClick: () => { // getUserSessionState().expired = true; } }, /*#__PURE__*/ React.createElement(HiQuestionMarkCircle, null), "\u767B\u5F55\u5931\u6548")))); }; const Dock = /*#__PURE__*/ memo(() => { return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("header", { className: "flex flex-col items-center gap-1 py-1" }, /*#__PURE__*/ React.createElement(UserAvatar, null)), /*#__PURE__*/ React.createElement("div", { className: "relative flex w-full flex-1 flex-col gap-1" }, /*#__PURE__*/ React.createElement(WindowControl, null), /*#__PURE__*/ React.createElement("div", { className: "relative w-full flex-1" }, /*#__PURE__*/ React.createElement("div", { className: "absolute inset-0 overflow-y-auto" }, /*#__PURE__*/ React.createElement(WindowDocks, null)))), /*#__PURE__*/ React.createElement("footer", { className: "flex flex-col items-center" }, /*#__PURE__*/ React.createElement(DockClock, null))); }); const WindowControlPopoverContent = (props) => { const root = getRootWindow(); // 避免单次操作内 layout 发生变化 const top = useMemo(() => root.top, []); const count = root.windows.length; return /*#__PURE__*/ React.createElement("ul", { className: "border-color menu menu-sm w-44 rounded-box border bg-base-100", ...props }, top && /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("li", { className: "menu-title" }, "\u5F53\u524D\u7A97\u53E3"), /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("a", { onClick: () => { top.close(); } }, /*#__PURE__*/ React.createElement(VscClose, null), "\u5173\u95ED")), /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("a", { onClick: () => { top.center(); } }, /*#__PURE__*/ React.createElement(VscPrimitiveSquare, null), "\u5C45\u4E2D"))), /*#__PURE__*/ React.createElement("li", { className: "menu-title" }, "\u7A97\u53E3\u7BA1\u7406 (", count, ")"), /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("a", { onClick: () => { Window.closeAll(); } }, /*#__PURE__*/ React.createElement(VscCloseAll, null), "\u5173\u95ED\u6240\u6709\u7A97\u53E3")), /*#__PURE__*/ React.createElement("li", null, /*#__PURE__*/ React.createElement("a", { onClick: () => { Window.minimizeAll(); } }, /*#__PURE__*/ React.createElement(HiMiniArrowsPointingIn, null), "\u6700\u5C0F\u5316\u6240\u6709\u7A97\u53E3"))); }; const WindowControl = /*#__PURE__*/ memo(() => { const { refs, getFloatingProps, getReferenceProps, open, setOpen, floatingStyles, context, nodeId } = usePopover({ placement: "left-start" }); const { isMounted, styles } = useTransitionStyles(context, { initial: { opacity: 0, transform: "translateY(-10px)" }, close: { opacity: 0, transform: "translateY(10px)" } }); return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("button", { type: "button", className: "btn btn-square btn-ghost btn-sm self-center", ref: refs.setReference, ...getReferenceProps() }, /*#__PURE__*/ React.createElement(PiBrowsersLight, { className: "h-5 w-5 opacity-75" })), isMounted && /*#__PURE__*/ React.createElement(FloatingFocusManager, { context: context }, /*#__PURE__*/ React.createElement("div", { ref: refs.setFloating, ...getFloatingProps(), style: floatingStyles, className: "z-50" }, /*#__PURE__*/ React.createElement(WindowControlPopoverContent, { style: styles, onClick: () => { setOpen(false); } })))); }); const WindowDock = /*#__PURE__*/ memo(({ win }) => { const iconClass = "w-8 h-8 "; const { minimized, icon, title } = useStoreWithEqualityFn(win.store, ({ minimized, icon, title }) => { if ( /*#__PURE__*/React.isValidElement(icon)) { icon = /*#__PURE__*/ React.cloneElement(icon, { className: iconClass }); } return { minimized, icon, title }; }, shallow); const { refs, open, context, floatingStyles, getFloatingProps, getReferenceProps } = usePopover({ hover: true, placement: "left" }); return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("button", { type: "button", className: cn("h-10 w-10", `flex items-center justify-center text-base-content hover:text-base-content`, "rounded-lg bg-base-200", !minimized ? `active bg-base-300` : "opacity-75"), ...getReferenceProps(), onClick: () => { win.minimize(); }, ref: refs.setReference }, icon ?? /*#__PURE__*/ React.createElement(PiBrowser, { className: iconClass })), open && /*#__PURE__*/ React.createElement(FloatingPortal, null, /*#__PURE__*/ React.createElement(FloatingFocusManager, { context: context }, /*#__PURE__*/ React.createElement("div", { className: "rounded bg-base-200 p-1 text-xs opacity-85", ref: refs.setFloating, ...getFloatingProps(), style: floatingStyles }, title)))); }); const WindowDocks = /*#__PURE__*/ memo(() => { const windows = useStoreWithEqualityFn(getRootWindow().store, (s) => s.windows, shallow); return /*#__PURE__*/ React.createElement("div", { className: "flex flex-col items-center gap-0.5" }, windows.map((win) => { return /*#__PURE__*/ React.createElement(WindowDock, { key: win.id, win: win }); })); }); Dock.displayName = "Dock"; //# sourceMappingURL=DockLayout.js.map