mirror of
				https://github.com/notion-enhancer/notion-enhancer.git
				synced 2025-11-05 00:28:07 +11:00 
			
		
		
		
	side panel component: working except switcher
This commit is contained in:
		
							parent
							
								
									33e8907d4f
								
							
						
					
					
						commit
						bc38f5d972
					
				@ -21,5 +21,5 @@ export * as fmt from './fmt.mjs';
 | 
				
			|||||||
export * as registry from './registry.mjs';
 | 
					export * as registry from './registry.mjs';
 | 
				
			||||||
/** helpers for manipulation of a webpage */
 | 
					/** helpers for manipulation of a webpage */
 | 
				
			||||||
export * as web from './web.mjs';
 | 
					export * as web from './web.mjs';
 | 
				
			||||||
/** notion-style elements inc. the sidebar */
 | 
					/** shared notion-style elements */
 | 
				
			||||||
export * as components from './components/_.mjs';
 | 
					export * as components from './components/_.mjs';
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * notion-style elements inc. the sidebar
 | 
					 * shared notion-style elements
 | 
				
			||||||
 * @module notion-enhancer/api/components
 | 
					 * @module notion-enhancer/api/components
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -18,4 +18,12 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export { tooltip } from './tooltip.mjs';
 | 
					export { tooltip } from './tooltip.mjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { side } from './tooltip.mjs';
 | 
					/**
 | 
				
			||||||
 | 
					 * generate an icon from the feather icons set
 | 
				
			||||||
 | 
					 * @param {string} name - the name/id of the icon
 | 
				
			||||||
 | 
					 * @param {object} attrs - an object of attributes to apply to the icon e.g. classes
 | 
				
			||||||
 | 
					 * @returns {string} an svg string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export { feather } from './feather.mjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { panel } from './panel.mjs';
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										36
									
								
								extension/api/components/feather.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								extension/api/components/feather.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * notion-enhancer: api
 | 
				
			||||||
 | 
					 * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 | 
				
			||||||
 | 
					 * (https://notion-enhancer.github.io/) under the MIT license
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * shared notion-style elements
 | 
				
			||||||
 | 
					 * @module notion-enhancer/api/components/feather
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { fs, web } from '../_.mjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let _$iconSheet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * generate an icon from the feather icons set
 | 
				
			||||||
 | 
					 * @param {string} name - the name/id of the icon
 | 
				
			||||||
 | 
					 * @param {object} attrs - an object of attributes to apply to the icon e.g. classes
 | 
				
			||||||
 | 
					 * @returns {string} an svg string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const feather = async (name, attrs = {}) => {
 | 
				
			||||||
 | 
					  if (!_$iconSheet) {
 | 
				
			||||||
 | 
					    _$iconSheet = web.html`${await fs.getText('dep/feather-sprite.svg')}`;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  attrs.style = (
 | 
				
			||||||
 | 
					    (attrs.style ? attrs.style + ';' : '') +
 | 
				
			||||||
 | 
					    'stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill:none;'
 | 
				
			||||||
 | 
					  ).trim();
 | 
				
			||||||
 | 
					  attrs.viewBox = '0 0 24 24';
 | 
				
			||||||
 | 
					  return `<svg ${Object.entries(attrs)
 | 
				
			||||||
 | 
					    .map(([key, val]) => `${web.escape(key)}="${web.escape(val)}"`)
 | 
				
			||||||
 | 
					    .join(' ')}>${_$iconSheet.getElementById(name)?.innerHTML}</svg>`;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										151
									
								
								extension/api/components/panel.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								extension/api/components/panel.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * notion-enhancer core: components
 | 
				
			||||||
 | 
					 * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 | 
				
			||||||
 | 
					 * (c) 2021 CloudHill <rl.cloudhill@gmail.com> (https://github.com/CloudHill)
 | 
				
			||||||
 | 
					 * (https://notion-enhancer.github.io/) under the MIT license
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:root {
 | 
				
			||||||
 | 
					  --component--panel-width: 260px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#enhancer--panel-hover-trigger {
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					  width: 2.5rem;
 | 
				
			||||||
 | 
					  max-height: 100%;
 | 
				
			||||||
 | 
					  z-index: 999;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  right: 0;
 | 
				
			||||||
 | 
					  flex-grow: 0;
 | 
				
			||||||
 | 
					  flex-shrink: 0;
 | 
				
			||||||
 | 
					  transition: width 300ms ease-in-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-hover-trigger[data-enhancer-panel-pinned] {
 | 
				
			||||||
 | 
					  /* taking up the physical space of the panel to move topbar buttons */
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  width: var(--component--panel-width);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.notion-cursor-listener > div[style*='flex-end'] {
 | 
				
			||||||
 | 
					  transition: margin-right 300ms ease-in-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.notion-cursor-listener > div[style*='flex-end'][data-enhancer-panel-pinned] {
 | 
				
			||||||
 | 
					  margin-right: var(--component--panel-width);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.notion-frame {
 | 
				
			||||||
 | 
					  transition: padding-right 300ms ease-in-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.notion-frame[data-enhancer-panel-pinned] {
 | 
				
			||||||
 | 
					  padding-right: var(--component--panel-width);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#enhancer--panel {
 | 
				
			||||||
 | 
					  z-index: 999;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  background: var(--theme--bg_secondary);
 | 
				
			||||||
 | 
					  width: var(--component--panel-width);
 | 
				
			||||||
 | 
					  right: calc(-1 * var(--component--panel-width));
 | 
				
			||||||
 | 
					  opacity: 0;
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					  flex-grow: 0;
 | 
				
			||||||
 | 
					  flex-shrink: 0;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  transition: 300ms ease-in;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  margin-top: 5rem;
 | 
				
			||||||
 | 
					  max-height: calc(100vh - 10rem);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-hover-trigger:hover + #enhancer--panel:not([data-enhancer-panel-pinned]),
 | 
				
			||||||
 | 
					#enhancer--panel:not([data-enhancer-panel-pinned]):hover {
 | 
				
			||||||
 | 
					  opacity: 1;
 | 
				
			||||||
 | 
					  transform: translateX(calc(-1 * var(--component--panel-width)));
 | 
				
			||||||
 | 
					  box-shadow: var(--theme--ui_shadow, rgba(15, 15, 15, 0.05)) 0px 0px 0px 1px,
 | 
				
			||||||
 | 
					    var(--theme--ui_shadow, rgba(15, 15, 15, 0.1)) 0px 3px 6px,
 | 
				
			||||||
 | 
					    var(--theme--ui_shadow, rgba(15, 15, 15, 0.2)) 0px 9px 24px !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel[data-enhancer-panel-pinned] {
 | 
				
			||||||
 | 
					  opacity: 1;
 | 
				
			||||||
 | 
					  max-height: 100%;
 | 
				
			||||||
 | 
					  margin-top: 0;
 | 
				
			||||||
 | 
					  transform: translateX(calc(-1 * var(--component--panel-width)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#enhancer--panel-header {
 | 
				
			||||||
 | 
					  font-size: 1.35rem;
 | 
				
			||||||
 | 
					  font-weight: bold;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  padding: 0.75rem 1rem;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-content {
 | 
				
			||||||
 | 
					  font-size: 1rem;
 | 
				
			||||||
 | 
					  padding: 0.75rem 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-title {
 | 
				
			||||||
 | 
					  padding-left: 0.5em;
 | 
				
			||||||
 | 
					  padding-bottom: 0.1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-title > p {
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					  height: 1em;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-title > p svg,
 | 
				
			||||||
 | 
					#enhancer--panel-header-title > p img {
 | 
				
			||||||
 | 
					  height: 1em;
 | 
				
			||||||
 | 
					  width: 1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-title > p span {
 | 
				
			||||||
 | 
					  font-size: 0.9em;
 | 
				
			||||||
 | 
					  margin-left: 0.5em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-toggle {
 | 
				
			||||||
 | 
					  margin-left: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-toggle,
 | 
				
			||||||
 | 
					#enhancer--panel-header-switcher {
 | 
				
			||||||
 | 
					  height: 1em;
 | 
				
			||||||
 | 
					  width: 1em;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  opacity: 0;
 | 
				
			||||||
 | 
					  transition: 300ms ease-in-out;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-header-switcher svg {
 | 
				
			||||||
 | 
					  width: 0.5em;
 | 
				
			||||||
 | 
					  height: 0.5em;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  margin: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#enhancer--panel:not([data-enhancer-panel-pinned]) #enhancer--panel-header-toggle {
 | 
				
			||||||
 | 
					  transform: rotateZ(-180deg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel:hover #enhancer--panel-header-toggle,
 | 
				
			||||||
 | 
					#enhancer--panel:hover #enhancer--panel-header-switcher {
 | 
				
			||||||
 | 
					  opacity: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#enhancer--panel-resize {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  left: -5px;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  width: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel[data-enhancer-panel-pinned] #enhancer--panel-resize {
 | 
				
			||||||
 | 
					  cursor: col-resize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel-resize div {
 | 
				
			||||||
 | 
					  transition: background 150ms ease-in-out;
 | 
				
			||||||
 | 
					  background: transparent;
 | 
				
			||||||
 | 
					  width: 2px;
 | 
				
			||||||
 | 
					  margin-left: 4px;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#enhancer--panel[data-enhancer-panel-pinned] #enhancer--panel-resize:hover div {
 | 
				
			||||||
 | 
					  background: var(--theme--ui_divider);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										141
									
								
								extension/api/components/panel.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								extension/api/components/panel.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * notion-enhancer: api
 | 
				
			||||||
 | 
					 * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 | 
				
			||||||
 | 
					 * (https://notion-enhancer.github.io/) under the MIT license
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * shared notion-style elements
 | 
				
			||||||
 | 
					 * @module notion-enhancer/api/components/side-panel
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { web, components, registry } from '../_.mjs';
 | 
				
			||||||
 | 
					const db = await registry.db('36a2ffc9-27ff-480e-84a7-c7700a7d232d');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let $panel,
 | 
				
			||||||
 | 
					  _views = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const panel = async (icon, title, generator = () => {}) => {
 | 
				
			||||||
 | 
					  _views.push({
 | 
				
			||||||
 | 
					    icon: web.html`${icon}`,
 | 
				
			||||||
 | 
					    title: web.html`<span>${web.escape(title)}</span>`,
 | 
				
			||||||
 | 
					    $elem: generator(),
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!$panel) {
 | 
				
			||||||
 | 
					    $panel = web.html`<div id="enhancer--panel"></div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const notionRightSidebarSelector = '.notion-cursor-listener > div[style*="flex-end"]';
 | 
				
			||||||
 | 
					    await web.whenReady([notionRightSidebarSelector]);
 | 
				
			||||||
 | 
					    web.loadStylesheet('api/components/panel.css');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const $title = web.html`<div id="enhancer--panel-header-title"></div>`,
 | 
				
			||||||
 | 
					      $header = web.render(web.html`<div id="enhancer--panel-header"></div>`, $title),
 | 
				
			||||||
 | 
					      $content = web.html`<div id="enhancer--panel-content"></div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // opening/closing
 | 
				
			||||||
 | 
					    const $notionFrame = document.querySelector('.notion-frame'),
 | 
				
			||||||
 | 
					      $notionRightSidebar = document.querySelector(notionRightSidebarSelector),
 | 
				
			||||||
 | 
					      $pinnedToggle = web.html`<div id="enhancer--panel-header-toggle">
 | 
				
			||||||
 | 
					        ${await components.feather('chevrons-right')}
 | 
				
			||||||
 | 
					      </div>`,
 | 
				
			||||||
 | 
					      $hoverTrigger = web.html`<div id="enhancer--panel-hover-trigger"></div>`,
 | 
				
			||||||
 | 
					      panelPinnedAttr = 'data-enhancer-panel-pinned',
 | 
				
			||||||
 | 
					      isPinned = () => $panel.hasAttribute(panelPinnedAttr),
 | 
				
			||||||
 | 
					      isRightSidebarOpen = () =>
 | 
				
			||||||
 | 
					        $notionRightSidebar.matches('[style*="border-left: 1px solid rgba(0, 0, 0, 0)"]'),
 | 
				
			||||||
 | 
					      togglePanel = () => {
 | 
				
			||||||
 | 
					        const $elems = [$notionRightSidebar, $hoverTrigger, $panel];
 | 
				
			||||||
 | 
					        if (isPinned()) {
 | 
				
			||||||
 | 
					          if (isRightSidebarOpen()) $elems.push($notionFrame);
 | 
				
			||||||
 | 
					          for (const $elem of $elems) $elem.removeAttribute(panelPinnedAttr);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          $elems.push($notionFrame);
 | 
				
			||||||
 | 
					          for (const $elem of $elems) $elem.setAttribute(panelPinnedAttr, 'true');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        db.set(['panel.pinned'], isPinned());
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    web.addDocumentObserver(() => {
 | 
				
			||||||
 | 
					      if (isPinned()) {
 | 
				
			||||||
 | 
					        if (isRightSidebarOpen()) {
 | 
				
			||||||
 | 
					          $notionFrame.removeAttribute(panelPinnedAttr);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          $notionFrame.setAttribute(panelPinnedAttr, 'true');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }, [notionRightSidebarSelector]);
 | 
				
			||||||
 | 
					    if (await db.get(['panel.pinned'])) togglePanel();
 | 
				
			||||||
 | 
					    web.addHotkeyListener(await db.get(['panel.hotkey']), togglePanel);
 | 
				
			||||||
 | 
					    $pinnedToggle.addEventListener('click', togglePanel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // resizing
 | 
				
			||||||
 | 
					    let dragStartX,
 | 
				
			||||||
 | 
					      dragStartWidth,
 | 
				
			||||||
 | 
					      dragEventsFired,
 | 
				
			||||||
 | 
					      panelWidth = await db.get(['panel.width'], 240);
 | 
				
			||||||
 | 
					    const $resizeHandle = web.html`<div id="enhancer--panel-resize"><div></div></div>`,
 | 
				
			||||||
 | 
					      updateWidth = async () => {
 | 
				
			||||||
 | 
					        document.documentElement.style.setProperty(
 | 
				
			||||||
 | 
					          '--component--panel-width',
 | 
				
			||||||
 | 
					          panelWidth + 'px'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        db.set(['panel.width'], panelWidth);
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      resizeDrag = (event) => {
 | 
				
			||||||
 | 
					        event.preventDefault();
 | 
				
			||||||
 | 
					        dragEventsFired = true;
 | 
				
			||||||
 | 
					        panelWidth = dragStartWidth + (dragStartX - event.clientX);
 | 
				
			||||||
 | 
					        if (panelWidth < 190) panelWidth = 190;
 | 
				
			||||||
 | 
					        if (panelWidth > 480) panelWidth = 480;
 | 
				
			||||||
 | 
					        $panel.style.width = panelWidth + 'px';
 | 
				
			||||||
 | 
					        $hoverTrigger.style.width = panelWidth + 'px';
 | 
				
			||||||
 | 
					        $notionFrame.style.paddingRight = panelWidth + 'px';
 | 
				
			||||||
 | 
					        $notionRightSidebar.style.right = panelWidth + 'px';
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      resizeEnd = (event) => {
 | 
				
			||||||
 | 
					        $panel.style.width = '';
 | 
				
			||||||
 | 
					        $hoverTrigger.style.width = '';
 | 
				
			||||||
 | 
					        $notionFrame.style.paddingRight = '';
 | 
				
			||||||
 | 
					        $notionRightSidebar.style.right = '';
 | 
				
			||||||
 | 
					        updateWidth();
 | 
				
			||||||
 | 
					        $resizeHandle.style.cursor = '';
 | 
				
			||||||
 | 
					        document.body.removeEventListener('mousemove', resizeDrag);
 | 
				
			||||||
 | 
					        document.body.removeEventListener('mouseup', resizeEnd);
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      resizeStart = (event) => {
 | 
				
			||||||
 | 
					        dragStartX = event.clientX;
 | 
				
			||||||
 | 
					        dragStartWidth = panelWidth;
 | 
				
			||||||
 | 
					        $resizeHandle.style.cursor = 'auto';
 | 
				
			||||||
 | 
					        document.body.addEventListener('mousemove', resizeDrag);
 | 
				
			||||||
 | 
					        document.body.addEventListener('mouseup', resizeEnd);
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    updateWidth();
 | 
				
			||||||
 | 
					    $resizeHandle.addEventListener('mousedown', resizeStart);
 | 
				
			||||||
 | 
					    $resizeHandle.addEventListener('click', () => {
 | 
				
			||||||
 | 
					      if (dragEventsFired) {
 | 
				
			||||||
 | 
					        dragEventsFired = false;
 | 
				
			||||||
 | 
					      } else togglePanel();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // view selection
 | 
				
			||||||
 | 
					    const $switcherTrigger = web.html`<div id="enhancer--panel-header-switcher">
 | 
				
			||||||
 | 
					        ${await components.feather('chevron-up')}
 | 
				
			||||||
 | 
					        ${await components.feather('chevron-down')}
 | 
				
			||||||
 | 
					      </div>`,
 | 
				
			||||||
 | 
					      renderView = (view) => {
 | 
				
			||||||
 | 
					        web.render(web.empty($title), web.render(web.html`<p></p>`, view.icon, view.title));
 | 
				
			||||||
 | 
					        web.render(web.empty($content), view.$elem);
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    renderView(_views[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    web.render(
 | 
				
			||||||
 | 
					      $panel,
 | 
				
			||||||
 | 
					      web.render($header, $switcherTrigger, $title, $pinnedToggle),
 | 
				
			||||||
 | 
					      $content,
 | 
				
			||||||
 | 
					      $resizeHandle
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    $notionRightSidebar.after($hoverTrigger, $panel);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -1,6 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * notion-enhancer core: components
 | 
					 | 
				
			||||||
 * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 | 
					 | 
				
			||||||
 * (c) 2021 CloudHill <rl.cloudhill@gmail.com> (https://github.com/CloudHill)
 | 
					 | 
				
			||||||
 * (https://notion-enhancer.github.io/) under the MIT license
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@ -1,24 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * notion-enhancer: api
 | 
					 | 
				
			||||||
 * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 | 
					 | 
				
			||||||
 * (https://notion-enhancer.github.io/) under the MIT license
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
'use strict';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * notion-style elements inc. the sidebar
 | 
					 | 
				
			||||||
 * @module notion-enhancer/api/components/side-panel
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { web } from '../_.mjs';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let _$sidebar;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const sidebar = (icon, name, loader = ($panel) => {}) => {
 | 
					 | 
				
			||||||
  if (!_$sidebar) {
 | 
					 | 
				
			||||||
    web.loadStylesheet('api/components/sidebar.css');
 | 
					 | 
				
			||||||
    _$sidebar = web.html`<div id="enhancer--sidebar"></div>`;
 | 
					 | 
				
			||||||
    web.render(document.body, _$sidebar);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * notion-style elements inc. the sidebar
 | 
					 * shared notion-style elements
 | 
				
			||||||
 * @module notion-enhancer/api/components/tooltip
 | 
					 * @module notion-enhancer/api/components/tooltip
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -22,8 +22,8 @@ let _$tooltip;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export const tooltip = ($ref, text) => {
 | 
					export const tooltip = ($ref, text) => {
 | 
				
			||||||
  if (!_$tooltip) {
 | 
					  if (!_$tooltip) {
 | 
				
			||||||
    web.loadStylesheet('api/components/tooltip.css');
 | 
					 | 
				
			||||||
    _$tooltip = web.html`<div id="enhancer--tooltip"></div>`;
 | 
					    _$tooltip = web.html`<div id="enhancer--tooltip"></div>`;
 | 
				
			||||||
 | 
					    web.loadStylesheet('api/components/tooltip.css');
 | 
				
			||||||
    web.render(document.body, _$tooltip);
 | 
					    web.render(document.body, _$tooltip);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  text = fmt.md.render(text);
 | 
					  text = fmt.md.render(text);
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@
 | 
				
			|||||||
 * @module notion-enhancer/api/fmt
 | 
					 * @module notion-enhancer/api/fmt
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { web, fs } from './_.mjs';
 | 
					import { web, fs, components } from './_.mjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import '../dep/prism.min.js';
 | 
					import '../dep/prism.min.js';
 | 
				
			||||||
/** syntax highlighting using https://prismjs.com/ */
 | 
					/** syntax highlighting using https://prismjs.com/ */
 | 
				
			||||||
@ -21,7 +21,7 @@ Prism.hooks.add('complete', async (event) => {
 | 
				
			|||||||
  event.element.parentElement.removeAttribute('tabindex');
 | 
					  event.element.parentElement.removeAttribute('tabindex');
 | 
				
			||||||
  event.element.parentElement.parentElement
 | 
					  event.element.parentElement.parentElement
 | 
				
			||||||
    .querySelector('.copy-to-clipboard-button')
 | 
					    .querySelector('.copy-to-clipboard-button')
 | 
				
			||||||
    .prepend(web.html`${await web.icon('clipboard')}`);
 | 
					    .prepend(web.html`${await components.feather('clipboard')}`);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import '../dep/markdown-it.min.js';
 | 
					import '../dep/markdown-it.min.js';
 | 
				
			||||||
 | 
				
			|||||||
@ -13,12 +13,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { fs, fmt } from './_.mjs';
 | 
					import { fs, fmt } from './_.mjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _hotkeyEventListeners = [],
 | 
					 | 
				
			||||||
  _documentObserverListeners = [],
 | 
					 | 
				
			||||||
  _documentObserverEvents = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let _hotkeyEvent, _documentObserver;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import '../dep/jscolor.min.js';
 | 
					import '../dep/jscolor.min.js';
 | 
				
			||||||
/** color picker with alpha channel using https://jscolor.com/ */
 | 
					/** color picker with alpha channel using https://jscolor.com/ */
 | 
				
			||||||
export const jscolor = JSColor;
 | 
					export const jscolor = JSColor;
 | 
				
			||||||
@ -144,21 +138,27 @@ export const loadStylesheet = (path) => {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					const _hotkeyEvent = document.addEventListener('keyup', (event) => {
 | 
				
			||||||
 * generate an icon from the feather icons set
 | 
					    if (document.activeElement.nodeName === 'INPUT') return;
 | 
				
			||||||
 * @param {string} name - the name/id of the icon
 | 
					    for (const hotkey of _hotkeyEventListeners) {
 | 
				
			||||||
 * @param {object} attrs - an object of attributes to apply to the icon e.g. classes
 | 
					      const pressed = hotkey.keys.every((key) => {
 | 
				
			||||||
 * @returns {string} an svg string
 | 
					        key = key.toLowerCase();
 | 
				
			||||||
 */
 | 
					        const modifiers = {
 | 
				
			||||||
export const icon = (name, attrs = {}) => {
 | 
					          metaKey: ['meta', 'os', 'win', 'cmd', 'command'],
 | 
				
			||||||
  attrs.style = (
 | 
					          ctrlKey: ['ctrl', 'control'],
 | 
				
			||||||
    (attrs.style || '') +
 | 
					          shiftKey: ['shift'],
 | 
				
			||||||
    ';stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill:none;'
 | 
					          altKey: ['alt'],
 | 
				
			||||||
  ).trim();
 | 
					        };
 | 
				
			||||||
  return `<svg ${Object.entries(attrs)
 | 
					        for (const modifier in modifiers) {
 | 
				
			||||||
    .map(([key, val]) => `${escape(key)}="${escape(val)}"`)
 | 
					          const pressed = modifiers[modifier].includes(key) && event[modifier];
 | 
				
			||||||
    .join(' ')}><use xlink:href="${fs.localPath('dep/feather-sprite.svg')}#${name}" /></svg>`;
 | 
					          if (pressed) return true;
 | 
				
			||||||
};
 | 
					        }
 | 
				
			||||||
 | 
					        if (key === event.key.toLowerCase()) return true;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      if (pressed) hotkey.callback();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }),
 | 
				
			||||||
 | 
					  _hotkeyEventListeners = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * register a hotkey listener to the page
 | 
					 * register a hotkey listener to the page
 | 
				
			||||||
@ -169,28 +169,6 @@ export const icon = (name, attrs = {}) => {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export const addHotkeyListener = (keys, callback) => {
 | 
					export const addHotkeyListener = (keys, callback) => {
 | 
				
			||||||
  if (typeof keys === 'string') keys = keys.split('+');
 | 
					  if (typeof keys === 'string') keys = keys.split('+');
 | 
				
			||||||
  if (!_hotkeyEvent) {
 | 
					 | 
				
			||||||
    _hotkeyEvent = document.addEventListener('keyup', (event) => {
 | 
					 | 
				
			||||||
      if (document.activeElement.nodeName === 'INPUT') return;
 | 
					 | 
				
			||||||
      for (const hotkey of _hotkeyEventListeners) {
 | 
					 | 
				
			||||||
        const pressed = hotkey.keys.every((key) => {
 | 
					 | 
				
			||||||
          key = key.toLowerCase();
 | 
					 | 
				
			||||||
          const modifiers = {
 | 
					 | 
				
			||||||
            metaKey: ['meta', 'os', 'win', 'cmd', 'command'],
 | 
					 | 
				
			||||||
            ctrlKey: ['ctrl', 'control'],
 | 
					 | 
				
			||||||
            shiftKey: ['shift'],
 | 
					 | 
				
			||||||
            altKey: ['alt'],
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
          for (const modifier in modifiers) {
 | 
					 | 
				
			||||||
            const pressed = modifiers[modifier].includes(key) && event[modifier];
 | 
					 | 
				
			||||||
            if (pressed) return true;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          if (key === event.key.toLowerCase()) return true;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        if (pressed) hotkey.callback();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _hotkeyEventListeners.push({ keys, callback });
 | 
					  _hotkeyEventListeners.push({ keys, callback });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -203,40 +181,39 @@ export const removeHotkeyListener = (callback) => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const _documentObserver = new MutationObserver((list, observer) => {
 | 
				
			||||||
 | 
					    if (!_documentObserverEvents.length)
 | 
				
			||||||
 | 
					      requestIdleCallback(() => (queue) => {
 | 
				
			||||||
 | 
					        while (queue.length) {
 | 
				
			||||||
 | 
					          const event = queue.shift();
 | 
				
			||||||
 | 
					          for (const listener of _documentObserverListeners) {
 | 
				
			||||||
 | 
					            if (
 | 
				
			||||||
 | 
					              !listener.selectors.length ||
 | 
				
			||||||
 | 
					              listener.selectors.some(
 | 
				
			||||||
 | 
					                (selector) =>
 | 
				
			||||||
 | 
					                  event.target.matches(selector) || event.target.matches(`${selector} *`)
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					              listener.callback(event);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    _documentObserverEvents.push(...list);
 | 
				
			||||||
 | 
					  }),
 | 
				
			||||||
 | 
					  _documentObserverListeners = [],
 | 
				
			||||||
 | 
					  _documentObserverEvents = [];
 | 
				
			||||||
 | 
					_documentObserver.observe(document.body, {
 | 
				
			||||||
 | 
					  childList: true,
 | 
				
			||||||
 | 
					  subtree: true,
 | 
				
			||||||
 | 
					  attributes: true,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * add a listener to watch for changes to the dom
 | 
					 * add a listener to watch for changes to the dom
 | 
				
			||||||
 * @param {onDocumentObservedCallback} callback
 | 
					 * @param {onDocumentObservedCallback} callback
 | 
				
			||||||
 * @param {array<string>} [selectors]
 | 
					 * @param {array<string>} [selectors]
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const addDocumentObserver = (callback, selectors = []) => {
 | 
					export const addDocumentObserver = (callback, selectors = []) => {
 | 
				
			||||||
  if (!_documentObserver) {
 | 
					 | 
				
			||||||
    const handle = (queue) => {
 | 
					 | 
				
			||||||
      while (queue.length) {
 | 
					 | 
				
			||||||
        const event = queue.shift();
 | 
					 | 
				
			||||||
        for (const listener of _documentObserverListeners) {
 | 
					 | 
				
			||||||
          if (
 | 
					 | 
				
			||||||
            !listener.selectors.length ||
 | 
					 | 
				
			||||||
            listener.selectors.some(
 | 
					 | 
				
			||||||
              (selector) =>
 | 
					 | 
				
			||||||
                event.target.matches(selector) || event.target.matches(`${selector} *`)
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
          ) {
 | 
					 | 
				
			||||||
            listener.callback(event);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    _documentObserver = new MutationObserver((list, observer) => {
 | 
					 | 
				
			||||||
      if (!_documentObserverEvents.length)
 | 
					 | 
				
			||||||
        requestIdleCallback(() => handle(_documentObserverEvents));
 | 
					 | 
				
			||||||
      _documentObserverEvents.push(...list);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    _documentObserver.observe(document.body, {
 | 
					 | 
				
			||||||
      childList: true,
 | 
					 | 
				
			||||||
      subtree: true,
 | 
					 | 
				
			||||||
      attributes: true,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _documentObserverListeners.push({ callback, selectors });
 | 
					  _documentObserverListeners.push({ callback, selectors });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function (api, db) {
 | 
					export default async function (api, db) {
 | 
				
			||||||
  const { web } = api;
 | 
					  const { web, components } = api;
 | 
				
			||||||
  await web.whenReady();
 | 
					  await web.whenReady();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let _lastPage = {};
 | 
					  let _lastPage = {};
 | 
				
			||||||
@ -30,4 +30,8 @@ export default async function (api, db) {
 | 
				
			|||||||
      _lastPage = getCurrentPage();
 | 
					      _lastPage = getCurrentPage();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  components.panel(await components.feather('sidebar'), 'Test Panel', ($panel) => {
 | 
				
			||||||
 | 
					    return web.html`<p>test</p>`;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
  "name": "components",
 | 
					  "name": "components",
 | 
				
			||||||
  "id": "36a2ffc9-27ff-480e-84a7-c7700a7d232d",
 | 
					  "id": "36a2ffc9-27ff-480e-84a7-c7700a7d232d",
 | 
				
			||||||
  "version": "0.2.0",
 | 
					  "version": "0.2.0",
 | 
				
			||||||
  "description": "notion-style elements reused by other mods, inc. the sidebar.",
 | 
					  "description": "shared notion-style elements.",
 | 
				
			||||||
  "tags": ["core"],
 | 
					  "tags": ["core"],
 | 
				
			||||||
  "authors": [
 | 
					  "authors": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -24,10 +24,10 @@
 | 
				
			|||||||
  "options": [
 | 
					  "options": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "type": "hotkey",
 | 
					      "type": "hotkey",
 | 
				
			||||||
      "key": "side-panel-hotkey",
 | 
					      "key": "panel.hotkey",
 | 
				
			||||||
      "label": "toggle enhancer sidebar hotkey",
 | 
					      "label": "toggle panel hotkey",
 | 
				
			||||||
      "value": "Ctrl+Alt+\\",
 | 
					      "value": "Ctrl+Alt+\\",
 | 
				
			||||||
      "tooltip": "opens/closes the extra sidebar in notion - will only work if a mod is making use of it."
 | 
					      "tooltip": "opens/closes the side panel in notion - will only work if a mod is making use of it."
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ export const options = {
 | 
				
			|||||||
  toggle: async (mod, opt) => {
 | 
					  toggle: async (mod, opt) => {
 | 
				
			||||||
    const checked = await profileDB.get([mod.id, opt.key], opt.value),
 | 
					    const checked = await profileDB.get([mod.id, opt.key], opt.value),
 | 
				
			||||||
      $toggle = blocks.toggle(opt.label, checked),
 | 
					      $toggle = blocks.toggle(opt.label, checked),
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = $toggle.children[0],
 | 
					      $label = $toggle.children[0],
 | 
				
			||||||
      $input = $toggle.children[1];
 | 
					      $input = $toggle.children[1];
 | 
				
			||||||
    if (opt.tooltip) {
 | 
					    if (opt.tooltip) {
 | 
				
			||||||
@ -73,7 +73,7 @@ export const options = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  select: async (mod, opt) => {
 | 
					  select: async (mod, opt) => {
 | 
				
			||||||
    const value = await profileDB.get([mod.id, opt.key], opt.values[0]),
 | 
					    const value = await profileDB.get([mod.id, opt.key], opt.values[0]),
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = web.render(
 | 
					      $label = web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
					        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
				
			||||||
@ -88,7 +88,7 @@ export const options = {
 | 
				
			|||||||
      $select = web.html`<select class="input">
 | 
					      $select = web.html`<select class="input">
 | 
				
			||||||
        ${$options.join('')}
 | 
					        ${$options.join('')}
 | 
				
			||||||
      </select>`,
 | 
					      </select>`,
 | 
				
			||||||
      $icon = web.html`${web.icon('chevron-down', { class: 'input-icon' })}`;
 | 
					      $icon = web.html`${await components.feather('chevron-down', { class: 'input-icon' })}`;
 | 
				
			||||||
    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
					    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
				
			||||||
    $select.addEventListener('change', async (event) => {
 | 
					    $select.addEventListener('change', async (event) => {
 | 
				
			||||||
      await profileDB.set([mod.id, opt.key], $select.value);
 | 
					      await profileDB.set([mod.id, opt.key], $select.value);
 | 
				
			||||||
@ -98,13 +98,13 @@ export const options = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  text: async (mod, opt) => {
 | 
					  text: async (mod, opt) => {
 | 
				
			||||||
    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
					    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = web.render(
 | 
					      $label = web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
					        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      $input = web.html`<input type="text" class="input" value="${web.escape(value)}">`,
 | 
					      $input = web.html`<input type="text" class="input" value="${web.escape(value)}">`,
 | 
				
			||||||
      $icon = web.html`${web.icon('type', { class: 'input-icon' })}`;
 | 
					      $icon = web.html`${await components.feather('type', { class: 'input-icon' })}`;
 | 
				
			||||||
    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
					    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
				
			||||||
    $input.addEventListener('change', async (event) => {
 | 
					    $input.addEventListener('change', async (event) => {
 | 
				
			||||||
      await profileDB.set([mod.id, opt.key], $input.value);
 | 
					      await profileDB.set([mod.id, opt.key], $input.value);
 | 
				
			||||||
@ -114,13 +114,13 @@ export const options = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  number: async (mod, opt) => {
 | 
					  number: async (mod, opt) => {
 | 
				
			||||||
    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
					    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = web.render(
 | 
					      $label = web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
					        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      $input = web.html`<input type="number" class="input" value="${value}">`,
 | 
					      $input = web.html`<input type="number" class="input" value="${value}">`,
 | 
				
			||||||
      $icon = web.html`${web.icon('hash', { class: 'input-icon' })}`;
 | 
					      $icon = web.html`${await components.feather('hash', { class: 'input-icon' })}`;
 | 
				
			||||||
    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
					    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
				
			||||||
    $input.addEventListener('change', async (event) => {
 | 
					    $input.addEventListener('change', async (event) => {
 | 
				
			||||||
      await profileDB.set([mod.id, opt.key], $input.value);
 | 
					      await profileDB.set([mod.id, opt.key], $input.value);
 | 
				
			||||||
@ -130,13 +130,13 @@ export const options = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  color: async (mod, opt) => {
 | 
					  color: async (mod, opt) => {
 | 
				
			||||||
    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
					    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = web.render(
 | 
					      $label = web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
					        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      $input = web.html`<input type="text" class="input">`,
 | 
					      $input = web.html`<input type="text" class="input">`,
 | 
				
			||||||
      $icon = web.html`${web.icon('droplet', { class: 'input-icon' })}`,
 | 
					      $icon = web.html`${await components.feather('droplet', { class: 'input-icon' })}`,
 | 
				
			||||||
      paint = () => {
 | 
					      paint = () => {
 | 
				
			||||||
        $input.style.background = $picker.toBackground();
 | 
					        $input.style.background = $picker.toBackground();
 | 
				
			||||||
        $input.style.color = $picker.isLight() ? '#000' : '#fff';
 | 
					        $input.style.color = $picker.isLight() ? '#000' : '#fff';
 | 
				
			||||||
@ -163,7 +163,7 @@ export const options = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  file: async (mod, opt) => {
 | 
					  file: async (mod, opt) => {
 | 
				
			||||||
    const { filename } = (await profileDB.get([mod.id, opt.key], {})) || {},
 | 
					    const { filename } = (await profileDB.get([mod.id, opt.key], {})) || {},
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = web.render(
 | 
					      $label = web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
					        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
				
			||||||
@ -172,7 +172,7 @@ export const options = {
 | 
				
			|||||||
      $input = web.html`<input type="file" class="hidden" accept=${web.escape(
 | 
					      $input = web.html`<input type="file" class="hidden" accept=${web.escape(
 | 
				
			||||||
        opt.extensions.join(',')
 | 
					        opt.extensions.join(',')
 | 
				
			||||||
      )}>`,
 | 
					      )}>`,
 | 
				
			||||||
      $icon = web.html`${web.icon('file', { class: 'input-icon' })}`,
 | 
					      $icon = web.html`${await components.feather('file', { class: 'input-icon' })}`,
 | 
				
			||||||
      $filename = web.html`<span>${web.escape(filename || 'none')}</span>`,
 | 
					      $filename = web.html`<span>${web.escape(filename || 'none')}</span>`,
 | 
				
			||||||
      $latest = web.render(web.html`<button class="file-latest">Latest: </button>`, $filename);
 | 
					      $latest = web.render(web.html`<button class="file-latest">Latest: </button>`, $filename);
 | 
				
			||||||
    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
					    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
				
			||||||
@ -201,13 +201,13 @@ export const options = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  hotkey: async (mod, opt) => {
 | 
					  hotkey: async (mod, opt) => {
 | 
				
			||||||
    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
					    const value = await profileDB.get([mod.id, opt.key], opt.value),
 | 
				
			||||||
      $tooltip = web.html`${web.icon('info', { class: 'input-tooltip' })}`,
 | 
					      $tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
 | 
				
			||||||
      $label = web.render(
 | 
					      $label = web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
					        web.render(web.html`<p></p>`, opt.tooltip ? $tooltip : '', opt.label)
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      $input = web.html`<input type="text" class="input" value="${web.escape(value)}">`,
 | 
					      $input = web.html`<input type="text" class="input" value="${web.escape(value)}">`,
 | 
				
			||||||
      $icon = web.html`${web.icon('command', { class: 'input-icon' })}`;
 | 
					      $icon = web.html`${await components.feather('command', { class: 'input-icon' })}`;
 | 
				
			||||||
    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
					    if (opt.tooltip) components.tooltip($tooltip, opt.tooltip);
 | 
				
			||||||
    $input.addEventListener('keydown', async (event) => {
 | 
					    $input.addEventListener('keydown', async (event) => {
 | 
				
			||||||
      event.preventDefault();
 | 
					      event.preventDefault();
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { env, fs, storage, registry, web } from '../../api/_.mjs';
 | 
					import { env, fs, storage, registry, web, components } from '../../api/_.mjs';
 | 
				
			||||||
import { notifications } from './notifications.mjs';
 | 
					import { notifications } from './notifications.mjs';
 | 
				
			||||||
import { blocks, options } from './blocks.mjs';
 | 
					import { blocks, options } from './blocks.mjs';
 | 
				
			||||||
import './styles.mjs';
 | 
					import './styles.mjs';
 | 
				
			||||||
@ -74,17 +74,17 @@ $profile.addEventListener('click', async (event) => {
 | 
				
			|||||||
        pattern="/^[A-Za-z0-9_-]+$/"
 | 
					        pattern="/^[A-Za-z0-9_-]+$/"
 | 
				
			||||||
      >`,
 | 
					      >`,
 | 
				
			||||||
      $export = web.html`<button class="profile-export">
 | 
					      $export = web.html`<button class="profile-export">
 | 
				
			||||||
        ${web.icon('download', { class: 'profile-icon-action' })}
 | 
					        ${await components.feather('download', { class: 'profile-icon-action' })}
 | 
				
			||||||
      </button>`,
 | 
					      </button>`,
 | 
				
			||||||
      $import = web.html`<label class="profile-import">
 | 
					      $import = web.html`<label class="profile-import">
 | 
				
			||||||
        <input type="file" class="hidden" accept="application/json">
 | 
					        <input type="file" class="hidden" accept="application/json">
 | 
				
			||||||
        ${web.icon('upload', { class: 'profile-icon-action' })}
 | 
					        ${await components.feather('upload', { class: 'profile-icon-action' })}
 | 
				
			||||||
      </label>`,
 | 
					      </label>`,
 | 
				
			||||||
      $save = web.html`<button class="profile-save">
 | 
					      $save = web.html`<button class="profile-save">
 | 
				
			||||||
        ${web.icon('save', { class: 'profile-icon-text' })} Save
 | 
					        ${await components.feather('save', { class: 'profile-icon-text' })} Save
 | 
				
			||||||
      </button>`,
 | 
					      </button>`,
 | 
				
			||||||
      $delete = web.html`<button class="profile-delete">
 | 
					      $delete = web.html`<button class="profile-delete">
 | 
				
			||||||
        ${web.icon('trash-2', { class: 'profile-icon-text' })} Delete
 | 
					        ${await components.feather('trash-2', { class: 'profile-icon-text' })} Delete
 | 
				
			||||||
      </button>`,
 | 
					      </button>`,
 | 
				
			||||||
      $error = web.html`<p class="profile-error"></p>`;
 | 
					      $error = web.html`<p class="profile-error"></p>`;
 | 
				
			||||||
    $export.addEventListener('click', async (event) => {
 | 
					    $export.addEventListener('click', async (event) => {
 | 
				
			||||||
@ -175,12 +175,12 @@ $profile.addEventListener('click', async (event) => {
 | 
				
			|||||||
      web.render(
 | 
					      web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        $select,
 | 
					        $select,
 | 
				
			||||||
        web.html`${web.icon('chevron-down', { class: 'input-icon' })}`
 | 
					        web.html`${await components.feather('chevron-down', { class: 'input-icon' })}`
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      web.render(
 | 
					      web.render(
 | 
				
			||||||
        web.html`<label class="input-label"></label>`,
 | 
					        web.html`<label class="input-label"></label>`,
 | 
				
			||||||
        $edit,
 | 
					        $edit,
 | 
				
			||||||
        web.html`${web.icon('type', { class: 'input-icon' })}`
 | 
					        web.html`${await components.feather('type', { class: 'input-icon' })}`
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      web.render(web.html`<p class="profile-actions"></p>`, $export, $import, $save, $delete),
 | 
					      web.render(web.html`<p class="profile-actions"></p>`, $export, $import, $save, $delete),
 | 
				
			||||||
      $error
 | 
					      $error
 | 
				
			||||||
@ -288,7 +288,7 @@ const _$modListCache = {},
 | 
				
			|||||||
          web.render(
 | 
					          web.render(
 | 
				
			||||||
            web.html`<label class="search-container"></label>`,
 | 
					            web.html`<label class="search-container"></label>`,
 | 
				
			||||||
            $search,
 | 
					            $search,
 | 
				
			||||||
            web.html`${web.icon('search', { class: 'input-icon' })}`
 | 
					            web.html`${await components.feather('search', { class: 'input-icon' })}`
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          message ? web.html`<p class="main-message">${web.escape(message)}</p>` : '',
 | 
					          message ? web.html`<p class="main-message">${web.escape(message)}</p>` : '',
 | 
				
			||||||
          $list
 | 
					          $list
 | 
				
			||||||
@ -303,14 +303,13 @@ const $notionNavItem = web.html`<h1 class="nav-notion">
 | 
				
			|||||||
      /width="\d+" height="\d+"/,
 | 
					      /width="\d+" height="\d+"/,
 | 
				
			||||||
      `class="nav-notion-icon"`
 | 
					      `class="nav-notion-icon"`
 | 
				
			||||||
    )}
 | 
					    )}
 | 
				
			||||||
    <a href="https://notion-enhancer.github.io/" target="_blank">notion-enhancer</a>
 | 
					    <span>notion-enhancer</span>
 | 
				
			||||||
  </h1>`;
 | 
					  </h1>`;
 | 
				
			||||||
$notionNavItem.children[0].addEventListener('click', env.focusNotion);
 | 
					$notionNavItem.addEventListener('click', env.focusNotion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const $coreNavItem = web.html`<a href="?view=core" class="nav-item">core</a>`,
 | 
					const $coreNavItem = web.html`<a href="?view=core" class="nav-item">core</a>`,
 | 
				
			||||||
  $extensionsNavItem = web.html`<a href="?view=extensions" class="nav-item">extensions</a>`,
 | 
					  $extensionsNavItem = web.html`<a href="?view=extensions" class="nav-item">extensions</a>`,
 | 
				
			||||||
  $themesNavItem = web.html`<a href="?view=themes" class="nav-item">themes</a>`,
 | 
					  $themesNavItem = web.html`<a href="?view=themes" class="nav-item">themes</a>`;
 | 
				
			||||||
  $communityNavItem = web.html`<a href="https://discord.gg/sFWPXtA" class="nav-item">community</a>`;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
web.render(
 | 
					web.render(
 | 
				
			||||||
  document.body,
 | 
					  document.body,
 | 
				
			||||||
@ -324,7 +323,8 @@ web.render(
 | 
				
			|||||||
        $coreNavItem,
 | 
					        $coreNavItem,
 | 
				
			||||||
        $extensionsNavItem,
 | 
					        $extensionsNavItem,
 | 
				
			||||||
        $themesNavItem,
 | 
					        $themesNavItem,
 | 
				
			||||||
        $communityNavItem
 | 
					        web.html`<a href="https://notion-enhancer.github.io" class="nav-item">docs</a>`,
 | 
				
			||||||
 | 
					        web.html`<a href="https://discord.gg/sFWPXtA" class="nav-item">community</a>`
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      $main
 | 
					      $main
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { env, fs, storage, fmt, registry, web } from '../../api/_.mjs';
 | 
					import { env, fs, storage, fmt, registry, web, components } from '../../api/_.mjs';
 | 
				
			||||||
import { tw } from './styles.mjs';
 | 
					import { tw } from './styles.mjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const notifications = {
 | 
					export const notifications = {
 | 
				
			||||||
@ -16,7 +16,7 @@ export const notifications = {
 | 
				
			|||||||
    registry.welcomeNotification,
 | 
					    registry.welcomeNotification,
 | 
				
			||||||
    ...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')),
 | 
					    ...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')),
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  add({ icon, message, id = undefined, color = undefined, link = undefined }) {
 | 
					  async add({ icon, message, id = undefined, color = undefined, link = undefined }) {
 | 
				
			||||||
    const $notification = link
 | 
					    const $notification = link
 | 
				
			||||||
        ? web.html`<a
 | 
					        ? web.html`<a
 | 
				
			||||||
          href="${web.escape(link)}"
 | 
					          href="${web.escape(link)}"
 | 
				
			||||||
@ -47,16 +47,16 @@ export const notifications = {
 | 
				
			|||||||
        web.html`<span class="notification-text markdown-inline">
 | 
					        web.html`<span class="notification-text markdown-inline">
 | 
				
			||||||
          ${fmt.md.renderInline(message)}
 | 
					          ${fmt.md.renderInline(message)}
 | 
				
			||||||
        </span>`,
 | 
					        </span>`,
 | 
				
			||||||
        web.html`${web.icon(icon, { class: 'notification-icon' })}`
 | 
					        web.html`${await components.feather(icon, { class: 'notification-icon' })}`
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    return $notification;
 | 
					    return $notification;
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  _onChange: false,
 | 
					  _onChange: false,
 | 
				
			||||||
  onChange() {
 | 
					  async onChange() {
 | 
				
			||||||
    if (this._onChange) return;
 | 
					    if (this._onChange) return;
 | 
				
			||||||
    this._onChange = true;
 | 
					    this._onChange = true;
 | 
				
			||||||
    const $notification = this.add({
 | 
					    const $notification = await this.add({
 | 
				
			||||||
      icon: 'refresh-cw',
 | 
					      icon: 'refresh-cw',
 | 
				
			||||||
      message: 'Reload to apply changes.',
 | 
					      message: 'Reload to apply changes.',
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -36,13 +36,13 @@ const customClasses = {
 | 
				
			|||||||
  'notification-icon': apply`fill-current opacity-75 h-4 w-4 mx-2`,
 | 
					  'notification-icon': apply`fill-current opacity-75 h-4 w-4 mx-2`,
 | 
				
			||||||
  'body-container': apply`flex w-full h-full overflow-hidden`,
 | 
					  'body-container': apply`flex w-full h-full overflow-hidden`,
 | 
				
			||||||
  'content-container': apply`h-full w-full-96`,
 | 
					  'content-container': apply`h-full w-full-96`,
 | 
				
			||||||
  'nav': apply`px-4 py-3 flex flex-wrap items-center border-b border-divider h-48 sm:h-32 lg:h-16`,
 | 
					  'nav': apply`px-4 py-3 flex flex-wrap items-center border-b border-divider h-64 sm:h-48 md:h-32 lg:h-16`,
 | 
				
			||||||
  'nav-notion': apply`flex items-center font-semibold text-xl cursor-pointer select-none mr-4
 | 
					  'nav-notion': apply`flex items-center font-semibold text-xl cursor-pointer select-none mr-4
 | 
				
			||||||
      ml-4 sm:mb-4 md:w-full lg:(w-auto ml-0 mb-0)`,
 | 
					      ml-4 sm:mb-4 md:w-full lg:(w-auto ml-0 mb-0)`,
 | 
				
			||||||
  'nav-notion-icon': apply`h-12 w-12 mr-5 sm:(h-6 w-6 mr-3)`,
 | 
					  'nav-notion-icon': apply`h-12 w-12 mr-5 sm:(h-6 w-6 mr-3)`,
 | 
				
			||||||
  'nav-item': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium hover:bg-interactive-hover focus:bg-interactive-focus`,
 | 
					  'nav-item': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium hover:bg-interactive-hover focus:bg-interactive-focus`,
 | 
				
			||||||
  'nav-item-selected': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-divider bg-notion-secondary`,
 | 
					  'nav-item-selected': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-divider bg-notion-secondary`,
 | 
				
			||||||
  'main': apply`transition px-4 py-3 overflow-y-auto max-h-full-48 sm:max-h-full-32 lg:max-h-full-16`,
 | 
					  'main': apply`transition px-4 py-3 overflow-y-auto max-h-full-64 sm:max-h-full-48 md:max-h-full-32 lg:max-h-full-16`,
 | 
				
			||||||
  'main-message': apply`mx-2.5 my-2.5 px-px text-sm text-foreground-secondary text-justify`,
 | 
					  'main-message': apply`mx-2.5 my-2.5 px-px text-sm text-foreground-secondary text-justify`,
 | 
				
			||||||
  'mods-list': apply`flex flex-wrap`,
 | 
					  'mods-list': apply`flex flex-wrap`,
 | 
				
			||||||
  'mod-container': apply`w-full md:w-1/2 lg:w-1/3 xl:w-1/4 2xl:w-1/5 px-2.5 py-2.5 box-border`,
 | 
					  'mod-container': apply`w-full md:w-1/2 lg:w-1/3 xl:w-1/4 2xl:w-1/5 px-2.5 py-2.5 box-border`,
 | 
				
			||||||
@ -145,6 +145,7 @@ setup({
 | 
				
			|||||||
        'full-16': 'calc(100% - 4rem)',
 | 
					        'full-16': 'calc(100% - 4rem)',
 | 
				
			||||||
        'full-32': 'calc(100% - 8rem)',
 | 
					        'full-32': 'calc(100% - 8rem)',
 | 
				
			||||||
        'full-48': 'calc(100% - 12rem)',
 | 
					        'full-48': 'calc(100% - 12rem)',
 | 
				
			||||||
 | 
					        'full-64': 'calc(100% - 16rem)',
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user