141 lines
4.6 KiB
TypeScript
141 lines
4.6 KiB
TypeScript
import { useEffect, useRef, useState } from 'react'
|
|
import { useIdeContext } from 'src/helpers/hooks/useIdeContext'
|
|
import { makeCodeStoreKey, requestRender } from 'src/helpers/hooks/useIdeState'
|
|
import Editor, { useMonaco } from '@monaco-editor/react'
|
|
import { theme } from 'src/../config/tailwind.config'
|
|
import { useSaveCode } from 'src/components/IdeWrapper/useSaveCode'
|
|
import type { CadPackageType } from 'src/components/CadPackage/CadPackage'
|
|
import EditorGuide from 'src/components/EditorGuide/EditorGuide'
|
|
|
|
const colors = theme.extend.colors
|
|
|
|
const IdeEditor = ({ Loading }) => {
|
|
const { state, thunkDispatch } = useIdeContext()
|
|
const [theme, setTheme] = useState('vs-dark')
|
|
const saveCode = useSaveCode()
|
|
|
|
const ideTypeToLanguageMap: { [key in CadPackageType]: string } = {
|
|
cadquery: 'python',
|
|
openscad: 'cpp',
|
|
jscad: 'javascript',
|
|
curv: 'javascript',
|
|
INIT: '',
|
|
}
|
|
const monaco = useMonaco()
|
|
useEffect(() => {
|
|
if (monaco) {
|
|
const themeName = 'cadhub'
|
|
monaco.editor.defineTheme(themeName, {
|
|
base: 'vs-dark',
|
|
inherit: true,
|
|
rules: [
|
|
{ background: colors['ch-gray'][750] },
|
|
{
|
|
token: 'comment',
|
|
foreground: colors['ch-blue'][600],
|
|
fontStyle: 'italic',
|
|
},
|
|
{ token: 'keyword', foreground: colors['ch-purple'][600] },
|
|
{ token: 'string', foreground: colors['ch-pink'][300] },
|
|
],
|
|
colors: {
|
|
'editor.background': colors['ch-gray'][800],
|
|
},
|
|
})
|
|
setTheme(themeName)
|
|
}
|
|
}, [monaco])
|
|
|
|
function handleCodeChange(value, _event) {
|
|
thunkDispatch({ type: 'updateCode', payload: value })
|
|
}
|
|
function handleSaveHotkey(event) {
|
|
//ctrl|meta + s is very intuitive for most devs
|
|
const { key, ctrlKey, metaKey } = event
|
|
if (key === 's' && (ctrlKey || metaKey)) {
|
|
event.preventDefault()
|
|
thunkDispatch((dispatch, getState) => {
|
|
const state = getState()
|
|
dispatch({ type: 'setLoading' })
|
|
saveCode({ code: state.code })
|
|
requestRender({
|
|
state,
|
|
dispatch,
|
|
})
|
|
})
|
|
localStorage.setItem(makeCodeStoreKey(state.ideType), state.code)
|
|
}
|
|
}
|
|
const currentTab = state.editorTabs[state.currentModel]
|
|
|
|
return (
|
|
<div // eslint-disable-line jsx-a11y/no-static-element-interactions
|
|
className="h-full"
|
|
onKeyDown={handleSaveHotkey}
|
|
>
|
|
{state.editorTabs.length > 1 && (
|
|
<fieldset className="bg-ch-gray-700 text-ch-gray-300 flex m-0 p-0">
|
|
{state.editorTabs.map((model, i) => (
|
|
<label
|
|
key={model.type + '-' + i}
|
|
className={
|
|
'flex items-center gap-2 px-4 py-1 block m-0 select-none relative bg-ch-gray-600 ' +
|
|
(state.currentModel === i && 'bg-ch-gray-800')
|
|
}
|
|
>
|
|
{model.label}
|
|
<input
|
|
type="radio"
|
|
name="models"
|
|
className="sr-only absolute inset-0"
|
|
value={i}
|
|
checked={state.currentModel === i}
|
|
onChange={() =>
|
|
thunkDispatch({ type: 'switchEditorModel', payload: i })
|
|
}
|
|
/>
|
|
{model.type !== 'code' && (
|
|
<button
|
|
onClick={() =>
|
|
thunkDispatch({ type: 'removeEditorModel', payload: i })
|
|
}
|
|
className="block p-1 m-.5 hover:bg-ch-gray-550"
|
|
>
|
|
<svg viewBox="0 0 5 5" className="w-4 text-ch-gray-300">
|
|
<path
|
|
stroke="currentColor"
|
|
d="M 1 1 l 3 3 M 1 4 l 3 -3"
|
|
strokeLinecap="round"
|
|
strokeWidth=".5"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
)}
|
|
</label>
|
|
))}
|
|
</fieldset>
|
|
)}
|
|
{currentTab.type === 'code' && (
|
|
<Editor
|
|
defaultValue={state.code}
|
|
value={state.code}
|
|
theme={theme}
|
|
loading={Loading}
|
|
// TODO #247 cpp seems better than js for the time being
|
|
defaultLanguage={ideTypeToLanguageMap[state.ideType] || 'cpp'}
|
|
language={ideTypeToLanguageMap[state.ideType] || 'cpp'}
|
|
onChange={handleCodeChange}
|
|
/>
|
|
)}
|
|
{currentTab.type === 'guide' && (
|
|
<div className="bg-ch-gray-800 h-full">
|
|
<EditorGuide content={currentTab.content} />
|
|
</div>
|
|
)}
|
|
{currentTab.type === 'component' && <currentTab.Component />}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default IdeEditor
|