/** * notion-enhancer * (c) 2023 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ import { Popup } from "./Popup.mjs"; function Option({ $icon = "", value = "", _get, _set }) { const { html, useState } = globalThis.__enhancerApi, $selected = html``, $option = html`
event.target.focus()} onclick=${() => _set?.(value)} onkeydown=${(event) => { if (["Enter", " "].includes(event.key)) _set?.(value); }} >
${$icon}${value}
`; useState(["rerender"], async () => { if ((await _get?.()) === value) { $option.append($selected); } else $selected.remove(); }); return $option; } function Select({ values, _get, _set, _requireReload = true, popupMode = "left", maxWidth = 256, ...props }) { const { html, extendProps, setState, useState } = globalThis.__enhancerApi, // dir="rtl" overflows to the left during transition $select = html`
`; const options = values.map((opt) => { if (typeof opt === "string") opt = { value: opt }; if (!(opt?.$icon instanceof Element)) { if (opt?.icon && typeof opt.icon === "string") { opt.$icon = html``; } else delete opt.$icon; } opt.$option = html`<${Option} ...${{ ...opt, _get, _set }} />`; opt.$selection = html`
${opt.value}${opt.$icon?.cloneNode(true) ?? ""}
`; return opt; }), getSelected = async () => { const value = (await _get?.()) ?? $select.innerText, option = options.find((opt) => opt.value === value); if (!option) _set(options[0].value); return option || options[0]; }, onKeydown = (event) => { const intercept = () => { event.preventDefault(); event.stopPropagation(); }; if (event.key === "Escape") { intercept(setState({ rerender: true })); } else if (!options.length) return; // prettier-ignore const $next = options.find(({ $option }) => $option === event.target) ?.$option.nextElementSibling ?? options.at(0).$option, $prev = options.find(({ $option }) => $option === event.target) ?.$option.previousElementSibling ?? options.at(-1).$option; // overflow to opposite end of list from dir of travel if (event.key === "ArrowUp") intercept($prev.focus()); if (event.key === "ArrowDown") intercept($next.focus()); // re-enable natural tab behaviour in notion interface if (event.key === "Tab") event.stopPropagation(); }; let _initialValue; useState(["rerender"], async () => { if (!options.length) return; const { value, $selection } = await getSelected(); $select.innerHTML = ""; $select.append($selection); if (_requireReload) { _initialValue ??= value; if (value !== _initialValue) setState({ databaseUpdated: true }); } }); extendProps(props, { class: "notion-enhancer--menu-select relative" }); return html`
${$select}<${Popup} tabindex="0" trigger=${$select} mode=${popupMode} onopen=${() => document.addEventListener("keydown", onKeydown, true)} onbeforeclose=${() => { document.removeEventListener("keydown", onKeydown, true); $select.style.width = `${$select.offsetWidth}px`; $select.style.background = "transparent"; }} onclose=${() => { $select.style.width = ""; $select.style.background = ""; }} >${options.map(({ $option }) => $option)}
`; } export { Select };