Skip to content

Elements: Type VirtualList's item template as an element - #71

Open
moersoy wants to merge 2 commits into
geastack:mainfrom
moersoy:elements/virtual-list-item-template
Open

moersoy wants to merge 2 commits into
geastack:mainfrom
moersoy:elements/virtual-list-item-template

Conversation

@moersoy

@moersoy moersoy commented Oct 17, 2026

Copy link
Copy Markdown

Part of #70 (item 1).

Problem

@geastack/elements VirtualList does not compile to C++. VirtualListItemTemplate returns any, and each slot renders {itemTemplate(...)} (VirtualList.tsx:79-82). An any result lowers to gea::Value, which gea::jsx::child has no rule for, so the C++ build stops:

gea_runtime.h:47048: static assertion failed due to requirement 'detail::always_false_v<gea::Value>':
gea::jsx::child: no append/text rule installed for this child value's C++ type

No app or test imports the component, so nothing caught it.

Fix

Type the template's result as GeaJsxElement, the type core uses for a component's returned element, in VirtualList.tsx and VirtualList.d.ts. The result now lowers to an element handle, which gea::jsx::child appends. The .d.ts says to wrap plain text in an element.

GeaJsxElement is an empty interface, so TypeScript still accepts a template that returns a string. geatsc then refuses it at compile time with "no runtime conversion is installed from string to native-handle(jsx-element)", instead of the C++ static_assert. Under any, no template compiled at all.

Tests

  • Added run-gea-elements-virtual-list-pipeline.sh with the fixture packages/core/test/fixtures/gea-elements-virtual-list, so the test does not depend on geastack/examples. The fixture uses the component the way the README shows. test_gea_elements_virtual_list_main.cpp checks:
    • the list takes its height from the class (the rows are absolutely positioned);
    • its 16 slots show rows 0..15 once each.
  • The test passes with the fix. With the template typed any again, the C++ build fails with the static_assert above.
  • With vlIndexForSlot shifted by one, the test fails with "expected rows 0..15 once each, got 16 labels: 1 2 ... 16".
  • The fixture and the README snippet type-check with tsc 5.9.3 (strict).
  • Full core suite, test by test on macOS: 153/155, the same as main apart from the new test. The two failures fail on main too: run-ui-memory-census.sh needs a reference engine, and test_gea_vite_module_graph_assets.mjs is fixed by Point the module-graph asset test's compiler at this checkout's Core #66. run-gea-virtual-list-pipeline.sh (the raw tag) still passes.

Not covered

Scrolling is not tested. onScroll does not fire until geastack/compiler#4 lands, and even then a scrollTop change re-renders VirtualList and replaces its <virtual-list> node, which resets the scroll offset. Both are described in #70. Target scope: native harness tested; other targets source-only.

VirtualListItemTemplate returned any. Every slot renders
{itemTemplate(...)}, and an any result lowers to gea::Value, which
gea::jsx::child has no rule for, so an app that used the component
stopped at a static_assert in the C++ build. No app or test imported the
component, so nothing caught it (geastack#70).

The template's result is now GeaJsxElement, the type core uses for a
component's returned element. It lowers to an element handle that
gea::jsx::child appends. The .d.ts says to wrap plain text in an element:
TypeScript still accepts a string because GeaJsxElement is an empty
interface, but geatsc then refuses it at compile time with a named
conversion error.

Tests: added run-gea-elements-virtual-list-pipeline.sh, which builds the
fixture packages/core/test/fixtures/gea-elements-virtual-list (the
component used the way the README shows) and checks that the list takes
its height from its class and that its 16 slots show rows 0..15 once
each. It passes. With the template typed any again the C++ build fails
with the static_assert, and with vlIndexForSlot shifted by one the row
check fails. The fixture type-checks with tsc 5.9.3 (strict). Scrolling
is not tested: onScroll waits on geastack/compiler#4, and a scrollTop
change replaces the <virtual-list> node (geastack#70).
@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b2fb2052-4aa2-47ca-8b90-89f3a8bb9c68
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

A native build resolves value imports of @geastack/elements to
components/index.ts, not index.d.ts. index.ts exported VirtualList but
not VirtualListProps or VirtualListItemTemplate, so an app that wrote
`import { VirtualList, type VirtualListItemTemplate } from
'@geastack/elements'` type-checked but failed to compile natively with
"has no exported member 'VirtualListItemTemplate'". index.ts now
re-exports both types as index.d.ts does. CameraViewProps has the same
gap and is left for a separate change.

Tests: a scratch app importing VirtualList, VirtualListProps and
VirtualListItemTemplate this way, built with
run-gea-native-app-pipeline.sh: fails with that error before the
change, builds and renders its rows after it.
run-gea-elements-virtual-list-pipeline.sh still passes.
@moersoy

moersoy commented Oct 18, 2026

Copy link
Copy Markdown
Author

Pushed a6771b7: components/index.ts now exports VirtualListProps and VirtualListItemTemplate too. A native build resolves value imports of @geastack/elements to index.ts, so import { VirtualList, type VirtualListItemTemplate } from '@geastack/elements' type-checked but failed in geatsc with "has no exported member". Checked with a scratch app built through run-gea-native-app-pipeline.sh: it fails before the change and builds and renders its rows after it. run-gea-elements-virtual-list-pipeline.sh still passes. CameraViewProps has the same gap and is left for a separate change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant