menu routing/structure + nav

This commit is contained in:
dragonwocky 2021-09-28 12:59:56 +10:00
parent a2b93cb513
commit f7c597ebb3
5 changed files with 141 additions and 108 deletions

View File

@ -42,7 +42,7 @@ export const reloadTabs = () => chrome.runtime.sendMessage({ action: 'reloadTabs
/** a notification displayed when the menu is opened for the first time */
export const welcomeNotification = {
id: '84e2d49b-c3dc-44b4-a154-cf589676bfa0',
color: 'blue',
// color: 'blue',
icon: 'message-circle',
message: 'Welcome! Come chat with us on Discord.',
link: 'https://discord.gg/sFWPXtA',

View File

@ -9,8 +9,6 @@
const _id = 'a6621988-551d-495a-97d8-3c568bca2e9e';
import { env, storage, web, fmt, fs, registry, regexers } from '../../api/_.mjs';
document.querySelector('img[data-notion]').addEventListener('click', env.focusNotion);
import * as router from './router.js';
const components = {};

View File

@ -24,7 +24,8 @@ const mapColorVariables = (color) => ({
setup({
preflight: {
body: apply`px-4 py-3 bg-notion-bg font-sans`,
html: apply`w-full h-full`,
body: apply`w-full h-full bg-notion-bg font-sans text-foreground`,
},
theme: {
fontFamily: {
@ -91,7 +92,7 @@ document.addEventListener('visibilitychange', loadTheme);
loadTheme();
const notifications = {
$container: web.html`<div class="${tw`absolute bottom-3 right-4 w-80`}"></div>`,
$container: web.html`<div class="${tw`absolute bottom-0 right-0 px-4 py-3 max-w-full w-96`}"></div>`,
cache: await db.get(['notifications'], []),
provider: [
env.welcomeNotification,
@ -99,7 +100,9 @@ const notifications = {
],
add({ icon, message, id = undefined, color = undefined, link = undefined }) {
const style = tw`p-2 ${
color ? `bg-${color}-tag text-${color}-tag-text` : 'bg-notion-popup text-foreground'
color
? `bg-${color}-tag text-${color}-tag-text border border-${color}-text hover:bg-${color}-text`
: 'bg-notion-popup text-foreground hover:bg-interactive-hover border border-notion-divider'
} flex items-center rounded-full mt-3 shadow-md cursor-pointer`,
$notification = web.render(
link
@ -143,3 +146,57 @@ if (errors.length) {
color: 'red',
});
}
// mod config
const $container = web.html`<div class="${tw`flex w-full h-full`}"></div>`,
$nav = web.html`<nav class="${tw`px-4 py-3 flex items-center border-b border-notion-divider space-x-4`}"></nav>`,
$main = web.html`<main class="${tw`transition px-4 py-3`}">abc</main>`,
$footer = web.html`<footer></footer>`,
$sidebar = web.html`<article class="${tw`h-full w-96 bg-notion-secondary border-l border-notion-divider`}"></article>`;
const $notion = web.html`<h1 class="${tw`flex items-center font-semibold text-xl cursor-pointer select-none mr-4`}">
${(await fs.getText('icon/colour.svg')).replace(
/width="\d+" height="\d+"/,
`class="${tw`h-6 w-6 mr-3`}"`
)}
<a href="https://notion-enhancer.github.io/" target="_blank">notion-enhancer</a>
</h1>`;
$notion.children[0].addEventListener('click', env.focusNotion);
const navItemStyle = tw`px-3 py-2 rounded-md text-sm font-medium bg-interactive hover:bg-interactive-hover`,
selectedNavItemStyle = tw`px-3 py-2 rounded-md text-sm font-medium ring-1 ring-notion-divider bg-notion-secondary`;
const $extensionsNavItem = web.html`<a href="?view=extensions" class="${navItemStyle}">extensions</a>`,
$themesNavItem = web.html`<a href="?view=themes" class="${navItemStyle}">themes</a>`,
$supportNavItem = web.html`<a href="https://discord.gg/sFWPXtA" class="${navItemStyle}">support</a>`;
web.render(
document.body,
web.render(
$container,
web.render(
web.html`<div class="${tw`h-full flex-auto`}"></div>`,
web.render($nav, $notion, $extensionsNavItem, $themesNavItem, $supportNavItem),
$main,
$footer
),
$sidebar
)
);
import * as router from './router.mjs';
router.addView('extensions', () => {
$themesNavItem.className = navItemStyle;
$extensionsNavItem.className = selectedNavItemStyle;
web.empty($main);
web.render($main, 123);
});
router.addView('themes', () => {
$extensionsNavItem.className = navItemStyle;
$themesNavItem.className = selectedNavItemStyle;
web.empty($main);
web.render($main, 456);
});
router.listen('extensions', $main);

View File

@ -1,102 +0,0 @@
/*
* notion-enhancer core: menu
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
* (https://notion-enhancer.github.io/) under the MIT license
*/
'use strict';
import { web } from '../../api/_.mjs';
export const getSearch = () =>
new Map(
location.search
.slice(1)
.split('&')
.map((query) => query.split('='))
);
let defaultView = '';
const views = new Map(),
filters = new Map();
export function setDefaultView(name) {
defaultView = name;
}
export function addView(name, loader, filter = () => {}) {
views.set(name, loader);
filters.set(name, filter);
}
export function removeView(name) {
views.delete(name);
filters.delete(name);
}
function router(event) {
event.preventDefault();
const anchor = event.path.find((anchor) => anchor.nodeName === 'A');
if (location.search !== anchor.getAttribute('href')) {
window.history.pushState(
{ search: anchor.getAttribute('href'), hash: '' },
'',
anchor.href
);
load();
}
}
function navigator(event) {
event.preventDefault();
const anchor = event.path.find((anchor) => anchor.nodeName === 'A'),
hash = anchor.getAttribute('href').slice(1);
document.getElementById(hash).scrollIntoView(true);
document.documentElement.scrollTop = 0;
history.replaceState({ search: location.search, hash }, null, `#${hash}`);
}
export async function load(force = false) {
const $container = document.querySelector('main'),
search = getSearch(),
fallbackView = () => {
window.history.replaceState(
{ search: `?view=${defaultView}`, hash: '' },
null,
`?view=${defaultView}`
);
return load();
};
if (force || !search.get('view') || document.body.dataset.view !== search.get('view')) {
if (views.get(search.get('view'))) {
const $body = await (views.get(search.get('view')) || (() => void 0))();
if ($body) {
$container.style.opacity = 0;
await new Promise((res, rej) =>
setTimeout(() => {
document.body.dataset.view = search.get('view');
$container.innerHTML = '';
$container.append($body);
requestAnimationFrame(() => {
$container.style.opacity = '';
setTimeout(res, 200);
});
}, 200)
);
} else return fallbackView();
} else return fallbackView();
}
if (filters.get(search.get('view'))) filters.get(search.get('view'))(search);
}
window.addEventListener('popstate', (event) => {
if (event.state) load();
document.getElementById(location.hash.slice(1))?.scrollIntoView(true);
document.documentElement.scrollTop = 0;
});
web.addDocumentObserver((mutation) => {
mutation.target.querySelectorAll('a[href^="?"]').forEach((a) => {
a.removeEventListener('click', router);
a.addEventListener('click', router);
});
mutation.target.querySelectorAll('a[href^="#"]').forEach((a) => {
a.removeEventListener('click', navigator);
a.addEventListener('click', navigator);
});
});

View File

@ -0,0 +1,80 @@
/*
* notion-enhancer core: menu
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
* (https://notion-enhancer.github.io/) under the MIT license
*/
'use strict';
import { web } from '../../api/_.mjs';
export const queryParams = () => new URLSearchParams(window.location.search);
let _defaultView = '',
$viewRoot;
const _views = new Map();
export function addView(name, loadFunc) {
_views.set(name, loadFunc);
}
export function removeView(name) {
_views.delete(name);
}
function router(event) {
event.preventDefault();
const anchor = event.path.find((anchor) => anchor.nodeName === 'A');
if (location.search !== anchor.getAttribute('href')) {
window.history.pushState(null, null, anchor.href);
listen();
}
}
function navigator(event) {
event.preventDefault();
const anchor = event.path.find((anchor) => anchor.nodeName === 'A'),
hash = anchor.getAttribute('href').slice(1);
document.getElementById(hash).scrollIntoView(true);
document.documentElement.scrollTop = 0;
history.replaceState({ search: location.search, hash }, null, `#${hash}`);
}
export async function listen(defaultView = null, $elem = null) {
if (defaultView) _defaultView = defaultView;
if ($elem) $viewRoot = $elem;
if (!$viewRoot) throw new Error('no view root set.');
if (!_defaultView) throw new Error('no view root set.');
const query = queryParams(),
fallbackView = () => {
window.history.replaceState(null, null, `?view=${_defaultView}`);
return listen();
};
if (!query.get('view') || document.body.dataset.view !== query.get('view')) {
if (_views.get(query.get('view'))) {
$viewRoot.style.opacity = 0;
const loadFunc = _views.get(query.get('view'))();
setTimeout(async () => {
await loadFunc;
requestAnimationFrame(() => {
$viewRoot.style.opacity = '';
});
}, 200);
} else return fallbackView();
} else return fallbackView();
}
window.addEventListener('popstate', (event) => {
if (event.state) listen();
document.getElementById(location.hash.slice(1))?.scrollIntoView(true);
document.documentElement.scrollTop = 0;
});
web.addDocumentObserver((mutation) => {
mutation.target.querySelectorAll('a[href^="?"]').forEach((a) => {
a.removeEventListener('click', router);
a.addEventListener('click', router);
});
mutation.target.querySelectorAll('a[href^="#"]').forEach((a) => {
a.removeEventListener('click', navigator);
a.addEventListener('click', navigator);
});
});