Import source: app/src/widgets/GlossaryWidget
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
// Embeddable glossary definition card.
|
||||||
|
// Rendered in an iframe; sends postMessage resize to parent only when height changes.
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
import { TeknavData } from '../../teknav-data.js';
|
||||||
|
|
||||||
|
const SITE_URL = 'https://www.teknav.ir';
|
||||||
|
|
||||||
|
const light = {
|
||||||
|
card: { background: '#fff', border: '1px solid #E4DDD2', color: '#263238' },
|
||||||
|
header: { background: '#0C1E22' },
|
||||||
|
footer: { background: '#F8F5F0', borderTop: '1px solid #E4DDD2' },
|
||||||
|
summary: { color: '#263238' },
|
||||||
|
faqQ: { color: '#0F6B73' },
|
||||||
|
faqA: { color: '#5F6B6D' },
|
||||||
|
link: { color: '#0F6B73' },
|
||||||
|
};
|
||||||
|
const dark = {
|
||||||
|
card: { background: '#0C1E22', border: '1px solid rgba(255,255,255,0.1)', color: '#E4DDD2' },
|
||||||
|
header: { background: '#061014' },
|
||||||
|
footer: { background: '#061014', borderTop: '1px solid rgba(255,255,255,0.08)' },
|
||||||
|
summary: { color: 'rgba(255,255,255,0.85)' },
|
||||||
|
faqQ: { color: '#D49A2A' },
|
||||||
|
faqA: { color: 'rgba(255,255,255,0.6)' },
|
||||||
|
link: { color: '#D49A2A' },
|
||||||
|
};
|
||||||
|
|
||||||
|
function useTheme() {
|
||||||
|
const darkMq = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)');
|
||||||
|
return darkMq?.matches ? dark : light;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GlossaryWidget({ slug }) {
|
||||||
|
const term = (TeknavData.glossary ?? []).find((g) => g.slug === slug);
|
||||||
|
const theme = useTheme();
|
||||||
|
const lastHeight = useRef(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = document.getElementById('widget-root');
|
||||||
|
if (!el) return;
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const h = entry.target.offsetHeight || 0;
|
||||||
|
if (h !== lastHeight.current) {
|
||||||
|
lastHeight.current = h;
|
||||||
|
window.parent?.postMessage({ type: 'resize', height: h }, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.observe(el);
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const cardBase = {
|
||||||
|
fontFamily: '\'Vazirmatn\', Tahoma, sans-serif',
|
||||||
|
direction: 'rtl',
|
||||||
|
maxWidth: 480,
|
||||||
|
borderRadius: 12,
|
||||||
|
overflow: 'hidden',
|
||||||
|
...theme.card,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!term) {
|
||||||
|
return (
|
||||||
|
<div style={{ ...cardBase, padding: 20, fontSize: 14 }}>
|
||||||
|
اصطلاح یافت نشد.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={cardBase}>
|
||||||
|
<div style={{ ...theme.header, padding: '16px 20px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<span style={{ color: '#D49A2A', fontWeight: 700, fontSize: 16 }}>{term.term}</span>
|
||||||
|
<span style={{ color: 'rgba(255,255,255,0.5)', fontSize: 12 }}>{term.english}</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ padding: '16px 20px' }}>
|
||||||
|
<p style={{ fontSize: 14, lineHeight: 1.9, margin: 0, ...theme.summary }}>{term.summary}</p>
|
||||||
|
{(term.faqs || []).length > 0 && (
|
||||||
|
<div style={{ marginTop: 12 }}>
|
||||||
|
{term.faqs.map(([q, a], i) => (
|
||||||
|
<details key={i} style={{ marginBottom: 8, fontSize: 13 }}>
|
||||||
|
<summary style={{ fontWeight: 600, cursor: 'pointer', ...theme.faqQ }}>{q}</summary>
|
||||||
|
<p style={{ lineHeight: 1.8, marginTop: 6, paddingRight: 12, ...theme.faqA }}>{a}</p>
|
||||||
|
</details>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div style={{ padding: '10px 20px', ...theme.footer }}>
|
||||||
|
<a
|
||||||
|
href={`${SITE_URL}/glossary/${slug}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ fontSize: 12, textDecoration: 'none', fontWeight: 600, ...theme.link }}
|
||||||
|
>
|
||||||
|
منبع: تکناو ↗
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user