fix(ui): the page's end scrolls out from under Back to top
The button floats over the bottom-right corner, and at the end of a long table it covered the closing pager's '100' and 'All'. While it is up, PageScroller ends the page a button's height later (only then, so a full-height layout gets no scrollbar). Its shown state is a shared store read through a use… wrapper: a store's .use() called straight from a component is memoized by the React Compiler and never re-renders (contract: store.contract.test.ts).
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import { readdirSync, readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
// A store's `.use()` is a hook the React Compiler cannot see: its name is a method's, not `use…`'s.
|
||||
// Called straight from a COMPONENT, the compiled render memoized its result and never re-rendered on
|
||||
// a change — Back to top stayed hidden (E28 UAT, measured under vitest's compiler build). Inside a
|
||||
// function named `use…` it is compiled as a hook and works, so that is the only place it may be read.
|
||||
describe("a store's use()", () => {
|
||||
it("is read only inside a function named use…", () => {
|
||||
const root = new URL("../", import.meta.url);
|
||||
const offenders: string[] = [];
|
||||
for (const f of readdirSync(root, { recursive: true, encoding: "utf8" })) {
|
||||
if (!/\.tsx?$/.test(f) || f.includes(".test.")) continue;
|
||||
const src = readFileSync(new URL(f.replace(/\\/g, "/"), root), "utf8");
|
||||
for (const m of src.matchAll(/\b\w+\.use\(\)/g)) {
|
||||
const before = src.slice(0, m.index);
|
||||
const owners = [...before.matchAll(/(?:function\s+(\w+)|const\s+(\w+)\s*=\s*\()/g)];
|
||||
const owner = owners.at(-1);
|
||||
const name = owner?.[1] ?? owner?.[2] ?? "";
|
||||
if (!name.startsWith("use")) offenders.push(`${f}: ${m[0]} in ${name || "?"}`);
|
||||
}
|
||||
}
|
||||
expect(offenders).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user