Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/ArrayVisualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function ArrayVisualizer({ step }: ArrayVisualizerProps) {
? highlightColors[highlight]
: isSorted
? highlightColors.sorted
: '#333'
: 'var(--viz-faint)'

return (
<div
Expand Down
38 changes: 33 additions & 5 deletions src/components/CodePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ interface CodePanelProps {
locale?: Locale
}

/** Custom dark theme that matches the app background */
function defineTheme(monaco: Monaco) {
function defineThemes(monaco: Monaco) {
monaco.editor.defineTheme('algoviz-dark', {
base: 'vs-dark',
inherit: true,
Expand All @@ -56,6 +55,19 @@ function defineTheme(monaco: Monaco) {
'editorCursor.foreground': '#fff',
},
})
monaco.editor.defineTheme('algoviz-light', {
base: 'vs',
inherit: true,
rules: [],
colors: {
'editor.background': '#ffffff',
'editor.lineHighlightBackground': '#00000006',
'editorLineNumber.foreground': '#b3b3b3',
'editorLineNumber.activeForeground': '#ca8a04',
'editor.selectionBackground': '#00000015',
'editorCursor.foreground': '#171717',
},
})
}

export default function CodePanel({
Expand All @@ -80,10 +92,22 @@ export default function CodePanel({
setIsMounted(true)
}, [])

useEffect(() => {
const updateEditorTheme = (event?: Event) => {
const theme =
event instanceof CustomEvent ? event.detail : document.documentElement.dataset.theme
monacoRef.current?.editor.setTheme(theme === 'light' ? 'algoviz-light' : 'algoviz-dark')
}
window.addEventListener('themechange', updateEditorTheme)
return () => window.removeEventListener('themechange', updateEditorTheme)
}, [])

const handleEditorDidMount = useCallback(
(editor: any, monacoInstance: Monaco) => {
defineTheme(monacoInstance)
monacoInstance.editor.setTheme('algoviz-dark')
defineThemes(monacoInstance)
monacoInstance.editor.setTheme(
document.documentElement.dataset.theme === 'light' ? 'algoviz-light' : 'algoviz-dark',
)
editorRef.current = editor
monacoRef.current = monacoInstance

Expand Down Expand Up @@ -232,7 +256,11 @@ export default function CodePanel({
<LazyEditor
defaultLanguage="javascript"
value={code}
theme="vs-dark"
theme={
document.documentElement.dataset.theme === 'light'
? 'algoviz-light'
: 'algoviz-dark'
}
onMount={handleEditorDidMount}
loading={null}
options={{
Expand Down
42 changes: 31 additions & 11 deletions src/components/ComplexityChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ function parseTimeComplexity(description: string): Entry[] {
if (!blockMatch) return entries
const block = blockMatch[0]

const oRe = (prefix: string) =>
new RegExp(`${prefix}:\\s*(O\\((?:[^()]+|\\([^)]*\\))*\\))`, 'i')
const oRe = (prefix: string) => new RegExp(`${prefix}:\\s*(O\\((?:[^()]+|\\([^)]*\\))*\\))`, 'i')

const best = block.match(oRe(isSpanish ? 'Mejor' : 'Best'))
const avg = block.match(oRe(isSpanish ? 'Promedio' : 'Average'))
Expand All @@ -85,15 +84,28 @@ function parseTimeComplexity(description: string): Entry[] {
if (best || avg || worst) {
if (best) {
const k = normalizeToKey(best[1])
if (k) entries.push({ label: isSpanish ? 'Mejor' : 'Best', raw: best[1], key: k, color: '#34d399' })
if (k)
entries.push({
label: isSpanish ? 'Mejor' : 'Best',
raw: best[1],
key: k,
color: '#34d399',
})
}
if (avg) {
const k = normalizeToKey(avg[1])
if (k) entries.push({ label: isSpanish ? 'Prom' : 'Avg', raw: avg[1], key: k, color: '#fbbf24' })
if (k)
entries.push({ label: isSpanish ? 'Prom' : 'Avg', raw: avg[1], key: k, color: '#fbbf24' })
}
if (worst) {
const k = normalizeToKey(worst[1])
if (k) entries.push({ label: isSpanish ? 'Peor' : 'Worst', raw: worst[1], key: k, color: '#f87171' })
if (k)
entries.push({
label: isSpanish ? 'Peor' : 'Worst',
raw: worst[1],
key: k,
color: '#f87171',
})
}
} else {
const single = block.match(O_RE)
Expand Down Expand Up @@ -162,7 +174,13 @@ function resolveOverlaps(
return sorted
}

export default function ComplexityChart({ description, locale = 'en' }: { description: string; locale?: string }) {
export default function ComplexityChart({
description,
locale = 'en',
}: {
description: string
locale?: string
}) {
const entries = useMemo(() => parseTimeComplexity(description), [description])

if (entries.length === 0) return null
Expand All @@ -179,7 +197,12 @@ export default function ComplexityChart({ description, locale = 'en' }: { descri
const labels: { y: number; text: string; color: string; opacity: number }[] = []
for (const key of REFERENCE_KEYS) {
if (!highlightedKeys.has(key)) {
labels.push({ y: endY(COMPLEXITY_FNS[key]), text: key, color: '#fff', opacity: 0.18 })
labels.push({
y: endY(COMPLEXITY_FNS[key]),
text: key,
color: 'var(--foreground)',
opacity: 0.18,
})
}
}
for (const [key, group] of grouped) {
Expand Down Expand Up @@ -300,10 +323,7 @@ export default function ComplexityChart({ description, locale = 'en' }: { descri
<div className="flex flex-wrap gap-x-4 gap-y-1 mt-2">
{entries.map((e, i) => (
<div key={i} className="flex items-center gap-1.5">
<div
className="w-3 h-0.5 rounded-full shrink-0"
style={{ backgroundColor: e.color }}
/>
<div className="w-3 h-0.5 rounded-full shrink-0" style={{ backgroundColor: e.color }} />
<span className="text-[10px] text-neutral-500">
{e.label ? `${e.label}: ` : ''}
<span className="font-mono text-neutral-400">{e.raw}</span>
Expand Down
Loading