@alejoamiras/presto-banners 0.0.0-bootstrap.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -0
- package/dist/element.d.ts +43 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +281 -0
- package/dist/element.js.map +1 -0
- package/dist/fonts.d.ts +8 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +17 -0
- package/dist/fonts.js.map +1 -0
- package/dist/icons.d.ts +9 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +15 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/persistence.d.ts +10 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/persistence.js +53 -0
- package/dist/persistence.js.map +1 -0
- package/dist/platform.d.ts +8 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +17 -0
- package/dist/platform.js.map +1 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +5 -0
- package/dist/register.js.map +1 -0
- package/dist/render.d.ts +16 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +126 -0
- package/dist/render.js.map +1 -0
- package/dist/status.d.ts +13 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +27 -0
- package/dist/status.js.map +1 -0
- package/dist/strings.d.ts +62 -0
- package/dist/strings.d.ts.map +1 -0
- package/dist/strings.js +118 -0
- package/dist/strings.js.map +1 -0
- package/dist/styles.d.ts +7 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +184 -0
- package/dist/styles.js.map +1 -0
- package/dist/types.d.ts +42 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +29 -0
- package/dist/types.js.map +1 -0
- package/package.json +26 -5
- package/src/element.ts +290 -0
- package/src/fonts.ts +18 -0
- package/src/icons.ts +25 -0
- package/src/index.ts +18 -0
- package/src/persistence.ts +53 -0
- package/src/platform.ts +14 -0
- package/src/register.ts +6 -0
- package/src/render.ts +159 -0
- package/src/status.ts +28 -0
- package/src/strings.ts +137 -0
- package/src/styles.ts +186 -0
- package/src/types.ts +72 -0
- package/index.js +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @alejoamiras/presto-banners
|
|
2
|
+
|
|
3
|
+
Install banners for dApps that integrate Presto: a zero-dependency `<presto-banner>` web component
|
|
4
|
+
rendered in Shadow DOM with Presto's own tokens, type and motion, so the "get Presto" moment looks
|
|
5
|
+
the same on every site. Six surfaces, one state model, keyed to the SDK's `PrestoStatus`.
|
|
6
|
+
|
|
7
|
+
| Variant | Shape | Shows for |
|
|
8
|
+
|-------------|----------------------------------------|----------------------------------------|
|
|
9
|
+
| `ribbon` | 44px full-width strip | every state (install, fix-it, connected) |
|
|
10
|
+
| `billboard` | inline solid-indigo bar | `offline` |
|
|
11
|
+
| `dock` | floating bottom-right, fixed | `offline` (fire it when a proof starts in-browser) |
|
|
12
|
+
| `card` | 300px sidebar card with illustration | `offline` |
|
|
13
|
+
| `tile` | 300×300 poster | static; ignores state |
|
|
14
|
+
| `sheet` | centred modal over a backdrop, fixed | `offline`, once before the first proof |
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<script type="module">
|
|
20
|
+
import { PrestoProver } from "@alejoamiras/presto";
|
|
21
|
+
import "@alejoamiras/presto-banners/register"; // defines <presto-banner>
|
|
22
|
+
|
|
23
|
+
const prover = new PrestoProver();
|
|
24
|
+
const banner = document.querySelector("presto-banner");
|
|
25
|
+
banner.status = await prover.checkPrestoStatus(); // maps to a banner state
|
|
26
|
+
banner.addEventListener("presto-banner:retry", async () => {
|
|
27
|
+
banner.status = await prover.checkPrestoStatus({ forceRefresh: true });
|
|
28
|
+
});
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<presto-banner variant="ribbon"></presto-banner>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The banner renders **nothing until `state` is set** (the static Tile is the one exception), so an
|
|
35
|
+
installed user never sees a flash of the install pitch. Set it from the status check, not on page load.
|
|
36
|
+
|
|
37
|
+
### Attributes
|
|
38
|
+
|
|
39
|
+
| Attribute | Values | Default |
|
|
40
|
+
|----------------|-----------------------------------------------------------|---------------------|
|
|
41
|
+
| `variant` | `ribbon` `billboard` `dock` `card` `tile` `sheet` | `ribbon` |
|
|
42
|
+
| `state` | `offline` `permission-blocked` `secure-connection-unavailable` `version-mismatch` `error` `downloading` `available` | unset (hidden) |
|
|
43
|
+
| `theme` | `auto` `light` `dark` | `auto` |
|
|
44
|
+
| `href` | install link | `https://presto.build` |
|
|
45
|
+
| `persist-key` | `localStorage` prefix for dismissals | `presto:banner` |
|
|
46
|
+
| `dismiss-days` | how long a dismissal lasts | `7` |
|
|
47
|
+
| `fonts` | `google` (links Bricolage Grotesque + Figtree once) or `none` | `google` |
|
|
48
|
+
| `os` | `macOS` `Windows` `Linux`, forces the Sheet's CTA label | detected from the user agent |
|
|
49
|
+
|
|
50
|
+
Set attributes with `setAttribute()`. Two properties exist on top: `banner.state` (read/write,
|
|
51
|
+
reflects the attribute) and `banner.status = prestoStatus` (write-only, runs `stateFromStatus`).
|
|
52
|
+
`variant`, `href`, `platform`, `dismissDays` and `persistKey` are read-only getters. Changing `href`
|
|
53
|
+
or `os` patches the CTA in place; the Sheet's checkbox and focus survive.
|
|
54
|
+
|
|
55
|
+
### States
|
|
56
|
+
|
|
57
|
+
`available` never paints. If the banner was showing, it plays the **detected morph** (400ms
|
|
58
|
+
crossfade to "Presto connected ✦", 1600ms hold, 350ms collapse) and hides; otherwise it stays
|
|
59
|
+
hidden. `permission-blocked`, `secure-connection-unavailable`, `version-mismatch` and `error` render
|
|
60
|
+
a gold "fix it" strip with a Retry button (Ribbon only); `downloading` shows a breathing dot.
|
|
61
|
+
|
|
62
|
+
`stateFromStatus` knows one SDK subtlety: under the browser's HTTPS-only default an *uninstalled*
|
|
63
|
+
Presto reports `secure-connection-unavailable` with diagnosis `unconfirmed`, not `offline`. That pair
|
|
64
|
+
maps to `offline` (the install pitch); the other diagnoses mean Presto is there and HTTPS needs fixing.
|
|
65
|
+
|
|
66
|
+
### Events
|
|
67
|
+
|
|
68
|
+
All bubble and are `composed`; `detail` carries `{ variant, state, href }`.
|
|
69
|
+
|
|
70
|
+
- `presto-banner:cta`: install link activated. `preventDefault()` to stop navigation.
|
|
71
|
+
- `presto-banner:retry`: re-run `checkPrestoStatus()` and set `status` again.
|
|
72
|
+
- `presto-banner:dismiss`: `detail.forever` is `true` from the Sheet's "Don't ask again".
|
|
73
|
+
- `presto-banner:collapsed`: the detected morph finished.
|
|
74
|
+
|
|
75
|
+
### Placement rules
|
|
76
|
+
|
|
77
|
+
- One status-driven surface per page: Ribbon *or* Billboard *or* Card.
|
|
78
|
+
- Dock only after a proof actually starts in the browser. Sheet once before the first proof.
|
|
79
|
+
- Dismissals persist per variant **and state**, so dismissing the pitch never silences a later
|
|
80
|
+
"browser blocked local access".
|
|
81
|
+
- Every status-driven surface has a dismiss; the Sheet is a native modal `<dialog>` whose decline
|
|
82
|
+
is "Continue in browser" and whose Escape dismisses. The static Tile has no dismiss. Nothing blocks.
|
|
83
|
+
|
|
84
|
+
### Theming
|
|
85
|
+
|
|
86
|
+
Override the `--pb-*` custom properties on the element from the host page:
|
|
87
|
+
|
|
88
|
+
```css
|
|
89
|
+
presto-banner { --pb-accent: #3b4fe0; --pb-surface: #fff; }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`theme="auto"` follows `prefers-color-scheme`. Solid surfaces (Billboard, Tile) keep the indigo in
|
|
93
|
+
both themes by design.
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bun test # bun:test + happy-dom
|
|
99
|
+
bun run test:lint
|
|
100
|
+
bun run dev # demo page for manual review
|
|
101
|
+
bun run build # tsc → dist (publish artifact)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`exports` point at TypeScript source for workspace consumers, like the SDK; the published package
|
|
105
|
+
(`npm install @alejoamiras/presto-banners`) maps `.` and `./register` to `dist/` with `types` +
|
|
106
|
+
`default` conditions and carries no dependencies. Releases go through `release-sdk.yml`
|
|
107
|
+
(`packages=presto-banners`) with npm provenance; see `docs/RELEASE_RUNBOOK.md`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type BannerPlatform, type BannerState, type BannerVariant, type PrestoStatusLike } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_HREF = "https://presto.build";
|
|
3
|
+
export declare const DEFAULT_PERSIST_KEY = "presto:banner";
|
|
4
|
+
declare const Base: typeof HTMLElement;
|
|
5
|
+
/**
|
|
6
|
+
* `<presto-banner variant state theme href persist-key fonts os dismiss-days>`.
|
|
7
|
+
*
|
|
8
|
+
* Renders nothing until `state` is set (Tile excepted: it is static placement), so an installed user
|
|
9
|
+
* never sees a flash of the install pitch. `available` never paints: if the banner was showing, it
|
|
10
|
+
* plays the detected morph (crossfade → hold → collapse) and hides; otherwise it stays hidden.
|
|
11
|
+
* Dismissals persist per variant and state under `persist-key` for `dismiss-days` (default 7), or
|
|
12
|
+
* forever from the Sheet's checkbox.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PrestoBanner extends Base {
|
|
15
|
+
#private;
|
|
16
|
+
static readonly tagName = "presto-banner";
|
|
17
|
+
/** `dismiss-days` is read at dismiss time and needs no render work. */
|
|
18
|
+
static readonly observedAttributes: string[];
|
|
19
|
+
/** Detected-morph phase durations in ms. Overridable (tests shorten them). */
|
|
20
|
+
static timings: {
|
|
21
|
+
morph: number;
|
|
22
|
+
hold: number;
|
|
23
|
+
collapse: number;
|
|
24
|
+
};
|
|
25
|
+
constructor();
|
|
26
|
+
get variant(): BannerVariant;
|
|
27
|
+
get state(): BannerState | null;
|
|
28
|
+
set state(value: BannerState | null);
|
|
29
|
+
/** Convenience: `banner.status = await prover.checkPrestoStatus()`. */
|
|
30
|
+
set status(status: PrestoStatusLike);
|
|
31
|
+
get href(): string;
|
|
32
|
+
get platform(): BannerPlatform | null;
|
|
33
|
+
get dismissDays(): number;
|
|
34
|
+
/** Storage key for the current variant + state; the pitch and each warn state dismiss separately. */
|
|
35
|
+
get persistKey(): string;
|
|
36
|
+
connectedCallback(): void;
|
|
37
|
+
disconnectedCallback(): void;
|
|
38
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
39
|
+
}
|
|
40
|
+
/** Register the element (idempotent, no-op without `customElements`). Returns whether it is defined. */
|
|
41
|
+
export declare function definePrestoBanner(tagName?: string): boolean;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,YAAY,yBAAyB,CAAC;AACnD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAOnD,QAAA,MAAM,IAAI,EAAoE,OAAO,WAAW,CAAC;AAajG;;;;;;;;GAQG;AACH,qBAAa,YAAa,SAAQ,IAAI;;IACpC,MAAM,CAAC,QAAQ,CAAC,OAAO,mBAAmB;IAC1C,uEAAuE;IACvE,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAA8D;IAChG,8EAA8E;IAC9E,MAAM,CAAC,OAAO;QAAK,KAAK;QAAO,IAAI;QAAQ,QAAQ;MAAQ;IAY3D,cAKC;IAED,IAAI,OAAO,IAAI,aAAa,CAG3B;IAED,IAAI,KAAK,IAAI,WAAW,GAAG,IAAI,CAG9B;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,EAGlC;IAED,uEAAuE;IACvE,IAAI,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAElC;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,QAAQ,IAAI,cAAc,GAAG,IAAI,CAIpC;IAED,IAAI,WAAW,IAAI,MAAM,CAGxB;IAED,qGAAqG;IACrG,IAAI,UAAU,IAAI,MAAM,CAGvB;IAED,iBAAiB,IAAI,IAAI,CAIxB;IAED,oBAAoB,IAAI,IAAI,CAI3B;IAED,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAM7F;CAuJF;AAED,wGAAwG;AACxG,wBAAgB,kBAAkB,CAAC,OAAO,SAAuB,GAAG,OAAO,CAI1E"}
|
package/dist/element.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { ensureFonts } from "./fonts.js";
|
|
2
|
+
import { dismiss, isDismissed } from "./persistence.js";
|
|
3
|
+
import { detectPlatform } from "./platform.js";
|
|
4
|
+
import { detectedContent, render } from "./render.js";
|
|
5
|
+
import { stateFromStatus } from "./status.js";
|
|
6
|
+
import { VARIANT_COPY, VARIANT_STATES } from "./strings.js";
|
|
7
|
+
import { STYLES } from "./styles.js";
|
|
8
|
+
import { BANNER_EVENTS, BANNER_STATES, BANNER_VARIANTS, } from "./types.js";
|
|
9
|
+
export const DEFAULT_HREF = "https://presto.build";
|
|
10
|
+
export const DEFAULT_PERSIST_KEY = "presto:banner";
|
|
11
|
+
const PLATFORMS = ["macOS", "Windows", "Linux"];
|
|
12
|
+
/** Attributes that only touch the CTA; patched in place so a re-render can't reset the Sheet. */
|
|
13
|
+
const CTA_ATTRIBUTES = new Set(["href", "os"]);
|
|
14
|
+
// Importing this module must be safe where there is no DOM (SSR, Node scripts): the class is only
|
|
15
|
+
// ever constructed by `customElements`, which those runtimes don't have either.
|
|
16
|
+
const Base = (typeof HTMLElement === "undefined" ? class {
|
|
17
|
+
} : HTMLElement);
|
|
18
|
+
/** Only http(s) install links; anything else (javascript:, data:, garbage) falls back to the default. */
|
|
19
|
+
function safeHref(raw, base) {
|
|
20
|
+
if (!raw)
|
|
21
|
+
return DEFAULT_HREF;
|
|
22
|
+
try {
|
|
23
|
+
const url = new URL(raw, base);
|
|
24
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : DEFAULT_HREF;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return DEFAULT_HREF;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* `<presto-banner variant state theme href persist-key fonts os dismiss-days>`.
|
|
32
|
+
*
|
|
33
|
+
* Renders nothing until `state` is set (Tile excepted: it is static placement), so an installed user
|
|
34
|
+
* never sees a flash of the install pitch. `available` never paints: if the banner was showing, it
|
|
35
|
+
* plays the detected morph (crossfade → hold → collapse) and hides; otherwise it stays hidden.
|
|
36
|
+
* Dismissals persist per variant and state under `persist-key` for `dismiss-days` (default 7), or
|
|
37
|
+
* forever from the Sheet's checkbox.
|
|
38
|
+
*/
|
|
39
|
+
export class PrestoBanner extends Base {
|
|
40
|
+
static tagName = "presto-banner";
|
|
41
|
+
/** `dismiss-days` is read at dismiss time and needs no render work. */
|
|
42
|
+
static observedAttributes = ["variant", "state", "href", "persist-key", "fonts", "os"];
|
|
43
|
+
/** Detected-morph phase durations in ms. Overridable (tests shorten them). */
|
|
44
|
+
static timings = { morph: 400, hold: 1600, collapse: 350 };
|
|
45
|
+
#shadow;
|
|
46
|
+
#timers = [];
|
|
47
|
+
/** Set by `connectedCallback`; upgrades of already-connected markup queue attribute callbacks first. */
|
|
48
|
+
#connected = false;
|
|
49
|
+
/** Currently painted. Drives the entrance animation and whether `available` morphs or just hides. */
|
|
50
|
+
#shown = false;
|
|
51
|
+
/** Hid itself after a morph; a later non-`available` state re-arms it. */
|
|
52
|
+
#collapsed = false;
|
|
53
|
+
#morphing = false;
|
|
54
|
+
constructor() {
|
|
55
|
+
super();
|
|
56
|
+
this.#shadow = this.attachShadow({ mode: "open" });
|
|
57
|
+
this.#shadow.addEventListener("click", (event) => this.#onClick(event));
|
|
58
|
+
this.addEventListener("keydown", (event) => this.#onKeydown(event));
|
|
59
|
+
}
|
|
60
|
+
get variant() {
|
|
61
|
+
const raw = this.getAttribute("variant");
|
|
62
|
+
return raw && BANNER_VARIANTS.includes(raw) ? raw : "ribbon";
|
|
63
|
+
}
|
|
64
|
+
get state() {
|
|
65
|
+
const raw = this.getAttribute("state");
|
|
66
|
+
return raw && BANNER_STATES.includes(raw) ? raw : null;
|
|
67
|
+
}
|
|
68
|
+
set state(value) {
|
|
69
|
+
if (value === null)
|
|
70
|
+
this.removeAttribute("state");
|
|
71
|
+
else
|
|
72
|
+
this.setAttribute("state", value);
|
|
73
|
+
}
|
|
74
|
+
/** Convenience: `banner.status = await prover.checkPrestoStatus()`. */
|
|
75
|
+
set status(status) {
|
|
76
|
+
this.state = stateFromStatus(status);
|
|
77
|
+
}
|
|
78
|
+
get href() {
|
|
79
|
+
return safeHref(this.getAttribute("href"), this.ownerDocument?.baseURI);
|
|
80
|
+
}
|
|
81
|
+
get platform() {
|
|
82
|
+
const forced = this.getAttribute("os");
|
|
83
|
+
if (forced && PLATFORMS.includes(forced))
|
|
84
|
+
return forced;
|
|
85
|
+
return typeof navigator === "undefined" ? null : detectPlatform(navigator.userAgent);
|
|
86
|
+
}
|
|
87
|
+
get dismissDays() {
|
|
88
|
+
const parsed = Number(this.getAttribute("dismiss-days"));
|
|
89
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 7;
|
|
90
|
+
}
|
|
91
|
+
/** Storage key for the current variant + state; the pitch and each warn state dismiss separately. */
|
|
92
|
+
get persistKey() {
|
|
93
|
+
const base = this.getAttribute("persist-key") || DEFAULT_PERSIST_KEY;
|
|
94
|
+
return `${base}:${this.variant}:${this.state ?? "none"}`;
|
|
95
|
+
}
|
|
96
|
+
connectedCallback() {
|
|
97
|
+
this.#connected = true;
|
|
98
|
+
ensureFonts(this.getAttribute("fonts"));
|
|
99
|
+
this.#update();
|
|
100
|
+
}
|
|
101
|
+
disconnectedCallback() {
|
|
102
|
+
this.#connected = false;
|
|
103
|
+
this.#clearTimers();
|
|
104
|
+
this.#morphing = false;
|
|
105
|
+
}
|
|
106
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
107
|
+
if (!this.#connected || oldValue === newValue)
|
|
108
|
+
return;
|
|
109
|
+
if (name === "fonts")
|
|
110
|
+
ensureFonts(newValue);
|
|
111
|
+
else if (CTA_ATTRIBUTES.has(name) && this.#shown)
|
|
112
|
+
this.#patchCta();
|
|
113
|
+
else if (name === "persist-key" && this.#shown && !isDismissed(this.persistKey))
|
|
114
|
+
return;
|
|
115
|
+
else
|
|
116
|
+
this.#update();
|
|
117
|
+
}
|
|
118
|
+
#update() {
|
|
119
|
+
const { variant, state } = this;
|
|
120
|
+
if (state !== "available")
|
|
121
|
+
this.#collapsed = false;
|
|
122
|
+
if (variant === "tile") {
|
|
123
|
+
this.#paint(variant, state ?? "offline");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (state === "available") {
|
|
127
|
+
if (this.#shown && !this.#collapsed)
|
|
128
|
+
this.#morph();
|
|
129
|
+
else
|
|
130
|
+
this.#hide();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const handled = state !== null && VARIANT_STATES[variant].includes(state);
|
|
134
|
+
if (!handled || this.#collapsed || isDismissed(this.persistKey)) {
|
|
135
|
+
this.#hide();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this.#paint(variant, state);
|
|
139
|
+
}
|
|
140
|
+
#paint(variant, state) {
|
|
141
|
+
this.#clearTimers();
|
|
142
|
+
this.#morphing = false;
|
|
143
|
+
const enter = !this.#shown;
|
|
144
|
+
const { href, platform } = this;
|
|
145
|
+
this.#shadow.innerHTML = `<style>${STYLES}</style>${render({ variant, state, href, platform, enter })}`;
|
|
146
|
+
this.hidden = false;
|
|
147
|
+
this.#shown = true;
|
|
148
|
+
if (variant === "sheet")
|
|
149
|
+
this.#openSheet(enter);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Native modal: focus containment, inert background, focus restore on close. `cancel` (Escape) and
|
|
153
|
+
* `close` don't bubble, so they are wired on the dialog itself; the dialog is recreated per paint.
|
|
154
|
+
*/
|
|
155
|
+
#openSheet(enter) {
|
|
156
|
+
const dialog = this.#shadow.querySelector("dialog");
|
|
157
|
+
if (!dialog || dialog.open)
|
|
158
|
+
return;
|
|
159
|
+
// `close` is queued, so a torn-down dialog's event can land after a newer paint: only a dialog
|
|
160
|
+
// that is still in the tree speaks for the banner.
|
|
161
|
+
const live = () => this.#shown && dialog.isConnected;
|
|
162
|
+
dialog.addEventListener("cancel", (event) => {
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
if (live())
|
|
165
|
+
this.#dismiss();
|
|
166
|
+
});
|
|
167
|
+
// Anything else that closes it (a form method=dialog, devtools) is a dismissal too.
|
|
168
|
+
dialog.addEventListener("close", () => {
|
|
169
|
+
if (live())
|
|
170
|
+
this.#dismiss();
|
|
171
|
+
});
|
|
172
|
+
if (typeof dialog.showModal === "function")
|
|
173
|
+
dialog.showModal();
|
|
174
|
+
else
|
|
175
|
+
dialog.setAttribute("open", "");
|
|
176
|
+
if (enter)
|
|
177
|
+
this.#shadow.querySelector('[data-action="cta"]')?.focus();
|
|
178
|
+
}
|
|
179
|
+
#patchCta() {
|
|
180
|
+
const cta = this.#shadow.querySelector('[data-action="cta"]');
|
|
181
|
+
if (!cta)
|
|
182
|
+
return;
|
|
183
|
+
cta.setAttribute("href", this.href);
|
|
184
|
+
if (this.variant !== "sheet")
|
|
185
|
+
return;
|
|
186
|
+
const { cta: plain, ctaFor } = VARIANT_COPY.sheet;
|
|
187
|
+
const { platform } = this;
|
|
188
|
+
cta.textContent = platform ? `${ctaFor} ${platform}` : plain;
|
|
189
|
+
}
|
|
190
|
+
#hide() {
|
|
191
|
+
this.#clearTimers();
|
|
192
|
+
this.#morphing = false;
|
|
193
|
+
// Flags first: the dialog's `close` listener treats a close while shown as a user dismissal.
|
|
194
|
+
this.#shown = false;
|
|
195
|
+
this.hidden = true;
|
|
196
|
+
const dialog = this.#shadow.querySelector("dialog");
|
|
197
|
+
if (dialog?.open)
|
|
198
|
+
dialog.close();
|
|
199
|
+
this.#shadow.innerHTML = "";
|
|
200
|
+
}
|
|
201
|
+
#morph() {
|
|
202
|
+
if (this.#morphing)
|
|
203
|
+
return;
|
|
204
|
+
const root = this.#shadow.querySelector(".root");
|
|
205
|
+
const overlay = root?.querySelector(".detected");
|
|
206
|
+
if (!root || !overlay) {
|
|
207
|
+
this.#hide();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.#morphing = true;
|
|
211
|
+
const { morph, hold, collapse } = PrestoBanner.timings;
|
|
212
|
+
overlay.innerHTML = detectedContent();
|
|
213
|
+
// The surface (not the dialog, whose live region must stay exposed) goes inert; the entrance
|
|
214
|
+
// keyframes are dropped so their filled opacity can't override the collapse.
|
|
215
|
+
root.querySelector("[data-surface]")?.setAttribute("inert", "");
|
|
216
|
+
root.firstElementChild?.classList.remove("is-enter");
|
|
217
|
+
root.setAttribute("data-phase", "detected");
|
|
218
|
+
this.#after(morph + hold, () => root.setAttribute("data-phase", "gone"));
|
|
219
|
+
this.#after(morph + hold + collapse, () => {
|
|
220
|
+
this.#collapsed = true;
|
|
221
|
+
this.#hide();
|
|
222
|
+
this.#emit(BANNER_EVENTS.collapsed);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
#after(ms, fn) {
|
|
226
|
+
this.#timers.push(setTimeout(fn, ms));
|
|
227
|
+
}
|
|
228
|
+
#clearTimers() {
|
|
229
|
+
for (const timer of this.#timers)
|
|
230
|
+
clearTimeout(timer);
|
|
231
|
+
this.#timers = [];
|
|
232
|
+
}
|
|
233
|
+
#onClick(event) {
|
|
234
|
+
const control = event.target?.closest?.("[data-action]");
|
|
235
|
+
if (!control)
|
|
236
|
+
return;
|
|
237
|
+
switch (control.getAttribute("data-action")) {
|
|
238
|
+
case "cta":
|
|
239
|
+
if (!this.#emit(BANNER_EVENTS.cta, {}, true))
|
|
240
|
+
event.preventDefault();
|
|
241
|
+
break;
|
|
242
|
+
case "retry":
|
|
243
|
+
this.#emit(BANNER_EVENTS.retry);
|
|
244
|
+
break;
|
|
245
|
+
case "dismiss":
|
|
246
|
+
this.#dismiss();
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
#onKeydown(event) {
|
|
251
|
+
if (event.key === "Escape" && this.variant === "sheet" && this.#shown)
|
|
252
|
+
this.#dismiss();
|
|
253
|
+
}
|
|
254
|
+
/** Hide before emitting: a listener that sets a new state must not be undone by the teardown. */
|
|
255
|
+
#dismiss() {
|
|
256
|
+
const never = this.#shadow.querySelector('[data-role="never"]');
|
|
257
|
+
const forever = never?.checked === true;
|
|
258
|
+
dismiss(this.persistKey, { days: this.dismissDays, forever });
|
|
259
|
+
this.#hide();
|
|
260
|
+
this.#emit(BANNER_EVENTS.dismiss, { forever });
|
|
261
|
+
}
|
|
262
|
+
/** Dispatch a bubbling, composed event; returns `false` when a listener called `preventDefault()`. */
|
|
263
|
+
#emit(type, extra = {}, cancelable = false) {
|
|
264
|
+
const detail = {
|
|
265
|
+
variant: this.variant,
|
|
266
|
+
state: this.state,
|
|
267
|
+
href: this.href,
|
|
268
|
+
...extra,
|
|
269
|
+
};
|
|
270
|
+
return this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable }));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/** Register the element (idempotent, no-op without `customElements`). Returns whether it is defined. */
|
|
274
|
+
export function definePrestoBanner(tagName = PrestoBanner.tagName) {
|
|
275
|
+
if (typeof customElements === "undefined")
|
|
276
|
+
return false;
|
|
277
|
+
if (!customElements.get(tagName))
|
|
278
|
+
customElements.define(tagName, PrestoBanner);
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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"}
|
package/dist/fonts.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const FONTS_HREF = "https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600..800&family=Figtree:wght@400..800&display=swap";
|
|
2
|
+
/**
|
|
3
|
+
* Link the brand faces into the document once (font faces defined in the document apply inside
|
|
4
|
+
* shadow trees). `mode: "none"` leaves typography to the host's page; the layout is designed to hold
|
|
5
|
+
* on the system stack.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ensureFonts(mode: string | null, doc?: Document | undefined): void;
|
|
8
|
+
//# sourceMappingURL=fonts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,qIAC6G,CAAC;AAIrI;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,QAAQ,GAAG,SAA+B,QAO/F"}
|
package/dist/fonts.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const FONTS_HREF = "https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600..800&family=Figtree:wght@400..800&display=swap";
|
|
2
|
+
const LINK_ID = "presto-banner-fonts";
|
|
3
|
+
/**
|
|
4
|
+
* Link the brand faces into the document once (font faces defined in the document apply inside
|
|
5
|
+
* shadow trees). `mode: "none"` leaves typography to the host's page; the layout is designed to hold
|
|
6
|
+
* on the system stack.
|
|
7
|
+
*/
|
|
8
|
+
export function ensureFonts(mode, doc = globalThis.document) {
|
|
9
|
+
if (mode === "none" || !doc?.head || doc.getElementById(LINK_ID))
|
|
10
|
+
return;
|
|
11
|
+
const link = doc.createElement("link");
|
|
12
|
+
link.id = LINK_ID;
|
|
13
|
+
link.rel = "stylesheet";
|
|
14
|
+
link.href = FONTS_HREF;
|
|
15
|
+
doc.head.appendChild(link);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GACrB,kIAAkI,CAAC;AAErI,MAAM,OAAO,GAAG,qBAAqB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAmB,EAAE,GAAG,GAAyB,UAAU,CAAC,QAAQ;IAC9F,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO;IACzE,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC;IAClB,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC;IACxB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACvB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/icons.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Inline SVG markup. `currentColor` everywhere so the tone tokens colour them. */
|
|
2
|
+
export declare const BOLT = "<svg class=\"ico-bolt\" viewBox=\"0 0 48 48\" aria-hidden=\"true\"><path d=\"M26 5 L12 27 H21 L19 43 L36 19 H25 Z\" fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linejoin=\"round\"/></svg>";
|
|
3
|
+
export declare const SPARK_GLYPH = "<i class=\"spark\" aria-hidden=\"true\">\u2726</i>";
|
|
4
|
+
export declare const SPARK_SVG = "<svg class=\"ico-spark\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M8 0l1.9 6.1L16 8l-6.1 1.9L8 16l-1.9-6.1L0 8l6.1-1.9Z\" fill=\"currentColor\"/></svg>";
|
|
5
|
+
export declare const CHECK = "<svg class=\"ico-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M8 12.5l2.5 2.5 5.5-6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>";
|
|
6
|
+
export declare const CLOSE = "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/></svg>";
|
|
7
|
+
/** The landing's hero drawing: dotted cloud, bolt, twinkling spark and mote. */
|
|
8
|
+
export declare const HERO: string;
|
|
9
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,eAAO,MAAM,IAAI,2NACyL,CAAC;AAE3M,eAAO,MAAM,WAAW,uDAA8C,CAAC;AAEvE,eAAO,MAAM,SAAS,wKACuI,CAAC;AAE9J,eAAO,MAAM,KAAK,+TAC8Q,CAAC;AAEjS,eAAO,MAAM,KAAK,+KAC8I,CAAC;AAEjK,gFAAgF;AAChF,eAAO,MAAM,IAAI,QAOP,CAAC"}
|
package/dist/icons.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Inline SVG markup. `currentColor` everywhere so the tone tokens colour them. */
|
|
2
|
+
export const BOLT = '<svg class="ico-bolt" viewBox="0 0 48 48" aria-hidden="true"><path d="M26 5 L12 27 H21 L19 43 L36 19 H25 Z" fill="currentColor" stroke="currentColor" stroke-width="4" stroke-linejoin="round"/></svg>';
|
|
3
|
+
export const SPARK_GLYPH = '<i class="spark" aria-hidden="true">✦</i>';
|
|
4
|
+
export const SPARK_SVG = '<svg class="ico-spark" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0l1.9 6.1L16 8l-6.1 1.9L8 16l-1.9-6.1L0 8l6.1-1.9Z" fill="currentColor"/></svg>';
|
|
5
|
+
export const CHECK = '<svg class="ico-check" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/><path d="M8 12.5l2.5 2.5 5.5-6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
6
|
+
export const CLOSE = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>';
|
|
7
|
+
/** The landing's hero drawing: dotted cloud, bolt, twinkling spark and mote. */
|
|
8
|
+
export const HERO = '<svg class="illo" viewBox="0 0 120 120" fill="none" aria-hidden="true">' +
|
|
9
|
+
'<path class="illo-cloud" d="M34 78 a16 16 0 0 1 -2 -31 a20 20 0 0 1 38 -8 a15 15 0 0 1 18 22 a14 14 0 0 1 -6 17" stroke-linecap="round" stroke-dasharray="1 7"/>' +
|
|
10
|
+
'<path class="illo-bolt" d="M64 34 L46 62 H58 L55 84 L77 52 H63 Z" stroke-linejoin="round"/>' +
|
|
11
|
+
'<path class="illo-spark tw" d="M88 30 l2.6 5.5 5.5 2.6 -5.5 2.6 -2.6 5.5 -2.6-5.5 -5.5-2.6 5.5-2.6 Z"/>' +
|
|
12
|
+
'<path class="illo-mote tw tw2" d="M28 40 l1.8 3.8 3.8 1.8 -3.8 1.8 -1.8 3.8 -1.8-3.8 -3.8-1.8 3.8-1.8 Z"/>' +
|
|
13
|
+
'<circle class="illo-dot1" cx="90" cy="78" r="2.6"/><circle class="illo-dot2" cx="30" cy="86" r="2"/>' +
|
|
14
|
+
"</svg>";
|
|
15
|
+
//# sourceMappingURL=icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.js","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,MAAM,CAAC,MAAM,IAAI,GACf,wMAAwM,CAAC;AAE3M,MAAM,CAAC,MAAM,WAAW,GAAG,2CAA2C,CAAC;AAEvE,MAAM,CAAC,MAAM,SAAS,GACpB,2JAA2J,CAAC;AAE9J,MAAM,CAAC,MAAM,KAAK,GAChB,8RAA8R,CAAC;AAEjS,MAAM,CAAC,MAAM,KAAK,GAChB,8JAA8J,CAAC;AAEjK,gFAAgF;AAChF,MAAM,CAAC,MAAM,IAAI,GACf,yEAAyE;IACzE,kKAAkK;IAClK,6FAA6F;IAC7F,yGAAyG;IACzG,4GAA4G;IAC5G,sGAAsG;IACtG,QAAQ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DEFAULT_HREF, DEFAULT_PERSIST_KEY, definePrestoBanner, PrestoBanner } from "./element.js";
|
|
2
|
+
export { FONTS_HREF } from "./fonts.js";
|
|
3
|
+
export { clearDismissal, DAY_MS, dismiss, isDismissed } from "./persistence.js";
|
|
4
|
+
export { detectPlatform } from "./platform.js";
|
|
5
|
+
export { stateFromStatus } from "./status.js";
|
|
6
|
+
export { STRINGS, VARIANT_COPY, VARIANT_STATES } from "./strings.js";
|
|
7
|
+
export { BANNER_EVENTS, BANNER_STATES, BANNER_VARIANTS, type BannerEventDetail, type BannerPlatform, type BannerState, type BannerTheme, type BannerTone, type BannerVariant, type PrestoStatusLike, } from "./types.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DEFAULT_HREF, DEFAULT_PERSIST_KEY, definePrestoBanner, PrestoBanner } from "./element.js";
|
|
2
|
+
export { FONTS_HREF } from "./fonts.js";
|
|
3
|
+
export { clearDismissal, DAY_MS, dismiss, isDismissed } from "./persistence.js";
|
|
4
|
+
export { detectPlatform } from "./platform.js";
|
|
5
|
+
export { stateFromStatus } from "./status.js";
|
|
6
|
+
export { STRINGS, VARIANT_COPY, VARIANT_STATES } from "./strings.js";
|
|
7
|
+
export { BANNER_EVENTS, BANNER_STATES, BANNER_VARIANTS, } from "./types.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,GAQhB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const DAY_MS = 86400000;
|
|
2
|
+
/** Whether a prior dismissal still suppresses this key. A corrupt or unreadable record never does. */
|
|
3
|
+
export declare function isDismissed(key: string, now?: number): boolean;
|
|
4
|
+
/** Record a dismissal for `days` (default 7) or forever. Silently no-ops without storage. */
|
|
5
|
+
export declare function dismiss(key: string, options?: {
|
|
6
|
+
days?: number;
|
|
7
|
+
forever?: boolean;
|
|
8
|
+
}): void;
|
|
9
|
+
export declare function clearDismissal(key: string): void;
|
|
10
|
+
//# sourceMappingURL=persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,WAAa,CAAC;AAwBjC,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAIlE;AAED,6FAA6F;AAC7F,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAS7F;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAMhD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export const DAY_MS = 86_400_000;
|
|
2
|
+
function storage() {
|
|
3
|
+
try {
|
|
4
|
+
return typeof localStorage === "undefined" ? null : localStorage;
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
// Some browsers throw on access when site data is blocked.
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function read(key) {
|
|
12
|
+
try {
|
|
13
|
+
const raw = storage()?.getItem(key);
|
|
14
|
+
if (!raw)
|
|
15
|
+
return null;
|
|
16
|
+
const parsed = JSON.parse(raw);
|
|
17
|
+
if (typeof parsed !== "object" || parsed === null || !("until" in parsed))
|
|
18
|
+
return null;
|
|
19
|
+
const until = parsed.until;
|
|
20
|
+
return until === "never" || typeof until === "number" ? { until } : null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Whether a prior dismissal still suppresses this key. A corrupt or unreadable record never does. */
|
|
27
|
+
export function isDismissed(key, now = Date.now()) {
|
|
28
|
+
const record = read(key);
|
|
29
|
+
if (!record)
|
|
30
|
+
return false;
|
|
31
|
+
return record.until === "never" || record.until > now;
|
|
32
|
+
}
|
|
33
|
+
/** Record a dismissal for `days` (default 7) or forever. Silently no-ops without storage. */
|
|
34
|
+
export function dismiss(key, options = {}) {
|
|
35
|
+
const until = options.forever
|
|
36
|
+
? "never"
|
|
37
|
+
: Date.now() + (options.days ?? 7) * DAY_MS;
|
|
38
|
+
try {
|
|
39
|
+
storage()?.setItem(key, JSON.stringify({ until }));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Quota or privacy mode: the banner simply shows again next time.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function clearDismissal(key) {
|
|
46
|
+
try {
|
|
47
|
+
storage()?.removeItem(key);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Nothing to clear.
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAC;AAEjC,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAO,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,GAAW;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACvF,MAAM,KAAK,GAAI,MAA6B,CAAC,KAAK,CAAC;QACnD,OAAO,KAAK,KAAK,OAAO,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,MAAM,CAAC,KAAK,KAAK,OAAO,IAAI,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC;AACxD,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,OAAO,GAAyC,EAAE;IACrF,MAAM,KAAK,GAAuB,OAAO,CAAC,OAAO;QAC/C,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;IAC9C,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BannerPlatform } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Desktop platform from a user-agent string, for the Sheet's "Get Presto for macOS" primary.
|
|
4
|
+
* Phones and tablets return `null` (nothing to install there), and so does anything unrecognised,
|
|
5
|
+
* so the label degrades to plain "Get Presto".
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectPlatform(userAgent: string): BannerPlatform | null;
|
|
8
|
+
//# sourceMappingURL=platform.d.ts.map
|