The onSwap migration turned filter_bar.js, range_slider.js, and
search_select.js into ES modules that register via htmx.onLoad. The five
filter synthetic e2e pages still loaded them as classic `<script defer>`
with no htmx present, so the `import { onSwap }` line was a SyntaxError and
no widget ever initialized — 18 failing tests.
Load htmx.min.js first (classic) and the three widgets as `type="module"`,
mirroring how Page() serves them in the real app. date_range_picker.js
stays a classic defer script (it is an IIFE, not a module).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the DateRangePicker design: a DateRangeField that looks like a
single input but splits each date into DD/MM/YYYY part inputs (ordered by
the new common.time.dateformat_hyphenated), and a DateRangeCalendar popup
with a preset column (today, yesterday, last 7/30 days, this/last month,
this year), anchor-style range picking with an outlined/filled/muted range
track, and a Cancel / Clear / Select footer.
Typing fills each part's placeholder from the right (YYYY -> YY19 -> 1987),
auto-advances between parts, and Backspace/Delete reverts the active part.
The committed value lives in hidden ISO {prefix}-min/{prefix}-max inputs --
the same contract as DateRangeFilter, so filter_bar.js needs no changes.
As a tryout, the Purchased filter in PurchaseFilterBar now uses the
DateRangePicker; Refunded keeps the native-date DateRangeFilter, and the
native-path e2e tests were repointed at it.
Includes unit tests for the component family and the filter-bar
integration, plus Playwright e2e tests for segment entry, calendar
picking, presets, and footer actions.
https://claude.ai/code/session_017b75KJAu4kNNpZPu9NAPBM