@wener/console
Version:
Base console UI toolkit
203 lines (202 loc) • 9.87 kB
JavaScript
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