game-maker / suite (push) Failing after 10m23s
Typing "variable" into the node palette landed on `Run behavior`, because the filter weighed label, type and description alike and then sorted by category. `searchRank` in `src/ui/search.ts` now ranks a match: exact label or type, then prefix, then label, then type, and only last a hit that lives in the description alone. Category and alphabet order within a rank. The searchable `Menu` uses the same function, so searching means the same thing everywhere. The `+` menu grew to fifteen entries in declaration order. It is built in two alphabetical groups now -- the types that go into a scene, then the ones that stay in the library -- with a separator between them, the split `isPlaceableType` already draws. `ASSET_TYPES` itself stays untouched: it is also the serialisation and check order. A search flattens the groups and drops the lines. Popups were capped at fixed heights (320 menu, 260 palette, 340 pickers) while the canvas had room to spare. `Popup.roomFor()` measures its own chrome and takes the window height minus a tenth at each end. Placement clamps asymmetrically: the bottom margin is enforced, the top is only a budget, so a menu anchored near the top stays at its button instead of being pushed off it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { clampPopupY, screenMargin } from '../../src/ui/widgets/Popup';
|
|
|
|
describe('screenMargin', () => {
|
|
it('is a tenth of the canvas, so it grows with the screen', () => {
|
|
expect(screenMargin(800)).toBe(80);
|
|
expect(screenMargin(1440)).toBe(144);
|
|
});
|
|
});
|
|
|
|
describe('clampPopupY', () => {
|
|
it('leaves a popup that already sits inside the band where it is', () => {
|
|
expect(clampPopupY(300, 200, 1000)).toBe(300);
|
|
});
|
|
|
|
it('keeps the same gap below as above when the anchor sits low', () => {
|
|
// 1000 tall canvas, 100 margin: a 700 tall popup asked for y=500 ends at 200, not at 300.
|
|
const y = clampPopupY(500, 700, 1000);
|
|
expect(y).toBe(200);
|
|
expect(1000 - (y + 700)).toBe(100); // the gap below matches the 100 above
|
|
});
|
|
|
|
it('leaves a popup anchored high where it is, the gap above is no minimum', () => {
|
|
// The + menu hangs off a button near the top; pushing it down to the margin would tear it away.
|
|
expect(clampPopupY(10, 200, 1000)).toBe(10);
|
|
expect(clampPopupY(0, 200, 1000)).toBe(0);
|
|
});
|
|
|
|
it('still keeps the gap below when a tall popup has to be shifted up', () => {
|
|
expect(clampPopupY(400, 900, 1000)).toBe(0);
|
|
});
|
|
|
|
it('gives up rather than shifting a popup taller than the canvas off screen', () => {
|
|
expect(clampPopupY(400, 1200, 1000)).toBe(0);
|
|
});
|
|
});
|