Rehbere mermaid şema desteği ve 4 yeni tercih dönemi yazısı ekle
Markdown'daki \`\`\`mermaid çitleri artık yazıyı parçalara bölüyor ve şemalar üründeki ortak el çizimi bileşeniyle (ElCizimiSema) çiziliyor; çitte "%% aria:" satırı zorunlu, "%% altyazi:" figcaption veriyor. Tercih dönemi aramalarına dayanan dört yeni yazı: merkezi yerleştirme algoritması, OBP hesabı, üniversite kayıt rehberi ve yerleşememe/istenmeyen bölüm karar ağacı — her biri risk renk dilinde birer şemayla. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
85
src/components/el-cizimi-sema.tsx
Normal file
85
src/components/el-cizimi-sema.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
"use client";
|
||||
|
||||
// Ürün genelindeki "el çizimi" mermaid şemalarının tek kaynağı: /meraklisina
|
||||
// hunisi de rehber yazılarındaki şemalar da bu bileşenle çizilir, böylece
|
||||
// görünüm (font, renk teması, çizgi titremesi) her yerde birebir aynı kalır.
|
||||
// Mermaid ağır bir paket olduğu için useEffect içinde dinamik import edilir;
|
||||
// sayfa paketine girmez.
|
||||
|
||||
import { useEffect, useId, useState } from "react";
|
||||
import localFont from "next/font/local";
|
||||
|
||||
// Şemanın "el çizimi" görünümüne uyan el yazısı fontu (Sweet Cucumber
|
||||
// Mocktail, Misti's Fonts). Türkçe glifler doğrulandı (ş, ğ, ı, İ… hepsi
|
||||
// var). DİKKAT: lisans "kişisel kullanım için ücretsiz" — canlıya çıkmadan
|
||||
// mistifonts.com/sweet-cucumber-mocktail adresinden ticari lisans alınmalı.
|
||||
const elYazisi = localFont({
|
||||
src: "../fonts/SweetCucumberMocktail.woff2",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export function ElCizimiSema({
|
||||
tanim,
|
||||
ariaLabel,
|
||||
figcaption,
|
||||
}: {
|
||||
/** Mermaid tanımı (flowchart vb.) */
|
||||
tanim: string;
|
||||
/** Şemanın tamamını anlatan erişilebilirlik metni */
|
||||
ariaLabel: string;
|
||||
figcaption?: React.ReactNode;
|
||||
}) {
|
||||
const [svg, setSvg] = useState<string | null>(null);
|
||||
// mermaid.render'ın istediği DOM id'si: useId'nin ":" karakterleri geçersiz
|
||||
const semaId = `sema-${useId().replace(/[^a-zA-Z0-9-]/g, "")}`;
|
||||
|
||||
useEffect(() => {
|
||||
let iptal = false;
|
||||
import("mermaid").then(async ({ default: mermaid }) => {
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
look: "handDrawn",
|
||||
handDrawnSeed: 7, // her render'da aynı çizgi titremesi (deterministik)
|
||||
theme: "base",
|
||||
fontFamily: `${elYazisi.style.fontFamily}, cursive`,
|
||||
themeVariables: {
|
||||
primaryColor: "#ffffff",
|
||||
primaryBorderColor: "#e2e8f0",
|
||||
primaryTextColor: "#0f172a",
|
||||
lineColor: "#94a3b8",
|
||||
edgeLabelBackground: "#ffffff",
|
||||
fontFamily: `${elYazisi.style.fontFamily}, cursive`,
|
||||
fontSize: "17px", // script fontun x-yüksekliği düşük; okunurluk için büyütüldü
|
||||
},
|
||||
});
|
||||
const sonuc = await mermaid.render(semaId, tanim);
|
||||
if (!iptal) setSvg(sonuc.svg);
|
||||
});
|
||||
return () => {
|
||||
iptal = true;
|
||||
};
|
||||
}, [semaId, tanim]);
|
||||
|
||||
return (
|
||||
<figure className="mt-6">
|
||||
{svg ? (
|
||||
<div
|
||||
role="img"
|
||||
aria-label={ariaLabel}
|
||||
className={`${elYazisi.className} overflow-x-auto [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full`}
|
||||
dangerouslySetInnerHTML={{ __html: svg }}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
aria-hidden
|
||||
className="h-96 animate-pulse rounded-xl bg-slate-100"
|
||||
/>
|
||||
)}
|
||||
{figcaption ? (
|
||||
<figcaption className="mt-3 text-xs text-slate-500">
|
||||
{figcaption}
|
||||
</figcaption>
|
||||
) : null}
|
||||
</figure>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user