Commit Graph

10 Commits

Author SHA1 Message Date
Bastian de Byl a943dd0ebd SEV-392: combobox setOptions() for reactive parent-fed option lists
Passing a parent component's reactive array into the nested combobox x-data
needs x-effect="setOptions(vpicMakes)" — a plain closure over the parent
scope doesn't track Alpine updates. Falls back to config.options for static
lists. 18/18 tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:09:00 -04:00
bastian 6789da1574 Merge pull request 'SEV-392: reusable fuzzy combobox component (+fuzzysort) v0.4.0' (#4) from sev-392/combobox into main 2026-06-10 19:07:17 -04:00
Bastian de Byl a676a3e99a SEV-392: reusable fuzzy combobox component (+fuzzysort) v0.4.0
comboboxData(config) Alpine factory: typeable input + fuzzysort-ranked
dropdown (prefix/substring/abbreviation subsequence matching), keyboard
nav (Arrow/Enter/Escape/Tab), a11y roles, x-modelable value binding.
allowFree (default) accepts off-list typed values so classics/kit cars are
never blocked; allowFree:false for closed lists (US states) snaps back to a
valid option on blur. Foundation for replacing native <select> chrome with
inputs that match our text fields. 17/17 tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:06:38 -04:00
bastian b7abf51087 Merge pull request 'SEV-378: add tolerant formatDate/formatDateTime (v0.3.0)' (#3) from sev-378/format-date into main 2026-06-10 16:36:43 -04:00
Bastian de Byl e405985c34 SEV-378: add tolerant formatDate/formatDateTime to shared (v0.3.0)
Our Go/Turso layer emits SQLite datetime('now') as "YYYY-MM-DD HH:MM:SS"
(UTC, no zone), which new Date() can't parse → "Invalid Date" in admin.
formatDate/formatDateTime normalize that shape (space→T + Z) and RFC3339,
returning '' for falsy/invalid. Tests cover both formats + empties.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 16:36:24 -04:00
bastian 2b54028495 Merge pull request 'SEV-362: format v0.2.0 — boundary spacing, acronyms, formatRange, numeric budget' (#2) from sev-362/format-v0.2.0 into main 2026-06-09 21:08:36 -04:00
Bastian de Byl 65889b6487 SEV-362: format v0.2.0 — boundary spacing, acronyms, formatRange, numeric budget
- formatLabel: letter→digit boundary spacing ("level2" → "Level 2"),
  acronym casing (DCFC/EV/SUV/VIN/DC/A\C), bare numeric ranges pass
  through untouched
- new formatRange: "150-200" → "150–200 mi", "200-plus"/"200+" →
  "200+ mi"; empty → '' (callers render their own placeholder)
- formatBudget is now the numeric (min, max) dollar formatter matching
  the API payload; the wizard's slug map moves to formatBudgetBucket
- new vehicleName({year, make, model, commissioned})

Breaking rename of formatBudget is safe: no frontend consumes 0.1.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 21:08:03 -04:00
bastian 50379c1868 Merge pull request 'SEV-329: @switchev/web-shared package (formatters, markdown, waitForImage)' (#1) from sev-329/web-shared-package into main 2026-06-09 09:44:29 -04:00
Bastian de Byl 137086109c SEV-329: @switchev/web-shared package — formatters, markdown, waitForImage
Stands up the shared browser-helpers package (consumed by public/vendor/admin
via the Gitea npm registry) to de-duplicate copy-pasted frontend code:
- format.js: formatLabel/formatStatus/formatTimeline/formatBudget (single source
  of truth — these had drifted, see SEV-310).
- markdown.js: renderMarkdown (marked + strict DOMPurify; both peer deps).
- wait-image.js: waitForImage (was byte-identical in public + vendor).

ESM source package (no build step — Vite consumers import directly). publishConfig
points at the Gitea npm registry. node --test green (formatters).

Next: publish v0.1.0, then migrate each site to consume it and delete the copies.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 09:42:38 -04:00
Bastian de Byl cb1d8ff661 SEV-17: Initial commit 2026-02-17 17:03:53 -05:00