// OfflineBanner: a banner across the top of the page for as long as the browser
// is offline, saying what still works; it goes by itself when the connection is
// back. Nothing shows while online.
//
//   <OfflineBanner/>
//   <OfflineBanner title="No connection" text="You can keep writing: your changes are sent when it is back." sticky={false}/>
//
// title ("You are offline"), text ("Some things may not work until the
// connection is back."): what it says. sticky: fixed across the top of the
// window (true); false puts it in the flow of the page where it is written.
// dismissable: a close button that hides it for this outage (true); it shows
// again the next time the connection drops. reload: a "Try again" button that
// reloads the page (false). It is an alert, so screen readers hear it at once.
// on_change(online): inside one of your components, called with true or false
// as the connection comes and goes. (ConnectionStatus is the smaller cousin: a
// pill or a dot, and "Back online" when it returns.)

import ui/theme.qwe use ui_cls

let offline_banner_css = css`
.ui-offline-host { display: contents; }
.ui-offline { display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: var(--ui-warning-soft); color: var(--ui-fg);
  border-bottom: 1px solid color-mix(in srgb, var(--ui-warning) 35%, transparent); font: 14px/1.45 var(--ui-font); }
.ui-offline-sticky { position: fixed; top: 0; left: 0; right: 0; z-index: 60; box-shadow: var(--ui-shadow); animation: ui-offline-in .2s ease-out; }
.ui-offline-flow { border: 1px solid color-mix(in srgb, var(--ui-warning) 35%, transparent); border-radius: var(--ui-radius-sm); }
.ui-offline-icon { flex: none; width: 20px; height: 20px; color: var(--ui-warning); }
.ui-offline-body { flex: 1; min-width: 0; }
.ui-offline-title { font-weight: 600; margin-right: 6px; }
.ui-offline-text { color: color-mix(in srgb, var(--ui-fg) 80%, transparent); }
.ui-offline-btn { flex: none; height: 30px; padding: 0 12px; border: 1px solid color-mix(in srgb, var(--ui-warning) 45%, var(--ui-border));
  border-radius: var(--ui-radius-sm); background: var(--ui-surface); color: var(--ui-fg); font: 500 13px/1 var(--ui-font); cursor: pointer; }
.ui-offline-btn:hover { background: var(--ui-subtle); }
.ui-offline-x { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: var(--ui-radius-sm);
  background: transparent; color: inherit; font-size: 20px; line-height: 1; opacity: .7; cursor: pointer; }
.ui-offline-x:hover { opacity: 1; background: color-mix(in srgb, var(--ui-warning) 18%, transparent); }
.ui-offline-btn:focus-visible, .ui-offline-x:focus-visible { outline: none; box-shadow: var(--ui-focus); }
@keyframes ui-offline-in { from { transform: translateY(-100%); } }
@media (prefers-reduced-motion: reduce) { .ui-offline-sticky { animation: none; } }
`

component OfflineBanner(title: str = "You are offline", text: str = "Some things may not work until the connection is back.",
                        sticky: bool = true, dismissable: bool = true, reload: bool = false, on_change = null, class: str? = null) {
    style global offline_banner_css
    state online = true
    state closed = false
    <div class="ui-offline-host" @mount={(_el) => {
        online = js("navigator.onLine") != false
        let w = js("window")
        let went = (_e = null) => { online = false; closed = false; on_change && on_change(false) }
        let came = (_e = null) => { online = true; on_change && on_change(true) }
        w.addEventListener("offline", went)
        w.addEventListener("online", came)
        () => { w.removeEventListener("offline", went); w.removeEventListener("online", came) }
    }}>
        {!online && !closed && <div class={ui_cls(["ui-offline", sticky ? "ui-offline-sticky" : "ui-offline-flow", class])} role="alert">
            <svg.ui-offline-icon viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                 stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5a10 10 0 0 1 14 0M8.5 16a5 5 0 0 1 7 0M12 19.5h.01M3 3l18 18"/></svg>
            <div.ui-offline-body><span.ui-offline-title>{title}</span><span.ui-offline-text>{text}</span></div>
            {reload && <button.ui-offline-btn type="button" @click={() => { js("location.reload") }}>Try again</button>}
            {dismissable && <button.ui-offline-x type="button" aria-label="Dismiss" @click={() => { closed = true }}>×</button>}
        </div>}
    </div>
}
