basic theme switcher

This commit is contained in:
Felix Roos 2023-02-08 18:54:34 +01:00
parent cdd40df9d3
commit 30b149053c
7 changed files with 250 additions and 6 deletions

View File

@ -79,9 +79,17 @@ const highlightField = StateField.define({
provide: (f) => EditorView.decorations.from(f),
});
const extensions = [javascript(), strudelTheme, highlightField, flashField];
const extensions = [javascript(), highlightField, flashField];
export default function CodeMirror({ value, onChange, onViewChanged, onSelectionChange, options, editorDidMount }) {
export default function CodeMirror({
value,
onChange,
onViewChanged,
onSelectionChange,
theme,
options,
editorDidMount,
}) {
const handleOnChange = useCallback(
(value) => {
onChange?.(value);
@ -106,6 +114,7 @@ export default function CodeMirror({ value, onChange, onViewChanged, onSelection
<>
<_CodeMirror
value={value}
theme={theme || strudelTheme}
onChange={handleOnChange}
onCreateEditor={handleOnCreateEditor}
onUpdate={handleOnUpdate}

View File

@ -1,14 +1,18 @@
.cm-editor {
background-color: transparent !important;
/* background-color: transparent !important; */
height: 100%;
z-index: 11;
font-size: 18px;
}
.cm-theme {
width: 100%;
}
.cm-theme-light {
width: 100%;
}
.cm-line > * {
background: #00000095;
/* background: #00000095; */
}

177
pnpm-lock.yaml generated
View File

@ -373,6 +373,7 @@ importers:
'@types/node': ^18.0.0
'@types/react': ^18.0.26
'@types/react-dom': ^18.0.9
'@uiw/codemirror-themes-all': ^4.19.7
'@vite-pwa/astro': ^0.0.1
astro: ^1.7.2
canvas: ^2.11.0
@ -415,6 +416,7 @@ importers:
'@types/node': 18.11.18
'@types/react': 18.0.27
'@types/react-dom': 18.0.10
'@uiw/codemirror-themes-all': 4.19.7
astro: 1.9.2_@types+node@18.11.18
canvas: 2.11.0
fraction.js: 4.2.0
@ -3994,6 +3996,181 @@ packages:
'@codemirror/view': 6.7.3
dev: false
/@uiw/codemirror-theme-abcdef/4.19.7:
resolution: {integrity: sha512-mkZrkcq0AfRXNfUQ9sZWe6is8VKfbFWvtbFLGtMqTctdzUbZS/SJj4+W5D1fHMdRBegWn3T5u3fDshtJq/Ky5Q==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-androidstudio/4.19.7:
resolution: {integrity: sha512-emZ9xWH/kOF3TZcCghQWBz5XUG2sM0/okVkXKIbt28uMp5EgPiSKxCR8tUNOXU2WvyFhkgfoNFl5kH+YfjCaNA==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-atomone/4.19.7:
resolution: {integrity: sha512-YBljhvQz2VynKt0bk6jOdPRblK/JtIRst6JDCfXg0TZGkxsNng9uJgYeIT7uNRDvXPtmg47hSqpjL7X0XeSFKg==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-aura/4.19.7:
resolution: {integrity: sha512-n1P3nD0f3RucFeqWZ4tGpKTz/G352XNN7JCCx0pTTSrcC6gXVwrTazAGjjmq60R5za2lufEP3u/PYGgz8joVlg==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-bbedit/4.19.7:
resolution: {integrity: sha512-WjrkNhwHNU+KiwJLbrdTin9YVq5UmveLuH3VFtswLxw8hlFjjEziKgpErD4C8PsC125o6Dlcc7p1nbqVSmQjog==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-bespin/4.19.7:
resolution: {integrity: sha512-ta0o7eX0G3OmDKbQJci51+YM1XFEAR5+21pbcjAQMgD85ZRV23A+8iW+simHNRiRA31cv09pi+tdfXQGcx4drg==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-darcula/4.19.7:
resolution: {integrity: sha512-BNRoEOjTHfolU+VfwT2MZehVaokG3bJuq1we2PcHXSKZtGUT2fHmDNZQ3BSiLUDfC/1f6/Aqf63T8u7mAWB2zw==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-dracula/4.19.7:
resolution: {integrity: sha512-QnVjtq31vqjVcq5GItbfXuaB7c9DAwSvqiTtFLxLXqPO37lwwyYmrMdd5AbFsGlVv3Bxq4zvJ3LbyVlF6mexcA==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-duotone/4.19.7:
resolution: {integrity: sha512-SncdJtjQVBAReEtOPAYJoxitZqxHCbmkJCyZqOj81VB8HI8sdC9pOvdOVviT22/1nzosspmRYoPSHNbq0Jzx6Q==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-eclipse/4.19.7:
resolution: {integrity: sha512-msy5pkECeslpb9J8RT+Oj1XIV7GfOMIl400BG/A2beMXktdBTvomtsjBvn2i124pxevafK0iiuXDm8Rpk9x/9w==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-github/4.19.7:
resolution: {integrity: sha512-yeBKOS31bJWvxHWv/hO8CC5Hz657poyuCRX533B+7c2W3B5TX48i49GC9k91yX/BfCsTVqneONk4ZgRWGJkDww==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-gruvbox-dark/4.19.7:
resolution: {integrity: sha512-Qc1eTPv5KFJ96HIv4tyGFKZ4cWJeEQfwQ6PCHPCMEjEhQEXrT2jkveEUWL/JiUADrF3B32eB3k8f6D0kfZiDyw==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-material/4.19.7:
resolution: {integrity: sha512-uJmausR247K31mM3mjHAAFDQJSB+PB9Wux+aXksGU8QMVSCm7QGBUD6oKrtdQ0+KusdtpO3x+XprlNXhAXDcIw==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-noctis-lilac/4.19.7:
resolution: {integrity: sha512-7j7jA+s0skPKp7BRPI8AmWjgounCgf+1lYDnGjezPsZhM60v9GN9JQRZgI0zNub4kaRz9efXI65E5yN0chjR5w==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-nord/4.19.7:
resolution: {integrity: sha512-nAz4mBHMURyZ/o0b1W1VN9Qp5SvS8frOVEbJyDoCg6MFQ3NYOE8QNPzWIl7525Z8D+bpSHZz9leGuopT2vmXzA==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-okaidia/4.19.7:
resolution: {integrity: sha512-a2NONl4hGW9toluBfhr530BolSRoFGAhqFZMSq4RT/GeeKACE3hI7+uDeJID9B3D9Xh0d9C0VEksvGgEDuVD2g==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-solarized/4.19.7:
resolution: {integrity: sha512-do+SQtXzEVokfFcfIRr6MLceVfE3cHiTFaWQ0npWi5rzc/0i+BNe3J4ewGjUyU2Bofi/LYhAuTTiVoaKNdc5gQ==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-sublime/4.19.7:
resolution: {integrity: sha512-TakRTzdbiLJTfM1htEKVPcHFpnHzUYOFexE5UQQD9BLPfTABTAWLSjb+DeCfbP+m0gsTyzvHd8gH4t+WDIK4gQ==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-tokyo-night-day/4.19.7:
resolution: {integrity: sha512-0oyfyoNNfaKOW2TkJFHMUyI/kyoI6DXYd+Drkp4vHGd8zaLZWm/yyi05b0Nk/RKXnOfzrmLY0uU0FL4471rM1w==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-tokyo-night-storm/4.19.7:
resolution: {integrity: sha512-ObXQDcfECWd9EeawRXqkQQUxdwFF6RdqusEmRl5SJYorcGZA/6zsmxpIjtmXRKwBj0vv+pMk/RKoEmedglMMjw==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-tokyo-night/4.19.7:
resolution: {integrity: sha512-D/oLEsamQ7goFYnP46kyrt60vc2Tx8nC9FWyHqJvD3DL8+ugUsQvCL2oIadCadfMm7pQrFj1ILfokb8uC9W5eg==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-vscode/4.19.7:
resolution: {integrity: sha512-LaT9kSr7U6JTKxTYN0XkKZva5dtM63ltp7ae3JQsinL4ePoI1xNgn0Z4XapCK0VK1VyYbFKEWz3RN8s+pX+N1Q==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-theme-xcode/4.19.7:
resolution: {integrity: sha512-Le3qV3kJe2QgHjfxHHkEvpXF+XSQVUAdDPY2xnyDzijBooxd61ukFqgEPDPHVPT1Aqh+VHglafQRNOxChnlwdQ==}
dependencies:
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-themes-all/4.19.7:
resolution: {integrity: sha512-JCVwjZF9+omz+RaNEJXd0estiD7VliKZe1XvaPG3dy0MqQMJLzoUPxaagetPJlaCskrz1piXYL4V0Qp0J6ni8Q==}
dependencies:
'@uiw/codemirror-theme-abcdef': 4.19.7
'@uiw/codemirror-theme-androidstudio': 4.19.7
'@uiw/codemirror-theme-atomone': 4.19.7
'@uiw/codemirror-theme-aura': 4.19.7
'@uiw/codemirror-theme-bbedit': 4.19.7
'@uiw/codemirror-theme-bespin': 4.19.7
'@uiw/codemirror-theme-darcula': 4.19.7
'@uiw/codemirror-theme-dracula': 4.19.7
'@uiw/codemirror-theme-duotone': 4.19.7
'@uiw/codemirror-theme-eclipse': 4.19.7
'@uiw/codemirror-theme-github': 4.19.7
'@uiw/codemirror-theme-gruvbox-dark': 4.19.7
'@uiw/codemirror-theme-material': 4.19.7
'@uiw/codemirror-theme-noctis-lilac': 4.19.7
'@uiw/codemirror-theme-nord': 4.19.7
'@uiw/codemirror-theme-okaidia': 4.19.7
'@uiw/codemirror-theme-solarized': 4.19.7
'@uiw/codemirror-theme-sublime': 4.19.7
'@uiw/codemirror-theme-tokyo-night': 4.19.7
'@uiw/codemirror-theme-tokyo-night-day': 4.19.7
'@uiw/codemirror-theme-tokyo-night-storm': 4.19.7
'@uiw/codemirror-theme-vscode': 4.19.7
'@uiw/codemirror-theme-xcode': 4.19.7
'@uiw/codemirror-themes': 4.19.7
dev: false
/@uiw/codemirror-themes/4.19.7:
resolution: {integrity: sha512-M/42RkPI60ItlssmNuEoZO2MQvlY6fRmdX7XRUAhKjxczZoaq8xS6HIvv1whGf2zGsTrwdVTPCm6ls0l17dvPA==}
dependencies:
'@codemirror/language': 6.4.0
'@codemirror/state': 6.2.0
'@codemirror/view': 6.7.3
dev: false
/@uiw/codemirror-themes/4.19.7_a4vbhepr4qhxm5cldqd4jpyase:
resolution: {integrity: sha512-M/42RkPI60ItlssmNuEoZO2MQvlY6fRmdX7XRUAhKjxczZoaq8xS6HIvv1whGf2zGsTrwdVTPCm6ls0l17dvPA==}
peerDependencies:

View File

@ -38,6 +38,7 @@
"@types/node": "^18.0.0",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@uiw/codemirror-themes-all": "^4.19.7",
"astro": "^1.7.2",
"canvas": "^2.11.0",
"fraction.js": "^4.2.0",

View File

@ -5,11 +5,12 @@ import { nanoid } from 'nanoid';
import React, { useContext, useCallback, useLayoutEffect, useRef, useState } from 'react';
import { useEvent, loadedSamples, ReplContext } from './Repl';
import { Reference } from './Reference';
import * as themes from './themes.mjs';
export function Footer({ context }) {
// const [activeFooter, setActiveFooter] = useState('console');
// const { activeFooter, setActiveFooter, isZen } = useContext?.(ReplContext);
const { activeFooter, setActiveFooter, isZen } = context;
const { activeFooter, setActiveFooter, isZen, setTheme } = context;
const footerContent = useRef();
const [log, setLog] = useState([]);
@ -69,11 +70,12 @@ export function Footer({ context }) {
return (
<footer className="bg-footer z-[20]">
<div className="flex justify-between px-2">
<div className={cx('flex select-none', activeFooter && 'pb-2')}>
<div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}>
<FooterTab name="intro" label="welcome" />
<FooterTab name="samples" />
<FooterTab name="console" />
<FooterTab name="reference" />
<FooterTab name="settings" />
</div>
{activeFooter !== '' && (
<button onClick={() => setActiveFooter('')} className="text-white" aria-label="Close Panel">
@ -164,6 +166,21 @@ export function Footer({ context }) {
))}
</div>
)}
{activeFooter === 'settings' && (
<div>
{Object.entries(themes).map(([k, t]) => (
<li key={k}>
<a
onClick={() => {
setTheme(t);
}}
>
{k}
</a>
</li>
))}
</div>
)}
{activeFooter === 'reference' && <Reference />}
</div>
)}

View File

@ -22,6 +22,7 @@ import { Header } from './Header';
import { prebake } from './prebake.mjs';
import * as tunes from './tunes.mjs';
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
import strudelTheme from '@strudel.cycles/react/src/themes/strudel-theme';
initAudioOnFirstClick();
@ -109,6 +110,7 @@ export const ReplContext = createContext(null);
export function Repl({ embedded = false }) {
const isEmbedded = embedded || window.location !== window.parent.location;
const [view, setView] = useState(); // codemirror view
const [theme, setTheme] = useState(strudelTheme);
const [lastShared, setLastShared] = useState();
const [activeFooter, setActiveFooter] = useState('');
const [isZen, setIsZen] = useState(false);
@ -255,6 +257,8 @@ export function Repl({ embedded = false }) {
handleShare,
isZen,
setIsZen,
theme,
setTheme,
};
return (
// bg-gradient-to-t from-blue-900 to-slate-900
@ -269,6 +273,7 @@ export function Repl({ embedded = false }) {
<Header context={context} />
<section className="grow flex text-gray-100 relative overflow-auto cursor-text pb-0" id="code">
<CodeMirror
theme={theme}
value={code}
onChange={handleChangeCode}
onViewChanged={setView}

View File

@ -0,0 +1,31 @@
export {
abcdef,
androidstudio,
atomone,
aura,
bespin,
darcula,
dracula,
duotoneDark,
eclipse,
githubDark,
gruvboxDark,
materialDark,
nord,
okaidia,
solarizedDark,
sublime,
tokyoNight,
tokyoNightStorm,
vscodeDark,
xcodeDark,
bbedit,
duotoneLight,
githubLight,
gruvboxLight,
materialLight,
noctisLilac,
solarizedLight,
tokyoNightDay,
xcodeLight,
} from '@uiw/codemirror-themes-all';