@ultimat3/render 27.2.2 → 27.3.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/package.json +6 -6
- package/src/navigation-modal.ts +27 -0
- package/src/sass-cache.ts +11 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/render",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.3.0",
|
|
4
4
|
"description": "The route primitive and the five render modes: static, isr, ssr, stream, spa.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"test": "bun test"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@ultimat3/cache": "27.
|
|
44
|
-
"@ultimat3/core": "27.
|
|
45
|
-
"@ultimat3/http": "27.
|
|
46
|
-
"@ultimat3/i18n": "27.
|
|
47
|
-
"@ultimat3/seo": "27.
|
|
43
|
+
"@ultimat3/cache": "27.3.0",
|
|
44
|
+
"@ultimat3/core": "27.3.0",
|
|
45
|
+
"@ultimat3/http": "27.3.0",
|
|
46
|
+
"@ultimat3/i18n": "27.3.0",
|
|
47
|
+
"@ultimat3/seo": "27.3.0",
|
|
48
48
|
"sass": "1.105.1"
|
|
49
49
|
}
|
|
50
50
|
}
|
package/src/navigation-modal.ts
CHANGED
|
@@ -146,6 +146,29 @@ export function modalController(
|
|
|
146
146
|
const onClose = (event: Event): void => {
|
|
147
147
|
if (event.target === dialog && dialog !== undefined && !dialog.open) close();
|
|
148
148
|
};
|
|
149
|
+
// A press on the backdrop. `closedby="any"` has the browser close the dialog itself (and fire
|
|
150
|
+
// `close`, read above); a browser without it reports the press as a click whose target is the
|
|
151
|
+
// dialog and whose point is outside its box — a click on the dialog's own padding is inside it
|
|
152
|
+
// and closes nothing, and so does one a keyboard made, which lands on a control. The press must
|
|
153
|
+
// START outside too: one that began inside (selecting text, dragging out of a field) and was
|
|
154
|
+
// released on the backdrop also clicks the dialog, and must not throw the visitor's work away.
|
|
155
|
+
// Idempotent with the browser's own: a close already under way is not started twice.
|
|
156
|
+
const outside = (event: Event): boolean => {
|
|
157
|
+
const open = dialog;
|
|
158
|
+
if (open === undefined || event.target !== open) return false;
|
|
159
|
+
const { clientX: x, clientY: y } = event as MouseEvent;
|
|
160
|
+
const box = open.getBoundingClientRect();
|
|
161
|
+
return x < box.left || x > box.right || y < box.top || y > box.bottom;
|
|
162
|
+
};
|
|
163
|
+
let pressedOutside = false;
|
|
164
|
+
const onPointerDown = (event: Event): void => {
|
|
165
|
+
pressedOutside = outside(event);
|
|
166
|
+
};
|
|
167
|
+
const onClick = (event: Event): void => {
|
|
168
|
+
const began = pressedOutside;
|
|
169
|
+
pressedOutside = false;
|
|
170
|
+
if (began && outside(event)) close();
|
|
171
|
+
};
|
|
149
172
|
|
|
150
173
|
const present = async (
|
|
151
174
|
next: Document,
|
|
@@ -165,8 +188,12 @@ export function modalController(
|
|
|
165
188
|
title = doc.title;
|
|
166
189
|
open = doc.createElement('dialog');
|
|
167
190
|
open.setAttribute(NAVIGATION_MODAL_ATTRIBUTE, '');
|
|
191
|
+
// Light dismiss: Escape AND a press outside close it, as every modal does (`Dialog` included).
|
|
192
|
+
open.setAttribute('closedby', 'any');
|
|
168
193
|
open.addEventListener('cancel', onCancel);
|
|
169
194
|
open.addEventListener('close', onClose);
|
|
195
|
+
open.addEventListener('pointerdown', onPointerDown);
|
|
196
|
+
open.addEventListener('click', onClick);
|
|
170
197
|
doc.body.append(open);
|
|
171
198
|
} else {
|
|
172
199
|
// One modal at a time: the next address replaces this one's content, in the same dialog.
|
package/src/sass-cache.ts
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
|
|
9
9
|
// why: Bun ships no path-join primitive.
|
|
10
10
|
import { join } from 'node:path';
|
|
11
|
+
import { appStatePath } from '@ultimat3/core';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* Relative to the
|
|
14
|
+
* Relative to the app root (`defaultSassCacheDir`), never the process's cwd. `.x/` is gitignored, and in
|
|
14
15
|
* a container it is the STATE directory a topology mounts a tmpfs over, so an image's own entries
|
|
15
16
|
* live elsewhere: the image build points this cache at its prebuilt store through
|
|
16
17
|
* `setSassCacheDir`, and the container's boot points it back at the same place.
|
|
@@ -20,7 +21,7 @@ export const SASS_CACHE_DIR = join('.x', 'cache', 'sass');
|
|
|
20
21
|
/** Bumped when the entry shape changes, so an old entry is a miss and never a misread. */
|
|
21
22
|
const ENTRY_VERSION = 2;
|
|
22
23
|
|
|
23
|
-
/** `undefined`: the default dir under
|
|
24
|
+
/** `undefined`: the default dir under the app root. `null`: off. A string: that directory. */
|
|
24
25
|
let configured: string | null | undefined;
|
|
25
26
|
|
|
26
27
|
/** Test/host seam. `null` turns the cache off; `undefined` restores the default. */
|
|
@@ -28,8 +29,15 @@ export function setSassCacheDir(dir: string | null | undefined): void {
|
|
|
28
29
|
configured = dir;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/**
|
|
33
|
+
* The default for a process started in `cwd`: `.x/cache/sass` under the APP ROOT above it (#738).
|
|
34
|
+
* It was `cwd` itself, so a `bun test` started in a source folder wrote a `.x/cache` beside the
|
|
35
|
+
* code. Outside any app (a package's own suite), the folder itself.
|
|
36
|
+
*/
|
|
37
|
+
export const defaultSassCacheDir = (cwd: string): string => appStatePath(cwd, 'cache', 'sass');
|
|
38
|
+
|
|
31
39
|
const cacheDir = (): string | null =>
|
|
32
|
-
configured === undefined ?
|
|
40
|
+
configured === undefined ? defaultSassCacheDir(process.cwd()) : configured;
|
|
33
41
|
|
|
34
42
|
const sha256 = (input: string | Uint8Array): string =>
|
|
35
43
|
new Bun.CryptoHasher('sha256').update(input).digest('hex');
|