Host fonts locally and guard FOUC
This commit is contained in:
+71
-1
@@ -1,4 +1,74 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('/fonts/inter/Inter-Regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('/fonts/inter/Inter-Medium.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('/fonts/inter/Inter-SemiBold.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('/fonts/inter/Inter-Bold.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url('/fonts/inter/Inter-ExtraBold.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2') format('woff2');
|
||||
}
|
||||
|
||||
body {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
:root[data-fonts='loading'] body {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
:root {
|
||||
/* ─── Colors (Dark Theme) ─────────────────────────────── */
|
||||
|
||||
@@ -1,12 +1,71 @@
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="dark" data-palette="classic">
|
||||
<html lang="en" data-theme="dark" data-palette="classic" data-fonts="loading">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/Inter-Regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/Inter-Medium.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/Inter-SemiBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/Inter-Bold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/Inter-ExtraBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<script>
|
||||
(function () {
|
||||
const doc = document.documentElement;
|
||||
if (!doc.dataset.fonts) {
|
||||
doc.dataset.fonts = 'loading';
|
||||
}
|
||||
try {
|
||||
const doc = document.documentElement;
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
const savedPalette = localStorage.getItem('palette');
|
||||
const prefersDark =
|
||||
@@ -19,6 +78,25 @@
|
||||
} catch (error) {
|
||||
// Ignore errors if storage or matchMedia is unavailable
|
||||
}
|
||||
const markFontsReady = () => {
|
||||
if (doc.dataset.fonts !== 'ready') {
|
||||
doc.dataset.fonts = 'ready';
|
||||
}
|
||||
};
|
||||
const fallback = setTimeout(markFontsReady, 3000);
|
||||
const resolveFonts = () => {
|
||||
clearTimeout(fallback);
|
||||
markFontsReady();
|
||||
};
|
||||
if (
|
||||
document.fonts &&
|
||||
document.fonts.ready &&
|
||||
typeof document.fonts.ready.then === 'function'
|
||||
) {
|
||||
document.fonts.ready.then(resolveFonts, resolveFonts);
|
||||
} else {
|
||||
resolveFonts();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
%sveltekit.head%
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
let val2 = '';
|
||||
let val3 = '';
|
||||
let activeField: 1 | 2 | 3 = 1;
|
||||
let swapSnapshot: { val1: string; val2: string } | null = null;
|
||||
let isSwapFlipped = false;
|
||||
|
||||
$: has3 = ['3col', '3col-mul'].includes(config.type) || !!config.labels.in3;
|
||||
$: isTextInput = ['base', 'text-bin', 'bin-text', 'dec-frac', 'dms-dd', 'dd-dms'].includes(config.type);
|
||||
@@ -27,13 +25,7 @@
|
||||
|
||||
let paramsInitializing = true;
|
||||
|
||||
function resetSwapState() {
|
||||
swapSnapshot = null;
|
||||
isSwapFlipped = false;
|
||||
}
|
||||
|
||||
function handleInput(source: 1 | 2 | 3) {
|
||||
resetSwapState();
|
||||
activeField = source;
|
||||
const result = solve(config, source, val1, val2, val3);
|
||||
if (source !== 1) val1 = result.val1;
|
||||
@@ -42,23 +34,14 @@
|
||||
}
|
||||
|
||||
function swap() {
|
||||
if (isSwapFlipped && swapSnapshot) {
|
||||
val1 = swapSnapshot.val1;
|
||||
val2 = swapSnapshot.val2;
|
||||
resetSwapState();
|
||||
} else {
|
||||
swapSnapshot = { val1, val2 };
|
||||
[val1, val2] = [val2, val1];
|
||||
isSwapFlipped = true;
|
||||
}
|
||||
activeField = activeField === 1 ? 2 : 1;
|
||||
const nextSource: 1 | 2 = activeField === 1 ? 2 : 1;
|
||||
handleInput(nextSource);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
val1 = '';
|
||||
val2 = '';
|
||||
val3 = '';
|
||||
resetSwapState();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user