"use client"; import { Anchor, Card, Flex, Group, Stack, Text, Title, UnstyledButton } from "@mantine/core"; import combineClasses from "clsx"; import type { RouterOutputs } from "@homarr/api"; import { clientApi } from "@homarr/api/client"; import { useRequiredBoard } from "@homarr/boards/context"; import { useRegisterSpotlightContextResults } from "@homarr/spotlight"; import { MaskedOrNormalImage } from "@homarr/ui"; import type { WidgetComponentProps } from "../definition"; import classes from "./bookmark.module.css"; export default function BookmarksWidget({ options, itemId }: WidgetComponentProps<"bookmarks">) { const board = useRequiredBoard(); const [data] = clientApi.app.byIds.useSuspenseQuery(options.items, { select(data) { return data.sort((appA, appB) => options.items.indexOf(appA.id) - options.items.indexOf(appB.id)); }, }); useRegisterSpotlightContextResults( `bookmark-${itemId}`, data .filter((app) => app.href !== null) .map((app) => ({ id: app.id, name: app.name, icon: app.iconUrl, interaction() { return { type: "link", // We checked above that app.href is defined // eslint-disable-next-line @typescript-eslint/no-non-null-assertion href: app.href!, newTab: false, }; }, })), [data], ); return ( {options.title.length > 0 && ( {options.title} )} {(options.layout === "grid" || options.layout === "gridHorizontal") && ( )} {options.layout !== "grid" && options.layout !== "gridHorizontal" && ( )} ); } interface FlexLayoutProps { data: RouterOutputs["app"]["byIds"]; direction: "row" | "column"; hideTitle: boolean; hideIcon: boolean; hideHostname: boolean; openNewTab: boolean; hasIconColor: boolean; } const FlexLayout = ({ data, direction, hideTitle, hideIcon, hideHostname, openNewTab, hasIconColor, }: FlexLayoutProps) => { const board = useRequiredBoard(); return ( {data.map((app) => (
{direction === "row" ? ( ) : ( )}
))}
); }; interface GridLayoutProps { data: RouterOutputs["app"]["byIds"]; hideTitle: boolean; hideIcon: boolean; hideHostname: boolean; openNewTab: boolean; itemDirection: "horizontal" | "vertical"; hasIconColor: boolean; } const GridLayout = ({ data, hideTitle, hideIcon, hideHostname, openNewTab, itemDirection, hasIconColor, }: GridLayoutProps) => { const board = useRequiredBoard(); return ( {data.map((app) => ( {itemDirection === "horizontal" ? ( ) : ( )} ))} ); }; const VerticalItem = ({ app, hideTitle, hideIcon, hideHostname, hasIconColor, }: { app: RouterOutputs["app"]["byIds"][number]; hideTitle: boolean; hideIcon: boolean; hideHostname: boolean; hasIconColor: boolean; }) => { return ( {!hideTitle && ( {app.name} )} {!hideIcon && ( )} {!hideHostname && ( {app.href ? new URL(app.href).hostname : undefined} )} ); }; const HorizontalItem = ({ app, hideTitle, hideIcon, hideHostname, hasIconColor, }: { app: RouterOutputs["app"]["byIds"][number]; hideTitle: boolean; hideIcon: boolean; hideHostname: boolean; hasIconColor: boolean; }) => { return ( {!hideIcon && ( )} {!(hideTitle && hideHostname) && ( <> {!hideTitle && ( {app.name} )} {!hideHostname && ( {app.href ? new URL(app.href).hostname : undefined} )} )} ); };