///
///
///
import { Item, makeGroup } from "./item.ts";
import { Cursor, Selection, takeStores } from "../scrapbox-userscript-std/dom.ts";
import type { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
declare const scrapbox: Scrapbox;
const { cursor, selection } = takeStores();
/** ボタンの設定 */
export interface Button {
/** .status-bar > div につけるclass name */
className?: string;
/** ボタンに表示するアイテム
*
* 空文字を渡すと非表示になる
*
* 函数系は、カーソルが動くたびに呼び出される
*/
display: Item | Item[] | ((props: Omit) => Item | Item[]);
onClick: (props: ClickProps) => void;
/** ボタンを表示するページの種類
*
* トップページやstreamなど、特殊なページで使いたいボタンがあれば指定する
*
* @default "page"
*/
context?: Context;
};
export interface ClickProps {
cursor: Cursor;
selection: Selection;
setDisplay: (...items: Item[]) => void;
}
export type Context = "page" | "stream" | "list";
/** ボタンの描画情報 */
export interface ButtonComponent {
status: HTMLDivElement;
context: Context;
update: () => void;
}
export const makeButton = (init: Button): ButtonComponent => {
const { className, display, onClick, context = "page" } = init;
const status = document.createElement("div");
if (className) status.classList.add(className);
if (!isContext(context)) status.style.display = "none";
const setDisplay = (...items: Item[]) => {
// 空文字の場合は非表示にする
if (items.length === 1 && items[0] === "") {
status.style.display = "none";
return;
}
status.textContent = "";
const group = makeGroup(...items);
if (group) status.append(group);
};
const itemList = typeof display === "function" ? display({ cursor, selection }) : display;
setDisplay(...(Array.isArray(itemList) ? itemList : [itemList]));
status.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
onClick({ cursor, selection, setDisplay });
});
const update = () => {
if (isContext(context)) {
status.removeAttribute("style");
} else {
status.style.display = "none";
}
if (typeof display === "function") {
const itemList = display({ cursor, selection });
setDisplay(...(Array.isArray(itemList) ? itemList : [itemList]));
}
};
return { status, context, update };
};
const isContext = (context: Context): boolean =>
context !== "stream" ?
scrapbox.Layout === context :
scrapbox.Layout === "list" && location.pathname.startsWith("/stream");