add basic code editor for playground
This commit is contained in:
parent
2842926f4f
commit
48a450c2fb
|
@ -2,75 +2,77 @@ import { defineConfig } from 'astro/config';
|
||||||
import starlight from '@astrojs/starlight';
|
import starlight from '@astrojs/starlight';
|
||||||
import starlightLinksValidator from "starlight-links-validator";
|
import starlightLinksValidator from "starlight-links-validator";
|
||||||
import shikiConfig from './src/utils/shiki';
|
import shikiConfig from './src/utils/shiki';
|
||||||
|
import react from "@astrojs/react";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [
|
integrations: [react(), starlight({
|
||||||
starlight({
|
|
||||||
title: 'ShulkerScript',
|
title: 'ShulkerScript',
|
||||||
logo: {
|
logo: {
|
||||||
src: './src/assets/logo.webp',
|
src: './src/assets/logo.webp',
|
||||||
alt: 'ShulkerScript Logo',
|
alt: 'ShulkerScript Logo'
|
||||||
},
|
},
|
||||||
favicon: '/favicon.ico',
|
favicon: '/favicon.ico',
|
||||||
description: 'A simple and powerful scripting language for Minecraft datapacks.',
|
description: 'A simple and powerful scripting language for Minecraft datapacks.',
|
||||||
social: {
|
social: {
|
||||||
github: 'https://github.com/moritz-hoelting/shulkerscript-cli',
|
github: 'https://github.com/moritz-hoelting/shulkerscript-cli'
|
||||||
|
},
|
||||||
|
tableOfContents: {
|
||||||
|
minHeadingLevel: 1,
|
||||||
|
maxHeadingLevel: 3
|
||||||
},
|
},
|
||||||
tableOfContents: { minHeadingLevel: 1, maxHeadingLevel: 3 },
|
|
||||||
defaultLocale: 'root',
|
defaultLocale: 'root',
|
||||||
locales: {
|
locales: {
|
||||||
root: {
|
root: {
|
||||||
label: 'English',
|
label: 'English',
|
||||||
lang: 'en',
|
lang: 'en'
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
label: 'Deutsch',
|
label: 'Deutsch',
|
||||||
lang: 'de',
|
lang: 'de'
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
editLink: {
|
editLink: {
|
||||||
baseUrl: 'https://github.com/moritz-hoelting/shulkerscript-webpage/edit/main',
|
baseUrl: 'https://github.com/moritz-hoelting/shulkerscript-webpage/edit/main'
|
||||||
},
|
},
|
||||||
customCss: ['./src/styles/style.css'],
|
customCss: ['./src/styles/style.css'],
|
||||||
plugins: [starlightLinksValidator({
|
plugins: [starlightLinksValidator({
|
||||||
errorOnFallbackPages: false,
|
errorOnFallbackPages: false
|
||||||
})],
|
})],
|
||||||
expressiveCode: {
|
expressiveCode: {
|
||||||
shiki: shikiConfig,
|
shiki: shikiConfig
|
||||||
},
|
},
|
||||||
sidebar: [
|
components: {
|
||||||
{
|
PageTitle: './src/components/override/PageTitle.astro',
|
||||||
|
ContentPanel: './src/components/override/ContentPanel.astro',
|
||||||
|
},
|
||||||
|
sidebar: [{
|
||||||
label: 'Guides',
|
label: 'Guides',
|
||||||
autogenerate: {
|
autogenerate: {
|
||||||
directory: 'guides',
|
directory: 'guides'
|
||||||
},
|
},
|
||||||
translations: {
|
translations: {
|
||||||
de: 'Anleitungen',
|
de: 'Anleitungen'
|
||||||
}
|
}
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
label: 'Roadmap',
|
label: 'Roadmap',
|
||||||
link: '/roadmap',
|
link: '/roadmap',
|
||||||
translations: {
|
translations: {
|
||||||
de: 'Zukunftspläne',
|
de: 'Zukunftspläne'
|
||||||
},
|
}
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
label: 'Reference',
|
label: 'Reference',
|
||||||
autogenerate: {
|
autogenerate: {
|
||||||
directory: 'reference',
|
directory: 'reference'
|
||||||
},
|
},
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
translations: {
|
translations: {
|
||||||
de: 'Referenz',
|
de: 'Referenz'
|
||||||
},
|
},
|
||||||
badge: {
|
badge: {
|
||||||
text: 'WIP',
|
text: 'WIP',
|
||||||
variant: 'caution',
|
variant: 'caution'
|
||||||
}
|
}
|
||||||
}
|
}]
|
||||||
]
|
})]
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
});
|
13
package.json
13
package.json
|
@ -11,10 +11,23 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.5.10",
|
"@astrojs/check": "^0.5.10",
|
||||||
|
"@astrojs/react": "^3.6.0",
|
||||||
"@astrojs/starlight": "^0.24.2",
|
"@astrojs/starlight": "^0.24.2",
|
||||||
|
"@emotion/react": "^11.11.4",
|
||||||
|
"@emotion/styled": "^11.11.5",
|
||||||
|
"@monaco-editor/react": "^4.6.0",
|
||||||
|
"@mui/icons-material": "^5.15.20",
|
||||||
|
"@mui/material": "^5.15.20",
|
||||||
|
"@types/react": "^18.3.3",
|
||||||
|
"@types/react-dom": "^18.3.0",
|
||||||
"astro": "^4.10.2",
|
"astro": "^4.10.2",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
"sharp": "^0.32.6",
|
"sharp": "^0.32.6",
|
||||||
"starlight-links-validator": "^0.7.1",
|
"starlight-links-validator": "^0.7.1",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.4.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"sass": "^1.77.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
728
pnpm-lock.yaml
728
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
namespace "my-shulkerscript-pack";
|
||||||
|
|
||||||
|
#[tick]
|
||||||
|
fn main() {
|
||||||
|
// Change this
|
||||||
|
/say Hello World!
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Editor, { useMonaco, type Monaco } from "@monaco-editor/react";
|
||||||
|
import FileView from "./playground/FileView";
|
||||||
|
|
||||||
|
import "@styles/playground.scss";
|
||||||
|
|
||||||
|
import mainFileContent from "@assets/playground/main.shu?raw";
|
||||||
|
import Header from "./playground/Header";
|
||||||
|
|
||||||
|
export type File = {
|
||||||
|
language?: string;
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
export type Directory = {
|
||||||
|
dirs?: { [key: string]: Directory };
|
||||||
|
files?: { [key: string]: File };
|
||||||
|
};
|
||||||
|
export type SetState<T> = React.Dispatch<React.SetStateAction<T>>;
|
||||||
|
|
||||||
|
export default function Playground() {
|
||||||
|
const rootDir: Directory = {
|
||||||
|
dirs: {
|
||||||
|
src: {
|
||||||
|
files: {
|
||||||
|
"main.shu": {
|
||||||
|
content: mainFileContent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
"pack.toml": {
|
||||||
|
content: "pack.toml content",
|
||||||
|
language: "toml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [fileName, setFileName] = useState("src/main.shu");
|
||||||
|
const file = getFile(rootDir, fileName)!;
|
||||||
|
|
||||||
|
const monaco = useMonaco();
|
||||||
|
useEffect(() => {
|
||||||
|
if (monaco) {
|
||||||
|
loadFiles(monaco, rootDir);
|
||||||
|
}
|
||||||
|
}, [monaco]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<main
|
||||||
|
className="playground not-content"
|
||||||
|
style={{
|
||||||
|
maxWidth: "95vw",
|
||||||
|
marginInline: "auto",
|
||||||
|
marginTop: "0.5cm",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Header />
|
||||||
|
<FileView
|
||||||
|
className="file-view"
|
||||||
|
root={rootDir}
|
||||||
|
fileName={fileName}
|
||||||
|
setSelectedFileName={setFileName}
|
||||||
|
/>
|
||||||
|
<div className="editor">
|
||||||
|
<Editor
|
||||||
|
height="60vh"
|
||||||
|
theme="vs-dark"
|
||||||
|
path={fileName}
|
||||||
|
defaultLanguage={file.language}
|
||||||
|
defaultValue={file.content}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFile(root: Directory, path: string): File | null {
|
||||||
|
if (path.includes("/")) {
|
||||||
|
let dir = root;
|
||||||
|
const split = path.split("/");
|
||||||
|
let last = split.pop()!;
|
||||||
|
|
||||||
|
for (const dirName of split) {
|
||||||
|
if (dir.dirs) {
|
||||||
|
dir = dir.dirs[dirName];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir.files?.[last] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.files?.[path] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadFiles(monaco: Monaco, dir: Directory, prefix = "") {
|
||||||
|
for (const [name, d] of Object.entries(dir.dirs ?? {})) {
|
||||||
|
loadFiles(monaco, d, prefix + name + "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [name, file] of Object.entries(dir.files ?? {})) {
|
||||||
|
loadFile(monaco, file, prefix + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadFile(monaco: Monaco, file: File, name: string) {
|
||||||
|
const uri = monaco.Uri.parse(name);
|
||||||
|
if (!monaco.editor.getModel(uri)) {
|
||||||
|
monaco.editor.createModel(file.content, file.language, uri);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
import type { Props } from "@astrojs/starlight/props";
|
||||||
|
import Default from "@astrojs/starlight/components/ContentPanel.astro";
|
||||||
|
|
||||||
|
const isPlayground = Astro.props.slug === 'playground';
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
{isPlayground ? <slot /> : <Default {...Astro.props}><slot /></Default>}
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
import type { Props } from "@astrojs/starlight/props";
|
||||||
|
import Default from "@astrojs/starlight/components/PageTitle.astro";
|
||||||
|
|
||||||
|
const isPlayground = Astro.props.slug === 'playground';
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
{isPlayground ? <></> : <Default {...Astro.props}><slot /></Default>}
|
|
@ -0,0 +1,125 @@
|
||||||
|
import type { Directory, SetState } from "@components/Playground";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
export default function FileView({
|
||||||
|
root,
|
||||||
|
fileName,
|
||||||
|
setSelectedFileName,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
root: Directory;
|
||||||
|
fileName: string;
|
||||||
|
setSelectedFileName: SetState<string>;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={className}>
|
||||||
|
{Object.entries(root.dirs ?? {}).map(([name, dir]) => {
|
||||||
|
return (
|
||||||
|
<DirElement
|
||||||
|
key={name}
|
||||||
|
name={name}
|
||||||
|
dir={dir}
|
||||||
|
fileName={fileName.slice(name.length + 1)}
|
||||||
|
setSelectedFileName={setSelectedFileName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{Object.entries(root.files ?? {}).map(([name, _]) => {
|
||||||
|
return (
|
||||||
|
<span key={name}>
|
||||||
|
<FileElement
|
||||||
|
name={name}
|
||||||
|
disabled={fileName == name}
|
||||||
|
onClick={() => setSelectedFileName(name)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FileElement({
|
||||||
|
name,
|
||||||
|
disabled,
|
||||||
|
onClick,
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
disabled: boolean;
|
||||||
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<button disabled={disabled} onClick={onClick}>
|
||||||
|
{name}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DirElement({
|
||||||
|
name,
|
||||||
|
dir: currentDir,
|
||||||
|
collapsed: pCollapsed,
|
||||||
|
fileName,
|
||||||
|
setSelectedFileName,
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
dir: Directory;
|
||||||
|
collapsed?: boolean;
|
||||||
|
fileName: string;
|
||||||
|
setSelectedFileName: SetState<string>;
|
||||||
|
}) {
|
||||||
|
const [collapsed, setCollapsed] = useState(pCollapsed ?? false);
|
||||||
|
|
||||||
|
const modSetSelectedFileName: SetState<string> = (selected) => {
|
||||||
|
setSelectedFileName(name + "/" + selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={name}>
|
||||||
|
<button
|
||||||
|
style={{ display: "block" }}
|
||||||
|
onClick={() => setCollapsed(!collapsed)}
|
||||||
|
>
|
||||||
|
{name}/
|
||||||
|
</button>
|
||||||
|
<div style={{ marginLeft: ".25cm" }}>
|
||||||
|
{collapsed ? null : (
|
||||||
|
<div>
|
||||||
|
{Object.entries(currentDir.dirs ?? {}).map(
|
||||||
|
([dirname, dir]) => {
|
||||||
|
return (
|
||||||
|
<DirElement
|
||||||
|
key={name}
|
||||||
|
name={name}
|
||||||
|
dir={dir}
|
||||||
|
fileName={fileName.slice(
|
||||||
|
name.length + 1
|
||||||
|
)}
|
||||||
|
setSelectedFileName={
|
||||||
|
modSetSelectedFileName
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
{Object.entries(currentDir.files ?? {}).map(
|
||||||
|
([currentName, _]) => {
|
||||||
|
return (
|
||||||
|
<FileElement
|
||||||
|
key={name}
|
||||||
|
name={name}
|
||||||
|
disabled={fileName == currentName}
|
||||||
|
onClick={() =>
|
||||||
|
modSetSelectedFileName(currentName)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import SplitButton from "./SplitButton";
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
const clickBuild = () => {
|
||||||
|
console.log("build");
|
||||||
|
}
|
||||||
|
const clickZip = () => {
|
||||||
|
console.log("zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: "0.5cm",
|
||||||
|
}}>
|
||||||
|
<h1 id="_top">Playground</h1>
|
||||||
|
<SplitButton onClick={clickBuild} options={[["Download zip", clickZip]]}>Build</SplitButton>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import ButtonGroup from "@mui/material/ButtonGroup";
|
||||||
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
||||||
|
import ClickAwayListener from "@mui/material/ClickAwayListener";
|
||||||
|
import Grow from "@mui/material/Grow";
|
||||||
|
import Paper from "@mui/material/Paper";
|
||||||
|
import Popper from "@mui/material/Popper";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import MenuList from "@mui/material/MenuList";
|
||||||
|
import { ThemeProvider } from "@mui/material";
|
||||||
|
|
||||||
|
import { customTheme } from "@utils/material-ui-theme";
|
||||||
|
|
||||||
|
export default function SplitButton({
|
||||||
|
options,
|
||||||
|
children,
|
||||||
|
onClick,
|
||||||
|
}: {
|
||||||
|
options: [string, React.MouseEventHandler<HTMLLIElement>][];
|
||||||
|
children: React.ReactNode;
|
||||||
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
}) {
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const anchorRef = React.useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleMenuItemClick = (
|
||||||
|
event: React.MouseEvent<HTMLLIElement, MouseEvent>,
|
||||||
|
index: number
|
||||||
|
) => {
|
||||||
|
options[index][1](event);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToggle = () => {
|
||||||
|
setOpen((prevOpen) => !prevOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = (event: Event) => {
|
||||||
|
if (
|
||||||
|
anchorRef.current &&
|
||||||
|
anchorRef.current.contains(event.target as HTMLElement)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={customTheme}>
|
||||||
|
<ButtonGroup
|
||||||
|
variant="contained"
|
||||||
|
ref={anchorRef}
|
||||||
|
aria-label="Button group with a nested menu"
|
||||||
|
>
|
||||||
|
<Button onClick={onClick}>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
aria-controls={open ? "split-button-menu" : undefined}
|
||||||
|
aria-expanded={open ? "true" : undefined}
|
||||||
|
aria-label="select merge strategy"
|
||||||
|
aria-haspopup="menu"
|
||||||
|
onClick={handleToggle}
|
||||||
|
>
|
||||||
|
<ArrowDropDownIcon />
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
<Popper
|
||||||
|
sx={{
|
||||||
|
zIndex: 1,
|
||||||
|
}}
|
||||||
|
open={open}
|
||||||
|
anchorEl={anchorRef.current}
|
||||||
|
role={undefined}
|
||||||
|
transition
|
||||||
|
disablePortal
|
||||||
|
>
|
||||||
|
{({ TransitionProps, placement }) => (
|
||||||
|
<Grow
|
||||||
|
{...TransitionProps}
|
||||||
|
style={{
|
||||||
|
transformOrigin:
|
||||||
|
placement === "bottom"
|
||||||
|
? "center top"
|
||||||
|
: "center bottom",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Paper>
|
||||||
|
<ClickAwayListener onClickAway={handleClose}>
|
||||||
|
<MenuList id="split-button-menu" autoFocusItem>
|
||||||
|
{options.map((option, index) => (
|
||||||
|
<MenuItem
|
||||||
|
key={option[0]}
|
||||||
|
onClick={(event) =>
|
||||||
|
handleMenuItemClick(
|
||||||
|
event,
|
||||||
|
index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{option[0]}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</MenuList>
|
||||||
|
</ClickAwayListener>
|
||||||
|
</Paper>
|
||||||
|
</Grow>
|
||||||
|
)}
|
||||||
|
</Popper>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
import PlaygroundComponent from '@components/Playground';
|
||||||
|
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<StarlightPage frontmatter={{ title: 'Playground', template: "splash" }}>
|
||||||
|
<PlaygroundComponent client:only="react" />
|
||||||
|
</StarlightPage>
|
|
@ -0,0 +1,19 @@
|
||||||
|
.playground {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 4fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"header header"
|
||||||
|
"files editor";
|
||||||
|
|
||||||
|
> header {
|
||||||
|
grid-area: header;
|
||||||
|
}
|
||||||
|
> .file-view {
|
||||||
|
grid-area: files;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
> .editor {
|
||||||
|
grid-area: editor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { createTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
|
export const customTheme = createTheme({
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
light: '#a700c3',
|
||||||
|
main: '#a400c0',
|
||||||
|
dark: '#a400c0',
|
||||||
|
contrastText: '#fff',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
light: '#ff7961',
|
||||||
|
main: '#f44336',
|
||||||
|
dark: '#ba000d',
|
||||||
|
contrastText: '#000',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,3 +1,12 @@
|
||||||
{
|
{
|
||||||
"extends": "astro/tsconfigs/strict"
|
"extends": "astro/tsconfigs/strict",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@*": ["src/*"]
|
||||||
|
},
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"jsxImportSource": "react"
|
||||||
|
},
|
||||||
|
"exclude": ["dist", "node_modules"]
|
||||||
}
|
}
|
Loading…
Reference in New Issue