Files
jrx/example/src/useHighlight.ts
Kenneth 968faac7f5 Fix counter, add input binding, syntax highlighting, dark mode
- Fix increment button: custom action handler instead of no-op setState
- Toggle visibility on Show/Hide Details button via $cond
- Input uses $bindState + useBoundProp for two-way binding
- Add shiki syntax highlighting (catppuccin-latte/mocha dual theme)
- Dark mode via prefers-color-scheme with CSS variables
- Layout: Live UI left, JSX Source + JSON Output stacked right

Co-authored-by: Ona <no-reply@ona.com>
2026-02-28 00:56:59 +00:00

41 lines
957 B
TypeScript

import { useState, useEffect } from "react";
import { createHighlighter, type Highlighter } from "shiki";
let highlighterPromise: Promise<Highlighter> | null = null;
function getHighlighter() {
if (!highlighterPromise) {
highlighterPromise = createHighlighter({
themes: ["catppuccin-mocha", "catppuccin-latte"],
langs: ["tsx", "json"],
});
}
return highlighterPromise;
}
export function useHighlight(code: string, lang: "tsx" | "json"): string {
const [html, setHtml] = useState("");
useEffect(() => {
if (!code) return;
let cancelled = false;
getHighlighter().then((highlighter) => {
if (cancelled) return;
setHtml(
highlighter.codeToHtml(code, {
lang,
themes: {
light: "catppuccin-latte",
dark: "catppuccin-mocha",
},
}),
);
});
return () => {
cancelled = true;
};
}, [code, lang]);
return html;
}