Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd6c4b6b

Browse files
authored
feat: coder editor enhancement + html editor split live view (#87)
* feat: enhance editor functionality with searchable language selector and formatting options- Introduced a new SearchableLanguageSelector component for improved language selection with search capabilities.- Updated Editor component to include a format button with tooltip for document formatting.- Enhanced styling for editor toolbar and language selector for better user experience.- Added responsive design elements to prevent overflow and improve layout consistency.* style: update Editor.scss for improved toolbar appearance- Commented out the background color for the toolbar to allow for a more flexible design.- Increased the border-top thickness for better visibility.- Adjusted padding-bottom to ensure sufficient space for the toolbar, enhancing overall layout consistency.* feat: enhance HTML editor integration and toolbar functionality- Replaced HtmlEditor component with a more versatile Editor component for HTML content rendering.- Introduced useHtmlEditor hook to manage HTML editor state and functionality.- Updated Editor.scss to improve toolbar layout and added new HTML-specific controls.- Enhanced Editor component to conditionally display HTML controls based on the selected language.- Refactored HtmlEditor to provide reusable controls for HTML editing, improving code organization and maintainability.* feat: implement split view for HTML editor with preview functionality- Added a split view mode to the HTML editor, allowing simultaneous editing and previewing of HTML content.- Introduced HtmlEditorSplitView component to manage the rendering of the editor and preview side by side.- Enhanced useHtmlEditor hook to support active state management and preview toggling.- Updated Editor and HtmlEditor components to integrate new split view features and improve user experience.- Refactored styles in Editor.scss and HtmlEditor.scss to accommodate the new layout and ensure responsive design.
1 parente43f771 commitd6c4b6b

File tree

10 files changed

+905
-178
lines changed

10 files changed

+905
-178
lines changed

‎src/frontend/src/CustomEmbeddableRenderer.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
Dashboard,
88
StateIndicator,
99
ControlButton,
10-
HtmlEditor,
1110
Editor,
1211
Terminal,
1312
}from'./pad';
@@ -28,7 +27,11 @@ export const renderCustomEmbeddable = (
2827

2928
switch(path){
3029
case'html':
31-
content=<HtmlEditorelement={element}appState={appState}excalidrawAPI={excalidrawAPI}/>;
30+
content=<Editor
31+
element={element}
32+
language="html"
33+
excalidrawAPI={excalidrawAPI}
34+
/>;
3235
title="HTML Editor";
3336
break;
3437
case'editor':

‎src/frontend/src/pad/editors/Editor.scss‎

Lines changed: 189 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,105 @@
11
.editor {
22
&__wrapper {
3-
display:flex;
4-
flex-direction:column;
3+
position:relative;/* For absolute positioning of toolbar*/
54
height:100%;
65
width:100%;
6+
overflow:hidden;/* Prevent overflow issues*/
7+
border-bottom-left-radius:20px;
8+
border-bottom-right-radius:20px;
9+
10+
&--split {
11+
.monaco-editor {
12+
width:50%!important;/* Force Monaco editor to resize*/
13+
}
14+
15+
.editor__container {
16+
width:50%!important;/* Force container to resize*/
17+
}
18+
19+
.editor__toolbar {
20+
right:50%;/* Limit toolbar width to match the editor in split view*/
21+
}
22+
}
723
}
824

925
&__toolbar {
1026
display:flex;
11-
justify-content:right;
27+
justify-content:flex-end;/* Default justify to the right when no HTML controls*/
1228
padding:8px;
29+
position:absolute;/* Position at bottom*/
30+
bottom:0;
31+
left:0;
32+
right:0;
33+
z-index:10;/* Keep toolbar above other elements*/
34+
// background-color: #191919; /* Match editor background */
35+
border-top:2pxsolid#3c3c3c;
36+
}
37+
38+
&__toolbar-right {
39+
display:flex;
40+
align-items:center;
41+
gap:8px;/* Add spacing between toolbar items*/
42+
43+
.excalidraw-tooltip-wrapper {
44+
height:100%;
45+
display:flex;
46+
align-items:center;
47+
}
48+
}
49+
50+
&__html-controls {
51+
display:flex;
52+
align-items:center;
53+
gap:8px;
54+
margin-right:auto;/* Push to the left side*/
55+
56+
.html-editor__label {
57+
font-size:12px;
58+
color:#e0e0e0;
59+
display:flex;
60+
align-items:center;
61+
gap:4px;
62+
}
63+
64+
.html-editor__button {
65+
padding:6px12px;
66+
background:#5294f6;
67+
color:white;
68+
border:none;
69+
border-radius:4px;
70+
cursor:pointer;
71+
font-size:12px;
72+
73+
&:hover {
74+
background:#4285e7;
75+
}
76+
}
77+
}
78+
79+
&__format-button {
80+
background-color:#252526;
81+
color:#cccccc;
82+
border:1pxsolid#3c3c3c;
83+
border-radius:7px;
84+
padding:4px8px;
85+
cursor:pointer;
86+
display:flex;
87+
align-items:center;
88+
justify-content:center;
89+
height:100%;
90+
&:hover {
91+
background-color:#2a2d2e;
92+
color:#ffffff;
93+
}
94+
95+
&:focus {
96+
outline:none;
97+
border-color:#007fd4;
98+
}
1399
}
14100

15101
&__language-selector {
102+
display:flex;
16103
margin-right:10px;
17104
}
18105

@@ -35,8 +122,106 @@
35122
color:#cccccc;
36123
}
37124
}
125+
126+
&__searchable-language-container {
127+
display:flex;
128+
align-items:center;
129+
background-color:#252526;
130+
border:1pxsolid#3c3c3c;
131+
border-radius:7px;
132+
max-width:150px;
133+
position:relative;
134+
135+
&:focus-within {
136+
border-color:#007fd4;
137+
}
138+
}
139+
140+
&__searchable-language-input {
141+
background-color:transparent;
142+
color:#cccccc;
143+
border:none;
144+
padding:4px8px;
145+
font-size:12px;
146+
width:100%;
147+
148+
&:focus {
149+
outline:none;
150+
}
151+
152+
&::placeholder {
153+
color:#cccccc;
154+
opacity:0.8;
155+
}
156+
}
157+
158+
&__searchable-language-toggle {
159+
background:none;
160+
border:none;
161+
color:#cccccc;
162+
cursor:pointer;
163+
display:flex;
164+
align-items:center;
165+
justify-content:center;
166+
padding:06px;
167+
transition:transform0.2sease;
168+
169+
&:hover {
170+
color:#ffffff;
171+
}
172+
173+
&:focus {
174+
outline:none;
175+
}
176+
}
177+
178+
&__searchable-language-dropdown {
179+
position:absolute;
180+
bottom:100%;/* Position above instead of below*/
181+
left:0;
182+
right:0;
183+
max-height:200px;
184+
overflow-y:auto;
185+
background-color:#252526;
186+
border:1pxsolid#3c3c3c;
187+
border-radius:7px;
188+
margin-bottom:4px;/* Margin at bottom instead of top*/
189+
z-index:20;/* Higher z-index to ensure it's above the toolbar*/
190+
box-shadow:0-4px8pxrgba(0,0,0,0.3);/* Shadow adjusted for upward direction*/
191+
}
192+
193+
&__searchable-language-option {
194+
padding:4px8px;
195+
font-size:12px;
196+
color:#cccccc;
197+
cursor:pointer;
198+
199+
&:hover {
200+
background-color:#2a2d2e;
201+
}
202+
203+
&--highlighted {
204+
background-color:#04395e;
205+
}
206+
207+
&--selected {
208+
color:#ffffff;
209+
font-weight:500;
210+
}
211+
}
212+
213+
&__searchable-language-no-results {
214+
padding:4px8px;
215+
font-size:12px;
216+
color:#cccccc;
217+
font-style:italic;
218+
text-align:center;
219+
}
38220

39221
&__container {
40-
flex:1;
222+
height:100%;
223+
width:100%;
224+
padding-bottom:60px;/* Make room for the toolbar*/
225+
box-sizing:border-box;
41226
}
42227
}

‎src/frontend/src/pad/editors/Editor.tsx‎

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,36 @@
11
importReact,{useRef,useState,useEffect,useCallback}from'react';
22
importMonacoEditorfrom'@monaco-editor/react';
3-
importLanguageSelectorfrom'./LanguageSelector';
3+
import{Tooltip,updateTooltipPosition,getTooltipDiv}from'@atyrode/excalidraw';
4+
importSearchableLanguageSelectorfrom'./SearchableLanguageSelector';
5+
import{useHtmlEditor,HtmlEditorControls,defaultHtml,HtmlEditorSplitView}from'./HtmlEditor';
46
import'./Editor.scss';
57

8+
// Custom tooltip wrapper that positions the tooltip at the top
9+
constTopTooltip:React.FC<{label:string,children:React.ReactNode}>=({ label, children})=>{
10+
consthandlePointerEnter=(event:React.PointerEvent<HTMLDivElement>)=>{
11+
consttooltip=getTooltipDiv();
12+
tooltip.classList.add("excalidraw-tooltip--visible");
13+
tooltip.textContent=label;
14+
15+
constitemRect=event.currentTarget.getBoundingClientRect();
16+
updateTooltipPosition(tooltip,itemRect,"top");
17+
};
18+
19+
consthandlePointerLeave=()=>{
20+
getTooltipDiv().classList.remove("excalidraw-tooltip--visible");
21+
};
22+
23+
return(
24+
<div
25+
className="excalidraw-tooltip-wrapper"
26+
onPointerEnter={handlePointerEnter}
27+
onPointerLeave={handlePointerLeave}
28+
>
29+
{children}
30+
</div>
31+
);
32+
};
33+
634
interfaceEditorProps{
735
defaultValue?:string;
836
language?:string;
@@ -21,7 +49,7 @@ interface EditorProps {
2149

2250
constEditor:React.FC<EditorProps>=({
2351
defaultValue='',
24-
language='javascript',
52+
language='plaintext',
2553
theme='vs-dark',
2654
height='100%',
2755
options={
@@ -259,25 +287,84 @@ const Editor: React.FC<EditorProps> = ({
259287
}
260288
};
261289

290+
// Format document function
291+
constformatDocument=()=>{
292+
if(editorRef.current){
293+
// Trigger Monaco's format document action
294+
editorRef.current.getAction('editor.action.formatDocument')?.run();
295+
}
296+
};
297+
298+
// Check if the language is HTML
299+
constisHtml=currentLanguage==='html';
300+
301+
// Always initialize HTML editor hooks, but pass isActive flag
302+
consthtmlEditor=useHtmlEditor(
303+
element,
304+
editorRef,
305+
excalidrawAPI,
306+
isHtml
307+
);
308+
309+
// Determine if we should show the split view
310+
constshowSplitView=isHtml&&!htmlEditor.createNew&&htmlEditor.showPreview;
311+
262312
return(
263-
<divclassName="editor__wrapper">
313+
<divclassName={`editor__wrapper${showSplitView ?'editor__wrapper--split' :''}`}>
264314
<MonacoEditor
265315
height={height}
266316
language={currentLanguage}
267-
defaultValue={defaultValue}
317+
defaultValue={defaultValue||(isHtml ?defaultHtml :'')}
268318
theme={theme}
269319
options={options}
270320
onMount={handleEditorDidMount}
271321
onChange={handleEditorChange}
272322
className={className}
273323
/>
324+
325+
{/* Render the HTML preview in split view mode */}
326+
{showSplitView&&(
327+
<HtmlEditorSplitView
328+
editorContent={contentRef.current||''}
329+
previewContent={htmlEditor.previewContent}
330+
showPreview={htmlEditor.showPreview}
331+
/>
332+
)}
274333
{showLanguageSelector&&(
275334
<divclassName="editor__toolbar">
276-
<LanguageSelector
277-
value={currentLanguage}
278-
onChange={handleLanguageChange}
279-
className="editor__language-selector"
280-
/>
335+
{/* Show HTML-specific controls when language is HTML */}
336+
{isHtml&&(
337+
<divclassName="editor__html-controls">
338+
<HtmlEditorControls
339+
createNew={htmlEditor.createNew}
340+
setCreateNew={htmlEditor.setCreateNew}
341+
applyHtml={htmlEditor.applyHtml}
342+
showPreview={htmlEditor.showPreview}
343+
togglePreview={htmlEditor.togglePreview}
344+
/>
345+
</div>
346+
)}
347+
348+
{/* Group format button and language selector together on the right */}
349+
<divclassName="editor__toolbar-right">
350+
<TopTooltiplabel="Format"children={
351+
<button
352+
className="editor__format-button"
353+
onClick={formatDocument}
354+
aria-label="Format Document"
355+
>
356+
<svgwidth="16"height="16"viewBox="0 0 16 16"fill="none"xmlns="http://www.w3.org/2000/svg">
357+
<pathd="M2 4H14M4 8H12M6 12H10"stroke="currentColor"strokeWidth="1.5"strokeLinecap="round"strokeLinejoin="round"/>
358+
</svg>
359+
</button>
360+
}/>
361+
362+
<SearchableLanguageSelector
363+
value={currentLanguage}
364+
onChange={handleLanguageChange}
365+
className="editor__language-selector"
366+
/>
367+
</div>
281368
</div>
282369
)}
283370
</div>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp