feat(ui): add CodeBlock and CodeEditor components with Monaco and hljs

- add CodeBlock for read-only syntax-highlighted display (hljs, js/json)
- add CodeEditor wrapping Monaco editor with theme sync, focus state, and error state
- replace code textareas in snippet, credential, and step pages with CodeEditor
- replace code <pre> blocks in snippet and credential detail pages with CodeBlock
- make form cards full-width on pages with code editors
- add resize:vertical support to CodeEditor wrapper with automaticLayout
This commit is contained in:
2026-04-10 15:53:26 +03:00
parent 2046e64428
commit 1c13e068ad
21 changed files with 391 additions and 76 deletions
+8 -14
View File
@@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { scenarios, steps } from '../../api';
import type { Scenario, ScenarioStep, StepType } from '../../api';
import { Breadcrumbs, Button, Card, Input, Select } from '../../ui';
import { Breadcrumbs, Button, Card, Input, Select, CodeEditor } from '../../ui';
import styles from '../Page.module.css';
const STEP_TYPES: StepType[] = ['login', 'exec', 'sign'];
@@ -91,7 +91,7 @@ export function EditStepPage() {
{!loading && step && (
<form onSubmit={handleSubmit} noValidate>
<Card className={styles.formCard}>
<Card className={styles.formCardFull}>
<div className={styles.formFields}>
<Input
label={t('steps.form_order')}
@@ -118,24 +118,18 @@ export function EditStepPage() {
/>
<div className={styles.formField}>
<label className={styles.fieldLabel}>{t('steps.form_exec_code')}</label>
<textarea
className={styles.textarea}
rows={6}
<CodeEditor
value={execCode}
onChange={(e) => setExecCode(e.target.value)}
placeholder={t('steps.form_exec_code_placeholder')}
spellCheck={false}
onChange={setExecCode}
rows={6}
/>
</div>
<div className={styles.formField}>
<label className={styles.fieldLabel}>{t('steps.form_validate_code')}</label>
<textarea
className={styles.textarea}
rows={6}
<CodeEditor
value={validateCode}
onChange={(e) => setValidateCode(e.target.value)}
placeholder={t('steps.form_validate_code_placeholder')}
spellCheck={false}
onChange={setValidateCode}
rows={6}
/>
</div>
</div>