diff --git a/.changeset/import-proposal-json.md b/.changeset/import-proposal-json.md new file mode 100644 index 0000000000..3c36228fef --- /dev/null +++ b/.changeset/import-proposal-json.md @@ -0,0 +1,5 @@ +--- +"@anticapture/dashboard": minor +--- + +Import a proposal from JSON when creating one. diff --git a/apps/dashboard/features/create-proposal/components/BodyField.tsx b/apps/dashboard/features/create-proposal/components/BodyField.tsx index a1ecefd9d0..13d32cce2d 100644 --- a/apps/dashboard/features/create-proposal/components/BodyField.tsx +++ b/apps/dashboard/features/create-proposal/components/BodyField.tsx @@ -10,6 +10,8 @@ import { MDXEditor, Separator, StrikeThroughSupSubToggles, + codeBlockPlugin, + codeMirrorPlugin, diffSourcePlugin, headingsPlugin, linkDialogPlugin, @@ -76,7 +78,6 @@ export const BodyField = ({ version = 0 }: BodyFieldProps) => { "[&_.mdxeditor-toolbar]:rounded-base! [&_.mdxeditor-toolbar]:!mb-2 [&_.mdxeditor-toolbar]:!bg-transparent [&_.mdxeditor-toolbar]:!px-0 [&_.mdxeditor-toolbar]:!py-0", "[&_.mdxeditor-root-contenteditable]:max-h-100 md:[&_.mdxeditor-root-contenteditable]:max-h-150 [&_.mdxeditor-root-contenteditable]:overflow-y-auto", "[&_.cm-editor]:min-h-75 [&_.cm-editor]:max-h-100 [&_.cm-scroller]:min-h-75 [&_.cm-scroller]:max-h-100 md:[&_.cm-editor]:min-h-130 md:[&_.cm-editor]:max-h-150 md:[&_.cm-scroller]:min-h-130 md:[&_.cm-scroller]:max-h-150", - // Markdown source view (CodeMirror) — match the dashboard theme "[&_.cm-editor]:bg-surface-background [&_.cm-editor]:text-primary", "[&_.cm-scroller]:bg-surface-background", "[&_.cm-content]:bg-surface-background [&_.cm-content]:text-primary [&_.cm-content]:caret-primary", @@ -91,7 +92,6 @@ export const BodyField = ({ version = 0 }: BodyFieldProps) => { "[&_.tok-comment]:text-secondary [&_.tok-comment]:italic", "[&_.tok-number]:text-warning [&_.tok-bool]:text-warning [&_.tok-atom]:text-warning", "[&_.tok-punctuation]:text-secondary [&_.tok-meta]:text-secondary", - // Heading styles for Visual Editor content (mdxeditor content area) "[&_.mdxeditor-root-contenteditable_h1]:mb-3 [&_.mdxeditor-root-contenteditable_h1]:mt-4 [&_.mdxeditor-root-contenteditable_h1]:text-2xl [&_.mdxeditor-root-contenteditable_h1]:font-semibold", "[&_.mdxeditor-root-contenteditable_h2]:mb-2 [&_.mdxeditor-root-contenteditable_h2]:mt-4 [&_.mdxeditor-root-contenteditable_h2]:text-xl [&_.mdxeditor-root-contenteditable_h2]:font-semibold", "[&_.mdxeditor-root-contenteditable_h3]:mb-2 [&_.mdxeditor-root-contenteditable_h3]:mt-3 [&_.mdxeditor-root-contenteditable_h3]:text-lg [&_.mdxeditor-root-contenteditable_h3]:font-semibold", @@ -122,6 +122,17 @@ export const BodyField = ({ version = 0 }: BodyFieldProps) => { linkPlugin(), linkDialogPlugin(), tablePlugin(), + codeBlockPlugin({ defaultCodeBlockLanguage: "" }), + codeMirrorPlugin({ + codeBlockLanguages: { + "": "Plain text", + json: "JSON", + js: "JavaScript", + ts: "TypeScript", + solidity: "Solidity", + bash: "Shell", + }, + }), markdownShortcutPlugin(), diffSourcePlugin({ viewMode: mode === "markdown" ? "source" : "rich-text", diff --git a/apps/dashboard/features/create-proposal/components/JsonTextarea.tsx b/apps/dashboard/features/create-proposal/components/JsonTextarea.tsx new file mode 100644 index 0000000000..471765165c --- /dev/null +++ b/apps/dashboard/features/create-proposal/components/JsonTextarea.tsx @@ -0,0 +1,86 @@ +"use client"; + +import { useRef, type Ref } from "react"; + +import { cn } from "@/shared/utils/cn"; + +type JsonTextareaProps = { + value: string; + onChange: (value: string) => void; + placeholder?: string; + errorLine?: number; + showLineNumbers?: boolean; + hasError?: boolean; + ariaLabel?: string; + className?: string; + ref?: Ref; +}; + +export const JsonTextarea = ({ + value, + onChange, + placeholder, + errorLine, + showLineNumbers = false, + hasError = false, + ariaLabel, + className, + ref, +}: JsonTextareaProps) => { + const gutterRef = useRef(null); + + const lineCount = value === "" ? 0 : value.split("\n").length; + + const gutterDigits = Math.max(2, String(lineCount).length); + + return ( +
+ {showLineNumbers && ( +
+ {Array.from({ length: lineCount }, (_, index) => { + const line = index + 1; + return ( +
+ {line} +
+ ); + })} +
+ )} + +