mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-18 18:59:01 +00:00
feat(panel): add open/close gui buttons
This commit is contained in:
parent
94460375bf
commit
bb5853e866
@ -142,9 +142,8 @@ const insertPanel = async (db) => {
|
|||||||
addKeyListener(togglePanelHotkey, (event) => {
|
addKeyListener(togglePanelHotkey, (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if ($panel.hasAttribute("open")) {
|
if ($panel.hasAttribute("open")) $panel.close();
|
||||||
$panel.close();
|
else $panel.open();
|
||||||
} else $panel.open();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,16 @@
|
|||||||
|
|
||||||
import { Tooltip } from "./Tooltip.mjs";
|
import { Tooltip } from "./Tooltip.mjs";
|
||||||
|
|
||||||
|
function PanelView(props) {
|
||||||
|
const { html } = globalThis.__enhancerApi;
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PanelSwitcher(props) {
|
||||||
|
const { html } = globalThis.__enhancerApi;
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
function Panel({
|
function Panel({
|
||||||
_getWidth,
|
_getWidth,
|
||||||
_setWidth,
|
_setWidth,
|
||||||
@ -26,7 +36,8 @@ function Panel({
|
|||||||
maxWidth = 640,
|
maxWidth = 640,
|
||||||
...props
|
...props
|
||||||
}) {
|
}) {
|
||||||
const { html, extendProps } = globalThis.__enhancerApi;
|
const { html, extendProps } = globalThis.__enhancerApi,
|
||||||
|
{ addMutationListener, removeMutationListener } = globalThis.__enhancerApi;
|
||||||
extendProps(props, {
|
extendProps(props, {
|
||||||
class: `notion-enhancer--side-panel order-2 shrink-0
|
class: `notion-enhancer--side-panel order-2 shrink-0
|
||||||
transition-[width] open:w-[var(--side\\_panel--width)]
|
transition-[width] open:w-[var(--side\\_panel--width)]
|
||||||
@ -40,11 +51,61 @@ function Panel({
|
|||||||
shadow-[var(--theme--fg-border)_-2px_0px_0px_0px_inset])
|
shadow-[var(--theme--fg-border)_-2px_0px_0px_0px_inset])
|
||||||
active:cursor-text group-not-[open]:hidden"
|
active:cursor-text group-not-[open]:hidden"
|
||||||
></div>`,
|
></div>`,
|
||||||
|
$chevronClose = html`<button
|
||||||
|
aria-label="Close side panel"
|
||||||
|
class="user-select-none h-[24px] w-[24px] duration-[20ms]
|
||||||
|
transition inline-flex items-center justify-center mr-[10px]
|
||||||
|
rounded-[3px] hover:bg-[color:var(--theme--bg-hover)]"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
class="w-[16px] h-[16px] fill-[color:var(--theme--fg-secondary)]"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M2.25781 14.1211C2.47656 14.1211 2.66797 14.0391 2.81836 13.8887L8.14355 8.67969C8.32812 8.49512 8.41699 8.29688 8.41699 8.06445C8.41699 7.8252 8.32812 7.62012 8.14355 7.44922L2.81836 2.24023C2.66797 2.08984 2.4834 2.00781 2.25781 2.00781C1.81348 2.00781 1.46484 2.35645 1.46484 2.80078C1.46484 3.0127 1.55371 3.21777 1.7041 3.375L6.50977 8.05762L1.7041 12.7539C1.55371 12.9043 1.46484 13.1094 1.46484 13.3281C1.46484 13.7725 1.81348 14.1211 2.25781 14.1211ZM8.36914 14.1211C8.58789 14.1211 8.77246 14.0391 8.92285 13.8887L14.2549 8.67969C14.4395 8.49512 14.5283 8.29688 14.5283 8.06445C14.5283 7.8252 14.4326 7.62012 14.2549 7.44922L8.92285 2.24023C8.77246 2.08984 8.58789 2.00781 8.36914 2.00781C7.9248 2.00781 7.56934 2.35645 7.56934 2.80078C7.56934 3.0127 7.66504 3.21777 7.81543 3.375L12.6211 8.05762L7.81543 12.7539C7.66504 12.9043 7.56934 13.1094 7.56934 13.3281C7.56934 13.7725 7.9248 14.1211 8.36914 14.1211Z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</div>`,
|
||||||
$panel = html`<aside ...${props}>
|
$panel = html`<aside ...${props}>
|
||||||
${$resizeHandle}
|
${$resizeHandle}
|
||||||
<div>Hello world.</div>
|
<div
|
||||||
|
class="flex justify-between items-center
|
||||||
|
border-(b [color:var(--theme--fg-border)])"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="font-size: 14px; color: rgba(255, 255, 255, 0.81); font-weight: 500; display: flex; align-items: center; padding: 12px 12px 12px 16px;"
|
||||||
|
>
|
||||||
|
Comments
|
||||||
|
</div>
|
||||||
|
${$chevronClose}
|
||||||
|
</div>
|
||||||
</aside>`;
|
</aside>`;
|
||||||
|
|
||||||
|
let preDragWidth,
|
||||||
|
userDragActive,
|
||||||
|
dragStartX = 0;
|
||||||
|
const startDrag = async (event) => {
|
||||||
|
userDragActive = true;
|
||||||
|
dragStartX = event.clientX;
|
||||||
|
preDragWidth = await _getWidth?.();
|
||||||
|
if (isNaN(preDragWidth)) preDragWidth = minWidth;
|
||||||
|
document.addEventListener("mousemove", onDrag);
|
||||||
|
document.addEventListener("mouseup", endDrag);
|
||||||
|
$panel.style.transitionDuration = "0ms";
|
||||||
|
},
|
||||||
|
onDrag = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
$panel.resize(preDragWidth + (dragStartX - event.clientX));
|
||||||
|
},
|
||||||
|
endDrag = (event) => {
|
||||||
|
userDragActive = false;
|
||||||
|
document.removeEventListener("mousemove", onDrag);
|
||||||
|
document.removeEventListener("mouseup", endDrag);
|
||||||
|
$panel.resize(preDragWidth + (dragStartX - event.clientX));
|
||||||
|
$panel.style.transitionDuration = "";
|
||||||
|
};
|
||||||
|
$resizeHandle.addEventListener("mousedown", startDrag);
|
||||||
|
|
||||||
const $tooltip = html`<${Tooltip}>
|
const $tooltip = html`<${Tooltip}>
|
||||||
<span>Drag</span> to resize<br />
|
<span>Drag</span> to resize<br />
|
||||||
<span>Click</span> to closed
|
<span>Click</span> to closed
|
||||||
@ -59,40 +120,16 @@ function Panel({
|
|||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
$resizeHandle.addEventListener("mouseover", showTooltip);
|
$resizeHandle.addEventListener("mouseover", showTooltip);
|
||||||
$resizeHandle.addEventListener("mouseout", $tooltip.hide);
|
$resizeHandle.addEventListener("mouseout", () => $tooltip.hide());
|
||||||
$resizeHandle.addEventListener("click", $panel.close);
|
$resizeHandle.addEventListener("click", () => {
|
||||||
|
if (!userDragActive) $panel.close();
|
||||||
let preDragWidth,
|
});
|
||||||
dragStartX = 0;
|
$chevronClose.addEventListener("click", () => $panel.close());
|
||||||
const startDrag = async (event) => {
|
|
||||||
dragStartX = event.clientX;
|
|
||||||
preDragWidth = await _getWidth?.();
|
|
||||||
if (isNaN(preDragWidth)) preDragWidth = minWidth;
|
|
||||||
document.addEventListener("mousemove", onDrag);
|
|
||||||
document.addEventListener("mouseup", endDrag);
|
|
||||||
$panel.style.transitionDuration = "0ms";
|
|
||||||
},
|
|
||||||
onDrag = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
const newWidth = preDragWidth + (dragStartX - event.clientX);
|
|
||||||
$panel.resize(newWidth, true);
|
|
||||||
},
|
|
||||||
endDrag = (event) => {
|
|
||||||
document.removeEventListener("mousemove", onDrag);
|
|
||||||
document.removeEventListener("mouseup", endDrag);
|
|
||||||
const finalWidth = preDragWidth + (dragStartX - event.clientX);
|
|
||||||
$panel.style.transitionDuration = "";
|
|
||||||
$panel.resize(finalWidth);
|
|
||||||
};
|
|
||||||
$resizeHandle.addEventListener("mousedown", startDrag);
|
|
||||||
|
|
||||||
const notionHelp = ".notion-help-button",
|
const notionHelp = ".notion-help-button",
|
||||||
repositionHelp = async (attempts = 0) => {
|
repositionHelp = async () => {
|
||||||
const $notionHelp = document.querySelector(notionHelp);
|
const $notionHelp = document.querySelector(notionHelp);
|
||||||
if (!$notionHelp) {
|
if (!$notionHelp) return;
|
||||||
if (attempts < 20) setTimeout(() => repositionHelp(attempts + 1), 150);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let width = await _getWidth?.();
|
let width = await _getWidth?.();
|
||||||
if (isNaN(width)) width = minWidth;
|
if (isNaN(width)) width = minWidth;
|
||||||
if (!$panel.hasAttribute("open")) width = 0;
|
if (!$panel.hasAttribute("open")) width = 0;
|
||||||
@ -102,14 +139,40 @@ function Panel({
|
|||||||
options = { duration: 150, easing: "cubic-bezier(0.4, 0, 0.2, 1)" };
|
options = { duration: 150, easing: "cubic-bezier(0.4, 0, 0.2, 1)" };
|
||||||
$notionHelp.style.setProperty("right", destination);
|
$notionHelp.style.setProperty("right", destination);
|
||||||
$notionHelp.animate(keyframes, options);
|
$notionHelp.animate(keyframes, options);
|
||||||
|
removeMutationListener(repositionHelp);
|
||||||
};
|
};
|
||||||
|
addMutationListener(notionHelp, repositionHelp);
|
||||||
|
|
||||||
$panel.resize = async (width, dragActive = false) => {
|
const notionTopbarMore = ".notion-topbar-more-button",
|
||||||
|
$topbarPanelButton = html`<button
|
||||||
|
aria-label="Open side panel"
|
||||||
|
class="user-select-none h-[28px] w-[33px] duration-[20ms]
|
||||||
|
transition inline-flex items-center justify-center mr-[2px]
|
||||||
|
rounded-[3px] hover:bg-[color:var(--theme--bg-hover)]
|
||||||
|
[data-active]:bg-[color:var(--theme--bg-hover)]"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="i-panel-right w-[20px] h-[20px] fill-[color:var(--theme--fg-secondary)]"
|
||||||
|
/>
|
||||||
|
</button>`,
|
||||||
|
appendToDom = () => {
|
||||||
|
if (document.contains($topbarPanelButton)) return;
|
||||||
|
const $notionTopbarMore = document.querySelector(notionTopbarMore);
|
||||||
|
$notionTopbarMore?.before($topbarPanelButton);
|
||||||
|
};
|
||||||
|
$topbarPanelButton.addEventListener("click", () => {
|
||||||
|
if ($panel.hasAttribute("open")) $panel.close();
|
||||||
|
else $panel.open();
|
||||||
|
});
|
||||||
|
addMutationListener(notionTopbarMore, appendToDom);
|
||||||
|
appendToDom();
|
||||||
|
|
||||||
|
$panel.resize = async (width) => {
|
||||||
$tooltip.hide();
|
$tooltip.hide();
|
||||||
if (width) {
|
if (width) {
|
||||||
width = Math.max(width, minWidth);
|
width = Math.max(width, minWidth);
|
||||||
width = Math.min(width, maxWidth);
|
width = Math.min(width, maxWidth);
|
||||||
if (!dragActive) _setWidth?.(width);
|
if (!userDragActive) _setWidth?.(width);
|
||||||
} else width = await _getWidth?.();
|
} else width = await _getWidth?.();
|
||||||
if (isNaN(width)) width = minWidth;
|
if (isNaN(width)) width = minWidth;
|
||||||
$panel.style.setProperty("--side_panel--width", `${width}px`);
|
$panel.style.setProperty("--side_panel--width", `${width}px`);
|
||||||
@ -118,6 +181,7 @@ function Panel({
|
|||||||
$panel.open = () => {
|
$panel.open = () => {
|
||||||
$panel.setAttribute("open", true);
|
$panel.setAttribute("open", true);
|
||||||
$panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = 0));
|
$panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = 0));
|
||||||
|
$topbarPanelButton.setAttribute("data-active", true);
|
||||||
$panel.onopen?.();
|
$panel.onopen?.();
|
||||||
_setOpen(true);
|
_setOpen(true);
|
||||||
$panel.resize();
|
$panel.resize();
|
||||||
@ -127,6 +191,7 @@ function Panel({
|
|||||||
$panel.onbeforeclose?.();
|
$panel.onbeforeclose?.();
|
||||||
$panel.removeAttribute("open");
|
$panel.removeAttribute("open");
|
||||||
$panel.style.pointerEvents = "auto";
|
$panel.style.pointerEvents = "auto";
|
||||||
|
$topbarPanelButton.removeAttribute("data-active");
|
||||||
$panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = -1));
|
$panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = -1));
|
||||||
repositionHelp();
|
repositionHelp();
|
||||||
_setOpen(false);
|
_setOpen(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user