focus/blur listeners on side panel

This commit is contained in:
dragonwocky 2021-10-19 16:38:48 +11:00
parent 860a943437
commit fe42600ab8
3 changed files with 40 additions and 20 deletions

View File

@ -29,10 +29,12 @@ export { feather } from './feather.mjs';
/**
* adds a view to the enhancer's side panel
* @param {object} panel - information used to construct and render the panel
* @param {string} [panel.id] - a uuid, used to restore the last open view on reload
* @param {string} panel.id - a uuid, used to restore the last open view on reload
* @param {string} panel.icon - an svg string
* @param {string} panel.title - the name of the view
* @param {Element} panel.$content - an element containing the content of the view
* @param {function} panel.onBlur - runs when the view is selected/focused
* @param {function} panel.onFocus - runs when the view is unfocused/closed
*/
export { addPanelView } from './panel.mjs';

View File

@ -170,6 +170,7 @@ const $panel = web.html`<div id="enhancer--panel"></div>`,
}
},
renderView = (view) => {
const prevView = _views.find(({ $content }) => document.contains($content));
web.render(
web.empty($panelTitle),
web.render(
@ -178,10 +179,13 @@ const $panel = web.html`<div id="enhancer--panel"></div>`,
view.$title
)
);
view.onFocus();
web.render(web.empty($panelContent), view.$content);
if (prevView) prevView.onBlur();
};
async function createPanel() {
await web.whenReady(['.notion-frame']);
$notionFrame = document.querySelector('.notion-frame');
const notionRightSidebarSelector = '.notion-cursor-listener > div[style*="flex-end"]',
@ -239,22 +243,35 @@ async function createViews() {
/**
* adds a view to the enhancer's side panel
* @param {object} panel - information used to construct and render the panel
* @param {string} [panel.id] - a uuid, used to restore the last open view on reload
* @param {string} panel.id - a uuid, used to restore the last open view on reload
* @param {string} panel.icon - an svg string
* @param {string} panel.title - the name of the view
* @param {Element} panel.$content - an element containing the content of the view
* @param {function} panel.onBlur - runs when the view is selected/focused
* @param {function} panel.onFocus - runs when the view is unfocused/closed
*/
export const addPanelView = async ({ id = fmt.uuidv4(), icon, title, $content }) => {
export const addPanelView = async ({
id,
icon,
title,
$content,
onFocus = () => {},
onBlur = () => {},
}) => {
const view = {
id,
$icon: web.html`<span class="enhancer--panel-view-title-icon">
${icon}
</span>`,
$title: web.html`<span class="enhancer--panel-view-title-text">
${web.escape(title)}
<span class="enhancer--panel-view-title-fade-edge"> </span>
</span>`,
$icon: web.render(
web.html`<span class="enhancer--panel-view-title-icon"></span>`,
icon instanceof Element ? icon : web.html`${icon}`
),
$title: web.render(
web.html`<span class="enhancer--panel-view-title-text"></span>`,
title,
web.html`<span class="enhancer--panel-view-title-fade-edge"></span>`
),
$content,
onFocus,
onBlur,
};
_views.push(view);
if (_views.length === 1) await createPanel();

View File

@ -194,17 +194,18 @@ export const addDocumentObserver = (callback, selectors = []) => {
if (!_documentObserver) {
const handle = (queue) => {
while (queue.length) {
const event = queue.shift();
const event = queue.shift(),
matchesAddedNode = ($node, selector) =>
$node instanceof Element &&
($node.matches(selector) ||
$node.matches(`${selector} *`) ||
$node.querySelector(selector)),
matchesTarget = (selector) =>
event.target.matches(selector) ||
event.target.matches(`${selector} *`) ||
[...event.addedNodes].some(($node) => matchesAddedNode($node, selector));
for (const listener of _documentObserverListeners) {
if (
!listener.selectors.length ||
listener.selectors.some(
(selector) =>
event.target.matches(selector) ||
event.target.matches(`${selector} *`) ||
event.target.querySelector(selector)
)
) {
if (!listener.selectors.length || listener.selectors.some(matchesTarget)) {
listener.callback(event);
}
}