Compare commits

...

27 Commits

Author SHA1 Message Date
JaniAnttonen
810d3b2524 Add a todo 2022-02-25 16:34:09 +02:00
JaniAnttonen
a3393ded1e Fix build 2022-02-25 15:22:09 +02:00
JaniAnttonen
17ede265b1 Remove debug logging 2022-02-25 14:39:06 +02:00
JaniAnttonen
629070edad Save split state 2022-02-25 13:50:56 +02:00
Vaclav Barta
cc83924c27 Merge pull request #98 from eqlabs/bugfix/typos
fix for #97
2022-02-15 08:49:38 +01:00
Vaclav Barta
e3e964f72a fix for #97 2022-02-11 13:54:52 +01:00
Joni Juup
bdb2c0cf8f Merge pull request #93 from eqlabs/bugfix/monaco-popups
Fix monaco popup issues
2022-02-09 15:10:28 +02:00
muzamil
3e8dbc9793 Merge pull request #91 from eqlabs/fixes
Clearing some issues
2022-02-09 18:32:47 +05:30
muzam
d735cd3833 Merge branch 'main' into fixes 2022-02-09 18:31:35 +05:30
Joni Juup
eddf228283 more specific rule for the box itself 2022-02-09 13:14:17 +02:00
Joni Juup
f9d617efdc more specific css rule for hr 2022-02-09 13:09:36 +02:00
Joni Juup
43796021da fix monaco editor issues with popups 2022-02-09 13:04:41 +02:00
Joni Juup
241c21782d Merge pull request #89 from eqlabs/enhancement/small-ui-fixes
new XRPL Hooks logo
clicking on the logo won't open the template dialog (retain gist path)
clicking gist under the Hook name opens the gist in a new window
documentation button open documentation in a new window
added meta tags & favicons
adjusted color schemes, removed pink (now matches design)
2022-02-09 12:42:18 +02:00
muzam
1a3f5d144c change accept template to starter 2022-02-09 14:26:19 +05:30
Joni Juup
66fb68d52e update share image 2022-02-08 18:58:59 +02:00
Joni Juup
aaeb32a576 update favicons 2022-02-08 18:29:12 +02:00
Joni Juup
78b5dcceb6 adjusting colors and themes 2022-02-08 18:07:37 +02:00
muzam
ce81c11c29 Update hooks installed info in card 2022-02-08 19:56:30 +05:30
muzam
3a98b95e3d fix firewall template link 2022-02-08 18:59:40 +05:30
muzam
8bc36655e2 disallow illegal characters in filename 2022-02-08 15:26:22 +05:30
muzam
b6ab536a60 Clear log on compile 2022-02-08 15:08:38 +05:30
Joni Juup
37a3d2b207 add share image 2022-02-07 17:10:00 +02:00
Joni Juup
cd0c5f8a0d meta tag changes 2022-02-07 16:54:31 +02:00
Vaclav Barta
8dde89fa9a Merge pull request #88 from eqlabs/feature/optimization
remove hardcoded file compilation options
2022-02-07 15:35:33 +01:00
Joni Juup
ca3d60cfb8 small ui fixes 2022-02-07 16:23:39 +02:00
Vaclav Barta
1a4d53cfbc removed hardcoded file compilation options 2022-02-07 15:03:47 +01:00
Joni Juup
94e126782b Merge pull request #65 from eqlabs/feature/panel-resize
Added panel resizing to all views.
2022-02-02 15:41:07 +02:00
37 changed files with 535 additions and 285 deletions

View File

@@ -36,13 +36,11 @@ const AccountDialog = ({
}) => {
const snap = useSnapshot(state);
const [showSecret, setShowSecret] = useState(false);
const activeAccount = snap.accounts.find(
(account) => account.address === activeAccountAddress
);
const activeAccount = snap.accounts.find(account => account.address === activeAccountAddress);
return (
<Dialog
open={Boolean(activeAccountAddress)}
onOpenChange={(open) => {
onOpenChange={open => {
setShowSecret(false);
!open && setActiveAccountAddress(null);
}}
@@ -137,7 +135,7 @@ const AccountDialog = ({
}}
ghost
size="xs"
onClick={() => setShowSecret((curr) => !curr)}
onClick={() => setShowSecret(curr => !curr)}
>
{showSecret ? "Hide" : "Show"}
</Button>
@@ -186,7 +184,7 @@ const AccountDialog = ({
<Button
size="sm"
ghost
css={{ color: "$green11 !important", mt: "$3" }}
css={{ color: "$grass11 !important", mt: "$3" }}
>
<ArrowSquareOut size="15px" />
</Button>
@@ -201,15 +199,7 @@ const AccountDialog = ({
fontFamily: "$monospace",
}}
>
{activeAccount && activeAccount?.hooks?.length > 0
? activeAccount?.hooks
.map((i) => {
return `${i?.substring(0, 6)}...${i?.substring(
i.length - 4
)}`;
})
.join(", ")
: ""}
{activeAccount && activeAccount.hooks.length}
</Text>
</Flex>
</Flex>
@@ -231,15 +221,13 @@ interface AccountProps {
showHookStats?: boolean;
}
const Accounts: FC<AccountProps> = (props) => {
const Accounts: FC<AccountProps> = props => {
const snap = useSnapshot(state);
const [activeAccountAddress, setActiveAccountAddress] = useState<
string | null
>(null);
const [activeAccountAddress, setActiveAccountAddress] = useState<string | null>(null);
useEffect(() => {
const fetchAccInfo = async () => {
if (snap.clientStatus === "online") {
const requests = snap.accounts.map((acc) =>
const requests = snap.accounts.map(acc =>
snap.client?.send({
id: acc.address,
command: "account_info",
@@ -251,15 +239,13 @@ const Accounts: FC<AccountProps> = (props) => {
const address = res?.account_data?.Account as string;
const balance = res?.account_data?.Balance as string;
const sequence = res?.account_data?.Sequence as number;
const accountToUpdate = state.accounts.find(
(acc) => acc.address === address
);
const accountToUpdate = state.accounts.find(acc => acc.address === address);
if (accountToUpdate) {
accountToUpdate.xrp = balance;
accountToUpdate.sequence = sequence;
}
});
const objectRequests = snap.accounts.map((acc) => {
const objectRequests = snap.accounts.map(acc => {
return snap.client?.send({
id: `${acc.address}-hooks`,
command: "account_objects",
@@ -269,9 +255,7 @@ const Accounts: FC<AccountProps> = (props) => {
const objectResponses = await Promise.all(objectRequests);
objectResponses.forEach((res: any) => {
const address = res?.account as string;
const accountToUpdate = state.accounts.find(
(acc) => acc.address === address
);
const accountToUpdate = state.accounts.find(acc => acc.address === address);
if (accountToUpdate) {
accountToUpdate.hooks = res.account_objects
.filter((ac: any) => ac?.LedgerEntryType === "Hook")
@@ -353,7 +337,7 @@ const Accounts: FC<AccountProps> = (props) => {
overflowY: "auto",
}}
>
{snap.accounts.map((account) => (
{snap.accounts.map(account => (
<Flex
column
key={account.address + account.name}
@@ -406,11 +390,10 @@ const Accounts: FC<AccountProps> = (props) => {
isLoading={account.isLoading}
disabled={
account.isLoading ||
!snap.files.filter((file) => file.compiledWatContent)
.length
!snap.files.filter(file => file.compiledWatContent).length
}
variant="secondary"
onClick={(e) => {
onClick={e => {
e.stopPropagation();
deployHook(account);
}}
@@ -421,7 +404,7 @@ const Accounts: FC<AccountProps> = (props) => {
</Flex>
{props.showHookStats && (
<Text muted small css={{ mt: "$2" }}>
X hooks installed
{account.hooks.length} hook{account.hooks.length === 1 ? "" : "s"} installed
</Text>
)}
</Flex>
@@ -453,7 +436,7 @@ const ImportAccountDialog = () => {
name="secret"
type="password"
value={value}
onChange={(e) => setValue(e.target.value)}
onChange={e => setValue(e.target.value)}
/>
</DialogDescription>

View File

@@ -91,26 +91,26 @@ export const StyledButton = styled("button", {
},
},
primary: {
backgroundColor: `$pink9`,
boxShadow: "inset 0 0 0 1px $colors$pink9",
backgroundColor: `$accent`,
boxShadow: "inset 0 0 0 1px $colors$purple9",
color: "$white",
"@hover": {
"&:hover": {
backgroundColor: "$pink10",
boxShadow: "inset 0 0 0 1px $colors$pink11",
backgroundColor: "$purple10",
boxShadow: "inset 0 0 0 1px $colors$purple11",
},
},
"&:active": {
backgroundColor: "$pink8",
boxShadow: "inset 0 0 0 1px $colors$pink8",
backgroundColor: "$purple8",
boxShadow: "inset 0 0 0 1px $colors$purple8",
},
"&:focus": {
boxShadow: "inset 0 0 0 2px $colors$pink12",
boxShadow: "inset 0 0 0 2px $colors$purple12",
},
'&[data-radix-popover-trigger][data-state="open"], &[data-radix-dropdown-menu-trigger][data-state="open"]':
{
backgroundColor: "$mauve4",
boxShadow: "inset 0 0 0 1px $colors$pink8",
boxShadow: "inset 0 0 0 1px $colors$purple8",
},
},
secondary: {

View File

@@ -34,7 +34,7 @@ const DeployEditor = () => {
display: "flex",
position: "relative",
flexDirection: "column",
backgroundColor: "$mauve3",
backgroundColor: "$mauve2",
width: "100%",
}}
>

View File

@@ -71,7 +71,7 @@ const itemStyles = {
},
"&:focus": {
backgroundColor: "$pink9",
backgroundColor: "$purple9",
color: "$white",
},
};
@@ -85,8 +85,8 @@ const StyledRadioItem = styled(DropdownMenuPrimitive.RadioItem, {
});
const StyledTriggerItem = styled(DropdownMenuPrimitive.TriggerItem, {
'&[data-state="open"]': {
backgroundColor: "$pink9",
color: "$pink9",
backgroundColor: "$purple9",
color: "$purple9",
},
...itemStyles,
});

View File

@@ -26,7 +26,12 @@ import NewWindow from "react-new-window";
import { signOut, useSession } from "next-auth/react";
import { useSnapshot } from "valtio";
import { createNewFile, syncToGist, updateEditorSettings, downloadAsZip } from "../state/actions";
import {
createNewFile,
syncToGist,
updateEditorSettings,
downloadAsZip,
} from "../state/actions";
import state from "../state";
import Box from "./Box";
import Button from "./Button";
@@ -57,7 +62,7 @@ import { styled } from "../stitches.config";
const DEFAULT_EXTENSION = ".c";
const ErrorText = styled(Text, {
color: "$red9",
color: "$crimson9",
mt: "$1",
display: "block",
});
@@ -85,9 +90,16 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
const validateFilename = useCallback(
(filename: string): { error: string | null } => {
// check if filename already exists
if (snap.files.find(file => file.name === filename)) {
return { error: "Filename already exists." };
}
// check for illegal characters
const ILLEGAL_REGEX = /[/]/gi;
if (filename.match(ILLEGAL_REGEX)) {
return { error: "Filename contains illegal characters" };
}
// More checks in future
return { error: null };
},
@@ -95,7 +107,9 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
);
const handleConfirm = useCallback(() => {
// add default extension in case omitted
let _filename = filename.includes(".") ? filename : filename + DEFAULT_EXTENSION;
let _filename = filename.includes(".")
? filename
: filename + DEFAULT_EXTENSION;
const chk = validateFilename(_filename);
if (chk.error) {
setNewfileError(`Error: ${chk.error}`);
@@ -139,7 +153,9 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
return (
<Button
size="sm"
outline={showWat ? snap.activeWat !== index : snap.active !== index}
outline={
showWat ? snap.activeWat !== index : snap.active !== index
}
onClick={() => (state.active = index)}
key={file.name + index}
css={{
@@ -174,7 +190,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
// If deleted file is behind active tab
// we keep the current state otherwise
// select previous file on the list
state.active = index > snap.active ? snap.active : snap.active - 1;
state.active =
index > snap.active ? snap.active : snap.active - 1;
}}
>
<X size="9px" weight="bold" />
@@ -184,10 +201,18 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
);
})}
{!showWat && (
<Dialog open={isNewfileDialogOpen} onOpenChange={setIsNewfileDialogOpen}>
<Dialog
open={isNewfileDialogOpen}
onOpenChange={setIsNewfileDialogOpen}
>
<DialogTrigger asChild>
<Button ghost size="sm" css={{ alignItems: "center", px: "$2", mr: "$3" }}>
<Plus size="16px" /> {snap.files.length === 0 && "Add new file"}
<Button
ghost
size="sm"
css={{ alignItems: "center", px: "$2", mr: "$3" }}
>
<Plus size="16px" />{" "}
{snap.files.length === 0 && "Add new file"}
</Button>
</DialogTrigger>
<DialogContent>
@@ -196,8 +221,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<label>Filename</label>
<Input
value={filename}
onChange={e => setFilename(e.target.value)}
onKeyPress={e => {
onChange={(e) => setFilename(e.target.value)}
onKeyPress={(e) => {
if (e.key === "Enter") {
handleConfirm();
}
@@ -216,10 +241,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<DialogClose asChild>
<Button outline>Cancel</Button>
</DialogClose>
<Button
variant="primary"
onClick={handleConfirm}
>
<Button variant="primary" onClick={handleConfirm}>
Create file
</Button>
</Flex>
@@ -237,11 +259,13 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<Flex
css={{
py: "$3",
backgroundColor: "$mauve3",
backgroundColor: "$mauve2",
zIndex: 1,
}}
>
<Container css={{ width: "unset", display: "flex", alignItems: "center" }}>
<Container
css={{ width: "unset", display: "flex", alignItems: "center" }}
>
{status === "authenticated" ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -274,10 +298,15 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem disabled onClick={() => signOut()}>
<User size="16px" /> {session?.user?.username} ({session?.user.name})
<User size="16px" /> {session?.user?.username} (
{session?.user.name})
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => window.open(`http://gist.github.com/${session?.user.username}`)}
onClick={() =>
window.open(
`http://gist.github.com/${session?.user.username}`
)
}
>
<ArrowSquareOut size="16px" />
Go to your Gist
@@ -291,7 +320,12 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</DropdownMenuContent>
</DropdownMenu>
) : (
<Button outline size="sm" css={{ mr: "$3" }} onClick={() => setPopUp(true)}>
<Button
outline
size="sm"
css={{ mr: "$3" }}
onClick={() => setPopUp(true)}
>
<GithubLogo size="16px" /> Login
</Button>
)}
@@ -330,7 +364,13 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
},
}}
>
<Button isLoading={snap.zipLoading} onClick={downloadAsZip} outline size="sm" css={{ alignItems: "center" }}>
<Button
isLoading={snap.zipLoading}
onClick={downloadAsZip}
outline
size="sm"
css={{ alignItems: "center" }}
>
<DownloadSimple size="16px" />
</Button>
<Button
@@ -338,7 +378,9 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
size="sm"
css={{ alignItems: "center" }}
onClick={() => {
navigator.clipboard.writeText(`${window.location.origin}/develop/${snap.gistId}`);
navigator.clipboard.writeText(
`${window.location.origin}/develop/${snap.gistId}`
);
toast.success("Copied share link to clipboard!");
}}
>
@@ -368,7 +410,10 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem disabled={snap.zipLoading} onClick={downloadAsZip}>
<DropdownMenuItem
disabled={snap.zipLoading}
onClick={downloadAsZip}
>
<DownloadSimple size="16px" /> Download as ZIP
</DropdownMenuItem>
<DropdownMenuItem
@@ -383,7 +428,9 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
Copy share link to clipboard
</DropdownMenuItem>
<DropdownMenuItem
disabled={session?.user.username !== snap.gistOwner || !snap.gistId}
disabled={
session?.user.username !== snap.gistOwner || !snap.gistId
}
onClick={() => {
syncToGist(session);
}}
@@ -409,15 +456,21 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</DropdownMenu>
</Stack>
{popup && !session ? <NewWindow center="parent" url="/sign-in" /> : null}
{popup && !session ? (
<NewWindow center="parent" url="/sign-in" />
) : null}
</Container>
</Flex>
<AlertDialog open={createNewAlertOpen} onOpenChange={value => setCreateNewAlertOpen(value)}>
<AlertDialog
open={createNewAlertOpen}
onOpenChange={(value) => setCreateNewAlertOpen(value)}
>
<AlertDialogContent>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogDescription>
This action will create new <strong>public</strong> Github Gist from your current saved
files. You can delete gist anytime from your GitHub Gists page.
This action will create new <strong>public</strong> Github Gist from
your current saved files. You can delete gist anytime from your
GitHub Gists page.
</AlertDialogDescription>
<Flex css={{ justifyContent: "flex-end", gap: "$3" }}>
<AlertDialogCancel asChild>
@@ -451,8 +504,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
type="number"
min="1"
value={editorSettings.tabSize}
onChange={e =>
setEditorSettings(curr => ({
onChange={(e) =>
setEditorSettings((curr) => ({
...curr,
tabSize: Number(e.target.value),
}))
@@ -462,12 +515,18 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<Flex css={{ marginTop: 25, justifyContent: "flex-end", gap: "$3" }}>
<DialogClose asChild>
<Button outline onClick={() => updateEditorSettings(editorSettings)}>
<Button
outline
onClick={() => updateEditorSettings(editorSettings)}
>
Cancel
</Button>
</DialogClose>
<DialogClose asChild>
<Button variant="primary" onClick={() => updateEditorSettings(editorSettings)}>
<Button
variant="primary"
onClick={() => updateEditorSettings(editorSettings)}
>
Save changes
</Button>
</DialogClose>

View File

@@ -29,7 +29,7 @@ loader.config({
const validateWritability = (editor: monaco.editor.IStandaloneCodeEditor) => {
const currPath = editor.getModel()?.uri.path;
if (apiHeaderFiles.find(h => currPath?.endsWith(h))) {
if (apiHeaderFiles.find((h) => currPath?.endsWith(h))) {
editor.updateOptions({ readOnly: true });
} else {
editor.updateOptions({ readOnly: false });
@@ -60,7 +60,7 @@ const HooksEditor = () => {
display: "flex",
position: "relative",
flexDirection: "column",
backgroundColor: "$mauve3",
backgroundColor: "$mauve2",
width: "100%",
}}
>
@@ -73,9 +73,9 @@ const HooksEditor = () => {
language={snap.files?.[snap.active]?.language}
path={`file:///work/c/${snap.files?.[snap.active]?.name}`}
defaultValue={snap.files?.[snap.active]?.content}
beforeMount={monaco => {
beforeMount={(monaco) => {
if (!snap.editorCtx) {
snap.files.forEach(file =>
snap.files.forEach((file) =>
monaco.editor.createModel(
file.content,
file.language,
@@ -100,7 +100,7 @@ const HooksEditor = () => {
// listen when the web socket is opened
listen({
webSocket: webSocket as WebSocket,
onConnection: connection => {
onConnection: (connection) => {
// create and start the language client
const languageClient = createLanguageClient(connection);
const disposable = languageClient.start();
@@ -139,10 +139,13 @@ const HooksEditor = () => {
enabled: true,
},
});
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
saveFile();
});
validateWritability(editor)
editor.addCommand(
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS,
() => {
saveFile();
}
);
validateWritability(editor);
}}
theme={theme === "dark" ? "dark" : "light"}
/>
@@ -160,7 +163,9 @@ const HooksEditor = () => {
<Box css={{ display: "inline-flex", pl: "35px" }}>
<ArrowBendLeftUp size={30} />
</Box>
<Box css={{ pl: "0px", pt: "15px", flex: 1, display: "inline-flex" }}>
<Box
css={{ pl: "0px", pt: "15px", flex: 1, display: "inline-flex" }}
>
<Text
css={{
fontSize: "14px",
@@ -168,7 +173,7 @@ const HooksEditor = () => {
fontFamily: "$monospace",
}}
>
Click the link above to create a your file
Click the link above to create your file
</Text>
</Box>
</Box>

View File

@@ -117,15 +117,17 @@ export const Input = styled("input", {
},
state: {
invalid: {
boxShadow: "inset 0 0 0 1px $colors$red7",
boxShadow: "inset 0 0 0 1px $colors$crimson7",
"&:focus": {
boxShadow: "inset 0px 0px 0px 1px $colors$red8, 0px 0px 0px 1px $colors$red8",
boxShadow:
"inset 0px 0px 0px 1px $colors$crimson8, 0px 0px 0px 1px $colors$crimson8",
},
},
valid: {
boxShadow: "inset 0 0 0 1px $colors$green7",
boxShadow: "inset 0 0 0 1px $colors$grass7",
"&:focus": {
boxShadow: "inset 0px 0px 0px 1px $colors$green8, 0px 0px 0px 1px $colors$green8",
boxShadow:
"inset 0px 0px 0px 1px $colors$grass8, 0px 0px 0px 1px $colors$grass8",
},
},
},

View File

@@ -11,13 +11,13 @@ const Text = styled("span", {
color: "$text",
},
warning: {
color: "$yellow11",
color: "$amber11",
},
error: {
color: "$red11",
color: "$crimson11",
},
success: {
color: "$green11",
color: "$grass11",
},
},
capitalize: {

View File

@@ -1,8 +1,8 @@
import { styled } from "../stitches.config";
const SVG = styled("svg", {
"& #path-one, & #path-two": {
fill: "$text",
"& #path": {
fill: "$accent",
},
});
function Logo({
@@ -14,21 +14,18 @@ function Logo({
}) {
return (
<SVG
width={width || "1em"}
height={height || "1em"}
viewBox="0 0 28 22"
width={width || "1.1em"}
height={height || "1.1em"}
viewBox="0 0 294 283"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
id="path-one"
d="M19.603 3.87h2.3l-4.786 4.747a4.466 4.466 0 01-6.276 0L6.054 3.871h2.3l3.636 3.605a2.828 2.828 0 003.975 0l3.638-3.605zM8.325 17.069h-2.3l4.816-4.776a4.466 4.466 0 016.276 0l4.816 4.776h-2.3l-3.665-3.635a2.828 2.828 0 00-3.975 0l-3.668 3.635z"
/>
<path
id="path-two"
fillRule="evenodd"
clipRule="evenodd"
d="M1.556 9.769h4.751v1.555H1.556v10.072H0V0h1.556v9.769zM26.444 9.769h-4.751v1.555h4.751v10.072H28V0h-1.556v9.769z"
id="path"
d="M265.827 235L172.416 141.589L265.005 49H226.822L147.732 128.089H53.5514L27.4824 155.089H147.732L227.643 235H265.827Z"
fill="#9D2DFF"
/>
</SVG>
);

View File

@@ -40,6 +40,7 @@ const Navigation = () => {
as="nav"
css={{
display: "flex",
backgroundColor: "$mauve1",
borderBottom: "1px solid $mauve6",
position: "relative",
zIndex: 2003,
@@ -61,7 +62,7 @@ const Navigation = () => {
pr: "$4",
}}
>
<Link href="/" passHref>
<Link href={gistId ? `/develop/${gistId}` : "/develop"} passHref>
<Box
as="a"
css={{
@@ -70,7 +71,7 @@ const Navigation = () => {
color: "$textColor",
}}
>
<Logo width="30px" height="30px" />
<Logo width="32px" height="32px" />
</Box>
</Link>
<Flex
@@ -91,10 +92,25 @@ const Navigation = () => {
css={{ fontSize: "$xs", color: "$mauve10", lineHeight: 1 }}
>
{snap.files.length > 0 ? "Gist: " : "Playground"}
<Text css={{ color: "$mauve12" }}>
{snap.files.length > 0 &&
`${snap.gistOwner || "-"}/${truncate(snap.gistId || "")}`}
</Text>
{snap.files.length > 0 && (
<Link
href={`https://gist.github.com/${snap.gistOwner || ""}/${
snap.gistId || ""
}`}
passHref
>
<Text
as="a"
target="_blank"
rel="noreferrer noopener"
css={{ color: "$mauve12" }}
>
{`${snap.gistOwner || "-"}/${truncate(
snap.gistId || ""
)}`}
</Text>
</Link>
)}
</Text>
</>
)}
@@ -138,10 +154,12 @@ const Navigation = () => {
flexDirection: "column",
p: "$7",
height: "100%",
backgroundColor: "$mauve2",
"@md": {
width: "30%",
maxWidth: "300px",
borderBottom: "0px",
borderRight: "1px solid $colors$mauve5",
borderRight: "1px solid $colors$mauve6",
},
}}
>
@@ -152,9 +170,11 @@ const Navigation = () => {
alignItems: "center",
gap: "$3",
fontSize: "$xl",
lineHeight: "$one",
fontWeight: "$bold",
}}
>
<Logo width="30px" height="30px" /> XRPL Hooks Editor
<Logo width="48px" height="48px" /> XRPL Hooks Builder
</DialogTitle>
<DialogDescription as="div">
<Text
@@ -176,9 +196,9 @@ const Navigation = () => {
display: "inline-flex",
alignItems: "center",
gap: "$3",
color: "$green9",
color: "$purple10",
"&:hover": {
color: "$green11 !important",
color: "$purple11",
},
"&:focus": {
outline: 0,
@@ -189,7 +209,7 @@ const Navigation = () => {
target="_blank"
href="https://github.com/XRPL-Labs/xrpld-hooks"
>
<ArrowUpRight size="15px" /> Developing Hooks
<ArrowUpRight size="15px" /> Hooks Github
</Text>
<Text
@@ -197,9 +217,9 @@ const Navigation = () => {
display: "inline-flex",
alignItems: "center",
gap: "$3",
color: "$green9",
color: "$purple10",
"&:hover": {
color: "$green11 !important",
color: "$purple11",
},
"&:focus": {
outline: 0,
@@ -217,9 +237,9 @@ const Navigation = () => {
display: "inline-flex",
alignItems: "center",
gap: "$3",
color: "$green9",
color: "$purple10",
"&:hover": {
color: "$green11 !important",
color: "$purple11",
},
"&:focus": {
outline: 0,
@@ -246,9 +266,7 @@ const Navigation = () => {
gap: "$3",
alignItems: "flex-start",
flexWrap: "wrap",
backgroundImage: `url('/pattern.svg'), url('/pattern-2.svg')`,
backgroundRepeat: "no-repeat",
backgroundPosition: "bottom left, top right",
backgroundColor: "$mauve1",
"@md": {
gridTemplateColumns: "1fr 1fr 1fr",
gridTemplateRows: "max-content",
@@ -261,28 +279,18 @@ const Navigation = () => {
>
<Heading>Starter</Heading>
<Text>
Just an empty starter with essential imports
Just a basic starter with essential imports
</Text>
</PanelBox>
<PanelBox
as="a"
href={`/develop/${templateFileIds.starter}`}
href={`/develop/${templateFileIds.firewall}`}
>
<Heading>Firewall</Heading>
<Text>
This Hook essentially checks a blacklist of accounts
</Text>
</PanelBox>
<PanelBox
as="a"
href={`/develop/${templateFileIds.accept}`}
>
<Heading>Accept</Heading>
<Text>
This hook just accepts any transaction coming through
it
</Text>
</PanelBox>
<PanelBox
as="a"
href={`/develop/${templateFileIds.notary}`}
@@ -304,7 +312,7 @@ const Navigation = () => {
href={`/develop/${templateFileIds.peggy}`}
>
<Heading>Peggy</Heading>
<Text>An oracle based stabe coin hook</Text>
<Text>An oracle based stable coin hook</Text>
</PanelBox>
</Flex>
</Flex>
@@ -391,9 +399,13 @@ const Navigation = () => {
</Button>
</Link>
</ButtonGroup>
<Button outline disabled>
<BookOpen size="15px" />
</Button>
<Link href="https://xrpl-hooks.readme.io/" passHref>
<a target="_blank" rel="noreferrer noopener">
<Button outline>
<BookOpen size="15px" />
</Button>
</a>
</Link>
</Stack>
</Flex>
</Container>

View File

@@ -5,8 +5,8 @@ import Text from "./Text";
const PanelBox = styled("div", {
display: "flex",
flexDirection: "column",
border: "1px solid $colors$mauve5",
backgroundColor: "$mauve1",
border: "1px solid $colors$mauve6",
backgroundColor: "$mauve2",
padding: "$3",
borderRadius: "$sm",
fontWeight: "lighter",

View File

@@ -1,4 +1,10 @@
import React, { useEffect, useState, Fragment, isValidElement, useCallback } from "react";
import React, {
useEffect,
useState,
Fragment,
isValidElement,
useCallback,
} from "react";
import type { ReactNode, ReactElement } from "react";
import { Box, Button, Flex, Input, Stack, Text } from ".";
import {
@@ -13,7 +19,7 @@ import { Plus, X } from "phosphor-react";
import { styled } from "../stitches.config";
const ErrorText = styled(Text, {
color: "$red9",
color: "$crimson9",
mt: "$1",
display: "block",
});
@@ -50,7 +56,7 @@ export const Tabs = ({
forceDefaultExtension,
}: Props) => {
const [active, setActive] = useState(activeIndex || 0);
const tabs: TabProps[] = children.map(elem => elem.props);
const tabs: TabProps[] = children.map((elem) => elem.props);
const [isNewtabDialogOpen, setIsNewtabDialogOpen] = useState(false);
const [tabname, setTabname] = useState("");
@@ -62,7 +68,7 @@ export const Tabs = ({
useEffect(() => {
if (activeHeader) {
const idx = tabs.findIndex(tab => tab.header === activeHeader);
const idx = tabs.findIndex((tab) => tab.header === activeHeader);
setActive(idx);
}
}, [activeHeader, tabs]);
@@ -74,7 +80,7 @@ export const Tabs = ({
const validateTabname = useCallback(
(tabname: string): { error: string | null } => {
if (tabs.find(tab => tab.header === tabname)) {
if (tabs.find((tab) => tab.header === tabname)) {
return { error: "Name already exists." };
}
return { error: null };
@@ -170,9 +176,16 @@ export const Tabs = ({
</Button>
))}
{onCreateNewTab && (
<Dialog open={isNewtabDialogOpen} onOpenChange={setIsNewtabDialogOpen}>
<Dialog
open={isNewtabDialogOpen}
onOpenChange={setIsNewtabDialogOpen}
>
<DialogTrigger asChild>
<Button ghost size="sm" css={{ alignItems: "center", px: "$2", mr: "$3" }}>
<Button
ghost
size="sm"
css={{ alignItems: "center", px: "$2", mr: "$3" }}
>
<Plus size="16px" /> {tabs.length === 0 && "Add new tab"}
</Button>
</DialogTrigger>
@@ -182,8 +195,8 @@ export const Tabs = ({
<label>Tabname</label>
<Input
value={tabname}
onChange={e => setTabname(e.target.value)}
onKeyPress={e => {
onChange={(e) => setTabname(e.target.value)}
onKeyPress={(e) => {
if (e.key === "Enter") {
handleCreateTab();
}
@@ -235,7 +248,9 @@ export const Tabs = ({
);
})
) : (
<Fragment key={tabs[active].header || active}>{tabs[active].children}</Fragment>
<Fragment key={tabs[active].header || active}>
{tabs[active].children}
</Fragment>
)}
</>
);

View File

@@ -18,6 +18,9 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const slug = router.query?.slug;
const gistId = (Array.isArray(slug) && slug[0]) ?? null;
const origin = "https://xrpl-hooks-ide.vercel.app"; // TODO: Change when site is deployed
const shareImg = "/share-image.png";
useEffect(() => {
if (gistId && router.isReady) {
fetchFiles(gistId);
@@ -31,7 +34,73 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
return (
<>
<Head>
<title>XRPL Hooks Playground</title>
<meta charSet="utf-8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<meta name="format-detection" content="telephone=no" />
<meta property="og:url" content={`${origin}${router.asPath}`} />
<title>XRPL Hooks Editor</title>
<meta property="og:title" content="XRPL Hooks Editor" />
<meta name="twitter:title" content="XRPL Hooks Editor" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@xrpllabs" />
<meta
name="description"
content="Playground for buildings Hooks, that add smart contract functionality to the XRP Ledger."
/>
<meta
property="og:description"
content="Playground for buildings Hooks, that add smart contract functionality to the XRP Ledger."
/>
<meta
name="twitter:description"
content="Playground for buildings Hooks, that add smart contract functionality to the XRP Ledger.."
/>
<meta property="og:image" content={`${origin}${shareImg}`} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:image" content={`${origin}${shareImg}`} />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#161618" />
<meta name="application-name" content="XRPL Hooks Editor" />
<meta name="msapplication-TileColor" content="#c10ad0" />
<meta
name="theme-color"
content="#161618"
media="(prefers-color-scheme: dark)"
/>
<meta
name="theme-color"
content="#FDFCFD"
media="(prefers-color-scheme: light)"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin=""
/>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital@0;1&family=Work+Sans:wght@400;600;700&display=swap"
rel="stylesheet"
/>
</Head>
<IdProvider>
<SessionProvider session={session}>

View File

@@ -16,21 +16,10 @@ class MyDocument extends Document {
}
render() {
globalStyles();
return (
<Html>
<Head>
<meta name="description" content="Playground for XRPL Hooks" />
<link rel="icon" href="/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin=""
/>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital@0;1&family=Work+Sans:wght@400;600;700&display=swap"
rel="stylesheet"
/>
<style
id="stitches"
dangerouslySetInnerHTML={{ __html: getCssText() }}

View File

@@ -1,8 +1,9 @@
import React from "react";
import dynamic from "next/dynamic";
import React from "react";
import Split from "react-split";
import { useSnapshot } from "valtio";
import state from "../../state";
import Split from "react-split";
import { getSplit, saveSplit } from "../../state/actions/persistSplits";
const DeployEditor = dynamic(() => import("../../components/DeployEditor"), {
ssr: false,
@@ -17,21 +18,22 @@ const LogBox = dynamic(() => import("../../components/LogBox"), {
});
const Deploy = () => {
const snap = useSnapshot(state);
const { deployLogs } = useSnapshot(state);
return (
<Split
direction="vertical"
gutterSize={4}
gutterAlign="center"
sizes={[40, 60]}
sizes={getSplit("deployVertical") || [40, 60]}
style={{ height: "calc(100vh - 60px)" }}
onDragEnd={(e) => saveSplit("deployVertical", e)}
>
<main style={{ display: "flex", flex: 1, position: "relative" }}>
<DeployEditor />
</main>
<Split
direction="horizontal"
sizes={[50, 50]}
sizes={getSplit("deployHorizontal") || [50, 50]}
minSize={[320, 160]}
gutterSize={4}
gutterAlign="center"
@@ -41,6 +43,7 @@ const Deploy = () => {
width: "100%",
height: "100%",
}}
onDragEnd={(e) => saveSplit("deployHorizontal", e)}
>
<div style={{ alignItems: "stretch", display: "flex" }}>
<Accounts />
@@ -48,7 +51,7 @@ const Deploy = () => {
<div>
<LogBox
title="Deploy Log"
logs={snap.deployLogs}
logs={deployLogs}
clearLog={() => (state.deployLogs = [])}
/>
</div>

View File

@@ -1,14 +1,15 @@
import dynamic from "next/dynamic";
import { useSnapshot } from "valtio";
import Hotkeys from "react-hot-keys";
import { Play } from "phosphor-react";
import Split from "react-split";
import type { NextPage } from "next";
import { compileCode } from "../../state/actions";
import state from "../../state";
import Button from "../../components/Button";
import dynamic from "next/dynamic";
import { Play } from "phosphor-react";
import Hotkeys from "react-hot-keys";
import Split from "react-split";
import { useSnapshot } from "valtio";
import Box from "../../components/Box";
import Button from "../../components/Button";
import state from "../../state";
import { compileCode } from "../../state/actions";
import { getSplit, saveSplit } from "../../state/actions/persistSplits";
const HooksEditor = dynamic(() => import("../../components/HooksEditor"), {
ssr: false,
@@ -24,11 +25,12 @@ const Home: NextPage = () => {
return (
<Split
direction="vertical"
sizes={[70, 30]}
sizes={getSplit("developVertical") || [70, 30]}
minSize={[100, 100]}
gutterAlign="center"
gutterSize={4}
style={{ height: "calc(100vh - 60px)" }}
onDragEnd={(e) => saveSplit("developVertical", e)}
>
<main style={{ display: "flex", flex: 1, position: "relative" }}>
<HooksEditor />

View File

@@ -1,22 +1,17 @@
import {
Container,
Flex,
Box,
Tabs,
Tab,
Input,
Select,
Text,
Button,
} from "../../components";
import { Play } from "phosphor-react";
import dynamic from "next/dynamic";
import { useSnapshot } from "valtio";
import { Play } from "phosphor-react";
import { FC, useCallback, useEffect, useState } from "react";
import Split from "react-split";
import { useSnapshot } from "valtio";
import {
Box, Button, Container,
Flex, Input,
Select, Tab, Tabs, Text
} from "../../components";
import transactionsData from "../../content/transactions.json";
import state from "../../state";
import { sendTransaction } from "../../state/actions";
import { useCallback, useEffect, useState, FC } from "react";
import transactionsData from "../../content/transactions.json";
import { getSplit, saveSplit } from "../../state/actions/persistSplits";
const DebugStream = dynamic(() => import("../../components/DebugStream"), {
ssr: false,
@@ -349,16 +344,17 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
};
const Test = () => {
const snap = useSnapshot(state);
const { transactionLogs } = useSnapshot(state);
const [tabHeaders, setTabHeaders] = useState<string[]>(["test1.json"]);
return (
<Container css={{ px: 0 }}>
<Split
direction="vertical"
sizes={[50, 50]}
sizes={getSplit("testVertical") || [50, 50]}
gutterSize={4}
gutterAlign="center"
style={{ height: "calc(100vh - 60px)" }}
onDragEnd={(e) => saveSplit("testVertical", e)}
>
<Flex
row
@@ -370,7 +366,7 @@ const Test = () => {
>
<Split
direction="horizontal"
sizes={[50, 50]}
sizes={getSplit("testHorizontal") || [50, 50]}
minSize={[180, 320]}
gutterSize={4}
gutterAlign="center"
@@ -380,6 +376,7 @@ const Test = () => {
width: "100%",
height: "100%",
}}
onDragEnd={(e) => saveSplit("testHorizontal", e)}
>
<Box css={{ width: "55%", px: "$2" }}>
<Tabs
@@ -428,7 +425,7 @@ const Test = () => {
>
<LogBox
title="Development Log"
logs={snap.transactionLogs}
logs={transactionLogs}
clearLog={() => (state.transactionLogs = [])}
/>
</Box>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

9
public/browserconfig.xml Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#161618</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/mstile-150x150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="588.000000pt" height="588.000000pt" viewBox="0 0 588.000000 588.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,588.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3843 4097 c-381 -380 -737 -736 -791 -790 l-99 -99 -940 1 -940 0
-204 -211 c-112 -116 -228 -235 -257 -265 -29 -30 -51 -57 -48 -60 2 -3 542
-5 1198 -5 l1193 0 799 -799 799 -799 380 0 c209 0 378 2 376 5 -2 2 -422 423
-933 934 l-928 929 921 920 c507 507 921 923 921 927 0 3 -170 5 -377 5 l-378
0 -692 -693z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 837 B

BIN
public/share-image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

19
public/site.webmanifest Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "Hooks Builder",
"short_name": "Hooks Builder",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#161618",
"background_color": "#161618",
"display": "standalone"
}

View File

@@ -1,4 +0,0 @@
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -25,6 +25,7 @@ export const compileCode = async (activeId: number) => {
}
// Set loading state to true
state.compiling = true;
state.logs = []
try {
const res = await fetch(process.env.NEXT_PUBLIC_COMPILE_API_ENDPOINT, {
method: "POST",
@@ -38,7 +39,6 @@ export const compileCode = async (activeId: number) => {
{
type: "c",
name: state.files[activeId].name,
options: "-O0",
src: state.files[activeId].content,
},
],
@@ -87,4 +87,4 @@ export const compileCode = async (activeId: number) => {
});
state.compiling = false;
}
};
};

View File

@@ -0,0 +1,15 @@
import { snapshot } from "valtio"
import state from ".."
export type SplitSize = number[]
export const saveSplit = (splitId: string, event: SplitSize) => {
state.splits[splitId] = event
}
export const getSplit = (splitId: string): SplitSize | null => {
const { splits } = snapshot(state)
const split = splits[splitId]
return split ? split : null
}

View File

@@ -1,6 +1,5 @@
export const templateFileIds = {
'starter': '1d14e51e2e02dc0a508cb0733767a914', // TODO currently same as accept
'accept': '1d14e51e2e02dc0a508cb0733767a914',
'firewall': 'bcd6d0c0fcbe52545ddb802481ff9d26',
'notary': 'a789c75f591eeab7932fd702ed8cf9ea',
'carbon': '43925143fa19735d8c6505c34d3a6a47',

View File

@@ -1,7 +1,8 @@
import { proxy, ref, subscribe } from "valtio";
import { devtools } from 'valtio/utils'
import type monaco from "monaco-editor";
import { proxy, ref, subscribe } from "valtio";
import { devtools } from 'valtio/utils';
import { XrplClient } from "xrpl-client";
import { SplitSize } from "./actions/persistSplits";
export interface IFile {
name: string;
@@ -55,6 +56,9 @@ export interface IState {
editorSettings: {
tabSize: number;
};
splits: {
[id: string]: SplitSize
};
client: XrplClient | null;
clientStatus: "offline" | "online";
mainModalOpen: boolean;
@@ -83,6 +87,7 @@ let initialState: IState = {
editorSettings: {
tabSize: 2,
},
splits: {},
client: null,
clientStatus: "offline" as "offline",
mainModalOpen: false,
@@ -91,6 +96,9 @@ let initialState: IState = {
let localStorageAccounts: string | null = null;
let initialAccounts: IAccount[] = [];
// TODO: What exactly should we store in localStorage? editorSettings, splits, accounts?
// Check if there's a persited accounts in localStorage
if (typeof window !== "undefined") {
try {
@@ -139,4 +147,4 @@ if (typeof window !== "undefined") {
}
});
}
export default state
export default state

View File

@@ -1,29 +1,25 @@
// stitches.config.ts
import type Stitches from '@stitches/react';
import { createStitches } from '@stitches/react';
import type Stitches from "@stitches/react";
import { createStitches } from "@stitches/react";
import {
gray,
blue,
red,
green,
plum,
crimson,
grass,
slate,
mauve,
pink,
yellow,
amber,
purple,
grayDark,
blueDark,
redDark,
greenDark,
plumDark,
crimsonDark,
grassDark,
slateDark,
mauveDark,
pinkDark,
yellowDark,
amberDark,
purpleDark,
} from '@radix-ui/colors';
} from "@radix-ui/colors";
export const {
styled,
@@ -39,26 +35,25 @@ export const {
colors: {
...gray,
...blue,
...red,
...green,
...plum,
...crimson,
...grass,
...slate,
...mauve,
...pink,
...yellow,
...amber,
...purple,
accent: "#9D2DFF",
background: "$gray1",
backgroundAlt: "$gray4",
text: "$gray12",
primary: "$plum",
white: "white",
black: "black",
'deep': 'rgb(244, 244, 244)'
deep: "rgb(244, 244, 244)",
},
fonts: {
body: 'Work Sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
heading: 'Work Sans, sans-serif',
monospace: 'Roboto Mono, monospace',
heading: "Work Sans, sans-serif",
monospace: "Roboto Mono, monospace",
},
fontSizes: {
xs: "0.6875rem",
@@ -74,7 +69,7 @@ export const {
"7xl": "4.5rem",
"8xl": "6rem",
"9xl": "8rem",
default: '$md'
default: "$md",
},
space: {
px: "1px",
@@ -110,15 +105,15 @@ export const {
72: "18rem",
80: "20rem",
96: "24rem",
"widePlus": '2048px',
"wide": '1536px',
"layoutPlus": '1260px',
"layout": '1024px',
"copyUltra": '980px',
"copyPlus": '768px',
"copy": '680px',
"narrowPlus": '600px',
"narrow": '512px',
widePlus: "2048px",
wide: "1536px",
layoutPlus: "1260px",
layout: "1024px",
copyUltra: "980px",
copyPlus: "768px",
copy: "680px",
narrowPlus: "600px",
narrow: "512px",
xs: "20rem",
sm: "24rem",
md: "28rem",
@@ -218,62 +213,112 @@ export const {
lg: "(min-width: 62em)",
xl: "(min-width: 80em)",
"2xl": "(min-width: 96em)",
hover: '(any-hover: hover)',
dark: '(prefers-color-scheme: dark)',
light: '(prefers-color-scheme: light)',
hover: "(any-hover: hover)",
dark: "(prefers-color-scheme: dark)",
light: "(prefers-color-scheme: light)",
},
utils: {
// Abbreviated margin properties
m: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'margin'>) => ({
m: (
value: Stitches.ScaleValue<"space"> | Stitches.PropertyValue<"margin">
) => ({
margin: value,
}),
mt: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'marginTop'>) => ({
mt: (
value: Stitches.ScaleValue<"space"> | Stitches.PropertyValue<"marginTop">
) => ({
marginTop: value,
}),
mr: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'marginRight'>) => ({
mr: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"marginRight">
) => ({
marginRight: value,
}),
mb: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'marginBottom'>) => ({
mb: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"marginBottom">
) => ({
marginBottom: value,
}),
ml: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'marginLeft'>) => ({
ml: (
value: Stitches.ScaleValue<"space"> | Stitches.PropertyValue<"marginLeft">
) => ({
marginLeft: value,
}),
mx: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'marginLeft' | 'marginRight'>) => ({
mx: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"marginLeft" | "marginRight">
) => ({
marginLeft: value,
marginRight: value,
}),
my: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'marginTop' | 'marginBottom'>) => ({
my: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"marginTop" | "marginBottom">
) => ({
marginTop: value,
marginBottom: value,
}),
// Abbreviated margin properties
p: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'padding'>) => ({
p: (
value: Stitches.ScaleValue<"space"> | Stitches.PropertyValue<"padding">
) => ({
padding: value,
}),
pt: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'paddingTop'>) => ({
pt: (
value: Stitches.ScaleValue<"space"> | Stitches.PropertyValue<"paddingTop">
) => ({
paddingTop: value,
}),
pr: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'paddingRight'>) => ({
pr: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"paddingRight">
) => ({
paddingRight: value,
}),
pb: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'paddingBottom'>) => ({
pb: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"paddingBottom">
) => ({
paddingBottom: value,
}),
pl: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'paddingLeft'>) => ({
pl: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"paddingLeft">
) => ({
paddingLeft: value,
}),
px: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'paddingLeft' | 'paddingRight'>) => ({
px: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"paddingLeft" | "paddingRight">
) => ({
paddingLeft: value,
paddingRight: value,
}),
py: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'paddingTop' | 'paddingBottom'>) => ({
py: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"paddingTop" | "paddingBottom">
) => ({
paddingTop: value,
paddingBottom: value,
}),
// A property for applying width/height together
size: (value: Stitches.ScaleValue<'space'> | Stitches.PropertyValue<'width' | 'height'>) => ({
size: (
value:
| Stitches.ScaleValue<"space">
| Stitches.PropertyValue<"width" | "height">
) => ({
width: value,
height: value,
}),
@@ -282,47 +327,44 @@ export const {
// }),
// A property to apply linear gradient
linearGradient: (value: Stitches.ScaleValue<'space'>) => ({
linearGradient: (value: Stitches.ScaleValue<"space">) => ({
backgroundImage: `linear-gradient(${value})`,
}),
// An abbreviated property for border-radius
br: (value: Stitches.ScaleValue<'space'>) => ({
br: (value: Stitches.ScaleValue<"space">) => ({
borderRadius: value,
}),
},
});
export const darkTheme = createTheme('dark', {
export const darkTheme = createTheme("dark", {
colors: {
...grayDark,
...blueDark,
...redDark,
...greenDark,
...plumDark,
...crimsonDark,
...grassDark,
...slateDark,
...mauveDark,
...pinkDark,
...yellowDark,
...amberDark,
...purpleDark,
deep: 'rgb(10, 10, 10)',
deep: "rgb(10, 10, 10)",
// backgroundA: transparentize(0.1, grayDark.gray1),
},
});
export const globalStyles = globalCss({
// body: { backgroundColor: '$background', color: '$text', fontFamily: 'Helvetica' },
'html, body': {
backgroundColor: '$gray1',
color: '$gray12',
fontFamily: '$body',
fontSize: '$md',
'-webkit-font-smoothing': 'antialiased',
'-moz-osx-font-smoothing': 'grayscale'
"html, body": {
backgroundColor: "$mauve2",
color: "$mauve12",
fontFamily: "$body",
fontSize: "$md",
"-webkit-font-smoothing": "antialiased",
"-moz-osx-font-smoothing": "grayscale",
},
a: {
color: "inherit",
textDecoration: "none",
},
'a': {
color: 'inherit',
textDecoration: 'none'
}
});

View File

@@ -39,3 +39,14 @@ html.light .gutter-vertical:hover {
html.light .gutter-horizontal:hover {
background-color: rgba(0, 0, 0, 0.25);
}
/* Adjust Monaco tooltip stylings */
.markdown-hover h3 {
margin: 0;
}
.monaco-editor .monaco-hover hr {
margin: 8px 0;
}
.monaco-editor .monaco-hover {
z-index: 9999;
}

View File

@@ -3,7 +3,7 @@
"inherit": true,
"rules": [
{
"background": "1a1d1e",
"background": "161618",
"token": ""
},
{
@@ -182,10 +182,10 @@
],
"colors": {
"editor.foreground": "#D0D0FF",
"editor.background": "#232326",
"editor.background": "#1C1C1F",
"editor.selectionBackground": "#ffffff30",
"editor.lineHighlightBackground": "#ffffff20",
"editorCursor.foreground": "#7070FF",
"editorWhitespace.foreground": "#BFBFBF"
}
}
}

View File

@@ -3,7 +3,7 @@
"inherit": true,
"rules": [
{
"background": "FFFFFF",
"background": "F4F2F4",
"token": ""
},
{
@@ -89,10 +89,10 @@
],
"colors": {
"editor.foreground": "#000000",
"editor.background": "#f4f2f4",
"editor.background": "#F9F8F9",
"editor.selectionBackground": "#B5D5FF",
"editor.lineHighlightBackground": "#00000012",
"editorCursor.foreground": "#000000",
"editorWhitespace.foreground": "#BFBFBF"
}
}
}