Files
oldboy/src/lib/components/editor/EditorSettings.svelte
2025-10-15 16:52:39 +02:00

286 lines
6.9 KiB
Svelte

<script lang="ts">
import { getAppContext } from '../../contexts/app-context';
const { editorSettings } = getAppContext();
let settings = $state($editorSettings);
$effect(() => {
settings = $editorSettings;
});
function updateSetting(key: keyof typeof settings, value: any) {
editorSettings.updatePartial({ [key]: value });
}
</script>
<div class="editor-settings">
<div class="setting">
<span class="label-text">Theme</span>
<div class="theme-toggle">
<button
class="theme-option"
class:active={settings.theme === 'dark'}
onclick={() => updateSetting('theme', 'dark')}
>
Dark
</button>
<button
class="theme-option"
class:active={settings.theme === 'light'}
onclick={() => updateSetting('theme', 'light')}
>
Light
</button>
</div>
</div>
<div class="setting">
<label>
<span class="label-text">Font Size: {settings.fontSize}px</span>
<input
type="range"
min="10"
max="24"
step="1"
value={settings.fontSize}
oninput={(e) => updateSetting('fontSize', parseInt(e.currentTarget.value))}
/>
</label>
</div>
<div class="setting">
<label>
<span class="label-text">Font Family</span>
<select
value={settings.fontFamily}
onchange={(e) => updateSetting('fontFamily', e.currentTarget.value)}
>
<option value="'Roboto Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace">Roboto Mono</option>
<option value="'JetBrains Mono', 'Roboto Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace">JetBrains Mono</option>
<option value="'Fira Code', 'Roboto Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace">Fira Code</option>
<option value="Monaco, 'Roboto Mono', Consolas, 'Liberation Mono', 'Courier New', monospace">Monaco</option>
<option value="Consolas, 'Roboto Mono', Monaco, 'Liberation Mono', 'Courier New', monospace">Consolas</option>
<option value="'Courier New', 'Roboto Mono', Monaco, Consolas, monospace">Courier New</option>
</select>
</label>
</div>
<div class="setting">
<label>
<span class="label-text">Tab Size: {settings.tabSize}</span>
<input
type="range"
min="2"
max="8"
step="2"
value={settings.tabSize}
oninput={(e) => updateSetting('tabSize', parseInt(e.currentTarget.value))}
/>
</label>
</div>
<div class="checkboxes">
<label class="checkbox-label">
<input
type="checkbox"
checked={settings.vimMode}
onchange={(e) => updateSetting('vimMode', e.currentTarget.checked)}
/>
<span>Vim mode</span>
</label>
<label class="checkbox-label">
<input
type="checkbox"
checked={settings.showLineNumbers}
onchange={(e) => updateSetting('showLineNumbers', e.currentTarget.checked)}
/>
<span>Display line numbers</span>
</label>
<label class="checkbox-label">
<input
type="checkbox"
checked={settings.enableLineWrapping}
onchange={(e) => updateSetting('enableLineWrapping', e.currentTarget.checked)}
/>
<span>Enable line wrapping</span>
</label>
<label class="checkbox-label">
<input
type="checkbox"
checked={settings.enableHoverTooltips}
onchange={(e) => updateSetting('enableHoverTooltips', e.currentTarget.checked)}
/>
<span>Enable hover tooltips</span>
</label>
</div>
</div>
<style>
.editor-settings {
padding: var(--space-sm);
color: var(--color-text-primary);
}
.setting {
margin-bottom: var(--space-lg);
}
label {
display: block;
}
.label-text {
display: block;
font-size: var(--font-sm);
font-weight: 500;
color: var(--color-text-secondary);
margin-bottom: var(--space-xs);
}
.theme-toggle {
display: flex;
gap: 0;
border: 1px solid var(--color-border-default);
overflow: hidden;
}
.theme-option {
flex: 1;
padding: var(--space-sm) var(--space-lg);
background-color: transparent;
color: var(--color-text-secondary);
border: none;
cursor: pointer;
font-size: var(--font-sm);
font-weight: 500;
transition: all var(--transition-base);
border-right: 1px solid var(--color-border-default);
}
.theme-option:last-child {
border-right: none;
}
.theme-option:hover:not(.active) {
background-color: var(--color-hover-overlay);
color: var(--color-text-primary);
}
.theme-option.active {
background-color: var(--color-accent-primary);
color: white;
}
input[type="range"] {
width: 100%;
height: 8px;
background: #4b5563;
appearance: none;
cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
appearance: none;
width: 12px;
height: 12px;
background: var(--color-accent-primary);
cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
width: 12px;
height: 12px;
background: var(--color-accent-primary);
cursor: pointer;
border: none;
}
input[type="range"]:hover {
background: #6b7280;
}
input[type="range"]::-webkit-slider-thumb:hover {
background: var(--color-accent-primary-hover);
}
input[type="range"]::-moz-range-thumb:hover {
background: var(--color-accent-primary-hover);
}
select {
width: 100%;
background-color: var(--color-bg-base);
color: var(--color-text-primary);
border: 1px solid #555;
padding: 0.4rem;
font-size: var(--font-sm);
cursor: pointer;
}
select:hover {
border-color: var(--color-accent-primary);
}
select:focus {
outline: none;
border-color: var(--color-accent-primary);
}
.checkboxes {
display: flex;
flex-direction: column;
gap: var(--space-sm);
}
.checkbox-label {
display: flex;
align-items: center;
gap: var(--space-sm);
font-size: var(--font-sm);
font-weight: 500;
color: var(--color-text-secondary);
cursor: pointer;
}
input[type="checkbox"] {
appearance: none;
width: 16px;
height: 16px;
background-color: #4b5563;
border: 1px solid #6b7280;
cursor: pointer;
transition: all var(--transition-base);
}
input[type="checkbox"]:hover {
background-color: #6b7280;
border-color: #9ca3af;
}
input[type="checkbox"]:checked {
background-color: var(--color-accent-primary);
border-color: var(--color-accent-primary);
}
input[type="checkbox"]:checked:hover {
background-color: var(--color-accent-primary-hover);
border-color: var(--color-accent-primary-hover);
}
input[type="checkbox"]:checked::before {
content: '✓';
color: white;
font-size: 12px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
</style>