@ethlete/core 5.0.0-next.7 → 5.0.0-next.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +849 -0
  2. package/README.md +28 -4
  3. package/design/interactive-styles.ts +5 -0
  4. package/design/theme-css.js +392 -0
  5. package/design/theme-css.ts +547 -0
  6. package/fesm2022/ethlete-core.mjs +9357 -5667
  7. package/fesm2022/ethlete-core.mjs.map +1 -1
  8. package/generators/devtools-about/generator.js +122 -0
  9. package/generators/devtools-about/schema.json +25 -0
  10. package/generators/generators.json +41 -5
  11. package/generators/migrate-color-theme-variants/color-theme-variants.js +136 -0
  12. package/generators/migrate-color-theme-variants/migration.js +46 -0
  13. package/generators/migrate-color-theme-variants/schema.json +26 -0
  14. package/generators/migrate-create-destroy/create-destroy.js +317 -0
  15. package/generators/migrate-create-destroy/migration.js +46 -0
  16. package/generators/migrate-create-destroy/schema.json +26 -0
  17. package/generators/migrate-legacy-color-themes/legacy-color-themes.js +123 -0
  18. package/generators/migrate-legacy-color-themes/migration.js +93 -0
  19. package/generators/migrate-legacy-color-themes/schema.json +26 -0
  20. package/generators/migrate-provider-shape/migration-scope.js +35 -0
  21. package/generators/migrate-provider-shape/migration.js +50 -0
  22. package/generators/migrate-provider-shape/provider-shape.js +284 -0
  23. package/generators/migrate-provider-shape/schema.json +26 -0
  24. package/generators/migrate-surface-interaction-swatch/interaction-swatch.js +63 -0
  25. package/generators/migrate-surface-interaction-swatch/migration.js +36 -0
  26. package/generators/migrate-surface-interaction-swatch/schema.json +26 -0
  27. package/generators/migrate-to-v5/apply-replacements.js +14 -0
  28. package/generators/migrate-to-v5/color-naming.js +124 -0
  29. package/generators/migrate-to-v5/create-provider.js +67 -55
  30. package/generators/migrate-to-v5/migration-files.js +13 -0
  31. package/generators/migrate-to-v5/migration.js +33 -19
  32. package/generators/migrate-to-v5/removed-exports.js +161 -0
  33. package/generators/migrate-to-v5/router-state-service.js +125 -330
  34. package/generators/migrate-to-v5/schema.json +22 -0
  35. package/generators/migrate-to-v5/service-classes.js +108 -0
  36. package/generators/migrate-to-v5/sync-observable-consumers.js +80 -0
  37. package/generators/migrate-to-v5/viewport-service.js +226 -491
  38. package/generators/tailwind-4-color-theme/generator.js +411 -0
  39. package/generators/tailwind-4-color-theme/schema.json +44 -0
  40. package/generators/tailwind-4-surface-theme/generator.js +379 -0
  41. package/generators/tailwind-4-surface-theme/schema.json +48 -0
  42. package/migrations/legacy-color-themes.md +38 -0
  43. package/migrations/seo-directive-removed.md +81 -0
  44. package/migrations/surface-theme-regenerate.md +20 -0
  45. package/migrations.json +59 -0
  46. package/package.json +38 -21
  47. package/src/lib/animations/easing-tokens-styles.component.css +155 -0
  48. package/src/lib/providers/visually-hidden-styles.component.css +13 -0
  49. package/src/lib/resize-handles/resize-handles.component.css +137 -0
  50. package/src/lib/theming/color-interactive-styles.component.css +147 -0
  51. package/src/lib/theming/surface-interactive-styles.component.css +42 -0
  52. package/types/ethlete-core.d.ts +3842 -2205
  53. package/generators/tailwind-4-theme/generator.js +0 -514
  54. package/generators/tailwind-4-theme/schema.json +0 -32
package/CHANGELOG.md CHANGED
@@ -1,5 +1,854 @@
1
1
  # @ethlete/core
2
2
 
3
+ ## 5.0.0-next.71
4
+
5
+ ### Patch Changes
6
+
7
+ - Overlay runtime: while the overlay enters, a backdrop click closes it; the second click of a double-click does not, so a double-click on the trigger no longer opens and closes it at once.
8
+
9
+ ## 5.0.0-next.70
10
+
11
+ ### Patch Changes
12
+
13
+ - The `migrate-to-v5` codemod now reports each `toSignal(…, { requireSync: true })`, `take(1)`, `first()` or `withLatestFrom` that reads an observable it rewrote to `toObservable()`, because that observable no longer emits synchronously.
14
+ - The `surface-interaction-swatch` migration declares that it needs `ts-morph`, so `et update` installs it first. The `@nx/devkit` peer range is now `>=23.0.0`, matching the Nx floor of the migration guide.
15
+ - Overlay runtime: Escape now closes an overlay during its enter transition instead of being dropped; outside-pointer closes stay ignored until the transition starts.
16
+
17
+ ## 5.0.0-next.69
18
+
19
+ ### Patch Changes
20
+
21
+ - Update all dependencies to their latest versions (Nx 24, Vitest 5, jsdom 30, ts-morph 28, @types/node 26 and others). The optional `@nx/devkit` peer dependency now requires `^24.0.0`, and the optional `ts-morph` peer of `@ethlete/core` requires `^28.0.0`.
22
+ - Update dependencies (Angular 22.2, Nx 23.3, Vitest 4.1.12 and others) and keep the `max-params` lint exceptions in the bracket layout types on the line ESLint 10.13 reports.
23
+
24
+ ## 5.0.0-next.68
25
+
26
+ ### Minor Changes
27
+
28
+ - Add `attributes` and `movingClass` options to `injectAnimatedListItems`: watch items a filter hides, and clip overflow while items move.
29
+ - Add `injectAnimatedListItems`: items of a list that stay slide to their new place, new items fade in, and removed items fade out where they were.
30
+ - `injectAnimatedListItems` takes an `animateChange` callback; returning `false` measures a change without moving or fading items.
31
+
32
+ ### Patch Changes
33
+
34
+ - Place anchored overlays on whole device pixels, so their content no longer shifts by a pixel when an animation ends.
35
+ - Round a shifted anchored overlay inward, so snapping to device pixels no longer pushes it past the viewport padding.
36
+ - The fade-out copy in `injectAnimatedListItems` keeps the padding, border, colour and text styles its item had from ancestor selectors.
37
+ - `createCanAnimateSignal` cancels its pending frame when its host is destroyed, and `matchesReducedMotion` returns `false` in an environment without `matchMedia` instead of throwing.
38
+ - `injectAnimatedListItems` fades a new item in only after the removed items have faded out, so a select's "No results" or loading row cross-fades with the options instead of overlapping them.
39
+ - `registerScrollRestorationState` now restores a page that registers after the navigation ended, such as a route component behind a nested `<router-outlet>`, on reload and back/forward navigation. The offset waits for that state before it is applied.
40
+ - A quick mouse flick on a snapping scrollable or carousel now carries on to the next child in its direction instead of gliding back to the nearest one.
41
+
42
+ ## 5.0.0-next.67
43
+
44
+ ### Patch Changes
45
+
46
+ - Keep `et-animation-leave-to` on an `AnimatedLifecycleDirective` host after its leave finishes, until the next `enter()`. An element removed a frame after its leave no longer flashes back to full opacity first.
47
+
48
+ ## 5.0.0-next.66
49
+
50
+ ### Minor Changes
51
+
52
+ - `injectRouterState()` now carries the navigation `id` and `trigger` (`'imperative' | 'popstate' | 'hashchange'`).
53
+ - Scroll restoration can restore page state, such as a paged list's page count, before it applies the offset (`registerScrollRestorationState`), and can restore after a reload (`restore.restoreOnReload`).
54
+
55
+ ### Patch Changes
56
+
57
+ - `injectIsRouterInitialized()` is now `true` only once the first navigation has ended, so a component created during it sees `false`.
58
+
59
+ ## 5.0.0-next.65
60
+
61
+ ### Minor Changes
62
+
63
+ - New `@ethlete/core/design/theme-css`: `themeCss()`, `surfaceThemeCss()` and `colorThemeCss()` turn surface and color themes into static CSS, sharing one implementation with the Tailwind theme generators.
64
+ - Add `hasAnchoredOverlayPositionExtras()`, which reports whether `enableAnchoredOverlayPositionExtras()` has run.
65
+ - `provideLocale(locale?)` now accepts the initial locale: `provideLocale('de')` starts `injectLocale().currentLocale` at `'de'`. Without an argument it still starts at `'en'`.
66
+
67
+ ### Patch Changes
68
+
69
+ - An anchored overlay strategy's `width`, such as `anchoredDialogOverlayStrategy({ width: '42rem' })`, now sizes the pane instead of being cleared by anchored positioning.
70
+ - Render an `etAutoSurface` above the root as inherited on the server in system color scheme mode, so a dark OS no longer sees a light surface before hydration.
71
+ - Remove the light accent variant class a server painted on `<html>` when `provideColorScheme()` hydrates in dark mode, so root-scoped accents no longer stay on the light variant.
72
+ - The style manager hides its container with the `hidden` attribute instead of an inline style, so server-rendered pages pass a CSP without `'unsafe-inline'` for style attributes.
73
+
74
+ ## 5.0.0-next.64
75
+
76
+ ### Minor Changes
77
+
78
+ - Theming: add the `migrate-color-theme-variants` generator. Run `nx g @ethlete/core:migrate-color-theme-variants` to rewrite the deprecated `colorTheme` and `semanticColorThemes` of your surface themes into `colorThemeVariants`.
79
+ - Theming: `provideColorScheme()` now swaps the default accent of the root surface through its `colorThemeVariants`, so the app root needs no `[etProvideSurface]` for it.
80
+ - Theming: add `SurfaceTheme.colorThemeVariants`, which swaps any chosen accent for a version that reads well on the surface, and deprecate `colorTheme` and `semanticColorThemes`.
81
+ - `provideColorScheme()` and `injectColorScheme().setMode()` switch between the default light and dark surface with an `et-scheme--*` class on `<html>`; regenerate the surface CSS to get the rule.
82
+
83
+ ### Patch Changes
84
+
85
+ - Surface and color directives no longer bundle the `provideColorScheme()` state (media query observer and root class painting) into apps that never call it.
86
+ - Theming: a surface now paints its swapped accent when it sits outside its parent surface in the DOM. A dialog or alert dialog opened with an opener from a light surface used the default accent instead of the variant.
87
+
88
+ ## 5.0.0-next.63
89
+
90
+ ### Patch Changes
91
+
92
+ - Fix modal focus trap tab stops, overlay stacking order for Escape and outside clicks, focus restore to disabled openers, `afterOpened()` on early close, and scroll restoration under a base href.
93
+ - Fix edge cases in `AnimatedLifecycleDirective` classes, `getScrollSnapTarget`, `[etClickOutside]`, `signalElementIntersection` order, `isElementVisible().intersectionRatio` and `createUnsavedChangesTracker` with a `null` default.
94
+ - `htmlToMarkdown` drops empty headings and list items, and normalizes block alignment to `center`, `right` or `justify`; other values serialize as plain Markdown.
95
+ - The modal focus trap treats a native radio group as one Tab stop, so Tab no longer escapes a dialog through it.
96
+
97
+ ## 5.0.0-next.62
98
+
99
+ ### Major Changes
100
+
101
+ - `AnimatedLifecycleDirective` gains a read-only `state` signal, and `state$` is now a read-only observable; read `state()` instead of `state$.value`.
102
+ - `OverlayRuntimeRef` no longer exposes the runtime's internal state mutators, and the runtime's style helpers and ref factory are no longer exported; the `OverlayRuntime` type is.
103
+ - Breaking: `ResizeMoveEvent` `dx`/`dy` are now `totalDx`/`totalDy`, and `resizeEnded` emits the final `ResizeMoveEvent` instead of `void`.
104
+
105
+ ### Minor Changes
106
+
107
+ - `*etAnimatedIf` narrows its `as` value like `@if`, and throws `ET9000` naming the missing `[etAnimatedLifecycle]` ancestor instead of a bare NG0201.
108
+ - `provideColorPalette` also takes one list per registered surface theme name plus a `default` list. The new `injectSurfaceColorPalette()` returns a signal of the list for the surface the caller sits on. `injectColorPalette()` returns the `default` list.
109
+ - Deprecate `createDestroy` in favour of `takeUntilDestroyed()` and add the hand-run `migrate-create-destroy` generator that rewrites the common pattern.
110
+ - Add the recommended assisted migration `legacy-color-themes`: `nx g @ethlete/core:migrate-legacy-color-themes` rewrites `provideColorThemes` into `provideColorThemesWithTailwind4` and lists the Tailwind 4 and surface theme setup that is left.
111
+ - Add `optionalBooleanAttribute`, a `booleanAttribute` that keeps `null` and `undefined`, for tri-state inputs.
112
+ - Adds `injectQueryParamAll` and an `injector` option on every router `inject*` helper; `injectQueryParam` now always returns the first value of a repeated param, and `KeyPressManager` is deprecated.
113
+ - Add `SurfaceTheme.semanticColorThemes`, which names the color theme serving `success`, `warning` or `error` on that surface, and `injectSemanticColorTheme(type)`, a signal of that theme for the nearest surface, else of the theme with that `type`.
114
+ - `OverlayRuntimeCloseSource` gains `'navigation'`, the source `@ethlete/components` overlays close with on a route change.
115
+ - Add a shared `et-visually-hidden` class and `mountVisuallyHidden()` to core, replacing 16 per-component copies of the clip rule in components.
116
+ - Add `colorTheme` to `SurfaceTheme`: an `[etProvideSurface]` that resolves the surface applies that color theme to its subtree, e.g. a darker `brand-on-light` on a light surface. An `[etProvideColor]` with a color on or above the surface element wins
117
+ - Unsaved changes: `confirm` is optional now - set it once with `provideUnsavedChangesConfirm()`, or use `provideUnsavedChangesAlertDialog()` for a ready-made dialog worded by `UNSAVED_CHANGES_LABELS`.
118
+
119
+ ### Patch Changes
120
+
121
+ - `*etAnimatedIf` no longer replays the enter animation when a shown value is swapped for another truthy value.
122
+ - `signalAnimatedNumber` with `duration: 0` now jumps to the target instead of setting `NaN`, and a first frame stamped before `play()` no longer moves the value backwards. `*etRepeat` with a non-numeric count now renders nothing instead of keeping the previous views.
123
+ - `writeViewportSizeToCssVariables()` and `writeScrollbarSizeToCssVariables()` keep updating their CSS variables after the component that first called them is destroyed. Before, the writer stopped with that component and every later call was skipped.
124
+ - Deprecate `injectErrorTheme()`, `injectWarningTheme()` and `injectSuccessTheme()` in favor of `injectSemanticColorTheme(type)`, which follows the surface.
125
+ - Fixes unsaved-changes tracking of a `null` signal, `[etClickOutside]` misfires, cookies on `*.co.uk` hosts, 2D `nearest` scrolling and element swaps, and warns about missing breakpoint and color providers.
126
+ - `equal` no longer treats two Maps as equal when their keys differ but their values are `undefined`. `isSafeUrl`, `isSafeLinkUrl` and Markdown rendering no longer throw on an out-of-range character reference such as `&#99999999;`. `getObjectProperty` follows chained array indexes like `a[0][1]`.
127
+ - `applyFaviconOverlay` loads the base icon with a CORS request, so an overlay now shows over a favicon served from a CORS-enabled CDN instead of being dropped on a tainted canvas.
128
+ - `injectUrl`, `injectRoute` and `injectRouterEvent` read the url before the first navigation through Angular's `Location`, so it no longer carries the base href or, under a hash location strategy, the `#`.
129
+ - `initials()` and the `initials` pipe take a whole character from each word, so a name starting outside the basic multilingual plane no longer yields half a surrogate pair, and a decomposed accent stays on its letter.
130
+ - The `legacy-color-themes` migration keeps the name a shorthand property or a local `export { provideColorThemes }` publishes, and also reports the Tailwind 3 helpers in a JavaScript Tailwind config.
131
+ - `createLogger` now goes quiet on a bare `?et-logger-quiet` query param, not only on one with a value. The JSDoc of `TitleConfig.prefixPart` and `suffixPart` no longer describes each other, and `UnsavedChangesTabConfig.title` no longer names the removed `etSeo` directive.
132
+ - A press on an anchored overlay's origin that closes it no longer swallows a later, unrelated click on that origin when the press ended without a click.
133
+ - The overlay ref's lifecycle observables now replay their event, so `mount(...).beforeOpened()` or a subscribe after `close()` still emits.
134
+ - `scrollToElement` with the `nearest` origin no longer hides the visible edge of an element larger than its container, and no longer scrolls toward an element that is not inside the container.
135
+ - A static provider override no longer erases a default with a key set to `undefined`, so `provideXDefaults({ size: undefined })` keeps the default size; `null` still overrides.
136
+ - The published typings no longer contain `@internal` members.
137
+ - An `Observable` returned from an unsaved-changes `confirm` is now unsubscribed when the session ends while it is open (`abandonAll()`, e.g. on logout), so it no longer keeps running - and a confirm dialog opened through it closes.
138
+ - Peer dependencies are ranges (`^22.1.0` for Angular, `^7.8.0` for RxJS, ...) instead of the workspace's exact versions. `migrate-to-v5` now reports every dropped 4.x export, such as `ObserveResizeDirective` and `LetDirective`, with its successor.
139
+ - `signalElementIntersection` now takes its first reading after render instead of before layout, and a `rootMargin` or `threshold` signal re-creates the observer when it changes.
140
+ - `htmlToMarkdown` and `markdownToHtml` keep the start number of an ordered list (`<ol start="3">` and `3.`) instead of renumbering from 1.
141
+ - Mark every migration with a `level`, so `et update` runs only the required ones.
142
+ - An overlay opened from inside another overlay that closes first (a dialog opened from a menu item) now returns focus to that overlay's own restore target instead of `<body>`.
143
+
144
+ ## 5.0.0-next.61
145
+
146
+ ### Minor Changes
147
+
148
+ - Breaking: `injectAppUpdates().check()` is now `check$()` and `fetchDeployedBuildFingerprint()` is now `fetchDeployedBuildFingerprint$()`; both return cold Observables instead of Promises.
149
+ - Markdown: `htmlToMarkdown` now backslash-escapes literal text (except code, rich-text editor tokens and `data-markdown-verbatim` spans) and drops links with unsafe URL schemes, which the rich-text editor's link tools also refuse.
150
+ - Markdown: `markdownToHtml` takes a `verbatim` pattern whose matches render as plain text. The rich-text editor and viewer pass their token codec's new `markdownPattern`, so `{{field:__x__}}` no longer loses its chip on reload.
151
+ - Rich text editor: an image upload that resolves to an unsafe URL reports `upload-failed`; core exports `isSafeUrl`.
152
+
153
+ ### Patch Changes
154
+
155
+ - The `provideAppUpdates` check no longer logs CSP `style-src` violations under a nonce policy. It reads the entry scripts from the fetched HTML text instead of parsing it with `DOMParser`.
156
+ - An anchored overlay with `autoResize` now flips to the roomier side when its content grows after it opened, instead of staying squeezed on its first side.
157
+ - Drag gestures now also suppress text selection in Safari and WebKitGTK, which ignore the unprefixed `user-select`.
158
+ - `migrate-to-v5` takes a `projects`/`include` scope, migrates every usage it used to skip, and prints what to review by hand. `tailwind-4-color-theme` resolves imported spreads or warns.
159
+ - The `migrate-to-v5` generator no longer rewrites `.foo$` when it migrates `.foo` from `ViewportService` or `RouterStateService`.
160
+ - `fromNextFrame()` now cancels its animation frames on unsubscribe, so an animated lifecycle destroyed mid-transition (e.g. an open menu when its page goes away) leaves no frame pending; `nextFrame()` returns a cancel function.
161
+ - Fix a service-worker notification that the user dismissed natively keeping its click handler. Handlers of notifications no longer shown are now dropped when the next service-worker notification is shown.
162
+ - Overlay runtime: a component that throws during `mount` no longer leaves its host element, its overlay root or its injectors behind.
163
+ - Internal cleanup from the core lib scan; no behaviour change. Exported API no longer carries `@internal` tags.
164
+ - `scrollToElement` with the `nearest` origin now scrolls an element that starts exactly at a container edge into view.
165
+ - `applyStructuredDataBinding` escapes `<` in its JSON-LD, so a value holding `</script>` or `<!--` no longer corrupts or breaks the script in SSR output.
166
+ - The `migrate-to-v5` generator now migrates `ViewportService` and `RouterStateService` per class, leaves classes that do not inject them untouched, and handles aliased imports.
167
+ - The `migrate-to-v5` generator now renames `ProvideThemeDirective` to `ProvideColorDirective` in files that import it from `@ethlete/theming`. Before, it left the old name, and the cdk migration then imported that old name from `@ethlete/core`.
168
+ - `markdownToHtml` now renders a link with a scheme the link editor refuses (`file:`, `intent:`, `ftp:`, ...) as its text.
169
+ - The rich text editor keeps an image whose URL holds parentheses or spaces an image after a save and reload. `htmlToMarkdown` escapes brackets and backslashes in image alt text, so the alt text comes back exactly as written.
170
+ - `getScrollItemTarget` no longer rounds a half-visible item up to fully visible, so element-mode paging in a scrollable lands on that item instead of skipping it.
171
+
172
+ ## 5.0.0-next.60
173
+
174
+ ### Minor Changes
175
+
176
+ - `provideSurfaceThemesWithTailwind4` now warns in dev mode when the page leaves the root font size at the browser default instead of setting `html { font-size: 62.5%; }`.
177
+
178
+ ### Patch Changes
179
+
180
+ - Element signals such as `signalElementIntersection` now accept a signal of a read-only array, so a `viewChildren` signal can be passed directly.
181
+ - `htmlToMarkdown` keeps block alignment as an `et-rte-align-*` class instead of a `style` attribute a strict CSP blocks, and structured-data scripts carry the `CSP_NONCE`. Other renderers need CSS for that class.
182
+ - The `provideX` functions from `defineProvider`, `defineRootProvider` and `defineStaticProvider` return `StaticProvider[]` instead of `Provider[]`. You can now spread them into a `StaticProvider[]`, for example into `Injector.create` or an overlay's `providers`.
183
+ - `defineStaticProvider` and `defineStaticRootProvider` now replace an array or other non-object default with the override, instead of spreading the array into an object. Only two plain objects are merged.
184
+ - `migrate-to-v5` lists every file that still uses the removed `@Memo` decorator or props module (`createProps`, `[etProps]`, …), which have no replacement.
185
+
186
+ ## 5.0.0-next.59
187
+
188
+ ### Patch Changes
189
+
190
+ - The legacy theme stylesheets carry the page's `ngCspNonce`, and `et-structured-data` no longer writes a static `style` attribute, so both pass a strict `style-src`.
191
+ - `markdownToHtml` renders block and table-cell alignment as an `et-rte-align-*` class instead of an inline `text-align` style, which a strict `style-src` dropped; `htmlToMarkdown` reads both.
192
+
193
+ ## 5.0.0-next.58
194
+
195
+ ### Minor Changes
196
+
197
+ - Add `signalCountdown(deadline)`, a signal of the days, hours, minutes and seconds left until a deadline, recounted on the whole second.
198
+ - Overlays and `[etTooltip]` can anchor to an SVG element, and `[etTooltip]` takes an `anchor` input to point at an element other than its trigger; core exports `isElement` and `isHTMLOrSVGElement`.
199
+
200
+ ### Patch Changes
201
+
202
+ - Place `takeUntilDestroyed()` last in every pipe, so operators after it no longer run or stay subscribed after destroy.
203
+
204
+ ## 5.0.0-next.57
205
+
206
+ ### Major Changes
207
+
208
+ - `signalElementMutations` now returns `Signal<MutationRecord[]>` with every record of a batch, where it returned only the first record or `null`. Read `.at(-1)` for the old single record.
209
+
210
+ ### Minor Changes
211
+
212
+ - The Angular peer dependency moves from 22.0.7 to 22.1.6. Angular 22.0.x is affected by
213
+ GHSA-hh8m-fm6v-7cvg, a sanitization bypass through directive host bindings, fixed in 22.1.0.
214
+ - `createOverlayOpener(definition, { single: 'replace' })` keeps one overlay open and replaces it on the next `open()`, through the unsaved-changes guard (`dismissSources.replace`); share one slot across openers with `createOverlaySingleSlot()`.
215
+
216
+ ### Patch Changes
217
+
218
+ - An anchored overlay near a side edge now keeps its placement and shifts along the edge. Before, a `top` pane next to the right edge flipped to `left`.
219
+ - `provideAppUpdates` detects a new deploy again when the entry scripts sit at the end of `<body>`, as the Angular CLI emits them, and ignores scripts the app appended itself.
220
+ - Core: overlays close and restore focus in a pop-up window, `unbindProps` undoes everything `bindProps` applied, cookie helpers no-op on the server, `equal()` compares `Date`s by tag, and `memoizeSignal` caches per application.
221
+ - Animations: `@ethlete/core` now ships the `--ease-*` tokens its own stylesheets transition with, through `mountEasingTokens()`, so an app that loads no `@ethlete/cdk` stylesheet no longer loses every overlay animation.
222
+ - `signalElementDimensions` now accepts a `viewChild.required(...)`. Before, it read the element while the component was created and threw NG0951.
223
+ - The focus-visible tracker now reports keyboard focus after a bare Shift press, like the browser's `:focus-visible`.
224
+ - Tearing down an app with an open overlay no longer logs Angular's NG0406 "ApplicationRef has already been destroyed" warning.
225
+ - Overlays can be mounted `passive` and are then skipped as the top layer, so a dialog still closes on a backdrop press while a tooltip shows inside it.
226
+ - An overlay now restores focus to its opener only when focus is still inside it at teardown, so an outside press that focuses another control keeps focus there.
227
+ - Title bindings created after the first navigation has completed apply at once instead of waiting for the next navigation.
228
+ - A meta or link binding that switches to another tag (a resource hint whose URL changes, an alternate link whose `hreflang` changes) removes the old tag instead of leaving it in `<head>`.
229
+ - Type `SurfaceTheme['name']` as `RegisteredSurfaceThemeName`. An app that augments
230
+ `EthleteSurfaceThemeNameRegistry` now gets its theme definitions checked against the same union as
231
+ `etProvideSurface`, and the internal provider sync compiles again. Apps that register no names keep
232
+ plain `string`.
233
+
234
+ ## 5.0.0-next.56
235
+
236
+ ### Patch Changes
237
+
238
+ - [#3075](https://github.com/ethlete-io/ethdk/pull/3075) [`1d38e7e`](https://github.com/ethlete-io/ethdk/commit/1d38e7e0a025769f065d8ca7d506cb75ad89139a) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et update` moves the `@ethlete/*` packages to a newer version, runs the codemods those versions
239
+ declare in their own `migrations.json`, and reports what needs a decision or an agent.
240
+
241
+ - [#3075](https://github.com/ethlete-io/ethdk/pull/3075) [`f19d4ae`](https://github.com/ethlete-io/ethdk/commit/f19d4ae835dc5171f328c660d44870aaf3bc8f77) Thanks [@github-actions](https://github.com/apps/github-actions)! - Let overlay content handle `Escape` first, so the command palette clears its query
242
+ before closing. A `strategies` array without a breakpoint-less entry now falls back
243
+ to its smallest one instead of throwing.
244
+
245
+ ## 5.0.0-next.55
246
+
247
+ ### Patch Changes
248
+
249
+ - [`c067767`](https://github.com/ethlete-io/ethdk/commit/c06776704a32d7d78ba057389ac9efb157f0e4fc) Thanks [@TomTomB](https://github.com/TomTomB)! - An overlay opened without an `injector` or a `viewContainerRef` now reaches its own `providers` from
250
+ the content component, instead of resolving them against the opener's environment injector.
251
+
252
+ ## 5.0.0-next.54
253
+
254
+ ### Major Changes
255
+
256
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`a9113cb`](https://github.com/ethlete-io/ethdk/commit/a9113cb6ce63942ffce0e26ca7df7f0556a14838) Thanks [@github-actions](https://github.com/apps/github-actions)! - Core: correct framework primitive behavior; breakpoint transforms now require explicit fallbacks, unresolved surface types return `null`, and the validator aggregate is renamed to `EthleteValidators`.
257
+
258
+ ### Minor Changes
259
+
260
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`a9113cb`](https://github.com/ethlete-io/ethdk/commit/a9113cb6ce63942ffce0e26ca7df7f0556a14838) Thanks [@github-actions](https://github.com/apps/github-actions)! - `MatchStateType` is now a const object plus a derived union type instead of an `enum`. Dotted access
261
+ and type-position use are unchanged.
262
+
263
+ ### Patch Changes
264
+
265
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`56e301f`](https://github.com/ethlete-io/ethdk/commit/56e301f6e3b455b1e7e2de54f101206bb890b557) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query: harden auth, caching, forms, GraphQL, WebSockets and legacy lifecycle behavior; add lifecycle-scoped form branches and secure host-only auth cookies.
266
+
267
+ ## 5.0.0-next.53
268
+
269
+ ### Major Changes
270
+
271
+ - [`2352137`](https://github.com/ethlete-io/ethdk/commit/235213735ede4c3542b7796d378e008bcab50bdc) Thanks [@TomTomB](https://github.com/TomTomB)! - An overlay strategy switch between a backdropped and a backdrop-less shape now adds or
272
+ removes the backdrop instead of keeping the one it mounted with. `elements.backdropElement`
273
+ is a signal.
274
+
275
+ ### Patch Changes
276
+
277
+ - [`0b4b4eb`](https://github.com/ethlete-io/ethdk/commit/0b4b4eb779218d6c70b27c212b03703ca8b64564) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay: an overlay's own providers are destroyed when it closes, so an overlay router with `syncUrl` removes its query param from the url again.
278
+
279
+ ## 5.0.0-next.52
280
+
281
+ ### Major Changes
282
+
283
+ - [`4044a00`](https://github.com/ethlete-io/ethdk/commit/4044a0007de55d25b5a697c6e4190e21d68d022f) Thanks [@TomTomB](https://github.com/TomTomB)! - - Notifications: a toast keeps one elevation, paints above overlays, and keeps out of every reserved viewport edge.
284
+ - Query devtools: a side dock reserves the edge it covers.
285
+ - `SurfaceContextTracker` drops `topType` / `topElevation`.
286
+
287
+ ### Minor Changes
288
+
289
+ - [`3122607`](https://github.com/ethlete-io/ethdk/commit/3122607d1727844a2d987032f45ad631f678c2ca) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlays and floating chrome now keep out of space a surface above the page reserved with `reserveOverlayViewportSpace()` - so a dialog, menu or toast is no longer stacked under the docked query devtools panel.
290
+
291
+ ### Patch Changes
292
+
293
+ - [`0116464`](https://github.com/ethlete-io/ethdk/commit/0116464f3efc92bfa7dc094a2b20ae9d813a8c45) Thanks [@TomTomB](https://github.com/TomTomB)! - - `etAnimatedLifecycle` no longer ends an enter or leave before its animation started, which destroyed a routed overlay page without playing its exit animation.
294
+ - Adds `AnimatableDirective.getRunningAnimations()`.
295
+
296
+ - [`68db91f`](https://github.com/ethlete-io/ethdk/commit/68db91fb975378cccebc4ad99f59365eba90fb43) Thanks [@TomTomB](https://github.com/TomTomB)! - - `etAutoSurface`, `et-grid-item` and `et-form-field` elevate above an app's root surface, instead of staying inherited.
297
+ - An unset `etProvideSurface` reports the surface it inherits, so content below it no longer resolves one elevation too low.
298
+ - Adds `injectParentSurface()`.
299
+
300
+ ## 5.0.0-next.51
301
+
302
+ ### Minor Changes
303
+
304
+ - [`5c1190a`](https://github.com/ethlete-io/ethdk/commit/5c1190ac76c244ff1c293b390dd599ed016d26de) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlays: a press on a surface stacked above them no longer counts as an outside press, so working in the query devtools leaves an open dialog, sheet, menu, select or tooltip alone.
305
+
306
+ ## 5.0.0-next.50
307
+
308
+ ### Minor Changes
309
+
310
+ - [#3062](https://github.com/ethlete-io/ethdk/pull/3062) [`79cb555`](https://github.com/ethlete-io/ethdk/commit/79cb5551c987c4584aabeae3c39d1415c3e79d6e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `provideAppUpdates()`, which stops a tab that was open across a deploy from breaking on a lazy chunk that no longer exists - reloading on its own when no form would lose changes.
311
+
312
+ - [#3063](https://github.com/ethlete-io/ethdk/pull/3063) [`37067ce`](https://github.com/ethlete-io/ethdk/commit/37067cee67c5cd360360a5f59c29f58afc08e62c) Thanks [@TomTomB](https://github.com/TomTomB)! - A single-scheme app no longer needs a root `etProvideSurface`: its default surface paints `:root` unconditionally once the surface CSS is regenerated, and the outermost provider resolves it through the new `injectDefaultSurfaceTheme()` / `injectSurfaceType()`.
313
+
314
+ ## 5.0.0-next.49
315
+
316
+ ### Minor Changes
317
+
318
+ - [#3061](https://github.com/ethlete-io/ethdk/pull/3061) [`7cd3da8`](https://github.com/ethlete-io/ethdk/commit/7cd3da8342d0d619f06154d4155cfafedbed28f4) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlays: `data-et-overlay-layer` (or a per-open `zIndex`) puts an overlay above the default stacking level, which is how the query devtools panel and its toggle now stay visible over an app's own modals and tooltips.
319
+
320
+ ## 5.0.0-next.48
321
+
322
+ ### Minor Changes
323
+
324
+ - [`15d88c6`](https://github.com/ethlete-io/ethdk/commit/15d88c6abb6ead4596357705b9c899e1f6474567) Thanks [@TomTomB](https://github.com/TomTomB)! - Loading indicators wait before they show and hold once shown, so a fast response leaves no flicker - via the new `signalDeferredLoading` from `@ethlete/core`, applied across form field, select, cascader, menu and table.
325
+
326
+ ## 5.0.0-next.47
327
+
328
+ ### Patch Changes
329
+
330
+ - [#3056](https://github.com/ethlete-io/ethdk/pull/3056) [`2e83ba8`](https://github.com/ethlete-io/ethdk/commit/2e83ba8233c30eead4b5f99d37fedb2629764304) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix `nx g @ethlete/core:migrate-surface-interaction-swatch` failing with `Cannot find module` instead
331
+ of running.
332
+
333
+ ## 5.0.0-next.46
334
+
335
+ ### Minor Changes
336
+
337
+ - [#3055](https://github.com/ethlete-io/ethdk/pull/3055) [`1f72eb9`](https://github.com/ethlete-io/ethdk/commit/1f72eb9453b6b7726cfe312720299b913f5c565f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `provideColorPalette` - the labelled color themes an app offers a user to pick from. The scheduler's color field becomes a swatch picker when one is in scope, and stays a text box when none is.
338
+
339
+ - [`512750a`](https://github.com/ethlete-io/ethdk/commit/512750a654bda671b4078fc726914ed5eecda14e) Thanks [@TomTomB](https://github.com/TomTomB)! - `[etProvideColor]="'surface'"` renders a component in the ambient surface's neutral instead of an accent. **Breaking:** `SurfaceTheme['interactionColor']` is now a swatch - run `nx g @ethlete/core:migrate-surface-interaction-swatch`, then regenerate.
340
+
341
+ ## 5.0.0-next.45
342
+
343
+ ### Minor Changes
344
+
345
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`19ac925`](https://github.com/ethlete-io/ethdk/commit/19ac92556c91563cda0b9639d985639e48255075) Thanks [@github-actions](https://github.com/apps/github-actions)! - Drag and resize gestures no longer sweep a text selection across the page, and `suppressTextSelection()` is exported for gestures you drive yourself.
346
+
347
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`ebcff36`](https://github.com/ethlete-io/ethdk/commit/ebcff36d21695414d8ea93e32a88f262110f8883) Thanks [@github-actions](https://github.com/apps/github-actions)! - The overlay mount config takes an optional `document`, so an overlay anchored inside a same-origin pop-up window now opens in that window.
348
+
349
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`f426563`](https://github.com/ethlete-io/ethdk/commit/f4265630749f162d097b147da55256e8bfa056ad) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: an About tab reporting the loaded `@ethlete/*` and Angular versions plus `provideQueryDevtools({ about })`, mirrored on `window.ethlete` and in the session export.
350
+
351
+ ### Patch Changes
352
+
353
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`8459c8b`](https://github.com/ethlete-io/ethdk/commit/8459c8b38595133b97e33615ba8fa6f685dddb8a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Anchored overlays no longer fly to the viewport corner when their reference element is removed while they are open - the pane keeps its last position, or closes at once with `autoCloseIfReferenceHidden`.
354
+
355
+ ## 5.0.0-next.44
356
+
357
+ ### Minor Changes
358
+
359
+ - [#3050](https://github.com/ethlete-io/ethdk/pull/3050) [`2d44597`](https://github.com/ethlete-io/ethdk/commit/2d44597f07b165a83c19f049a022c4247a8e3eb1) Thanks [@github-actions](https://github.com/apps/github-actions)! - Slider and rating now drag on `dragGestureFrom`, so a gesture the browser takes away reverts
360
+ instead of committing. `dragEnded` carries the release position.
361
+
362
+ ## 5.0.0-next.43
363
+
364
+ ### Minor Changes
365
+
366
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`6bd6057`](https://github.com/ethlete-io/ethdk/commit/6bd6057398465ecd24a2f187321934e12430d127) Thanks [@github-actions](https://github.com/apps/github-actions)! - New `injectFileDownload()` and `createObjectUrlHandle()` in core replace four hand-rolled object URLs. The query devtools exports now append their anchor before clicking it, which Firefox ignored.
367
+
368
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`6c95aa0`](https://github.com/ethlete-io/ethdk/commit/6c95aa00bb0df0aa4c3638453a35c4f14a9364eb) Thanks [@github-actions](https://github.com/apps/github-actions)! - A gesture the browser takes away mid-drag now emits `dragCancelled` / `resizeCancelled` instead of `dragEnded`. Grid moves and resizes, table column reorder and column resize revert instead of committing a drop the user never made.
369
+
370
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`5008c81`](https://github.com/ethlete-io/ethdk/commit/5008c81d726021d078e87ecb37cfb1d5d4eee6cb) Thanks [@github-actions](https://github.com/apps/github-actions)! - Grid resize strips grow into the gap - a 14px target at the default gap, with the marker unmoved - via the new `--et-resize-handles-outset`. Touch sizes now key on `any-pointer: coarse`, so a touchscreen laptop gets them too.
371
+
372
+ ## 5.0.0-next.42
373
+
374
+ ### Minor Changes
375
+
376
+ - [#3047](https://github.com/ethlete-io/ethdk/pull/3047) [`309dc57`](https://github.com/ethlete-io/ethdk/commit/309dc576d296efe39d9ff85030102c10db834b9b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Scroll restoration: mark a "back to the overview" link with `etRestoreScroll` (or `routerRestoreScroll()` in the navigation state) and it restores that page's last offset instead of scrolling to top.
377
+
378
+ ## 5.0.0-next.41
379
+
380
+ ### Major Changes
381
+
382
+ - [#3046](https://github.com/ethlete-io/ethdk/pull/3046) [`263dae8`](https://github.com/ethlete-io/ethdk/commit/263dae89d864db2a05541f373a2a1b7d2e75c42f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Remove the deprecated, SSR-unsafe `SeoDirective` and its `SeoConfig` types - use the `apply*Binding` functions instead (the SEO guide has a per-key migration table).
383
+
384
+ ### Minor Changes
385
+
386
+ - [#3046](https://github.com/ethlete-io/ethdk/pull/3046) [`5b94adc`](https://github.com/ethlete-io/ethdk/commit/5b94adc97abb32555fb462fad71cbe27fc733a4a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Select and cascader panels now stay below the field with a shorter list instead of flipping
387
+ above it or sliding over it, via the new anchored-overlay `minAvailableSpace` option.
388
+
389
+ ## 5.0.0-next.40
390
+
391
+ ### Minor Changes
392
+
393
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`e660b34`](https://github.com/ethlete-io/ethdk/commit/e660b34d6b791296733824b6ae2bf48ab7a1c5b6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `injectDefaultColorTheme()`, resolving the `ColorTheme` marked `isDefault: true` for components with no themed ancestor to inherit from.
394
+
395
+ ### Patch Changes
396
+
397
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`26909f9`](https://github.com/ethlete-io/ethdk/commit/26909f9bce86f379e900e588b733719414ea7add) Thanks [@github-actions](https://github.com/apps/github-actions)! - The deprecated `createTailwindRgbVar` now returns `string` instead of `string | null` when called with
398
+ a defined value.
399
+
400
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`1fb193c`](https://github.com/ethlete-io/ethdk/commit/1fb193c0e494357cbfb8a6a6428643b114c177f8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay dialogs, sheets and full-screen dialogs now skip their enter/leave motion under `prefers-reduced-motion`, matching tooltip/menu/toggletip. Fixes the animation lifecycle getting stuck under reduced motion, which could leave focus and `overlayRef.afterOpened()` never firing.
401
+
402
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`019edcc`](https://github.com/ethlete-io/ethdk/commit/019edcc95e372166ec6332a9fb99758de50af178) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: raise the shared overlay root's z-index above the query devtools panel, so a menu/tooltip/dialog opened from inside the devtools (e.g. its response override menu) is no longer rendered behind the panel.
403
+
404
+ ## 5.0.0-next.39
405
+
406
+ ### Patch Changes
407
+
408
+ - [`74850e3`](https://github.com/ethlete-io/ethdk/commit/74850e3a62339565c13bdeb89c4334993eefd2b3) Thanks [@TomTomB](https://github.com/TomTomB)! - The provider-definition doc comments no longer spell the pure annotation out verbatim, so Rollup stops warning about (and stripping) an annotation it cannot attach to a call while bundling `@ethlete/core`.
409
+
410
+ ## 5.0.0-next.38
411
+
412
+ ### Minor Changes
413
+
414
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`eeb8db3`](https://github.com/ethlete-io/ethdk/commit/eeb8db366907058d9f8357ab84582580dc5ab7d9) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a browser notification API: `injectNotifications()` exposes a reactive `permission` signal,
415
+ `request()`, `show(config)` returning a `NotificationRef`, and `closeAll()` - over both the
416
+ `Notification` constructor and the service-worker path, SSR-safe.
417
+
418
+ ## 5.0.0-next.37
419
+
420
+ ### Major Changes
421
+
422
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`6c9d38d`](https://github.com/ethlete-io/ethdk/commit/6c9d38d7e6b41586d7c9abb3296e5f45ccc3767c) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay runtime: build anchored strategies with `anchoredOverlayPosition({ referenceElement, … })`
423
+ instead of a `{ kind: 'anchored', … }` literal - it is what pulls `@floating-ui/dom` in, so apps
424
+ that only center dialogs no longer bundle it (~7 kB gz). `autoResize`, `autoHide`,
425
+ `autoCloseIfReferenceHidden` and arrows additionally need `enableAnchoredOverlayPositionExtras()`.
426
+
427
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`6c9d38d`](https://github.com/ethlete-io/ethdk/commit/6c9d38d7e6b41586d7c9abb3296e5f45ccc3767c) Thanks [@github-actions](https://github.com/apps/github-actions)! - `@ethlete/core` no longer depends on `@angular/cdk`: `injectBreakpointObserver()` is a plain
428
+ `matchMedia` implementation (same API), and `AnimatedOverlayDirective` moved to `@ethlete/cdk` -
429
+ import it from there.
430
+
431
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`42ec970`](https://github.com/ethlete-io/ethdk/commit/42ec970d6963bb5a3aa3af4e207ef2cac801c915) Thanks [@github-actions](https://github.com/apps/github-actions)! - DI: `createProvider` / `createRootProvider` / `createStaticProvider` / `createStaticRootProvider` /
432
+ `createLabels` are replaced by `defineProvider` & co., which return a definition you read with
433
+ `toProvideFn` / `toInjectFn` / `toToken`; `createQueryClient`, `createBearerAuthProvider` and
434
+ `createWebSocketClient` return that definition instead of a tuple. Every `provideX` / `injectX` /
435
+ token export keeps its name - run `nx g @ethlete/core:migrate-provider-shape` for your own call sites.
436
+ Cuts the `@ethlete/components` import floor from 89.9 to 2.4 kB gz.
437
+
438
+ ### Minor Changes
439
+
440
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`62b03f9`](https://github.com/ethlete-io/ethdk/commit/62b03f937274d68139be12df3778ce7d316600ea) Thanks [@github-actions](https://github.com/apps/github-actions)! - Carousel & Scrollable: much smoother swiping on a phone - 85% less style recalculation and 88% less
441
+ paint with `transition="wipe"`, and no observer work during a scroll. Snapping is native CSS scroll
442
+ snap (`ScrollableDirective.suspendSnap()` holds it off while something writes an offset itself), and
443
+ the built-in transitions run as composited keyframes. New `transition="custom"` fills
444
+ `--et-carousel-slide-progress` without applying an effect, for CSS of your own; new
445
+ `--et-carousel-wipe-dim-color`; `signalElementChildren` / `signalElementScrollState` take a
446
+ `mutations` option to narrow their observers.
447
+
448
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`7e444d6`](https://github.com/ethlete-io/ethdk/commit/7e444d6d11f65b00ae22b9d0f9d553ff3b45b733) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: block quote and fenced code block tools (`'blockquote'` / `'codeBlock'`, also
449
+ typed as `> ` / ` ``` `), both in the default toolbar. Quotes nest with Tab/Shift+Tab; a code block
450
+ holds literal text, so the marks that can't serialize inside one disable themselves. `htmlToMarkdown`
451
+ / `markdownToHtml` now round-trip nested quotes (`>>`).
452
+
453
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`30d3dfb`](https://github.com/ethlete-io/ethdk/commit/30d3dfbfd0ffa08f4eb6c9a95a0d0a7739576264) Thanks [@github-actions](https://github.com/apps/github-actions)! - `unsavedChanges`: a tracker now locks the browser tab while the value differs from its baseline - a
454
+ `beforeunload` listener attached only while changes exist - through the new `tab` option (`false` opts
455
+ out), with opt-in `titleMarker`, `flash`, `favicon` and `badge` extras.
456
+ `createUnsavedChangesTabLock()` is the same guard standalone, for state that isn't a form.
457
+
458
+ - New `injectUnsavedChangesCoordinator()`: one confirm on screen at a time app-wide, plus
459
+ `abandonAll(reason?)` for a session that ends underneath a guard. `confirm` now receives a
460
+ `{ signal }` argument so a dialog can close itself instead of being stranded.
461
+ - New favicon store and `applyFaviconOverlay(binding)`, plus title-store `addMarker` / `removeMarker`
462
+ behind the public `applyHeadTitleMarker(binding)`.
463
+
464
+ ### Patch Changes
465
+
466
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`c622e2c`](https://github.com/ethlete-io/ethdk/commit/c622e2c82b1a64956e3b5d14e7f44ea03c677b81) Thanks [@github-actions](https://github.com/apps/github-actions)! - Breakpoint inputs: warn in dev mode when a breakpoint map mixes valid and unknown keys. One bad key (a
467
+ `default` entry, say) makes the whole map inert - it becomes a plain value, which for an attribute binding
468
+ renders as `[object Object]` and does nothing - and that failed silently until now.
469
+
470
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`fba7ed8`](https://github.com/ethlete-io/ethdk/commit/fba7ed852d7f4bfb7791cce13f5062b8c4fa4c59) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix `applyStructuredDataBinding` writing its JSON into a `text` **attribute** on the `<script>` instead
471
+ of into the script's content - the tag was emitted, but empty, so no crawler ever read the structured
472
+ data. (`StructuredDataComponent` was unaffected.)
473
+
474
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`353777b`](https://github.com/ethlete-io/ethdk/commit/353777bb56e42ad1c02058a2ccf694f69c94b025) Thanks [@github-actions](https://github.com/apps/github-actions)! - Mark build-tooling peer dependencies (`vite`, `typescript`, `ts-morph`, `@nx/devkit`, `@analogjs/*`) and feature-scoped runtime peers (`date-fns` in components) as optional via `peerDependenciesMeta`. They are only needed when running the Nx generators or using the date/time components - consumers no longer have to install them just to use the libraries.
475
+
476
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`6c9d38d`](https://github.com/ethlete-io/ethdk/commit/6c9d38d7e6b41586d7c9abb3296e5f45ccc3767c) Thanks [@github-actions](https://github.com/apps/github-actions)! - `RuntimeError` logs its `data` directly instead of deep-cloning it first, which keeps the clone
477
+ helper out of every package's baseline bundle.
478
+
479
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`353777b`](https://github.com/ethlete-io/ethdk/commit/353777bb56e42ad1c02058a2ccf694f69c94b025) Thanks [@github-actions](https://github.com/apps/github-actions)! - Adopt the `@ethlete/eslint-plugin` styleguide flat configs in `core`, `query`, `contentful` and
480
+ `types`, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible to
481
+ TypeScript consumers: exported `types` shapes are `type` aliases rather than `interface` declarations
482
+ (so they can no longer be extended by declaration merging), `core`'s `PropsDirective.destroyRef` and
483
+ `SeoDirective.parent` are `private`, and `ConsentHandler` is a `type`. The theme name registries stay
484
+ interfaces so consumers can keep augmenting them.
485
+
486
+ ## 5.0.0-next.36
487
+
488
+ ### Minor Changes
489
+
490
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`e052061`](https://github.com/ethlete-io/ethdk/commit/e0520614647b784f19ad55a4d7f6df47acec154e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Localization: one mechanism for every string the library renders. `createLabels` (core) backs a
491
+ `provide<Domain>Labels` / `inject<Domain>Labels` pair per domain - 22 of them, all locale-reactive and
492
+ signal-shaped. See the [localization guide](https://ethlete-sdk-docs-next.web.app/components/localization).
493
+
494
+ - New tokens make the rich text editor, stream, grid, loader, chip, calendar, time picker, dropzone,
495
+ select, cascader, phone input, slider, date/time and notification strings overridable.
496
+ - **Breaking:** `inject*Labels()` now returns a signal; the string fields left `StreamConsentConfig`,
497
+ `StreamPlayerErrorConfig`, `PipSlotPlaceholderConfig`, `GridConfig` and `NotificationManagerConfig`
498
+ (with their `transformer` hooks); per-instance label inputs default to `null` instead of English.
499
+ - Fixes the PiP close/back buttons, which set an attribute literally named `attr.aria-label`.
500
+
501
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`38bb816`](https://github.com/ethlete-io/ethdk/commit/38bb8165006c4ebfba6a34623468ded140002188) Thanks [@github-actions](https://github.com/apps/github-actions)! - Card presets and a tabs variant: `et-radio` and `et-choice-field` take `variant="card"` (full-width clickable
502
+ panel, label leading, selection on the border and label), and `et-segmented-button-group` takes `variant="tabs"` (underlined
503
+ selection instead of a filled pill). Closes the last cdk parity gaps.
504
+
505
+ `@ethlete/core` adds `injectRouterNavigationState<T>()` for reading the state a navigation was given.
506
+
507
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`4624559`](https://github.com/ethlete-io/ethdk/commit/4624559c81ed9b6efffc539b8f1dd0db0556420c) Thanks [@github-actions](https://github.com/apps/github-actions)! - RTL and reduced-motion consistency pass:
508
+
509
+ - Side sheets and the notification stack dock, animate and drag toward their logical inline edge under `dir="rtl"` - `dragToDismiss.direction` gains `'to-inline-start'` / `'to-inline-end'`.
510
+ - `createFlipAnimation` and the PiP animations now skip to their end state under `prefers-reduced-motion`; `ignoreReducedMotion` opts out, and `matchesReducedMotion()` is exported for helpers with no injection context.
511
+ - The full-screen overlay animation throws `ET1209` when it has no origin element, instead of a bare `Error`.
512
+
513
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`f6061e1`](https://github.com/ethlete-io/ethdk/commit/f6061e162aacd3c847ad1a9c9c9ef13d2e494b7f) Thanks [@github-actions](https://github.com/apps/github-actions)! - `createSwipeTracker` now reports the release velocity - measured over the trailing
514
+ 100ms of the gesture (`SWIPE_VELOCITY_WINDOW_MS`) - in `pixelPerSecondX/Y` instead
515
+ of the whole-gesture average. A slow drag ending in a flick reports the flick, and a
516
+ flick parked before release reports ~0.
517
+
518
+ ### Patch Changes
519
+
520
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`b06ed44`](https://github.com/ethlete-io/ethdk/commit/b06ed44db47a52d2a07a4d9a6b3bd3b04011decb) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: the anchored arrow no longer rides into a pane's rounded corner on aligned placements or when a pane
521
+ shifts near a viewport edge. `arrowPadding` now measures the arrow's actual base, so it means "how close the
522
+ arrow may get to the corners" - tooltip and toggletip default to `20` (was `8`), a bare anchored strategy to
523
+ `12` (was `4`).
524
+
525
+ ## 5.0.0-next.35
526
+
527
+ ### Minor Changes
528
+
529
+ - [`a20d0ce`](https://github.com/ethlete-io/ethdk/commit/a20d0cee2f9937ad45ac1fd5eaec3c1a6ac1d27c) Thanks [@TomTomB](https://github.com/TomTomB)! - Add `injectIsDocumentVisible()` - a signal for whether the page is the tab in front, which an
530
+ IntersectionObserver cannot tell you.
531
+
532
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`d787b1d`](https://github.com/ethlete-io/ethdk/commit/d787b1de041da31b6974a9f1b06ceb6ba6f5f6c5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Export `dragGestureFrom(event, element, { commitThreshold })` - the pointer-drag primitive that
533
+ `etDragHandle` is built on, now usable directly. It takes a `pointerdown` and returns an observable of
534
+ `start` / `move` / `end` (or a single `tapped` when the pointer never crossed the commit threshold),
535
+ completing with the gesture.
536
+
537
+ Prefer the directive. Reach for the primitive when the draggable element belongs to someone else's
538
+ template and you only have a delegated `pointerdown` - the case that motivated this: `et-table`'s
539
+ opt-in column-reorder feature attaches a drag to header cells the table itself renders, without the
540
+ table having to import any drag code.
541
+
542
+ `DragHandleDirective` is unchanged and now uses this primitive internally; `DragStartEvent` /
543
+ `DragMoveEvent` keep their import path.
544
+
545
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`929e355`](https://github.com/ethlete-io/ethdk/commit/929e3554770a132b4791edd2c063fa677f758762) Thanks [@github-actions](https://github.com/apps/github-actions)! - `setupScrollRestoration` can now restore the previous scroll offset on browser back/forward navigation instead of scrolling to top, via `restore: { enabled: true }`.
546
+
547
+ - The offset is applied only once the content is tall enough to reach it, so query-driven pages no longer land at the wrong place while their skeleton/loading state is on screen. Options: `timeout`, `maxTimeout`, `clampOnTimeout`.
548
+ - `holdScrollRestoration(() => query.isLoading())` suspends the wait from inside a route component when the data takes longer than `timeout` to arrive.
549
+ - `scrollElement` now also accepts a getter (`() => HTMLElement | null`), for scroll containers that only exist after the app shell rendered or are created per route.
550
+
551
+ ### Patch Changes
552
+
553
+ - [`4ffabfb`](https://github.com/ethlete-io/ethdk/commit/4ffabfbe1830d4560b98dcda7d262155273dd62e) Thanks [@TomTomB](https://github.com/TomTomB)! - `useCursorDragScroll` no longer starts a drag on a secondary click, and ends one when a context menu opens -
554
+ previously a right-click left it latched on, so every later mouse move scrolled the container.
555
+
556
+ ## 5.0.0-next.34
557
+
558
+ ### Patch Changes
559
+
560
+ - [`ef65231`](https://github.com/ethlete-io/ethdk/commit/ef65231ed04184345200f1e6f2e80d3207778157) Thanks [@TomTomB](https://github.com/TomTomB)! - Auto-surface: content that is grafted into an overlay pane after it first renders (e.g. a select option's `etAutoSurface` avatar) now re-resolves its elevation once it lands in the pane, instead of staying stuck one level too low.
561
+
562
+ ## 5.0.0-next.33
563
+
564
+ ### Patch Changes
565
+
566
+ - [#3034](https://github.com/ethlete-io/ethdk/pull/3034) [`9dd2a23`](https://github.com/ethlete-io/ethdk/commit/9dd2a2335f4cb677e3eb8120098cfb1b8a67d87d) Thanks [@github-actions](https://github.com/apps/github-actions)! - `injectAnimatedBlockSize`: keep the `resizingClass` applied when a resize animation is interrupted by a new one, so overlay panels (select, cascader, date-picker, menu) no longer flash a scrollbar during rapid successive content changes such as async search typing.
567
+
568
+ ## 5.0.0-next.32
569
+
570
+ ### Patch Changes
571
+
572
+ - [`ed58b19`](https://github.com/ethlete-io/ethdk/commit/ed58b19b1957f2051e0f1ef68c3814747af9ccd0) Thanks [@TomTomB](https://github.com/TomTomB)! - `etAutoSurface`: opening an overlay (date-picker, select, menu, …) no longer elevates unrelated surfaces on the base page. The overlay surface-context tracker is now matched by DOM containment, so an `etAutoSurface` only adopts an overlay's elevation when it actually renders inside that overlay's pane.
573
+
574
+ ## 5.0.0-next.31
575
+
576
+ ### Minor Changes
577
+
578
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`1a6849f`](https://github.com/ethlete-io/ethdk/commit/1a6849fa37e8f6907d08766846a50d3d9de8211b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add the `unsavedChanges` family for guarding forms against accidental discard, and a close-veto seam in the overlay runtime that powers it.
579
+ - `createUnsavedChangesTracker` - snapshots a default value, tracks whether the watched form/value differs from it (deep-equal snapshot semantics, not signal-forms `dirty()`), and normalizes an async `confirm` (value / Promise / Observable) to a `Promise<boolean>`. Signal-forms `FieldTree` is the first-class source; `Signal<FieldTree | null>` (late/async forms), `AbstractControl` (migration), and `WritableSignal` (escape hatch) are also supported. Includes `refreshDefaultValue` (re-baseline after a save-and-keep-open) and `restoreDefaultValue`.
580
+ - `createUnsavedChangesGuard` - the router/manual flavor, adding a `canDeactivate` bridge for Angular route guards.
581
+ - Overlay runtime: `overlayRef.registerCloseGuard(guard)` (synchronous veto for pending closes, returns an unregister fn) and `overlayRef.forceClose(result?, source?)` (commit a close bypassing guards). `reference-detached` closes always bypass guards. This is the seam `createOverlayUnsavedChangesGuard` in `@ethlete/components` builds on.
582
+
583
+ ### Patch Changes
584
+
585
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`4d70fb1`](https://github.com/ethlete-io/ethdk/commit/4d70fb1fd173e7e9d25031551f752196abb6f94e) Thanks [@github-actions](https://github.com/apps/github-actions)! - `etAutoSurface` now elevates correctly for content rendered inside an overlay. Projected/portaled content keeps the injector of where it was _declared_ (the trigger location), not the pane it renders into, so an `etAutoSurface` inside a select body, menu, date-picker, etc. resolved its parent surface from the outer trigger context and came out one elevation too low - the same level as the overlay's own panel instead of one above it.
586
+
587
+ `AutoSurfaceDirective` now also consults the root surface-context tracker (which records the innermost open overlay's surface across the portal boundary) and takes whichever parent surface sits higher. Overlay panels that are themselves the overlay's surface (menu, select/date/cascader panels, tooltip, toggletip) opt out via the new `AutoSurfaceDirective.ignoreOverlaySurfaceContext()` so they keep adopting their overlay's elevation rather than stacking above it - their rendered surface is unchanged.
588
+
589
+ - [`eee0451`](https://github.com/ethlete-io/ethdk/commit/eee0451642bfbce97991e539b938fc7c4c84e846) Thanks [@TomTomB](https://github.com/TomTomB)! - `ColorInteractiveDirective`: a readonly control (`aria-readonly="true"`) now keeps its resting accent - hover/active/focus no longer retint it, matching the view-only intent (previously a readonly switch still showed a press color shift).
590
+
591
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`008fca5`](https://github.com/ethlete-io/ethdk/commit/008fca57ad434e6d996b1af21f95c55902f74dcd) Thanks [@github-actions](https://github.com/apps/github-actions)! - `ColorInteractiveHasFocusDirective` (`[etColorInteractiveHasFocus]`) now resolves the theme's **base** accent while a descendant is `:focus-visible`, instead of the `-focus` variant. A container merely mirroring a child's focus (e.g. a form field's frame) should read as the plain accent color; the `-focus` variant remains reserved for an element that is itself focused (`[etColorInteractive]:focus-visible`). Effect: focused form fields now paint their focus border/label in the base accent rather than the focus-adjusted shade.
592
+
593
+ ## 5.0.0-next.30
594
+
595
+ ### Patch Changes
596
+
597
+ - [#3028](https://github.com/ethlete-io/ethdk/pull/3028) [`d8f50c5`](https://github.com/ethlete-io/ethdk/commit/d8f50c530b976390a8e655f3b1a4c0b9eaaae6ab) Thanks [@github-actions](https://github.com/apps/github-actions)! - Hover styles across all interactive components (buttons, chips, form controls, selects, cascader, menu, tabs, calendar, time picker, notification) no longer stick after tapping on touch devices - including the `etColorInteractive`/`etSurfaceInteractive` hover token resolution (guarded by `@media (hover: hover)`).
598
+
599
+ ## 5.0.0-next.29
600
+
601
+ ### Minor Changes
602
+
603
+ - [`2fca323`](https://github.com/ethlete-io/ethdk/commit/2fca323a6beac0299b8e0ec6724fffd4149ad7cd) Thanks [@TomTomB](https://github.com/TomTomB)! - `injectAnimatedBlockSize` can now animate the inline axis too via the new `axes` option (`['block' | 'inline']`, static or signal-based; default `['block']` as before). Used by the cascader panel to grow/shrink its width as columns drill in and out.
604
+
605
+ - [`4b7cf51`](https://github.com/ethlete-io/ethdk/commit/4b7cf51a6f68cdaf364169945586fedc5621cad6) Thanks [@TomTomB](https://github.com/TomTomB)! - Theme generators: pick the default theme at generation time - `--defaultTheme=<name>` on `tailwind-4-color-theme` and `--defaultLightTheme=<name>` / `--defaultDarkTheme=<name>` on `tailwind-4-surface-theme` override any `isDefault` flags in the definitions, so apps sharing one theme definition set (e.g. in a monorepo) can each generate a different default.
606
+
607
+ ### Patch Changes
608
+
609
+ - [`ddb3413`](https://github.com/ethlete-io/ethdk/commit/ddb3413c2673a4f2f513598a208f376b36b7535b) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid items can now be moved with touch: `[etDragHandle]` sets `touch-action: none` on its host while enabled (the browser was claiming touch pointermoves for scrolling and cancelling the gesture), and read-only grids keep normal touch scrolling.
610
+
611
+ - [`06377b6`](https://github.com/ethlete-io/ethdk/commit/06377b6312fd32c7d1f497816fa91a655bf72d19) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay: a color theme provided on the app root component (e.g. `ProvideColorDirective` via `hostDirectives` plus `forceColor()`) now propagates into overlays even when they are opened without a `viewContainerRef`, and updates reactively while the overlay is open.
612
+
613
+ ## 5.0.0-next.28
614
+
615
+ ### Minor Changes
616
+
617
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`9431073`](https://github.com/ethlete-io/ethdk/commit/9431073bb693aa10bbb84d5196597cb2c4b7463f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlays and menus now open on insecure origins (plain-HTTP pages on a LAN IP, not just `localhost`/HTTPS). Id generation used `crypto.randomUUID()`, which is `undefined` outside a secure context, so opening any dialog, sheet, anchored overlay or menu threw and only the backdrop appeared. A new `randomId()` helper in `@ethlete/core` uses `crypto.randomUUID()` when available and falls back to `getRandomValues` otherwise.
618
+
619
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`9431073`](https://github.com/ethlete-io/ethdk/commit/9431073bb693aa10bbb84d5196597cb2c4b7463f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the link flow is now a responsive popover (arrow-anchored on wider screens, a keyboard-pinned top sheet on touch) to edit a link's text and URL, with an open-in-new-tab toggle - replacing the browser `prompt()`. New-tab links persist through the Markdown value as raw HTML (`<a target="_blank" rel="noopener noreferrer">`); ordinary links stay `[text](url)`. `htmlToMarkdown` / `markdownToHtml` in `@ethlete/core` now round-trip `target="_blank"` anchors (sanitized href + forced `rel`). After applying a link the caret moves just past it, with a trailing space added when the link ends the line.
620
+
621
+ ### Patch Changes
622
+
623
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`49591f4`](https://github.com/ethlete-io/ethdk/commit/49591f4e529552fde07ef88b9754bf7c0cd91a3b) Thanks [@github-actions](https://github.com/apps/github-actions)! - `injectAnimatedBlockSize`: growing panels (menu, select) no longer flash at their final size for one frame before the resize animation plays - the animation now starts inside the `ResizeObserver` callback, before the browser paints the new layout.
624
+
625
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d262f59`](https://github.com/ethlete-io/ethdk/commit/d262f596a4f0e3dda315447d0173cba301237c01) Thanks [@github-actions](https://github.com/apps/github-actions)! - `htmlToMarkdown`: boundary whitespace inside bold/italic/strikethrough now serializes outside the delimiters (`<strong> x</strong>` → ` **x**` instead of the invalid `** x**`).
626
+
627
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`00b7c33`](https://github.com/ethlete-io/ethdk/commit/00b7c337e5ae0ac1bfc7186237b1ac2879eb018d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Theming: overlay panes (menu, select) now resolve their color context through passive providers and apply it before the first painted frame.
628
+ - `ProvideColorDirective` gains `resolvedColor` - the color that actually applies at the provider's location, falling through passive providers like the CSS cascade does. `syncWithProvider` uses it, so a passive in-between provider (e.g. a form field's) no longer erases the theme inside a detached overlay pane.
629
+ - The menu and select panels install the context sync during construction instead of in an effect, eliminating a wrong-theme flash during the enter animation.
630
+
631
+ ## 5.0.0-next.27
632
+
633
+ ### Minor Changes
634
+
635
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`1d7aaca`](https://github.com/ethlete-io/ethdk/commit/1d7aacaec10f3d3d7278733ebf5d834e8a89b1f7) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `injectAnimatedBlockSize` - a core util that smoothly animates an element's `block-size` as its
636
+ content resizes (baseline captured on first render so the initial layout never plays as a
637
+ grow-from-0, interruption-safe, respects `prefers-reduced-motion`). `et-menu` and the rich text
638
+ editor's trigger popup now share it, giving a more consistent, smoother resize.
639
+
640
+ - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Add clipboard utilities: `copyToClipboard(text)` writes text to the clipboard (async Clipboard API with an `execCommand('copy')` fallback) and resolves to a success boolean, `readFromClipboard()` resolves to the clipboard text or `null`. Both are SSR-safe and never throw.
641
+
642
+ - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Markdown: GFM table column alignment round-trips - `markdownToHtml` applies `:---` / `:---:` / `---:` separators as `text-align` on every cell of the column, and `htmlToMarkdown` serializes the header cells' `text-align` back into the separator line.
643
+
644
+ - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Markdown: `markdownToHtml` now escapes raw HTML in text (only the deliberate `<u>` / aligned-block passthroughs render, with aligned blocks reduced to a safe inline vocabulary) and rejects script-running URL schemes in links/images. Round-trip fixes and additions:
645
+ - Soft line breaks (`<br>`) survive in paragraphs and block quotes, and degrade to a space in table cells and list items instead of being dropped.
646
+ - Whitespace-flanked delimiters stay literal (`2 * 3 * 4` is no longer italicized), and `_emphasis_` is now supported without firing inside snake_case words.
647
+ - `<div>` boundaries in converted HTML act as paragraph boundaries.
648
+
649
+ ### Patch Changes
650
+
651
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`c68d2b2`](https://github.com/ethlete-io/ethdk/commit/c68d2b2e2e64316bb67bf58ec16d3aad9bd84f34) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: added an opt-in **alignment** tool. Provide `provideRichTextEditorAlignmentTool()` and include `'align'` in the editor's `tools` to get a block-alignment menu (left / center / right / justify) that also works inside table cells. The button reflects the caret's current alignment live. Alignment has no Markdown form, so it persists as a native `text-align` style and round-trips as raw HTML.
652
+
653
+ `@ethlete/core`: `markdownToHtml`/`htmlToMarkdown` now round-trip block elements carrying a `text-align` style (preserved verbatim as native HTML).
654
+
655
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`af660e3`](https://github.com/ethlete-io/ethdk/commit/af660e346204d18ad39cc700c8698bb897fba339) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: added **inline code** and **underline** formatting tools (in the static and selection toolbars, and the default toolbar). Inline code round-trips as `` `code` ``; underline is preserved as native `<u>` since Markdown has no underline form.
656
+
657
+ `@ethlete/core`: `htmlToMarkdown`/`markdownToHtml` now round-trip `<u>` (underline) instead of dropping it.
658
+
659
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`c68d2b2`](https://github.com/ethlete-io/ethdk/commit/c68d2b2e2e64316bb67bf58ec16d3aad9bd84f34) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: list items can now be nested. **Tab** nests the current item under the previous one, **Shift+Tab** lifts it out one level, and **Enter**/**Backspace** on an empty item step out one level at a time (leaving the list entirely only at the top level). Marker styles cycle by depth (disc → circle → square, and decimal → lower-alpha → lower-roman).
660
+
661
+ `@ethlete/core`: `markdownToHtml`/`htmlToMarkdown` now round-trip **nested** lists (two-space indentation per level), instead of flattening them.
662
+
663
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`af660e3`](https://github.com/ethlete-io/ethdk/commit/af660e346204d18ad39cc700c8698bb897fba339) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the toolbar is now configurable. A new `tools` input takes an ordered list of tool tokens (`'bold' | 'italic' | 'strike' | 'heading' | 'bulletedList' | 'numberedList' | 'link' | 'divider'`), and `provideRichTextEditorTools(...)` sets the default for a scope. The block style is now picked from a `heading` menu (Normal / Heading 1–3) shown first in the toolbar, and toolbar buttons are larger and squarer.
664
+
665
+ Form field: read-only text controls (`et-input`, `et-rich-text-editor`) now keep their normal box but drop all interactive affordances - no hover/focus border change, default cursor - so read-only reads as view-only content, distinct from disabled.
666
+
667
+ Icon button: added an `--et-icon-button-border-radius` custom property so an ancestor context (e.g. a toolbar) can square off the otherwise fully-round button.
668
+
669
+ Overlay (`@ethlete/core`): anchored overlay positions accept an optional `boundary`, so an anchored pane (e.g. the editor's selection toolbar) can be kept inside a region and flip instead of overflowing it.
670
+
671
+ ## 5.0.0-next.26
672
+
673
+ ### Minor Changes
674
+
675
+ - [#3018](https://github.com/ethlete-io/ethdk/pull/3018) [`5d26649`](https://github.com/ethlete-io/ethdk/commit/5d266491805f5f0af4a5912a08beab02dafb629b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add an `initials` util and `InitialsPipe` (`| initials`) that extract uppercased initials from a name, capped at a configurable number of characters (defaults to 2).
676
+
677
+ - [#3018](https://github.com/ethlete-io/ethdk/pull/3018) [`5d26649`](https://github.com/ethlete-io/ethdk/commit/5d266491805f5f0af4a5912a08beab02dafb629b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a `slugify` util and `SlugifyPipe` (`| slugify`) that convert a string into a URL-friendly slug - diacritics stripped, lowercased, non-alphanumeric runs collapsed to single hyphens.
678
+
679
+ ## 5.0.0-next.25
680
+
681
+ ### Patch Changes
682
+
683
+ - [#3017](https://github.com/ethlete-io/ethdk/pull/3017) [`83853d6`](https://github.com/ethlete-io/ethdk/commit/83853d6138bc7d0a481b5b982c2a7137b9cc65e6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: anchored overlays with `autoCloseIfReferenceHidden` now close instantly when their anchor is removed, instead of jumping to the viewport corner and animating out from there.
684
+
685
+ ## 5.0.0-next.24
686
+
687
+ ### Minor Changes
688
+
689
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`2f18e43`](https://github.com/ethlete-io/ethdk/commit/2f18e4344759dbbcd17ba0dbeca138f1f7043cdf) Thanks [@github-actions](https://github.com/apps/github-actions)! - Anchored overlays: the `shift` option now also accepts `{ crossAxis?: boolean }` in addition to a boolean. With `crossAxis: true`, an overlay that fits on neither side of its reference is shifted along the placement's cross axis to stay inside the viewport (it may then overlap the reference) instead of overflowing off-screen.
690
+
691
+ Menus enable this by default: a nested submenu near the viewport edge first flips to the other side and, when neither side fits, slides over its parent menu - matching native OS menu behavior - instead of being cut off by the viewport.
692
+
693
+ The `size` middleware (`autoResize`) now runs after `shift` instead of before it, so `--et-overlay-max-width` / `--et-overlay-max-height` are measured from the pane's shifted position. Previously a cross-axis-shifted pane had its max size capped to the unshifted leftover space, squeezing e.g. a submenu to a sliver instead of letting it keep its width while overlapping its parent.
694
+
695
+ ### Patch Changes
696
+
697
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`2f18e43`](https://github.com/ethlete-io/ethdk/commit/2f18e4344759dbbcd17ba0dbeca138f1f7043cdf) Thanks [@github-actions](https://github.com/apps/github-actions)! - Animations: fix overlays getting stuck in the DOM in an invisible but click-blocking state when their leave transition never reported completion.
698
+
699
+ When several anchored overlays close at once (e.g. clicking an item inside a nested menu closes the whole menu tree), destroying an ancestor pane shifts the anchored position of a still-leaving descendant. The browser then cancels and restarts the running transition, so its end event arrives either flagged as cancelled or under a stale transition id - and the animated lifecycle waited forever for an event that could no longer arrive, leaving the pane orphaned at `opacity: 0` while still intercepting pointer events. The lifecycle now treats the transition as settled once no animation is running anymore, matching the fallback the interrupted-transition path already had, so the overlay is torn down reliably.
700
+
701
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`3b359e5`](https://github.com/ethlete-io/ethdk/commit/3b359e52c5efa1cd9b0e79216fc578525aafa8e8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Tailwind surface & color theme generators: fix the dynamic `--color-*-surface-*` /
702
+ `--color-*-theme-*` variables not resolving per scope. They were emitted only inside
703
+ `@theme`, which lands on `:root`, so `rgb(var(--<runtime>-surface-background))` resolved
704
+ once against the root surface and inherited that concrete color into descendants. As a
705
+ result `bg-<prefix>-surface-*` / `bg-<prefix>-theme-*` utilities ignored nested
706
+ `.<runtime>-surface--*` / `.<runtime>-color--*` scopes (e.g. an elevated surface would
707
+ still paint the root background). The dynamic colors are now also re-declared on each
708
+ surface/color selector in the alias block, so the utilities resolve against the nearest
709
+ scope while still being generated from `@theme`.
710
+
711
+ ## 5.0.0-next.23
712
+
713
+ ### Major Changes
714
+
715
+ - [`11ce5e1`](https://github.com/ethlete-io/ethdk/commit/11ce5e1795249a6b975dab2eab7e8e2a9c9bc979) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay: replace the `inputBindings` / `outputBindings` config objects with a
716
+ single `bindings` array using Angular's native binding API. Bind overlay
717
+ component inputs, outputs, and two-way models with `inputBinding`,
718
+ `outputBinding`, and `twoWayBinding` from `@angular/core`.
719
+
720
+ ## 5.0.0-next.22
721
+
722
+ ### Minor Changes
723
+
724
+ - [`ea1eb65`](https://github.com/ethlete-io/ethdk/commit/ea1eb656b4f1144602830a3cd27a521ca50a9d06) Thanks [@TomTomB](https://github.com/TomTomB)! - Theming: add `AutoSurfaceDirective` (`etAutoSurface`), which resolves the surface
725
+ theme one elevation above its parent (or an explicitly provided) surface context
726
+ and applies it through a host `ProvideSurfaceDirective`. Meant to be used as a
727
+ host directive on components that render inside a detached overlay pane, where
728
+ surface context can't cascade through the DOM.
729
+
730
+ Tooltip and toggletip now use `AutoSurfaceDirective` as a host directive instead
731
+ of duplicating the auto-surface resolution logic. No change to their rendered
732
+ surface.
733
+
734
+ ## 5.0.0-next.21
735
+
736
+ ### Minor Changes
737
+
738
+ - [#3013](https://github.com/ethlete-io/ethdk/pull/3013) [`3f2eaad`](https://github.com/ethlete-io/ethdk/commit/3f2eaadf324bc6962a78efd2be1b7935106cc423) Thanks [@github-actions](https://github.com/apps/github-actions)! - Enrich the drag and resize gesture events:
739
+ - `DragHandleDirective`'s `dragStarted` output now emits a `DragStartEvent` with the `clientX` / `clientY` of the initial pointerdown (previously it emitted `void`).
740
+ - `DragMoveEvent` now includes `totalDx` / `totalDy`, the cumulative delta from the pointerdown position, alongside the per-step deltas.
741
+ - `ResizeMoveEvent` now includes `clientX` / `clientY`.
742
+
743
+ These give consumers absolute pointer information without having to accumulate the per-step deltas themselves.
744
+
745
+ - [#3013](https://github.com/ethlete-io/ethdk/pull/3013) [`3f2eaad`](https://github.com/ethlete-io/ethdk/commit/3f2eaadf324bc6962a78efd2be1b7935106cc423) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: anchored positioning now accepts a `VirtualElement` (from `@floating-ui/dom`) as the `referenceElement`, not just an `HTMLElement`. This makes it possible to anchor an overlay to an arbitrary point or region - for example positioning a context menu at the pointer. When a virtual reference is used, `mirrorWidth` and origin-element based behaviors gracefully fall back since there is no real element to measure.
746
+
747
+ - [#3013](https://github.com/ethlete-io/ethdk/pull/3013) [`3f2eaad`](https://github.com/ethlete-io/ethdk/commit/3f2eaadf324bc6962a78efd2be1b7935106cc423) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `injectPrefersReducedMotion`, a signal that reflects the `(prefers-reduced-motion: reduce)` media query so components can opt out of animations for users who prefer reduced motion.
748
+
749
+ ### Patch Changes
750
+
751
+ - [`4e9f2b4`](https://github.com/ethlete-io/ethdk/commit/4e9f2b4d12335fafef192350aef8ffc584996a91) Thanks [@TomTomB](https://github.com/TomTomB)! - Remove the now-redundant `changeDetection: ChangeDetectionStrategy.OnPush` declaration (and its `ChangeDetectionStrategy` import) from all components. OnPush is the default change detection strategy since Angular 22, so this is a no-op cleanup with no behavioral change.
752
+
753
+ ## 5.0.0-next.20
754
+
755
+ ### Minor Changes
756
+
757
+ - [#3007](https://github.com/ethlete-io/ethdk/pull/3007) [`74974ff`](https://github.com/ethlete-io/ethdk/commit/74974ff36e64b80c750358441d8f5e8647557bdc) Thanks [@github-actions](https://github.com/apps/github-actions)! - Support satisfies for theme definitions
758
+
759
+ - [#3007](https://github.com/ethlete-io/ethdk/pull/3007) [`6539c72`](https://github.com/ethlete-io/ethdk/commit/6539c727c6d56ed9add30fa41039a0880d5c5121) Thanks [@github-actions](https://github.com/apps/github-actions)! - Gave surface theming the same treatment as color theming:
760
+ - Added an augmentable `EthleteSurfaceThemeNameRegistry` (mirroring `EthleteColorThemeNameRegistry`), so `etProvideSurface` and `provideSurfaceThemesWithTailwind4` can be narrowed to your app's actual surface theme names instead of a plain `string`.
761
+ - `tailwind-4-surface-theme` now also generates a `.d.ts` (next to the CSS output by default, or at a custom `typesOutputPath`) that augments the registry automatically.
762
+ - Fixed `tailwind-4-surface-theme` failing to parse individual surface theme objects written with `satisfies X` instead of `as const`, matching the same fix in `tailwind-4-color-theme`.
763
+ - Added a `runtimePrefix` option to `tailwind-4-surface-theme`, decoupling the Tailwind utility surface prefix from the runtime theme-swap prefix used by `ProvideSurfaceDirective`/`etProvideSurface` (the `.et-surface--<name>` selectors and `--et-surface-*` CSS variables) - the same fix already applied to `tailwind-4-color-theme`. Defaults to `prefix`, so existing usages are unaffected.
764
+
765
+ - [#3007](https://github.com/ethlete-io/ethdk/pull/3007) [`6539c72`](https://github.com/ethlete-io/ethdk/commit/6539c727c6d56ed9add30fa41039a0880d5c5121) Thanks [@github-actions](https://github.com/apps/github-actions)! - `tailwind-4-color-theme` now also generates a `.d.ts` file (next to the CSS output by default, or at a custom `typesOutputPath`) that augments `EthleteColorThemeNameRegistry` with your theme names. Previously this had to be hand-written; now it's kept in sync automatically whenever you regenerate. Also fixed the generator failing to parse individual theme objects written with `satisfies X` instead of `as const` (e.g. `export const RED = { ... } satisfies ColorTheme;`).
766
+
767
+ ### Patch Changes
768
+
769
+ - [#3009](https://github.com/ethlete-io/ethdk/pull/3009) [`9a029a5`](https://github.com/ethlete-io/ethdk/commit/9a029a551b5e2d8d30cba5382384dcbd47565f66) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix `setupScrollRestoration` scrolling to top only after the new route had already painted under zoneless change detection, causing a visible jump from the previous scroll offset on tall pages. It is now driven synchronously off `router.events` (`NavigationEnd` / `NavigationSkipped`) instead of going through signal interop plus `debounceTime`, so `scrollTop = 0` lands before the first paint of the new route. All existing behavior (query param triggers, fragment scrolling, `routerDisableScrollTop`) is unchanged.
770
+
771
+ ## 5.0.0-next.19
772
+
773
+ ### Minor Changes
774
+
775
+ - [#3006](https://github.com/ethlete-io/ethdk/pull/3006) [`f6b9c10`](https://github.com/ethlete-io/ethdk/commit/f6b9c10b9702722d55a8a815ad9539a92c65e20a) Thanks [@TomTomB](https://github.com/TomTomB)! - Add `runtimePrefix` option to the `tailwind-4-color-theme` generator. This decouples the Tailwind utility color prefix (`prefix`, e.g. `bg-fut-primary`) from the runtime theme-swap prefix used by `ProvideColorDirective`/`etProvideColor` (the `.et-color--<name>` selectors and `--et-color-primary` CSS variables). Previously both were driven by the same `prefix` value, which broke consumers whose Tailwind utility naming convention differs from their runtime theme-switching convention. `runtimePrefix` defaults to `prefix`, so existing usages are unaffected.
776
+
777
+ ### Patch Changes
778
+
779
+ - [#3003](https://github.com/ethlete-io/ethdk/pull/3003) [`e7f482b`](https://github.com/ethlete-io/ethdk/commit/e7f482bc170b27374c03cd84b1a5df23ceda9bf6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix markdown headings not being parsed when directly followed by a list or paragraph without a blank line
780
+
781
+ ## 5.0.0-next.18
782
+
783
+ ### Patch Changes
784
+
785
+ - [`d7c4fbe`](https://github.com/ethlete-io/ethdk/commit/d7c4fbe23359ebf68e4f769ac6eda05ce01f90c8) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix broken heading support in markdown utils
786
+
787
+ ## 5.0.0-next.17
788
+
789
+ ### Minor Changes
790
+
791
+ - [`edea44b`](https://github.com/ethlete-io/ethdk/commit/edea44bf1c494420f02b545202f4b24db9a6395c) Thanks [@TomTomB](https://github.com/TomTomB)! - Update to angular 22
792
+
793
+ ## 5.0.0-next.16
794
+
795
+ ### Minor Changes
796
+
797
+ - [#2999](https://github.com/ethlete-io/ethdk/pull/2999) [`0232803`](https://github.com/ethlete-io/ethdk/commit/0232803afcee04ddc5d8c6ab57a8e920a908e1ac) Thanks [@github-actions](https://github.com/apps/github-actions)! - Update overlay runtime to support stategies
798
+
799
+ ## 5.0.0-next.15
800
+
801
+ ### Patch Changes
802
+
803
+ - [#2995](https://github.com/ethlete-io/ethdk/pull/2995) [`05da5f2`](https://github.com/ethlete-io/ethdk/commit/05da5f2c9ac78907f8be5003690332eea1f99ff8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix `injectRoute`, `injectUrl` and the `injectRouterState` based signals (`injectPathParams`, `injectQueryParams`, `injectRouteData`, etc.) returning the previous route when read synchronously inside a component constructor during navigation. They now read the already committed router state instead of waiting for the `NavigationEnd` event.
804
+
805
+ ## 5.0.0-next.14
806
+
807
+ ### Minor Changes
808
+
809
+ - [`7dcbb8e`](https://github.com/ethlete-io/ethdk/commit/7dcbb8e3f3823728bc370fb89d1a89ee831e779b) Thanks [@TomTomB](https://github.com/TomTomB)! - Add utils for converting between markdown and html
810
+
811
+ ## 5.0.0-next.13
812
+
813
+ ### Patch Changes
814
+
815
+ - [`8f77e78`](https://github.com/ethlete-io/ethdk/commit/8f77e78d39a8fa91b9ccb8e038e9b3f62a9f1b94) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix theme class name generation for legacy tailwind 3 themes
816
+
817
+ ## 5.0.0-next.12
818
+
819
+ ### Patch Changes
820
+
821
+ - [`b73a127`](https://github.com/ethlete-io/ethdk/commit/b73a127002a06e3aa0c4e7e977b1ad1f3e04e7e6) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump yet again, final one for sure, pinky promise
822
+
823
+ ## 5.0.0-beta.11
824
+
825
+ ### Patch Changes
826
+
827
+ - [`ddb5d09`](https://github.com/ethlete-io/ethdk/commit/ddb5d09e4bc56e18cc8c228aa78a200441e7a766) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump to beta
828
+
829
+ - Updated dependencies [[`ddb5d09`](https://github.com/ethlete-io/ethdk/commit/ddb5d09e4bc56e18cc8c228aa78a200441e7a766)]:
830
+ - @ethlete/types@2.0.0-beta.4
831
+
832
+ ## 5.0.0-next.10
833
+
834
+ ### Patch Changes
835
+
836
+ - [`a690217`](https://github.com/ethlete-io/ethdk/commit/a6902172efd9bd1956a16237e79acbfbd816d946) Thanks [@TomTomB](https://github.com/TomTomB)! - Version bump only
837
+
838
+ ## 5.0.0-next.9
839
+
840
+ ### Minor Changes
841
+
842
+ - [`5d1d3ac`](https://github.com/ethlete-io/ethdk/commit/5d1d3accbd4a7657bc50cdc0653a7ca24fe761e2) Thanks [@TomTomB](https://github.com/TomTomB)! - Add overlay runtime
843
+
844
+ - [`5d1d3ac`](https://github.com/ethlete-io/ethdk/commit/5d1d3accbd4a7657bc50cdc0653a7ca24fe761e2) Thanks [@TomTomB](https://github.com/TomTomB)! - Cleanup surface and color theming
845
+
846
+ ## 5.0.0-next.8
847
+
848
+ ### Minor Changes
849
+
850
+ - [#2958](https://github.com/ethlete-io/ethdk/pull/2958) [`8ecdfc0`](https://github.com/ethlete-io/ethdk/commit/8ecdfc00d785b0b535601b5d95ca7e2cd55455b6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add surface theming support alongside color theming
851
+
3
852
  ## 5.0.0-next.7
4
853
 
5
854
  ### Patch Changes