@grimoire-rs/indexer 0.5.0 → 0.5.2
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/CHANGELOG.md +117 -1
- package/dist/cli/dev.d.ts +14 -0
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +22 -1
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/renderer/astro/components/Catalog.js +146 -24
- package/dist/renderer/astro/components/Catalog.tsx +200 -31
- package/dist/renderer/astro/components/CodeBlock.astro +74 -0
- package/dist/renderer/astro/components/PackageCard.js +1 -1
- package/dist/renderer/astro/components/PackageCard.tsx +9 -1
- package/dist/renderer/astro/layouts/Base.astro +196 -83
- package/dist/renderer/astro/lib/code.d.ts +2 -2
- package/dist/renderer/astro/lib/code.js +2 -2
- package/dist/renderer/astro/lib/code.ts +2 -2
- package/dist/renderer/astro/lib/commands.d.ts +9 -3
- package/dist/renderer/astro/lib/commands.js +10 -5
- package/dist/renderer/astro/lib/commands.ts +22 -6
- package/dist/renderer/astro/pages/p/[...slug].astro +23 -17
- package/dist/renderer/index.d.ts +19 -0
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +18 -2
- package/dist/renderer/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,120 @@ props `{ pkg }` → `{ pkg, compact }`.
|
|
|
21
21
|
|
|
22
22
|
## [Unreleased]
|
|
23
23
|
|
|
24
|
+
## [0.5.2] - 2026-08-31
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **The sort control drew two borders when clicked.** Hover tints a control's
|
|
29
|
+
border to the accent and focus drew a 2px accent outline standing 1px clear
|
|
30
|
+
of it, so anyone who reached the control with a mouse had both at once — one
|
|
31
|
+
state reading as two lines with a gap between them. The ring merges onto the
|
|
32
|
+
border now, the way the card's focus state already did, and the offset comes
|
|
33
|
+
off every bordered control in the toolbar together rather than off the one
|
|
34
|
+
that showed it: the search field, the keyword overflow menu's search, both
|
|
35
|
+
sort halves and both view picks. Keyword chips gain the same ring, having
|
|
36
|
+
taken the browser's default until now.
|
|
37
|
+
- **A long address no longer wraps the card's head onto a second line.** A
|
|
38
|
+
namespace breaks at its own slashes and dots, so a wide one took two rows and
|
|
39
|
+
left the card taller than its neighbours with the tail of the address against
|
|
40
|
+
the padding edge. It stays on one line and the overflow is trimmed from the
|
|
41
|
+
*front* — the registry host is on every address in an index and the
|
|
42
|
+
repository at the tail is what tells two apart — with the whole of it in the
|
|
43
|
+
element's `title`.
|
|
44
|
+
- **Keyword chips could stutter, or stop part-way through the rail's slide.**
|
|
45
|
+
The rail's FLIP pass inverted each chip with an inline `transition: none` and
|
|
46
|
+
a `translate`, then dropped both on the next animation frame; any commit
|
|
47
|
+
landing inside that window left the chip carrying the offset with its
|
|
48
|
+
transition disabled, and nothing else took those off. It also measured seats
|
|
49
|
+
with `getBoundingClientRect`, which reports where a chip is *drawn*, so a
|
|
50
|
+
chip caught mid-slide recorded its animated box and the next inversion
|
|
51
|
+
compounded the error instead of correcting it. Neither window was rare: the
|
|
52
|
+
rail's own fit measurement re-commits whenever a rescore changes how many
|
|
53
|
+
chips fit. Seats now come from `offsetLeft`/`offsetTop`, which ignore
|
|
54
|
+
transforms and scroll, and the slide is a Web Animation — it starts without a
|
|
55
|
+
frame, writes nothing to `style`, and clears itself when it finishes or is
|
|
56
|
+
cancelled. `prefers-reduced-motion` is honoured by the effect rather than by
|
|
57
|
+
the stylesheet, and `--grim-duration-slow` is still its length.
|
|
58
|
+
|
|
59
|
+
## [0.5.1] - 2026-08-31
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- **`grim-indexer dev --host [addr]`.** Bare, it binds every interface; with a
|
|
64
|
+
value, that address. Without it the server binds loopback only — Astro's own
|
|
65
|
+
default — which is unreachable from a dev container, a VM or a WSL guest,
|
|
66
|
+
where the port forwards and the connection then hangs against a socket that
|
|
67
|
+
is not listening for it. `npm run dev -- --host` takes the same two forms.
|
|
68
|
+
Bare `--host` puts the preview on your network; the CLI reference says so.
|
|
69
|
+
- **`CodeBlock.astro`**, a reusable code block: the site's own frame, the same
|
|
70
|
+
Shiki theme pair every rendered README uses, the same copy button and toast,
|
|
71
|
+
and an optional VS Code button. Props
|
|
72
|
+
`{ code, lang?, name?, vscodeHref?, vscodeLabel? }`; `vscodeHref` is a plain
|
|
73
|
+
URL, so `vscodeUrl`, `vscodeVoteUrl`, `addRegistryUrl` and a hand-written
|
|
74
|
+
deep link all work. Worked example in
|
|
75
|
+
[Reuse shipped components](docs/how-to/reuse-components.md#code-blocks).
|
|
76
|
+
- **`data-slot="code-block"`**, for it. Contract tier, like every other slot.
|
|
77
|
+
- **A second argument on `registryAddCommand` and `registryScopeChoices`**,
|
|
78
|
+
the registry to build the command for — defaulting to the one in your config,
|
|
79
|
+
so nothing existing changes. It is what lets a setup page draw the "add
|
|
80
|
+
registry" bar for an index *other* than the site's own: a corporate index in
|
|
81
|
+
the hero and the public one further down.
|
|
82
|
+
- **A clear button on the keyword filters**, in the catalog toolbar. Rendered
|
|
83
|
+
only while a keyword is picked, and it lifts the keywords alone — Escape is
|
|
84
|
+
still what clears the search and the kinds with them.
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
- **The keyword overflow menu opened invisibly.** Its panel was an absolutely
|
|
89
|
+
positioned child of the toolbar's filter row, which is a scroll container, so
|
|
90
|
+
the panel was cropped to the row and stretched the row's scroll extent — a
|
|
91
|
+
menu nobody could see, with a stray horizontal and vertical scrollbar to show
|
|
92
|
+
for it. It is a popover now, which puts it in the top layer, outside every
|
|
93
|
+
ancestor's `overflow`, and brings Escape and light dismiss with it. The
|
|
94
|
+
trigger is a `<button>` rather than a `<summary>`, so the toolbar's arrow-key
|
|
95
|
+
navigation now reaches it.
|
|
96
|
+
- **The detail page's logo drifted down under a long description.** The header
|
|
97
|
+
centred the tile against the text beside it, so the same package's mark sat
|
|
98
|
+
at a different height on every page. It holds against the title now.
|
|
99
|
+
- **Dropped the tinted square behind a package logo**, on the cards, the list
|
|
100
|
+
rows and the detail header alike. A logo is a designed mark already sitting
|
|
101
|
+
on its own ground, so the slot framed it twice — most visibly for the many
|
|
102
|
+
logos that are themselves a rounded square, which then sat inside a slightly
|
|
103
|
+
larger one. The slot still reserves the same box, so nothing shifts. The
|
|
104
|
+
dashed frame the broken-logo state drew goes with it — it read as a fault in
|
|
105
|
+
the layout rather than in the image; the slashed glyph is what says the logo
|
|
106
|
+
failed, and `role="img"` with a label is what announces it. The
|
|
107
|
+
initial-letter tile a package with no logo gets is unchanged: there the
|
|
108
|
+
coloured ground is the mark.
|
|
109
|
+
- **The dev server's URL is a legal URL when the server binds an IPv6
|
|
110
|
+
address.** An unbracketed literal reads its own colons as a port, so
|
|
111
|
+
`http://::1:4321/` threw `ERR_INVALID_URL` at the first `new URL` against it
|
|
112
|
+
and took `dev:smoke` down with a message naming neither the address nor the
|
|
113
|
+
host. Wildcard binds still become `localhost`; anything carrying a colon is
|
|
114
|
+
bracketed.
|
|
115
|
+
- **The detail page's logo tile is a fixed square.** `aspect-ratio: 1` derived
|
|
116
|
+
its width from the height the box had *before* `align-self: stretch` grew it,
|
|
117
|
+
so it rendered 56x93 beside a logo and 56x70 beside a letter — portrait,
|
|
118
|
+
never square, and narrow enough to read as bounding the image rather than
|
|
119
|
+
framing it.
|
|
120
|
+
- **The list row's glyphs sit on the row's centre.** `vertical-align: middle`
|
|
121
|
+
aligns to half the parent's x-height, about 2px under the line's true middle
|
|
122
|
+
at this step, and the upvote arrow's optical nudge added a third pixel the
|
|
123
|
+
same way. The kind and rating cells are flex boxes now and centre their
|
|
124
|
+
contents as boxes.
|
|
125
|
+
- **Keyword chips could freeze part-way through the rail's slide.** The rail
|
|
126
|
+
animates a rescore by inverting each chip with an inline `translate` and
|
|
127
|
+
dropping it on the next animation frame. A rescore that also changes how many
|
|
128
|
+
chips fit commits a second time, and that commit cancelled the frame before
|
|
129
|
+
it ran — leaving every moved chip parked at its offset with transitions
|
|
130
|
+
disabled. Deselecting the last keyword hit it most often, because that
|
|
131
|
+
rescore is the largest. The offsets are now cleared before each measurement
|
|
132
|
+
and on cleanup, so an interrupted slide resolves instead of sticking.
|
|
133
|
+
- **Switching between the cards and list views repainted the whole catalog.**
|
|
134
|
+
Off-screen cards are skipped until they are scrolled to. The two views share
|
|
135
|
+
no element types, so a switch still rebuilds every item — past a few hundred
|
|
136
|
+
packages the answer is windowing the list, and this is not that.
|
|
137
|
+
|
|
24
138
|
## [0.5.0] - 2026-08-30
|
|
25
139
|
|
|
26
140
|
### Added
|
|
@@ -186,5 +300,7 @@ props `{ pkg }` → `{ pkg, compact }`.
|
|
|
186
300
|
boot can leave a `.index-*` holding Vite's `deps_temp_<hash>`, which the
|
|
187
301
|
dependency optimizer recreates after the removal has already returned.
|
|
188
302
|
|
|
189
|
-
[Unreleased]: https://github.com/grimoire-rs/indexer/compare/v0.5.
|
|
303
|
+
[Unreleased]: https://github.com/grimoire-rs/indexer/compare/v0.5.2...HEAD
|
|
304
|
+
[0.5.2]: https://github.com/grimoire-rs/indexer/compare/v0.5.1...v0.5.2
|
|
305
|
+
[0.5.1]: https://github.com/grimoire-rs/indexer/compare/v0.5.0...v0.5.1
|
|
190
306
|
[0.5.0]: https://github.com/grimoire-rs/indexer/compare/v0.4.4...v0.5.0
|
package/dist/cli/dev.d.ts
CHANGED
|
@@ -2,6 +2,20 @@ import { type ExitCode } from "./exit.js";
|
|
|
2
2
|
export interface DevFlags {
|
|
3
3
|
outDir?: string;
|
|
4
4
|
port?: string;
|
|
5
|
+
/** `true` for a bare `--host` (every interface), or the address to bind. */
|
|
6
|
+
host?: string | boolean;
|
|
5
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* What `--host` binds to, in the shape Astro's `server.host` takes: `true` for
|
|
10
|
+
* every interface, a string for one address, `undefined` to leave the default
|
|
11
|
+
* loopback bind alone.
|
|
12
|
+
*
|
|
13
|
+
* Only the shapes that cannot be an address are rejected here — an empty value,
|
|
14
|
+
* and anything carrying whitespace or a `/`, which is what `--host
|
|
15
|
+
* http://0.0.0.0` and a pasted URL look like. Whether the address exists on
|
|
16
|
+
* this machine is the kernel's answer, not this function's, and it arrives as a
|
|
17
|
+
* bind error naming the address.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveHost(host: string | boolean | undefined): string | boolean | undefined;
|
|
6
20
|
export declare function dev(root: string, flags: DevFlags): Promise<ExitCode>;
|
|
7
21
|
//# sourceMappingURL=dev.d.ts.map
|
package/dist/cli/dev.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1D,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1D,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAgBD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAU5F;AAED,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqC1E"}
|
package/dist/cli/dev.js
CHANGED
|
@@ -21,10 +21,31 @@ function resolvePort(port) {
|
|
|
21
21
|
}
|
|
22
22
|
return value;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* What `--host` binds to, in the shape Astro's `server.host` takes: `true` for
|
|
26
|
+
* every interface, a string for one address, `undefined` to leave the default
|
|
27
|
+
* loopback bind alone.
|
|
28
|
+
*
|
|
29
|
+
* Only the shapes that cannot be an address are rejected here — an empty value,
|
|
30
|
+
* and anything carrying whitespace or a `/`, which is what `--host
|
|
31
|
+
* http://0.0.0.0` and a pasted URL look like. Whether the address exists on
|
|
32
|
+
* this machine is the kernel's answer, not this function's, and it arrives as a
|
|
33
|
+
* bind error naming the address.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveHost(host) {
|
|
36
|
+
if (host === undefined || typeof host === "boolean")
|
|
37
|
+
return host;
|
|
38
|
+
const value = host.trim();
|
|
39
|
+
if (value === "" || /[\s/]/.test(value)) {
|
|
40
|
+
throw new CliError(`--host ${JSON.stringify(host)}: must be a hostname or IP address, or bare for all interfaces`, EXIT.usage);
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
24
44
|
export async function dev(root, flags) {
|
|
25
45
|
const rootDir = path.resolve(root);
|
|
26
46
|
const outDir = resolveOutDir(rootDir, flags.outDir);
|
|
27
47
|
const port = resolvePort(flags.port);
|
|
48
|
+
const host = resolveHost(flags.host);
|
|
28
49
|
const [{ loadConfig }, { compileIndex }, { devSite }] = await Promise.all([
|
|
29
50
|
import("../config.js"),
|
|
30
51
|
import("../data/index.js"),
|
|
@@ -32,7 +53,7 @@ export async function dev(root, flags) {
|
|
|
32
53
|
]);
|
|
33
54
|
const config = await loadConfig(rootDir);
|
|
34
55
|
const { count, namespaces } = await compileIndex({ root: rootDir, outDir });
|
|
35
|
-
const server = await devSite({ root: rootDir, outDir, config, port });
|
|
56
|
+
const server = await devSite({ root: rootDir, outDir, config, port, host });
|
|
36
57
|
console.log(`\n ${server.url}\n`);
|
|
37
58
|
console.log(` ${count} package(s) across ${namespaces.length} namespace(s)`);
|
|
38
59
|
// `index.config.json` is read once, at boot, and baked into the bundle — the
|
package/dist/cli/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,sCAAsC;AAEtC,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,uBAAuB;AACvB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAiB,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AA+FA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AA+FA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyJzD"}
|
package/dist/cli/main.js
CHANGED
|
@@ -143,6 +143,11 @@ export async function run(argv) {
|
|
|
143
143
|
.description("serve this index locally with a live preview")
|
|
144
144
|
.option("--out-dir <dir>", "output directory", "dist")
|
|
145
145
|
.option("--port <n>", "port to listen on")
|
|
146
|
+
// `[addr]` and not `<addr>`: bare `--host` means every interface, the same
|
|
147
|
+
// thing it means to `astro dev`, whose own banner is what tells a reader
|
|
148
|
+
// stuck behind a dev container or a WSL port forward to reach for it.
|
|
149
|
+
// Commander hands back `true` for the bare form and the string otherwise.
|
|
150
|
+
.option("--host [addr]", "expose the server on a network address (bare: all interfaces)")
|
|
146
151
|
.action(async (root, opts) => {
|
|
147
152
|
code = await dev(root, opts);
|
|
148
153
|
});
|
package/dist/cli/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-ru
|
|
|
2
2
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from "preact/hooks";
|
|
3
3
|
// Lucide (ISC) draws the toolbar. The brand marks and kind glyphs moved out
|
|
4
4
|
// with the card and the row that wear them.
|
|
5
|
-
import { ArrowDownWideNarrow, ArrowUpNarrowWide, LayoutGrid, List, } from "lucide-preact";
|
|
5
|
+
import { ArrowDownWideNarrow, ArrowUpNarrowWide, LayoutGrid, List, X, } from "lucide-preact";
|
|
6
6
|
import { PackageCard } from "./PackageCard.js";
|
|
7
7
|
import { PackageRow } from "./PackageRow.js";
|
|
8
8
|
import { keywordFrequency, selectRailKeywords } from "../lib/keywordRail.js";
|
|
@@ -22,6 +22,12 @@ function kindOrder(kind) {
|
|
|
22
22
|
* all of it is a wall of chips nobody reads.
|
|
23
23
|
*/
|
|
24
24
|
const KEYWORD_CHIP_LIMIT = 8;
|
|
25
|
+
/**
|
|
26
|
+
* `popovertarget` needs an id, and the catalog is a singleton on its page —
|
|
27
|
+
* one island, one toolbar, one overflow menu — so this is a constant rather
|
|
28
|
+
* than something generated per mount.
|
|
29
|
+
*/
|
|
30
|
+
const KEYWORD_MENU_ID = "grim-keyword-overflow";
|
|
25
31
|
/**
|
|
26
32
|
* The direction each field is *worth* reading first in — A→Z for a name,
|
|
27
33
|
* newest and best-liked first for the two ranked keys.
|
|
@@ -252,8 +258,69 @@ export default function Catalog({ packages, vscodeExtension, }) {
|
|
|
252
258
|
...(controlsRef.current?.querySelectorAll('button.chip:not([aria-hidden="true"])') ?? []),
|
|
253
259
|
];
|
|
254
260
|
const railRefs = useRef(new Map());
|
|
255
|
-
|
|
261
|
+
/**
|
|
262
|
+
* Where each chip sat at the last commit, as `offsetLeft`/`offsetTop`.
|
|
263
|
+
*
|
|
264
|
+
* Layout positions, deliberately, not `getBoundingClientRect`: the offsets
|
|
265
|
+
* ignore transforms and page scroll, so a chip measured mid-slide reports
|
|
266
|
+
* the seat it is animating towards rather than the box it is drawn in this
|
|
267
|
+
* frame. See the FLIP effect below for why that distinction is the whole
|
|
268
|
+
* fix.
|
|
269
|
+
*/
|
|
270
|
+
const railSeats = useRef(new Map());
|
|
271
|
+
/** The slide each chip is currently running, so a new one can replace it. */
|
|
272
|
+
const railSlides = useRef(new WeakMap());
|
|
256
273
|
const railRef = useRef(null);
|
|
274
|
+
const kwMenuRef = useRef(null);
|
|
275
|
+
const kwTriggerRef = useRef(null);
|
|
276
|
+
// Drives the trigger's own `aria-expanded` and its open styling. The panel's
|
|
277
|
+
// visibility is the popover's business, not this flag's.
|
|
278
|
+
const [kwMenuOpen, setKwMenuOpen] = useState(false);
|
|
279
|
+
/**
|
|
280
|
+
* Seat the overflow menu under its trigger.
|
|
281
|
+
*
|
|
282
|
+
* The panel is a popover, so it lives in the top layer and is positioned
|
|
283
|
+
* against the viewport rather than against any ancestor — which is the whole
|
|
284
|
+
* point (`.filter-row` is a scroll container and used to crop it). That
|
|
285
|
+
* leaves the seat to us.
|
|
286
|
+
*
|
|
287
|
+
* It always opens downward: the toolbar sits at the top of the page, and a
|
|
288
|
+
* flip would only ever fire on a viewport short enough that the panel has
|
|
289
|
+
* nowhere to go either way. What does not fit becomes `max-height` and
|
|
290
|
+
* scrolls inside the list.
|
|
291
|
+
*
|
|
292
|
+
* Called twice per open, from `beforetoggle` and again from `toggle`. The
|
|
293
|
+
* first runs while the panel is still `display: none`, so its measured width
|
|
294
|
+
* is 0 and the horizontal clamp is a no-op — but the vertical seat is right,
|
|
295
|
+
* which is what stops it appearing in the wrong place for a frame. The
|
|
296
|
+
* second has a real width and finishes the clamp.
|
|
297
|
+
*/
|
|
298
|
+
const placeKwMenu = () => {
|
|
299
|
+
const panel = kwMenuRef.current;
|
|
300
|
+
const trigger = kwTriggerRef.current;
|
|
301
|
+
if (!panel || !trigger)
|
|
302
|
+
return;
|
|
303
|
+
const seat = trigger.getBoundingClientRect();
|
|
304
|
+
const gap = 8;
|
|
305
|
+
const width = panel.getBoundingClientRect().width;
|
|
306
|
+
panel.style.left = `${Math.max(gap, Math.min(seat.left, window.innerWidth - width - gap))}px`;
|
|
307
|
+
panel.style.top = `${seat.bottom + gap}px`;
|
|
308
|
+
panel.style.maxHeight = `${Math.max(120, window.innerHeight - seat.bottom - gap * 3)}px`;
|
|
309
|
+
};
|
|
310
|
+
// A fixed panel does not travel with the trigger, so it is re-seated rather
|
|
311
|
+
// than left behind. Only while open — there is nothing to follow otherwise.
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
if (!kwMenuOpen)
|
|
314
|
+
return;
|
|
315
|
+
const reseat = () => placeKwMenu();
|
|
316
|
+
// Capturing: the scroll may be any ancestor's, including `.filter-row`'s.
|
|
317
|
+
window.addEventListener("scroll", reseat, { capture: true, passive: true });
|
|
318
|
+
window.addEventListener("resize", reseat);
|
|
319
|
+
return () => {
|
|
320
|
+
window.removeEventListener("scroll", reseat, { capture: true });
|
|
321
|
+
window.removeEventListener("resize", reseat);
|
|
322
|
+
};
|
|
323
|
+
}, [kwMenuOpen]);
|
|
257
324
|
/**
|
|
258
325
|
* How many keyword chips actually fit on the row, measured.
|
|
259
326
|
*
|
|
@@ -317,42 +384,76 @@ export default function Catalog({ packages, vscodeExtension, }) {
|
|
|
317
384
|
* between two frames reads as having been *replaced*, and a reader who
|
|
318
385
|
* cannot see that a chip moved has no reason to believe it is the same one.
|
|
319
386
|
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
387
|
+
* Two choices carry the whole thing, and both are here because the shape
|
|
388
|
+
* they replace — an inline `translate` under the stylesheet's transition,
|
|
389
|
+
* dropped again on a `requestAnimationFrame` — could leave a chip stopped
|
|
390
|
+
* off its seat with no path back:
|
|
391
|
+
*
|
|
392
|
+
* - **Seats come from `offsetLeft`/`offsetTop`, never from
|
|
393
|
+
* `getBoundingClientRect`.** The offsets are layout positions and ignore
|
|
394
|
+
* both transforms and scroll; a rect is where the chip is *drawn*, so a
|
|
395
|
+
* chip measured mid-slide recorded its animated box and the next
|
|
396
|
+
* inversion compounded that error — the stutter. Mid-slide is the common
|
|
397
|
+
* case, not a rare one: the fit measurement above commits a second time
|
|
398
|
+
* whenever a rescore changes how many chips fit, and that commit lands
|
|
399
|
+
* inside the previous slide. Because the offsets are transform-blind,
|
|
400
|
+
* that second commit now measures the same seats and starts nothing.
|
|
401
|
+
* - **The slide is a Web Animation, not an inline style.** It needs no
|
|
402
|
+
* frame to start, so no commit can land between an invert and its play
|
|
403
|
+
* and freeze a chip at the offset. It writes nothing to `style`, so
|
|
404
|
+
* there is nothing left to strip when a chip unmounts or a pass is
|
|
405
|
+
* superseded. And it clears itself the instant it finishes or is
|
|
406
|
+
* cancelled, which makes "the rail always ends up in its real state" a
|
|
407
|
+
* property of the mechanism rather than of a cleanup remembering to run.
|
|
326
408
|
*/
|
|
327
409
|
useLayoutEffect(() => {
|
|
328
|
-
const previous =
|
|
410
|
+
const previous = railSeats.current;
|
|
329
411
|
const current = new Map();
|
|
330
412
|
const moved = [];
|
|
331
413
|
for (const [keyword, el] of railRefs.current) {
|
|
332
|
-
const
|
|
333
|
-
|
|
414
|
+
const x = el.offsetLeft;
|
|
415
|
+
const y = el.offsetTop;
|
|
416
|
+
current.set(keyword, { x, y });
|
|
334
417
|
const was = previous.get(keyword);
|
|
335
418
|
if (!was)
|
|
336
419
|
continue;
|
|
337
|
-
const dx = was.
|
|
338
|
-
const dy = was.
|
|
420
|
+
const dx = was.x - x;
|
|
421
|
+
const dy = was.y - y;
|
|
339
422
|
if (dx !== 0 || dy !== 0)
|
|
340
423
|
moved.push({ el, dx, dy });
|
|
341
424
|
}
|
|
342
|
-
|
|
425
|
+
// Rebuilt from `railRefs` every pass, so a chip that left the rail leaves
|
|
426
|
+
// this map with it and cannot seed a slide if it comes back elsewhere.
|
|
427
|
+
railSeats.current = current;
|
|
343
428
|
if (moved.length === 0)
|
|
344
429
|
return;
|
|
430
|
+
const rail = railRef.current;
|
|
431
|
+
// Guarded rather than assumed, like the fit observer above: the test
|
|
432
|
+
// renderer's DOM has no Web Animations API, and a rail that does not
|
|
433
|
+
// slide is not worth throwing during a render over.
|
|
434
|
+
if (!rail || typeof rail.animate !== "function")
|
|
435
|
+
return;
|
|
436
|
+
// The motion is the ornament here — the filtering works identically
|
|
437
|
+
// without it — so a reader who asked for less of it gets none.
|
|
438
|
+
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)
|
|
439
|
+
return;
|
|
440
|
+
// The stylesheet stays the source of truth for how long a slide runs:
|
|
441
|
+
// `--grim-duration-slow` is written in milliseconds and that is the unit
|
|
442
|
+
// the Web Animations API takes, so the token survives the move out of CSS.
|
|
443
|
+
// Read once, after every seat above, so the reads and the writes below
|
|
444
|
+
// stay in two passes rather than interleaving per chip.
|
|
445
|
+
const ms = Number.parseFloat(getComputedStyle(rail).getPropertyValue("--grim-duration-slow"));
|
|
345
446
|
for (const { el, dx, dy } of moved) {
|
|
346
|
-
|
|
347
|
-
|
|
447
|
+
// One slide per chip. A chip that moves again mid-slide takes the new
|
|
448
|
+
// delta from its layout seat, which starts the second slide a step off
|
|
449
|
+
// where the first had drawn it — a jump measured in the pixels one
|
|
450
|
+
// frame of easing covers, and it is bounded, unlike two animations
|
|
451
|
+
// compositing the same property against each other.
|
|
452
|
+
// ponytail: not blended with the in-flight offset, which would cost a
|
|
453
|
+
// computed-style read per chip in the middle of the write pass.
|
|
454
|
+
railSlides.current.get(el)?.cancel();
|
|
455
|
+
railSlides.current.set(el, el.animate({ translate: [`${dx}px ${dy}px`, "none"] }, { duration: Number.isFinite(ms) ? ms : 200, easing: "ease-out" }));
|
|
348
456
|
}
|
|
349
|
-
const frame = requestAnimationFrame(() => {
|
|
350
|
-
for (const { el } of moved) {
|
|
351
|
-
el.style.transition = "";
|
|
352
|
-
el.style.translate = "";
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
return () => cancelAnimationFrame(frame);
|
|
356
457
|
});
|
|
357
458
|
/** Move focus `delta` cards along, clamping at both ends rather than wrapping. */
|
|
358
459
|
const focusCard = (from, delta) => {
|
|
@@ -768,7 +869,28 @@ export default function Catalog({ packages, vscodeExtension, }) {
|
|
|
768
869
|
]
|
|
769
870
|
.filter(Boolean)
|
|
770
871
|
.join(" "), "data-slot": "filter-chip", "aria-pressed": keywords.includes(keyword), "aria-hidden": clipped ? "true" : undefined, tabIndex: clipped ? -1 : undefined, onKeyDown: onChipKeyDown, onClick: () => toggleKeyword(keyword), children: keyword }, keyword));
|
|
771
|
-
}) })] })), menuKeywords.length > 0 && (_jsxs("
|
|
872
|
+
}) })] })), menuKeywords.length > 0 && (_jsxs("div", { class: "kw-menu", children: [_jsxs("button", { type: "button", class: "chip", "data-slot": "filter-chip", ref: kwTriggerRef, popovertarget: KEYWORD_MENU_ID, "aria-expanded": kwMenuOpen, children: ["+", menuKeywords.length, " more"] }), _jsxs("div", { class: "kw-menu-panel", id: KEYWORD_MENU_ID, popover: "auto", ref: kwMenuRef,
|
|
873
|
+
// Both, and in this order: `beforetoggle` runs synchronously
|
|
874
|
+
// inside the show steps, so the panel is seated before it is
|
|
875
|
+
// ever painted; `toggle` runs after, when its width can
|
|
876
|
+
// actually be measured for the clamp.
|
|
877
|
+
onBeforeToggle: (e) => {
|
|
878
|
+
setKwMenuOpen(e.newState === "open");
|
|
879
|
+
placeKwMenu();
|
|
880
|
+
}, onToggle: (e) => {
|
|
881
|
+
setKwMenuOpen(e.newState === "open");
|
|
882
|
+
placeKwMenu();
|
|
883
|
+
}, children: [_jsx("input", { type: "text", class: "kw-menu-search", placeholder: "Filter keywords\u2026", "aria-label": "Filter keywords", value: keywordFilter, onInput: (e) => setKeywordFilter(e.target.value) }), _jsxs("div", { class: "kw-menu-list", children: [menuShown.map(({ keyword, count }) => (_jsxs("button", { type: "button", class: "kw-menu-item", onClick: () => toggleKeyword(keyword), children: [_jsx("span", { children: keyword }), _jsx("small", { children: count })] }, keyword))), menuShown.length === 0 && (_jsx("p", { class: "kw-menu-empty", children: "No keyword matches." }))] })] })] })), keywords.length > 0 && (_jsxs("button", { type: "button", class: "chip kw-clear", "data-slot": "filter-chip", title: "Clear the keyword filters", onKeyDown: onChipKeyDown, onClick: (e) => {
|
|
884
|
+
setKeywords([]);
|
|
885
|
+
// This button is the last thing standing when it is pressed:
|
|
886
|
+
// clearing the facets unmounts it, and focus would land on
|
|
887
|
+
// `<body>`, sending a keyboard reader back to the top of the
|
|
888
|
+
// document. `detail === 0` is a click synthesized by Enter or
|
|
889
|
+
// Space, so a pointer user is left alone and a keyboard one
|
|
890
|
+
// gets the toolbar's own anchor instead of nothing.
|
|
891
|
+
if (e.detail === 0)
|
|
892
|
+
searchRef.current?.focus();
|
|
893
|
+
}, children: [_jsx(X, { size: 13, "aria-hidden": "true" }), "clear ", keywords.length] })), hasDeprecated && (_jsx("button", { type: "button", class: showDeprecated
|
|
772
894
|
? "chip deprecated-toggle active"
|
|
773
895
|
: "chip deprecated-toggle", "aria-pressed": showDeprecated, title: showDeprecated
|
|
774
896
|
? "Hide deprecated packages"
|