745f20c9ec
* fix: fire `select` event on the Tabs container itself
The frontend event dispatcher remapped a Tabs `select` event onto the
selected child Tab's logical `id`, so a listener attached to the Tabs
container (`tabs.select(...)`) never matched its dependency and never
fired. It also used the tab's user-facing `id`, which fails to match a
`TabItem.select(...)` dependency whenever the tab was given an explicit
string id (e.g. `gr.Tab("A", id="a")`).
Dispatch the event to both the selected TabItem (by its `component_id`,
which always identifies the component) and the original Tabs container,
so listeners on either fire correctly. Adds e2e coverage for the
container-level `select` event.
Ref #3793
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* changes
* simplify: dispatch Tabs select only to container; drop redundant per-tab forward
The selected TabItem already dispatches its own `select` event, so forwarding
the container's `select` to the child component id fired `tab.select` twice
(observable under trigger_mode="multiple"). Removing the forward fixes the
double-fire while keeping the container-level `tabs.select(...)` fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test: count tab.select via separate non-racy listener to fix flaky demo
Making get_selected_index stateful (read+write select_count) under
trigger_mode="multiple" raced the initial-load select against the clicked
select, letting a stale write win and breaking the `correct selected tab
shown` e2e test. Restore get_selected_index to its original form and count
selects via a separate server-side accumulator listener instead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>