By: Mayne
Micro Block Description
import React, { useState, useEffect } from "react";
import Editor from "@monaco-editor/react";
import { useDebounceValue } from 'usehooks-ts';
import { Button } from '@/components/ui/button';
export async function getServerSideProps(context) {
const url = context.request.url;
const nodeId = new URL(url).pathname.split('/')[1];
const data = await context.currentSpace.extNode.getText(nodeId);
const node = await context.currentSpace.tree.get(nodeId);
return {
props: {
data,
nodeId,
nodeName: node.name
}
};
}
const defaultThemeCss = `:root {
--background: 0 0% 100%;
--foreground: 224 71.4% 4.1%;
--muted: 220 14.3% 95.9%;
--muted-foreground: 220 8.9% 46.1%;
--popover: 0 0% 100%;
--popover-foreground: 224 71.4% 4.1%;
--border: 220 13% 91%;
--input: 220 13% 91%;
--card: 0 0% 100%;
--card-foreground: 224 71.4% 4.1%;
--primary: 220.9 39.3% 11%;
--primary-foreground: 210 20% 98%;
--secondary: 220 14.3% 95.9%;
--secondary-foreground: 220.9 39.3% 11%;
--accent: 220 14.3% 95.9%;
--accent-foreground: 220.9 39.3% 11%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 20% 98%;
--ring: 224 71.4% 4.1%;
--radius: 0.5rem;
--token-comment-color: #6c757d;
--token-punctuation-color: #999;
--token-property-color: #905;
--token-selector-color: #690;
--token-operator-color: #9a6e3a;
--token-attr-color: #07a;
--token-variable-color: #e90;
--token-function-color: #dd4a68;
/* monaco editor */
--custom-editor-background: hsl(var(--background));
/* --rhm */
--rhm-rect: #ebedf0;
--rhm-text-color: #24292e;
--rhm-rect-hover-stroke: rgba(0, 0, 0, 0.14);
--rhm-rect-active: #196127;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--sidebar: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 224 71.4% 4.1%;
--foreground: 210 20% 98%;
--muted: 215 27.9% 16.9%;
--muted-foreground: 217.9 10.6% 64.9%;
--accent: 215 27.9% 16.9%;
--accent-foreground: 210 20% 98%;
--popover: 224 71.4% 4.1%;
--popover-foreground: 210 20% 98%;
--border: 215 27.9% 16.9%;
--input: 215 27.9% 16.9%;
--card: 224 71.4% 4.1%;
--card-foreground: 210 20% 98%;
--primary: 210 20% 98%;
--primary-foreground: 220.9 39.3% 11%;
--secondary: 215 27.9% 16.9%;
--secondary-foreground: 210 20% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 20% 98%;
--ring: 216 12.2% 83.9%;
--radius: 0.5rem;
--token-comment-color: #6c757d;
--token-punctuation-color: #999;
--token-property-color: #d19a66;
--token-selector-color: #c678dd;
--token-operator-color: #a9a9a9;
--token-attr-color: #56a8a8;
--token-variable-color: #e09062;
--token-function-color: #cb6d90;
/* monaco editor */
--custom-editor-background: hsl(var(--background));
/* --rhm */
--rhm-rect: #2d333b;
--rhm-text-color: #c9d1d9;
--rhm-rect-hover-stroke: rgba(255, 255, 255, 0.14);
--rhm-rect-active: #196127;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
--sidebar: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
`
export default function CSSEditor({ data, nodeId, nodeName }) {
const [cssCode, setCssCode] = useState(data || defaultThemeCss);
const [debouncedValue] = useDebounceValue(cssCode, 500);
useEffect(() => {
if (debouncedValue !== undefined && nodeId) {
eidos.currentSpace.extNode.setText(nodeId, debouncedValue);
}
}, [nodeId, debouncedValue]);
const handleApplyTheme = async () => {
await eidos.currentSpace.theme.applyTheme(nodeName || `theme-${nodeId?.slice(-4)}`, cssCode);
};
const handleRefresh = async () => {
if (nodeId) {
const newData = await eidos.currentSpace.extNode.getText(nodeId);
setCssCode(newData);
}
};
return (
<div className="flex flex-col h-full">
<div className="w-full flex justify-end p-2 border-b space-x-2">
<Button onClick={handleRefresh}>Refresh</Button>
<Button onClick={handleApplyTheme}>Apply Theme</Button>
</div>
<Editor
height="100%"
defaultLanguage="css"
value={cssCode}
onChange={(value) => setCssCode(value || '')}
options={{
minimap: { enabled: false },
fontSize: 14,
scrollBeyondLastLine: false,
automaticLayout: true,
}}
/>
</div>
);
}