-
-
Notifications
You must be signed in to change notification settings - Fork 215
Feature Reqquest - Add Font Size and Word Wrap settings to editor pre… #735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,21 @@ | ||
| import React from 'react'; | ||
| import { Modal, Switch } from 'antd'; | ||
| import { Modal, Switch, Select } from 'antd'; | ||
| import DarkModeToggle from 'react-dark-mode-toggle'; | ||
| import useAppStore from '../store/store'; | ||
|
|
||
| const FONT_SIZES = [12, 13, 14, 15, 16, 18, 20]; | ||
|
|
||
| const SettingsModal: React.FC = () => { | ||
| const { | ||
| isSettingsOpen, | ||
| setSettingsOpen, | ||
| showLineNumbers, | ||
| const { | ||
| isSettingsOpen, | ||
| setSettingsOpen, | ||
| showLineNumbers, | ||
| setShowLineNumbers, | ||
| textColor, | ||
| backgroundColor, | ||
| toggleDarkMode | ||
| toggleDarkMode, | ||
| editorSettings, | ||
| setEditorSettings, | ||
| } = useAppStore((state) => ({ | ||
| isSettingsOpen: state.isSettingsOpen, | ||
| setSettingsOpen: state.setSettingsOpen, | ||
|
|
@@ -20,6 +24,8 @@ const SettingsModal: React.FC = () => { | |
| textColor: state.textColor, | ||
| backgroundColor: state.backgroundColor, | ||
| toggleDarkMode: state.toggleDarkMode, | ||
| editorSettings: state.editorSettings, | ||
| setEditorSettings: state.setEditorSettings, | ||
| })); | ||
|
|
||
| const isDarkMode = backgroundColor === '#121212'; | ||
|
|
@@ -35,7 +41,8 @@ const SettingsModal: React.FC = () => { | |
| style={{ maxWidth: 480 }} | ||
| > | ||
| <div className="space-y-6 py-4"> | ||
| {/* Dark Mode Toggle */} | ||
|
|
||
| {/* Dark Mode */} | ||
| <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"> | ||
| <div className="flex-1 min-w-0"> | ||
| <h4 className="font-medium text-sm sm:text-base" style={{ color: textColor }}> | ||
|
|
@@ -45,18 +52,12 @@ const SettingsModal: React.FC = () => { | |
| Toggle between light and dark theme | ||
| </p> | ||
| </div> | ||
| <div className="flex-shrink-0"> | ||
| <DarkModeToggle | ||
| onChange={toggleDarkMode} | ||
| checked={isDarkMode} | ||
| size={50} | ||
| /> | ||
| </div> | ||
| <DarkModeToggle onChange={toggleDarkMode} checked={isDarkMode} size={50} /> | ||
| </div> | ||
|
|
||
| <hr className={isDarkMode ? 'border-gray-600' : 'border-gray-200'} /> | ||
|
|
||
| {/* Line Numbers Toggle */} | ||
| {/* Line Numbers */} | ||
| <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"> | ||
| <div className="flex-1 min-w-0"> | ||
| <h4 className="font-medium text-sm sm:text-base" style={{ color: textColor }}> | ||
|
|
@@ -66,17 +67,56 @@ const SettingsModal: React.FC = () => { | |
| Display line numbers in code editors | ||
| </p> | ||
| </div> | ||
| <div className="flex-shrink-0"> | ||
| <Switch | ||
| checked={showLineNumbers} | ||
| onChange={setShowLineNumbers} | ||
| aria-label="Toggle line numbers" | ||
| /> | ||
| <Switch checked={showLineNumbers} onChange={setShowLineNumbers} /> | ||
| </div> | ||
|
|
||
| <hr className={isDarkMode ? 'border-gray-600' : 'border-gray-200'} /> | ||
|
|
||
| {/* Font Size */} | ||
| <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"> | ||
| <div className="flex-1 min-w-0"> | ||
| <h4 className="font-medium text-sm sm:text-base" style={{ color: textColor }}> | ||
| Font Size | ||
| </h4> | ||
| <p className={`text-xs sm:text-sm ${isDarkMode ? 'text-gray-400' : 'text-gray-500'}`}> | ||
| Adjust editor font size | ||
| </p> | ||
| </div> | ||
| <Select | ||
| value={editorSettings.fontSize} | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
| onChange={(value) => setEditorSettings({ fontSize: value })} | ||
| style={{ width: 110 }} | ||
| options={FONT_SIZES.map((size) => ({ | ||
| label: `${size}px`, | ||
| value: size, | ||
| }))} | ||
| /> | ||
| </div> | ||
|
|
||
| <hr className={isDarkMode ? 'border-gray-600' : 'border-gray-200'} /> | ||
|
|
||
| {/* Word Wrap */} | ||
| <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"> | ||
| <div className="flex-1 min-w-0"> | ||
| <h4 className="font-medium text-sm sm:text-base" style={{ color: textColor }}> | ||
| Word Wrap | ||
| </h4> | ||
| <p className={`text-xs sm:text-sm ${isDarkMode ? 'text-gray-400' : 'text-gray-500'}`}> | ||
| Wrap long lines in editors | ||
| </p> | ||
| </div> | ||
| <Switch | ||
| checked={editorSettings.wordWrap === 'on'} | ||
| onChange={(checked) => | ||
| setEditorSettings({ wordWrap: checked ? 'on' : 'off' }) | ||
| } | ||
| /> | ||
| </div> | ||
|
Comment on lines
+75
to
+115
|
||
|
|
||
| </div> | ||
| </Modal> | ||
| ); | ||
| }; | ||
|
|
||
| export default SettingsModal; | ||
| export default SettingsModal; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,6 @@ const concertoKeywords = [ | |
| "enum", | ||
| "scalar", | ||
| "extends", | ||
| "default", | ||
| "participant", | ||
|
||
| "asset", | ||
| "o", | ||
|
|
@@ -60,22 +59,21 @@ const handleEditorWillMount = (monacoInstance: typeof monaco) => { | |
| { open: "{", close: "}" }, | ||
| { open: "[", close: "]" }, | ||
| { open: "(", close: ")" }, | ||
| { open: "\"", close: "\"" }, | ||
| { open: `"`, close: `"` }, | ||
| ], | ||
| surroundingPairs: [ | ||
| { open: "{", close: "}" }, | ||
| { open: "[", close: "]" }, | ||
| { open: "(", close: ")" }, | ||
| { open: "\"", close: "\"" }, | ||
| { open: `"`, close: `"` }, | ||
| ], | ||
| }); | ||
|
|
||
| monacoInstance.languages.setMonarchTokensProvider("concerto", { | ||
| keywords: concertoKeywords, | ||
| typeKeywords: concertoTypes, | ||
| operators: ["=", "{", "}", "@", '"'], | ||
| operators: ["=", "{", "}", "@", `"`], | ||
| symbols: /[=}{@"]+/, | ||
| escapes: /\\(?:[btnfru"'\\]|\\u[0-9A-Fa-f]{4})/, | ||
| tokenizer: { | ||
| root: [ | ||
| { include: "@whitespace" }, | ||
|
|
@@ -89,12 +87,11 @@ const handleEditorWillMount = (monacoInstance: typeof monaco) => { | |
| }, | ||
| }, | ||
| ], | ||
| [/"([^"\\]|\\.)*$/, "string.invalid"], // non-terminated string | ||
| [/"([^"\\]|\\.)*$/, "string.invalid"], | ||
| [/"/, "string", "@string"], | ||
| ], | ||
| string: [ | ||
| [/[^\\"]+/, "string"], | ||
| [/@escapes/, "string.escape"], | ||
| [/\\./, "string.escape.invalid"], | ||
|
||
| [/"/, "string", "@pop"], | ||
| ], | ||
|
|
@@ -105,71 +102,93 @@ const handleEditorWillMount = (monacoInstance: typeof monaco) => { | |
| }, | ||
| }); | ||
|
|
||
| if (monacoInstance) { | ||
| registerAutocompletion('concerto', monacoInstance); | ||
| } | ||
| registerAutocompletion("concerto", monacoInstance); | ||
| }; | ||
|
|
||
| interface ConcertoEditorProps { | ||
| value: string; | ||
| onChange?: (value: string | undefined) => void; | ||
| } | ||
|
|
||
| export default function ConcertoEditor({ | ||
| value, | ||
| onChange, | ||
| }: ConcertoEditorProps) { | ||
| export default function ConcertoEditor({ value, onChange }: ConcertoEditorProps) { | ||
| const { handleSelection, MenuComponent } = useCodeSelection("concerto"); | ||
| const monacoInstance = useMonaco(); | ||
| const { error, backgroundColor, aiConfig, showLineNumbers } = useAppStore((state) => ({ | ||
|
|
||
| const { | ||
| error, | ||
| backgroundColor, | ||
| aiConfig, | ||
| showLineNumbers, | ||
| editorSettings, | ||
| } = useAppStore((state) => ({ | ||
| error: state.error, | ||
| backgroundColor: state.backgroundColor, | ||
| aiConfig: state.aiConfig, | ||
| showLineNumbers: state.showLineNumbers, | ||
| editorSettings: state.editorSettings, | ||
| })); | ||
|
|
||
| const ctoErr = error?.startsWith("c:") ? error : undefined; | ||
|
|
||
| const themeName = useMemo( | ||
| () => (backgroundColor ? "darkTheme" : "lightTheme"), | ||
| () => (backgroundColor === "#121212" ? "darkTheme" : "lightTheme"), | ||
| [backgroundColor] | ||
| ); | ||
|
|
||
| const options: monaco.editor.IStandaloneEditorConstructionOptions = useMemo(() => ({ | ||
| minimap: { enabled: false }, | ||
| wordWrap: "on", | ||
| automaticLayout: true, | ||
| scrollBeyondLastLine: false, | ||
| lineNumbers: showLineNumbers ? 'on' : 'off', | ||
| autoClosingBrackets: "languageDefined", | ||
| autoSurround: "languageDefined", | ||
| bracketPairColorization: { enabled: true }, | ||
| inlineSuggest: { | ||
| enabled: aiConfig?.enableInlineSuggestions !== false, | ||
| mode: "prefix", | ||
| suppressSuggestions: false, | ||
| fontFamily: "inherit", | ||
| keepOnBlur: true, | ||
| }, | ||
| suggest: { | ||
| preview: true, | ||
| showInlineDetails: true, | ||
| }, | ||
| quickSuggestions: false, | ||
| suggestOnTriggerCharacters: false, | ||
| acceptSuggestionOnCommitCharacter: false, | ||
| acceptSuggestionOnEnter: "off", | ||
| tabCompletion: "off", | ||
| }), [aiConfig?.enableInlineSuggestions, showLineNumbers]); | ||
|
|
||
| const handleEditorDidMount = (editor: monaco.editor.IStandaloneCodeEditor) => { | ||
| const options: monaco.editor.IStandaloneEditorConstructionOptions = useMemo( | ||
| () => ({ | ||
| minimap: { enabled: false }, | ||
| automaticLayout: true, | ||
| scrollBeyondLastLine: false, | ||
|
|
||
| // 🔑 NEW — editor settings | ||
| fontSize: editorSettings.fontSize, | ||
| wordWrap: editorSettings.wordWrap, | ||
|
|
||
| lineNumbers: showLineNumbers ? "on" : "off", | ||
|
|
||
| autoClosingBrackets: "languageDefined", | ||
| autoSurround: "languageDefined", | ||
| bracketPairColorization: { enabled: true }, | ||
|
|
||
| inlineSuggest: { | ||
| enabled: aiConfig?.enableInlineSuggestions !== false, | ||
| mode: "prefix", | ||
| suppressSuggestions: false, | ||
| fontFamily: "inherit", | ||
| keepOnBlur: true, | ||
| }, | ||
|
|
||
| suggest: { | ||
| preview: true, | ||
| showInlineDetails: true, | ||
| }, | ||
|
|
||
| quickSuggestions: false, | ||
| suggestOnTriggerCharacters: false, | ||
| acceptSuggestionOnCommitCharacter: false, | ||
| acceptSuggestionOnEnter: "off", | ||
| tabCompletion: "off", | ||
| }), | ||
| [ | ||
| aiConfig?.enableInlineSuggestions, | ||
| showLineNumbers, | ||
| editorSettings.fontSize, | ||
| editorSettings.wordWrap, | ||
| ] | ||
| ); | ||
|
|
||
| const handleEditorDidMount = ( | ||
| editor: monaco.editor.IStandaloneCodeEditor | ||
| ) => { | ||
| editor.onDidChangeCursorSelection(() => { | ||
| handleSelection(editor); | ||
| }); | ||
| }; | ||
|
|
||
| const handleChange = useCallback( | ||
| (val: string | undefined) => { | ||
| if (onChange) onChange(val); | ||
| onChange?.(val); | ||
| }, | ||
| [onChange] | ||
| ); | ||
|
|
@@ -183,8 +202,9 @@ export default function ConcertoEditor({ | |
| if (ctoErr) { | ||
| const match = ctoErr.match(/Line (\d+) column (\d+)/); | ||
| if (match) { | ||
| const lineNumber = parseInt(match[1], 10); | ||
| const columnNumber = parseInt(match[2], 10); | ||
| const lineNumber = Number(match[1]); | ||
| const columnNumber = Number(match[2]); | ||
|
|
||
| monacoInstance.editor.setModelMarkers(model, "customMarker", [ | ||
| { | ||
| startLineNumber: lineNumber, | ||
|
|
@@ -218,4 +238,4 @@ export default function ConcertoEditor({ | |
| {MenuComponent} | ||
| </div> | ||
| ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The eslint-disable comment for unsafe-assignment is unnecessary. The Select onChange handler receives a number value which matches the fontSize type. Consider removing this comment to keep the codebase clean.