mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 21:46:49 +00:00
0a5c8be83d
- Wiki pages (sync to the GitHub wiki on push to main): Plugins overview + trust model, Plugin Development (SDK, definePlugin, ctx, routes/jobs, the client bridge, testing with the mock host), Plugin Permissions reference, and Publishing (registry PR + CI gates + provenance). Linked from the sidebar. - Reference plugin plugin-sdk/examples/trip-countdown: a complete, minimal- permission widget (reads trip data through ctx, renders in the sandboxed iframe via the bridge, filled-in README). Validated in the SDK test suite so it passes the exact gate authors face.
63 lines
2.4 KiB
HTML
63 lines
2.4 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>Trip Countdown</title>
|
|
<style>
|
|
:root { color-scheme: light dark; }
|
|
body { margin: 0; font: 14px system-ui, sans-serif; display: grid; place-items: center; height: 100vh;
|
|
background: transparent; color: #111827; }
|
|
body[data-theme="dark"] { color: #e5e7eb; }
|
|
.card { text-align: center; padding: 16px; }
|
|
.days { font-size: 40px; font-weight: 800; letter-spacing: -0.02em; }
|
|
.label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.6; margin-top: 2px; }
|
|
.name { margin-top: 6px; opacity: 0.85; }
|
|
.empty { opacity: 0.6; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="card" id="root"><span class="empty">Loading…</span></div>
|
|
<script>
|
|
var ctx = null
|
|
var reqSeq = 0
|
|
|
|
function send(msg) { window.parent.postMessage(msg, '*') }
|
|
|
|
function render(data) {
|
|
var root = document.getElementById('root')
|
|
if (!data || !data.trip) { root.innerHTML = '<span class="empty">No upcoming trip</span>'; return }
|
|
var d = data.trip.days
|
|
root.innerHTML = d == null
|
|
? '<div class="name">' + escapeHtml(data.trip.name) + '</div><div class="label">in progress</div>'
|
|
: '<div class="days">' + d + '</div><div class="label">days to go</div><div class="name">' + escapeHtml(data.trip.name) + '</div>'
|
|
}
|
|
|
|
function escapeHtml(s) { return String(s).replace(/[&<>"]/g, function (c) {
|
|
return ({ '&': '&', '<': '<', '>': '>', '"': '"' })[c] }) }
|
|
|
|
function load() {
|
|
var id = 'r' + (++reqSeq)
|
|
send({ type: 'trek:invoke', requestId: id, sub: '/next?tripId=' + (ctx && ctx.tripId ? ctx.tripId : ''), method: 'GET' })
|
|
window._pending = id
|
|
}
|
|
|
|
window.addEventListener('message', function (e) {
|
|
var m = e.data
|
|
if (!m || typeof m !== 'object') return
|
|
if (m.type === 'trek:context') {
|
|
ctx = m
|
|
document.body.dataset.theme = m.theme
|
|
load()
|
|
} else if (m.type === 'trek:response' && m.requestId === window._pending) {
|
|
render(m.data)
|
|
} else if (m.type === 'trek:error' && m.requestId === window._pending) {
|
|
document.getElementById('root').innerHTML = '<span class="empty">Unavailable</span>'
|
|
}
|
|
})
|
|
|
|
// Ask TREK for context (theme, current trip id) — it replies with trek:context.
|
|
send({ type: 'trek:ready' })
|
|
</script>
|
|
</body>
|
|
</html>
|