mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-12 00:09:03 +00:00
theme: classic dark, feat(menu): render card lists of available mods
This commit is contained in:
parent
d738801dc1
commit
c6d58f37ee
@ -69,6 +69,92 @@ function View({ id }, ...children) {
|
|||||||
return $el;
|
return $el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function List({}, ...children) {
|
||||||
|
const { html } = globalThis.__enhancerApi;
|
||||||
|
return html`<div class="flex flex-col gap-y-[14px]">${children}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Mod({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
description,
|
||||||
|
thumbnail,
|
||||||
|
tags = [],
|
||||||
|
authors,
|
||||||
|
options = [],
|
||||||
|
enabled,
|
||||||
|
_update,
|
||||||
|
_src,
|
||||||
|
}) {
|
||||||
|
const { html, enhancerUrl } = globalThis.__enhancerApi,
|
||||||
|
$thumbnail = thumbnail
|
||||||
|
? html`<img
|
||||||
|
src="${enhancerUrl(`${_src}/${thumbnail}`)}"
|
||||||
|
class="rounded-[4px] mr-[12px] h-[74px] my-auto"
|
||||||
|
/>`
|
||||||
|
: "",
|
||||||
|
$options = options.length
|
||||||
|
? html`<button
|
||||||
|
class="flex items-center p-[4px] rounded-[4px] transition
|
||||||
|
text-[color:var(--theme--fg-secondary)] my-auto mr-[8px]
|
||||||
|
duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
|
||||||
|
onclick=${() => {
|
||||||
|
// open mod options page
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i class="i-settings w-[18px] h-[18px]"></i>
|
||||||
|
</button>`
|
||||||
|
: "";
|
||||||
|
return html`<label
|
||||||
|
id=${id}
|
||||||
|
for="${id}-toggle"
|
||||||
|
class="notion-enhancer--menu-mod flex items-stretch rounded-[4px]
|
||||||
|
bg-[color:var(--theme--bg-secondary)] w-full py-[18px] px-[16px]
|
||||||
|
border border-[color:var(--theme--fg-border)] cursor-pointer
|
||||||
|
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
|
||||||
|
>
|
||||||
|
${$thumbnail}
|
||||||
|
<div class="flex flex-col max-w-[50%]">
|
||||||
|
<div class="flex items-center text-[14px] mb-[5px]">
|
||||||
|
<h3 class="my-0">${name}</h3>
|
||||||
|
${[`v${version}`, ...tags].map((tag) => {
|
||||||
|
return html`<span
|
||||||
|
class="text-([12px] [color:var(--theme--fg-secondary)])
|
||||||
|
ml-[8px] py-[2px] px-[6px] leading-tight tracking-wide
|
||||||
|
rounded-[3px] bg-[color:var(--theme--bg-hover)]"
|
||||||
|
>
|
||||||
|
${tag}
|
||||||
|
</span>`;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
class="text-[12px] leading-[16px] mb-[6px]
|
||||||
|
text-[color:var(--theme--fg-secondary)]"
|
||||||
|
innerHTML=${description}
|
||||||
|
></p>
|
||||||
|
<div class="flex gap-x-[8px] text-[12px] leading-[16px]">
|
||||||
|
${authors.map((author) => {
|
||||||
|
return html`<a href=${author.homepage} class="flex items-center">
|
||||||
|
<img src=${author.avatar} alt="" class="h-[12px] rounded-full" />
|
||||||
|
<span class="ml-[6px]">${author.name}</span>
|
||||||
|
</a>`;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex ml-auto">
|
||||||
|
${$options}
|
||||||
|
<div class="my-auto scale-[1.15]">
|
||||||
|
<${Toggle}
|
||||||
|
id="${id}-toggle"
|
||||||
|
checked=${enabled}
|
||||||
|
onchange="${(event) => _update(event.target.checked)}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>`;
|
||||||
|
}
|
||||||
|
|
||||||
function Option({ type, value, description, _update, ...props }) {
|
function Option({ type, value, description, _update, ...props }) {
|
||||||
const { html } = globalThis.__enhancerApi,
|
const { html } = globalThis.__enhancerApi,
|
||||||
camelToSentenceCase = (string) =>
|
camelToSentenceCase = (string) =>
|
||||||
@ -80,13 +166,13 @@ function Option({ type, value, description, _update, ...props }) {
|
|||||||
onchange = (event) => _update(event.target.value);
|
onchange = (event) => _update(event.target.value);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "heading":
|
case "heading":
|
||||||
return html`<h3
|
return html`<h4
|
||||||
class="notion-enhancer--menu-heading font-semibold
|
class="notion-enhancer--menu-heading font-semibold
|
||||||
mb-[16px] mt-[48px] first:mt-0 pb-[12px] text-[16px]
|
mb-[16px] mt-[48px] first:mt-0 pb-[12px] text-[16px]
|
||||||
border-b border-b-[color:var(--theme--fg-border)]"
|
border-b border-b-[color:var(--theme--fg-border)]"
|
||||||
>
|
>
|
||||||
${label}
|
${label}
|
||||||
</h3>`;
|
</h4>`;
|
||||||
case "text":
|
case "text":
|
||||||
$input = html`<${TextInput} ...${{ value, onchange }} />`;
|
$input = html`<${TextInput} ...${{ value, onchange }} />`;
|
||||||
break;
|
break;
|
||||||
@ -127,7 +213,7 @@ function Option({ type, value, description, _update, ...props }) {
|
|||||||
class="notion-enhancer--menu-option flex items-center justify-between
|
class="notion-enhancer--menu-option flex items-center justify-between
|
||||||
mb-[18px] ${type === "toggle" ? "cursor-pointer" : ""}"
|
mb-[18px] ${type === "toggle" ? "cursor-pointer" : ""}"
|
||||||
><div class="flex flex-col ${type === "text" ? "w-full" : "mr-[10%]"}">
|
><div class="flex flex-col ${type === "text" ? "w-full" : "mr-[10%]"}">
|
||||||
<h4 class="text-[14px] mb-[2px] mt-0">${label}</h4>
|
<h5 class="text-[14px] mb-[2px] mt-0">${label}</h5>
|
||||||
${type === "text" ? $input : ""}
|
${type === "text" ? $input : ""}
|
||||||
<p
|
<p
|
||||||
class="text-[12px] leading-[16px]
|
class="text-[12px] leading-[16px]
|
||||||
@ -397,8 +483,8 @@ function Toggle(props) {
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="w-[30px] h-[18px] transition duration-200
|
class="w-[30px] h-[18px] rounded-[44px] cursor-pointer
|
||||||
rounded-[44px] bg-[color:var(--theme--bg-hover)]"
|
transition duration-200 bg-[color:var(--theme--bg-hover)]"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="w-full h-full rounded-[44px] p-[2px]
|
class="w-full h-full rounded-[44px] p-[2px]
|
||||||
@ -418,6 +504,8 @@ export {
|
|||||||
SidebarSection,
|
SidebarSection,
|
||||||
SidebarButton,
|
SidebarButton,
|
||||||
View,
|
View,
|
||||||
|
List,
|
||||||
|
Mod,
|
||||||
Option,
|
Option,
|
||||||
TextInput,
|
TextInput,
|
||||||
NumberInput,
|
NumberInput,
|
||||||
|
@ -10,6 +10,8 @@ import {
|
|||||||
SidebarSection,
|
SidebarSection,
|
||||||
SidebarButton,
|
SidebarButton,
|
||||||
View,
|
View,
|
||||||
|
List,
|
||||||
|
Mod,
|
||||||
Option,
|
Option,
|
||||||
} from "./components.mjs";
|
} from "./components.mjs";
|
||||||
|
|
||||||
@ -17,27 +19,40 @@ const renderOptions = async (mod) => {
|
|||||||
const { html, platform, getProfile } = globalThis.__enhancerApi,
|
const { html, platform, getProfile } = globalThis.__enhancerApi,
|
||||||
{ optionDefaults, initDatabase } = globalThis.__enhancerApi,
|
{ optionDefaults, initDatabase } = globalThis.__enhancerApi,
|
||||||
profile = await getProfile();
|
profile = await getProfile();
|
||||||
const db = initDatabase([profile, mod.id], await optionDefaults(mod.id)),
|
const db = initDatabase([profile, mod.id], await optionDefaults(mod.id));
|
||||||
options = mod.options.reduce((options, opt, i) => {
|
let options = mod.options.reduce((options, opt, i) => {
|
||||||
if (!opt.key && (opt.type !== "heading" || !opt.label)) return options;
|
if (!opt.key && (opt.type !== "heading" || !opt.label)) return options;
|
||||||
if (opt.targets && !opt.targets.includes(platform)) return options;
|
if (opt.targets && !opt.targets.includes(platform)) return options;
|
||||||
const prevOpt = options[options.length - 1];
|
const prevOpt = options[options.length - 1];
|
||||||
// no consective headings
|
// no consective headings
|
||||||
if (opt.type === "heading" && prevOpt?.type === opt.type) {
|
if (opt.type === "heading" && prevOpt?.type === opt.type) {
|
||||||
options[options.length - 1] = opt;
|
options[options.length - 1] = opt;
|
||||||
} else options.push(opt);
|
} else options.push(opt);
|
||||||
return options;
|
return options;
|
||||||
}, []);
|
}, []);
|
||||||
// no empty/end headings e.g. if section is platform-specific
|
// no empty/end headings e.g. if section is platform-specific
|
||||||
if (options[options.length - 1]?.type === "heading") options.pop();
|
if (options[options.length - 1]?.type === "heading") options.pop();
|
||||||
return Promise.all(
|
options = options.map(async (opt) => {
|
||||||
options.map(async (opt) => {
|
if (opt.type === "heading") return html`<${Option} ...${opt} />`;
|
||||||
if (opt.type === "heading") return html`<${Option} ...${opt} />`;
|
const value = await db.get(opt.key),
|
||||||
const value = await db.get(opt.key),
|
_update = (value) => db.set(opt.key, value);
|
||||||
_update = (value) => db.set(opt.key, value);
|
return html`<${Option} ...${{ ...opt, value, _update }} />`;
|
||||||
return html`<${Option} ...${{ ...opt, value, _update }} />`;
|
});
|
||||||
})
|
return Promise.all(options);
|
||||||
);
|
};
|
||||||
|
|
||||||
|
const renderList = async (mods) => {
|
||||||
|
const { html, platform, getProfile } = globalThis.__enhancerApi,
|
||||||
|
{ isEnabled, initDatabase } = globalThis.__enhancerApi,
|
||||||
|
enabledMods = initDatabase([await getProfile(), "enabledMods"]);
|
||||||
|
mods = mods
|
||||||
|
.filter((mod) => !mod.platforms || mod.platforms.includes(platform))
|
||||||
|
.map(async (mod) => {
|
||||||
|
const enabled = await isEnabled(mod.id),
|
||||||
|
_update = (enabled) => enabledMods.set(mod.id, enabled);
|
||||||
|
return html`<${Mod} ...${{ ...mod, enabled, _update }} />`;
|
||||||
|
});
|
||||||
|
return html`<${List}>${await Promise.all(mods)}<//>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
let renderStarted;
|
let renderStarted;
|
||||||
@ -96,9 +111,13 @@ const render = async (iconStyle) => {
|
|||||||
$views = [
|
$views = [
|
||||||
html`<${View} id="welcome">welcome<//>`,
|
html`<${View} id="welcome">welcome<//>`,
|
||||||
html`<${View} id="core">${await renderOptions(await getCore())}<//>`,
|
html`<${View} id="core">${await renderOptions(await getCore())}<//>`,
|
||||||
html`<${View} id="themes">themes<//>`,
|
html`<${View} id="themes">${await renderList(await getThemes())}<//>`,
|
||||||
html`<${View} id="extensions">extensions<//>`,
|
html`<${View} id="extensions">
|
||||||
html`<${View} id="integrations">integrations<//>`,
|
${await renderList(await getExtensions())}
|
||||||
|
<//>`,
|
||||||
|
html`<${View} id="integrations">
|
||||||
|
${await renderList(await getIntegrations())}
|
||||||
|
<//>`,
|
||||||
];
|
];
|
||||||
document.body.append($sidebar, ...$views);
|
document.body.append($sidebar, ...$views);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* notion-enhancer
|
* notion-enhancer
|
||||||
* (c) 2022 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
* (https://notion-enhancer.github.io/) under the MIT license
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
["core"]
|
["core", "themes/classic-dark"]
|
||||||
|
BIN
src/themes/classic-dark/classic-dark.png
Normal file
BIN
src/themes/classic-dark/classic-dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 115 KiB |
60
src/themes/classic-dark/client.css
Normal file
60
src/themes/classic-dark/client.css
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* notion-enhancer
|
||||||
|
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
body.dark {
|
||||||
|
--theme--fg-primary: rgba(255, 255, 255, 0.9);
|
||||||
|
--theme--fg-secondary: rgba(255, 255, 255, 0.6);
|
||||||
|
--theme--fg-border: rgb(255, 255, 255, 0.07);
|
||||||
|
--theme--fg-gray: rgba(159, 164, 169, 1);
|
||||||
|
--theme--fg-brown: rgba(212, 150, 117, 1);
|
||||||
|
--theme--fg-orange: rgba(217, 133, 56, 1);
|
||||||
|
--theme--fg-yellow: rgba(201, 145, 38, 1);
|
||||||
|
--theme--fg-green: rgba(113, 178, 131, 1);
|
||||||
|
--theme--fg-blue: rgba(102, 170, 218, 1);
|
||||||
|
--theme--fg-purple: rgba(176, 152, 217, 1);
|
||||||
|
--theme--fg-pink: rgba(223, 132, 209, 1);
|
||||||
|
--theme--fg-red: rgba(234, 135, 140, 1);
|
||||||
|
|
||||||
|
--theme--bg-primary: rgb(47, 52, 55);
|
||||||
|
--theme--bg-secondary: rgb(55, 60, 63);
|
||||||
|
--theme--bg-hover: rgba(255, 255, 255, 0.1);
|
||||||
|
--theme--bg-light_gray: rgba(71, 76, 80, 0.7);
|
||||||
|
--theme--bg-gray: rgb(71, 76, 80);
|
||||||
|
--theme--bg-brown: rgb(92, 71, 61);
|
||||||
|
--theme--bg-orange: rgb(136, 84, 44);
|
||||||
|
--theme--bg-yellow: rgb(146, 118, 63);
|
||||||
|
--theme--bg-green: rgb(50, 82, 65);
|
||||||
|
--theme--bg-blue: rgb(42, 78, 107);
|
||||||
|
--theme--bg-purple: rgb(83, 68, 116);
|
||||||
|
--theme--bg-pink: rgb(106, 59, 99);
|
||||||
|
--theme--bg-red: rgb(122, 54, 59);
|
||||||
|
|
||||||
|
--theme--dim-light_gray: rgb(63, 68, 71);
|
||||||
|
--theme--dim-gray: rgb(60, 65, 68);
|
||||||
|
--theme--dim-brown: rgb(76, 61, 53);
|
||||||
|
--theme--dim-orange: rgb(85, 59, 41);
|
||||||
|
--theme--dim-yellow: rgb(79, 64, 41);
|
||||||
|
--theme--dim-green: rgb(46, 68, 58);
|
||||||
|
--theme--dim-blue: rgb(45, 66, 86);
|
||||||
|
--theme--dim-purple: rgb(69, 58, 91);
|
||||||
|
--theme--dim-pink: rgb(81, 56, 77);
|
||||||
|
--theme--dim-red: rgb(94, 52, 54);
|
||||||
|
|
||||||
|
--theme--accent-primary: rgb(46, 170, 220);
|
||||||
|
--theme--accent-primary_hover: rgb(6, 156, 205);
|
||||||
|
--theme--accent-primary_contrast: #fff;
|
||||||
|
--theme--accent-primary_transparent: rgb(46, 170, 220, 0.25);
|
||||||
|
--theme--accent-secondary: #eb5757;
|
||||||
|
--theme--accent-secondary_contrast: #fff;
|
||||||
|
--theme--accent-secondary_transparent: rgba(235, 87, 87, 0.1);
|
||||||
|
|
||||||
|
--theme--scrollbar-track: rgba(202, 204, 206, 0.04);
|
||||||
|
--theme--scrollbar-thumb: #474c50;
|
||||||
|
--theme--scrollbar-thumb_hover: rgba(202, 204, 206, 0.3);
|
||||||
|
|
||||||
|
--theme--code-block_fg: rgba(255, 255, 255, 0.9);
|
||||||
|
--theme--code-block_bg: rgb(63, 68, 71);
|
||||||
|
}
|
16
src/themes/classic-dark/mod.json
Normal file
16
src/themes/classic-dark/mod.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"id": "fe0f4498-df34-4dd8-8470-27b6fcec9acd",
|
||||||
|
"name": "Classic Dark",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "The original Notion dark theme from pre-2022.",
|
||||||
|
"thumbnail": "classic-dark.png",
|
||||||
|
"tags": ["dark"],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "dragonwocky",
|
||||||
|
"homepage": "https://dragonwocky.me/",
|
||||||
|
"avatar": "https://dragonwocky.me/avatar.jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"clientStyles": ["client.css"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user