Eidos

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>
  );
}

Information

Author
Mayne
Type
m_block
Latest Version
0.0.4
Last Updated
06/08/2025
Published
06/08/2025

Version History

  • v0.0.4 06/08/2025
  • v0.0.3 06/08/2025
  • v0.0.2 06/08/2025
  • v0.0.1 06/08/2025