mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-09 15:09:02 +00:00
extension: collapsible headers
This commit is contained in:
parent
dbb94bc29b
commit
38484b7e42
@ -2,7 +2,7 @@
|
|||||||
"name": "calendar scroll",
|
"name": "calendar scroll",
|
||||||
"id": "b1c7db33-dfee-489a-a76c-0dd66f7ed29a",
|
"id": "b1c7db33-dfee-489a-a76c-0dd66f7ed29a",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"description": "add a button to jump down to the current week in fullpage/infinite-scroll calendars.",
|
"description": "adds a button to jump down to the current week in fullpage/infinite-scroll calendars.",
|
||||||
"tags": ["extension", "shortcut"],
|
"tags": ["extension", "shortcut"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
86
repo/collapsible-headers/app.css
Normal file
86
repo/collapsible-headers/app.css
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* collapsible headers
|
||||||
|
* (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (c) 2020 CloudHill
|
||||||
|
* under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
.notion-page-content .notion-selectable[collapsed] {
|
||||||
|
max-height: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notion-page-content .notion-selectable[collapsed] .notion-selectable {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-header {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-self: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 6px;
|
||||||
|
margin: 0 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 200ms ease-in;
|
||||||
|
}
|
||||||
|
.collapse-header:hover {
|
||||||
|
background: var(--theme--interactive_hover);
|
||||||
|
}
|
||||||
|
/* position: left */
|
||||||
|
.collapse-header:first-child {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
/* position: right / inline */
|
||||||
|
.collapse-header:last-child {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show toggle on: collapsed, hover, focus */
|
||||||
|
[data-collapsed="true"] .collapse-header:last-child,
|
||||||
|
[data-collapsed]:hover .collapse-header:last-child,
|
||||||
|
[data-collapsed] :focus + .collapse-header:last-child {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-header svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: transform 200ms ease-out 0s;
|
||||||
|
}
|
||||||
|
/* position: left */
|
||||||
|
.collapse-header:first-child svg {
|
||||||
|
transform: rotateZ(90deg);
|
||||||
|
}
|
||||||
|
/* position: right / inline */
|
||||||
|
.collapse-header:last-child svg {
|
||||||
|
transform: rotateZ(270deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-collapsed="false"] .collapse-header svg {
|
||||||
|
transform: rotateZ(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* position: inline */
|
||||||
|
[inline-toggle] {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
[inline-toggle] [placeholder] {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
[inline-toggle] [placeholder]::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
cursor: text;
|
||||||
|
}
|
81
repo/collapsible-headers/client.css
Normal file
81
repo/collapsible-headers/client.css
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* notion-enhancer: collapsible headerrs
|
||||||
|
* (c) 2020 CloudHill <rl.cloudhill@gmail.com> (https://github.com/CloudHill)
|
||||||
|
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
.collapsible_headers--toggle {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-self: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 6px;
|
||||||
|
margin: 0 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 200ms ease-in;
|
||||||
|
}
|
||||||
|
.collapsible_headers--toggle:hover {
|
||||||
|
background: var(--theme--ui_interactive-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsible_headers--toggle svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: transform 200ms ease-out 0s;
|
||||||
|
}
|
||||||
|
[data-section-collapsed='false'] .collapsible_headers--toggle svg {
|
||||||
|
transform: rotateZ(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* position = left */
|
||||||
|
[data-section-collapsed='true'] .collapsible_headers--toggle:first-child svg {
|
||||||
|
transform: rotateZ(90deg);
|
||||||
|
}
|
||||||
|
.collapsible_headers--toggle:first-child {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* position = right / inline */
|
||||||
|
[data-section-collapsed='true'] .collapsible_headers--toggle:last-child svg {
|
||||||
|
transform: rotateZ(270deg);
|
||||||
|
}
|
||||||
|
.collapsible_headers--toggle:last-child {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
[data-section-collapsed='true'] .collapsible_headers--toggle:last-child,
|
||||||
|
[data-section-collapsed]:hover .collapsible_headers--toggle:last-child,
|
||||||
|
[data-section-collapsed] :focus + .collapsible_headers--toggle:last-child {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* position = inline */
|
||||||
|
.collapsible_headers--inline {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.collapsible_headers--inline [placeholder] {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
.collapsible_headers--inline [placeholder]::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notion-page-content .notion-selectable[data-collapsed] {
|
||||||
|
margin: 0px !important;
|
||||||
|
pointer-events: none;
|
||||||
|
max-height: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
279
repo/collapsible-headers/client.mjs
Normal file
279
repo/collapsible-headers/client.mjs
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
* notion-enhancer: collapsible headerrs
|
||||||
|
* (c) 2020 CloudHill <rl.cloudhill@gmail.com> (https://github.com/CloudHill)
|
||||||
|
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default async function ({ web }, db) {
|
||||||
|
const headerSelector = '.notion-page-content [class*="header-block"]',
|
||||||
|
haloClass = 'notion-selectable-halo',
|
||||||
|
blockSelector = '.notion-selectable[data-block-id]',
|
||||||
|
dividerClass = 'notion-divider-block',
|
||||||
|
toggleClass = 'collapsible_headers--toggle',
|
||||||
|
inlineToggleClass = 'collapsible_headers--inline';
|
||||||
|
|
||||||
|
const togglePosition = await db.get(['position']),
|
||||||
|
animateToggle = await db.get(['animate']),
|
||||||
|
breakOnDividers = await db.get(['dividers']),
|
||||||
|
toggleHotkey = await db.get(['hotkey']);
|
||||||
|
|
||||||
|
const animationStyle = {
|
||||||
|
duration: 250,
|
||||||
|
easing: 'ease',
|
||||||
|
},
|
||||||
|
animationCollapsed = {
|
||||||
|
height: 0,
|
||||||
|
opacity: 0,
|
||||||
|
marginTop: 0,
|
||||||
|
marginBottom: 0,
|
||||||
|
overflow: 'hidden',
|
||||||
|
};
|
||||||
|
|
||||||
|
const collapseParentsCache = new Map(),
|
||||||
|
collapsedBlocksCache = new Map();
|
||||||
|
|
||||||
|
const getHeaderLevel = ($block) => {
|
||||||
|
if (!$block?.className?.includes?.('header-block')) return 9;
|
||||||
|
return ($block.className.match(/sub_/gi)?.length || 0) + 1;
|
||||||
|
},
|
||||||
|
getSelectedHeaders = () => {
|
||||||
|
return [...document.querySelectorAll(`${headerSelector} ${haloClass}`)]
|
||||||
|
.map(($halo) => $halo.parentElement)
|
||||||
|
.filter(($header) => $header.dataset.sectionCollapsed === 'true');
|
||||||
|
},
|
||||||
|
getHeaderSection = ($header) => {
|
||||||
|
const blockList = [];
|
||||||
|
let $nextBlock = $header?.nextElementSibling;
|
||||||
|
// is this weird? yes
|
||||||
|
// labels were the simplest way to do this tho
|
||||||
|
blockLoop: while (true) {
|
||||||
|
const isSectionEnd =
|
||||||
|
!$nextBlock ||
|
||||||
|
getHeaderLevel($nextBlock) <= getHeaderLevel($header) ||
|
||||||
|
(breakOnDividers && $nextBlock?.classList?.contains(dividerClass));
|
||||||
|
if (isSectionEnd) break;
|
||||||
|
blockList.push($nextBlock);
|
||||||
|
const $childBlock = $nextBlock.querySelector(blockSelector);
|
||||||
|
if ($childBlock) {
|
||||||
|
$nextBlock = $childBlock;
|
||||||
|
} else if ($nextBlock.nextElementSibling) {
|
||||||
|
$nextBlock = $nextBlock.nextElementSibling;
|
||||||
|
} else {
|
||||||
|
let $parentBlock = $nextBlock.parentElement.closest(blockSelector);
|
||||||
|
while (!$parentBlock?.nextElementSibling) {
|
||||||
|
if (!$parentBlock) break blockLoop;
|
||||||
|
if ($parentBlock === $header.parentElement) break blockLoop;
|
||||||
|
$parentBlock = $parentBlock.parentElement.closest(blockSelector);
|
||||||
|
}
|
||||||
|
$nextBlock = $parentBlock.nextElementSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return blockList;
|
||||||
|
};
|
||||||
|
|
||||||
|
const expandBlock = async ($header, $block, animate) => {
|
||||||
|
const collapseParents = collapseParentsCache.get($block.dataset.blockId),
|
||||||
|
expand = async () => {
|
||||||
|
delete $block.dataset.collapsed;
|
||||||
|
if (animate) {
|
||||||
|
await $block.animate(
|
||||||
|
[
|
||||||
|
animationCollapsed,
|
||||||
|
{
|
||||||
|
height: $block.scrollHeight + 'px',
|
||||||
|
opacity: 1,
|
||||||
|
marginTop: $block.style.marginTop,
|
||||||
|
marginBottom: $block.style.marginBottom,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
animationStyle
|
||||||
|
).finished;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (collapseParents) {
|
||||||
|
collapseParents.delete($header.dataset.blockId);
|
||||||
|
if (!collapseParents.size) await expand();
|
||||||
|
} else await expand();
|
||||||
|
},
|
||||||
|
expandHeaderSection = async ($header, animate) => {
|
||||||
|
const isBusy = $header.dataset.collapseAnimating,
|
||||||
|
isCollapsibleHeader =
|
||||||
|
$header.matches(headerSelector) && $header.dataset.sectionCollapsed === 'true';
|
||||||
|
if (isBusy || !isCollapsibleHeader) return;
|
||||||
|
$header.dataset.collapseAnimating = 'true';
|
||||||
|
$header.dataset.sectionCollapsed = false;
|
||||||
|
await db.set(['collapsed_ids', $header.dataset.blockId], false);
|
||||||
|
|
||||||
|
const sectionContent = getHeaderSection($header),
|
||||||
|
animations = [];
|
||||||
|
for (const $block of sectionContent) {
|
||||||
|
animations.push(expandBlock($header, $block, animate));
|
||||||
|
}
|
||||||
|
if ($header.dataset.collapsed) {
|
||||||
|
const collapseParents = collapseParentsCache.get($header.dataset.blockId) || [];
|
||||||
|
for (const parentId of collapseParents) {
|
||||||
|
animations.push(
|
||||||
|
expandHeaderSection(
|
||||||
|
document.querySelector(`[data-block-id="${parentId}"]`),
|
||||||
|
animate
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsedBlocksCache.set($header.dataset.blockId, undefined);
|
||||||
|
await Promise.all(animations);
|
||||||
|
delete $header.dataset.collapseAnimating;
|
||||||
|
},
|
||||||
|
collapseHeaderSection = async ($header, animate) => {
|
||||||
|
const isBusy = $header.dataset.collapseAnimating,
|
||||||
|
isCollapsibleHeader =
|
||||||
|
$header.matches(headerSelector) && $header.dataset.sectionCollapsed === 'false';
|
||||||
|
if (isBusy || !isCollapsibleHeader) return;
|
||||||
|
$header.dataset.collapseAnimating = 'true';
|
||||||
|
$header.dataset.sectionCollapsed = true;
|
||||||
|
await db.set(['collapsed_ids', $header.dataset.blockId], true);
|
||||||
|
|
||||||
|
const sectionContent = getHeaderSection($header),
|
||||||
|
animations = [];
|
||||||
|
collapsedBlocksCache.set($header.dataset.blockId, sectionContent);
|
||||||
|
for (const $block of sectionContent) {
|
||||||
|
if (!collapseParentsCache.get($block.dataset.blockId)) {
|
||||||
|
collapseParentsCache.set($block.dataset.blockId, new Set());
|
||||||
|
}
|
||||||
|
const collapseParents = collapseParentsCache.get($block.dataset.blockId);
|
||||||
|
collapseParents.add($header.dataset.blockId);
|
||||||
|
|
||||||
|
if (animate) {
|
||||||
|
animations.push(
|
||||||
|
$block.animate(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
maxHeight: $block.offsetHeight + 'px',
|
||||||
|
opacity: 1,
|
||||||
|
marginTop: $block.style.marginTop,
|
||||||
|
marginBottom: $block.style.marginBottom,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
animationCollapsed,
|
||||||
|
],
|
||||||
|
animationStyle
|
||||||
|
).finished
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$block.dataset.collapsed = true;
|
||||||
|
}
|
||||||
|
await Promise.all(animations);
|
||||||
|
|
||||||
|
delete $header.dataset.collapseAnimating;
|
||||||
|
},
|
||||||
|
toggleHeaderSection = async ($header, animate) => {
|
||||||
|
if ($header.dataset.collapseAnimating) return;
|
||||||
|
if ($header.dataset.sectionCollapsed === 'true') {
|
||||||
|
const collapseParents = collapseParentsCache.get($header.dataset.blockId) ?? [];
|
||||||
|
for (const $parent of collapseParents) {
|
||||||
|
await expandHeaderSection($parent, animateToggle);
|
||||||
|
}
|
||||||
|
await expandHeaderSection($header, animate);
|
||||||
|
} else await collapseHeaderSection($header, animate);
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertToggles = async (event) => {
|
||||||
|
const childNodeEvent =
|
||||||
|
event.target.matches(blockSelector) && !event.target.matches(headerSelector);
|
||||||
|
if (childNodeEvent) return;
|
||||||
|
|
||||||
|
const removeHeaderEvent = [...event.removedNodes].filter(($node) =>
|
||||||
|
$node?.className?.includes('header-blocks')
|
||||||
|
);
|
||||||
|
if (removeHeaderEvent.length) {
|
||||||
|
return removeHeaderEvent.forEach(($header) => expandHeaderSection($header, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleEvent =
|
||||||
|
[...event.addedNodes, ...event.removedNodes].some(($node) =>
|
||||||
|
$node?.classList?.contains(toggleClass)
|
||||||
|
) ||
|
||||||
|
event.target.classList.contains(toggleClass) ||
|
||||||
|
event.attributeName === 'data-collapsed' ||
|
||||||
|
(event.target.classList.contains(inlineToggleClass) && event.attributeName === 'class');
|
||||||
|
if (toggleEvent) return;
|
||||||
|
|
||||||
|
const haloRemoveEvent =
|
||||||
|
event.target.classList.contains(haloClass) ||
|
||||||
|
[...event.removedNodes].some(($node) => $node?.classList?.contains(haloClass));
|
||||||
|
if (haloRemoveEvent) return;
|
||||||
|
|
||||||
|
for (const $header of document.querySelectorAll(headerSelector)) {
|
||||||
|
const $nextBlock = $header.nextElementSibling,
|
||||||
|
sectionContent = getHeaderSection($header),
|
||||||
|
prevCollapseCache = collapsedBlocksCache.get($header.dataset.blockId) ?? [];
|
||||||
|
|
||||||
|
let hasMoved =
|
||||||
|
prevCollapseCache.length && prevCollapseCache.length !== sectionContent.length;
|
||||||
|
for (const $collapsedBlock of prevCollapseCache) {
|
||||||
|
if (hasMoved) break;
|
||||||
|
if (!sectionContent.includes($collapsedBlock)) hasMoved = true;
|
||||||
|
}
|
||||||
|
if (hasMoved) {
|
||||||
|
for (const $collapsedBlock of prevCollapseCache)
|
||||||
|
expandBlock($header, $collapsedBlock, animateToggle);
|
||||||
|
await db.set(['collapsed_ids', $header.dataset.blockId], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isEmpty =
|
||||||
|
!$nextBlock ||
|
||||||
|
getHeaderLevel($nextBlock) <= getHeaderLevel($header) ||
|
||||||
|
(breakOnDividers && $nextBlock.classList.contains(dividerClass));
|
||||||
|
if (isEmpty) {
|
||||||
|
delete $header.dataset.sectionCollapsed;
|
||||||
|
$header.querySelector(`.${toggleClass}`)?.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($header.querySelector(`.${toggleClass}`)) continue;
|
||||||
|
const $toggle = web.html`
|
||||||
|
<div class="${toggleClass}">
|
||||||
|
<svg viewBox="0 0 100 100"><polygon points="5.9,88.2 50,11.8 94.1,88.2"></polygon></svg>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
if (togglePosition === 'left') {
|
||||||
|
$header.firstChild.prepend($toggle);
|
||||||
|
} else $header.firstChild.append($toggle);
|
||||||
|
if (togglePosition === 'inline') $header.firstChild.classList.add(inlineToggleClass);
|
||||||
|
|
||||||
|
$toggle.header = $header;
|
||||||
|
$toggle.addEventListener('click', (ev) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
$header.querySelector('[contenteditable="true"]').click();
|
||||||
|
toggleHeaderSection($header, animateToggle);
|
||||||
|
});
|
||||||
|
|
||||||
|
$header.dataset.sectionCollapsed = false;
|
||||||
|
if (await db.get(['collapsed_ids', $header.dataset.blockId], false)) {
|
||||||
|
await collapseHeaderSection($header, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const haloAddedEvent =
|
||||||
|
[...event.addedNodes].some(($node) => $node?.classList?.contains(haloClass)) &&
|
||||||
|
event.target.matches(headerSelector),
|
||||||
|
$selectedHeaders = new Set(getSelectedHeaders());
|
||||||
|
if (haloAddedEvent) $selectedHeaders.add(event.target);
|
||||||
|
for (const $header of $selectedHeaders) {
|
||||||
|
expandHeaderSection($header, animateToggle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
web.addDocumentObserver(insertToggles, [headerSelector]);
|
||||||
|
|
||||||
|
web.addHotkeyListener(toggleHotkey, (event) => {
|
||||||
|
const $header = document.activeElement.closest(headerSelector);
|
||||||
|
if ($header) {
|
||||||
|
toggleHeaderSection($header, animateToggle);
|
||||||
|
} else {
|
||||||
|
getSelectedHeaders().forEach(($header) => toggleHeaderSection($header, animateToggle));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
48
repo/collapsible-headers/mod.json
Normal file
48
repo/collapsible-headers/mod.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "collapsible headers",
|
||||||
|
"id": "548fe2d7-174a-44dd-88d8-35c7f9a093a7",
|
||||||
|
"version": "0.2.0",
|
||||||
|
"description": "adds toggles to collapse header sections of pages.",
|
||||||
|
"tags": ["extension", "layout"],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "CloudHill",
|
||||||
|
"email": "rh.cloudhill@gmail.com",
|
||||||
|
"homepage": "https://github.com/CloudHill",
|
||||||
|
"avatar": "https://avatars.githubusercontent.com/u/54142180"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"js": {
|
||||||
|
"client": ["client.mjs"]
|
||||||
|
},
|
||||||
|
"css": {
|
||||||
|
"client": ["client.css"]
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"type": "select",
|
||||||
|
"key": "position",
|
||||||
|
"label": "toggle icon position",
|
||||||
|
"values": ["left", "right", "inline"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "toggle",
|
||||||
|
"key": "animate",
|
||||||
|
"label": "animate opening/closing",
|
||||||
|
"value": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "toggle",
|
||||||
|
"key": "dividers",
|
||||||
|
"label": "use divider blocks to break header sections",
|
||||||
|
"value": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hotkey",
|
||||||
|
"key": "hotkey",
|
||||||
|
"label": "toggle header collapse hotkey",
|
||||||
|
"tooltip": "**opens/closes the currently focused header section**",
|
||||||
|
"value": "ctrl+enter"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "collapse properties",
|
"name": "collapsible properties",
|
||||||
"id": "4034a578-7dd3-4633-80c6-f47ac5b7b160",
|
"id": "4034a578-7dd3-4633-80c6-f47ac5b7b160",
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"description": "add a button to quickly collapse/expand page properties that usually push down page content.",
|
"description": "adds a button to quickly collapse/expand page properties that usually push down page content.",
|
||||||
"tags": ["extension", "layout"],
|
"tags": ["extension", "layout"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
@ -24,8 +24,8 @@ export default async function ({ web, components, notion }, db) {
|
|||||||
8c0,2.98,1.634,5.575,4.051,6.951C4.021,18.638,4,18.321,4,18 c0-0.488,0.046-0.967,
|
8c0,2.98,1.634,5.575,4.051,6.951C4.021,18.638,4,18.321,4,18 c0-0.488,0.046-0.967,
|
||||||
0.115-1.436C2.823,15.462,2,13.827,2,12z M25.953,11.051C25.984,11.363,26,11.68,26,12
|
0.115-1.436C2.823,15.462,2,13.827,2,12z M25.953,11.051C25.984,11.363,26,11.68,26,12
|
||||||
c0,0.489-0.047,0.965-0.117,1.434C27.176,14.536,28,16.172,28,18c0,3.309-2.691,6-6,6h-8c-3.309,
|
c0,0.489-0.047,0.965-0.117,1.434C27.176,14.536,28,16.172,28,18c0,3.309-2.691,6-6,6h-8c-3.309,
|
||||||
0-6-2.691-6-6s2.691-6,6-6h6 c0-0.731-0.199-1.413-0.545-2H14c-4.418,0-8,3.582-8,8c0,4.418,3.582,8,8,
|
0-6-2.691-6-6s2.691-6,6-6h6 c0-0.731-0.199-1.413-0.545-2H14c-4.418,0-8,3.582-8,8c0,
|
||||||
8h8c4.418,0,8-3.582,8-8 C30,15.021,28.368,12.428,25.953,11.051z"></path>
|
4.418,3.582,8,8,8h8c4.418,0,8-3.582,8-8 C30,15.021,28.368,12.428,25.953,11.051z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<span>Copy link</span>
|
<span>Copy link</span>
|
||||||
<span class="${hiddenClass}">Link copied!</span>
|
<span class="${hiddenClass}">Link copied!</span>
|
||||||
|
@ -58,6 +58,9 @@ export default async function ({ web, components }, db) {
|
|||||||
style="--outliner--indent:${indent}px;"></a>`,
|
style="--outliner--indent:${indent}px;"></a>`,
|
||||||
$header.innerText
|
$header.innerText
|
||||||
);
|
);
|
||||||
|
$outlineHeader.addEventListener('click', (event) => {
|
||||||
|
location.hash = '';
|
||||||
|
});
|
||||||
$fragment.append($outlineHeader);
|
$fragment.append($outlineHeader);
|
||||||
}
|
}
|
||||||
if ($fragment.innerHTML !== $headingList.innerHTML) {
|
if ($fragment.innerHTML !== $headingList.innerHTML) {
|
||||||
|
@ -28,8 +28,9 @@
|
|||||||
"word-counter",
|
"word-counter",
|
||||||
"code-line-numbers",
|
"code-line-numbers",
|
||||||
"calendar-scroll",
|
"calendar-scroll",
|
||||||
|
"collapsible-headers",
|
||||||
|
"collapsible-properties",
|
||||||
"weekly-view",
|
"weekly-view",
|
||||||
"collapse-properties",
|
|
||||||
"truncated-titles",
|
"truncated-titles",
|
||||||
"focus-mode",
|
"focus-mode",
|
||||||
"global-block-links"
|
"global-block-links"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "scroll to top",
|
"name": "scroll to top",
|
||||||
"id": "0a958f5a-17c5-48b5-8713-16190cae1959",
|
"id": "0a958f5a-17c5-48b5-8713-16190cae1959",
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"description": "add an arrow in the bottom right corner to scroll back to the top of a page.",
|
"description": "adds an arrow in the bottom right corner to scroll back to the top of a page.",
|
||||||
"tags": ["extension", "shortcut"],
|
"tags": ["extension", "shortcut"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user