diff --git a/repo/collapsible-headers/client.css b/repo/collapsible-headers/client.css deleted file mode 100644 index 95e3616..0000000 --- a/repo/collapsible-headers/client.css +++ /dev/null @@ -1,81 +0,0 @@ -/** - * notion-enhancer: collapsible headers - * (c) 2020 CloudHill (https://github.com/CloudHill) - * (c) 2021 dragonwocky (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; -} diff --git a/repo/collapsible-headers/client.mjs b/repo/collapsible-headers/client.mjs deleted file mode 100644 index c3b7699..0000000 --- a/repo/collapsible-headers/client.mjs +++ /dev/null @@ -1,286 +0,0 @@ -/** - * notion-enhancer: collapsible headers - * (c) 2020 CloudHill (https://github.com/CloudHill) - * (c) 2021 dragonwocky (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"]', - pageScroller = '.notion-frame > .notion-scroller.vertical.horizontal', - 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', - }; - - let 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, - { - maxHeight: '100%', - 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) => { - if ([...event.addedNodes].some(($node) => $node?.matches?.(pageScroller))) { - collapseParentsCache = new Map(); - collapsedBlocksCache = new Map(); - return; - } - - 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` -
- -
- `; - if (togglePosition === 'left') { - $header.firstChild.prepend($toggle); - } else web.render($header.firstChild, $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, ['.notion-page-content', headerSelector]); - - web.addHotkeyListener(toggleHotkey, (event) => { - const $header = document.activeElement.closest(headerSelector); - if ($header) { - toggleHeaderSection($header, animateToggle); - } else { - getSelectedHeaders().forEach(($header) => toggleHeaderSection($header, animateToggle)); - } - }); -} diff --git a/repo/collapsible-headers/collapsible-headers.gif b/repo/collapsible-headers/collapsible-headers.gif deleted file mode 100644 index 6aff7f5..0000000 Binary files a/repo/collapsible-headers/collapsible-headers.gif and /dev/null differ diff --git a/repo/collapsible-headers/mod.json b/repo/collapsible-headers/mod.json deleted file mode 100644 index 14700b3..0000000 --- a/repo/collapsible-headers/mod.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "collapsible headers", - "id": "548fe2d7-174a-44dd-88d8-35c7f9a093a7", - "version": "0.2.0", - "description": "adds toggles to collapse header sections of pages.", - "preview": "collapsible-headers.gif", - "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" - } - ] -} diff --git a/repo/registry.json b/repo/registry.json index b861688..6093766 100644 --- a/repo/registry.json +++ b/repo/registry.json @@ -23,7 +23,6 @@ "word-counter", "code-line-numbers", "calendar-scroll", - "collapsible-headers", "collapsible-properties", "weekly-view", "truncated-titles",