* CommandPalette: Rewrite with modular API and Raycast-style UI Replace the monolithic palette with a command/page registry, capture-phase keyboard routing, fuzzy search with pins and aliases, form pages including Send DM with markdown preview, and a top-anchored shell layout. * CommandPalette: Fix stylelint errors in palette CSS Reorder selectors for no-descending-specificity, replace deprecated word-break, and use overflow shorthand on picker list. * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
/*
|
|
* Vencord, a Discord client mod
|
|
* Copyright (c) 2026 Vendicated and contributors
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
import { classNameFactory } from "@utils/css";
|
|
import { useEffect, useRef } from "@webpack/common";
|
|
|
|
import type { PaletteAction } from "../api/types";
|
|
import { PaletteIcon } from "./PaletteIcon";
|
|
|
|
const cl = classNameFactory("vc-cmdpal-");
|
|
|
|
interface ActionsPanelProps {
|
|
actions: PaletteAction[];
|
|
selectedIndex: number;
|
|
onSelect(index: number): void;
|
|
onRun(action: PaletteAction): void;
|
|
}
|
|
|
|
function PanelRow({ action, selected, index, onSelect, onRun }: {
|
|
action: PaletteAction;
|
|
selected: boolean;
|
|
index: number;
|
|
onSelect(index: number): void;
|
|
onRun(action: PaletteAction): void;
|
|
}) {
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (selected) ref.current?.scrollIntoView({ block: "nearest" });
|
|
}, [selected]);
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className={cl("panel-row", { "panel-row-selected": selected })}
|
|
onMouseMove={() => { if (!selected) onSelect(index); }}
|
|
onClick={() => onRun(action)}
|
|
>
|
|
<div className={cl("chip-wrap", "chip-wrap-sm")}>
|
|
<PaletteIcon icon={action.icon} className={typeof action.icon === "string" ? cl("chip-img") : cl("panel-icon")} />
|
|
</div>
|
|
<span className={cl("panel-label")}>{action.label}</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function ActionsPanel({ actions, selectedIndex, onSelect, onRun }: ActionsPanelProps) {
|
|
return (
|
|
<div className={cl("panel")}>
|
|
<div className={cl("panel-title")}>Actions</div>
|
|
<div className={cl("panel-list")}>
|
|
{actions.map((action, i) => (
|
|
<PanelRow
|
|
key={action.id}
|
|
action={action}
|
|
index={i}
|
|
selected={i === selectedIndex}
|
|
onSelect={onSelect}
|
|
onRun={onRun}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|