@escape-game-over/atlas 0.1.67 → 0.1.68
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/docs/checks.md +1 -1
- package/package.json +6 -6
- package/src/astro/AutoDialog.astro +11 -3
- package/src/astro/Document.astro +5 -5
- package/src/astro/auto-dialog.ts +26 -8
package/docs/checks.md
CHANGED
|
@@ -124,7 +124,7 @@ dependencies at all. Vitest type-checks them itself when it runs them.
|
|
|
124
124
|
| `breadcrumbs.test.ts` | the trail, a dropped ancestor, `orphanSegments`, and how a gap is reported |
|
|
125
125
|
| `jsonld/*.test.ts` | that a `</script>` in any value cannot close the block, each node's shape and `@id`, and how a price table becomes offers |
|
|
126
126
|
| `analytics.test.ts` | Umami's attributes, its three-state booleans, the `domains` list that would record nothing, and that `consentRequired` answers exactly when a tag was emitted |
|
|
127
|
-
| `google-analytics.test.ts` | that consent is denied first and precedes every tag, one loader for many ids, dead `UA-` properties, the preconnect — once, ahead of the block that writes the loader's URL, never `crossorigin`
|
|
127
|
+
| `google-analytics.test.ts` | that consent is denied first and precedes every tag, one loader for many ids, dead `UA-` properties, and the preconnect — once, ahead of the block that writes the loader's URL, never `crossorigin` |
|
|
128
128
|
| `contact.test.ts` | the E.164 a `tel:` needs — trunk zero dropped, spacing stripped — and the displayed form kept |
|
|
129
129
|
| `hours.test.ts` | collapsing a week into runs, week start changing the answer, and every impossible week that throws |
|
|
130
130
|
| `money.test.ts` | a bare count widened to a band, the span of a table, and the gaps and overlaps that throw |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@escape-game-over/atlas",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.68",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Typed, data-driven machinery for static multi-locale, multi-deployment Astro sites.",
|
|
6
6
|
"private": false,
|
|
@@ -54,14 +54,14 @@
|
|
|
54
54
|
"@types/node": ">=22",
|
|
55
55
|
"astro": ">=7",
|
|
56
56
|
"typescript": ">=5",
|
|
57
|
-
"vite": ">=8"
|
|
57
|
+
"vite": ">= 8"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@biomejs/biome": "2.5.
|
|
61
|
-
"@types/node": "26.6.
|
|
62
|
-
"@vitest/coverage-istanbul": "5.0.
|
|
60
|
+
"@biomejs/biome": "2.5.15",
|
|
61
|
+
"@types/node": "26.6.3",
|
|
62
|
+
"@vitest/coverage-istanbul": "5.0.3",
|
|
63
63
|
"astro": "7.3.5",
|
|
64
64
|
"typescript": "6.0.3",
|
|
65
|
-
"vitest": "5.0.
|
|
65
|
+
"vitest": "5.0.3"
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
* (`closedby="any"`). Close it with `<form method="dialog"><button>…</button></form>`.
|
|
6
6
|
*
|
|
7
7
|
* ```astro
|
|
8
|
-
* <AutoDialog id="promo" aria-label="…"
|
|
8
|
+
* <AutoDialog id="promo" aria-label="…" when={{ on: "delay", ms: 2000 }} once="session">…</AutoDialog>
|
|
9
9
|
* ```
|
|
10
10
|
*
|
|
11
|
+
* With `when={{ on: "visible" }}` it opens when the place it is written
|
|
12
|
+
* scrolls into view.
|
|
13
|
+
*
|
|
11
14
|
* A dialog opened only by a button or a script needs none of this: write
|
|
12
15
|
* `<dialog closedby="any">`.
|
|
13
16
|
*/
|
|
@@ -20,8 +23,8 @@ type Props = AutoOpen &
|
|
|
20
23
|
readonly id: string;
|
|
21
24
|
};
|
|
22
25
|
|
|
23
|
-
const {
|
|
24
|
-
const auto: AutoOpen = {
|
|
26
|
+
const { when, once, waitForConsent, modal, ...attrs } = Astro.props;
|
|
27
|
+
const auto: AutoOpen = { when, once, waitForConsent, modal };
|
|
25
28
|
---
|
|
26
29
|
|
|
27
30
|
<script src="./auto-dialog.ts" />
|
|
@@ -31,6 +34,11 @@ const auto: AutoOpen = { after, once, waitForConsent, modal };
|
|
|
31
34
|
data-auto={JSON.stringify(auto)}
|
|
32
35
|
style="display:contents"
|
|
33
36
|
>
|
|
37
|
+
<!-- Out of the flow, so it adds no gap to a flex or grid parent. -->
|
|
38
|
+
<span
|
|
39
|
+
data-spot
|
|
40
|
+
style="position:absolute"
|
|
41
|
+
></span>
|
|
34
42
|
<dialog
|
|
35
43
|
closedby="any"
|
|
36
44
|
{...attrs}
|
package/src/astro/Document.astro
CHANGED
|
@@ -78,11 +78,11 @@ if (meta.consentVendors.length > 0 && !Astro.slots.has("consent")) {
|
|
|
78
78
|
<MetaTags tags={meta.tags} />
|
|
79
79
|
{rememberLocale && <RememberLocale />}
|
|
80
80
|
{Object.entries(fonts).map(([key, font]) => (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
))}
|
|
81
|
+
<Font
|
|
82
|
+
cssVariable={`--${key}`}
|
|
83
|
+
preload={font.preload === true}
|
|
84
|
+
/>
|
|
85
|
+
))}
|
|
86
86
|
<slot name="head" />
|
|
87
87
|
</head>
|
|
88
88
|
<body {...body}>
|
package/src/astro/auto-dialog.ts
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import { CONSENT_EVENT, CONSENT_TAG, readConsent } from "./consent.ts";
|
|
2
2
|
import { element } from "./element.ts";
|
|
3
|
+
import { type LoadTrigger, triggered } from "./load-script.ts";
|
|
3
4
|
import { data, ref } from "./ref.ts";
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* `loadScript`'s triggers, as a dialog uses them. `visible` watches where the
|
|
8
|
+
* `<AutoDialog>` sits in the page, so placing it in a section opens it as the
|
|
9
|
+
* visitor scrolls there. A dialog opened by a click is a plain `<dialog>`.
|
|
10
|
+
*/
|
|
11
|
+
export type OpenTrigger =
|
|
12
|
+
| { readonly on: "idle" }
|
|
13
|
+
| { readonly on: "delay"; readonly ms: number }
|
|
14
|
+
| { readonly on: "visible"; readonly margin?: string }
|
|
15
|
+
| { readonly on: "interaction" };
|
|
16
|
+
|
|
5
17
|
/** When an `<AutoDialog>` opens by itself. */
|
|
6
18
|
export interface AutoOpen {
|
|
7
|
-
/**
|
|
8
|
-
readonly
|
|
19
|
+
/** Counted from `load`, or from the consent answer with `waitForConsent`. */
|
|
20
|
+
readonly when: OpenTrigger;
|
|
9
21
|
/**
|
|
10
22
|
* Once closed, stays closed for the tab (`session`) or for good (`visitor`).
|
|
11
23
|
* Omitted, it opens on every page.
|
|
12
24
|
*/
|
|
13
25
|
readonly once?: "session" | "visitor";
|
|
14
|
-
/** Holds the
|
|
26
|
+
/** Holds the trigger until the consent banner is answered, where it asks. */
|
|
15
27
|
readonly waitForConsent?: boolean;
|
|
16
28
|
/** Defaults to `true`; `false` leaves the page usable behind it. */
|
|
17
29
|
readonly modal?: boolean;
|
|
@@ -20,10 +32,14 @@ export interface AutoOpen {
|
|
|
20
32
|
const storage = (once: "session" | "visitor"): Storage =>
|
|
21
33
|
once === "session" ? sessionStorage : localStorage;
|
|
22
34
|
|
|
23
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Opens `dialog` as `options` say, until `signal` aborts. `spot` is where the
|
|
37
|
+
* dialog sits in the page, which a `visible` trigger watches.
|
|
38
|
+
*/
|
|
24
39
|
export function autoOpen(
|
|
25
40
|
dialog: HTMLDialogElement,
|
|
26
|
-
|
|
41
|
+
spot: Element,
|
|
42
|
+
{ when, once, waitForConsent = false, modal = true }: AutoOpen,
|
|
27
43
|
signal: AbortSignal
|
|
28
44
|
): void {
|
|
29
45
|
const key = `atlas-dialog:${dialog.id}`;
|
|
@@ -44,13 +60,14 @@ export function autoOpen(
|
|
|
44
60
|
);
|
|
45
61
|
}
|
|
46
62
|
|
|
63
|
+
const trigger: LoadTrigger =
|
|
64
|
+
when.on === "visible" ? { ...when, element: spot } : when;
|
|
47
65
|
const start = () => {
|
|
48
|
-
|
|
66
|
+
void triggered(trigger, signal).then(() => {
|
|
49
67
|
if (dialog.open) return;
|
|
50
68
|
if (modal) dialog.showModal();
|
|
51
69
|
else dialog.show();
|
|
52
|
-
}
|
|
53
|
-
signal.addEventListener("abort", () => clearTimeout(timer));
|
|
70
|
+
});
|
|
54
71
|
};
|
|
55
72
|
|
|
56
73
|
const asking =
|
|
@@ -66,6 +83,7 @@ export function autoOpen(
|
|
|
66
83
|
export const autoDialog = element("atlas-dialog", ({ root, signal }) => {
|
|
67
84
|
autoOpen(
|
|
68
85
|
ref<HTMLDialogElement>(root, "dialog"),
|
|
86
|
+
ref(root, "[data-spot]"),
|
|
69
87
|
JSON.parse(data(root, "auto")),
|
|
70
88
|
signal
|
|
71
89
|
);
|