feat(menu): add reload btn to footer, move return to category btn to footer

This commit is contained in:
dragonwocky 2023-01-16 19:29:53 +11:00
parent 4456871f6d
commit 7bafbedc67
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
3 changed files with 84 additions and 31 deletions

View File

@ -55,6 +55,17 @@ function SidebarButton({ id, icon, ...props }, ...children) {
return $el;
}
function Footer({}, ...children) {
const { html } = globalThis.__enhancerApi;
return html`<div
class="flex w-full px-[60px] py-[16px]
border-t-(& [color:var(--theme--fg-border)])
bg-[color:var(--theme--bg-primary)]"
>
${children}
</div>`;
}
function View({ id }, ...children) {
const { html } = globalThis.__enhancerApi,
$el = html`<article
@ -122,10 +133,10 @@ function View({ id }, ...children) {
return $el;
}
function List({ description }, ...children) {
function List({ id, description }, ...children) {
const { html } = globalThis.__enhancerApi;
return html`<div class="flex flex-col gap-y-[14px]">
<${Search} items=${children} />
<${Search} type=${id} items=${children} />
<p
class="notion-enhancer--menu-description
text-([12px] [color:var(--theme--fg-secondary)])"
@ -135,13 +146,15 @@ function List({ description }, ...children) {
</div>`;
}
function Search({ items, oninput, ...props }) {
function Search({ type, items, oninput, ...props }) {
const { html, addKeyListener } = globalThis.__enhancerApi,
$search = html`<${Input}
size="lg"
type="text"
placeholder="Search ${items.length} ${items.length === 1
? type.replace(/s$/, "")
: type} (Press '/' to focus)"
icon="search"
placeholder="Search ('/' to focus)"
oninput=${(event) => {
oninput?.(event);
const query = event.target.value.toLowerCase();
@ -251,7 +264,7 @@ function Option({ type, value, description, _get, _set, ...props }) {
return html`<h4
class="notion-enhancer--menu-heading font-semibold
mb-[16px] mt-[48px] first:mt-0 pb-[12px] text-[16px]
border-b border-b-[color:var(--theme--fg-border)]"
border-b-(& [color:var(--theme--fg-border)])"
>
${label}
</h4>`;
@ -296,17 +309,23 @@ function Option({ type, value, description, _get, _set, ...props }) {
<//>`;
}
function Button({ icon, ...props }, children) {
const { html } = globalThis.__enhancerApi;
function Button({ primary, icon, class: cls, ...props }, children) {
const { html } = globalThis.__enhancerApi,
$icon = icon
? html`<i class="i-${icon} w-[18px] h-[18px] mr-[8px]"></i>`
: "";
return html`<button
class="mt-[14px] first:mt-0 mb-[14px] last:mb-0
flex items-center h-[32px] px-[12px] rounded-[4px]
cursor-pointer border-(& [color:var(--theme--fg-border)])
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
class="flex items-center h-[32px] px-[12px] ${cls}
rounded-[4px] transition duration-[20ms] ${primary
? `text-[color:var(--theme--accent-primary_contrast)]
font-medium bg-[color:var(--theme--accent-primary)]
hover:bg-[color:var(--theme--accent-primary\\_hover)]`
: `border-(& [color:var(--theme--fg-border)])
hover:bg-[color:var(--theme--bg-hover)]`}"
...${props}
>
<i class="i-${icon} w-[18px] h-[18px]"></i>
<span class="ml-[8px] text-[14px]">${children}</span>
${$icon}
<span class="text-[14px]">${children}</span>
</button>`;
}
@ -680,6 +699,7 @@ export {
Sidebar,
SidebarSection,
SidebarButton,
Footer,
View,
List,
Mod,

View File

@ -44,6 +44,7 @@ body {
height: 100vh;
color: var(--theme--fg-primary);
font-family: var(--theme--font-sans);
overflow: hidden;
}
body > #skeleton {

View File

@ -9,6 +9,7 @@ import {
Sidebar,
SidebarSection,
SidebarButton,
Footer,
View,
List,
Mod,
@ -61,18 +62,18 @@ const renderSidebar = (items, categories) => {
}
return $sidebar;
},
renderList = async (mods, description) => {
renderList = async (id, mods, description) => {
const { html, getProfile, initDatabase } = globalThis.__enhancerApi,
enabledMods = initDatabase([await getProfile(), "enabledMods"]);
mods = mods.map(async (mod) => {
const _get = () => enabledMods.get(mod.id),
_set = async (enabled) => {
await enabledMods.set(mod.id, enabled);
setState({ rerender: true });
setState({ rerender: true, databaseUpdated: true });
};
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
});
return html`<${List} description=${description}>
return html`<${List} ...${{ id, description }}>
${await Promise.all(mods)}
<//>`;
},
@ -98,7 +99,7 @@ const renderSidebar = (items, categories) => {
const _get = () => db.get(opt.key),
_set = async (value) => {
await db.set(opt.key, value);
setState({ rerender: true });
setState({ rerender: true, databaseUpdated: true });
};
return html`<${Option} ...${{ ...opt, _get, _set }} />`;
});
@ -115,17 +116,9 @@ const renderSidebar = (items, categories) => {
const _get = () => enabledMods.get(mod.id),
_set = async (enabled) => {
await enabledMods.set(mod.id, enabled);
setState({ rerender: true });
setState({ rerender: true, databaseUpdated: true });
};
return html`<${View} id=${mod.id}>
<${Button}
icon="chevron-left"
onclick=${() => {
setState({ transition: "slide-to-left", view: category.id });
}}
>
${category.title}
<//>
<${Mod} ...${{ ...mod, options: [], _get, _set }} />
${await renderOptions(mod)}
<//>`;
@ -134,8 +127,8 @@ const renderSidebar = (items, categories) => {
};
const render = async () => {
const { html, getCore, getThemes } = globalThis.__enhancerApi,
{ getExtensions, getIntegrations } = globalThis.__enhancerApi,
const { html, reloadApp, getCore } = globalThis.__enhancerApi,
{ getThemes, getExtensions, getIntegrations } = globalThis.__enhancerApi,
[icon, renderStarted] = getState(["icon", "renderStarted"]);
if (!html || !getCore || !icon || renderStarted) return;
setState({ renderStarted: true });
@ -210,18 +203,57 @@ const render = async () => {
];
// view wrapper necessary for transitions
const $views = html`<div class="relative overflow-hidden">
const $views = html`<div class="grow relative overflow-hidden">
<${View} id="welcome">welcome<//>
<${View} id="core">${await renderOptions(await getCore())}<//>
</div>`;
for (const { id, title, description, mods } of categories) {
const $list = await renderList(mods, description),
const $list = await renderList(id, mods, description),
$mods = await renderMods({ id, title }, mods);
$views.append(html`<${View} id=${id}>${$list}<//>`, ...$mods);
}
categories.forEach((c) => {
c.button = html`<${Button}
icon="chevron-left"
onclick=${() => setState({ transition: "slide-to-left", view: c.id })}
>
${c.title}
<//>`;
});
const $reload = html`<${Button}
primary
class="ml-auto"
icon="refresh-cw"
onclick=${() => reloadApp()}
style="display: none"
>
Reload & Apply Changes
<//>`,
$footer = html`<${Footer}>${categories.map((c) => c.button)}${$reload}<//>`,
$main = html`<div class="flex flex-col overflow-hidden transition-[height]">
${$views} ${$footer}
</div>`,
updateFooter = () => {
const buttons = [...$footer.children],
renderFooter = buttons.some(($el) => $el.style.display === "");
$main.style.height = renderFooter ? "100%" : "calc(100% + 65px)";
};
useState(["view"], ([view]) => {
for (const { mods, button } of categories) {
const renderButton = mods.some((mod) => mod.id === view);
button.style.display = renderButton ? "" : "none";
updateFooter();
}
});
useState(["databaseUpdated"], ([databaseUpdated]) => {
if (!databaseUpdated) return;
$reload.style.display = "";
updateFooter();
});
const $skeleton = document.querySelector("#skeleton");
$skeleton.replaceWith(renderSidebar(sidebar, categories), $views);
$skeleton.replaceWith(renderSidebar(sidebar, categories), $main);
};
window.addEventListener("focus", () => setState({ rerender: true }));