reactdesk-core
Version:
A powerful React-based desktop environment library for creating Windows 11-like desktop interfaces with window management, taskbar, themes, and more
205 lines (195 loc) • 6.6 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { memo, lazy, useCallback, useState, useMemo, isValidElement } from "react";
import styled, { useTheme } from "styled-components";
import { X as defaultStyles, Y as m, Z as TRANSITIONS_IN_SECONDS, _ as useContext, $ as useContext$1, a0 as useContext$2, a1 as isSafari, a2 as DIV_BUTTON_PROPS, a3 as Icon, a4 as AnimatePresence, a5 as label } from "./index-CGa3ZYCK.js";
import { u as useNextFocusable, a as useTitlebarContextMenu } from "./useTitlebarContextMenu-DjUJ9T4Z.js";
const onKeyDown = (event) => {
if (!(event.target instanceof HTMLTextAreaElement)) event.preventDefault();
};
styled("div");
const Button = styled.button.attrs(({ as }) => ({
onKeyDown,
type: !as || as === "button" ? "button" : void 0
}))`
${defaultStyles}
background-color: transparent;
font-family: inherit;
max-width: ${({ $short }) => $short ? "31px" : void 0};
width: 100%;
`;
const StyledTaskbarEntry = styled(m.li)`
display: flex;
min-width: 0;
overflow: hidden;
place-content: center;
position: relative;
cursor: default;
width: ${({ theme }) => theme.sizes.taskbar.entry.maxWidth};
&::before {
background-color: ${({ $foreground, $progress, theme }) => $foreground ? $progress && $progress > 0 && $progress < 100 ? theme.colors.taskbar.foregroundProgress : theme.colors.taskbar.foreground : ""};
background-image: ${({ $progress, theme }) => $progress && $progress > 0 && $progress < 100 ? `linear-gradient(to right, ${theme.colors.progressBackground} 0% ${$progress}%, transparent ${$progress}% 100%)` : ""};
border-bottom: ${({ $progress, theme }) => `
${theme.sizes.taskbar.entry.borderSize} solid ${$progress && $progress > 0 && $progress < 100 ? theme.colors.progress : theme.colors.highlight}
`};
bottom: 2px;
content: "";
height: ${({ $foreground }) => $foreground ? "100%" : 0};
margin: ${({ $foreground }) => $foreground ? "" : "0 4px"};
position: absolute;
transition-duration: 0.1s;
transition-property: ${({ $foreground }) => $foreground ? "all" : "width"};
width: ${({ $foreground }) => $foreground ? "100%" : `calc(100% - 8px)`};
z-index: -1;
}
&:hover {
&::before {
background-color: ${({ $foreground, theme }) => $foreground ? theme.colors.taskbar.foregroundHover : theme.colors.taskbar.hover};
height: 100%;
margin: 0;
width: 100%;
}
}
&:active {
&::before {
background-color: ${({ $foreground, theme }) => $foreground ? theme.colors.taskbar.activeForeground : theme.colors.taskbar.active};
}
}
figure {
align-items: center;
display: flex;
margin-left: 4px;
padding: 4px;
figcaption {
color: ${({ theme }) => theme.colors.text};
font-size: ${({ theme }) => theme.sizes.taskbar.entry.fontSize};
margin: 0 4px;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.icon {
font-size: ${({ theme }) => theme.sizes.taskbar.entry.iconSize};
}
picture, .icon {
height: ${({ theme }) => theme.sizes.taskbar.entry.iconSize};
position: relative;
width: ${({ theme }) => theme.sizes.taskbar.entry.iconSize};
}
}
> ${Button} {
align-items: center;
display: flex;
figure {
width: 100%;
}
}
`;
const useTaskbarTransition = () => {
const {
sizes: { taskbar }
} = useTheme();
return {
animate: "active",
exit: "initial",
initial: "initial",
transition: {
duration: TRANSITIONS_IN_SECONDS.WINDOW
},
variants: {
active: { width: taskbar.entry.maxWidth },
initial: { width: 0 }
}
};
};
const PeekWindow = lazy(() => import("./PeekWindow-xF6uH7jm.js"));
const TaskbarEntry = ({
icon,
id,
title,
...otherProps
}) => {
const nextFocusableId = useNextFocusable(id);
const { foregroundId, setForegroundId, setPreviewID } = useContext();
const isForeground = id === foregroundId;
const {
linkElement,
minimize,
windows: { [id]: currentWindow }
} = useContext$1();
const { enablePeek } = useContext$2();
const { minimized, progress } = currentWindow || {};
const linkTaskbarEntry = useCallback(
(taskbarEntry) => {
if (taskbarEntry) linkElement(id, "taskbarEntry", taskbarEntry);
},
[id, linkElement]
);
const [isPeekVisible, setIsPeekVisible] = useState(false);
const hidePeek = () => {
setIsPeekVisible(false);
setPreviewID(false);
};
const showPeek = () => {
setIsPeekVisible(true);
setPreviewID(id);
};
const onClick = () => {
if (minimized || isForeground) minimize(id);
setForegroundId(isForeground ? nextFocusableId : id);
};
const focusable = useMemo(() => isSafari() ? DIV_BUTTON_PROPS : {}, []);
const renderIcon = useMemo(() => {
if (typeof icon === "string") {
return /* @__PURE__ */ jsx(Icon, { alt: title, imgSize: 24, src: icon });
} else if (isValidElement(icon)) {
return /* @__PURE__ */ jsx("div", { className: "icon", children: icon });
} else if (typeof icon === "function") {
const IconComponent = icon;
return /* @__PURE__ */ jsx("div", { className: "icon", children: /* @__PURE__ */ jsx(IconComponent, {}) });
}
}, [icon, title]);
const stopPropagation = (event) => {
event.stopPropagation();
};
return /* @__PURE__ */ jsxs(
StyledTaskbarEntry,
{
$foreground: isForeground,
$progress: progress,
onClick: hidePeek,
onMouseEnter: showPeek,
onMouseLeave: hidePeek,
onMouseDown: stopPropagation,
...useTaskbarTransition(),
...useTitlebarContextMenu(id),
...otherProps,
children: [
enablePeek && /* @__PURE__ */ jsx(AnimatePresence, { initial: false, presenceAffectsLayout: false, children: isPeekVisible && /* @__PURE__ */ jsx(PeekWindow, { id }) }),
/* @__PURE__ */ jsx(
Button,
{
as: "div",
ref: linkTaskbarEntry,
onClick,
...focusable,
...label(title),
children: /* @__PURE__ */ jsxs("figure", { children: [
renderIcon,
/* @__PURE__ */ jsx("figcaption", { children: title })
] })
}
)
]
}
);
};
const index = memo(TaskbarEntry);
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
default: index
}, Symbol.toStringTag, { value: "Module" }));
export {
StyledTaskbarEntry as S,
index$1 as i
};
//# sourceMappingURL=index-BA88Gpwx.js.map