diff --git a/src/core/client.mjs b/src/core/client.mjs
index 9899313..707151b 100644
--- a/src/core/client.mjs
+++ b/src/core/client.mjs
@@ -123,13 +123,18 @@ const insertPanel = async (api, db) => {
const notionFrame = ".notion-frame",
notionTopbarBtn = ".notion-topbar-more-button",
togglePanelHotkey = await db.get("togglePanelHotkey"),
- { html } = api;
+ { html, setState, addPanelView } = api;
const $panel = html`<${Panel}
- _getWidth=${() => db.get("sidePanelWidth")}
- _setWidth=${(width) => db.set("sidePanelWidth", width)}
- _getOpen=${() => db.get("sidePanelOpen")}
- _setOpen=${(open) => db.set("sidePanelOpen", open)}
+ ...${Object.assign(
+ ...["Width", "Open", "View"].map((key) => ({
+ [`_get${key}`]: () => db.get(`sidePanel${key}`),
+ [`_set${key}`]: async (value) => {
+ await db.set(`sidePanel${key}`, value);
+ setState({ rerender: true });
+ },
+ }))
+ )}
/>`,
togglePanel = () => {
if ($panel.hasAttribute("open")) $panel.close();
diff --git a/src/core/islands/Panel.mjs b/src/core/islands/Panel.mjs
index fc00eb3..8142976 100644
--- a/src/core/islands/Panel.mjs
+++ b/src/core/islands/Panel.mjs
@@ -7,9 +7,73 @@
import { Tooltip } from "./Tooltip.mjs";
import { Select } from "../menu/islands/Select.mjs";
-function View(props) {
- const { html } = globalThis.__enhancerApi;
- return html``;
+// note: these islands do not accept extensible
+// properties, i.e. they are not reusable.
+// please register your own interfaces via
+// globalThis.__enhancerApi.addPanelView and
+// not by re-instantiating additional panels
+
+let panelViews = [],
+ // "$icon" may either be an actual dom element,
+ // or an icon name from the lucide icons set
+ addPanelView = ({ title, $icon, $view }) => {
+ panelViews.push([{ title, $icon }, $view]);
+ panelViews.sort(([{ title: a }], [{ title: b }]) => a.localeCompare(b));
+ const { setState } = globalThis.__enhancerApi;
+ setState?.({ panelViews });
+ },
+ removePanelView = ($view) => {
+ panelViews = panelViews.filter(([, v]) => v !== $view);
+ const { setState } = globalThis.__enhancerApi;
+ setState?.({ panelViews });
+ };
+
+function View({ _get }) {
+ const { html, setState, useState } = globalThis.__enhancerApi,
+ $container = html`
`;
+ useState(["rerender"], async () => {
+ const openView = await _get?.(),
+ $view =
+ panelViews.find(([{ title }]) => {
+ return title === openView;
+ })?.[1] || panelViews[0]?.[1];
+ if (!$container.contains($view)) {
+ $container.innerHTML = "";
+ $container.append($view);
+ }
+ });
+ return $container;
+}
+
+function Switcher({ _get, _set, minWidth, maxWidth }) {
+ const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
+ $switcher = html``,
+ setView = (view) => {
+ _set?.(view);
+ setState({ activePanelView: view });
+ };
+ useState(["panelViews"], ([panelViews]) => {
+ const values = panelViews.map(([{ title, $icon }]) => {
+ // panel switcher internally uses the select island,
+ // which expects an option value rather than a title
+ return { value: title, $icon };
+ });
+ $switcher.innerHTML = "";
+ $switcher.append(html`<${Select}
+ popupMode="dropdown"
+ class="w-full text-left"
+ maxWidth=${maxWidth - 56}
+ minWidth=${minWidth - 56}
+ ...${{ _get, _set: setView, values }}
+ />`);
+ });
+ return $switcher;
}
function Panel({
@@ -17,91 +81,77 @@ function Panel({
_setWidth,
_getOpen,
_setOpen,
+ _getView,
+ _setView,
minWidth = 250,
maxWidth = 640,
transitionDuration = 300,
- ...props
}) {
- const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
- { addMutationListener, removeMutationListener } = globalThis.__enhancerApi;
- extendProps(props, {
- class: `notion-enhancer--panel order-2 shrink-0
- transition-[width] open:w-[var(--panel--width)]
- border-l-1 border-[color:var(--theme--fg-border)]
- relative bg-[color:var(--theme--bg-primary)] w-0
- duration-[${transitionDuration}ms] group/panel`,
- });
+ const { html, setState, useState } = globalThis.__enhancerApi,
+ { addMutationListener, removeMutationListener } = globalThis.__enhancerApi,
+ $panel = html``;
- const values = [
- {
- icon: "type",
- value: "word counter",
- },
- {
- // prettier-ignore
- $icon: html``,
- value: "outliner",
- },
- ],
- _get = () => useState(["panelView"])[0],
- _set = (value) => {
- setState({ panelView: value, rerender: true });
- };
-
- const $resize = html``,
- $close = html`