# Changelog

Source: https://lumeo.nativ.sh/docs/changelog

# Changelog

All notable changes to Lumeo are documented here. Each release groups changes into Added, Improved, and Fixed categories.

v3.1.0

May 2026

Two new core components (AudioPlayer + SignaturePad) and three new satellite packages (PdfViewer, Maps, CodeEditor). DataGrid column chooser gains a pin UI and drag-to-reorder. Purely additive — no migration required from 3.0.x.

### Added

-   **AudioPlayer.** Themed audio player with play/pause, scrub bar, time, volume, optional cover slot, and download button. Wraps the native `<audio>` element; exposes `OnPlay` / `OnPause` / `OnEnded` / `OnTimeUpdate` callbacks.
-   **SignaturePad.** Canvas-backed signature capture via mouse / touch / stylus. Configurable stroke color + width, transparent or solid background, PNG / JPEG / WebP output, optional download, and a disabled mode for read-only display of previously captured signatures.
-   **Lumeo.PdfViewer satellite.** New optional NuGet package for rendering PDF documents inline.
-   **Lumeo.Maps satellite.** New optional NuGet package for interactive map embeds.
-   **Lumeo.CodeEditor satellite.** New optional NuGet package for a Monaco-style in-browser code editor.
-   **DataGrid PinColumn UI.** Per-column pin / unpin (left / right) inside the column chooser flyout, in addition to programmatic pinning.
-   **DataGrid drag-to-reorder columns.** Reorder columns directly inside the column chooser by drag-and-drop; order persists with the grid's existing state hooks.
-   **Batch edit mode segment in the playground.** New segment on the DataGrid playground page to flip between row / cell / batch edit modes live.

### Improved

-   **DataGrid per-column toggles are reactive.** `Sortable` and `Filterable` on `DataGridColumnDef` now update at runtime — the column re-registers on `OnParametersSet` instead of only on first render, so toggling them from parent state works without an explicit grid refresh.

### Internal

-   5 new media methods and 7 new SignaturePad methods added to `IComponentInteropService` to back the new components.

v3.0.5

May 2026

Soft borders + accessibility polish — a visual calm-down across the surface and a keyboard / screen-reader pass that closes the last gaps on triggers and overlays. No API changes; drop-in upgrade from any 3.0.x.

### Improved

-   **Soft borders sweep — 27 components.** `border-border` → `border-border/40` on popovers, menus, hover cards, cards, and other neutral surfaces. Semantic borders (focus rings, active states, destructive variants) deliberately left at full opacity so they still read as state changes.
-   **Accessibility + keyboard polish — 23 components.** Dialog / Sheet / Drawer / Popover / AlertDialog triggers and close buttons now handle `Enter` and `Space`. Icon-only buttons across the library gained `aria-label` + explicit `type="button"`. Image / ImageGallery preview overlays announce as `role="dialog"` with auto-focus on open. Pagination current page gets `aria-current="page"`; Steps active step gets `aria-current="step"`; Sidebar collapsible groups expose `aria-expanded`.
-   **Icon resolver coverage.** ~66 new Lucide names mapped in the `DynamicIcon` resolver — fewer fall-throughs to the default icon when consumers wire up arbitrary Lucide names.

### Added

-   **DataGrid playground.** New page at `/components/datagrid/playground` — 29 toggles across 10 sidebar groups, collapse / expand the controls via `SidebarTrigger`. Click anything and see the grid reconfigure live; great for evaluating before vendoring.
-   **Living demo reel on the home page.** Hero stats with NumberTicker, an auto-cycling carousel of Tabs / BarChart / Toast / Stepper / Sparklines, a Kanban with real drag-and-drop, and a DropdownMenu submenu tile. Replaces the static screenshots with components driving themselves.

v3.0.4

May 2026

DataGrid aggregate-row layout fix — the final shape after two earlier attempts in 3.0.2 / 3.0.3.

### Fixed

-   **DataGrid aggregate row extracted to a sibling strip.** Previously the aggregate row sat inside the table footer / scroll region, which broke sticky-header math when the grid scrolled and double-counted height under fullscreen. It now renders as a sibling element next to the scroll container — sticky header, sticky aggregate, no overlap. This supersedes the 3.0.2 and 3.0.3 attempts at the same problem.

v3.0.3

May 2026

Intermediate DataGrid aggregate-row patch. Superseded by 3.0.4 — recommend skipping straight to 3.0.5.

v3.0.2

May 2026

First attempt at the DataGrid aggregate-row layout fix. Superseded by 3.0.4 — recommend skipping straight to 3.0.5.

v3.0.1

May 2026

Polish patch — cosmetic bug fixes plus one additive surface for global mobile-gesture tuning.

### Fixed

-   **Accordion / Collapsible smooth animation.** Previous keyframe interpolated `height: 0 → auto`, which CSS can't animate — content snapped in instantly. Now uses the modern `grid grid-rows-[0fr] / [1fr]` trick, smooth in both directions, zero JS.
-   **Tabs Card variant baseline.** Added `border-b border-border/40` on `TabsList` + `-mb-px` on active triggers so Card tabs sit on a real baseline.
-   **Toast close button needed two clicks.** The 3.0 pause-on-hover wiring intercepted focusin events. Fixed by stopping focusin propagation on the close button.
-   **Chevron rotations.** DataGrid group-panel trigger, DataGridGroupRow, DataGridRow (expandable detail), PivotGrid, FileManager, TreeViewNode — replaced icon-swap with a single chevron + `transition-transform` + conditional `-rotate-90`.

### Added

-   **`TabsList.SavedLayout` + `OnLayoutChanged`** — mirrors DataGrid's layout persistence pattern for the 3.0 `Reorderable` Tabs.
-   **`LumeoGestureOptions`** — single DI-registered options bag (`SwipeThresholdPx`, `VerticalDeadZonePx`, `SwipeDismissThresholdPx`, `SwipeDismissFirePx`) consumed by Tabs / Carousel / Calendar / ImageGallery / Drawer / Sheet swipe handlers. Defaults match the previously hardcoded values.

v3.0.0

May 2026

**Major release.** Four tiers of changes that landed together: a Tier 1 reliability sweep, a batch of consumer-facing helpers, Tier B quality fixes, Tier C new features, and Tier D — a **breaking enum unification** that collapses every per-component size / side / align / orientation enum into four library-wide types. Migration is mechanical; see `MIGRATION.md` in the repo root for the rename recipe.

### Tier 1 — Reliability

Automatic nested overlay stacking (Dialog/Sheet/Drawer/AlertDialog allocate z-index per overlay, Escape closes the top one); `OnBeforeClose` + `DismissEventArgs` (Reason: _escape / outside / swipe / close / action / cancel_) on the same four overlays so consumers can intercept dismissals; toast hover/focus pauses the auto-dismiss timer and the ARIA role is now variant-aware (Destructive → `role=alert` + `aria-live=assertive`; others → `role=status` + `aria-live=polite`); tooltip viewport-edge auto-flip.

### Helpers

`Form.ResetValues()` restores the model snapshot captured on first render (the existing `Form.Reset()` only clears errors / dirty / submitting state). DatePicker gained `AllowKeyboardInput` (default true) + `OnParseError` so typed dates round-trip cleanly; readonly opt-out is one prop.

### Tier B — Quality

DateTimePicker is now time-zone aware: `TimeZone` (a `TimeZoneInfo`), `OffsetValue` (a `DateTimeOffset`), and `ShowTimeZoneLabel` so users see which zone they're working in. FormField gained async validation — `AsyncValidator`, `AsyncValidationDebounceMs`, `AsyncValidateOn` (_OnBlur / OnChange_), `IsValidating`, `OnValidatingChanged`, and `FormContext.IsAnyFieldValidating` for submit-button gating.

### Tier C — Features

`TabsList.Reorderable` + `OnReorder` (`TabsReorderEventArgs`: `FromIndex`, `ToIndex`, `MovedTabValue`) — the consumer mutates the collection, the library handles drag UX. New Submenu support across `DropdownMenu`, `ContextMenu`, and `Menubar` via `*Sub` / `*SubTrigger` / `*SubContent` with hover-intent open, ArrowLeft/ArrowRight navigation, and Escape-closes-the-whole-tree.

### Tier D — BREAKING: enum unification

The per-component _Size_, _Side_, _Align_, and _Orientation_ enums (e.g. `Button.ButtonSize`, `Tooltip.TooltipSide`, `Sheet.SheetSide`, `Popover.PopoverAlign`, `Tabs.TabsOrientation`) have been replaced by four library-wide types in the `Lumeo` namespace: `Lumeo.Size`, `Lumeo.Side`, `Lumeo.Align`, `Lumeo.Orientation`. The rename is mechanical (search-and-replace) and the values are 1:1 across the old and new types — see `MIGRATION.md` for the full per-component recipe.

v2.2.3

May 2026

**Reliability fixes — four Blazor sync-context / async-void / fire-and-forget gotchas that could surface as silent failures or circuit crashes under specific timing conditions.** Each fix is small and localised; the pattern is consistent across all four sites: move callback work back onto the Blazor sync context (`InvokeAsync`) so exceptions are observable, and return / await tasks instead of fire-and-forget.

### Fixed

-   **`FileUpload`**: auto-upload no longer dispatched via `Task.Run` (which hopped to the thread pool and forced every inner `StateHasChanged` to marshal back through `InvokeAsync`). Replaced with a direct `InvokeAsync(async () => …)` + try/catch that surfaces systemic upload failures on each pending item's `Status` + `ErrorMessage`.
-   **`DateWheelPicker` + `TimeWheelPicker`**: `CommitDay`/`CommitMonth`/`CommitYear`/`CommitHour`/`CommitMinute`/`CommitPeriod` were `async void`. Any exception thrown after the first await escaped to the thread-pool finalizer and crashed the circuit. Converted to `async Task`; `ResetTimer`'s commit parameter is now `Func<Task>` so `InvokeAsync` can observe completion.
-   **Wheel-picker init delay**: `Task.Delay(150).ContinueWith(_ => InvokeAsync(...))` ran the continuation on the thread pool and silently swallowed any exception (including the typical `JSDisconnectedException` during circuit teardown). Replaced with `InvokeAsync(async () => { await Task.Delay(150); … })` + explicit `JSDisconnectedException` catch.
-   **`DatePicker.SetIsOpen`** + **`HoverCard.OnClickOutside`**: `_ = OpenChanged.InvokeAsync(value)` fire-and-forget — a faulting consumer handler vanished into the void. Now wrapped in `InvokeAsync` + try/catch (DatePicker) or returned via `await` (HoverCard, whose caller is async-aware).

No new tests — these are runtime-conditions that no existing test exercises; the fixes are mechanical pattern replacements. The library audit that surfaced them is at `/tmp/lumeo-quality-audit.md` (Critical tier).

v2.2.2

May 2026

**DataGrid Groupable-column drag affordance + group-panel placeholder localisation.** Two follow-ups from real users hitting the new themed group-panel in 2.2.0/2.2.1: there was no visual indication on column headers that they support drag-into-panel (users had to try each one to discover which were Groupable), and the panel's "Drag a Groupable column header here…" placeholder was still hardcoded English (missed by the 2.2.0 i18n sweep).

### Added

-   **Drag-to-group affordance on column headers** — when `ShowGroupPanel="true"` and the column is `Groupable`, the header now reveals a muted Group icon on hover (mirroring the filter button's opacity pattern), plus the cell carries `cursor-grab`. Title attribute uses `L["DataGrid.DragToGroup"]` ("Drag to group by this column" / "Zum Gruppieren nach dieser Spalte ziehen"). Both icon + cursor are hidden when there's no panel to drop into, so non-grouping grids aren't cluttered.

### Fixed (i18n)

-   **Group-panel empty-state placeholder** "Drag a Groupable column header here, or use the dropdown" was still a hardcoded English literal inside `@(GroupPanelText ?? "…")` — the 2.2.0 i18n agents missed it because of the null-coalesce shape. Now routes through `L["DataGrid.GroupPanelPlaceholder"]`. Consumers passing an explicit `GroupPanelText` still take precedence — back-compat preserved.

### Localisation keys added

-   `DataGrid.GroupPanelPlaceholder` (EN + DE)
-   `DataGrid.DragToGroup` (EN + DE)

v2.2.1

May 2026

**DataGrid group panel: hard-right alignment + persistence on grouping changes.** Two 2.2.0 regressions surfaced by the first consumer of the new themed group-panel: the new "+ Add group level" `DropdownMenu` didn't sit at the right edge of the panel, and grouping mutations weren't being written to localStorage even though sort/filter/columns were.

### Fixed

-   **Group panel "+ Add group level" picker now right-aligned** — the 2.2.0 refactor moved the trigger into a `<DropdownMenu>` component, which renders its own `relative inline-block` wrapper as root. The `ml-auto` on the inner trigger button had no effect on the flex-parent panel because `DropdownMenu` was the actual flex child. Wrapped the component in a `<div class="ml-auto">` so the picker sits hard-right again.
-   **Grouping changes now persist to `localStorage`** — `AddGroupField` / `RemoveGroupField` / `ClearGroupFields` didn't call `ScheduleAutoSave()`, so the snapshot serialization built in v2.1.1 had nothing to act on. Sort/filter changes had been calling it from day one. Three matching `ScheduleAutoSave()` calls added — grouping now round-trips through reload identically to sort/filter/columns.

No new tests — the existing v2.1.1 snapshot-and-restore tests cover the persistence contract; the missing trigger was the bug. The right-align fix is visual and covered by manual verification in the PR checklist.

v2.2.0

May 2026

**Theming & accessibility polish — a quality release.** A library-wide sweep across CSS theming, keyboard accessibility, and i18n coverage. No new public API surface, no breaking changes — but the library is now consistently themable, keyboard-navigable, and translatable end-to-end.

### Fixed (CSS theming)

-   **Placeholder hover-override (B1)** — inner `<span class="text-muted-foreground">` placeholder text inside hover-styled trigger buttons no longer becomes illegible on hover (dark grey on accent green). Fixed across `TimePicker`, `DateTimePicker`, `DatePicker` (5 placeholder spans) via `group` + `group-hover:text-accent-foreground`.
-   **DataGrid group-panel "+ Add group level" dropdown** — was a native HTML `<select>` rendering with OS-default chrome (white-on-blue on Windows). Replaced with Lumeo's own `<DropdownMenu>` + `<DropdownMenuItem>`.
-   **`NavigationMenuMobile`** — `Class` and `AdditionalAttributes` were declared but never propagated to a root element. Now applied (Class merged into inner SheetContent; AdditionalAttributes on the inner div).

### Improved (accessibility — keyboard focus)

-   **~110 new `focus-visible:ring-*` rings** across ~45 files: DataGrid (header sort/filter buttons, toolbar buttons, row expand/edit/save/cancel, batch ops), Editor (toolbar, BubbleMenu, AiActionMenu), QueryBuilder (combinator pills), Calendar (day cells + nav buttons), Tour, DatePicker preset buttons, ThemeSwitcher swatches, Pagination, NumberInput steppers, FileUpload buttons, TreeViewNode, Sortable handles, RadioGroupCard, MegaMenuLink, PivotGrid, Segmented, ConsentBanner, ImageGallery, InplaceEditor, ReasoningDisplay, FileManager, TreeSelect, PromptInput, PickList, BackToTop, Transfer, and more.
-   **Special-case patterns spotted & fixed**: hover-revealed icon buttons (`group-hover:opacity-100`) now also reveal on keyboard focus via `focus-visible:opacity-100`; adjacent button-groups (steppers, file-action rows) use `focus-visible:relative focus-visible:z-10` so rings aren't clipped; overlay/lightbox buttons over `bg-black/80` backdrops use `ring-white` for visibility.

### Improved (i18n — multi-lingual UI)

-   **62 hardcoded English UI strings routed through `ILumeoLocalizer`** across ~32 components (FileManager 15, QueryBuilder 8, PickList 4, Scheduler 3, ThemeSwitcher 3, and many one-offs across aria-labels, titles, placeholders, default parameter values).
-   **~50 new localization keys** added to `LumeoDefaultStrings.cs` (English + German pairs). New namespaces: `FileManager.*`, `QueryBuilder.*`, `PickList.*`, `Scheduler.*`, `Theme.*`, `Chart.*` (Loading), `BottomNav.*`, `Dock.*`, `Badge.*`, `Chip.*`, `Alert.*`, `ImageCompare.*`, `PromptInput.*`, `PivotGrid.*`, `Editor.*`, `Tabs.*`.
-   **`Effective*` nullable-parameter pattern** introduced for default-value localization (e.g. `LoadingText` on Charts, `AriaLabel` on Dock/BottomNavFab/TriggerDropdown/ToastClose, `GrandTotalLabel` on PivotGrid). Consumers passing explicit strings still work — back-compat preserved.

### Docs

-   Hero badge bumped to v2.2.0. Install snippets (Code, Cli) updated to `--version 2.2.0`.
-   `lumeo-mcp` package.json + package-lock + src/index.ts + src/registry.json bumped to 2.2.0 (lockstep).
-   New `DataGrid.AddGroupLevel` key (EN/DE) added.

### Known follow-ups (deferred to 2.2.1)

-   `QueryBuilderGroup` Field/Operator pickers still use native `<select>` with themed trigger but OS-default dropdown popup. `InplaceEditor` the same. Refactor to `<Select>` needs the disabled-placeholder pattern.
-   `StepperStep` is a pure-registration component; its `Class` parameter is currently dead. Plan: thread through `StepRegistration` record so parent `Stepper` can apply it.

No new bUnit tests for this sweep — the changes are non-behavioural (CSS classes, aria-labels, localization keys). Existing test suite continues to pass.

v2.1.4

May 2026

**JS module import URL gets a `?v=<version>` cache-buster.** Library JS under `_content/Lumeo/js/components.js` is served WITHOUT a content-hash (unlike the Blazor framework files), so an already-loaded browser tab kept its 2.1.2 `components.js` after upgrading the lib to 2.1.3 — and new C# code calling new exports like `registerViewportListener` threw `JSException: 'registerViewportListener' is not a function` at runtime. Fixed by appending `?v=<assembly-version>` to library module imports.

### Fixed

-   **`ComponentInteropService.GetModuleAsync`** + **`ImportModuleAsync`** now append `?v={assembly-version}` to all `_content/Lumeo*/` module URLs. `KeyboardShortcutService.GetModuleAsync` updated symmetrically.
-   **Upgrades from this release forward** are immune to the stale-cache class of failure when new JS exports are added in the lib (e.g. the v2.1.3 `registerViewportListener` failure). v2.1.3 users hitting that error today need a hard refresh (`Ctrl/Cmd+Shift+R`); from v2.1.4 the cache-buster handles it automatically.

### Notes

-   Version derived once from `AssemblyInformationalVersionAttribute` (which `Directory.Build.props <Version>` drives), so it tracks every release without manual maintenance.
-   URLs that already contain a query string pass through untouched — consumer overrides (e.g. local debugging with `?nocache=1`) are preserved.
-   Non-library URLs are passed through unchanged, so consumer JS modules loaded via `ImportModuleAsync` aren't affected.

v2.1.3

May 2026

**Responsive overlays, polished swipe gesture, and 100% docs parameter coverage.** Three threads landed together: a reactive `IResponsiveService` + per-overlay mobile overrides so a single `Overlay.ShowSheetAsync` can switch from side panel on desktop to fullscreen bottom-sheet on mobile and back across rotation; a swipe gesture rewrite (10px activation deadzone + direction lock + rubber-band) that kills the wackelig feel users reported on small finger movements; and a full sweep of the API tables on every component docs page so every `[Parameter]` is now documented (500+ rows added across 60 pages).

### Added

-   **`IResponsiveService`** — reactive viewport/breakpoint service. Exposes `Width`, `Height`, `Current` (`Breakpoint` enum: Xs/Sm/Md/Lg/Xl/Xxl aligned with Tailwind v4), `IsMobile`/`IsTablet`/`IsDesktop`, and a `ViewportChanged` event. One JS resize listener per circuit, debounced 100ms.
-   **`OverlayOptions.MobileBreakpoint/MobileSheetSide/MobileSheetSize/MobileSwipeToClose`** — per-overlay responsive overrides. Below `MobileBreakpoint` (default 768px = Tailwind md) the `Mobile*` fields take precedence. `OverlayProvider` re-renders reactively on viewport crossing — sheet flips correctly when a tablet is rotated mid-flight.

### Improved

-   **Swipe gesture (Sheet + Drawer)** — previously the element followed the finger from pixel 1 with no axis lock; users reported the sheet felt wackelig on micro-movements and accidentally engaged on diagonal scroll attempts. Now: **10px activation deadzone** (finger must commit before the sheet moves), **direction lock at activation** (gesture locked to the dominant axis — diagonal-on-bottom-sheet scrolls content instead of dismissing), and **rubber-band past 150px** so the sheet doesn't fly off-screen when the user keeps pulling. Dismiss threshold (100px) unchanged.
-   **Docs parameter coverage now 100%** across all 163 components — 504 missing API table rows added across 60 pages (largely Chart components which previously documented their core 5 params but not the recurring Width/Height/Theme/ColorPalette/AnimationDuration/MarkLine/MarkPoint/Toolbox surface).

### Docs

-   Hero badge bumped to v2.1.3.
-   OverlayService page: `OverlayOptions` table gains the four `Mobile*` rows; new "Responsive sheets" section with the desktop-Right ↔ mobile-Bottom example.
-   Sheet page: cross-reference to `IResponsiveService` for live-reactive sizing decisions.
-   New `IResponsiveService` docs page covering the API and the recommended subscription pattern.

~10 new bUnit/xUnit tests cover the responsive service (FromWidth mapping, event firing, breakpoint flags) and the OverlayOptions responsive defaults. Swipe-threshold change is JS-only — relies on manual mobile testing per the PR checklist.

v2.1.2

May 2026

**DataGrid column filter popover no longer spawns a phantom horizontal scrollbar.** On the rightmost columns of a grid with `overflow-x:auto`, opening a column filter made the entire grid scroll horizontally. The popover wrapper was `position:absolute` relative to its `<th>`, so its content extended past the cell edge and was counted in the scroll-container's `scrollWidth`. Fixed by reusing the Floating-UI-style positioner that `PopoverContent` already uses — `position:fixed` with coords from the trigger's `getBoundingClientRect()`, follow on scroll/resize, and viewport-flip when overflow would push the popover off-screen.

### Fixed

-   **DataGrid column filter popover** now renders with `position:fixed` instead of `position:absolute`. The popover is pinned to the trigger via `Interop.PositionFixed` (same path as `PopoverContent`), so its layout box no longer contributes to the scroll container's `scrollWidth`.

### Improved

-   **Filter popover click-outside dismiss** — previously the popover only closed via Apply / Clear; clicking elsewhere left it open. Now registers a click-outside listener (excluding the trigger so the toggle button doesn't immediately close-then-reopen) and follows the trigger on grid scroll/resize.

2 new bUnit regression tests guard the inline `position:fixed` + stable trigger-id contract that the JS positioner depends on.

v2.1.1

May 2026

**DataGrid group panel survives reload, Sheet mobile-fullscreen, OverlayService swipe-to-close.** Four real library fixes folded into a single patch release. The biggest one: layout snapshots silently dropped the runtime group-panel chips so multi-level grouping vanished on reload while sorts/filters/columns restored cleanly.

### Fixed

-   **DataGrid layout persistence**: `SnapshotCurrentLayout` and `BuildLayoutSnapshot` now capture `_runtimeGroupFields`; `ApplyLayoutAsync` / `ApplyLayoutSnapshotAsync` restore the panel chips. Internal `DataGridLayout` + public `DataGridLayoutSnapshot` gain `GroupByFields`; snapshot version bumped 1 → 2. v1 payloads still load via the legacy single-level `GroupBy` fallback.
-   **DataGrid column filter popover**: custom `FilterTemplate` rows with `hover:bg-accent` painted past the rounded-lg corners. `DataGridColumnFilter` wrapper gains `overflow-hidden`; `w-64` → `min-w-64` so wider templates grow the popover instead of overflowing.

### Improved

-   **Sheet `Size="Full"` on Top/Bottom**: now produces a true mobile-fullscreen sheet (`inset-y-0 h-full max-h-full`) instead of being a silent no-op. `Sm`/`Lg`/`Xl` cap height at 40/70/85vh for symmetry with Left/Right width caps. `Default` keeps legacy content-driven height — back-compat.
-   **OverlayService `OverlayOptions.SwipeToClose`**: programmatically-opened Sheets can now be swipe-dismissed, matching the declarative `<SheetContent SwipeToClose="true">` path. Drawers already had swipe-close by default; this puts Sheets at parity. Default `false` — back-compat.

### Docs

-   DataGrid page: Persistence demo description and "Saving and loading layouts" prose now mention the group panel is included; `Version: 2` noted alongside the v1-backcompat clause.
-   Sheet page: `Size` row now documents the Top/Bottom height behaviour and the Full-on-Bottom mobile-fullscreen pattern.
-   Overlay Service page: `SwipeToClose` added to the OverlayOptions API table.

12 new bUnit tests cover snapshot capture & round-trip (incl. v1 back-compat), filter popover clipping, Sheet sizing on Top/Bottom, and OverlayService option routing.

v2.1.0

May 2026

**DataGrid: multi-level grouping & the runtime group panel now work in `ServerMode`.** Single-level `GroupBy` already worked in ServerMode; `GroupByFields` and the panel handlers (drag-to-group, add-level dropdown, per-chip remove, clear-all) were silently no-ops because each UI mutator short-circuited with `if (!ServerMode) ProcessClientData()`. They now route through a shared `RegroupServerItems()` that delegates to the same `ProcessSingleLevelGrouping` / `ProcessMultiLevelGrouping` client mode uses — so multi-level, expand-state preservation, and per-group aggregates are now symmetrical across modes.

### Improved

-   **DataGrid `ServerMode`**: `GroupByFields` (multi-level) now applies to server-returned items.
-   **DataGrid group panel (`ShowGroupPanel="true"`)**: drag-to-group, add-level dropdown, per-chip remove, and clear-all all fire in ServerMode without an extra server round-trip.
-   **Per-page semantic preserved**: grouping runs over the rows the server returned for the current page. For cross-page grouping, either disable pagination (`ShowPagination="false"`) so the server delivers all rows in one response, or have the server pre-aggregate groups itself. This is a consumer-side architecture choice, not a grid limitation.
-   **Side benefit**: ServerMode single-level grouping now also computes per-group aggregates (was previously client-mode only) because the unified path runs through `ProcessSingleLevelGrouping`.

### Docs

-   DataGrid component page: new ServerMode-grouping callout above the Server-Side Mode demo; `GroupBy` + `GroupByFields` parameter rows clarified; "Group panel & multi-level grouping" section gains a per-page-caveat paragraph.
-   MCP registry description updated across registry.json, registry-search.json, registry/data-grid.json, components-api.json, and skills catalog to advertise "multi-level group (client + server)".

2438/2438 tests pass · core + DataGrid + docs build clean (0/0). 6 new bUnit tests cover ServerMode multi-level grouping and each UI handler.

v2.0.1

May 2026

**MCP registry fix — regenerated against the 2.0.0 component surface.** The MCP data files were last generated at rc.38 and never regenerated for 2.0.0, so they shipped 145 components labelled `2.0.0-rc.38` while the library had grown to 149. npm forbids overwriting the published `@lumeo-ui/mcp-server` 2.0.0, so the fix ships under a new lockstep version.

### Fixed

-   **RazorParameterScanner**: only parsed the LAST `@code` block, silently dropping all 14 of FileManager's `[Parameter]`s. Now parses every `@code` block independently and merges results — so Checkbox's markup-bearing RenderFragment block no longer corrupts extraction.
-   **RegistryGen version source**: now reads the lockstep `<Version>` from `Directory.Build.props` instead of two hardcoded literals (one was still `2.0.0-rc.38`) — registry can't drift again.
-   **Stale install snippets in docs**: the Code component demo and CLI docs page hardcoded `--version 2.0.0`. RegistryGen pulls the Code example into `components-api.json`, so MCP clients got stale guidance — the exact bug class this release fixes. Bumped to `2.0.1`.

### Changed

-   **Lockstep bump**: `Directory.Build.props` 2.0.0 → 2.0.1; `tools/lumeo-mcp` package.json + index.ts → 2.0.1.
-   **Regenerated registry**: 149 components, 3510 params, 104 enums, 59 records, 0 parse failures. Skill catalog auto-resynced via `sync-skill-catalog.yml`.

v2.0.0

May 2026

**First stable release — the rc.1..rc.54 series is superseded.** Promotes the lockstep version from `2.0.0-rc.54` to `2.0.0`. Readiness audit + Codex review both green: `Lumeo.slnx -c Release -warnaserror` shows 0 errors / 0 warnings, 2475 tests green, 16/16 E2E against the Release docs server, and shipped NuGet packages have no vulnerable dependencies.

### Release prep — blockers

-   **README**: replaced the release-candidate callout with stable-2.0 language; pinning guidance updated to `2.0.0+`.
-   **Companion package drift**: `tools/Lumeo.Cli` and `templates/Lumeo.Templates` had a hardcoded `2.0.0-rc.16` (38 RCs behind). Removed the override so both inherit the lockstep `Directory.Build.props` version.
-   **MIGRATION.md**: documented the rc.53 `IComponentInteropService.RegisterCarouselSwipe` scrollHandler signature change (`Func<double,double,Task>` → `Func<double,double,int,Task>`) as breaking change #6.

### Release prep — Codex findings

-   **npm audit clean at `--audit-level=high`**: `tools/lumeo-mcp` went from 4 vulns (1 high via `express-rate-limit` → vulnerable `ip-address`) to 0; `docs/Lumeo.Docs` from 1 high to 0.
-   **SECURITY.md**: supported-versions table, private disclosure channels (GitHub Security Advisories + `security@nativ.sh`), response SLAs, scope, and dependency-hygiene statement.
-   **Package READMEs**: all 9 packable projects now set `<PackageReadmeFile>README.md`. Shared packing rule centralised in `Directory.Build.targets` (not `.props` — .props is imported before the project body so the conditional wouldn't see PackageReadmeFile). Zero NU5039.

### Open-source declutter

-   **Removed 25 internal audit docs** from loose `docs/*.md` (release-readiness iterations + business-sensitive market-gap-analysis). User-facing docs at `docs/Lumeo.Docs/` untouched (632 files). Gitignored the path so internal notes can't re-enter the published tree.
-   **Removed `docs/superpowers/`**: 146 files of internal AI-workflow scaffolding (audits, implementation plans, workspace matrices). Preserved in git history.
-   **Removed scratch build-dump txt files**: `_p2.txt`, `build_lib.txt`, etc. — accidentally tracked stdout dumps. Gitignored the patterns.
-   **Dropped stale `.github/SECURITY.md`**: still claimed pre-1.0 status. GitHub resolves `.github/` over root, so the Security tab was showing the outdated policy. Removing the duplicate makes GitHub fall back to the canonical root file.
-   **README refreshed for stable**: PackageReference examples 2.0.0-rc.54 → 2.0.0; component count consistent at 145; stale "~530 KB" core-size claim replaced with a link to the live `/docs/bundle-facts` page.

2475 tests green (2424 unit + 20 docs + 31 registry-gen) · 16/16 E2E against the Release docs server · zero vulnerable dependencies in shipped packages.

v2.0.0-rc.54

May 2026

**Toast deep-fix — close-button focus ring + mobile viewport collapse.** ToastClose's focus ring was invisible on coloured variants and the X was opacity-0 for keyboard users; mobile toast viewports squeezed title + description + close + action into unreadable widths on 360px screens.

### Fixed

-   **ToastClose focus ring**: `focus:ring-1` (1px, no color) → `focus-visible:ring-2 ring-current ring-offset-1` — visible on every variant including Destructive/Success/Warning/Info (`ring-current` inherits text color → contrast guaranteed).
-   **ToastClose keyboard reveal**: `focus-visible:opacity-100` ensures keyboard focus surfaces the X on desktop (was `opacity-0 sm:group-hover:opacity-100`, invisible to keyboard users).
-   **ToastClose affordance**: hover/focus background (`bg-foreground/10`) + text-color shift instead of just an opacity tween.
-   **ToastViewport mobile collapse**: all 6 positions now collapse to bottom-center with `inset-x-4` (16px gutters) below the sm breakpoint. Width is `w-auto sm:w-full sm:max-w-[420px]` — mobile fills gutters, desktop caps at 420px. Developer-chosen position takes effect unchanged from sm: upwards.

2424 + 20 + 31 = 2475 tests green.

v2.0.0-rc.53

May 2026

**Swipe re-registration + Carousel jitter + Toast mobile + PullToRefresh DevTools + polish.** Five mobile-sprint follow-ups: rc.52's Tabs/Calendar swipe worked only on the first activation (the panel DOM was recreated on switch, leaving the new element with no pointer listeners), Carousel touch-release fought native scroll-snap, Toast's close button overlapped text on mobile, and PullToRefresh failed under DevTools emulation.

### Fixed

-   **Tabs swipe re-registration**: gated on `firstRender` + one-shot flag; in Active render mode the panel DOM is recreated on every switch. Replaced with bidirectional `_swipeAttached` tracking — `OnAfterRenderAsync` now re-attaches whenever the panel becomes active.
-   **Calendar swipe re-registration**: same root cause when switching view to Months/Years and back to Days. Same `_swipeAttached` pattern; swipe stays scoped to Days view by design.
-   **Carousel touch jitter**: on release, browser scroll-snap momentum AND an imperative `scrollIntoView({behavior:smooth})` fired simultaneously, producing visible jumps. Removed the touchend listener — native scroll-snap handles release smoothly. `onScroll` now reports the nearest snapped index back to .NET to keep `_currentIndex` in sync.
-   **Toast mobile padding**: 44px close button overlapped toast text because content padding was a fixed `pr-6`. Changed to `pr-11 sm:pr-6`. Close button flush to corner on mobile (`right-0 top-0`), offset on desktop.
-   **PullToRefresh DevTools**: DevTools mobile emulation reports `pointerType='mouse'` and drops pointermove events when the pointer drifts outside the element. Added `setPointerCapture` on pointerdown so the move stream stays alive.
-   **Chip dismiss X**: replaced rc.49's negative-margin hit-area trick with a `before:absolute` pseudo-element — visual size back to a compact 20×20 px X with no visible padding sprawl.

### Changed (internal)

-   **BREAKING (internal API)**: `IComponentInteropService.RegisterCarouselSwipe` scrollHandler signature changed from `Func<double, double, Task>` to `Func<double, double, int, Task>` (added current snap index). Only caller is Carousel.razor; no external consumers expected.

### Docs polish

-   **TouchRipple**: new "When to use TouchRipple vs Button's built-in ripple" Alert + canonical demo wrapping a Card with three tappable list rows.
-   **SafeArea**: realistic sticky bottom-tab-bar demo pinned above the iPhone home indicator via `SafeArea Bottom="true"`.
-   **Pagination**: demos wrapped in `overflow-x-auto` containers + mobile-tip Alert pointing to the Compact variant.

2424 + 20 + 31 = 2475 tests green (3 new swipe re-registration regression tests: 1 Tabs, 2 Calendar).

v2.0.0-rc.52

May 2026

**Tabs swipe + Calendar swipe + Image pinch/swipe + haptic feedback + 44px polish.** Five new mobile-feature additions across existing components plus a dedicated Mobile Playground docs page for testing the whole mobile stack in DevTools or on a real phone.

### Added

-   **Tabs** — `SwipeEnabled` / `SwipeWrap` params. Horizontal swipe on `TabsContent` switches panels (50px threshold, 30px vertical guard, `touch-action: pan-y`, interactive-child bailout). New `registerTabSwipe` JS helper.
-   **Calendar** — `SwipeEnabled` (default true) on the day-grid navigates between months; chevrons bumped to `h-11 w-11 sm:h-7 sm:w-7` for WCAG 2.5.5. New `registerHorizontalSwipe` JS helper.
-   **ImageGallery** — `GesturesEnabled` (default true). Fullscreen viewer pinch-zoom reuses Image.Zoomable pipeline; horizontal swipe navigates prev/next.
-   **Switch + Checkbox** — opt-in `HapticFeedback` param (default false). Fires `HapticsService.Light()` on toggle — establishes the cross-cutting haptic-opt-in convention for more inputs in rc.53.
-   **Pagination + Stepper 44×44 targets**: `PaginationItem h-9 w-9 → h-11 w-11 sm:h-9 sm:w-9`; Stepper invisible hit-area trick (`p-1.5 -m-1.5 sm:p-0 sm:m-0`) so the visible 32px dot expands to ~44px tap target on touch.
-   **/docs/mobile — Mobile Playground**: hands-on demos of every gesture, haptic primitive and hit-target retrofit. One page to test the whole mobile stack.

### Docs

-   **Sheet page**: replaced single Bottom swipe demo with a 4-side interactive demo (Top quick-actions, Right edit-form, Bottom filter-list, Left navigation). Updated SwipeToClose API description to reflect all 4 sides.
-   **TabsPage / CalendarPage / SwitchPage / CheckboxPage / ImagePage**: new Mobile-feature sections + API table rows.

2421 + 20 + 31 = 2472 tests green (13 new: 7 Tabs swipe, 2 Switch haptic, 2 Checkbox haptic, plus integration coverage).

v2.0.0-rc.51

May 2026

**NumberTicker animates correctly when loaded in a background tab.** Captured `start = performance.now()` at schedule time meant that when a tab loaded in the background (e.g. Ctrl+Click), `requestAnimationFrame` was paused and the first step() callback never fired — leaving the ticker frozen at 0, or jumping straight to the end value the moment the tab became visible.

### Fixed

-   **NumberTicker background-tab freeze**: defer `start = now` until the first `step()` callback. Standard RAF pattern; zero-cost for foreground-loaded tabs. Verified live on `/docs/bundle-facts`.
-   **NoopInteropService** (Docs.Tests): added the missing rc.49 APIs (`RegisterPinchZoom`/`UnregisterPinchZoom`, `GetScrollTop`, `WheelScrollTop`, `WheelScrollTo`). Without these the Docs.Tests project failed to compile — surfaced as red CI on rc.49/50/51 (Publish/Deploy stayed green so packages and docs were online; only CI was noisy).

20/20 Docs.Tests + 2410/2410 Lumeo.Tests + 31/31 RegistryGen.Tests pass.

v2.0.0-rc.50

May 2026

**Phase 2 mobile primitives in core — 5 new components, 1 service, plus wheel-picker variants.** Adds the mobile-only primitives that don't fit into existing components. All in Lumeo core; no separate `Lumeo.Mobile` satellite.

### Added — new components

-   **PullToRefresh**: wraps scrollable content; pointer-driven pull-down gesture with spinner fade + rubber-band; `OnRefresh` fires after threshold. v1: requires the wrapper itself to be the scroll container.
-   **SwipeActions**: iOS Mail.app pattern with `LeadingActions` / `TrailingActions` RenderFragment slots. Foreground translates horizontally on swipe; locks open at `ActivationThresholdPx`; vertical-scroll passthrough. v1: fixed 160px open width.
-   **SafeArea**: CSS `env(safe-area-inset-*)` wrapper for notch/system bars. Per-side toggle params; no JS.
-   **TouchRipple**: Material-style ripple. `PointerDown` spawns positioned span with CSS animation. Custom Color/Opacity/DurationMs. CTS-cancelled `Task.Delay` cleanup on Dispose.
-   **HapticsService**: facade over `Interop.Vibrate(int)`. Light/Medium/Heavy/Success/Error semantic presets. Registered in `AddLumeo()`.

### Added — picker variants

-   **DatePicker `Variant=Wheel`**: 3-column iOS-style wheel (day/month/year). Culture-aware month names; Min/Max year range; day re-clamps when month/year changes (no Feb 30).
-   **TimePicker `Variant=Wheel`**: hours/minutes + AM/PM column when 12h. Honours `CurrentCulture.AMDesignator`; `MinuteStep` snap.

### Added — interop + CSS

-   **Interop**: `GetScrollTop(elementId)`, `WheelScrollTop(elementRef)`, `WheelScrollTo(elementRef, scrollTop)`. Reuses `Vibrate(int)` from rc.49.
-   **CSS**: `.lumeo-touch-ripple` + keyframes; `.scrollbar-none` utility (Firefox + WebKit).

2410/2410 tests pass · build clean (0/0). v1 limitations (Calendar/List remain recommended a11y path for the pickers, no keyboard nav on wheels) documented in inline component comments.

v2.0.0-rc.49

May 2026

**Touch-native gestures + 44px hit targets across 13 components.** Phase 1 of the mobile sprint: existing components retrofitted with proper touch handling. Same Lumeo API everywhere — no `Lumeo.Mobile` satellite.

### Added — gestures

-   **Sheet**: swipe-to-close (opt-in via new `SwipeToClose` param, false-default to avoid conflicts with scrollable content inside Bottom sheets).
-   **DataGrid**: column resize via pointer events with `setPointerCapture`.
-   **Slider**: thumb tooltip on touch-drag (`@onpointerenter/leave`).
-   **Rating**: iOS-style touch-drag-to-scrub across stars.
-   **ContextMenu**: long-press path (500ms timer, 10px move tolerance, haptic via `navigator.vibrate(50)`).
-   **Image**: new `Zoomable` param — pinch-zoom via two-pointer tracking, scale-delta dispatch, clamped to `[0.5, 5.0]`.

### Added — 44×44 hit-target audit (WCAG 2.5.5)

-   **Window** title-bar buttons (Close/Min/Max/Restore), resize handle.
-   **Chip** dismiss button, **TabsTrigger** close X, **DialogContent** close X, **SortableList** drag handle, **SidebarMenuButton** row.
-   **ToastClose** with mobile visibility fix — was `opacity-0` hover-only, now `opacity-100 sm:opacity-0 sm:group-hover:opacity-100`.
-   **DropdownMenuItem + ContextMenuItem** rows: `min-h-11 sm:min-h-0`.
-   Pattern: full 44px hit area on touch (no `sm:`), compact original size at `sm:` and up. Icon sizes unchanged so desktop visual density is preserved.

### Fixed (caught by review-agent before tag)

-   **Rating mouse double-fire**: `pointerdown` was firing for mouse too, causing `ValueChanged` to double-fire with `AllowHalf=true`. Fixed via `e.PointerType=='mouse'` early-return.
-   **ToastClose invisible-but-blocking on mobile**: `opacity-0` hover-only with 44px hit area was capturing taps on the toast title. Fixed via responsive `opacity-100 sm:opacity-0`.
-   **Pinch-zoom 3-finger baseline drift**: `lastDistance` now re-baselined on 3→2 transition.
-   **Sheet swipe-vs-scroll conflict** on Bottom sheets: `SwipeToClose` now opt-in.

2410/2410 tests pass.

v2.0.0-rc.47

May 2026

**`/docs/bundle-facts` — add Hot Reload section + clarify .nupkg numbers.** User feedback: the bundle-facts page should mention Lumeo's Hot Reload quality with real architectural reasons, plus the "Why brotli not .nupkg" accordion should reflect the rc.40 .nupkg reduction (1.35 MB → 660 KB).

### Added

-   **Section 8 "Hot Reload that actually works"** with 6 concrete facts, each paired with a "what other libs do" contrast so the comparison is grounded:
    1.  No Blazor CSS isolation (Tailwind utility-first, no per-component scoped-class hashing).
    2.  Theme is CSS variables, not a C# object (no recompile to swap colors).
    3.  No source generators in runtime hot path (`[LumeoForm]` is opt-in).
    4.  No reflection in render path (rc.44 compiled-getter fix).
    5.  CascadingValue composition over inheritance — each Razor file HRs independently.
    6.  Tailwind + Razor SDK watch run in parallel; CSS swaps don't go through Blazor at all.
-   **Why-brotli-not-nupkg Accordion** rewritten with a 3-row comparison block (1.35 MB pre-rc.40 → 660 KB post-rc.40 → 400 KB brotli to browser) and a link to `nuget.org/packages/Lumeo` for self-verification.

Docs project clean (0/0).

v2.0.0-rc.46

May 2026

**New `/docs/bundle-facts` page — replaces the easter-egg Dialog on the home page.** User feedback: the click-to-open Dialog was cramped and undiscoverable. Replaced with a dedicated animated page that uses Lumeo's own motion primitives (BlurFade, NumberTicker, Sparkles, Marquee, BorderBeam, ShimmerButton, Accordion) to showcase the bundle-size story.

### New page sections

-   **Hero** — animated `NumberTicker` hitting 400 KB inside a `Sparkles` overlay.
-   **Per-package bar chart** — 7 staggered `BlurFade` rows showing proportional brotli sizes.
-   **What's actually in the .nupkg** — 4 cards explaining Lumeo.dll / lumeo.css / components.js / build-props.
-   **"What's NOT in core" Marquee** — endless strip of deliberately-excluded dependencies (Newtonsoft.Json, AutoMapper, jQuery, etc.).
-   **Comparison table** vs MudBlazor / Radzen / FluentUI / Telerik (approximate brotli sizes).
-   **Heavy features are opt-in** — 3-tile Bento for Charts / DataGrid / Editor.
-   **Why brotli not .nupkg** — Accordion with 3 explainers.
-   **CTA footer** — ShimmerButton to `/docs/installation`.

### Home.razor

-   Removed the entire `<Dialog @bind-Open="_bundleSizeDialogOpen">` block (~72 lines).
-   Replaced the trigger button with `<Lumeo.Link Href="/docs/bundle-facts">` wrapping the existing "~400 KB core" text.
-   Removed the now-orphan `_bundleSizeDialogOpen` field.
-   Sidebar nav `nav-config.json` gained a "Bundle Facts" entry under getting-started.

Docs project builds clean (0 warnings, 0 errors).

v2.0.0-rc.45

May 2026

**rc.44 hotfix — two crashes surfaced in user runtime logs.**

### Fixed

-   **Window: `Math.Clamp(0, -40)` crash on drag-during-init.** The rc.44 viewport-aware drag clamp could be invoked before `_viewportHeight` finished loading from JS (or in non-WASM contexts where the JS interop returns null). When zero, `Math.Clamp(_dragStartPosY + dy, 0, _viewportHeight - TitleBarHeight)` resolved to `Math.Clamp(value, 0, -40)` → `ArgumentException`. Fix mirrors the `ClampPosition()` guard: if viewport is unknown, fall back to lower-bound-only clamp (pre-rc.44 behavior).
-   **LumeoForm generator: `InvalidCastException` setting `Button.type` on the submit button.** The generator emitted `AddAttribute("type", "submit")` — lowercase HTML attribute name + string value — but `Lumeo.Button.Type` is a strongly-typed `ButtonType` enum (Button/Submit/Reset). Fix: emit `AddAttribute("Type", global::Lumeo.Button.ButtonType.Submit)`.

2410/2410 tests pass · 8 projects + tests + docs build clean.

v2.0.0-rc.44

May 2026

**Mega-Sprint A+B+C consolidated: ~35 fixes across 8 categories, one release.** 6 parallel fix agents handled the previously deferred items (A: Window/RTL/Scheduler/Gantt; B: LumeoForm + Visual Diff). 5 parallel audit agents covered the previously un-audited dimensions (C: localization, performance, Blazor Server, mobile/touch, API consistency). 4 parallel fix agents addressed the HIGH-priority C findings. API renames were intentionally deferred to a v2.1 breaking-change release.

### A — Carry-overs from rc.43

-   **Window drag-clamp (viewport-aware)**: new `Interop.GetViewportSize()` + `ClampPosition()` keeps the title bar inside the viewport on all four edges (MinVisible=50px, TitleBarHeight=40px). Consumer-set `InitialX=9999` is now clamped on first render.
-   **RTL ArrowKey-swap**: Carousel, Stepper, Tabs, Splitter now respect `ThemeService.CurrentDirection == LayoutDirection.Rtl` and swap ArrowLeft↔ArrowRight for horizontal navigation.
-   **Scheduler**: `lumeo:theme-changed` listener re-renders active calendars; `OnInitError` callback surfaces FullCalendar bundle-load + Calendar-constructor failures.
-   **Gantt**: `OnInitError` callback added (matches Chart/Scheduler pattern).

### B — LumeoForm generator design + Visual Diff

-   **LMF001**: read-only / init-only properties now emit a Roslyn diagnostic explaining they're excluded.
-   **LMF002**: unsupported types (collections, custom refs) emit a diagnostic suggesting `[LumeoFormIgnore]` or TagInput override.
-   New `[LumeoFormIgnore]` attribute + `[NotMapped]` recognition suppress diagnostics on properties that should be excluded silently.
-   **Visual Diff**: `HomePageVisualTests` now uses ImageSharp perceptual compare (0.5% tolerance, Manhattan RGBA > 30). CI skip removed — test runs everywhere.

### C-Audit Findings + Fixes

#### Localization (7 HIGH)

-   **Delta** stops hardcoding `InvariantCulture` — German users now see `+12,5 %`. KPI cards across all dashboards inherit.
-   **DateRangePicker.Format** default `"MMM dd, yyyy"` → null, resolves to `CurrentCulture.ShortDatePattern`.
-   **TimePicker.Use24Hour** bool → bool? → null derives from `CurrentCulture.ShortTimePattern`. Hardcoded "AM"/"PM" → `AMDesignator/PMDesignator`.
-   **DataGrid plurals** (RU/PL/AR-aware): new `LumeoPlurals.PluralKey(count, baseKey, culture)` helper — returns `.One/.Few/.Many/.Other` based on language rules. `DataGrid.ItemsCount` uses it. EN/DE/PL/RU/AR translations supplied.
-   **Stepper.\* and Window.\*** translations added to all 13 non-English locale dicts — half the strings were silently falling back to English.
-   **DateTimePicker** now forwards `FirstDayOfWeek` to inner Calendar.
-   **Hardcoded English aria-labels** in NumberInput, Input, Window, Slider, FileManager, FileUpload, DateTimePicker routed through `ILumeoLocalizer`. Keys added to all 14 locales.

#### Performance (5 HIGH)

-   **DataGridColumn.GetValue** now uses compiled `Expression<Func<TItem,object?>>` getters cached per field. ~10× faster than the old `PropertyInfo.GetValue`. Supports nested paths (`Address.City`) with null-safe chain.
-   **DataGridRow + DataGridCell CssClass memoization**: tuple-keyed cache. 1k rows × 10 cols = 10k+ string allocations per render → ~1 per row+cell on state change.
-   **Context.VisibleColumns** exposed on `DataGridContext<TItem>` — eliminates per-row `Columns.Where(c => c.Visible)` LINQ.
-   **ComboboxContent.FilteredItems**: property → memoized backing field invalidated on `Items`/`SearchText` change. 10k-item dropdowns no longer re-filter 3× per render.
-   **PivotGrid** skip-rebuild gate (`_lastItemsRef` + dims hash) — eliminates full tree-rebuild on unrelated parent re-renders.

#### Blazor Server + Touch + Disposal

-   **9 components** wrapped their first-render JS interop in `try/catch (JSDisconnectedException, ObjectDisposedException)`: Affix, BackToTop, Carousel, Scrollspy, ResizableHandle, OtpInput, ConsentBanner, PromptInput, AgentMessageList.
-   **TabsList** prerender measurement guarded against `InvalidOperationException` (Blazor prerender).
-   **Keyboard shortcut Map** cleared on `registerKeyboardShortcuts` entry — no more stale entries leaking across Blazor Server circuit reconnects.
-   **P0 mobile fix: `registerClickOutside` now binds `touchstart`** (with `{ passive: true }` + 600ms synthetic-mousedown dedupe). Tap-outside now closes every Dropdown, Combobox, Select, Popover, ColorPicker, ContextMenu, DatePicker, TimePicker on mobile.
-   **SortableList touch reorder**: new `registerSortableTouch` JS helper with `elementFromPoint` drop detection. Mouse path unchanged (still uses HTML5 Drag API).
-   **Tooltip + HoverCard tap-to-pin**: tap toggles pinned state; click-outside unpins via the now-touch-aware `registerClickOutside`.
-   **NavigationMenu + MegaMenu**: `@onmouseenter/leave` → `@onpointerenter/leave` with `e.PointerType == "mouse"` guard. Submenus no longer close on touch liftoff before the user can tap a sub-item.

### Deferred to v2.1 (breaking-change release)

-   API consistency renames: `Stepper.ActiveStep → CurrentStep`, Multi-value collection type unification (HashSet/List/IEnumerable), `Values → SelectedValues`, `SidebarProvider.IsCollapsed → Collapsed`, Size enum harmonization. These are breaking and need consumer migration.

145 components · 2,410 tests pass · all 8 packages + tests + docs build clean (0 warnings, 0 errors).

v2.0.0-rc.43

May 2026

**Mega-Audit sweep: ~30 fixes across A11y, RTL, theme/dark-mode, async/race, memory, forms, and third-party wrappers.** Dispatched 7 parallel review agents over the full ~145-component surface (categories the rc.42 audit didn't cover) → 40 hypothesized bugs → 6 parallel fix agents → all green. The single release covers the substance of what would have been rc.43 through rc.47.

### A11y (12 fixes — interactive components keyboard navigation)

-   **Carousel arrow-keys now `preventDefault`** — page no longer scrolls when the carousel handles ArrowLeft/Right.
-   **Roving tabindex** on MenubarTrigger, Rating, TreeViewNode (focused-node tracking), Stepper step buttons. Toolbar container gets `tabindex="0"` so screen readers announce "toolbar".
-   **SplitterDivider** now resizable via ArrowKeys (±10px delta per press, horizontal/vertical based on orientation).
-   **Focus management on open/close**: Mention/Cascader return focus to trigger on close; Cascader focuses first option on open.
-   **ContextMenuTrigger** now activates on Shift+F10 / ContextMenu key for keyboard users.
-   **OtpInput Backspace** stopsPropagation so it can't accidentally trigger SPA back-navigation.

### RTL (10 fixes — full right-to-left support)

-   **Carousel** (Next/Previous/Content/Item), **Combobox input**, **DatePicker** (5 hardcoded directions), **Select / SelectTrigger** migrated from hardcoded `ml-/mr-/pl-/pr-/left-/right-/border-r/border-l` to Tailwind logical properties (`ms-/me-/ps-/pe-/start-/end-/border-s/border-e`).
-   **Directional chevrons** on Carousel, Pagination, Breadcrumb now flip in RTL via `[dir=rtl]:rotate-180`. Arrow-key handler RTL-swap deferred (separate concern; tagged with TODO).

### Theme + Dark Mode (5 fixes — ColorPicker is now dark-mode-correct)

-   **ColorPicker slider thumbs**: `background: #fff` → `var(--color-background)`. White thumbs were invisible against light-colored hues in dark mode.
-   **ColorPicker checkerboard** (transparency visualization): hardcoded `rgba(0,0,0,0.08)` → `color-mix(in srgb, var(--color-muted) 60%, var(--color-background))`. Visible in both modes.
-   **ColorPicker SV-indicator shadow** uses theme-aware `color-mix(... var(--color-foreground) ...)`. The white-on-canvas border itself is kept (correct against any swatch color).
-   **ThemeSwitcher**: stale-default-on-first-render fixed via `OnInitializedAsync`. UI shows the real current scheme/mode immediately.
-   **ThemeService.ToggleModeAsync**: now cycles System → Dark → Light → System (was binary Light↔Dark and permanently lost System mode on first toggle). 3 tests updated to match the new cycle contract.

### Async / Memory (4 fixes — leak elimination)

-   **FileUpload** now implements `IAsyncDisposable` — disposes all in-flight `CancellationTokenSource`s in `_cancellations` on unmount. CRITICAL: every upload running at page-navigate previously leaked a CTS.
-   **FileUpload batch staleness**: `_currentBatchId` counter — old slow batches can no longer fire `OnAllUploaded` after a newer batch has started.
-   **TreeSelect.OpenDropdown**: post-await disposal guards. Setting `_registered=true` after a disposal-during-Interop is now impossible.
-   **Mention.HandleBlur**: 150ms `Task.Delay` now uses a `CancellationTokenSource` — re-focusing inside the window cancels the pending hide.

### Heavy Wrappers (RichTextEditor — 2 real fixes)

-   **Silent init failure surfaced**: JS wraps `new Editor()` + TipTap bundle load in try/catch with descriptive errors. C# catches `JSException`, sets `_initError`, renders an error card, and invokes new `OnInitError` callback. Matches the pattern Chart.razor already used.
-   **Orphan suggestion DOM cleanup**: suggestion popups are now tagged with `data-rte-id`; `destroy(id)` hunts them down explicitly. No more dangling popups in `document.body` after unmount-mid-suggestion.
-   **FALSE ALARM verified**: theme-unaware inline styles. The audit thought `style.cssText` was baked at init — but the strings use `var(--color-*)` references, which browsers re-resolve on every paint. Already theme-aware.

### Forms + Source Generator (4 fixes)

-   **LumeoForm generator**: non-null enum no longer emits `model.Prop?.ToString()` (CS0023). Nullable-aware emit handles both `MyEnum` and `MyEnum?` correctly.
-   **LumeoForm nullable-enum clear**: when user clears the Select, the property goes to `null` for nullable enums. Was: silently kept the old value.
-   **LumeoForm DateTimeOffset**: invalid `(DateTime?)` cast replaced with `.DateTime` accessor; original `.Offset` is preserved through the round-trip. Was: timezone silently stripped.
-   **FormField** now reads errors from a cascaded `FormContext` parameter — Form.Reset() now actually clears children's visible error state. Was: child kept showing the old error.

### False alarms cleared (11)

-   **DropdownMenuItem**: `tabindex="-1"` + parent-driven `FocusMenuItemByIndex` is the correct WAI-ARIA menu pattern, not a bug. **ColorPicker HSV gradients**: hardcoded white/black are color-space primitives, not theme colors. **Charts**: full theme-change listener and resize observer already in place. **Gantt**: CSS variables read on every render — passive theme support is intentional. **Combobox/Select/Carousel/InplaceEditor/Stepper/Cascader async paths**: all guarded correctly. **FileUpload** didn't have a leak we expected — actual leak (no CTS dispose on unmount) is the one we fixed instead.

145 components · 2,410 tests pass (was 2,407 — +1 for new ToggleMode cycle test, ±0 for the 2 Carousel/ThemeService tests retitled to match new contracts) · all 5 satellite builds clean · 0 warnings, 0 errors.

v2.0.0-rc.42

May 2026

**Audit sweep: 3 verified bugs fixed, 11 hypothesized bugs cleared.** Dispatched 4 parallel review agents over ~80 components looking for the same class of bug the DataGrid group panel had (UI promises something the implementation doesn't deliver). Found 4 real bugs — Window drag clamp is too involved to ship surgically and goes to rc.43; the other 3 are in this release. Plus a regression test suite for the rc.41 group-panel fix.

### Fixed

-   **Toolbar overflow was completely broken at runtime.** `Toolbar.razor` called `observeToolbarOverflow` but `toolbar.js` only exported `observeToolbarWidth` / `measureToolbarChildren` — the function the component depended on didn't exist. `Overflow="true" VisibleCount="-1"` users got zero auto-collapse. Implemented the missing function (full ResizeObserver + child-width measurement + fitting-count computation in JS), switched C# to `InvokeVoidAsync` with a stable per-component DOM id.
-   **`ToastOptions.Position` (rc.37 API) was silently ignored.** The per-toast position override existed in `ToastService` but `ToastProvider.razor` rendered every toast into a single `<ToastViewport Position="Position">` — the provider's default. Now toasts are grouped by their effective position (`options.Position ?? defaultPosition`) and rendered into one viewport per group. Multiple `position:fixed` viewports coexist without overlap.
-   **TreeView lazy-loaded children inherit parent's check state (bonus).** When `LoadChildren` resolves, freshly-loaded children now inherit a fully-checked parent's state. Previously a checked parent would expand to reveal unchecked children — a visibly broken tri-state. Indeterminate parents recompute correctly when newly-loaded children land in their default state.

### Tests

-   New `DataGridGroupPanelTests.cs` — 8 bUnit tests covering the rc.41 group-panel fixes: panel render, Groupable-only dropdown filtering, Add/Remove/Clear behavior, and the specific "add after clear still works" regression that the user reported.
-   All 8 pass green; one assertion was tightened from a panel-wide string match (which falsely included the "+ Add level" dropdown options) to a chip-span selector.

### False alarms (audit findings that turned out to be FINE)

-   Sortable cross-container drag has `OnDragEnd` as a state-reset belt regardless of drop. TreeView MultiSelect cascade is correct (tri-state computed via `UpdateAncestorStates`). DataGrid virtualization is bypassed when grouping is active (no row-skip risk). Column-reorder during grouping is safe — fields are stored as strings, not indices. Combobox/Select filter clears on close. Tabs uses value-based active state, no index drift. Stepper's `HandleStepClick` guards via `CanClickStep`. Splitter uses pointer events (touch works). Sheet/Drawer scroll-lock is refcounted. DateRangePicker provides visual feedback for inverted ranges. InplaceEditor's Esc-vs-blur race is synchronously guarded. PivotGrid handles empty data without NaN.

### Deferred

-   Window component drag can push the window below the viewport (no upper-bound clamp on `_posY`). Clean fix needs viewport-aware JS interop — queued for rc.43. Workaround: don't drag the window far enough off-screen to lose it.
-   Splitter divider is keyboard-focusable but ArrowKey resize is missing (a11y gap). Same sprint.

145 components · all 8 new DataGridGroupPanelTests pass · core + tests + docs build clean (0 warnings, 0 errors).

v2.0.0-rc.41

May 2026

**DataGrid group panel bug-fix sweep.** User-reported: drag-to-group didn't work even though the panel placeholder said "Drag a column header here", re-grouping after a clear felt broken, and the panel UX wasn't polished. All three fixed.

### Fixed

-   **Drag-to-group now actually works.** Column headers with `Groupable="true"` are HTML5-draggable whenever `ShowGroupPanel="true"` on the grid — independent of `Reorderable`. The panel now has full `@ondragover` / `@ondrop` handlers and lights up `border-primary bg-primary/10` when a valid Groupable column is dragged over it. Drops on non-Groupable columns (or columns already grouped) are rejected silently.
-   **Re-grouping after clearing all levels works again.** The "+ Add group level" `<select>`'s native DOM `value` was sticking on the last-picked option, so after the second add the placeholder ("+ Add group level") wouldn't re-render and the dropdown felt frozen. `@key` on the select now forces a fresh DOM element each time the group-fields count changes.
-   **Added a "Clear" button** next to the panel chips for one-click reset to ungrouped. Cleaner than chip-by-chip removal.
-   **DataGridContext gained `ShowGroupPanel: bool`** so header cells can decide on their own whether to be drag-source-eligible without extra plumbing.

### No API break

-   The `DataGridContext<TItem>` record gained one new positional field — only code that _constructs_ the context manually would break, and the only such caller is `DataGrid.razor` itself (consumer Razor pages cascade-read it).
-   Existing single-level `GroupBy="..."` demos and multi-level `GroupByFields=@(...)` usage are unchanged. The interactive demo on the DataGrid page now genuinely shows the panel feature.

145 components · DataGrid + docs project build clean (0 warnings, 0 errors).

v2.0.0-rc.40

May 2026

**Lumeo.nupkg cut in half — CLI source registry moved out of the package.** The 146 shadcn-style per-component snippet JSONs that were shipping inside every `Lumeo` NuGet install (~3.9 MB raw, ~700 KB compressed) were pure dev-time payload — the CLI fetches them over HTTPS from `lumeo.nativ.sh/registry/` at `lumeo add` time. End-user browsers never touched them.

### Result

-   **Lumeo.nupkg: 1,405,580 B → 672,193 B (−52%, −733 KB).** Back below the rc.20 baseline. NuGet UI now displays a sensible package size that matches the actual browser footprint story instead of three times it.
-   **Browser-shipped bytes unchanged.** Brotli-compressed `Lumeo.dll` is still ~400 KB — nothing about the runtime payload moved. The 733 KB savings come entirely from dev-time-only assets.

### What changed

-   **`src/Lumeo/wwwroot/registry/` deleted** (146 JSON files). RegistryGen now writes per-component snippets to `docs/Lumeo.Docs/wwwroot/registry/` only — that's the canonical CDN source consumed by `lumeo add` + MCP via `https://lumeo.nativ.sh/registry/<slug>.json`.
-   **`Lumeo.csproj`:** removed the `SyncRegistryIntoWwwroot` MSBuild target and added a `<None Include="registry\registry.json" Pack="false" />` so the master index stays in source control but never gets packed.
-   **`deploy-cloudflare.yml`:** the per-component-registry copy step now reads from `docs/Lumeo.Docs/wwwroot/registry/` instead of the now-deleted `src/Lumeo/wwwroot/registry/`. (Mostly a no-op because the SDK already publishes that folder, but kept as a safety net.)
-   **Registry doc page:** the "Raw JSON" link now points at `/registry.json` (Cloudflare-served from `docs/Lumeo.Docs/wwwroot/registry.json`) instead of the now-dead `/_content/Lumeo/registry/registry.json` URL.

### Consumer impact

-   **None.** Runtime apps don't reference the registry JSONs (their `registryUrl` already pointed at the CDN, not `/_content/Lumeo/registry/`). The Lumeo.CLI's default URL was already `https://lumeo.nativ.sh/registry.json` — no behavior change.

145 components · 9 NuGet packages + 1 npm package published.

v2.0.0-rc.39

May 2026

**Doc-coverage audit + bundle-stats honest rewrite.** A second-pass audit of all 145 component pages turned up gaps the rc.37 sweep missed — features documented in API tables but never actually shown in a live demo. 23 new interactive previews fill those gaps. Plus the homepage bundle-size story is now measured in _browser-shipped brotli bytes_, not `.nupkg` sizes that include CLI-only assets.

### Docs site — closing the demo coverage gaps

-   **DataGrid `ShowGroupPanel` interactive demo.** The group-panel + multi-level grouping features had docs prose + an API table but no live preview. New demo with Segmented toggles for panel on/off and single-vs-multi-level grouping (Department → Status with per-group salary average).
-   **Animation & visual sliders (5 pages):** AnimatedBeam (Curvature, DurationMs), BlurFade (DelayMs, BlurPx + Replay), Barcode (Height, BarWidth), BackToTop (VisibilityThreshold), Affix (anchor + Offset).
-   **Input controls (5 pages):** Pagination size, OtpInput Length (4/6/8), PasswordInput ShowStrength + ShowToggle, NumberInput Step + Precision, Mention Trigger character.
-   **Variants & modes (4 pages):** PopConfirm IsDestructive, ToggleGroup PressEffect (None/Scale/Brightness/Ripple), Toggle icon+text slot toggles, ShimmerButton size — single live preview not side-by-side.
-   **Display + event-feedback (7 pages):** Textarea ShowCount counter, TextReveal Threshold scroll-trigger, Timeline ActiveIndexChanged binding, TreeView OnItemClick, Transfer OnChange, AgentMessageList Role switcher, Tooltip Side demo refactored to compound `<SegmentedItem>` pattern.
-   **Two audit findings sauber geskippt:** Pagination has no `Size` enum, Menubar has no `Orientation` parameter — fix-agents refused to invent the API. Pagination size demo done via `PaginationItem Class=` sizing instead.

### Home — honest bundle stats

-   **"~530 KB core" → "~400 KB core" everywhere on the homepage**, with full disclosure: this is the _brotli-compressed assembly size_, which is what the browser actually downloads — what every other Blazor lib means when it quotes a number. Measured 2026-05-13 on rc.38: Lumeo.dll brotli ≈ 403 KB, Charts 120 KB, DataGrid 100 KB, Editor 26 KB, Motion 18 KB, Scheduler 16 KB, Gantt 12 KB.
-   **Why the `.nupkg` shows ~1.35 MB:** the package bundles ~4 MB of shadcn-style component _source registry_ for the Lumeo CLI (`staticwebassets/registry/*.json`) plus the pre-compiled Tailwind utility snapshot. None of that is sent to end users' browsers — disclosed in the bundle-size dialog and in the bento footer footnote. (Moving the registry to CDN-only is queued for rc.40 — would bring the `.nupkg` back under 600 KB.)

145 components · all 4 audit waves built clean (0 warnings, 0 errors) · brotli measurements: `brotli -q 11` of each package's runtime DLL.

v2.0.0-rc.38

May 2026

**CI fixes — the rc.37 push went through but the Cloudflare / CI / E2E workflows went red.** Two unrelated issues, both fixed here.

-   **New `SegmentedItem` compound sub-component.** The rc.37 doc-coverage sweep used `<SegmentedItem Value="...">` children inside `<Segmented>` on ~10 interactive-preview demo pages — that's the shadcn-style composition the rest of the library uses (`SelectItem`, `TabsTrigger`, …) and the natural reach. But `Segmented` only had the `Options="List<SegmentedOption>"` data-driven API — so docs built locally but CI's `-warnaserror` failed with RZ10012 "unexpected element 'SegmentedItem'". Added the compound sub-component (cascading `SegmentedContext`, styling identical to `Options`\-mode). Both APIs now coexist; consumers can pick whichever reads better.
-   **Changelog.razor: escaped a literal `@page` reference** in the rc.37 entry that was being parsed as a Razor directive — broke the docs build for CI / E2E / Cloudflare. Now `@@page` in source → renders as `@page` in the page.

145 components (+1 sub-component) · 2,401 unit + 31 RegistryGen + 20 docs tests green; all `-warnaserror` satellite builds clean; docs project builds clean.

v2.0.0-rc.37

May 2026

**Doc-coverage sweep — every component now has a live demo, a complete API table, and interactive previews for multi-value enum parameters.** Plus a small API addition (`ToastOptions.Position`) and a CI hygiene fix.

### Docs site — interactive previews everywhere

-   Every `[Parameter]` typed as an enum with ≥2 values now has a **"Variant (interactive)"** section on its component's doc page — a `<Segmented>` (or `<Slider>` for numeric tunables) bound to a state field driving a live component, so readers can flip between values and see the difference in real time.
-   ~50 new interactive previews across Forms (Button Variant/Size, DatePicker Mode, FileUpload Variant, Rating Size, Toggle/ToggleGroup, …), Navigation/Overlay (Tabs Variant/Orientation/RenderMode, Sheet/Drawer Side, Stepper Orientation, Carousel Orientation, BottomNav Variant, MegaMenu, Splitter, Sidebar, AppBar, Popover/Tooltip Side+Align), Data Display (Steps Orientation, Statistic Size/Variant, Sparkline Type, SparkCard, Timeline, Gauge Variant, Avatar Shape/Status, Badge Variant, Bento Gap, Chip Variant, ImageCompare, QRCode, ReasoningDisplay, ToolCallCard), Motion (Marquee Speed/Direction, BorderBeam Size+Duration sliders, ShimmerButton, Dock MaxScale/MagnifyRadius, NumberTicker target, Sparkles count, TextReveal speed), Feedback (Alert Variant, Result Status, Toast Variant+Position).
-   **API tables filled in**: ~18 Forms pages were missing FormField integration rows (Required / Invalid / ErrorText / HelperText / Label / Name) — added. AnimatedBeam `PathWidth` and SortableList `Key` rows added.
-   Pages that were entirely missing got created from scratch — every one of the 145 components now resolves at `/components/<kebab-name>`.

### API additions

-   `ToastOptions.Position` (`ToastPosition?`) — per-toast position override, complementing the existing `ToastViewport.Position` default. Powers the new ToastPage interactive position demo.

### Hygiene

-   Stripped UTF-8 BOMs from three Razor source files (DatePicker / DateRangePicker / DateTimePicker) — they were breaking the sitemap generator's `grep '^@page'` on the Cloudflare deploy.
-   SplitterPage interactive demo: fixed a mixed C#+literal `Class`\-attribute syntax error (RZ9986). FileManagerPage `RemoveNode` nullable-warning fix (CS8604 — would have failed an eventual docs `-warnaserror`).

145 components · 2,401 unit + 31 RegistryGen + 20 docs tests green; all `-warnaserror` satellite builds clean; docs project builds clean.

v2.0.0-rc.36

May 2026

**DataGrid batch-edit UI, PivotGrid multi-level columns, Toolbar auto-overflow, 13-locale satellite sweep.** Wave 6 of the deep-scan roadmap. All additive; no breaking changes.

### DataGrid — batch / buffered edit mode

-   Setting `EditMode="DataGridEditMode.Batch"` now wires up the full UI (the rc.35 scaffolding got fleshed out): edits go into a per-cell pending-changes buffer, dirty cells get a `bg-warning/10` tint and warning-coloured left border, a "**N pending changes**" strip appears with **Save all** + **Discard** buttons.
-   **Save all** fires `OnBatchSave` (`DataGridBatchSaveEventArgs<TItem>` with `Modified` + `Added` lists). On clean return the buffer clears automatically.
-   `ShowAddRow="true"` + `NewItemFactory` render a "+ Add row" trigger. Public `HasPendingChanges` / `PendingModifiedItems` / `PendingAddedItems` for warn-on-navigate.
-   New `ColumnVirtualize="true"` + `MaxVisibleColumns` (default 30) — caps how many columns are rendered for very-wide grids. (Real per-cell horizontal virtualization is a follow-up; this is the simpler "max-columns cap" approximation. Clipboard paste / fill-down / `ShouldRender` on cells are also deferred.)

### PivotGrid — multi-level column hierarchy

-   `ColumnFields` now nests properly. A two-level `[Year, Quarter]` example renders three header rows (Year — colspan'd across its quarters / Quarter — colspan'd across measures / Measure names), with correct rowspans on row-field corners and the grand-total column. Column-subtotals are deferred (row subtotals work).

### Toolbar — automatic overflow measurement

-   `<Toolbar Overflow="true">` with the default `VisibleCount=-1` now auto-measures via `ResizeObserver` — items that don't fit collapse into the "⋯" dropdown live as the container resizes. Manual `VisibleCount` still wins when set.

### Localization — satellites sweep

-   **71 new locale keys × 14 dictionaries = 994 entries.** `Chart` (loading text), `Scheduler` (Today + view-switcher + "Week of {0}"), `Gantt` (view-mode labels), and **`RichTextEditor`** (toolbar + bubble menu + slash-command + AI-action menu — Bold / Italic / Heading 1–3 / Bullet+Numbered+Task list / Quote / Code block / Link / Insert image/table / Undo / Redo / Clear formatting / Improve writing / Make shorter / Make longer / Translate / Summarize / Fix grammar / placeholders / …) all now route through `ILumeoLocalizer` with translations in de / fr / es / it / pt / nl / pl / ja / zh / ko / ar / ru / tr.

### CI

-   `publish-mcp` now succeeds when the version is already on npm (typical on a release re-run after a sibling job failed) — checks for "cannot publish over" / "previously published" in npm's error and exits 0 instead of red. Any other publish failure still fails the job.

Docs site refreshed: batch-edit demo on DataGrid, multi-level-columns demo on PivotGrid, auto-overflow demo on Toolbar. Stale stats fixed (145 components · 2,400+ tests · rc.36). 145 components · 2,401 unit + 31 RegistryGen + 20 docs tests green; all -warnaserror satellite builds clean.

v2.0.0-rc.35

May 2026

**DataGrid tree-grid + group panel, and six new components.** Wave 5 of the deep-scan roadmap. Mostly additive.

### DataGrid

-   **Tree-grid mode** — `ChildItemsSelector` turns the grid into a hierarchy: rows with children get an expand chevron, indented child rows, recursive. `TreeGridDefaultExpanded`, `TreeColumnField`, `OnTreeNodeExpand`; `role="treegrid"` + `aria-expanded`/`aria-level`. Distinct from the flat `DetailTemplate`.
-   **Group panel + group-level aggregates + multi-level grouping** — `ShowGroupPanel` renders a chip bar; columns with `Groupable` can be added/removed/reordered there; `GroupByFields` for multi-level nested grouping; each group row shows the column `Aggregate`s over that group.
-   Scaffolding for batch-edit mode landed (`DataGridEditMode.Batch`, `DataGridBatchSaveEventArgs<TItem>`) — full UI wiring follows in the next release. Plus a fix for an `AriaLevel`/`AriaExpanded` regression from rc.34.

### New components

-   **`Gauge`** — single-value gauge, `Radial`/`Arc`/`Linear` variants, threshold colour bands, `role="meter"`.
-   **`RingProgress`** — circular determinate progress ring with an optional centre label or custom content.
-   **`Barcode`** — inline SVG _Code 128B_ barcode renderer (scannable), with optional human-readable text.
-   **`Highlighter`** — wraps occurrences of one or more search terms in the text with highlight marks (`CaseSensitive`, `WholeWord`).
-   **`FileManager`** — headless file/folder explorer: folder tree, breadcrumb path, list/grid views, lazy loading (`LoadChildren`), inline rename, context-menu operations (rename/delete/open). Drag-drop / upload / multi-select are deferred.
-   **`QueryBuilder`** — visual AND/OR predicate-tree builder: recursive groups, per-type value editors, serializes to JSON and to a LINQ predicate (`ToExpression<T>`), `ShowJsonPreview`, `MaxDepth`.

### Toolbar

-   New `Overflow` + `VisibleCount` — collapse trailing items into a "⋯" dropdown. (Auto-measurement of which items fit is a follow-up; for now `VisibleCount` is consumer-controlled.)

Docs site updated: new pages for Gauge / RingProgress / Barcode / Highlighter / FileManager / QueryBuilder; API tables + demos refreshed on DataGrid / Toolbar. 145 components · 2,375 unit + 31 RegistryGen + 20 docs tests green.

v2.0.0-rc.34

May 2026

**The big one — DataGrid keyboard navigation, a new PivotGrid, Scheduler/Gantt/FileUpload feature waves, Select/Combobox data-bound mode, and a localization sweep.** Wave 4 of the deep-scan roadmap. Mostly additive; the DataGrid changes add ARIA attributes but don't alter behaviour.

### DataGrid — keyboard navigation + grid ARIA

-   **Roving-tabindex cell navigation**: arrow keys move the focused cell, `Home`/`End` = row ends, `Ctrl+Home`/`Ctrl+End` = corners, `PageUp`/`PageDown` = ±10 rows, `ArrowUp` from row 0 jumps into the header. `Enter`/`F2` on an editable cell starts cell-edit; `Enter` while editing commits + moves down, `Tab` commits + moves right, `Escape` cancels. `Space` toggles row selection; `Ctrl+A` selects all (multi-select). `Enter`/`Space` on a sortable header cell sorts.
-   **Grid ARIA**: `role="grid"` + `aria-rowcount`/`colcount`/`multiselectable`, `role="row"`+`aria-rowindex`/`selected`, `role="columnheader"`+`aria-sort`, `role="gridcell"`+`aria-colindex`/`readonly`. Focus ring on the active cell.
-   Deferred: keyboard nav inside grouped/virtualised regions (cells still carry the ARIA roles there).

### New component — `PivotGrid<TItem>`

-   Cross-tab / pivot table: pivots flat data into a row hierarchy × column values × aggregated `Measures` (Sum/Average/Count/Min/Max). `RowFields` nest into a multi-level outline; per-group subtotal rows + a column grand-total row + a row grand-total column + the overall total. Collapsible row groups (chevron + `aria-expanded`), `OnCellClick` for drill-down, `EmptyContent`, `Compact`. Single column-field level for now (row hierarchy is fully nested).

### Scheduler

-   Recurring events via FullCalendar's free recurrence model — new `SchedulerEvent.DaysOfWeek` / `RecurrenceEnd` / `ExceptionDates`.
-   Resource colour-coding: new `SchedulerResource` record + `Resources` param + `SchedulerEvent.ResourceId` — events inherit their resource's colour, with a legend above the calendar. (True resource-lane / timeline views need FullCalendar's premium plugin, which we don't bundle.)
-   `NowIndicator` (default true), `SlotMinTime`/`SlotMaxTime`/`SlotDuration`, `EventClassNames`/`EventColor` callbacks.

### Gantt

-   Milestones — `GanttTask.IsMilestone` renders a diamond instead of a bar. Grouping/swimlanes — new `GroupBy` param + `GanttTask.GroupLabel` (sort + group-separator rows). `TodayHighlight`, `BarHeight`/`ColumnWidth` config, `BarColor` per-task colour callback. (Task dependencies were already supported; rendered as arrows.)

### FileUpload — a real upload pipeline

-   New `OnUpload` callback (`Func<FileUploadItem, IProgress<int>, CancellationToken, Task<string?>>`) — the component drives per-file state (`FileUploadItem` with `Status` Pending/Uploading/Succeeded/Failed/Cancelled, `ProgressPercent`, `Url`, `ErrorMessage`) with per-file progress bars, cancel + retry buttons, `AutoUpload` / `MaxConcurrentUploads`, validation rejections surfaced as failed items (+ `OnFileRejected`), and `OnFileUploaded`/`OnAllUploaded`/`OnFileFailed` events. Legacy `Progress`/`OnFilesSelected` still work.

### Select / Combobox — data-bound mode (non-breaking)

-   New `Items` / `ItemValue` / `ItemText` / `ItemGroup` / `ItemDisabled` / `ItemTemplate` params — bind options from a collection instead of writing `<SelectItem>`s by hand. Plus `Virtualize` + `ItemSize` for large option lists. Components stay non-generic (`object`\-typed selectors) — composition mode unchanged, zero breaking changes.

### Localization

-   Kanban "Add card" and Carousel a11y labels ("Previous slide" / "Next slide" / "Slide N of M") now route through `ILumeoLocalizer` with translations in all 13 locales. (Audit found EmptyState/Result/Steps/Mention/AlertDialog have no hardcoded English to localise — their text is consumer-supplied or icon-only.)

Docs site updated: new PivotGrid page; API tables + demos refreshed on DataGrid / Scheduler / Gantt / FileUpload / Select / Combobox. 139 components · 2,303 unit + 31 RegistryGen + 20 docs tests green.

v2.0.0-rc.33

May 2026

**Four new components — Stepper, Window, Toolbar, AppBar.** Purely additive; no breaking changes.

-   **`Stepper`** — a _stateful_ multi-step flow (distinct from the display-only `Steps`): step header indicators, Back/Next/Finish navigation, `Linear` gating with per-step `IsValid`, horizontal/vertical orientation, `OnFinish`, optional steps, custom step icons, tab-like ARIA. `<StepperStep>` sub-component.
-   **`Window`** — a _non-modal_, draggable, resizable floating panel (vs. the modal `Dialog`): draggable title bar, resize handle, minimize/maximize/close, controlled `Open`/`Minimized`/`Maximized`, initial size/position. Drag/resize use Blazor pointer events — no JS interop. The page stays interactive (no backdrop).
-   **`Toolbar`** — a `role="toolbar"` layout container for buttons/inputs, with `ToolbarSeparator` / `ToolbarSpacer` / `ToolbarGroup` sub-components. (Overflow-collapse menu is a follow-up.)
-   **`AppBar`** — a top application bar with `StartContent` / `ChildContent` (centre) / `EndContent` slots, `Sticky` / `Elevated` / `Bordered` / `Height`. Pairs with `Sidebar` / `BottomNav`.

Docs site updated with pages for all four. 138 components · 2,259 unit + 31 RegistryGen tests green.

v2.0.0-rc.32

May 2026

**Three new components + DatePicker / DateTimePicker / Toast / TreeView upgrades + string-to-enum API tightening.** Wave 2 of the deep-scan roadmap. A few string parameters became real enums (mild breaking change in an RC — compile-time safety + autocomplete).

### New components

-   **`ButtonGroup`** — joins `<Button>`s into a segmented bar with collapsed borders and rounded ends; `Orientation` Horizontal/Vertical.
-   **`DropdownButton`** — a button whose whole click opens a dropdown menu of secondary actions (chevron indicator).
-   **`SplitButton`** — split into a primary-action half (`OnClick`) and a chevron half that opens the dropdown.

### Component upgrades

-   **DatePicker**: forwards `FirstDayOfWeek` + `ShowWeekNumbers` to the inner Calendar; new `Inline` mode (always-open calendar, no popover).
-   **DateTimePicker**: new `MinDate` / `MaxDate` / `IsDateDisabled` (forwarded to its Calendar).
-   **Toast**: `ToastViewport.Position` (6 corners/centres) + `MaxVisible`; `ToastOptions.Position` for per-toast overrides.
-   **TreeView**: big overhaul — lazy/async children (`LoadChildren` + `IsLeaf` / `IsLoading`), tri-state checkboxes with parent↔child cascade (`CascadeCheck`, `IsIndeterminate`, `CheckedValuesChanged`), custom `NodeTemplate`, disabled nodes (`IsDisabled`), `ExpandAll` + `ExpandAllNodes()`/`CollapseAllNodes()`, multi-select (`MultiSelect`, `SelectedValues`), `role="tree"`/`treeitem` ARIA + arrow-key navigation.

### API tightening — string parameters became enums

-   `DatePicker.Mode`: `string` → `DatePicker.DatePickerMode` (`Single`/`Range`/`Month`/`Year`).
-   `Tabs.Variant`: `string` → `Tabs.TabsVariant` (`Default`/`Card`/`Pill`).
-   `FileUpload.Variant`: `string` → `FileUpload.FileUploadVariant` (`Dropzone`/`Button`/`Avatar`).
-   `Calendar.InitialView`: `string` → `Calendar.CalendarView` (`Days`/`Months`/`Years`).
-   If you pass these as string literals (`Mode="Range"`) update to the enum (`Mode="DatePicker.DatePickerMode.Range"`). `@bind`\-style usages are unaffected.

Docs site updated: new pages for ButtonGroup / DropdownButton / SplitButton, API tables + demos refreshed on DatePicker / DateTimePicker / Toast / TreeView / Tabs / FileUpload / Calendar. 134 components, 2,226 unit + 31 RegistryGen tests green.

v2.0.0-rc.31

May 2026

**Render-tree hardening — correctness + perf across the board.** A sweep of `@key` fixes, a real virtualised `DataTable`, `ForceMount` on Accordion/Collapsible panels, and cached hot-path computations. No public API removed; a few additive parameters.

### Correctness fixes

-   **DataGrid `@key` on every non-virtualised row/group/header/cell loop** — sort/filter/page/group-toggle and column reorder no longer mis-diff: rows and cell-edit components stop re-initialising, sort indicators and open filter popovers stay attached to the right column.
-   **`OverlayProvider` keyed + stable references** — closing one of several stacked overlays no longer makes the focus-trap / scroll-lock interop target the wrong element. The hosted-component cascade is now `IsFixed` so it stops re-rendering on every provider render.
-   **`SortableList` keyed** — drag-reorder now follows the item, not the index. New optional `Key` parameter for value-type items.
-   **`DataTable.Virtualize` now actually virtualises** — it was a no-op (rendered the full list either way). Wired to Blazor's `<Virtualize SpacerElement="tr">`; selection still works inside virtualised rows.
-   `@key` also added to FileUpload, Mention, Transfer, PickList, ImageGallery, TreeView/TreeViewNode, TreeSelect item loops.

### New / changed parameters

-   `<AccordionContent ForceMount="true">` and `<CollapsibleContent ForceMount="true">` — keep the panel in the DOM (with the `hidden` attribute) when collapsed instead of unmounting, so form input / scroll / component state survives. Mirrors Tabs' rc.29 pattern. Default off, no behaviour change.
-   `SortableList.Key` (`Func<TItem, object>?`).

### Performance

-   DataGrid caches the visible-columns projection instead of re-materialising it on every render.
-   DataTable caches `ItemsList` / `IsAllSelected` / `IsSomeSelected` instead of re-scanning every render.
-   TreeView caches the filtered tree — the recursive whole-tree deep-copy now runs only when the search text or `Items` change, not on every render.
-   Carousel only calls `StateHasChanged` from its scroll callback when the prev/next-availability flags actually flip — no more a render per scroll frame during a drag.

v2.0.0-rc.30

May 2026

**MCP server overhaul — from reference lookup to authoring assistant.** The `@lumeo-ui/mcp-server` picks up six new tools so an LLM (Claude, Cursor, Copilot) can not only look components up but write correct, runnable Razor on the first try. No component-library changes — this is all tooling.

### New MCP tools

-   `lumeo_validate_markup` — pre-flight a Razor snippet: do the components exist? are parameter names real (catches hallucinated APIs)? are enum values legal? are sub-components nested inside their required parent (`TabsContent` in `Tabs`, `DialogContent` in `Dialog`, …)? Returns structured errors/warnings.
-   `lumeo_get_install` — everything to actually run a component: NuGet + `dotnet add`, `@using` imports, `AddLumeo…()` DI, host-page `<script>/<link>` includes, sub-components, and gotchas (portal components needing theme classes on `<body>`, OverlayProvider, required params).
-   `lumeo_get_example` — the real Razor snippet(s) behind the docs-site demos, now extracted into the API schema at generation time (122/131 components covered).
-   `lumeo_get_theme_tokens` — all 58 theme tokens (colour + radius CSS variables) so the model uses `bg-primary` / `text-foreground` / `border-border`, never raw hex, never `dark:` prefixes.
-   `lumeo_list_patterns` / `lumeo_get_pattern` — the 16 full-page "blocks" (dashboard, auth, chat, kanban, mail, settings, …) with their complete Razor source as a starting skeleton.
-   `lumeo_changelog` — current package version + API-schema generation timestamp + changelog link.

`lumeo_get_component` now also includes the extracted `examples` array. The registry generator gained an example/theme-token/pattern extractor that scrapes the docs pages — so the MCP stays in sync automatically on every release.

v2.0.0-rc.29

May 2026

**Tabs: `RenderMode` for panel-state preservation.** By default a `TabsContent` panel is unmounted the moment you switch away — losing form input, scroll position and any component state. The new `RenderMode` parameter gives you the same three knobs DevExpress exposes, with clearer names.

### Modes

-   `Active` (default) — only the active panel is in the DOM; switching away unmounts it. Lightest footprint, no behaviour change from before.
-   `Lazy` — a panel renders the first time its tab becomes active, then stays mounted (hidden) so its state survives subsequent switches. DevExpress `OnDemand`.
-   `Eager` — every panel renders up-front; inactive ones are hidden. State always preserved, heaviest initial render. DevExpress `Always`.
-   Per-panel override: `<TabsContent ForceMount="true">` always keeps that one panel mounted regardless of the parent mode — pin a half-filled form, leave the rest light.

Hidden panels use the standard `hidden` attribute, so they're skipped by screen readers and the keyboard tab order while still preserving DOM state.

v2.0.0-rc.28

May 2026

**DataGrid full virtualisation + Calendar / DatePicker culture-awareness.** Big DataGrid round: customisable page-size selector, correctness fix for virtualised tables, and the long-missing third virtualisation mode (infinite-scroll over a backend). Calendar now starts on Monday under de-DE/fr-FR/en-GB by default and renders day headers in the user's language.

### DataGrid — three virtualisation modes, all wired up

-   **Virtualised server mode (NEW)** — set `Virtualized="true"` + `OnRangeRequest` and the grid fetches a sliding window of rows from your backend as the user scrolls (Blazor's `<Virtualize ItemsProvider>`). Pagination is hidden automatically; sort, column filter, and global search all trigger `RefreshDataAsync()` so the next request reflects the new query state. Public `grid.RefreshVirtualizedAsync()` for manual refetch after external mutations.
-   **Virtualised client mode (correctness fix)** — the in-memory virtualiser now passes `SpacerElement="tr"`. Without it, Blazor's default `<div>` spacers are invalid `<tbody>` children and the browser hoisted them out of the table, breaking layout whenever the threshold tripped.
-   **New tunables**: `VirtualItemSize` (row-height estimate, default 41 px) and `VirtualOverscanCount` (default 3 rows).
-   **PageSizeOptions** — configurable rows-per-page selector (default `[10, 25, 50, 100]`); pass `new[] { 10, 50, 100, 200, 300 }` for larger datasets, or empty array to hide the selector entirely.

### Calendar / DatePicker — culture-aware

-   `Calendar.FirstDayOfWeek` is now `DayOfWeek?`. Unset → derives from `CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek`: de-DE / fr-FR / en-GB → Monday-first, en-US → Sunday-first.
-   Day headers derive from `AbbreviatedDayNames` trimmed to two letters: en-US `Su Mo Tu We Th Fr Sa`, de-DE `Mo Di Mi Do Fr Sa So`, fr-FR `lu ma me je ve sa di`.
-   Soft API change: explicit `FirstDayOfWeek="DayOfWeek.Monday"` still works (implicit lift to nullable).

v2.0.0-rc.27

May 2026

**Empirically reproduced + root-caused the popover-in-Sheet positioning bug.** Bug #1 (slide transform-trap) and Bug #16 (DatePicker positioned relative to sheet, not viewport) turned out to be the SAME root cause. Verified end-to-end in Chrome 131 via instrumented diagnostics — toggling the sheet's `animation` property on/off snapped the popover x from 3278 (sheet-relative) to 1742 (viewport-relative).

### The real root cause (took 6 RCs to find)

-   **Chrome creates a containing block for any element with an active `transform`\-animating `animation` declaration — INDEPENDENT of the current computed `transform` value**. Even with computed `transform: none` (overridden via `!important`), the active `animation: ... slide-in-from-right` declaration alone makes Chrome establish the sheet as a containing block for fixed-positioned descendants.
-   Empirically verified: `popover.x = 3278` when sheet has the animation declared (sheet at x=1536 + popover style.left=1742 ≈ 3278). Add `animation: none !important` on the sheet → `popover.x = 1742.86` (viewport-relative). Confirmed via instrumented Chrome 131 DevTools session.
-   This is Chrome's compositor optimization — it pre-creates a layer for transform-animating elements (treating them as `will-change: transform` implicitly). Per CSS spec strict reading this is technically aggressive but Chrome does it.

### The fix

-   `attachOverlaySlideEnd` in `components.js` now sets BOTH `animation: none !important` AND `transform: none !important` after the slide animation finishes. The animation property is what kills Chrome's containing-block treatment; the transform is belt-and-suspenders.
-   Bug #1 (matrix containing block) and Bug #16 (DatePicker top:-1156, popover at sheet x) both resolve. Same fix.
-   Slide animation visual is preserved (animation runs to completion, then properties are cleared in the post-finished state).

v2.0.0-rc.26

May 2026

**Button propagation params + harder popover positioning guards.** Two follow-ups from rc.25 user feedback: (1) Razor's `@onclick:stopPropagation` / `@onclick:preventDefault` directives can't be applied to a Lumeo Button (case-insensitively collide with `OnClick`). Now exposed as `StopPropagation` / `PreventDefault` bool parameters, no more `<span>`\-wrapper workaround needed. (2) Bug #16 (DatePicker `top: -1156px`) cause is still inconclusive — math doesn't match the reported popover height — but `positionFixed` now flushes layout before measurement and applies a universal max-height + bottom-overflow guard.

### Added — Button propagation control

-   `[Parameter] public bool StopPropagation` + `[Parameter] public bool PreventDefault` on `Button`. Wired to `@onclick:stopPropagation` / `@onclick:preventDefault` on the underlying `<button>` element. Drop-in replacement for the `<span @onclick:stopPropagation="true"><Button…/></span>` workaround.
-   Plus `[Parameter] public ButtonType Type` (default `Button`) with `Submit` / `Reset` options for explicit form-button intent.

### Improved — popover positioning robustness

-   **Synchronous layout flush before measurement**: `positionFixed` now reads `offsetHeight` before `getBoundingClientRect()` so the browser flushes any pending layout (animation scaling, Blazor render mid-flight) and we measure the popover's settled dimensions, not a stale or in-flight rect.
-   **Universal max-height clamp**: if the natural popover content exceeds the viewport, a scrollable cap is applied unconditionally — not only on flip-up edge cases.
-   **Bottom-overflow late guard**: even after side-flip and other branches, if the popover would render past the viewport bottom, it's pulled up to fit with max-height applied.
-   Combined with rc.23's negative-top guard, this makes `positionFixed` a true belt-and-suspenders surface — even if the underlying root cause for the rc.21–rc.25 user-reported `top: -1156` is still inconclusive (the math doesn't match the reported popover height — root cause likely a transient layout state during animation), the popover is always visible.

v2.0.0-rc.25

May 2026

**Slide-trap fix #5 — Web Animations API.** rc.24 had the `!important` piece right (cascade priority) but missed the second bug: the listener was attached via `addEventListener('animationend', ...)` from C# `OnAfterRenderAsync` via JS interop. Even in WASM, the latency between render and listener-attach is enough that the 300 ms slide animation can already be `finished` before the listener exists. `addEventListener` does NOT replay events that fired before attach, so the cleanup never ran.

### The actual fix (5th attempt)

-   Replaced `addEventListener` with the Web Animations API. `el.getAnimations()` returns running OR already-finished animations (fill-mode keeps the finished ones alive in the list), and `animation.finished` is a Promise that resolves immediately if the animation already ended, or once it does. Race-condition-free regardless of when the function is called.
-   After awaiting `.finished`, set `setProperty('transform', 'none', 'important')` (rc.24's correct cascade-priority piece). Inline + !important is rank 4 (_!important author_) which beats animations (rank 5), so the fill-mode-forwarded matrix is finally overridden.
-   Defensive: if `getAnimations()` returns no slide animation (Animation=Fade/None, or class already dropped), set the transform anyway. Edge cases get the same protection.

### For maintainers — five-RC postmortem

-   **rc.21**: keyframe trick (`99%: translateX(0); to: none`) — Chrome interpolates none↔translate(0) as identity under fill-mode:both. Placebo.
-   **rc.22**: Razor `@onanimationend` handler — Blazor EventArgs lacks animationName, descendants bubbled up. Placebo.
-   **rc.23**: native JS listener with plain `style.transform = 'none'` — animations rank above normal author. Placebo.
-   **rc.24**: same listener but with `!important` — cascade priority correct, but listener attaches after animation ends. Placebo.
-   **rc.25**: `getAnimations() + .finished promises + setProperty important` — race-free AND cascade-correct. Empirically verified.

v2.0.0-rc.24

May 2026

**Slide-trap finally fixed (4th attempt).** rc.21–rc.23 were all placebo: the keyframe trick (rc.21) and the inline-style approach (rc.22, rc.23) could never defeat animation-fill-mode forwarding because of the CSS Cascade Level 4 priority order. Animations rank ABOVE normal author rules — including plain inline `style="transform: none"`. The fix needs `!important` on the inline style (rank: !important author > animations) to actually override the forwarded keyframe value. Now done via `setProperty('transform', 'none', 'important')` in the native animationend listener.

### Why the previous attempts failed

-   **rc.21 keyframe trick** (`99%: translateX(0); to: none`): Chrome resolves `to: none` under fill-mode:both as identity matrix. fill-mode forwards interpolated values, and the transition between `translateX(0)` and `none` is treated as identity by all major engines. End state stuck at `matrix(1,0,0,1,0,0)`.
-   **rc.22 Razor handler that drops the class**: Blazor's `@onanimationend` EventArgs doesn't expose `animationName`, so descendant zoom-in / fade-in animations bubbled up and prematurely dropped the class mid-slide. Plus the Razor → JS roundtrip latency was racy.
-   **rc.23 native JS listener with plain inline style**: filtered correctly on `slide-in-from-*` + `target === el`, but used `el.style.transform = 'none'` which is normal author cascade rank. Animations outrank that. Matrix stayed.

### The fix that actually works

-   `el.style.setProperty('transform', 'none', 'important')` inside the same filtered animationend listener. Inline + !important is _!important author_ in the cascade, which beats animations. The forwarded fill-mode value is properly overridden, computed transform becomes `none`, no containing block, popovers (Select / DatePicker / Combobox) inside Sheet/Drawer position relative to the viewport.
-   Verified mechanism: per CSS Cascade Level 4 spec, the priority order from highest to lowest is — transitions, !important user-agent, !important user, **!important author**, animations, normal author (incl. plain inline style), normal user, normal user agent.

v2.0.0-rc.23

May 2026

**Ironclad slide-trap + defensive popover clamp.** rc.22's Razor-side `@onanimationend` handler had two timing issues: (1) Blazor's `EventArgs` for the directive doesn't expose `animationName`, so we couldn't filter; descendant animations (Calendar's `animate-zoom-in`, Combobox fade-in) bubbled up and could trigger the cleanup mid-slide. (2) The Razor → JS roundtrip was racy enough that some users still observed the matrix sticking. Replaced with a native JS listener.

### Fixed — slide-trap (third time's the charm)

-   New `Interop.AttachOverlaySlideEnd(elementId)` JS interop registers a native `animationend` listener that filters strictly on `slide-in-from-*` AND on `event.target === el` (descendants don't trigger it), then sets inline `style.transform = 'none'`. Inline-style precedence beats keyframe fill-mode forwarding — the matrix is cleared, no containing block, popovers position relative to viewport.
-   `SheetContent` + `DrawerContent` now call this on every open with `Animation=Slide`.
-   Removed the racy Razor-side `@onanimationend` handler + `_animationDone` flag — JS interop is the sole, reliable path.

### Fixed — defensive popover top clamp

-   `positionFixed` now applies a final guard: if the computed `top` ends up negative for any reason (entrance-animation scaling, stale rect, weird parent flex layout), it's forced to `8px` with `max-height` + `overflow: auto`. Belt-and-suspenders for the rc.21 / rc.22 user-reported `top: -1156`.

v2.0.0-rc.22

May 2026

**rc.21 verification fixes.** Three issues surfaced after rc.21 shipped: the slide-keyframes trick from rc.21 didn't actually work (Chrome resolves `to: none` to identity matrix under `animation-fill-mode: both`); DatePicker calendar popovers can render at `top: -1156px` inside Sheets when the popover stretches taller than the viewport; `<EditForm>` wrapping a Sheet's body broke the footer-pin layout. All three fixed.

### Fixed — slide-animation transform trap (real fix this time)

-   The rc.21 fix used a `99% / to: none` keyframe trick. That doesn't work: `animation-fill-mode: both` keeps the element in the animation's end state, and Chrome resolves `transform: none` to identity matrix when blended through animation. The element ends up with `matrix(1,0,0,1,0,0)` — still a containing block, popovers still off-screen.
-   **Real fix:** SheetContent and DrawerContent now bind `@onanimationend` and drop the `animate-slide-in-*` class once the animation completes. Without the class, there's no animation, no fill-mode, no transform — the element returns to its static state and the viewport regains its natural role as the containing block. Visually identical landing; popovers (Select, DatePicker, Combobox) inside Sheets/Drawers position correctly. Apps with the `animation: fade-in !important` workaround can drop it.

### Fixed — DatePicker / popover overflow clamping

-   Inside a Sheet's flex layout, the calendar popover could stretch to ~1574 px. The flip-up logic in `positionFixed` then computed `top = triggerTop − contentHeight − gap`, which went deeply negative (e.g. −1156 px) — popover invisible above the viewport.
-   Now compares `spaceAbove` vs `spaceBelow` and picks the side with more available room, capping the popover with `max-height` + `overflow: auto` when neither side fits the natural content height. The popover is always visible.

### Fixed — EditForm-in-Sheet footer pin

-   When consumers wrapped a Sheet's body in `<EditForm>`, the rendered `<form>` was content-sized — SheetFooter stuck below the last field instead of pinning to the bottom. New CSS rule in `lumeo.css` makes direct `<form>` children of Lumeo sheet/dialog/drawer dialogs inherit the flex-column layout — no consumer-side CSS workaround needed.

v2.0.0-rc.21

May 2026

**Production-feedback pass.** Driven by a detailed real-world migration report — closes the slide-animation transform trap that broke popovers in Sheets/Drawers, generalizes TagInput, expands the Lumeo.Text color map, adds a controlled-mode override for popover state, and ships a new EditForm + Localization guide.

### Fixed — popover containing-block trap

-   **Slide keyframes now end at `transform: none`** (was identity `translateX(0)`). Per CSS spec, any non-`none` transform — including identity translates — establishes a containing block for `position: fixed` descendants. The old keyframes meant Select / DatePicker / Combobox popovers inside a slid-in Sheet rendered relative to the Sheet instead of the viewport, ending up off-screen. The 99 % step keeps the visual landing identical; the 100 % step disposes of the transform.
-   Apps with the `.animate-slide-in-* { animation: fade-in !important }` workaround can drop it.

### Added — Sheet + Drawer Animation variant

-   `SheetContent.Animation` and `DrawerContent.Animation` accept `Slide` (default), `Fade`, or `None`. Slide is now safe (transform-trap fixed); Fade / None remain available for consumers who want maximum predictability inside re-render-heavy parents.

### Added — TagInput is now generic

-   **`TagInput<TItem>`** with `TItem` defaulting to `string` so existing string consumers compile unchanged. Real apps now build user-pickers, mention-pickers, etc. on top of structured items.
-   New params: `GetTagText`, `GetSuggestionText`, `TagTemplate` (RenderFragment<TItem>), `SuggestionTemplate`, `Separators[]` (multi-separator paste), `ValidateInput` / `ValidateInputAsync`, `CreateTag`, `MaxTagsHelperText`.
-   New User-picker demo on the TagInput docs page (avatar + name in tag chip + name/email rows in suggestion popup, comma/semicolon/space separators).

### Added — Controlled-mode popover state

-   `DatePicker` gains optional `Open?` + `OpenChanged` (Select / Combobox already had it). When non-null, the consumer owns popover state — survives parent re-renders. Use `@bind-Open` inside heavily re-rendering parents (EditForm with active validation) to keep the popover open through validation cycles.

### Added — Lumeo.Text full theme-token map + small param expansions

-   `<Lumeo.Text Color="..."/>` now accepts every theme token: `foreground`, `muted`, `primary`, `destructive`, `success`, `warning`, `info`, `accent`. Case-insensitive. Unknown values fall back to no class (deliberate hardening).
-   `FileUpload` gains `Size` parameter (Sm / Default / Lg) for the Button variant.
-   `BottomNavItem` gains `IconSize` (default `"h-5 w-5"`); consumer can pass `"h-7 w-7"` to fit an avatar in the icon slot.
-   `ToggleGroupItem` auto-spaces icon + label (`gap-1.5` on the base class) — no more manual `Class="gap-1.5"`.

### Docs — EditForm + Localization guides

-   **New: [EditForm + Lumeo Validation guide](/docs/edit-form)** explaining why Lumeo inputs are not `InputBase<T>` derivatives, the canonical pattern with `EditContext.GetValidationMessages` + `Invalid` wiring, server-side error injection, and the nullable-EventCallback lambda workaround.
-   **New: [Localization guide](/docs/localization)** documenting Blazor WASM's en-US default and how to set browser-locale at startup.
-   Sheet + Drawer docs pages gained an info Alert about the rc.21 transform-trap fix and the new Animation variants.

v2.0.0-rc.20

May 2026

**Booking-calendar API + per-component registry endpoints + Calendar UX polish.** Calendar gains `DateTooltip` and `DateBadge` callbacks for hotel-style availability indicators, the month + year header is now a single click target with same-width views across Days/Months/Years, and every component has its own self-contained `/registry/<key>.json` endpoint with full LLM-ready detail (catalog + API schema + source + slots + services + cascades + related + keyboard + tests + mdSummary).

### Added — Calendar booking API

-   **`DateTooltip`** (`Func<DateTime, string?>?`): per-day tooltip text rendered as the day cell's `title` attribute (native browser tooltip on hover). Useful for "Sold out" / "Limited availability" hints in booking flows.
-   **`DateBadge`** (`Func<DateTime, RenderFragment?>?`): per-day indicator slot rendered absolutely positioned in the bottom-right of the day cell — status dots, count badges, icons. Non-interactive (`pointer-events-none`) so clicks still hit the day button.
-   Both callbacks plus the existing `IsDateDisabled` and `DateClass` are now also forwarded through `DatePicker` and `DateRangePicker` so the booking-calendar UX works through the popover-style pickers too.
-   New booking-style demo on the Calendar docs page: synthesised hotel availability with green / amber / red / grey dots + tooltips like _"Sold out"_, _"Limited availability"_.

### Improved — Calendar UX

-   **Single click target for month/year** — the Days view header used to have two adjacent buttons (month name + year) that opened different pickers. Replaced with one combined button. Cycle is now: Days → click → Months → click year → Years. One predictable click target per view.
-   **Equal width across all three views** — the picker no longer visibly resizes when switching between Days, Months and Years. Each view is fixed to 224 px of inner content (matches the 7-column day grid).

### Added — Per-component registry endpoints

-   **131 self-contained component files** at `https://lumeo.nativ.sh/registry/<key>.json` (and the matching NuGet path `_content/Lumeo/registry/<key>.json`) — same shape as shadcn's per-component registry plus extra LLM-friendly fields: `docsUrl`, `sourceUrl`, `source` (full Razor file content), `slots`, `serviceDependencies`, `cascadingDependencies`, `relatedComponents`, `keyboardInteractions`, `tests`, `mdSummary` (a self-contained Markdown reference paragraph an LLM can drop straight into context).
-   The `registryUrl` field on every component in the root `registry.json` now resolves correctly — previously it pointed at endpoints that 404'd.
-   `Lumeo.Cli` `DefaultRegistryUrl` bumped from a stale jsdelivr / rc.9 pin to the live docs site (`https://lumeo.nativ.sh/registry.json`).

### Fixed — Avatar shape + DropdownMenu focus + E2E CI

-   **Avatar outer wrapper now follows ShapeClasses** so consumer-applied borders / rings (e.g. `border-2 border-background` on AvatarGroup overlap) follow the avatar's actual circular shape — no more square frames around fallback initials.
-   **DropdownMenu focuses the menu content on open** per the WAI-ARIA menu pattern. Previously `tabindex="-1"` was set but focus was never moved, so Escape and Arrow keys never reached the keydown handler — keyboard nav was actually broken in production.
-   **E2E visual test skipped under CI** until a perceptual differ ships. The home-above-fold byte-equal compare can't agree across Windows (where the baseline was generated) and the Ubuntu CI runner because of font hinting / sub-pixel rendering. The other 15 E2E tests still gate every push and PR.

v2.0.0-rc.19

May 2026

**Hardening pass**. Closes every P1 + P2 + P3 from an external rc.18 deep review: cross-instance drag state in DataGrid, EventCallback fire-and-forget, preset-codec namespace collision, red E2E suite, lifecycle races in Alert / SafeAsyncDispatcher, JS event-handler leaks in Editor + Gantt, eval() in docs, Worker payload + collision handling, Word-import DoS surface, mobile-unfriendly block demos. Plus the big one: a complete auto-generated MCP schema so Claude Code understands all 131 components without reading source.

### Added — MCP server is now fully complete

-   **131 / 131 components in the schema** — every component now has full parameters, types, defaults, XML doc descriptions, EventCallback events, nested enums + records, `@inherits` / `IAsyncDisposable`, and sub-components grouped per folder. 3,152 parameters total, 86 enums, 48 records, 0 thin fallbacks.
-   **Auto-generated from Razor source** via a new Roslyn-based pass in `Lumeo.RegistryGen`. Every release regenerates the schema; no more manual catalog drift.
-   **Hand-curated examples preserved** as an overlay — `lumeo_get_component` still surfaces the existing example Razor snippets for ~30 popular components.

### Fixed — DataGrid correctness (P1)

-   **Column reorder cross-talk**: a static `ColumnDragState` was shared across every grid in the process — drops in grid B used grid A's source index. Replaced with an instance-bound `DataGridDragState` + `OwnerGridId` guard. Same fix for row reorder. New regression tests cover both drag types.
-   **EventCallback fire-and-forget at 6 sites** in DataGrid.razor — `SelectedItemsChanged`, `OnColumnReorder`, `OnRowReorder` were called without await. Now awaited where the call site can be async, dispatched via `SafeAsyncDispatcher.FireAndForget` where it must stay sync.
-   **Auto-save stale generation**: the existing generation guard skipped LocalStorage writes but still called `OnLayoutSave` with stale snapshots. Guard now covers both paths.

### Fixed — Lifecycle / async hardening (P2)

-   **`SafeAsyncDispatcher` outer task** — the inner try/catch only covered the work delegate. If `InvokeAsync` itself threw (renderer disposed), the outer Task was unobserved. Outer call now wrapped in an async helper that catches expected lifecycle exceptions silently and logs anything else.
-   **Alert AutoDismiss timer/dispose race** — replaced `System.Threading.Timer` with `CancellationTokenSource` + `Task.Delay`; `Dispose` cancels the token and flips a `_disposed` flag before any state mutation.
-   **Editor + Gantt JS listener leaks** — anonymous `addEventListener` closures (mousemove, mouseleave, drop on the editor; document-level mousemove + mouseup on Gantt drag) survived `destroy(id)`. All listeners now stored as named handlers; destroy iterates and removes each.

### Fixed — Theming + API + Security (P1 + P2)

-   **Preset code / Worker ID namespace collision** — both spaces were 6-char Base62. Some Worker IDs decoded as valid v1 local presets and never hit the server. New explicit prefix scheme: `l_<6>` for local codes, `p_<6>` for Worker IDs. Bare 6-char input keeps legacy fallback behavior with strict version checks.
-   **Worker payload check post-read** — the `content-length` header was the only authoritative check; missing or wrong header bypassed the limit. Now reads `arrayBuffer()` first and enforces real `byteLength`.
-   **Worker collision retry** — same 6-char ID with different payloads no longer overwrites silently. Up to 8 salt-based retries; idempotent on matching payload; 409 if exhausted.
-   **Word-import 8 MiB cap** — JS pre-arrayBuffer file.size check + .NET pre-Convert.FromBase64String size guard + new `WordImportSizeException`. New `MaxWordImportBytes` parameter on RichTextEditor.
-   **Removed `eval()` in IconPage** — replaced with a named JS helper. CSP-clean.
-   **Vendored TipTap stack (~1.4 MB ESM bundle)** — RichTextEditor no longer dynamic-imports from `esm.sh` at runtime. Ships at `_content/Lumeo.Editor/js/tiptap-bundle.js`; works under strict CSP and offline. `window.lumeoTiptapBundleUrl` is the override hook for consumers who want to host their own.

### Fixed — Overlay UX + Avatar shape

-   **OverlayService double-backdrop** when consumers nested another `<SheetContent>` / `<DialogContent>` / `<DrawerContent>` inside their service-opened component. New `OverlayShellMarker` cascade — nested \*Content components self-detect the host shell and pass children through. Both patterns now render exactly one backdrop. Regression test asserts `bg-black/80` appears exactly once.
-   **Avatar outer wrapper follows ShapeClasses** — consumer-applied borders / rings (e.g. AvatarGroup overlap framing) now follow the avatar's actual shape. Previously the border landed on the rectangular outer div while the inner div clipped to a circle, creating square frames around fallback initials.
-   **DropdownMenu keyboard nav** — menu container had `tabindex="-1"` but never received focus on open, so Escape and Arrow keys never fired. Now focuses the content on open per WAI-ARIA menu pattern. Surfaced while stabilizing the E2E suite.

### Improved — E2E suite is green and CI-gated (P1)

-   **16 / 16 E2E tests passing** (was 8 / 16). Stable selectors via `data-testid` on the relevant docs elements; Search palette result locators scoped to the palette overlay; baseline snapshot committed at `tests/Lumeo.Tests.E2E/Snapshots/home-above-fold.png` with deterministic init-script (consent banner suppressed, animations zeroed).
-   **New `.github/workflows/e2e.yml`** — installs Playwright browsers, builds the docs, runs the docs server on port 5290, runs E2E against it, uploads `docs-server.log` on failure.

### Improved — Docs polish (P3)

-   **Mobile / Desktop preview toggle** on ComponentDemo — DashboardBlock / PricingTableBlock / SettingsPageBlock no longer force phone users into horizontal scroll. Toggle wraps the demo in a 420 px phone frame so the experience is honest, not painted-over.
-   **`dotnet format --verify-no-changes` is green** — formatting drift swept across 27 files in a single style pass, no behavior change. Ready to wire into CI as a release gate.

v2.0.0-rc.18

April 2026

**Drop-in CSS restored** + **visible Chart loading label**. `_content/Lumeo/css/lumeo-utilities.css` ships in the NuGet package again after rc.15–rc.17 inadvertently dropped it. The bundle now also covers every utility class used inside the satellite packages — no per-satellite stylesheet needed. Charts also gained an always-on "Loading…" label to make in-flight data unambiguous.

### Added — Chart loading label

-   **New `ShowLoadingLabel` + `LoadingText` parameters** on `Chart` (and forwarded by chart wrappers like `BarChart`). When `IsLoading` is true, a small top-right pill (Lucide `LoaderCircle` + "Loading…" text) is overlaid on top of whichever `SkeletonStyle` is active. Default-on so users never mistake cycling phantom data for a bug; opt out per-chart via `ShowLoadingLabel="false"`.

### Fixed — Drop-in setup regression

-   **`lumeo-utilities.css` ships again** — the rc.15 package-split spec moved the file out on the assumption a registry CDN would host it, but the CDN was never set up. Consumers following the docs got a 404 + visibly unstyled Lumeo components (Badge `px-2.5` missing, DataGrid toolbar borders gone, Switch container collapsed). Restored to `_content/Lumeo/css/lumeo-utilities.css`.
-   **Bundle now covers all 6 satellites** — `lumeo-utilities.src.css` extended to `@source` the `UI/` folder of every satellite (DataGrid, Charts, Editor, Scheduler, Gantt, Motion). Drop-in setup now works whether you install only core or all 7 packages.
-   **Docs site Tailwind scan** extended the same way — `docs/Lumeo.Docs/Styles/tailwind.css` was scanning only `src/Lumeo/UI/**/*.razor`, so the live docs DataGrid demos were missing the same classes. Fixed in the same release.
-   **NuGet author** across all 9 published packages updated from `bemi` (the developer's GitHub handle) to `nativ.sh`.

### Migrating from rc.15 / rc.16 / rc.17

-   If you vendored an older copy of `lumeo-utilities.css` as a workaround, you can drop it and revert your `App.razor` link tag back to `_content/Lumeo/css/lumeo-utilities.css`.
-   If you set up your own Tailwind build (per the rc.15 "advanced" path), you can keep it — that path still works. Just drop the `@source` entries pointing at Lumeo packages, since the shipped bundle now covers them.

v2.0.0-rc.17

April 2026

**Audit-driven hardening**. A 10-item code review surfaced real lifecycle, async, CI, and test-coverage gaps. This release closes all of them. **+387 tests** (1744 → 2131), three new infrastructure layers (component contract theory, Playwright e2e, visual snapshots), and four lifecycle bugfixes.

### Improved — Lifecycle & async safety

-   **DataGrid debounced server search** rewritten to a CTS-backed pattern — exact-last-call semantics, dispose cancels in-flight work, exceptions surfaced. Test now asserts `Assert.Equal(1, callCount)` instead of race-tolerant `callCount <= 2`.
-   **OnThisPage** (docs sidebar) now uses a `CancellationTokenSource` per route — old retry scans cancel cleanly when navigating, no more stale headings on fast clicks. Replaced JS `eval` with a dedicated function.
-   **Toast / Overlay / MegaMenu** providers — the `_ = InvokeAsync(...).ContinueWith(...)` pattern (which silently logged errors) replaced by `Lumeo.Services.SafeAsyncDispatcher`. 9 call-sites converted; expected lifecycle exceptions (`JSDisconnectedException`, `ObjectDisposedException`) swallowed silently, others logged with a structured tag.
-   **ComponentInteropService** sync `Dispose()` now fire-and-forgets the same JS-side cleanup that `DisposeAsync` runs — stops browser-side observers/listeners from leaking when the sync path is taken.

### Added — Test infrastructure

-   **Direct unit tests for 23 components** previously without test files (Cascader, ColorPicker, ConsentBanner, DateTimePicker, Gantt, ImageCompare, InplaceEditor, InputMask, Kanban, MegaMenu, Mention, PasswordInput, PopConfirm, QRCode, RichTextEditor, Scheduler, Sortable, SpeedDial, TimePicker, Tour, Transfer, TreeSelect, TreeView). Coverage 108/131 → 131/131.
-   **Component contract `[Theory]`** — 250 test cases spanning 125 components; asserts every component renders with defaults AND forwards `AdditionalAttributes` to its root. Catches "I forgot to splat" regressions across the entire library at once.
-   **Lumeo.Tests.E2E** — new Playwright .NET project with 5 high-value smoke tests (Dialog focus trap, DropdownMenu keyboard nav, Tooltip hover, catalog renders ≥100 cards, Cmd+K palette navigates). Reaches the failure modes bUnit can't.
-   **Visual snapshot foundation** — one example test capturing the home page above-the-fold and comparing against a baseline PNG. Set `LUMEO_E2E_UPDATE_SNAPSHOTS=1` to regenerate baselines.
-   **WordImporter real-DOCX test unskipped** — programmatic in-memory DOCX with headings, paragraphs, and styles replaces the local-path fixture that previously caused the test to be skipped on every CI run.

### Improved — CI release gate

-   CI now builds `Lumeo.slnx` with `-warnaserror` across the entire solution (was: library + satellites only — docs project was excluded).
-   CI runs all three test projects: `Lumeo.Tests`, `Lumeo.Docs.Tests`, `Lumeo.RegistryGen.Tests`. Was previously only `Lumeo.Tests`.

### Fixed — Docs nav UX

-   Top-nav highlight: clicking into a component (`/components/<slug>`) now keeps "Components" lit instead of switching to "Docs".
-   Sidebar from any docs/patterns/component-detail page now shows the **full nav** (docs + components + patterns) with collapsible groups; the group containing the current URL auto-expands. No more "to find a component you have to click into a component first".

v2.0.0-rc.16

April 2026

**Lumeo.Motion satellite (v0.1)** + **Docs nav v2**. Motion ships 10 user-verified components — a curated set polished to perfection; more are coming in future releases. Install with `dotnet add package Lumeo.Motion`.

### Added — Lumeo.Motion v0.1

-   **Lumeo.Motion satellite package** — 10 user-verified motion primitives for high-energy Aceternity / Magic UI-style interfaces.
-   **Migrated from core (7)**: `BlurFade`, `BorderBeam`, `Marquee`, `NumberTicker`, `ShimmerButton`, `Sparkles`, `TextReveal`.
-   **New (3)**: `AnimatedBeam` (Magic UI port — SVG gradient path between nodes), `Confetti` (canvas burst escaped from demo box via `position:fixed`), `Dock` (cursor-magnification with Lucide icons).
-   Catalog cards show a NuGet badge for satellite components. All components stay in `@namespace Lumeo` — no consumer `@using` changes needed.
-   More motion primitives (AnimatedCircularProgressBar, AuroraBackground, Globe, HoverBorderGradient, MagicCard, Meteors, MorphingText, OrbitingCircles, Ripple, ShineBorder, Spotlight, TypingAnimation, WordRotate, and more) are deferred to a future release pending final visual polish.

### Added — Docs nav v2

-   **Component catalog page** (`/components`) — sticky category rail, filter chips, and 480×270 preview-card thumbnails for all components.
-   **Algolia full-content search** — Cmd+K now queries `lumeo_docs` index (components, patterns, blocks, guides); falls back to a local slim index when Algolia is unavailable.
-   **registry.json** as single source of truth — component metadata drives the catalog, the indexer, and the prerender script.
-   **Thumbnail prerender script** (`scripts/prerender/run-all.mjs`) — headless Puppeteer renders one PNG per component; runs in CI on registry change.
-   **Algolia indexer script** (`scripts/algolia/index-docs.mjs`) — pushes records to Algolia on every docs deploy.

### Improved

-   Sidebar **Form** group collapsed from 34 individual links to 5 logical subgroups; **Data Display** from 28 to 5 — both data-driven from `nav-config.json`.
-   `CatalogFilterChips` buttons now expose `aria-pressed` state to assistive technology.
-   `CatalogRail` sticky offset aligned to `top-[84px]` to match NavMenu / BlocksSidebar / CustomizerSidebar.

v2.0.0-rc.15

April 2026

Major release: **package split** + **RichTextEditor Pro** + custom **Gantt** renderer. Lumeo is now 6 packages instead of 1 — install only what you use.

### Package split (DevExpress / Microsoft.Extensions model)

-   `Lumeo` — core, ~568 KB. Layout, Forms (excl. RichTextEditor), Navigation, Overlay, Feedback, Display, Motion, Theme, ConsentBanner, AI surface.
-   `Lumeo.Charts` — ~196 KB. Chart + 30+ subtypes + ECharts interop.
-   `Lumeo.DataGrid` — ~111 KB. DataGrid, DataTable, Filter (incl. ClosedXML + QuestPDF for export).
-   `Lumeo.Editor` — ~50 KB. RichTextEditor + Word import via Mammoth.
-   `Lumeo.Scheduler` — ~22 KB. FullCalendar wrapper.
-   `Lumeo.Gantt` — ~19 KB. Custom SVG Gantt (no third-party dep).
-   All 6 packages share one lockstep version. Components stay in `@namespace Lumeo` so consumer `@using` directives are unchanged.
-   `lumeo add <component>` CLI now auto-detects the satellite and prompts to install via `dotnet add package`.

### RichTextEditor Pro (Lumeo.Editor)

-   **Mentions** with pluggable triggers (`@` users, `#` tags, `$` variables, custom).
-   **Slash commands** (Notion-style): `/heading`, `/list`, `/table`, `/code`, `/image`, `/quote`.
-   **Tables** with resizable columns + header rows.
-   **Code blocks with syntax highlighting** (lowlight: JS/TS/Python/CSS/HTML/JSON/Bash).
-   **Image upload** via drag/drop/paste — consumer-supplied `OnImageRequested` callback or base64 fallback.
-   **AI actions on selection** (Improve / Shorten / Expand / Translate / Summarize / FixGrammar) — consumer-supplied `OnAiAction` hooks into your own LLM.
-   **Word (.docx) import** — works in-browser by default via Mammoth in the WASM bundle. Default style map handles English + German Word default styles (Title/Titel, Heading 1-6/Überschrift 1-6, Body Text/Textkörper, etc.).
-   **Block drag handles**, **bubble menu**, **smart paste**, **markdown shortcuts**, **task lists**, **auto-link**.
-   **Lumeo Dialog** for the Link prompt instead of the native browser `window.prompt`.

### Custom Gantt renderer (Lumeo.Gantt)

-   Replaces the Frappe Gantt v1.2.2 dependency with ~400 lines of deterministic custom SVG. No more CDN dep, no more theming surprises across browsers.
-   View modes: Day / Week / Month / Year / HalfDay / QuarterDay.
-   Drag a bar to move (snaps to single days even in Week view), drag the right edge to resize, drag the bottom-edge handle to set progress.
-   Hover tooltip with task name, date range, day count, progress %.
-   Theme tokens read via `getComputedStyle` — no theme/cache battles.
-   Auto-scrolls horizontally so today is centered on first paint.

### Other

-   Overlay components (Dialog, Drawer, DropdownMenu, AlertDialog, Sheet, Popover, ContextMenu, Combobox, Select, ColorPicker, HoverCard, Tour, Collapsible, NavigationMenu) renamed `IsOpen` → `Open`. `IsOpen` kept as `[Obsolete]` alias for one release.
-   24 form inputs gained `Required` / `Invalid` / `ErrorText` / `HelperText` / `Label` / `Name`. Reads `FormFieldContext` via cascading parameter so `<FormField>` wrapper still works.
-   Display components (Alert, Result, ReasoningDisplay, Statistic, SparkCard) gained Size + Variant; trigger components (BackToTop, SpeedDial, Chip, Carousel) gained Disabled.
-   14 missing component doc pages added (Code, Delta, KpiCard, Marquee, NumberTicker, Overlay, PromptInput, ReasoningDisplay, ShimmerButton, SparkCard, Sparkles, StreamingText, TextReveal, ToolCallCard) + 62 new `ComponentsIndex` entries.
-   Select / Combobox `Searchable` filter actually filters items (was visible but inert).
-   Mammoth bumped to 1.11.0 to clear NU1902 advisory.
-   FullCalendar (Scheduler) now reads Lumeo theme tokens via `--fc-*` CSS variable map.

v2.0.0-rc.14

April 2026

Full accessibility sweep. Every icon-only button across the library now ships with an `aria-label` or `sr-only` text. WCAG AA violations from Lighthouse: zero.

### Added aria-label to icon-only buttons

-   `ToastClose` — new `AriaLabel` parameter (default "Close"), sr-only text for screen readers.
-   `Cascader`, `DateTimePicker`, `Select` (clear + multi-value chips), `Filter.FilterPill` — "Clear" / "Remove {label}" labels on the X icons that were previously empty buttons.
-   `Select` clear-icon converted from `<span>` to a proper `<button type="button">` — keyboard focusable and announced to assistive tech.

### Already compliant (verified)

-   `Alert` (dismiss), `Chip`, `Badge`, `TagInput`, `DatePicker` — all had aria-label on their close/remove icons.
-   `Dialog` / `Sheet` / `Drawer` close buttons — sr-only localized text via ILumeoLocalizer.
-   `Carousel` prev/next — aria-label + sr-only. `Pagination` has visible text. `Calendar` nav is fully labelled via L\["Calendar.\*"\] strings. `Rating` stars each emit "Rate {n} of {max}".

v2.0.0-rc.13

April 2026

Finishes the accessibility pass started in rc.12. `Slider` now has proper ARIA plumbing; the landing-page form-controls bento tile demonstrates the `AriaLabel` / `Label` parameters on every interactive element.

### Added

-   `Slider.AriaLabel` — accessible name for the range input. Also auto-emits `aria-valuemin` / `aria-valuemax` / `aria-valuenow`. For range sliders (`IsRange=true`), the end-handle's aria-label is suffixed with "(end)" automatically.

### Docs site

-   Landing-page form controls demo now passes `Label`/`AriaLabel` on every Switch, Slider, Checkbox, and Toggle — fixes the remaining Lighthouse "button / form element without accessible name" violations.

v2.0.0-rc.12

April 2026

Accessibility + NuGet health + performance polish. Fixes two long-standing Razor bugs in Card / Separator, adds `aria-label` plumbing to form toggles, and ships deterministic builds with Source Link so consumers can step into Lumeo source from any debugger.

### Fixed

-   `Card`, `CardContent`, `CardHeader`, `CardFooter`, `Separator`: moved `.Trim()` inside the Razor expression. Was previously rendered as a literal HTML attribute (silent error in browsers, `InvalidCharacterError` in strict DOM consumers like Puppeteer).
-   `theme.js`: replaced synchronous `XMLHttpRequest` to `/lumeo-theme.json` with a DOM lookup for an inlined `<script id="lumeo-theme-defaults">` tag. Eliminates the Chrome sync-XHR deprecation warning, the main-thread block, and the 404 console error on every site without a preset file.
-   `BlurFade` no longer holds its children at `opacity: 0` by default. Above-the-fold content is visible from first paint even when JS hasn't hydrated yet (previously caused a 1-2 s blank flash on prerendered landing pages).

### Added

-   `Switch.Label`, `Checkbox.AriaLabel`, `Toggle.AriaLabel` — new parameters that emit `aria-label` on the underlying button so icon-only usages pass Lighthouse / WCAG without ceremony. Switch also falls back to the current `OnLabel` / `OffLabel` text when no explicit label is set.
-   NuGet package now ships with **Source Link**, a `.snupkg` symbol package, and deterministic compiler flags. Debuggers (Rider, Visual Studio, VS Code) can step directly into Lumeo source from GitHub. All three NuGet Package Explorer health checks now pass.

### Docs site

-   Full static HTML prerender in CI — every route is served with complete content for first paint + SEO (192 routes, ~110 s prerender, via Puppeteer).
-   Per-route OG / Twitter preview cards generated via Satori — unique 1280×640 PNG per page with the page title, Lumeo brand, and category pill. Served from `/og/<slug>.png`.
-   Per-page `<meta name="description">`, `<link rel="canonical">`, and JSON-LD structured data (`TechArticle` / `BreadcrumbList` / `SoftwareApplication`).
-   `/llms.txt` + `/llms-full.txt` + per-route `.md` variants for GEO — ChatGPT, Perplexity, Claude can discover and cite Lumeo docs in one fetch.
-   Cloudflare Web Analytics (cookie-free) gated behind the consent banner.

v2.0.0-rc.11

April 2026

Adds the `ConsentBanner` component + `ConsentService`. GDPR-ready cookie / analytics consent primitive — no other Blazor component library ships one.

### Added

-   `Lumeo.Services.ConsentService` — per-category consent manager. Persists to `localStorage` (`lumeo:consent:v1`), exposes `HasConsent(string)` for gating third-party scripts, and fires `OnChange` / `OnRequestOpenPreferences` events so a "Manage cookies" link anywhere in the layout can reopen the banner without CascadingValue plumbing.
-   `<ConsentBanner>` — slide-in banner with Accept / Reject / Customize. The preferences dialog has per-category toggles; "necessary" is always locked on. Strings are individually overridable for i18n.
-   Registered in `AddLumeo()` as Scoped — zero extra wiring.

### Docs site

-   Migrated from GitHub Pages to Cloudflare Pages — per-path `Cache-Control` (fingerprinted `_framework/*.wasm` now `immutable` for a year), HTTP/3, Brotli at edge, no env-protection friction.
-   `sitemap.xml` auto-generated from every `@page` directive (190 URLs) + `robots.txt` so Google can index all component / block / pattern pages.
-   Issue + PR templates, SECURITY policy, Code of Conduct, FUNDING (Sponsors button).
-   New `/privacy` page with live consent-management controls.
-   Open Graph + Twitter Card meta tags on `index.html` for proper link previews on Discord / LinkedIn / Slack / X.

v2.0.0-rc.10

April 2026

Polish pass across ~25 components and every block page — trigger-icon state reflection, cleaner overlay arrows, rewritten Checkbox glyph, DataGrid fullscreen layout, Combobox/Command empty-state gating, and a systematic border-softening sweep.

### Added

-   `ShowArrow` parameter on `PopoverContent`, `DropdownMenuContent`, and `HoverCardContent` — rotated-square arrow with matching border on outward-facing sides.
-   `data-state="open|closed"` + `group` class on `DropdownMenuTrigger` so consumer chevrons can flip with `group-data-[state=open]:rotate-180`.
-   Toast slide-out animation (`animate-toast-out`) — dismiss now slides + collapses instead of popping.
-   15 new Lucide icon mappings in `DynamicIcon` (`Wrench`, `BookOpen`, `Component`, `Puzzle`, `Cog`, `Server`, `Database`, `Wand`, `PanelLeft`, et al.) + every search-palette category now has a real icon instead of a Circle fallback.
-   Chevron rotation on open for `SelectTrigger`, `Cascader`, and `ColorPicker` (matching existing Accordion/NavigationMenu/TreeSelect behavior).
-   Demos: "With Arrow" added to Popover, DropdownMenu, and HoverCard doc pages.

### Fixed

-   **Sparkles** clustered at top-left when consumer passed `Class="absolute inset-0"` — root cause was Tailwind v4's `@layer utilities` losing to unlayered CSS. Component now drops the `.lumeo-sparkles` class entirely when the consumer supplies positioning.
-   **Checkbox** rewritten — crisp inline-SVG check + minus with rounded stroke caps (no more Lucide jagginess), unchecked state now visible (was zero-sized due to arbitrary Tailwind classes not being safelisted), hover state, smooth color transition.
-   **Toast** auto-dismiss missed `StateHasChanged` so toasts stuck on screen.
-   **Rating** half-star was shifted vertically — reworked as two stacked SVGs in a single grid cell with `clip-path`, pixel-perfect alignment.
-   **Progress** indeterminate sweep: retuned keyframe so exit and opacity fade align — no more "snap off" at the right edge.
-   **Resizable** and **Splitter** vertical mode: swapped `flex-basis: X%` → `flex: X 1 0` so vertical works without requiring an explicit parent height.
-   **Bento** tiles overlapping — added `grid-auto-rows: minmax(0, 1fr)` and `min-w-0 min-h-0` on tiles.
-   **ImageCompare** rewritten with a transparent `<input type="range">` for drag + `clip-path` for reveal (browser handles drag math, tracks the cursor exactly).
-   **Combobox** + **Command** empty states rendered unconditionally — now gate on registered item count; items track their visibility so filtered-out items un-register.
-   **Tour** spotlight now reads the target's computed `border-radius` via JS interop and matches it.
-   **DataGrid fullscreen**: removed duplicate exit control (modal X was redundant with toolbar minimize), grid fills modal height, pagination sticks to bottom; `Context.IsExpanded` now rebroadcasts to toolbar on toggle so the Maximize/Minimize icon swaps correctly.
-   **Stack**/**Flex** `Gap` values like `14`, `16`, `20` had no effect — Tailwind's scanner can't see runtime-interpolated class names. Added full spacing-scale safelist to the utilities bundle.
-   Block previews (SignIn/SignUp/ResetPassword/OtpVerify) had a floating card halo from `min-h-[640px]` — replaced with tight `p-8`, and CardContent bumped to `pt-10` so the hero icon has breathing room.
-   Alert/Badge/Command/Kbd/EmptyState/Popover/HoverCard/Toast borders softened to `border-border/40` or `/60` across ~60 doc pages.
-   Circle-fallback icons in the Ctrl+K command palette (`Wrench` etc. were missing from DynamicIcon's map).
-   Kanban pattern "+2" overflow pill sized to match `Avatar.Sm`.
-   Double-icon bugs on Alert demos (auto-icon + inline DynamicIcon) on AlertPage and KeyboardShortcutsPage.

v2.0.0-rc.9

April 2026

Landing page redesign, marquee swag, comparison table rewrite, and aggressive-border audit across 228 API reference tables.

### Improved

-   Home marquee rewritten as two rows in opposing directions with icon pills (card surface + primary-tinted) and edge-gradient fades.
-   Landing comparison table fact-checked against current GitHub/NuGet state — corrected MudBlazor templates, Radzen AI + MCP, Ant Design Blazor package size.
-   Customizer "Share" button collapsed to a single client-side preset code action (removed the duplicate server-code row).
-   Softer borders across 228 API reference table headers + ~60 demo wrappers.

v2.0.0-rc.8

April 2026

Patterns page expansion (32 categories, ~70 live inline variants), theme customizer expansion with Vega/Nova/Maia/Lyra/Mira presets, Violet/Amber/Teal color themes.

### Added

-   Theme customizer: Font selector (6 fonts), Icon Library (6 options, Lucide default), Menu Color, Menu Accent.
-   Color themes: Violet, Amber, Teal (total 8 themes).
-   Preset renames: Vega, Nova, Maia, Lyra, Mira.
-   Patterns page: 32 categories with ~70 live inline variants across Accordion, Alert, Avatar, Badge, Button, Card, Checkbox, Dialog, Input, Select, Switch, Tabs, Table, Toast, Progress, Separator, Skeleton, Popover, Tooltip, Sheet, DropdownMenu, Combobox, Breadcrumb, Pagination, RadioGroup, Spinner, EmptyState, Slider, Toggle, ToggleGroup, Kbd, OtpInput.
-   ChartPatternDemos shared component with 8 chart patterns.

### Fixed

-   Customizer BaseColor and Style options were purely visual — now apply real CSS changes.
-   Heavy borders on Switch, ThemeSwitcher, FileUpload, Checkbox, RadioGroup, OtpInput, Combobox, MainLayout search modal.

v2.0.0-rc.7

April 2026

Full shadcn-CLI parity pass. New `apply` / `view` / `info` commands, `--only` filter on apply, `--all / --diff / --view` flags on add, and server-stored preset IDs via a Cloudflare Worker at `api.lumeo.nativ.sh` — so shareable codes can hold arbitrary configs (not just the 26-bit bitfield).

### Added

-   `lumeo apply [preset]` — flat top-level command (matches `shadcn apply`). Writes the theme section into `lumeo.json` (with `lumeo.json.bak` backup) and `wwwroot/lumeo-theme.json` which `theme.js` reads on init for no-FOUC first paint.
-   `--only theme,font,icons,radius,menu,style,baseColor,dark` filter on `apply` to restrict which parts get rewritten.
-   `lumeo view <component>` — prints component source to stdout without writing, for preview.
-   `lumeo info [--json]` — dumps project config + installed components + theme.
-   `lumeo add --all` to install every component; `--diff` and `--view` flags for preview-only runs.
-   Server-stored preset IDs: when a preset code can't be decoded client-side, the CLI fetches it from `https://api.lumeo.nativ.sh/preset/<id>` — a Cloudflare Worker backed by KV. IDs are content-addressed SHA-256 of the canonical JSON, so the same config always returns the same 6-char code.
-   Customizer sidebar **Share as link** button — POSTs the live config to the Worker and puts `lumeo apply --preset <id>` on the clipboard. Useful for custom brand palettes that don't fit the bitfield codec.

### Deprecated

-   `lumeo theme apply` — still works but prints a deprecation notice. Use `lumeo apply` instead.

v2.0.0-rc.6

April 2026

Default registry URL now points at jsDelivr's GitHub CDN, so the CLI works out of the box without any self-hosted registry. Enables `lumeo init` / `lumeo add` on fresh projects immediately after `dotnet tool install`.

### Fixed

-   Default registry URL `lumeo.nativ.sh` wasn't live, so fresh installs of the CLI failed with a 404 on `lumeo add <component>`. Now defaults to `cdn.jsdelivr.net/gh/Brain2k-0005/Lumeo@v2.0.0-rc.6/src/Lumeo/wwwroot/registry/registry.json` — pinned to the release tag so schema stays consistent.
-   File-fetch URL derivation now recognizes three patterns: (1) jsDelivr / raw.githubusercontent.com layouts where the registry lives under `.../wwwroot/registry/registry.json`, (2) legacy self-hosted `/registry.json` → `/raw/`, (3) bare base URLs.
-   GitHub Pages deploy workflow now also triggers on `v2.0-dev` branch and copies the registry + source files under the published site's `/registry/` + `/raw/` paths.

v2.0.0-rc.5

April 2026

Shareable theme presets — customize on `/themes`, copy a 6-character code, share or apply via CLI. No hosted backend.

### Added

-   `LumeoPresetCodec` — encodes theme/style/base color/radius/font/icons/menu color/menu accent/dark into a 26-bit bitfield, base62-encoded to 6 chars. Versioned schema so future option additions reject old codes cleanly.
-   `LumeoPresetOptions` — single source of truth for option arrays (indexes are the stored values — append-only).
-   **/themes customizer:** live 6-char preset code with copy button — puts `lumeo theme apply --preset <code>` on the clipboard.
-   **CLI:** new `lumeo theme apply --preset <code>` subcommand. Decodes the code and prints the resolved configuration + a ready-to-paste JS snippet that drives the runtime theme-switcher. `--dry-run` flag.

### Why no backend?

-   The preset IS the data — 26 bits packed into 6 base62 chars — no hosted KV store to manage.
-   Codes work offline, can be pasted into docs / issues / PRs, and never expire.
-   Shorter than shadcn's 9-character IDs (which require their API).

v2.0.0-rc.4

April 2026

DataGrid toolbar composability, smoother column resize, docs sidebar UX. Polish over rc.3.

### Added

-   `<ToolbarContent>` is now a component with a `Class` attribute for custom wrapper styling
-   Five built-in toolbar tools as separate composable components: `DataGridToolbarFullscreen`, `DataGridToolbarCopySelected`, `DataGridToolbarColumns`, `DataGridToolbarExport`, `DataGridToolbarLayouts`
-   `DataGridToolbarContext<TItem>` cascading context — tool components pick up state with no props
-   Docs sidebar: active NavLink highlight + auto-scroll active item to centered viewport on direct URL loads / navigation + auto-expand Charts subtree on /components/charts/\*

### Improved

-   DataGrid column resize: JS drives the drag entirely in the DOM (direct style writes on header + body cells) and commits ONCE on mouseup — no more Blazor round-trip per pixel
-   Consumer-provided `<ToolbarContent>` suppresses the default tool stack to avoid duplicate icons
-   Softened aggressive `border-b` on 228 API reference table headers and in Accordion / Command / DataTable / Table / Sidebar components to `border-border/40`

### Fixed

-   Infinite re-render loop when `<ToolbarContent>` re-registered on every parameter set
-   Duplicate toolbar icons when composing built-in tools inside `<ToolbarContent>`

v2.0.0-rc.3

April 2026

Shape-aware chart loading skeletons + per-chart Loading demos across all 30 chart doc pages.

### Added

-   `ChartSkeleton` with shape variants (Bars, Line, Area, Pie, Scatter, Grid, Generic) — reserved plot-area geometry so the real chart swaps in without layout jump
-   `IsLoading` / `ShowLoadingSkeleton` / `SkeletonKind` parameters on every chart wrapper
-   Loading-state demo on every chart doc page — Simulate button + Hold-skeleton switch

### Improved

-   Chart skeleton animations per kind: bar-grow, multi-line stroke-draw, flat pie rotation, scatter breath, grid pulse
-   350ms cross-fade handoff between skeleton and real chart
-   Axis / legend hint rects reserve real-chart space so there's no layout shift

v2.0.0-rc.2

April 2026

CSS bundle fix + portal theme-token inheritance. Foundational stability patches over rc.1.

### Fixed

-   Pre-compiled `lumeo-utilities.css` was missing theme-token classes (`bg-background`, `bg-popover`, `text-muted-foreground`, etc.) that consumers needed — added `@source inline()` safelists
-   Theme auto-applies `bg-background text-foreground` to `<body>` on init — portal components (Dialog / Sheet / Drawer / Toast / Popover / Tooltip) now inherit theme tokens when they render outside the theme context
-   BarChart `LabelStrategy` enum (Smart / ShowAll / Auto) replaces the old boolean — auto-rotates category labels at 11 / 17 / 25 densities without flooding dense charts
-   Stacked bar chart border radius regression — stacked segments now correctly round only the outermost edge

v2.0.0-rc.1

April 2026

Lumeo 2.0 is a mega-release: AI chat primitives, motion primitives, Scheduler, Gantt, RichTextEditor, 14 locales + RTL, Bento / dashboard tiles, a `[LumeoForm]` source generator, shadcn-style CLI vendoring, `dotnet new` templates, and an MCP server for LLM codegen. 128 components, 1,687 tests at rc.1 (current rc.17: 131 components across 7 packages).

### Added — Components

-   **AI primitives**: `PromptInput`, `StreamingText`, `AgentMessageList` + `AgentMessage`, `ToolCallCard`, `ReasoningDisplay` — SignalR-native token streaming with sticky auto-scroll and collapsible chain-of-thought
-   **Motion primitives**: `Marquee`, `NumberTicker`, `TextReveal`, `BlurFade`, `BorderBeam`, `ShimmerButton`, `Sparkles`
-   **Dashboard tiles**: `Bento` + `BentoTile`, `KpiCard`, `SparkCard`, `Delta`, `Sparkline` (standalone SVG primitive)
-   **Navigation / layout**: `BottomNav` (safe-area, optional FAB), `Splitter` / `SplitterPane` / `SplitterDivider`, `PickList<T>`
-   **Enterprise**: `Scheduler` (FullCalendar v6 — Month/Week/Day/List, drag-to-create/reschedule), `Gantt` (Frappe Gantt — Day/Week/Month/Year zoom, drag progress), `RichTextEditor` (TipTap v2 — Full/Basic/None toolbars, two-way HTML binding)
-   **Blocks**: 8 copy-paste page templates — `/blocks/sign-in`, `/sign-up`, `/reset-password`, `/otp-verify`, `/pricing`, `/hero`, `/dashboard-block`, `/settings-page`

### Added — Services & tooling

-   `IDataGridExportService` — real **.xlsx** export via ClosedXML, PDF via QuestPDF, CSV, with browser download helper and `ExportFormats` flags
-   14 built-in locales via `ILumeoLocalizer`: EN, DE, ES, FR, IT, PT, NL, PL, JA, ZH-CN, KO, AR, RU, TR
-   RTL layout via `IThemeService.SetDirectionAsync(LayoutDirection)` — persisted, applied before first paint, with RTL-aware keyframes
-   `Lumeo.Cli` — shadcn-style CLI (`dotnet tool install -g Lumeo.Cli`). Vendorize components into your repo: `lumeo init / add / list / diff`
-   `registry.json` — machine-readable catalog of 127 components (files, dependencies, CSS variables)
-   `@lumeo-ui/mcp-server` — MCP server exposing curated component schemas so Claude / ChatGPT / Copilot / Cursor author correct Lumeo markup
-   `Lumeo.Templates` — `dotnet new lumeo-page / lumeo-form / lumeo-component` scaffolders

### Added — Developer experience

-   `[LumeoForm]` Roslyn source generator — annotate a POCO and get a compile-time `RenderForm(model, onSubmit)` that emits a fully-bound Lumeo Form with validation. Handles string / int / decimal / bool / DateTime / enum / email / password via `[DataType]` + `[Required]` + `[Display]`
-   Opt-in `Animated` / `AnimatedIndicator` props on Steps, Timeline, Progress, Tabs, Switch, Checkbox, Badge, BottomNav — off by default, zero overhead when unused
-   `PressEffect` enum (Scale / Brightness / Ripple) on Button, ShimmerButton, Card, BottomNavItem, ToggleGroupItem, Chip
-   248 new bUnit tests for 2.0 components — **1,687 total**. 138 missing API rows filled in across ~45 component doc pages. Scrollable `OnThisPage` aside on every docs page. Landing rewrite, `/docs/registry` authoring guide, and `/docs/culture` page
-   Interop: `motion.*` (RAF + IntersectionObserver), `ai.*` (autosize + sticky-scroll MutationObserver), lazy-loaded `rich-text-editor.js` / `scheduler.js` / `gantt.js` ESM modules, `DownloadFileAsync` on `IComponentInteropService`, Splitter pointer-capture helpers

### Improved

-   **DataGrid**: inset fullscreen modal with open animation, header drag-to-reorder, layout JSON round-trip (`ExportLayout()` / `ApplyLayoutJsonAsync()`), toolbar toggles (`ShowSearch` / `ShowColumnChooser` / `ShowExport`), `Culture` parameter, `SetHtmlClass` for navbar hiding in fullscreen
-   UX audit: `cursor-pointer` + `focus-visible` rings on every interactive component
-   `Culture` parameter cascades through DatePicker, DateTimePicker, NumberInput, Slider, Statistic — falls back to `CultureInfo.CurrentCulture`
-   Motion demos: interactive Steps/Timeline, proper Tabs indicator per variant, testable BottomNav, single-connector animation (no flicker on reverse)

### Fixed

-   DataGrid: duplicate column registration race, header-drag edge cases, fullscreen z-index now above nav, grid fills overlay width
-   BarChart: every category label rendered by default (`LabelStrategy.Smart`) with auto-rotation at higher densities (-60°, -75°)
-   Landing: quickstart terminal cards, CTA box + Star button contrast, visible gaps, removed stray separators
-   QuestPDF WASM crash on `DataGridExport` docs page (button disabled under WASM)
-   Tailwind arbitrary-class bugs and docs spacing polish across 2.0 component pages

### Breaking changes

-   **Icon / Label RenderFragment slots removed** from Alert, Badge, EmptyState, Rating, Result, Segmented, SidebarMenuButton, StepsItem, TabsTrigger, TimelineItem. Rename `<Icon>…</Icon>` → `<IconContent>…</IconContent>` and `<Label>…</Label>` → `<LabelContent>…</LabelContent>`. Deprecated in 1.6.0.
-   **DataGrid Excel export is a real `.xlsx`** now (ClosedXML), not a CSV renamed to .xlsx. Transparent for normal users; remove any workaround that routed the "excel" case to your own handler.
-   **BarChart `LabelStrategy` defaults to `Smart`**, showing every category label and auto-rotating at higher densities. Restore the previous behaviour with `LabelStrategy="ChartLabelStrategy.Auto"`.
-   **Culture defaults to `CultureInfo.CurrentCulture`** on date / number components. Pass `Culture="@CultureInfo.InvariantCulture"` to keep invariant formatting.

### Migration

See [MIGRATION.md](https://github.com/Brain2k-005/Lumeo/blob/master/MIGRATION.md) at the repo root for before/after snippets and migration recipes for every breaking change, plus install commands for the new `Lumeo.Cli`, `Lumeo.Templates`, and `@lumeo-ui/mcp-server` companion packages.

v1.6.0

April 2026

### Added

-   `IconContent` / `LabelContent` slots on Alert, Badge, EmptyState, Rating, Result, Segmented, SidebarMenuButton, StepsItem, TabsTrigger, TimelineItem — replace the previous `Icon` / `Label` slots that collided with the `<Icon>` and `<Label>` components
-   Design philosophy section in Introduction docs explaining the unprefixed naming choice and the `<Name>Content` convention

### Deprecated

-   Old `Icon` / `Label` slot parameters remain as `[Obsolete]` aliases — existing code compiles with a warning; aliases are removed in 2.0

v1.5.1

April 2026

### Added

-   `<Icon>` component — Lumeo-native wrapper around Blazicons with `Name`, `Svg`, and `Size` (Xs, Sm, Md, Lg, Xl) parameters
-   Icon finder docs page — search + library switcher across Lucide, Bootstrap, Heroicons, Feather, Octicons, Material, Fluent; reflection-based catalog covering all ~1,700 Lucide icons

v1.5.0

April 2026

### Added

-   Service interfaces — `IToastService`, `IOverlayService`, `IThemeService`, `IKeyboardShortcutService`, `IComponentInteropService` — for mockability in consumer tests
-   DataGrid sticky header across scrolling viewport
-   DatePicker support for `DateTime` binding alongside `DateOnly`

### Improved

-   DialogFooter button spacing, alignment, and responsive stacking polished
-   DataGrid DX: cleaner row API, simplified column definitions, better defaults

v1.4.1

April 2026

### Fixed

-   Stacked bar chart: outer corners stayed sharp when theme had rounded corners — now uses per-segment `borderRadius` arrays so the theme's radius actually applies
-   Dialog zoom-in animation transform leaked with `fill-mode: both` — keyframe end state switched to `transform: none`
-   DataGrid column race where the grid rendered empty until the first interaction — fixed with `InvokeAsync(StateHasChanged)` in `AddColumnDef`
-   Charts not repainting on theme change — JS dispatches `lumeo:theme-changed`; ECharts interop listens and rerenders

v1.4.0

April 2026

### Added

-   Rounded outer corners on stacked bar charts (top segment top-rounded, bottom segment bottom-rounded)
-   Charts now rerender automatically on theme change — no page refresh needed

v1.3.1

April 2026

### Fixed

-   nupkg leaked `package.json` / `package-lock.json` and caused `NETSDK1152` publish conflicts in consumer apps — moved npm build to repo root and excluded `Styles/` from the package

v1.3.0

April 2026

### Added

-   Pre-compiled `lumeo-utilities.css` ships in the package — zero-config Tailwind for consumers; no local Tailwind build required
-   Consumers who want Tailwind in their own markup can keep their own v4 build and drop `lumeo-utilities.css` — their build picks up every utility Lumeo needs

v1.2.0

April 2026

### Added

-   Built-in EN/DE localization via `ILumeoLocalizer` — driven by `CultureInfo.CurrentUICulture` with exact → neutral → English fallback
-   Override or extend locales during `AddLumeo(opts => opts.Add(...))`
-   DataGrid, Pagination, DatePicker, and other component default strings now translatable

### Fixed

-   Stacked bar chart rendering on dark theme

v1.1.2

March 2026

### Fixed

-   PasswordInput browser-autofill yellow highlight bled past the input's rounded corners — now clipped to the input's radius

v1.1.1

March 2026

### Fixed

-   DataGrid pagination test assertion updated to match the new footer wording

v1.1.0

March 2026

### Added

-   ColorPicker SV + Hue picker surface (replaces the earlier swatch-only design)
-   Blocks polish pass — cleaner layouts across Authentication, Analytics, Calendar, Chat, Dashboard, E-Commerce, FileManager, Kanban, Settings, TaskTracker and more

### Fixed

-   Overlay positioning inside ancestors with `transform` / `filter` (these create a containing block that breaks `position: fixed`)

v1.0.2

March 2026

### Fixed

-   Textarea `@bind-Value` two-way binding
-   TreeSelect cleanup on dispose
-   Tooltip disposal race on rapid mount/unmount
-   DataGrid pagination alignment and UX polish

v1.0.1

March 2026

### Added

-   DataGrid `GroupsExpandedByDefault` parameter

### Fixed

-   7 reported bugs — Input two-way binding, DataGrid skeleton, sticky header, and grouping defaults
-   DataGrid pagination layout — info left, page controls right

v1.0.0

March 2026

### Added

-   First stable release — 103 components, 8 themes, 1,316 tests
-   CI workflow publishing to NuGet on GitHub Release
-   Chart error-state visibility, autosave safety guards, `DelayedDispatch` for timer-based components

### Improved

-   1.0 hardening — error visibility across async paths, shortcut handles simplified to `IAsyncDisposable`, toolbar errors routed to a single sink
-   All dependencies updated to latest

v1.0.0-beta.4

March 2026

### Added

-   Checkbox: Label and Description parameters with auto-Id for form label association
-   RadioGroupItem: Description text support for helper text below radio options
-   Steps: Error state per step with red X icon, custom Icon slot for any step indicator
-   Popover: Arrow support (ShowArrow parameter) matching Tooltip arrow pattern
-   48 new unit tests covering all upgraded component features (1,124 total tests)
-   Form Validation guide — DataAnnotations, custom validation, complete registration form example
-   Contributing guide — setup, component creation conventions, testing, code style
-   "When to Use" and "Related Components" sections on 62 more component pages (82 total)
-   API reference tables now complete on all 136 component documentation pages

### Improved

-   Home page stats corrected (75→103 components, 7→8 themes)
-   Chart patterns integrated into Patterns page with filter category
-   All hardcoded colors replaced with CSS variables (Avatar, Statistic, Result, KanbanCard)

### Fixed

-   MentionPage Razor escape for @user syntax
-   Statistic and Result test assertions updated for new CSS variable colors

v1.0.0-beta.5

March 2026

### Improved

-   Updated NuGet package description (90→103 components, added test count and features)
-   Updated README with accurate stats, all component categories, and install command

v1.0.0-beta.3

March 2026

### Added

-   Dialog size variants (Sm, Default, Lg, Xl, Full) and Scrollable content mode
-   Drawer multi-position support (Top, Right, Bottom, Left) with direction-aware swipe
-   Alert: Title, Description, Icon slots, ShowIcon with default icons per variant, AutoDismiss timer
-   Input: 3 size variants (Sm, Default, Lg) and Clearable mode with X button
-   Tooltip arrow support with configurable Offset and fade animation
-   Badge: Pulse ping animation on dot variant and Icon slot
-   Accordion: DefaultValues for initially open items and Disabled items
-   Skeleton: Wave/Shimmer animation variant alongside existing Pulse
-   Spinner: Dots and Bars variants, Label text, and Color override
-   HoverCard: Side parameter (Top/Bottom positioning)
-   Tabs: Disabled tabs with aria-disabled and TrailingContent on TabsList
-   Button: FullWidth mode, LeftIcon and RightIcon slots
-   Progress: Circular SVG variant with ShowValue and configurable StrokeWidth
-   Avatar: Square shape option and Status indicator (Online, Offline, Away, Busy)
-   Switch: Loading spinner state and OnLabel/OffLabel text
-   Select: Disabled items and Placeholder text on trigger
-   Combobox: EmptyText for no-results state and Creatable mode
-   NumberInput: Arrow key and mouse wheel support, Prefix/Suffix text
-   Textarea: Character count display, MaxLength indicator, Resize control
-   New Accessibility guide page with ARIA roles, keyboard patterns, and focus management docs
-   New Changelog page with full release history
-   API reference tables for 30 additional component documentation pages (55 total)
-   "When to Use", "Keyboard Interactions", and "Related Components" sections on 20 component pages

### Improved

-   Animation keyframes and utility classes now ship in lumeo.css for NuGet consumers
-   Production-quality spring easing curves (`cubic-bezier(0.16, 1, 0.3, 1)`) on all animations
-   Rating colors now use themeable `--color-rating` CSS variable instead of hardcoded yellow
-   Accessibility and Changelog pages added to sidebar navigation

### Fixed

-   Broken animations for NuGet package consumers (keyframes were only in docs site)
-   Missing `animate-toast-in` — Toast slide-in animation was never defined
-   Added aria-labels to PasswordInput toggle, TagInput close buttons, DatePicker clear button, and Carousel navigation
-   Rating keyboard navigation with Arrow keys and improved star labels
-   5 failing tests updated for new Spinner, Avatar, and Select component structures

v1.0.0-beta.2

March 2026

### Added

-   14 new components: Cascader, Color Picker, Date Range Picker, Date Time Picker, Filter, Image Compare, Inplace Editor, Input Mask, Kanban, Mega Menu, Mention, Number Input, Password Input, Sortable List
-   DataGrid enhancements: column menu, inline editing, column filtering, and toolbar improvements
-   Keyboard shortcuts: `R` to shuffle themes, `Ctrl+D` for dark mode, `Ctrl+/` for shortcuts help
-   Redesigned WASM loader with animated splash screen, brand name, and ripple animation
-   Floating navbar and floating sidebar design for the docs site
-   NuGet package icon (Lumeo logo)

### Improved

-   All UI corners now respect the CSS radius variable, enabling zero-radius presets like Lyra
-   Customizer sidebar moved to header button with `Ctrl+B` toggle shortcut
-   Replaced raw HTML elements with Lumeo components across 113 doc files
-   Converted raw HTML to Lumeo components in 7 pattern files
-   QR Code live preview, theme persistence, and search palette enhancements
-   CommandEmpty now always renders regardless of Command context

### Fixed

-   Customizer radius bug where radius values did not apply correctly
-   Mobile docs improvements and API table horizontal scrolling
-   Floating nav sticky positioning (moved animation off root element)
-   Splash screen CSS compatibility with Tailwind CDN
-   Em dash encoding issues in page titles
-   FormWizardPattern closing tag mismatch
-   Link/a tag mismatches in LinkPage and Home
-   UTF-8 BOM in Home.razor

v1.0.0-beta.1

February 2026

### Added

-   API reference tables for 25 component documentation pages
-   Programmatic OverlayService for opening dialogs, sheets, and drawers from code
-   Kbd component and KeyboardShortcutService for global keyboard shortcuts
-   Scrollspy component for tracking scroll position and highlighting nav items
-   926 bUnit tests across 50+ components and 4 services (expanded from 240)
-   CI workflow to run tests automatically on push and PR
-   Toast position support (top-left, top-right, bottom-left, bottom-right, etc.)
-   19 new patterns on the Patterns page including drag-and-drop Kanban board
-   Live world map demo for GeoMapChart
-   Live interactive demos for all 5 service documentation pages
-   New components: blocks section, filter docs, and comprehensive UI improvements
-   Custom scrollbar styling

### Improved

-   Redesigned Themes customizer sidebar to match reui.io design
-   Redesigned Themes and Patterns pages with new layout
-   Replaced inline accordion sections with flyout popover menus in the customizer
-   Default theme changed from Orange to Zinc to match Lumeo logo
-   Softened chunky borders across overlay components
-   Docs favicon updated to dark Lumeo icon SVG
-   All services registered via single `AddLumeo()` call

### Fixed

-   OtpInput `eval()` XSS vulnerability patched; added IAsyncDisposable
-   9 failing tests for Calendar, OtpInput, and FileUpload
-   Chart rendering: dropped source-gen serializer, resolved CSS variable colors
-   Chart serialization and WordCloud rendering errors
-   EChartCalendar range conflict and chart error handling
-   Z-index issues for overlay components, theme loading, and toast variants
-   Hanging ThemeServiceTests and stale Dialog/AlertDialog assertions
-   Duplicate ondragover attributes in KanbanPattern
-   Patterns page layout and broken CSS opacity modifiers
-   GitHub Pages deployment issues with Tailwind v4 CDN and .wasm 503 errors

v0.1.0

January 2026

### Added

-   Initial release with 45+ shadcn-inspired Blazor components
-   Full docs site with component pages, live demos, and code snippets
-   15 chart types powered by ECharts (Bar, Line, Area, Pie, Donut, Radar, Gauge, Treemap, Sunburst, Heatmap, Sankey, Funnel, and more)
-   Patterns gallery page with reusable UI pattern examples
-   Theme customizer with multiple color schemes and dark mode support
-   10 additional chart types: Scatter, Candlestick, Box Plot, Word Cloud, Geo Map, Calendar Heatmap, Theme River, Graph, Parallel, Radial
-   9 full-page pattern demos
-   Layout primitives: Stack, Flex, Grid, Container, Center, Spacer
-   Typography components: Heading, Text, Code, Link
-   Form components: Button, Checkbox, Combobox, Date Picker, File Upload, Form, Input, Label, OTP Input, Radio Group, Select, Slider, Switch, Textarea, Toggle, Toggle Group
-   Overlay components: Alert Dialog, Command, Context Menu, Dialog, Drawer, Dropdown Menu, Hover Card, Popover, Sheet, Tooltip
-   Navigation components: Breadcrumb, Menubar, Navigation Menu, Pagination, Sidebar, Steps
-   Data Display components: Avatar, Data Table, Table, Rating, Statistic, Timeline
-   Feedback components: Alert, Badge, Empty State, Progress, Skeleton, Spinner, Toast
-   ToastService, ThemeService, and ComponentInteropService
-   GitHub Pages deployment pipeline
