← back to Fleet Tv
public/widget/embed.html
190 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fleet TV — Embed Snippet</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #07080a; --fg: #e8e6e0; --dim: #6a6862; --accent: #c9a14b;
--pane: #11141a; --rule: rgba(255,255,255,0.08);
}
html, body { background: var(--bg); color: var(--fg); font-family: -apple-system, "Helvetica Neue", "Segoe UI", system-ui, sans-serif; min-height: 100vh; padding: 1.5rem; }
h1 { font-size: 0.95rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; margin-bottom: 0.4rem; }
.crumb { color: var(--dim); font-size: 0.78rem; letter-spacing: 0.16em; text-transform: uppercase; margin-bottom: 2rem; }
.crumb a { color: var(--dim); text-decoration: none; border-bottom: 1px solid transparent; }
.crumb a:hover { color: var(--fg); border-color: var(--rule); }
.layout { display: grid; grid-template-columns: 360px 1fr; gap: 2rem; max-width: 1100px; }
.preview {
background: var(--pane); border: 1px solid var(--rule); border-radius: 6px;
overflow: hidden;
aspect-ratio: 320/420;
}
.preview iframe { width: 100%; height: 100%; border: 0; display: block; }
.right { display: grid; gap: 1.25rem; }
.panel {
background: var(--pane); border: 1px solid var(--rule); border-radius: 6px;
overflow: hidden;
}
.panel header {
padding: 0.85rem 1.25rem;
border-bottom: 1px solid var(--rule);
font-size: 0.78rem; letter-spacing: 0.22em; text-transform: uppercase; font-weight: 500;
}
.panel .body { padding: 1rem 1.25rem; }
.panel .body p { color: var(--dim); font-size: 0.85rem; line-height: 1.5; margin-bottom: 0.5rem; }
pre {
background: #0a0c10;
border: 1px solid var(--rule);
border-radius: 4px;
padding: 0.85rem 1rem;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 0.78rem;
color: var(--fg);
overflow-x: auto;
white-space: pre;
line-height: 1.5;
}
.copy-btn {
margin-top: 0.5rem;
background: transparent; color: var(--accent);
border: 1px solid var(--accent); border-radius: 999px;
padding: 0.35rem 0.85rem; cursor: pointer;
font-family: inherit; font-size: 0.7rem; letter-spacing: 0.22em; text-transform: uppercase;
}
.copy-btn:hover { background: var(--accent); color: var(--bg); }
.copy-btn.copied { background: var(--accent); color: var(--bg); }
.controls {
display: grid; gap: 0.75rem;
}
.controls label {
display: grid; grid-template-columns: 110px 1fr; gap: 0.85rem; align-items: center;
font-size: 0.78rem; letter-spacing: 0.04em;
}
.controls input {
background: var(--bg); color: var(--fg); border: 1px solid var(--rule);
border-radius: 4px; padding: 0.45rem 0.65rem; font-family: inherit;
}
.controls input:focus { outline: none; border-color: var(--accent); }
.hint { color: var(--dim); font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase; }
</style>
</head>
<body>
<h1>Fleet TV · Embed Snippet</h1>
<div class="crumb"><a href="/">← wall</a> · <a href="/mosaic.html">mosaic</a> · <a href="/stats.html">stats</a> · <a href="/search.html">search</a> · widget</div>
<div class="layout">
<div>
<div class="preview">
<iframe id="preview-iframe" src="/widget/spotlight.html" referrerpolicy="no-referrer"></iframe>
</div>
<div class="hint" style="margin-top:0.75rem;">live preview — rotates every 30s</div>
</div>
<div class="right">
<div class="panel">
<header>customize</header>
<div class="body controls">
<label>width <input id="opt-w" type="text" value="320"></label>
<label>height <input id="opt-h" type="text" value="420"></label>
<label>rotate (ms) <input id="opt-r" type="text" value="30000" placeholder="≥ 5000"></label>
<label>host <input id="opt-host" type="text" value=""></label>
<p class="hint" style="margin-top:0.25rem;">host = the URL where Fleet TV is reachable. For a local-only widget keep it as 127.0.0.1; for embedding on a public site, expose Fleet TV through your tailnet or a proxy.</p>
</div>
</div>
<div class="panel">
<header>iframe snippet (paste anywhere)</header>
<div class="body">
<pre id="snippet-iframe">—</pre>
<button class="copy-btn" data-target="snippet-iframe">copy</button>
</div>
</div>
<div class="panel">
<header>shopify section / liquid</header>
<div class="body">
<pre id="snippet-liquid">—</pre>
<button class="copy-btn" data-target="snippet-liquid">copy</button>
<p class="hint" style="margin-top:0.5rem;">drop into a Liquid section as a "Featured Cross-Fleet" block.</p>
</div>
</div>
<div class="panel">
<header>raw JSON endpoint</header>
<div class="body">
<pre id="snippet-api">—</pre>
<button class="copy-btn" data-target="snippet-api">copy</button>
<p class="hint" style="margin-top:0.5rem;">use this if you want a fully custom card. <code>?count=N</code> returns up to 20 random products.</p>
</div>
</div>
</div>
</div>
<script>
(() => {
const $ = (id) => document.getElementById(id);
$('opt-host').value = location.origin;
function update() {
const w = ($('opt-w').value || '320').trim();
const h = ($('opt-h').value || '420').trim();
const r = ($('opt-r').value || '30000').trim();
const host = ($('opt-host').value || location.origin).trim().replace(/\/$/, '');
const src = `${host}/widget/spotlight.html?rotate=${r}`;
$('snippet-iframe').textContent =
`<iframe src="${src}"
width="${w}" height="${h}"
style="border:0;border-radius:6px;overflow:hidden;"
loading="lazy" referrerpolicy="no-referrer"
title="Fleet Spotlight"></iframe>`;
$('snippet-liquid').textContent =
`{%- comment -%} Fleet TV cross-fleet spotlight {%- endcomment -%}
<div class="fleet-spotlight" style="max-width:${w}px;margin:1.5rem auto;">
<iframe src="${src}"
width="${w}" height="${h}"
style="border:0;border-radius:6px;overflow:hidden;display:block;"
loading="lazy" referrerpolicy="no-referrer"
title="Featured wallcovering"></iframe>
</div>`;
$('snippet-api').textContent = `${host}/api/random?count=1`;
$('preview-iframe').src = `/widget/spotlight.html?rotate=${r}`;
}
['opt-w','opt-h','opt-r','opt-host'].forEach(id => $(id).addEventListener('input', update));
document.querySelectorAll('.copy-btn').forEach(btn => {
btn.addEventListener('click', async () => {
const id = btn.dataset.target;
const text = $(id).textContent;
try {
await navigator.clipboard.writeText(text);
const original = btn.textContent;
btn.classList.add('copied');
btn.textContent = 'copied ✓';
setTimeout(() => { btn.classList.remove('copied'); btn.textContent = original; }, 1500);
} catch (e) { alert('clipboard blocked — select & copy manually'); }
});
});
update();
})();
</script>
</body>
</html>