Font size
This commit is contained in:
@@ -47,10 +47,11 @@ interface EditorProps {
|
||||
initialValue?: string;
|
||||
onChange?: (editor: any, changes: any) => void;
|
||||
onReady?: (editor: any) => void;
|
||||
fontSize?: number;
|
||||
}
|
||||
|
||||
export const Editor = forwardRef<any, EditorProps>(function Editor(
|
||||
{ initialValue = "", onChange, onReady },
|
||||
{ initialValue = "", onChange, onReady, fontSize = 14 },
|
||||
ref
|
||||
) {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
@@ -113,6 +114,17 @@ export const Editor = forwardRef<any, EditorProps>(function Editor(
|
||||
};
|
||||
}, []); // DO NOT FILL ARRAY
|
||||
|
||||
// Update font size when it changes
|
||||
useEffect(() => {
|
||||
if (editorRef.current) {
|
||||
const wrapper = editorRef.current.getWrapperElement();
|
||||
if (wrapper) {
|
||||
wrapper.style.fontSize = `${fontSize}px`;
|
||||
editorRef.current.refresh();
|
||||
}
|
||||
}
|
||||
}, [fontSize]);
|
||||
|
||||
return (
|
||||
<div className={styles.editorContainer}>
|
||||
<textarea
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useState, useRef, useCallback, useEffect } from "react";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { Dropdown } from "@/components/ui/Dropdown";
|
||||
import { Slider } from "@/components/ui/Slider";
|
||||
import { Editor } from "@/components/Editor";
|
||||
import { Terminal, TerminalRef } from "@/components/Terminal";
|
||||
import {
|
||||
@@ -46,6 +47,7 @@ const exampleScriptList = [
|
||||
export default function Playground() {
|
||||
const [isScriptRunning, setIsScriptRunning] = useState(false);
|
||||
const [isEditorReady, setIsEditorReady] = useState(false);
|
||||
const [fontSize, setFontSize] = useState(14);
|
||||
|
||||
const editorRef = useRef<any>(null);
|
||||
const resultRef = useRef<HTMLTextAreaElement>(null);
|
||||
@@ -191,6 +193,24 @@ export default function Playground() {
|
||||
}))}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
trigger="Config"
|
||||
align="right"
|
||||
customContent={
|
||||
<div className={styles.configPanel}>
|
||||
<Slider
|
||||
label="Font Size"
|
||||
value={fontSize}
|
||||
min={10}
|
||||
max={24}
|
||||
step={1}
|
||||
onChange={setFontSize}
|
||||
unit="px"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
triggerIcon="help-circle"
|
||||
align="right"
|
||||
@@ -246,6 +266,7 @@ export default function Playground() {
|
||||
initialValue={initialCode}
|
||||
onChange={() => {}}
|
||||
onReady={() => setIsEditorReady(true)}
|
||||
fontSize={fontSize}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.rightPanel}>
|
||||
@@ -255,6 +276,7 @@ export default function Playground() {
|
||||
<Terminal
|
||||
ref={terminalRef}
|
||||
onData={sendDataToScript}
|
||||
fontSize={fontSize}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,6 +288,7 @@ export default function Playground() {
|
||||
readOnly
|
||||
autoComplete="off"
|
||||
placeholder="Use print() to produce output"
|
||||
style={{ fontSize: `${fontSize}px` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@ export const Terminal = forwardRef<
|
||||
TerminalRef,
|
||||
{
|
||||
onData: (data: String) => void;
|
||||
fontSize?: number;
|
||||
}
|
||||
>(function Terminal(props, ref) {
|
||||
const terminalRef = useRef<HTMLDivElement>(null);
|
||||
@@ -54,7 +55,7 @@ export const Terminal = forwardRef<
|
||||
// - `init_term()` ccompletes, and we attempt to set `xtermRef.current`, causing issues
|
||||
let mounted = true;
|
||||
|
||||
init_term(terminalRef, props.onData, () => mounted)
|
||||
init_term(terminalRef, props.onData, () => mounted, props.fontSize)
|
||||
.then((term) => {
|
||||
if (!mounted) return;
|
||||
xtermRef.current = term;
|
||||
@@ -70,7 +71,14 @@ export const Terminal = forwardRef<
|
||||
xtermRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [props.onData]);
|
||||
}, [props.onData, props.fontSize]);
|
||||
|
||||
// Update font size when it changes
|
||||
useEffect(() => {
|
||||
if (xtermRef.current && props.fontSize !== undefined) {
|
||||
xtermRef.current.options.fontSize = props.fontSize;
|
||||
}
|
||||
}, [props.fontSize]);
|
||||
|
||||
return <div ref={terminalRef} style={{ height: "100%", width: "100%" }} />;
|
||||
});
|
||||
@@ -80,7 +88,8 @@ async function init_term(
|
||||
|
||||
// Called when the terminal receives data
|
||||
onData: (data: String) => void,
|
||||
isMounted: () => boolean
|
||||
isMounted: () => boolean,
|
||||
fontSize?: number
|
||||
) {
|
||||
if (!ref.current) return;
|
||||
|
||||
@@ -90,7 +99,7 @@ async function init_term(
|
||||
const term = new Terminal({
|
||||
//"fontFamily": "Fantasque",
|
||||
rows: 30,
|
||||
fontSize: 18,
|
||||
fontSize: fontSize ?? 18,
|
||||
tabStopWidth: 4,
|
||||
cursorBlink: false,
|
||||
cursorStyle: "block",
|
||||
|
||||
49
webui/src/components/ui/Slider.tsx
Normal file
49
webui/src/components/ui/Slider.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
"use client";
|
||||
|
||||
import { ChangeEvent } from "react";
|
||||
import styles from "@/styles/Slider.module.css";
|
||||
|
||||
interface SliderProps {
|
||||
label: string;
|
||||
value: number;
|
||||
min: number;
|
||||
max: number;
|
||||
step?: number;
|
||||
onChange: (value: number) => void;
|
||||
unit?: string;
|
||||
}
|
||||
|
||||
export function Slider({
|
||||
label,
|
||||
value,
|
||||
min,
|
||||
max,
|
||||
step = 1,
|
||||
onChange,
|
||||
unit = "",
|
||||
}: SliderProps) {
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(Number(e.target.value));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.sliderContainer}>
|
||||
<div className={styles.sliderLabel}>
|
||||
<span>{label}</span>
|
||||
<span className={styles.sliderValue}>
|
||||
{value}
|
||||
{unit}
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
className={styles.slider}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
57
webui/src/styles/Slider.module.css
Normal file
57
webui/src/styles/Slider.module.css
Normal file
@@ -0,0 +1,57 @@
|
||||
.sliderContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sliderLabel {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.sliderValue {
|
||||
font-weight: 600;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.slider {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background: #3a3a3a;
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #4fc3f7;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb:hover {
|
||||
background: #6dd1ff;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: #4fc3f7;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb:hover {
|
||||
background: #6dd1ff;
|
||||
}
|
||||
Reference in New Issue
Block a user