@grimoire-rs/indexer 0.5.0 → 0.5.1

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 CHANGED
@@ -21,6 +21,85 @@ props `{ pkg }` → `{ pkg, compact }`.
21
21
 
22
22
  ## [Unreleased]
23
23
 
24
+ ## [0.5.1] - 2026-08-31
25
+
26
+ ### Added
27
+
28
+ - **`grim-indexer dev --host [addr]`.** Bare, it binds every interface; with a
29
+ value, that address. Without it the server binds loopback only — Astro's own
30
+ default — which is unreachable from a dev container, a VM or a WSL guest,
31
+ where the port forwards and the connection then hangs against a socket that
32
+ is not listening for it. `npm run dev -- --host` takes the same two forms.
33
+ Bare `--host` puts the preview on your network; the CLI reference says so.
34
+ - **`CodeBlock.astro`**, a reusable code block: the site's own frame, the same
35
+ Shiki theme pair every rendered README uses, the same copy button and toast,
36
+ and an optional VS Code button. Props
37
+ `{ code, lang?, name?, vscodeHref?, vscodeLabel? }`; `vscodeHref` is a plain
38
+ URL, so `vscodeUrl`, `vscodeVoteUrl`, `addRegistryUrl` and a hand-written
39
+ deep link all work. Worked example in
40
+ [Reuse shipped components](docs/how-to/reuse-components.md#code-blocks).
41
+ - **`data-slot="code-block"`**, for it. Contract tier, like every other slot.
42
+ - **A second argument on `registryAddCommand` and `registryScopeChoices`**,
43
+ the registry to build the command for — defaulting to the one in your config,
44
+ so nothing existing changes. It is what lets a setup page draw the "add
45
+ registry" bar for an index *other* than the site's own: a corporate index in
46
+ the hero and the public one further down.
47
+ - **A clear button on the keyword filters**, in the catalog toolbar. Rendered
48
+ only while a keyword is picked, and it lifts the keywords alone — Escape is
49
+ still what clears the search and the kinds with them.
50
+
51
+ ### Fixed
52
+
53
+ - **The keyword overflow menu opened invisibly.** Its panel was an absolutely
54
+ positioned child of the toolbar's filter row, which is a scroll container, so
55
+ the panel was cropped to the row and stretched the row's scroll extent — a
56
+ menu nobody could see, with a stray horizontal and vertical scrollbar to show
57
+ for it. It is a popover now, which puts it in the top layer, outside every
58
+ ancestor's `overflow`, and brings Escape and light dismiss with it. The
59
+ trigger is a `<button>` rather than a `<summary>`, so the toolbar's arrow-key
60
+ navigation now reaches it.
61
+ - **The detail page's logo drifted down under a long description.** The header
62
+ centred the tile against the text beside it, so the same package's mark sat
63
+ at a different height on every page. It holds against the title now.
64
+ - **Dropped the tinted square behind a package logo**, on the cards, the list
65
+ rows and the detail header alike. A logo is a designed mark already sitting
66
+ on its own ground, so the slot framed it twice — most visibly for the many
67
+ logos that are themselves a rounded square, which then sat inside a slightly
68
+ larger one. The slot still reserves the same box, so nothing shifts. The
69
+ dashed frame the broken-logo state drew goes with it — it read as a fault in
70
+ the layout rather than in the image; the slashed glyph is what says the logo
71
+ failed, and `role="img"` with a label is what announces it. The
72
+ initial-letter tile a package with no logo gets is unchanged: there the
73
+ coloured ground is the mark.
74
+ - **The dev server's URL is a legal URL when the server binds an IPv6
75
+ address.** An unbracketed literal reads its own colons as a port, so
76
+ `http://::1:4321/` threw `ERR_INVALID_URL` at the first `new URL` against it
77
+ and took `dev:smoke` down with a message naming neither the address nor the
78
+ host. Wildcard binds still become `localhost`; anything carrying a colon is
79
+ bracketed.
80
+ - **The detail page's logo tile is a fixed square.** `aspect-ratio: 1` derived
81
+ its width from the height the box had *before* `align-self: stretch` grew it,
82
+ so it rendered 56x93 beside a logo and 56x70 beside a letter — portrait,
83
+ never square, and narrow enough to read as bounding the image rather than
84
+ framing it.
85
+ - **The list row's glyphs sit on the row's centre.** `vertical-align: middle`
86
+ aligns to half the parent's x-height, about 2px under the line's true middle
87
+ at this step, and the upvote arrow's optical nudge added a third pixel the
88
+ same way. The kind and rating cells are flex boxes now and centre their
89
+ contents as boxes.
90
+ - **Keyword chips could freeze part-way through the rail's slide.** The rail
91
+ animates a rescore by inverting each chip with an inline `translate` and
92
+ dropping it on the next animation frame. A rescore that also changes how many
93
+ chips fit commits a second time, and that commit cancelled the frame before
94
+ it ran — leaving every moved chip parked at its offset with transitions
95
+ disabled. Deselecting the last keyword hit it most often, because that
96
+ rescore is the largest. The offsets are now cleared before each measurement
97
+ and on cleanup, so an interrupted slide resolves instead of sticking.
98
+ - **Switching between the cards and list views repainted the whole catalog.**
99
+ Off-screen cards are skipped until they are scrolled to. The two views share
100
+ no element types, so a switch still rebuilds every item — past a few hundred
101
+ packages the answer is windowing the list, and this is not that.
102
+
24
103
  ## [0.5.0] - 2026-08-30
25
104
 
26
105
  ### Added
@@ -186,5 +265,6 @@ props `{ pkg }` → `{ pkg, compact }`.
186
265
  boot can leave a `.index-*` holding Vite's `deps_temp_<hash>`, which the
187
266
  dependency optimizer recreates after the removal has already returned.
188
267
 
189
- [Unreleased]: https://github.com/grimoire-rs/indexer/compare/v0.5.0...HEAD
268
+ [Unreleased]: https://github.com/grimoire-rs/indexer/compare/v0.5.1...HEAD
269
+ [0.5.1]: https://github.com/grimoire-rs/indexer/compare/v0.5.0...v0.5.1
190
270
  [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
@@ -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;CACf;AAgBD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoC1E"}
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
@@ -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;AAO7C;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAwB;IAC3C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;QAC3D,MAAM,IAAI,QAAQ,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,mCAAmC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAY,EAAE,KAAe;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErC,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxE,MAAM,CAAC,cAAc,CAAC;QACtB,MAAM,CAAC,kBAAkB,CAAC;QAC1B,MAAM,CAAC,sBAAsB,CAAC;KAC/B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtE,OAAO,CAAC,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,sBAAsB,UAAU,CAAC,MAAM,eAAe,CAAC,CAAC;IAC9E,6EAA6E;IAC7E,yEAAyE;IACzE,kCAAkC;IAClC,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAE9E,4EAA4E;IAC5E,4EAA4E;IAC5E,0DAA0D;IAC1D,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAU,EAAE,CAAC;YACpD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;gBACtB,KAAK,MAAM;qBACR,IAAI,EAAE;qBACN,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;qBACf,OAAO,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC"}
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;AAS7C;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAwB;IAC3C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;QAC3D,MAAM,IAAI,QAAQ,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,mCAAmC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAAkC;IAC5D,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACjE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,KAAK,KAAK,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,QAAQ,CAChB,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,gEAAgE,EAC9F,IAAI,CAAC,KAAK,CACX,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAY,EAAE,KAAe;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErC,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxE,MAAM,CAAC,cAAc,CAAC;QACtB,MAAM,CAAC,kBAAkB,CAAC;QAC1B,MAAM,CAAC,sBAAsB,CAAC;KAC/B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5E,OAAO,CAAC,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,sBAAsB,UAAU,CAAC,MAAM,eAAe,CAAC,CAAC;IAC9E,6EAA6E;IAC7E,yEAAyE;IACzE,kCAAkC;IAClC,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAE9E,4EAA4E;IAC5E,4EAA4E;IAC5E,0DAA0D;IAC1D,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAU,EAAE,CAAC;YACpD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;gBACtB,KAAK,MAAM;qBACR,IAAI,EAAE;qBACN,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;qBACf,OAAO,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC"}
@@ -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,CAkJzD"}
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
  });
@@ -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.
@@ -254,6 +260,56 @@ export default function Catalog({ packages, vscodeExtension, }) {
254
260
  const railRefs = useRef(new Map());
255
261
  const railRects = useRef(new Map());
256
262
  const railRef = useRef(null);
263
+ const kwMenuRef = useRef(null);
264
+ const kwTriggerRef = useRef(null);
265
+ // Drives the trigger's own `aria-expanded` and its open styling. The panel's
266
+ // visibility is the popover's business, not this flag's.
267
+ const [kwMenuOpen, setKwMenuOpen] = useState(false);
268
+ /**
269
+ * Seat the overflow menu under its trigger.
270
+ *
271
+ * The panel is a popover, so it lives in the top layer and is positioned
272
+ * against the viewport rather than against any ancestor — which is the whole
273
+ * point (`.filter-row` is a scroll container and used to crop it). That
274
+ * leaves the seat to us.
275
+ *
276
+ * It always opens downward: the toolbar sits at the top of the page, and a
277
+ * flip would only ever fire on a viewport short enough that the panel has
278
+ * nowhere to go either way. What does not fit becomes `max-height` and
279
+ * scrolls inside the list.
280
+ *
281
+ * Called twice per open, from `beforetoggle` and again from `toggle`. The
282
+ * first runs while the panel is still `display: none`, so its measured width
283
+ * is 0 and the horizontal clamp is a no-op — but the vertical seat is right,
284
+ * which is what stops it appearing in the wrong place for a frame. The
285
+ * second has a real width and finishes the clamp.
286
+ */
287
+ const placeKwMenu = () => {
288
+ const panel = kwMenuRef.current;
289
+ const trigger = kwTriggerRef.current;
290
+ if (!panel || !trigger)
291
+ return;
292
+ const seat = trigger.getBoundingClientRect();
293
+ const gap = 8;
294
+ const width = panel.getBoundingClientRect().width;
295
+ panel.style.left = `${Math.max(gap, Math.min(seat.left, window.innerWidth - width - gap))}px`;
296
+ panel.style.top = `${seat.bottom + gap}px`;
297
+ panel.style.maxHeight = `${Math.max(120, window.innerHeight - seat.bottom - gap * 3)}px`;
298
+ };
299
+ // A fixed panel does not travel with the trigger, so it is re-seated rather
300
+ // than left behind. Only while open — there is nothing to follow otherwise.
301
+ useEffect(() => {
302
+ if (!kwMenuOpen)
303
+ return;
304
+ const reseat = () => placeKwMenu();
305
+ // Capturing: the scroll may be any ancestor's, including `.filter-row`'s.
306
+ window.addEventListener("scroll", reseat, { capture: true, passive: true });
307
+ window.addEventListener("resize", reseat);
308
+ return () => {
309
+ window.removeEventListener("scroll", reseat, { capture: true });
310
+ window.removeEventListener("resize", reseat);
311
+ };
312
+ }, [kwMenuOpen]);
257
313
  /**
258
314
  * How many keyword chips actually fit on the row, measured.
259
315
  *
@@ -325,9 +381,26 @@ export default function Catalog({ packages, vscodeExtension, }) {
325
381
  * shape that makes a layout thrash, and this runs per keystroke.
326
382
  */
327
383
  useLayoutEffect(() => {
384
+ // Undo whatever the last pass left on the chips before measuring
385
+ // anything. Two reasons, and both were visible: `getBoundingClientRect`
386
+ // reports the *translated* box, so a chip caught mid-slide would be
387
+ // measured where it is drawn rather than where it belongs and the next
388
+ // inversion would compound that error; and a chip whose play frame never
389
+ // ran is still carrying `transition: none` with an offset, which is a chip
390
+ // frozen off its seat. Clearing here is what unfreezes it.
391
+ //
392
+ // Mid-slide is not a rare case: the fit measurement above commits a second
393
+ // time whenever the rescore changes how many chips fit, and that commit
394
+ // lands between this one and its animation frame.
395
+ for (const el of railRefs.current.values()) {
396
+ el.style.transition = "";
397
+ el.style.translate = "";
398
+ }
328
399
  const previous = railRects.current;
329
400
  const current = new Map();
330
401
  const moved = [];
402
+ // A second pass, deliberately: every write above is flushed before the
403
+ // first read below, rather than interleaving them per chip.
331
404
  for (const [keyword, el] of railRefs.current) {
332
405
  const rect = el.getBoundingClientRect();
333
406
  current.set(keyword, rect);
@@ -352,7 +425,19 @@ export default function Catalog({ packages, vscodeExtension, }) {
352
425
  el.style.translate = "";
353
426
  }
354
427
  });
355
- return () => cancelAnimationFrame(frame);
428
+ return () => {
429
+ cancelAnimationFrame(frame);
430
+ // Cancelling is not enough on its own. Nothing else takes these off, so
431
+ // a commit landing before the frame ran would leave every moved chip
432
+ // sitting at its inverted offset with transitions disabled — the rail
433
+ // stopping halfway and staying there. Deselecting the last keyword is
434
+ // the reliable way to see it: the rescore is at its largest, so the fit
435
+ // changes and the extra commit always lands.
436
+ for (const { el } of moved) {
437
+ el.style.transition = "";
438
+ el.style.translate = "";
439
+ }
440
+ };
356
441
  });
357
442
  /** Move focus `delta` cards along, clamping at both ends rather than wrapping. */
358
443
  const focusCard = (from, delta) => {
@@ -768,7 +853,28 @@ export default function Catalog({ packages, vscodeExtension, }) {
768
853
  ]
769
854
  .filter(Boolean)
770
855
  .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("details", { class: "kw-menu", children: [_jsxs("summary", { class: "chip", "data-slot": "filter-chip", children: ["+", menuKeywords.length, " more"] }), _jsxs("div", { class: "kw-menu-panel", 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." }))] })] })] })), hasDeprecated && (_jsx("button", { type: "button", class: showDeprecated
856
+ }) })] })), 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,
857
+ // Both, and in this order: `beforetoggle` runs synchronously
858
+ // inside the show steps, so the panel is seated before it is
859
+ // ever painted; `toggle` runs after, when its width can
860
+ // actually be measured for the clamp.
861
+ onBeforeToggle: (e) => {
862
+ setKwMenuOpen(e.newState === "open");
863
+ placeKwMenu();
864
+ }, onToggle: (e) => {
865
+ setKwMenuOpen(e.newState === "open");
866
+ placeKwMenu();
867
+ }, 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) => {
868
+ setKeywords([]);
869
+ // This button is the last thing standing when it is pressed:
870
+ // clearing the facets unmounts it, and focus would land on
871
+ // `<body>`, sending a keyboard reader back to the top of the
872
+ // document. `detail === 0` is a click synthesized by Enter or
873
+ // Space, so a pointer user is left alone and a keyboard one
874
+ // gets the toolbar's own anchor instead of nothing.
875
+ if (e.detail === 0)
876
+ searchRef.current?.focus();
877
+ }, children: [_jsx(X, { size: 13, "aria-hidden": "true" }), "clear ", keywords.length] })), hasDeprecated && (_jsx("button", { type: "button", class: showDeprecated
772
878
  ? "chip deprecated-toggle active"
773
879
  : "chip deprecated-toggle", "aria-pressed": showDeprecated, title: showDeprecated
774
880
  ? "Hide deprecated packages"
@@ -12,6 +12,7 @@ import {
12
12
  ArrowUpNarrowWide,
13
13
  LayoutGrid,
14
14
  List,
15
+ X,
15
16
  } from "lucide-preact";
16
17
  import { PackageCard } from "./PackageCard.js";
17
18
  import { PackageRow } from "./PackageRow.js";
@@ -41,6 +42,13 @@ export type View = "cards" | "table";
41
42
  */
42
43
  const KEYWORD_CHIP_LIMIT = 8;
43
44
 
45
+ /**
46
+ * `popovertarget` needs an id, and the catalog is a singleton on its page —
47
+ * one island, one toolbar, one overflow menu — so this is a constant rather
48
+ * than something generated per mount.
49
+ */
50
+ const KEYWORD_MENU_ID = "grim-keyword-overflow";
51
+
44
52
  /**
45
53
  * The direction each field is *worth* reading first in — A→Z for a name,
46
54
  * newest and best-liked first for the two ranked keys.
@@ -329,6 +337,57 @@ export default function Catalog({
329
337
  const railRects = useRef(new Map<string, DOMRect>());
330
338
  const railRef = useRef<HTMLDivElement>(null);
331
339
 
340
+ const kwMenuRef = useRef<HTMLDivElement>(null);
341
+ const kwTriggerRef = useRef<HTMLButtonElement>(null);
342
+ // Drives the trigger's own `aria-expanded` and its open styling. The panel's
343
+ // visibility is the popover's business, not this flag's.
344
+ const [kwMenuOpen, setKwMenuOpen] = useState(false);
345
+
346
+ /**
347
+ * Seat the overflow menu under its trigger.
348
+ *
349
+ * The panel is a popover, so it lives in the top layer and is positioned
350
+ * against the viewport rather than against any ancestor — which is the whole
351
+ * point (`.filter-row` is a scroll container and used to crop it). That
352
+ * leaves the seat to us.
353
+ *
354
+ * It always opens downward: the toolbar sits at the top of the page, and a
355
+ * flip would only ever fire on a viewport short enough that the panel has
356
+ * nowhere to go either way. What does not fit becomes `max-height` and
357
+ * scrolls inside the list.
358
+ *
359
+ * Called twice per open, from `beforetoggle` and again from `toggle`. The
360
+ * first runs while the panel is still `display: none`, so its measured width
361
+ * is 0 and the horizontal clamp is a no-op — but the vertical seat is right,
362
+ * which is what stops it appearing in the wrong place for a frame. The
363
+ * second has a real width and finishes the clamp.
364
+ */
365
+ const placeKwMenu = () => {
366
+ const panel = kwMenuRef.current;
367
+ const trigger = kwTriggerRef.current;
368
+ if (!panel || !trigger) return;
369
+ const seat = trigger.getBoundingClientRect();
370
+ const gap = 8;
371
+ const width = panel.getBoundingClientRect().width;
372
+ panel.style.left = `${Math.max(gap, Math.min(seat.left, window.innerWidth - width - gap))}px`;
373
+ panel.style.top = `${seat.bottom + gap}px`;
374
+ panel.style.maxHeight = `${Math.max(120, window.innerHeight - seat.bottom - gap * 3)}px`;
375
+ };
376
+
377
+ // A fixed panel does not travel with the trigger, so it is re-seated rather
378
+ // than left behind. Only while open — there is nothing to follow otherwise.
379
+ useEffect(() => {
380
+ if (!kwMenuOpen) return;
381
+ const reseat = () => placeKwMenu();
382
+ // Capturing: the scroll may be any ancestor's, including `.filter-row`'s.
383
+ window.addEventListener("scroll", reseat, { capture: true, passive: true });
384
+ window.addEventListener("resize", reseat);
385
+ return () => {
386
+ window.removeEventListener("scroll", reseat, { capture: true });
387
+ window.removeEventListener("resize", reseat);
388
+ };
389
+ }, [kwMenuOpen]);
390
+
332
391
  /**
333
392
  * How many keyword chips actually fit on the row, measured.
334
393
  *
@@ -399,9 +458,26 @@ export default function Catalog({
399
458
  * shape that makes a layout thrash, and this runs per keystroke.
400
459
  */
401
460
  useLayoutEffect(() => {
461
+ // Undo whatever the last pass left on the chips before measuring
462
+ // anything. Two reasons, and both were visible: `getBoundingClientRect`
463
+ // reports the *translated* box, so a chip caught mid-slide would be
464
+ // measured where it is drawn rather than where it belongs and the next
465
+ // inversion would compound that error; and a chip whose play frame never
466
+ // ran is still carrying `transition: none` with an offset, which is a chip
467
+ // frozen off its seat. Clearing here is what unfreezes it.
468
+ //
469
+ // Mid-slide is not a rare case: the fit measurement above commits a second
470
+ // time whenever the rescore changes how many chips fit, and that commit
471
+ // lands between this one and its animation frame.
472
+ for (const el of railRefs.current.values()) {
473
+ el.style.transition = "";
474
+ el.style.translate = "";
475
+ }
402
476
  const previous = railRects.current;
403
477
  const current = new Map<string, DOMRect>();
404
478
  const moved: { el: HTMLElement; dx: number; dy: number }[] = [];
479
+ // A second pass, deliberately: every write above is flushed before the
480
+ // first read below, rather than interleaving them per chip.
405
481
  for (const [keyword, el] of railRefs.current) {
406
482
  const rect = el.getBoundingClientRect();
407
483
  current.set(keyword, rect);
@@ -423,7 +499,19 @@ export default function Catalog({
423
499
  el.style.translate = "";
424
500
  }
425
501
  });
426
- return () => cancelAnimationFrame(frame);
502
+ return () => {
503
+ cancelAnimationFrame(frame);
504
+ // Cancelling is not enough on its own. Nothing else takes these off, so
505
+ // a commit landing before the frame ran would leave every moved chip
506
+ // sitting at its inverted offset with transitions disabled — the rail
507
+ // stopping halfway and staying there. Deselecting the last keyword is
508
+ // the reliable way to see it: the rescore is at its largest, so the fit
509
+ // changes and the extra commit always lands.
510
+ for (const { el } of moved) {
511
+ el.style.transition = "";
512
+ el.style.translate = "";
513
+ }
514
+ };
427
515
  });
428
516
 
429
517
  /** Move focus `delta` cards along, clamping at both ends rather than wrapping. */
@@ -961,14 +1049,42 @@ export default function Catalog({
961
1049
  // catalog's keyword vocabulary is open-ended, and a few hundred
962
1050
  // chips at once is a wall, not a control.
963
1051
  //
964
- // A `<details>` for the same reason the platform picker and the
965
- // version menus are: it opens, closes and takes Escape on its
966
- // own, with no popover library and no script.
967
- <details class="kw-menu">
968
- <summary class="chip" data-slot="filter-chip">
1052
+ // A popover, and not by preference: the panel used to be an
1053
+ // absolutely-positioned child of `.filter-row`, which is a scroll
1054
+ // container, so it was cropped to the row and stretched the row's
1055
+ // scroll extent — an invisible menu and two stray scrollbars. The
1056
+ // top layer is outside every ancestor's `overflow`. Escape and
1057
+ // light dismiss come with it; only the seat is ours to compute,
1058
+ // and that is `placeKwMenu` above.
1059
+ <div class="kw-menu">
1060
+ <button
1061
+ type="button"
1062
+ class="chip"
1063
+ data-slot="filter-chip"
1064
+ ref={kwTriggerRef}
1065
+ popovertarget={KEYWORD_MENU_ID}
1066
+ aria-expanded={kwMenuOpen}
1067
+ >
969
1068
  +{menuKeywords.length} more
970
- </summary>
971
- <div class="kw-menu-panel">
1069
+ </button>
1070
+ <div
1071
+ class="kw-menu-panel"
1072
+ id={KEYWORD_MENU_ID}
1073
+ popover="auto"
1074
+ ref={kwMenuRef}
1075
+ // Both, and in this order: `beforetoggle` runs synchronously
1076
+ // inside the show steps, so the panel is seated before it is
1077
+ // ever painted; `toggle` runs after, when its width can
1078
+ // actually be measured for the clamp.
1079
+ onBeforeToggle={(e) => {
1080
+ setKwMenuOpen(e.newState === "open");
1081
+ placeKwMenu();
1082
+ }}
1083
+ onToggle={(e) => {
1084
+ setKwMenuOpen(e.newState === "open");
1085
+ placeKwMenu();
1086
+ }}
1087
+ >
972
1088
  <input
973
1089
  type="text"
974
1090
  class="kw-menu-search"
@@ -996,7 +1112,38 @@ export default function Catalog({
996
1112
  )}
997
1113
  </div>
998
1114
  </div>
999
- </details>
1115
+ </div>
1116
+ )}
1117
+ {keywords.length > 0 && (
1118
+ // Lifts every keyword at once. Only rendered while there is
1119
+ // something to lift — a permanently visible control that does
1120
+ // nothing most of the time is a chip's width spent on nothing, and
1121
+ // this row is already the one that runs out of room first.
1122
+ //
1123
+ // Keywords only, deliberately. Escape clears the search and the
1124
+ // kinds along with them, and a button that quietly did the same
1125
+ // would undo a filter the reader did not ask about; the label
1126
+ // names exactly what it lifts.
1127
+ <button
1128
+ type="button"
1129
+ class="chip kw-clear"
1130
+ data-slot="filter-chip"
1131
+ title="Clear the keyword filters"
1132
+ onKeyDown={onChipKeyDown}
1133
+ onClick={(e) => {
1134
+ setKeywords([]);
1135
+ // This button is the last thing standing when it is pressed:
1136
+ // clearing the facets unmounts it, and focus would land on
1137
+ // `<body>`, sending a keyboard reader back to the top of the
1138
+ // document. `detail === 0` is a click synthesized by Enter or
1139
+ // Space, so a pointer user is left alone and a keyboard one
1140
+ // gets the toolbar's own anchor instead of nothing.
1141
+ if (e.detail === 0) searchRef.current?.focus();
1142
+ }}
1143
+ >
1144
+ <X size={13} aria-hidden="true" />
1145
+ clear {keywords.length}
1146
+ </button>
1000
1147
  )}
1001
1148
  {hasDeprecated && (
1002
1149
  // A toggle, not a filter: `aria-pressed` rather than the `active`