@ethlete/components 1.0.0-next.31 → 1.0.0-next.33

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,392 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0-next.33
4
+
5
+ ### Major Changes
6
+
7
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`df55f32`](https://github.com/ethlete-io/ethdk/commit/df55f3237f2fc7234165b83ed564df78060ea133) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: layouts are opt-in values you register, so an app bundles only the renderers it draws with.
8
+ Pass factories to `provideBracketConfig({ layouts })` or the `layouts` input on either host. The
9
+ `layout` input and `BracketConfig.swiss` are gone - mirrored is a layout, swiss options live on
10
+ `swissBracketLayout()` - and an unregistered mode throws `ET3413`.
11
+
12
+ ```diff
13
+ - provideBracketConfig({ swiss: { colors } });
14
+ - <et-bracket layout="mirrored" [source]="source()" />
15
+ + provideBracketConfig({ layouts: [mirroredSingleEliminationBracketLayout(), swissBracketLayout({ colors })] });
16
+ + <et-bracket [source]="source()" />
17
+ ```
18
+
19
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`beec05f`](https://github.com/ethlete-io/ethdk/commit/beec05f70be10fcded054d825320d93f96c6b414) Thanks [@github-actions](https://github.com/apps/github-actions)! - Breadcrumb: collapsing the trail is now opt-in. Import `BREADCRUMB_COLLAPSE_IMPORTS` and apply `etBreadcrumbCollapse` to the breadcrumb, the outlet, or any ancestor to keep the overflow control; without it the trail is clipped and the toggletip's overlay runtime stays out of your bundle.
20
+
21
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`beec05f`](https://github.com/ethlete-io/ethdk/commit/beec05f70be10fcded054d825320d93f96c6b414) Thanks [@github-actions](https://github.com/apps/github-actions)! - Grid: `GridDebugComponent` moved out of `GRID_IMPORTS` into `GRID_DEBUG_IMPORTS`, so the development-only overlay no longer ships in production bundles. Import that barrel where you use `<et-grid-debug />`.
22
+
23
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`caa8c92`](https://github.com/ethlete-io/ethdk/commit/caa8c9286c6e25c298995525e91159e9ad04cd0d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query error: labels default to English only — the German status tables are no longer bundled or auto-selected by locale. Keep the old behavior with `provideQueryErrorLabels(queryErrorLabelsForLocale)` (or `GERMAN_QUERY_ERROR_LABELS`); the `migrate-query-error-labels` generator finds affected sites.
24
+
25
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`6be90f2`](https://github.com/ethlete-io/ethdk/commit/6be90f28518a969607202ebc8d99365f3506bae5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the link editor popover is opt-in via `provideRichTextEditorLinkEditor()` — without
26
+ it the `link` tool falls back to `prompt()`. Run
27
+ `nx g @ethlete/components:migrate-rich-text-editor-link-editor` to find affected editors.
28
+
29
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`a0e5424`](https://github.com/ethlete-io/ethdk/commit/a0e5424be31a2031b566e4cdf150275ab7bd4f37) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the `'heading'` block-style menu is now an opt-in tool -
30
+ `provideRichTextEditorHeadingTool()`, like the align/table/image tools. It stays in the default toolbar,
31
+ so that call is all it takes; without it no block-style control renders (Markdown `#` autoformat is
32
+ unaffected). It was the only default tool needing the menu system, worth 8.5 kB gz to every editor.
33
+
34
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`2c0d3c9`](https://github.com/ethlete-io/ethdk/commit/2c0d3c9f78bfceed19dd49b01f934d1cfebc83c2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Scrollable: the buttons, dots, drag and snap are now opt-in directives on the `<et-scrollable>` itself, so a plain track no longer bundles them. Replace `renderButtons` / `buttonPosition` / `stickyButtons` with `[etScrollableButtons]` (`SCROLLABLE_NAVIGATION_IMPORTS`), `renderNavigation` with `etScrollableNavigation`, `snap` / `snapOrigin` / `cursorDragScroll` with `etScrollableSnap` / `etScrollableDrag` (`SCROLLABLE_DRAG_IMPORTS`), and `darkenNonIntersectingItems` with `etScrollableDarken` (`SCROLLABLE_DARKEN_IMPORTS`). `ScrollableMasksDirective` / `ScrollableButtonsDirective` / `ScrollableNavigationDirective` are renamed to `…Component`; the directive names now belong to the opt-ins.
35
+
36
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`beec05f`](https://github.com/ethlete-io/ethdk/commit/beec05f70be10fcded054d825320d93f96c6b414) Thanks [@github-actions](https://github.com/apps/github-actions)! - Stream: `STREAM_IMPORTS` now holds only the shared consent, loading, error and slot pieces. Add the barrel of each platform you embed (`STREAM_YOUTUBE_IMPORTS`, `STREAM_TWITCH_IMPORTS`, … `STREAM_SOOP_IMPORTS`) and `STREAM_PIP_IMPORTS` for picture-in-picture - or `STREAM_ALL_IMPORTS` to keep the old contents. A YouTube-only app saves ~5 kB gz.
37
+
38
+ ### Minor Changes
39
+
40
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`1f528bd`](https://github.com/ethlete-io/ethdk/commit/1f528bd629b9c4f1cc5160d87745ad927a02203d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Accordion: add `preventCloseLast` to the group - the header can no longer collapse the last open
41
+ panel, so paired with `autoCloseOthers` the group behaves like a radio set. `close()`, `closeAll()`
42
+ and `[(isOpen)]` still collapse it.
43
+
44
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`c796f12`](https://github.com/ethlete-io/ethdk/commit/c796f123982b7e93dc756b9926f8b5e6e1788a41) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: add `density="compact"` - narrower columns, and match cards that answer with a code and a
45
+ score, for a full bracket inside an article column. Layout inputs are now overrides on top of it, so
46
+ an unbound input resolves through the preset instead of a fixed default.
47
+
48
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`568e937`](https://github.com/ethlete-io/ethdk/commit/568e9379c7ba2d4176f29d7a7939d4c5a7e1bfa7) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: `mirroredDoubleEliminationBracketLayout()` draws double elimination as stacked winners and
49
+ losers blocks, each folded around its own centre on a shared middle column, with the deciding rounds
50
+ chained below. Also fixes hovering a card lighting the wrong participant's journey, and a mirrored
51
+ bracket drawing its way-back connectors backwards.
52
+
53
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`35d4f03`](https://github.com/ethlete-io/ethdk/commit/35d4f03e81d7f916e7057d8525372176fa463f27) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: journeys are now per participant. Hovering one side of a card lights that participant's path
54
+ alone and marks where they went out, and `[(focusedParticipantId)]` pins a path for touch and keyboard
55
+ - driven from a control of yours, cleared with `Escape`. Match cards mark each side with
56
+ `data-participant-id`.
57
+
58
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`a8dd388`](https://github.com/ethlete-io/ethdk/commit/a8dd388e8846cf6a19cac7645d8f9b24207401d3) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: add `<et-bracket-rounds-list>`, the same source drawn as a vertical round-by-round list
59
+ (sectioned for double elimination), plus `bracketNaturalWidth()` / `bracketFitsWidth()` to decide when
60
+ to swap to it on a narrow screen.
61
+
62
+ - [#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)! - Breadcrumb: add `etBreadcrumbSeo` (`BREADCRUMB_SEO_IMPORTS`) - opt-in `schema.org` **BreadcrumbList**
63
+ JSON-LD, which is what earns a site the breadcrumb line in a search result. Crumbs state their own
64
+ `name` and `url` through new inputs on `etBreadcrumbItemTemplate`; loading and unnamed crumbs are
65
+ skipped, and the last crumb needs no `url`.
66
+
67
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`06a6ba2`](https://github.com/ethlete-io/ethdk/commit/06a6ba2889124267c05f0b0432578aaa2c8794ca) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: `comparisonStart` / `comparisonEnd` band a compared period under the selection - the
68
+ analytics "vs. the previous 30 days" pattern - and the date range input forwards them. It is
69
+ presentation only, so picking never writes to it. Cells expose `data-comparison-band`, and
70
+ comparisons band at the calendar's `precision`.
71
+
72
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`d97e71a`](https://github.com/ethlete-io/ethdk/commit/d97e71a9e0ee6f53cb71c2b05f8dae64fcdb92a5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: the header is replaceable, and now moves with the grid it names.
73
+
74
+ - `ng-template etCalendarHeader` projected into `et-calendar` renders instead of the default header,
75
+ with the headless directive as its context; `et-calendar` also exposes it as `headless`.
76
+ - The label travels with the rows, the caret no longer swings with the label's width, grids crossfade
77
+ rather than cut, and the picker's bottom sheet keeps one height.
78
+ - Fixed: the calendar warned NG0956 twice per navigation in dev.
79
+
80
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8ff5062`](https://github.com/ethlete-io/ethdk/commit/8ff506229e889dda5389404b187b517fe6158baa) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: `monthsShown` renders several months side by side - the classic two-month range picker,
81
+ where a range spanning the turn of a month is one gesture. The span shares one keyboard scope, one
82
+ selection and a band that runs through the seam, and stepping moves by a single month. Headless:
83
+ `monthPages()`. The date inputs deliberately don't forward it.
84
+
85
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8692c2c`](https://github.com/ethlete-io/ethdk/commit/8692c2c8d00577ec701e9fa50ac2487be8a54ef0) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: `mode="multiple"` selects a set of unrelated dates into its own `multipleValue` model
86
+ (`Date[]`, kept ascending). Picking a date again removes it, nothing bands or previews, and the grid
87
+ is `aria-multiselectable`. It composes with `precision`. The date inputs have no equivalent - their
88
+ value is one wire string.
89
+
90
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`35c463c`](https://github.com/ethlete-io/ethdk/commit/35c463cc17c2a7ea1e0bfa791371c10cf92fbe18) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar and date inputs: `precision` (`'day' | 'month' | 'year'`) makes them month or year pickers -
91
+ picking in that grid writes the value (the start of the unit) instead of drilling further, and ranges
92
+ compare, band and complete at the same unit. On `et-date-input` / `et-date-range-input` it also
93
+ derives the text format, so `displayFormat` now defaults to `null`.
94
+
95
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`c41beec`](https://github.com/ethlete-io/ethdk/commit/c41beec18d6920eb154ffc84a1393fd0b18ea8b6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: `rangeSelectionStrategy` decides what a pick means in `range` mode, forwarded by the date
96
+ range input. A strategy is two pure functions of `(date, currentRange)` - `select`, and the optional
97
+ `preview` for what to band on hover. `createWeekRangeStrategy({ weekStartsOn })` snaps to whole weeks
98
+ and `createFixedLengthRangeStrategy({ days })` makes every pick a complete span.
99
+
100
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`d5012e1`](https://github.com/ethlete-io/ethdk/commit/d5012e10ce81514c62eb1c1b76784a30a6d6b6de) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `startAt` to the calendar: where an empty calendar opens and which day takes the
101
+ initial roving focus (e.g. next month for a booking form). A selection or an explicit
102
+ `activeMonth` still wins over it, and without any of the three the calendar opens on
103
+ today. `et-date-input`, `et-date-range-input` and `et-date-time-input` forward it to
104
+ their picker calendar.
105
+
106
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`d9b05fc`](https://github.com/ethlete-io/ethdk/commit/d9b05fc92ca568a4d57e0711a6a0bab6db3a0e0c) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: the header label is a button that zooms the day grid out to months and then years, and
107
+ picking one drills back in; `startView` decides where it opens, forwarded by the three date inputs. A
108
+ coarse pick only navigates, reported as `monthSelect` / `yearSelect`. `min`/`max`/`dateFilter` and the
109
+ keyboard model reach every view, and the new `dateClass` puts classes of your own on any cell.
110
+
111
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`cbd68e0`](https://github.com/ethlete-io/ethdk/commit/cbd68e0287667b9cfb9b3138d0508378fffea0b5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Calendar: `weekNumbers` renders a leading week-number column on the day grid, forwarded by the date,
112
+ date-range and date-time inputs. The numbering is localized rather than always ISO, so it names the
113
+ rows actually on screen. Each number is its row's `rowheader`, and `--et-calendar-week-number-size`
114
+ sizes the column.
115
+
116
+ - [#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
117
+ paint with `transition="wipe"`, and no observer work during a scroll. Snapping is native CSS scroll
118
+ snap (`ScrollableDirective.suspendSnap()` holds it off while something writes an offset itself), and
119
+ the built-in transitions run as composited keyframes. New `transition="custom"` fills
120
+ `--et-carousel-slide-progress` without applying an effect, for CSS of your own; new
121
+ `--et-carousel-wipe-dim-color`; `signalElementChildren` / `signalElementScrollState` take a
122
+ `mutations` option to narrow their observers.
123
+
124
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`cb1c5b0`](https://github.com/ethlete-io/ethdk/commit/cb1c5b0ee5a4cf735b8846364fd06bed77b59018) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: the placeholder cards are now real - compact `et-match-card` cells, a hero final card with a
125
+ champion line, heading round headers (`roundHeaderLevel`) and a labelled continue cell. They need
126
+ `provideBracketConfig({ matchNormalizer })` to read your match data (`normalizeEthleteBracketMatch` ships
127
+ for Ethlete feeds), and `finalColumnWidth` / `finalMatchHeight` now default to `360` / `200` to fit them.
128
+
129
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`9057738`](https://github.com/ethlete-io/ethdk/commit/90577383b754af4789f034cee5199bf2b56f8203) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add the match domain behind `MATCH_CARD_IMPORTS`: `<et-match-card>` (one card, three container-query layouts -
130
+ dense row, featured card, wide row; `size` pins one; put it on an `<a>` to make the whole card the link),
131
+ `<et-match-participant>`, the headless `etMatchCard` directive with its score/meta/game-score parts,
132
+ `provideMatchLabels()`, and `normalizeEthleteMatch()` - cards take a `NormalizedMatch`, so any backend maps in
133
+ with a plain adapter.
134
+
135
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`0d30c38`](https://github.com/ethlete-io/ethdk/commit/0d30c385db868f70c92f2b0db670e99dd645177d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Match card: live scores now roll when they change - old value out, new value in, with a flash on the side
136
+ that scored - plus a `scoreChange` output carrying the side and delta for your own effects. Only while the
137
+ match is live, never on first render, instant under reduced motion; `animateScoreChanges` turns it off.
138
+
139
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`fd8ac2f`](https://github.com/ethlete-io/ethdk/commit/fd8ac2f546fd8ac8cab61b249dccf01089b4b18e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add the standings table behind `STANDINGS_IMPORTS`: `<et-standings>` draws a real `<table>` from
140
+ `NormalizedStandingRow`s (any backend maps in; `normalizeEthletePlacement` ships for Ethlete feeds), bands
141
+ position `zones` in your own color themes and draws their legend from the same config, drops columns rather
142
+ than scrolling on narrow widths, and can single out one row.
143
+
144
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`26a987f`](https://github.com/ethlete-io/ethdk/commit/26a987f9972d25156dfec4753170b06b79b74793) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form field: an `[etIcon]` projected into `[etInputPrefix]` / `[etInputSuffix]` is now sized by the
145
+ shell (`--et-form-field-affix-icon-size`, `16px`) - no size class needed, matching the other
146
+ in-field icons.
147
+
148
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`d97e71a`](https://github.com/ethlete-io/ethdk/commit/d97e71a9e0ee6f53cb71c2b05f8dae64fcdb92a5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Icon: add a `label` input. An icon stays `aria-hidden` by default - it usually repeats the text beside
149
+ it - but a lone status glyph is the content, and `label` turns the host into a named `role="img"` so
150
+ the meaning survives for a screen reader.
151
+
152
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`d97e71a`](https://github.com/ethlete-io/ethdk/commit/d97e71a9e0ee6f53cb71c2b05f8dae64fcdb92a5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Menu: add `loop` (default `true`, the current behaviour). Turn it off and the arrow keys stop at the
153
+ ends instead of wrapping, which reads better in a long menu. A menu with a search field is
154
+ unaffected - its ends hand focus back to the field either way.
155
+
156
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`f0082cd`](https://github.com/ethlete-io/ethdk/commit/f0082cd3a6e3ed20fc534b02d25e260f4e1d8600) Thanks [@github-actions](https://github.com/apps/github-actions)! - Notification upgrades:
157
+
158
+ - `manager.promise(work, { loading, success, error })` follows a promise, an observable or an `@ethlete/query` query in one toast.
159
+ - `id` in the config replaces a live notification instead of stacking a duplicate.
160
+ - Status icons (overridable per notification via `icon`), plus `secondaryAction` for an action pair.
161
+ - Swipe/flick a notification away; opt out with `swipeToDismiss: false`.
162
+
163
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`0e08bc2`](https://github.com/ethlete-io/ethdk/commit/0e08bc23450a58635dfae906d9fefc96f18a359b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Pagination: add `<et-page-size-select>` (`PAGE_SIZE_SELECT_IMPORTS`) - the "Items per page" control
164
+ that completes the Material-style controls row beside a compact paginator. A native `<select>`, so it
165
+ pulls in nothing; a separate component, because page size is the app's state rather than the
166
+ paginator's. Changing the size deliberately does not reset the page. Two new label keys, `pageSize`
167
+ and `pageSizeOption`.
168
+
169
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`38b3c2b`](https://github.com/ethlete-io/ethdk/commit/38b3c2b6c1f6f54efcac63f4f991b682dfd1485e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: undo/redo over the Markdown value, replacing the browser's native
170
+ `contenteditable` history (which could restore states the value never had). Ctrl/Cmd+Z, Ctrl+Y and
171
+ the platform's own undo all route into it, plus new `'undo'` / `'redo'` toolbar tools that lead the
172
+ default toolbar. Typing goes back word by word; a paste, autoformat or tool rewrite in one step.
173
+
174
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`1c7ad03`](https://github.com/ethlete-io/ethdk/commit/1c7ad0373cf8cf7845be1d3337bbafe71eec9fc0) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: `provideRichTextEditorImageTool({ upload })` embeds images as `![alt](url)` - pick,
175
+ paste or drop a file, uploaded by your handler (a promise, an observable, or a `createDropzoneUpload`
176
+ config for real progress), with a placeholder that never touches the value and a popover for alt text.
177
+ Tool definitions gained `paste`, `drop` and `click` content hooks; without the tool, pasted image
178
+ files are refused rather than becoming `blob:` URLs in the value.
179
+
180
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`48fbe62`](https://github.com/ethlete-io/ethdk/commit/48fbe62fefe815a59d1b41e6fbc7055c88537e58) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: pasted text that spells a token out - `#First name`, the trigger char plus an
181
+ item's label or id - comes back as a real chip, for HTML and plain-text clipboards alike (opt out with
182
+ `parsePastedTokens="false"`). A trigger with a static `items` list no longer needs `resolveItem` to
183
+ render chip labels.
184
+
185
+ - [#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
186
+ typed as `> ` / ` ``` `), both in the default toolbar. Quotes nest with Tab/Shift+Tab; a code block
187
+ holds literal text, so the marks that can't serialize inside one disable themselves. `htmlToMarkdown`
188
+ / `markdownToHtml` now round-trip nested quotes (`>>`).
189
+
190
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`b3673f3`](https://github.com/ethlete-io/ethdk/commit/b3673f32015277a57be0887e43775869dd72b3ca) Thanks [@github-actions](https://github.com/apps/github-actions)! - Selection lists: add `<et-checkbox-group-select-all>`, the prebuilt tri-state select-all row that had
191
+ to be hand-rolled until now - a real `role="checkbox"` with `aria-checked="mixed"`, taking its text
192
+ from the new shared `selectAll` form label. Also `orientation="horizontal"` on `et-checkbox-group` and
193
+ `et-radio-group`, flowing the options in a wrapping row.
194
+
195
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`84a8d00`](https://github.com/ethlete-io/ethdk/commit/84a8d005838660be71cac158769f659c670465e8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Sliders: `orientation="vertical"` turns `et-slider` / `et-range-slider` (and the headless `etSlider` /
196
+ `etRangeSlider`) into a bottom→up slider, its length set by `--et-slider-vertical-size`. `marks`
197
+ renders ticks on the track - `true` for one per `step`, or an array of `{ value, label? }` stops - and
198
+ `snapToMarks` moves commits and keyboard steps mark to mark instead of along the `step` grid.
199
+
200
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`41c2683`](https://github.com/ethlete-io/ethdk/commit/41c268395cfa476024a3ef4680eacda0660cd9ba) Thanks [@github-actions](https://github.com/apps/github-actions)! - Table: add CSV export - `TABLE_CSV_EXPORT_IMPORTS` / `etTableCsvExport` for a button of your own, or
201
+ `injectTableCsvExport()` / `tableToCsv()` from TypeScript. It writes the visible columns and the
202
+ table's own rows by default (`exportValue` gives a column its text form), `rows` also takes a provider
203
+ function, `tableCsvRowsFromPages({ fetchPage })` walks a paginated endpoint, and `file` saves a CSV the
204
+ server built instead. A server-paginated table that would silently export a single page is a dev-mode
205
+ error (`ET3506`) unless you pass `partial: true`.
206
+
207
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`e5ffd4d`](https://github.com/ethlete-io/ethdk/commit/e5ffd4d031e956e12b0d32f9cdee9dc843832c32) Thanks [@github-actions](https://github.com/apps/github-actions)! - Table: add `etTableInlineEdit` (`TABLE_INLINE_EDIT_IMPORTS`) - inline cell editing. Mark a column
208
+ `editable` and give it an `etTableCellEdit` template, whose context is the draft as a signal-forms
209
+ field, so any of the library's controls is an editor with a plain `[formField]` binding. Double-click
210
+ or `Enter` starts, `Enter` saves, `Escape` restores, `Tab` saves and moves on; `cellCommit` reports
211
+ `{ row, column, previous, next }` and the mutation stays yours.
212
+
213
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`040bbb3`](https://github.com/ethlete-io/ethdk/commit/040bbb3559b2c1705b2358a5c7158f491dce4a67) Thanks [@github-actions](https://github.com/apps/github-actions)! - Table: add `etTableKeyboardNav` (`TABLE_KEYBOARD_NAV_IMPORTS`) - arrow-key navigation over the body's
214
+ cells following the ARIA grid pattern, with Home/End, Ctrl+Home/End and PageUp/PageDown. The body
215
+ becomes a single tab stop; `Enter` drills into a cell's own control and `Escape` comes back out.
216
+ Composes with virtual scrolling.
217
+
218
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`255bebc`](https://github.com/ethlete-io/ethdk/commit/255bebcad8a0db468093784c300a865d90c224e7) Thanks [@github-actions](https://github.com/apps/github-actions)! - Time picker: `etTimePicker` / `et-time-picker` take `min`, `max` and `timeFilter`, matching the
219
+ calendar's bounds, and `et-time-input` / `et-date-time-input` forward them as `minTime` / `maxTime` /
220
+ `timeFilter`. Availability is per column - an hour is disabled only when no minute inside it is
221
+ selectable - unselectable options stay in place and the keyboard steps over them, and picking a part
222
+ moves the finer ones to the first value that works, including the hour behind an AM/PM pick.
223
+
224
+ ### Patch Changes
225
+
226
+ - [#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, … })`
227
+ instead of a `{ kind: 'anchored', … }` literal - it is what pulls `@floating-ui/dom` in, so apps
228
+ that only center dialogs no longer bundle it (~7 kB gz). `autoResize`, `autoHide`,
229
+ `autoCloseIfReferenceHidden` and arrows additionally need `enableAnchoredOverlayPositionExtras()`.
230
+
231
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`d97e71a`](https://github.com/ethlete-io/ethdk/commit/d97e71a9e0ee6f53cb71c2b05f8dae64fcdb92a5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix `<et-carousel>` autoplaying by default: `autoplay` is the component's own input now and defaults
232
+ to `false`, which is what it always documented. Add `autoplay` to a carousel that should play. On the
233
+ headless directive, read the new `isEnabled()` for what is in effect.
234
+
235
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`833b579`](https://github.com/ethlete-io/ethdk/commit/833b579f42f413ae715e792d5aa40e14d3e95513) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-match-participant` now takes an attribute form (`<a et-match-participant>` / `<button …>`), so a player or
236
+ team card can be the click target itself. On an interactive host it names itself after the participant - the
237
+ link would otherwise read "FC Berlin emblem FC Berlin" - takes the shared focus ring, and drops the button
238
+ chrome. `et-match-card` already worked this way.
239
+
240
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8609171`](https://github.com/ethlete-io/ethdk/commit/8609171a498982cdde8b7ce2c600cf4d42031016) Thanks [@github-actions](https://github.com/apps/github-actions)! - Docs: add a Sport UI recipes guide - the today's-matches rail (built on `et-scrollable`, which is why
241
+ `et-match-list` was never shipped as a component) plus competition, team, player and nation cards, each with
242
+ a live story to copy from.
243
+
244
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8f0e42a`](https://github.com/ethlete-io/ethdk/commit/8f0e42a8a436aba6a061968bfd6dc144344a896f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form field: the text-field shell, rich-text, textarea, hint and counter CSS now ships with the
245
+ control that uses it, so a field holding only a checkbox, switch or slider no longer pulls the
246
+ whole form-field stylesheet. No API change; chrome renders as before.
247
+
248
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`2c0d3c9`](https://github.com/ethlete-io/ethdk/commit/2c0d3c9f78bfceed19dd49b01f934d1cfebc83c2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Choice field's card variant, the carousel autoplay chrome and the cascader's bottom-sheet
249
+ presentation now inject their CSS only once that feature is actually used.
250
+
251
+ - [#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.
252
+
253
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`95c3d2f`](https://github.com/ethlete-io/ethdk/commit/95c3d2f096180119ed21937d5c41ed62a7b050e6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: `--et-overlay-body-padding-block` now reserves real space at the end of a scrolling body. Its end value used to be swallowed by the scroll container, leaving the last child's border and focus ring clipped against the divider once scrolled to the bottom.
254
+
255
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`f59128f`](https://github.com/ethlete-io/ethdk/commit/f59128f23932f647f2653d2ee804cd474011915f) Thanks [@github-actions](https://github.com/apps/github-actions)! - `createOverlayUnsavedChangesGuard` stops vetoing closes once its tracker was abandoned (a logout), so the overlay closes instead of prompting over a page the user is being redirected away from. It also inherits the tracker's tab guard - the `beforeunload` lock is on by default, with the title marker / blink / favicon / badge extras available through the `tab` option.
256
+
257
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`2c0d3c9`](https://github.com/ethlete-io/ethdk/commit/2c0d3c9f78bfceed19dd49b01f934d1cfebc83c2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: the default enter/leave animation CSS now ships with the strategy that uses it
258
+ (`stylesComponent` on the breakpoint config), so an app only bundles the animations for the overlay
259
+ kinds it opens. Overlays that hand-roll a layout `containerClass` instead of using a built-in
260
+ strategy must now provide their own animation CSS.
261
+
262
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8b13854`](https://github.com/ethlete-io/ethdk/commit/8b13854aa079196c84fc08da0aee685f728a441d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query client: multi-tab sync and response persistence are opt-in `features` instead of defaults - the
263
+ `multiTabSync` / `persistence` client options are gone and a client without the features ships neither
264
+ engine. Migrate with `nx g @ethlete/query:migrate-query-client-features`.
265
+
266
+ - `withMultiTabSync()` shares reads, polls a cache key in one tab for all of them and refreshes the
267
+ others after a mutation; per-query `multiTabSync: false` keeps a query tab-local.
268
+ - `withQueryPersistence()` keeps public reads in IndexedDB, so a reload renders the last known data
269
+ while it revalidates. Secure responses need an explicit opt-in and are removed on logout.
270
+ - `refreshQueriesInUse()` also refreshes GraphQL queries transported over POST; devtools gain Sync
271
+ and Disk columns.
272
+
273
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8422cf0`](https://github.com/ethlete-io/ethdk/commit/8422cf09bcb4cdc07621d7a495004d8bf5e37d2c) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: fix escaping a code block that sits flush against the start or end of the content,
274
+ where there is no line to move to. ArrowUp off the first line and ArrowDown off the last now create
275
+ the paragraph they would move to, and a second Enter on the empty last line leaves the block.
276
+
277
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`1c7ad03`](https://github.com/ethlete-io/ethdk/commit/1c7ad0373cf8cf7845be1d3337bbafe71eec9fc0) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the docked (touch) toolbar no longer leaves a gap between itself and the on-screen
278
+ keyboard, however much the browser over-reports the keyboard's height, and it re-checks while the
279
+ keyboard is up in case a viewport event never arrives. A page that opted into the VirtualKeyboard API
280
+ gets `env(keyboard-inset-height)` instead of the measurement.
281
+
282
+ - [#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` /
283
+ `createLabels` are replaced by `defineProvider` & co., which return a definition you read with
284
+ `toProvideFn` / `toInjectFn` / `toToken`; `createQueryClient`, `createBearerAuthProvider` and
285
+ `createWebSocketClient` return that definition instead of a tuple. Every `provideX` / `injectX` /
286
+ token export keeps its name - run `nx g @ethlete/core:migrate-provider-shape` for your own call sites.
287
+ Cuts the `@ethlete/components` import floor from 89.9 to 2.4 kB gz.
288
+
289
+ ## 1.0.0-next.32
290
+
291
+ ### Major Changes
292
+
293
+ - [#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
294
+ `provide<Domain>Labels` / `inject<Domain>Labels` pair per domain - 22 of them, all locale-reactive and
295
+ signal-shaped. See the [localization guide](https://ethlete-sdk-docs-next.web.app/components/localization).
296
+
297
+ - New tokens make the rich text editor, stream, grid, loader, chip, calendar, time picker, dropzone,
298
+ select, cascader, phone input, slider, date/time and notification strings overridable.
299
+ - **Breaking:** `inject*Labels()` now returns a signal; the string fields left `StreamConsentConfig`,
300
+ `StreamPlayerErrorConfig`, `PipSlotPlaceholderConfig`, `GridConfig` and `NotificationManagerConfig`
301
+ (with their `transformer` hooks); per-instance label inputs default to `null` instead of English.
302
+ - Fixes the PiP close/back buttons, which set an attribute literally named `attr.aria-label`.
303
+
304
+ ### Minor Changes
305
+
306
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`57494e0`](https://github.com/ethlete-io/ethdk/commit/57494e0834708ef1d397829074e20e35bc5d8acd) Thanks [@github-actions](https://github.com/apps/github-actions)! - Boolean and numeric inputs now coerce attribute values via `booleanAttribute` / `numberAttribute`,
307
+ so static values need no binding - `<et-tab disabled>`, `<et-textarea rows="6">`. Inputs where
308
+ `null`/`undefined` means "unset" (the slider's `min`/`max`, the overlay's `hasBackdrop`, …) are
309
+ deliberately left untransformed.
310
+
311
+ - [`2a5a48d`](https://github.com/ethlete-io/ethdk/commit/2a5a48dba8899d4b17b4139cf829ccb5d2daab4e) Thanks [@TomTomB](https://github.com/TomTomB)! - Card presets: `et-checkbox-option` now takes `variant="card"` too. Cards drop the tinted fill and
312
+ follow the form-field frame for hover/press/focus, a selected card's border tracks the theme's
313
+ interaction shades, `et-choice-field` cards are clickable across the whole panel including its
314
+ border, and disabled / readonly cards no longer offer a pointer cursor. `et-form-field`'s hover
315
+ treatment now follows the frame and label instead of the whole field, so the hint/counter row no
316
+ longer triggers it.
317
+
318
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`bc8aca7`](https://github.com/ethlete-io/ethdk/commit/bc8aca76900a47a3faed4ad2be2ce2ab7b70b27d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Filter overlay: new `provideFilterOverlay` / `injectFilterOverlay` - a filter panel that drafts the page's query
319
+ form, reports how many results the draft would return on its submit button, and applies on submit or discards on
320
+ dismiss. Replaces cdk's `FilterOverlayService`, rebuilt on signal forms and the current query client.
321
+
322
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`4fb18af`](https://github.com/ethlete-io/ethdk/commit/4fb18afb4159a1a301c66c98029e7af1d46a02ad) Thanks [@github-actions](https://github.com/apps/github-actions)! - Floating action: new `etFloatingAction` family - a trigger that pins itself to the viewport corner once its place
323
+ in the page scrolls away, and stands down once the region it acts on is gone. Replaces cdk's `rich-filter`, which
324
+ rendered no filter UI; the three states are published as one `data-state`.
325
+
326
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`c1db7e3`](https://github.com/ethlete-io/ethdk/commit/c1db7e3e8cf15d9dc192e51de699f0de8ee6fcbb) Thanks [@github-actions](https://github.com/apps/github-actions)! - Masonry: new `etMasonry` / `etMasonryItem` directives - column-balancing layout for variable-height cards.
327
+ Items are measured continuously, so late-loading content reflows, and they keep their column when one grows.
328
+ Gate infinite scroll on `isSettled()`.
329
+
330
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`3a6d9ad`](https://github.com/ethlete-io/ethdk/commit/3a6d9ad0130b6141add15c2660c976b61455e5a4) Thanks [@github-actions](https://github.com/apps/github-actions)! - Picture: new `et-picture` - responsive `<picture>` with art direction, format negotiation, `priority` hints,
331
+ `aspectRatio` for reserving space, and `etPicturePlaceholder` / `etPictureError` slots. `providePictureConfig`
332
+ prefixes relative srcsets per candidate.
333
+
334
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`38f6af1`](https://github.com/ethlete-io/ethdk/commit/38f6af115c7a5107b268c44597dc5b871503d9d9) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query error: new `<et-query-error>` and `[etQueryError]` - status title, message or violation list, and a retry
335
+ button when the retry policy says it's worth offering. Themed with the app's `type: 'error'` theme, localized via
336
+ `injectLocale()`, with `etQueryErrorTitle` / `etQueryErrorActions` slots. `legacyQueryErrorSource` bridges a V2
337
+ query.
338
+
339
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`d93dce3`](https://github.com/ethlete-io/ethdk/commit/d93dce3520e882a4cd4c6217d8a4cceedf74167c) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form field: add `<et-counter />` - an `x / N` character counter in the support region, at the inline-end of the hint/error and persistent alongside them. It takes its limit from the bound field's schema `maxLength()`, or an explicit `[max]`, and counts array values (so it counts tags in an `et-tag-input`) via `lengthOf`.
340
+
341
+ The field also shows a subtle busy spinner and `aria-busy` while an async validator is pending, plus `[busy]` on `et-form-field` to force it.
342
+
343
+ - [#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
344
+ panel, label leading, selection on the border and label), and `et-segmented-button-group` takes `variant="tabs"` (underlined
345
+ selection instead of a filled pill). Closes the last cdk parity gaps.
346
+
347
+ `@ethlete/core` adds `injectRouterNavigationState<T>()` for reading the state a navigation was given.
348
+
349
+ - [#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:
350
+
351
+ - 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'`.
352
+ - `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.
353
+ - The full-screen overlay animation throws `ET1209` when it has no origin element, instead of a bare `Error`.
354
+
355
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`fde4349`](https://github.com/ethlete-io/ethdk/commit/fde4349c2557d6f35d43e7eab09536a6b30524b4) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overhaul the sheet drag-to-dismiss gesture. It runs on pointer events now (one path
356
+ for touch, pen and mouse) and waits for 8px of travel along the dismiss axis before
357
+ following the pointer, so a swipe starting on scrolled overlay content scrolls it
358
+ instead of hijacking the sheet. Both the snap-back and the exit animate at the speed
359
+ the pointer had when it let go, clamped to 100–350ms and skipped under
360
+ `prefers-reduced-motion`. New `dragToDismiss.snapPoints` parks the sheet at fractions
361
+ of its own size, advancing one point per flick and dismissing past the last one.
362
+
363
+ ### Patch Changes
364
+
365
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`894c821`](https://github.com/ethlete-io/ethdk/commit/894c821c80df962f4c3cce986fb68f88ae26955d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Breadcrumb: leaner chrome - a neutral `et-ellipsis` overflow button that stays neutral while open, menu-like
366
+ rows in its popover, and no flash of the full trail before it collapses on load. Adds
367
+ `--et-breadcrumb-radius` and the `[data-toggletip-hug]` hook for content-width toggletips.
368
+
369
+ Overlay: the anchored arrow now meets the pane's border line instead of leaving an unbordered wedge at its
370
+ base - menus, tooltips and toggletips included.
371
+
372
+ - [#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
373
+ shifts near a viewport edge. `arrowPadding` now measures the arrow's actual base, so it means "how close the
374
+ arrow may get to the corners" - tooltip and toggletip default to `20` (was `8`), a bare anchored strategy to
375
+ `12` (was `4`).
376
+
377
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`bd369da`](https://github.com/ethlete-io/ethdk/commit/bd369da0b898096411d65c352220a26b48ec7a67) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: arrays and objects in the value explorer now copy too - a container copies its
378
+ subtree as JSON, a leaf copies the bare value. The toggle and close buttons print the platform's
379
+ open/close shortcut, which now also fires on macOS. The inspect filter reads as a labelled banner
380
+ instead of a bare pill.
381
+
382
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`b0a0869`](https://github.com/ethlete-io/ethdk/commit/b0a08696a0bcad9f120f8c58599b33d82d0fc61d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Touch quality fixes: the overlay body and scrollable containers keep overscroll to
383
+ themselves (`overscroll-behavior: contain`), so reaching an end no longer scrolls the
384
+ page behind them or triggers pull-to-refresh. Buttons, chips, menu items, select
385
+ options, calendar cells and carousel dots drop the grey tap-highlight flash that
386
+ duplicated their own `:active` state. Tooltips no longer open from touch input -
387
+ mobile browsers synthesize a hover around a tap, which popped a tooltip nobody asked
388
+ for - and any open tooltip now closes on a press elsewhere.
389
+
3
390
  ## 1.0.0-next.31
4
391
 
5
392
  ### Minor Changes
@@ -15,7 +402,7 @@
15
402
  (`etBreadcrumbItemTemplate`, `loading` placeholders, `etBreadcrumbSeparator`) and measured overflow that
16
403
  moves the middle crumbs into a toggletip. In a routed app each view contributes only the crumbs it owns
17
404
  via `<ng-template etBreadcrumbSegment>`, and the single `<et-breadcrumb-outlet>` in the shell renders
18
- every registered segment as one trail — no view restates the path above it. Labels are localizable via
405
+ every registered segment as one trail - no view restates the path above it. Labels are localizable via
19
406
  `provideBreadcrumbLabels`.
20
407
 
21
408
  - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`b4eb950`](https://github.com/ethlete-io/ethdk/commit/b4eb9506b3c3beff52670115bf50b26ea45b0c22) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add the carousel: `<et-carousel>` with slides from data plus an `etCarouselSlide` template, seamless looping,
@@ -23,18 +410,18 @@
23
410
  `slideAlign`, opt-in `autoplay` with per-slide `autoplayTimeFor`, and the headless `etCarousel` /
24
411
  `etCarouselAutoplay` / `etCarouselItem` / control directives behind `CAROUSEL_IMPORTS`.
25
412
 
26
- - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`11ed986`](https://github.com/ethlete-io/ethdk/commit/11ed986c9391b6e4927312d166e8603bf1cefef8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: new `<et-bracket>` tournament renderer — single/double-elimination and swiss layouts, SVG connectors, journey highlighting, and the `generateBracketDataForEthlete` data-source integration. Round-header, match, and continue cards render via barebones default components for now; supply custom cards through the `roundHeaderComponent` / `matchComponent` / `finalMatchComponent` / `continueComponent` inputs or `provideBracketConfig`.
413
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`11ed986`](https://github.com/ethlete-io/ethdk/commit/11ed986c9391b6e4927312d166e8603bf1cefef8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bracket: new `<et-bracket>` tournament renderer - single/double-elimination and swiss layouts, SVG connectors, journey highlighting, and the `generateBracketDataForEthlete` data-source integration. Round-header, match, and continue cards render via barebones default components for now; supply custom cards through the `roundHeaderComponent` / `matchComponent` / `finalMatchComponent` / `continueComponent` inputs or `provideBracketConfig`.
27
414
 
28
415
  This is the `@ethlete/cdk` `NewBracket` renderer moved here and renamed (`et-new-bracket` → `et-bracket`, `NewBracket*` → `Bracket*`), with colors now driven by the `--et-bracket-line-color` / `--et-bracket-swiss-group-border-color` tokens (default `--et-surface-border-solid`) and errors thrown as `RuntimeError` (ET34xx). The fifa.gg integration was not ported. See the guide's "Migrating from @ethlete/cdk" section.
29
416
 
30
- - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`875d22b`](https://github.com/ethlete-io/ethdk/commit/875d22bbde15669723cccf73c86983ad761c69b2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a **Pagination** component (`et-pagination`, `PAGINATION_IMPORTS`) — responsive, localizable, with optional crawlable page links and SEO head tags. See the [pagination guide](https://ethlete-sdk-docs-next.web.app/components/pagination).
417
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`875d22b`](https://github.com/ethlete-io/ethdk/commit/875d22bbde15669723cccf73c86983ad761c69b2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a **Pagination** component (`et-pagination`, `PAGINATION_IMPORTS`) - responsive, localizable, with optional crawlable page links and SEO head tags. See the [pagination guide](https://ethlete-sdk-docs-next.web.app/components/pagination).
31
418
 
32
419
  - [`4b661b3`](https://github.com/ethlete-io/ethdk/commit/4b661b366682c18cf5371df03d3100d843146e5d) Thanks [@TomTomB](https://github.com/TomTomB)! - Scrollable: add `snapOrigin` for where a snapped child comes to rest (`'center'` suits a peeking layout), and
33
- stop snapping while a pointer is held on the track — it used to scroll out from under a paused drag.
420
+ stop snapping while a pointer is held on the track - it used to scroll out from under a paused drag.
34
421
 
35
- - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`36c7119`](https://github.com/ethlete-io/ethdk/commit/36c71192663e3b491de0e7210887852012308c4e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a **Skeleton** component (`et-skeleton`, `SKELETON_IMPORTS`) for loading placeholders — see the [skeleton guide](https://ethlete-sdk-docs-next.web.app/components/skeleton).
422
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`36c7119`](https://github.com/ethlete-io/ethdk/commit/36c71192663e3b491de0e7210887852012308c4e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a **Skeleton** component (`et-skeleton`, `SKELETON_IMPORTS`) for loading placeholders - see the [skeleton guide](https://ethlete-sdk-docs-next.web.app/components/skeleton).
36
423
 
37
- - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`3c09f1d`](https://github.com/ethlete-io/ethdk/commit/3c09f1dd0c87ca366fe8f6c45fd138f4e8645402) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a type-safe **Table** component (`et-table`, `TABLE_IMPORTS`) with a lean base and opt-in features for filtering, column menus, resizing, reordering, selection, virtual scrolling and state persistence — see the [table guide](https://ethlete-sdk-docs-next.web.app/components/table).
424
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`3c09f1d`](https://github.com/ethlete-io/ethdk/commit/3c09f1dd0c87ca366fe8f6c45fd138f4e8645402) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a type-safe **Table** component (`et-table`, `TABLE_IMPORTS`) with a lean base and opt-in features for filtering, column menus, resizing, reordering, selection, virtual scrolling and state persistence - see the [table guide](https://ethlete-sdk-docs-next.web.app/components/table).
38
425
 
39
426
  ### Patch Changes
40
427
 
@@ -56,7 +443,7 @@
56
443
  `box`/`filled` skins need, so the rule sits directly under the value instead of at the
57
444
  bottom of a taller frame. A `size="sm"` field previously left ~12px of dead space
58
445
  between its value and the underline (most visible on a compact control like a table
59
- footer's page-size select) — that is now the field's own
446
+ footer's page-size select) - that is now the field's own
60
447
  `--et-form-field-control-padding-block`, and the frame is content-height (27px instead of
61
448
  42px at `sm`).
62
449
 
@@ -64,12 +451,12 @@
64
451
  `--et-form-field-control-font-size` / `-line-height` / `-padding-block`, and a floating
65
452
  label still grows the frame past it. `box` and `filled` appearances are unchanged.
66
453
 
67
- Note this makes underline fields shorter on touch as well — reach for `box`/`filled` or
454
+ Note this makes underline fields shorter on touch as well - reach for `box`/`filled` or
68
455
  a larger `size` where a full-size tap target matters more than density.
69
456
 
70
457
  - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`dab7346`](https://github.com/ethlete-io/ethdk/commit/dab73460c22b47cf88106d3435cb95f78f756273) Thanks [@github-actions](https://github.com/apps/github-actions)! - Load more now dead-ends properly when the response can't state the end exactly: a page that comes back
71
- empty — or that repeats the previous page, which is what an API asked for a page past the end usually
72
- serves — is dropped instead of appended, and `hasMore` turns off regardless of `toHasMore`. Affects
458
+ empty - or that repeats the previous page, which is what an API asked for a page past the end usually
459
+ serves - is dropped instead of appended, and `hasMore` turns off regardless of `toHasMore`. Affects
73
460
  `selectOptionsFromQuery`, `selectOptionsFromV2Query` and both table rows adapters, so a load-more
74
461
  control no longer survives one page too long or duplicates the tail of the list.
75
462
 
@@ -77,24 +464,24 @@
77
464
 
78
465
  - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`5616552`](https://github.com/ethlete-io/ethdk/commit/56165523fa96b6aef6feffd4302d73f18f094155) Thanks [@github-actions](https://github.com/apps/github-actions)! - Menu: a checkbox/radio item's check, dot or custom icon is pinned to the item's trailing edge again.
79
466
  Its label's layout was declared in the plain menu item's stylesheet, which is only injected once that
80
- component renders — so in a menu built entirely from selection items (a filter menu, the rich text
467
+ component renders - so in a menu built entirely from selection items (a filter menu, the rich text
81
468
  editor's heading and alignment menus) the label didn't grow and the indicator sat against the text
82
469
  instead of the edge.
83
470
 
84
471
  - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`3151b7a`](https://github.com/ethlete-io/ethdk/commit/3151b7a253d14e38e22e20d67bf0191f141c144e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `ethlete/no-template-literal-before-inline-template`, and restructure the files it flagged.
85
472
 
86
- The Angular VS Code extension decides **client-side** whether the cursor sits inside an inline `template:` before it forwards completion, hover, go-to-definition or signature-help to the language server. That check (`isNotTypescriptOrSupportedDecoratorField`) walks the file with a bare `ts.createScanner()` loop, which cannot re-scan `}` as `TemplateMiddle`/`TemplateTail` — that needs the parser's `reScanTemplateToken()`. So the first template literal containing a `${…}` substitution desynchronises both the token stream and the brace counter, the scanner never recognises `template` `:` again, and every template request below it is dropped. The language server answers those requests correctly; the editor just never asks, so the template silently has no IntelliSense at all.
473
+ The Angular VS Code extension decides **client-side** whether the cursor sits inside an inline `template:` before it forwards completion, hover, go-to-definition or signature-help to the language server. That check (`isNotTypescriptOrSupportedDecoratorField`) walks the file with a bare `ts.createScanner()` loop, which cannot re-scan `}` as `TemplateMiddle`/`TemplateTail` - that needs the parser's `reScanTemplateToken()`. So the first template literal containing a `${…}` substitution desynchronises both the token stream and the brace counter, the scanner never recognises `template` `:` again, and every template request below it is dropped. The language server answers those requests correctly; the editor just never asks, so the template silently has no IntelliSense at all.
87
474
 
88
- The new rule reproduces that scanner verbatim, so it reports exactly the templates the extension would abandon — no heuristic. Twenty inline templates across `components`, `cdk` and the playground were affected, all of them behind a fixture or helper that happened to use an interpolated template literal. Story fixtures moved into sibling `*-storybook.data.ts` files; spec fixtures and in-class helpers that must stay above their component (because a later `@Component` references the class in `imports`) were rewritten without the interpolation.
475
+ The new rule reproduces that scanner verbatim, so it reports exactly the templates the extension would abandon - no heuristic. Twenty inline templates across `components`, `cdk` and the playground were affected, all of them behind a fixture or helper that happened to use an interpolated template literal. Story fixtures moved into sibling `*-storybook.data.ts` files; spec fixtures and in-class helpers that must stay above their component (because a later `@Component` references the class in `imports`) were rewritten without the interpolation.
89
476
 
90
- No public API changed — the `components` and `cdk` bumps are story/spec restructuring plus moving `signalVisibilityChangeClasses` below `RichFilterHostComponent` in the same module.
477
+ No public API changed - the `components` and `cdk` bumps are story/spec restructuring plus moving `signalVisibilityChangeClasses` below `RichFilterHostComponent` in the same module.
91
478
 
92
479
  - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`d666dcd`](https://github.com/ethlete-io/ethdk/commit/d666dcd73055e0044a2e635eef15c24849cf1751) Thanks [@github-actions](https://github.com/apps/github-actions)! - Log the logout-wide secure unbind in the query devtools event log. A logout drops every secure cache
93
480
  entry at once; without a row of its own, the requests disappearing from the cache view had no visible
94
481
  cause.
95
482
 
96
- - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`d85c58a`](https://github.com/ethlete-io/ethdk/commit/d85c58a84fc857847a03e4b736e27cd70fb5ee14) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the anchored link popover enters and leaves like a toggletip — a
97
- short fade plus a small nudge away from the selection it points at — instead of the
483
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`d85c58a`](https://github.com/ethlete-io/ethdk/commit/d85c58a84fc857847a03e4b736e27cd70fb5ee14) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: the anchored link popover enters and leaves like a toggletip - a
484
+ short fade plus a small nudge away from the selection it points at - instead of the
98
485
  anchored-dialog spring scale, which was far too much movement for a card sitting on
99
486
  top of the text being edited. The phone-sized top sheet is unchanged.
100
487
 
@@ -107,7 +494,7 @@
107
494
  - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`88cf3af`](https://github.com/ethlete-io/ethdk/commit/88cf3af9e61f9cc5ea7e6f547430246327c88f96) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix `et-select` not forwarding the headless `mirrorPanelWidth` input, which made the
108
495
  documented escape hatch for compact triggers unreachable from the default component.
109
496
  With `[mirrorPanelWidth]="false"` the panel sizes to its own content (capped at
110
- `min(400px, 100vw - 24px)`) instead of the field's width — needed whenever the trigger
497
+ `min(400px, 100vw - 24px)`) instead of the field's width - needed whenever the trigger
111
498
  is narrower than an option row, e.g. a page-size select where the value plus the
112
499
  selected-check indicator no longer fit and the label was squeezed to a few pixels.
113
500
 
@@ -116,7 +503,7 @@
116
503
  ### Minor Changes
117
504
 
118
505
  - [#3036](https://github.com/ethlete-io/ethdk/pull/3036) [`aa4bdde`](https://github.com/ethlete-io/ethdk/commit/aa4bdde586615ed13735ed9c970831b91323ebad) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `<et-query-devtools>` (`QUERY_DEVTOOLS_IMPORTS`): a floating, dockable panel
119
- that inspects the signals-first `@ethlete/query` system — queries, stacks,
506
+ that inspects the signals-first `@ethlete/query` system - queries, stacks,
120
507
  sequences, GraphQL queries, bearer auth providers, web socket clients, the
121
508
  repository cache and a rolling event log. Enable instrumentation with
122
509
  `provideQueryDevtools()` from `@ethlete/query`.
@@ -141,14 +528,14 @@
141
528
 
142
529
  ### Patch Changes
143
530
 
144
- - [`90dad92`](https://github.com/ethlete-io/ethdk/commit/90dad922e8985b76e5f5ad67727333de6f5b9431) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlays now elevate one level above the surface their **trigger** actually sits on, resolved from the trigger's nearest surface ancestor in the DOM rather than from dependency injection. The overlay container previously read its parent surface from the injector context (`SURFACE_PROVIDER`), which is wrong across the portal boundary: an overlay's trigger keeps the injector of where it was _declared_, and the anchored panel overlays (select, cascader, date-picker, menu) mount with no DI link to the trigger at all — so they always landed at elevation 1.
531
+ - [`90dad92`](https://github.com/ethlete-io/ethdk/commit/90dad922e8985b76e5f5ad67727333de6f5b9431) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlays now elevate one level above the surface their **trigger** actually sits on, resolved from the trigger's nearest surface ancestor in the DOM rather than from dependency injection. The overlay container previously read its parent surface from the injector context (`SURFACE_PROVIDER`), which is wrong across the portal boundary: an overlay's trigger keeps the injector of where it was _declared_, and the anchored panel overlays (select, cascader, date-picker, menu) mount with no DI link to the trigger at all - so they always landed at elevation 1.
145
532
 
146
533
  This fixes two cases:
147
534
 
148
535
  - A `select` (or any anchored panel) opened from **inside a dialog** now mounts at elevation 2 instead of matching the dialog's elevation 1.
149
536
  - A picker anchored to a field inside an **elevated card** (e.g. a date input in a card at elevation 1) now elevates above the card instead of staying at elevation 1.
150
537
 
151
- Nested content (submenus elevating above their parent menu) and the plain non-nested case (an overlay opened from the base page mounts at elevation 1) are unchanged. Modal dialogs still always mount at elevation 1 — a backdrop resets the visual context.
538
+ Nested content (submenus elevating above their parent menu) and the plain non-nested case (an overlay opened from the base page mounts at elevation 1) are unchanged. Modal dialogs still always mount at elevation 1 - a backdrop resets the visual context.
152
539
 
153
540
  ## 1.0.0-next.28
154
541
 
@@ -156,7 +543,7 @@
156
543
 
157
544
  - [`b9fd6c2`](https://github.com/ethlete-io/ethdk/commit/b9fd6c2cc9dfac8211b33c4eed7039538257c2ef) Thanks [@TomTomB](https://github.com/TomTomB)! - Rename the module import arrays to SCREAMING_SNAKE_CASE for consistency with the rest of the library: `StreamImports` → `STREAM_IMPORTS`, `TabImports` → `TAB_IMPORTS`, `NavTabImports` → `NAV_TAB_IMPORTS` and `GridImports` → `GRID_IMPORTS`. Update your `imports` arrays accordingly.
158
545
 
159
- - [#3034](https://github.com/ethlete-io/ethdk/pull/3034) [`deccbdd`](https://github.com/ethlete-io/ethdk/commit/deccbdda82d0df9984cdcdac1ab3485d7e080759) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: give the boxed overlay kinds (`dialog`, `anchoredDialog`, the four sheets and the full-screen dialog) a default themed pane surface — `--et-surface-background-solid` background, a `0.1rem` `--et-surface-border-solid` border (all around for dialogs; every edge but the docked one for bottom/top sheets; only the exposed inner edge for side sheets, whose block edges sit flush against the viewport), and a radius on the exposed corners (`1.6rem` dialogs/sheets, `1.2rem` anchored dialog; full-screen stays square). Plain overlay content no longer needs to paint its own surface. Overridable per instance via the new `--et-overlay-surface-background`, `--et-overlay-surface-color`, `--et-overlay-surface-border-color`, `--et-overlay-surface-border-width` and `--et-overlay-radius` tokens. Anchored/centered panes (menu, tooltip, select, date-picker) are unaffected — they still paint their own surface.
546
+ - [#3034](https://github.com/ethlete-io/ethdk/pull/3034) [`deccbdd`](https://github.com/ethlete-io/ethdk/commit/deccbdda82d0df9984cdcdac1ab3485d7e080759) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: give the boxed overlay kinds (`dialog`, `anchoredDialog`, the four sheets and the full-screen dialog) a default themed pane surface - `--et-surface-background-solid` background, a `0.1rem` `--et-surface-border-solid` border (all around for dialogs; every edge but the docked one for bottom/top sheets; only the exposed inner edge for side sheets, whose block edges sit flush against the viewport), and a radius on the exposed corners (`1.6rem` dialogs/sheets, `1.2rem` anchored dialog; full-screen stays square). Plain overlay content no longer needs to paint its own surface. Overridable per instance via the new `--et-overlay-surface-background`, `--et-overlay-surface-color`, `--et-overlay-surface-border-color`, `--et-overlay-surface-border-width` and `--et-overlay-radius` tokens. Anchored/centered panes (menu, tooltip, select, date-picker) are unaffected - they still paint their own surface.
160
547
 
161
548
  ## 1.0.0-next.27
162
549
 
@@ -180,22 +567,22 @@
180
567
 
181
568
  ### Minor Changes
182
569
 
183
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`08ccfb4`](https://github.com/ethlete-io/ethdk/commit/08ccfb406db0269237ce3d026036c3400dff01d6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `createV2DropzoneUpload` — a legacy `V2QueryClient` flavor of the dropzone `upload` config, mirroring `createDropzoneUpload`. Apps that haven't migrated to the new `@ethlete/query` API can now drive the dropzone from a legacy v2 creator (`client.post(...)` or a `createLegacyQueryCreator` interop wrapper); it slots into the same `upload` input and supports the full lifecycle (progress, success, failure, retry, existing values). Internally the per-file query lifecycle now runs behind an upload-handle abstraction, so both flavors share the directive/entry code and the failure display handles both `QueryErrorResponse` and `RequestError`.
570
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`08ccfb4`](https://github.com/ethlete-io/ethdk/commit/08ccfb406db0269237ce3d026036c3400dff01d6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `createV2DropzoneUpload` - a legacy `V2QueryClient` flavor of the dropzone `upload` config, mirroring `createDropzoneUpload`. Apps that haven't migrated to the new `@ethlete/query` API can now drive the dropzone from a legacy v2 creator (`client.post(...)` or a `createLegacyQueryCreator` interop wrapper); it slots into the same `upload` input and supports the full lifecycle (progress, success, failure, retry, existing values). Internally the per-file query lifecycle now runs behind an upload-handle abstraction, so both flavors share the directive/entry code and the failure display handles both `QueryErrorResponse` and `RequestError`.
184
571
 
185
- - [`edb1f14`](https://github.com/ethlete-io/ethdk/commit/edb1f146792c308a0b80e8108d48934369d27b1d) Thanks [@TomTomB](https://github.com/TomTomB)! - Form field: the label is now truly optional — the label-mode layouts (`static`,
572
+ - [`edb1f14`](https://github.com/ethlete-io/ethdk/commit/edb1f146792c308a0b80e8108d48934369d27b1d) Thanks [@TomTomB](https://github.com/TomTomB)! - Form field: the label is now truly optional - the label-mode layouts (`static`,
186
573
  `floating-outside`) no longer reserve the label band when no `<et-label>` is
187
574
  projected.
188
575
  - Text-field controls (`et-input`, `et-number-input`, `et-password-input`,
189
576
  `et-color-input`, `et-textarea`) now accept `aria-label` / `aria-labelledby`,
190
577
  forwarded onto the native control; a consumer `aria-labelledby` overrides the
191
578
  projected `<et-label>`.
192
- - In dev mode a form field whose control has no accessible name — no `<et-label>`
193
- and no `aria-label`/`aria-labelledby` — now throws (`ET2201`). A placeholder is
579
+ - In dev mode a form field whose control has no accessible name - no `<et-label>`
580
+ and no `aria-label`/`aria-labelledby` - now throws (`ET2201`). A placeholder is
194
581
  not an accessible name.
195
582
 
196
583
  - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`0ecb9db`](https://github.com/ethlete-io/ethdk/commit/0ecb9dbe116b566beab61391b2cb92f3439c07f6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: public API to insert a token chip at the caret from your own UI.
197
584
  - `RichTextEditorDirective.insertToken(type, id, opts?)` inserts a `{{type:id}}` token chip at the
198
- caret (or the end when unfocused), resolving its label via the trigger's `resolveItem` — the same
585
+ caret (or the end when unfocused), resolving its label via the trigger's `resolveItem` - the same
199
586
  result as picking it from the `#`/`@` popup. `insertTokenItem(type, item, opts?)` does the same
200
587
  when you already hold the resolved `{ id, label }`. The directive now also exports as
201
588
  `etRichTextEditor`.
@@ -204,40 +591,40 @@
204
591
 
205
592
  - [#3029](https://github.com/ethlete-io/ethdk/pull/3029) [`129c3c9`](https://github.com/ethlete-io/ethdk/commit/129c3c97c8b2e62fd4532ba03e7cf9bf6aaee764) Thanks [@EliasPapavlassopoulos](https://github.com/EliasPapavlassopoulos)! - Add a two-way `mixed` bulk-edit state (plus `mixedLabel` where the control has a text display slot) across the form controls: select (single, multi, searchable, headless, virtualized), cascader, input, number-input, password-input, textarea, color-input, date-input, time-input, date-time-input, date-range-input, duration-input, tag-input, phone-input, slider, range-slider, rating, and the selection-list groups (radio, checkbox-group, segmented). While `mixed` is set the raw form value stays untouched and masked; the first user commit replaces it and resolves the state. All implementations follow one executable contract (shared conformance suite); checkbox keeps expressing the concept via its platform-named `indeterminate`, and switch deliberately stays two-state (ARIA forbids a mixed switch).
206
593
 
207
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`b5c0207`](https://github.com/ethlete-io/ethdk/commit/b5c0207db2af40b15f8575e3f6c721d07cf81b2f) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-select` (and the headless `[etSelect]`) gains the `[etSelectOptions]` directive: bind the bundle returned by `selectOptionsFromQuery` or `selectOptionsFromV2Query` with a single attribute and it wires the async plumbing for you — forwarding `loading`, `error` and `hasMoreItems`, forcing `filterMode` to `external`, and driving the bundle's `setQuery`/`loadMore` from the select's `(queryChange)`/`(loadMore)` outputs. You only render the options. Both factories return the same shape, so one directive serves the current query client and the legacy `V2QueryClient` alike. The manual per-input wiring stays fully supported.
594
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`b5c0207`](https://github.com/ethlete-io/ethdk/commit/b5c0207db2af40b15f8575e3f6c721d07cf81b2f) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-select` (and the headless `[etSelect]`) gains the `[etSelectOptions]` directive: bind the bundle returned by `selectOptionsFromQuery` or `selectOptionsFromV2Query` with a single attribute and it wires the async plumbing for you - forwarding `loading`, `error` and `hasMoreItems`, forcing `filterMode` to `external`, and driving the bundle's `setQuery`/`loadMore` from the select's `(queryChange)`/`(loadMore)` outputs. You only render the options. Both factories return the same shape, so one directive serves the current query client and the legacy `V2QueryClient` alike. The manual per-input wiring stays fully supported.
208
595
 
209
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`5fc9aa4`](https://github.com/ethlete-io/ethdk/commit/5fc9aa4316390c2db908c6dcd3c2118945a11089) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-select` (and the headless `[etSelect]`) gains an `pickOption` output and a `pickOnly` input. `pickOption` emits the picked value whenever a single-select option is committed — a "the user actively picked this" signal distinct from `valueChange`. With `pickOnly`, committing an option emits `pickOption` without ever writing `value`, so the select stays empty: a fire-and-forget "add" picker that feeds an external list without the set-then-clear dance (and its race with the `[(value)]` write-back). `pickOnly` has no effect in multi-select.
596
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`5fc9aa4`](https://github.com/ethlete-io/ethdk/commit/5fc9aa4316390c2db908c6dcd3c2118945a11089) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-select` (and the headless `[etSelect]`) gains an `pickOption` output and a `pickOnly` input. `pickOption` emits the picked value whenever a single-select option is committed - a "the user actively picked this" signal distinct from `valueChange`. With `pickOnly`, committing an option emits `pickOption` without ever writing `value`, so the select stays empty: a fire-and-forget "add" picker that feeds an external list without the set-then-clear dance (and its race with the `[(value)]` write-back). `pickOnly` has no effect in multi-select.
210
597
 
211
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`6605423`](https://github.com/ethlete-io/ethdk/commit/6605423235364f06c07e827205de2c3a351a538f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Switch now supports an `indeterminate` state (two-way `[(indeterminate)]`), mirroring checkbox — the first toggle resolves it to on. Since `role="switch"` cannot carry `aria-checked="mixed"`, it's presentational only (thumb parks mid-track behind `data-indeterminate`; `aria-checked` stays boolean). The mixed/indeterminate state on the graphical controls (rating, slider, range-slider, checkbox-group, radio-group, switch) now uses a consistent dashed "provisional" treatment so it reads as "values differ" rather than empty.
598
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`6605423`](https://github.com/ethlete-io/ethdk/commit/6605423235364f06c07e827205de2c3a351a538f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Switch now supports an `indeterminate` state (two-way `[(indeterminate)]`), mirroring checkbox - the first toggle resolves it to on. Since `role="switch"` cannot carry `aria-checked="mixed"`, it's presentational only (thumb parks mid-track behind `data-indeterminate`; `aria-checked` stays boolean). The mixed/indeterminate state on the graphical controls (rating, slider, range-slider, checkbox-group, radio-group, switch) now uses a consistent dashed "provisional" treatment so it reads as "values differ" rather than empty.
212
599
 
213
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`d738771`](https://github.com/ethlete-io/ethdk/commit/d738771a05b4505616defab52359870892bae171) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `createOverlayUnsavedChangesGuard` — the overlay flavor of the `unsavedChanges` family. Called from an overlay content component's injection context, it injects the current `OVERLAY_REF` and vetoes a dismissal (outside pointer, escape, drag, or a programmatic `close()`) while the watched form has unsaved changes, runs the `confirm`, and only then re-issues the close. Per-source opt-out via `dismissSources`, honors `disableClose`, and auto-cleans up on injector destroy.
600
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`d738771`](https://github.com/ethlete-io/ethdk/commit/d738771a05b4505616defab52359870892bae171) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `createOverlayUnsavedChangesGuard` - the overlay flavor of the `unsavedChanges` family. Called from an overlay content component's injection context, it injects the current `OVERLAY_REF` and vetoes a dismissal (outside pointer, escape, drag, or a programmatic `close()`) while the watched form has unsaved changes, runs the `confirm`, and only then re-issues the close. Per-source opt-out via `dismissSources`, honors `disableClose`, and auto-cleans up on injector destroy.
214
601
 
215
602
  Also exposes the underlying close-veto seam on `OverlayRef`: `registerCloseGuard(guard)` and `forceClose(source?, result?)`.
216
603
 
217
604
  ### Patch Changes
218
605
 
219
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`b5b037e`](https://github.com/ethlete-io/ethdk/commit/b5b037e6e4e1c1d1ecef9c4c13edab01e40a1d0f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix anchored panels (`select`, `cascader`, the date/time pickers) closing when a popover opened from inside them is clicked. A nested overlay (a select body, menu or tooltip) mounts as a sibling pane in the overlay root, not a DOM descendant, so the panel's outside-pointer check treated a click in the child as an outside dismissal and closed itself. The check now resolves the whole nested overlay tree — anchored by each pane's `origin` — so a pointerdown anywhere inside a descendant popover no longer dismisses the panel that opened it.
606
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`b5b037e`](https://github.com/ethlete-io/ethdk/commit/b5b037e6e4e1c1d1ecef9c4c13edab01e40a1d0f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix anchored panels (`select`, `cascader`, the date/time pickers) closing when a popover opened from inside them is clicked. A nested overlay (a select body, menu or tooltip) mounts as a sibling pane in the overlay root, not a DOM descendant, so the panel's outside-pointer check treated a click in the child as an outside dismissal and closed itself. The check now resolves the whole nested overlay tree - anchored by each pane's `origin` - so a pointerdown anywhere inside a descendant popover no longer dismisses the panel that opened it.
220
607
 
221
- - [#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.
608
+ - [#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.
222
609
 
223
- `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.
610
+ `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.
224
611
 
225
612
  - [`995eab1`](https://github.com/ethlete-io/ethdk/commit/995eab158002c0e36779cbd54dbbaf7da9355f58) Thanks [@TomTomB](https://github.com/TomTomB)! - Forms: clear ("×") buttons now fade in/out (opacity only) instead of appearing abruptly, consistently across date, time, date-time, duration, phone, select, and cascader. Respects `prefers-reduced-motion`. `et-date-range-input` gains the same clear button (new `clearable`/`clearLabel` inputs).
226
613
 
227
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`43e8711`](https://github.com/ethlete-io/ethdk/commit/43e8711f49ca995a4fdb95d95359219bd8298407) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form fields now keep their focused styling (accent border, lit label/affix) while a control's popup is open. Opening a date/time/date-range picker, select or cascader panel moves focus into the detached overlay, so `:focus-visible` no longer matched the field and it visibly dropped back to its resting look — controls now report an `expanded` state the field reflects as `[data-expanded]`.
614
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`43e8711`](https://github.com/ethlete-io/ethdk/commit/43e8711f49ca995a4fdb95d95359219bd8298407) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form fields now keep their focused styling (accent border, lit label/affix) while a control's popup is open. Opening a date/time/date-range picker, select or cascader panel moves focus into the detached overlay, so `:focus-visible` no longer matched the field and it visibly dropped back to its resting look - controls now report an `expanded` state the field reflects as `[data-expanded]`.
228
615
 
229
616
  Also fixes a flicker on the date-picker trigger button: clicking it while the field was focused briefly blurred the input (hiding the clear button and dropping the focused style) one frame before the picker opened. The trigger now prevents the mousedown default, matching the clear button, so focus stays on the field through the toggle.
230
617
 
231
618
  - [`246bb5e`](https://github.com/ethlete-io/ethdk/commit/246bb5ee26d6c28adacea316426a5af19b248a17) Thanks [@TomTomB](https://github.com/TomTomB)! - Form field: text-field controls (`et-input`, `et-number-input`,
232
619
  `et-password-input`, `et-textarea`) no longer render an empty `autocomplete=""`
233
- attribute when no autocomplete is set — the attribute is now omitted, clearing
620
+ attribute when no autocomplete is set - the attribute is now omitted, clearing
234
621
  Chrome's "Incorrect use of autocomplete attribute" warning.
235
622
 
236
623
  - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`b712197`](https://github.com/ethlete-io/ethdk/commit/b712197005495bc180e86d9645f77032da9fb266) Thanks [@github-actions](https://github.com/apps/github-actions)! - Date/time/date-range pickers, select and cascader now flip their alignment on the same side before flipping vertically: their anchored fallback placements changed from `['top-start']` to `['bottom-end', 'top-start', 'top-end']`. A field near the right viewport edge now opens right-aligned under the field (`bottom-end`) instead of being cross-axis shifted, matching the fallback behaviour menus already use.
237
624
 
238
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`62dbf77`](https://github.com/ethlete-io/ethdk/commit/62dbf77444238841fcd22a1c39467fd7f577d707) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor content no longer retints when the editor gains focus. The field frame is an `et-color-interactive--has-focus` ancestor that re-resolves the accent tokens on focus, and rendered content reading the accent — token chips (their outline and fill), links and the caret — inherited that shift. The content root now re-anchors the accent tokens to their resting value, insulating it from the field's interaction state (the same immunity the interactive toolbar buttons already have from carrying `et-color-interactive`).
625
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`62dbf77`](https://github.com/ethlete-io/ethdk/commit/62dbf77444238841fcd22a1c39467fd7f577d707) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor content no longer retints when the editor gains focus. The field frame is an `et-color-interactive--has-focus` ancestor that re-resolves the accent tokens on focus, and rendered content reading the accent - token chips (their outline and fill), links and the caret - inherited that shift. The content root now re-anchors the accent tokens to their resting value, insulating it from the field's interaction state (the same immunity the interactive toolbar buttons already have from carrying `et-color-interactive`).
239
626
 
240
- - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`5fc9aa4`](https://github.com/ethlete-io/ethdk/commit/5fc9aa4316390c2db908c6dcd3c2118945a11089) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-select`: a searchable single select with a custom value template (`etSelectValue`) now swaps the rich display for the option's editable plain-text label inside the search input while the field is focused (edit mode), and restores the rich template on blur. Keyboard editing is now at parity with a plain searchable single select — the label is selected on open, Backspace edits the visible text, and erasing it clears the selection. Previously the input stayed empty in this case, so a single Backspace silently deleted the whole selected value with nothing visible to edit.
627
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`5fc9aa4`](https://github.com/ethlete-io/ethdk/commit/5fc9aa4316390c2db908c6dcd3c2118945a11089) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et-select`: a searchable single select with a custom value template (`etSelectValue`) now swaps the rich display for the option's editable plain-text label inside the search input while the field is focused (edit mode), and restores the rich template on blur. Keyboard editing is now at parity with a plain searchable single select - the label is selected on open, Backspace edits the visible text, and erasing it clears the selection. Previously the input stayed empty in this case, so a single Backspace silently deleted the whole selected value with nothing visible to edit.
241
628
 
242
629
  - [`139d734`](https://github.com/ethlete-io/ethdk/commit/139d73474ec710834a28df50160c2cce1e795c1c) Thanks [@TomTomB](https://github.com/TomTomB)! - Form field: trigger-based controls (select, date pickers) keep their focused frame after a pointer-driven commit, so the frame and the clear affordance no longer disagree about whether the field is focused.
243
630
 
@@ -253,29 +640,29 @@
253
640
 
254
641
  ### Patch Changes
255
642
 
256
- - [#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)`).
643
+ - [#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)`).
257
644
 
258
645
  ## 1.0.0-next.23
259
646
 
260
647
  ### Minor Changes
261
648
 
262
- - [`221c878`](https://github.com/ethlete-io/ethdk/commit/221c878d5f3e382ffed074bf93ab30afeda9d63f) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: flat search across all levels. Implement the optional `search(query)` hook on the `CascaderDataSource` (returning root → match path chains) and the panel gains a search input that swaps the columns for a flat, breadcrumb-labelled result list — committing a match closes, while a branch-only match jumps the columns to it. New headless pieces `etCascaderSearch` and `etCascaderSearchOption`; `et-cascader` renders the input automatically (`searchPlaceholder` input) and Escape now clears an active query before closing the panel.
649
+ - [`221c878`](https://github.com/ethlete-io/ethdk/commit/221c878d5f3e382ffed074bf93ab30afeda9d63f) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: flat search across all levels. Implement the optional `search(query)` hook on the `CascaderDataSource` (returning root → match path chains) and the panel gains a search input that swaps the columns for a flat, breadcrumb-labelled result list - committing a match closes, while a branch-only match jumps the columns to it. New headless pieces `etCascaderSearch` and `etCascaderSearchOption`; `et-cascader` renders the input automatically (`searchPlaceholder` input) and Escape now clears an active query before closing the panel.
263
650
 
264
- - [`221c878`](https://github.com/ethlete-io/ethdk/commit/221c878d5f3e382ffed074bf93ab30afeda9d63f) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: `cascaderFromQuery` builds a `CascaderDataSource` from `@ethlete/query` creators — per-level loads (concurrent, deduped/cached by the client), optional flat-search wiring with debounce and `minQueryLength`, and a `resolvePath` passthrough. The cascader's default `toErrorMessage` now shows an `Error`'s `message` verbatim (falling back to the generic text), so query failure messages surface without extra wiring.
651
+ - [`221c878`](https://github.com/ethlete-io/ethdk/commit/221c878d5f3e382ffed074bf93ab30afeda9d63f) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: `cascaderFromQuery` builds a `CascaderDataSource` from `@ethlete/query` creators - per-level loads (concurrent, deduped/cached by the client), optional flat-search wiring with debounce and `minQueryLength`, and a `resolvePath` passthrough. The cascader's default `toErrorMessage` now shows an `Error`'s `message` verbatim (falling back to the generic text), so query failure messages surface without extra wiring.
265
652
 
266
- - [`221c878`](https://github.com/ethlete-io/ethdk/commit/221c878d5f3e382ffed074bf93ab30afeda9d63f) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: multi-select via the new `multiple` input — activations toggle values (the form value becomes a `T[]`), the panel stays open, rows gain check squares, ancestors of a partial selection show an indeterminate dash and promote to a full checkmark once all their loaded descendants are selected. Search results toggle in place (keeping the result list), the trigger joins the selected labels, and programmatic values resolve their chains through `resolvePath`. The `value` model is now typed `T | T[] | null`.
653
+ - [`221c878`](https://github.com/ethlete-io/ethdk/commit/221c878d5f3e382ffed074bf93ab30afeda9d63f) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: multi-select via the new `multiple` input - activations toggle values (the form value becomes a `T[]`), the panel stays open, rows gain check squares, ancestors of a partial selection show an indeterminate dash and promote to a full checkmark once all their loaded descendants are selected. Search results toggle in place (keeping the result list), the trigger joins the selected labels, and programmatic values resolve their chains through `resolvePath`. The `value` model is now typed `T | T[] | null`.
267
654
 
268
- - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: new `et-cascader` / `[etCascader]` (`CASCADER_IMPORTS`) — a generic hierarchy value control that browses an abstract `CascaderDataSource<T>` level by level (sync array, `Promise` or `Observable`, each level lazy-loaded). Miller columns on desktop, single-column drill in a bottom sheet on mobile; `selectableLevels` (`'leaf'` | `'any'`), `path`/`pathValue` chain, per-column loading/empty/error states with retry, full ARIA tree keyboard navigation, and signal-forms integration. Error block `ET3300`–`ET3399`.
655
+ - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Cascader: new `et-cascader` / `[etCascader]` (`CASCADER_IMPORTS`) - a generic hierarchy value control that browses an abstract `CascaderDataSource<T>` level by level (sync array, `Promise` or `Observable`, each level lazy-loaded). Miller columns on desktop, single-column drill in a bottom sheet on mobile; `selectableLevels` (`'leaf'` | `'any'`), `path`/`pathValue` chain, per-column loading/empty/error states with retry, full ARIA tree keyboard navigation, and signal-forms integration. Error block `ET3300`–`ET3399`.
269
656
 
270
- Deep hierarchies stay compact: the desktop panel shows at most `maxVisibleColumns` (default 3) columns side by side, showing the whole drilled trail as a breadcrumb row below the columns once it overflows. All drilled levels ride a sliding track, so collapsing into a crumb (and navigating back out of one) is a coordinated slide rather than a pop. Navigating back is non-destructive — a crumb click or Arrow Left past the window edge slides the column window without discarding the deeper drill. Headless: `visibleColumns()`, `breadcrumbPath()`, `visibleColumnStart()`, `showColumn()`.
657
+ Deep hierarchies stay compact: the desktop panel shows at most `maxVisibleColumns` (default 3) columns side by side, showing the whole drilled trail as a breadcrumb row below the columns once it overflows. All drilled levels ride a sliding track, so collapsing into a crumb (and navigating back out of one) is a coordinated slide rather than a pop. Navigating back is non-destructive - a crumb click or Arrow Left past the window edge slides the column window without discarding the deeper drill. Headless: `visibleColumns()`, `breadcrumbPath()`, `visibleColumnStart()`, `showColumn()`.
271
658
 
272
- - [#3027](https://github.com/ethlete-io/ethdk/pull/3027) [`0a62001`](https://github.com/ethlete-io/ethdk/commit/0a6200181b706828bc8b228afb0743a269bd7e8e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: add `et-date-time-input` (+ headless `[etDateTimeInput]`), a combined date & time control with a string wire value — one field with a combined display format (strict-then-lenient typed entry, bare dates commit at midnight) and a picker overlay hosting calendar and time picker side by side (Date/Time tabs in the bottom sheet). A first day pick in the picker also commits at midnight — never the current wall-clock time.
659
+ - [#3027](https://github.com/ethlete-io/ethdk/pull/3027) [`0a62001`](https://github.com/ethlete-io/ethdk/commit/0a6200181b706828bc8b228afb0743a269bd7e8e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: add `et-date-time-input` (+ headless `[etDateTimeInput]`), a combined date & time control with a string wire value - one field with a combined display format (strict-then-lenient typed entry, bare dates commit at midnight) and a picker overlay hosting calendar and time picker side by side (Date/Time tabs in the bottom sheet). A first day pick in the picker also commits at midnight - never the current wall-clock time.
273
660
 
274
661
  - [`8bfe3ed`](https://github.com/ethlete-io/ethdk/commit/8bfe3ed805a760f13a5cef11125473b1342d747c) Thanks [@TomTomB](https://github.com/TomTomB)! - Date, time, date-time and date range inputs: new opt-in `mask` input. With a fixed-width numeric `displayFormat` (`dd.MM.yyyy`, `HH:mm`, …) typing gets guide placeholders (`__.__.____`), auto-inserted separators, paste filtering and a numeric soft keyboard; the lenient blur/Enter commit parsers stay authoritative. Formats a mask can't represent (locale formats like the default `P`/`p`, variable-width or text tokens) are refused with a dev-mode warning and typing stays unmasked. On the date range input each side is its own mask host, so the guide follows the focused field. The duration input deliberately gets no mask (unbounded first segment, right-anchored lenient entry). Supporting API: `[etInputMask]` now accepts `null` to disable the mask conditionally, and `InputMaskHost` grew an optional `resumeNativeSync()` for hosts whose mask can toggle off again.
275
662
 
276
- - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Duration input: new `et-duration-input` / `[etDurationInput]` (`DURATION_INPUT_IMPORTS`) — a duration control whose value is total elapsed **milliseconds** (`number | null`), kept out of the `Date` system. Configurable segment layout (`durationFormat`, e.g. `mm:ss`, `hh:mm:ss`, `hh:mm:ss.SSS`) with a lenient typed parse (`130` → `1:30`) committing on blur/Enter. Error code `ET3050` inside the shared date-time block.
663
+ - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Duration input: new `et-duration-input` / `[etDurationInput]` (`DURATION_INPUT_IMPORTS`) - a duration control whose value is total elapsed **milliseconds** (`number | null`), kept out of the `Date` system. Configurable segment layout (`durationFormat`, e.g. `mm:ss`, `hh:mm:ss`, `hh:mm:ss.SSS`) with a lenient typed parse (`130` → `1:30`) committing on blur/Enter. Error code `ET3050` inside the shared date-time block.
277
664
 
278
- - [`4c6b6d0`](https://github.com/ethlete-io/ethdk/commit/4c6b6d000ba568d73c8b191c52fed3206b6a00a6) Thanks [@TomTomB](https://github.com/TomTomB)! - Chip: filter-chip support — `etSelectionList` + `etSelectionOption` compose directly onto `et-chip` for selectable chip groups (single or multiple), with a color-theme tonal selected state and hover/focus affordances. Selection options now tolerate late-bound `value` inputs (directive compositions no longer throw NG0950).
665
+ - [`4c6b6d0`](https://github.com/ethlete-io/ethdk/commit/4c6b6d000ba568d73c8b191c52fed3206b6a00a6) Thanks [@TomTomB](https://github.com/TomTomB)! - Chip: filter-chip support - `etSelectionList` + `etSelectionOption` compose directly onto `et-chip` for selectable chip groups (single or multiple), with a color-theme tonal selected state and hover/focus affordances. Selection options now tolerate late-bound `value` inputs (directive compositions no longer throw NG0950).
279
666
 
280
667
  - [`04ffa53`](https://github.com/ethlete-io/ethdk/commit/04ffa53bf3b65977bd4f87d312781faa93057d1f) Thanks [@TomTomB](https://github.com/TomTomB)! - Forms: fix bugs and accessibility issues across the form controls, and add a few
281
668
  opt-in APIs.
@@ -298,31 +685,31 @@
298
685
  password `hideLabel`, phone `countryLabel`, date-picker-panel `dialogLabel`.
299
686
  - **Note:** the checkbox now toggles on `keydown` Space (matching switch and the
300
687
  selection options), and the select panel renders its listbox as an inner
301
- element — restyle if you targeted the panel host as the listbox.
688
+ element - restyle if you targeted the panel host as the listbox.
302
689
 
303
690
  - [`888ce8a`](https://github.com/ethlete-io/ethdk/commit/888ce8a504c7001f2fb50ae83302483d7148486a) Thanks [@TomTomB](https://github.com/TomTomB)! - Forms consistency: `readonly` and one-click clearing across more controls.
304
- - Checkbox, switch and the three selection-list groups now honor `readonly` (e.g. from a `readonly(...)` schema): normal look, still focusable (`aria-readonly`), toggling/selecting blocked — arrows in a readonly radio group move focus without selecting.
691
+ - Checkbox, switch and the three selection-list groups now honor `readonly` (e.g. from a `readonly(...)` schema): normal look, still focusable (`aria-readonly`), toggling/selecting blocked - arrows in a readonly radio group move focus without selecting.
305
692
  - Date, time, date-time, duration and phone inputs render a clear (×) button while the focused field holds a value (`clearable`, default on; label via `clearLabel`), backed by a public `clearValue()` on their headless directives.
306
693
 
307
694
  - [`85d7332`](https://github.com/ethlete-io/ethdk/commit/85d73327be9a5fc2154c5a0f0f2defe25e657a55) Thanks [@TomTomB](https://github.com/TomTomB)! - Masked input: the mask now attaches through a public `INPUT_MASK_HOST` contract (provided by `et-input` out of the box), so custom field directives can host `[etInputMask]` too. Pattern masks additionally expose `complete()` on the directive (`0`/`a`/`*` slots required, `9` optional; `null` for masks without completeness) via a new optional `MaskSpec.isComplete`.
308
695
 
309
- - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Masked input: new `[etInputMask]` directive layering input masking onto `et-input` — pattern-string masks (`00-00-0000` style grammar) or `MaskSpec` objects, with `createCurrencyMask` / `createIbanMask` / `createCardMask` factories, raw-or-masked form values (`maskValueMode`, raw by default), focused-state guide placeholders (`placeholderChar`) and full caret handling (`MASKED_INPUT_IMPORTS`).
696
+ - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Masked input: new `[etInputMask]` directive layering input masking onto `et-input` - pattern-string masks (`00-00-0000` style grammar) or `MaskSpec` objects, with `createCurrencyMask` / `createIbanMask` / `createCardMask` factories, raw-or-masked form values (`maskValueMode`, raw by default), focused-state guide placeholders (`placeholderChar`) and full caret handling (`MASKED_INPUT_IMPORTS`).
310
697
 
311
698
  - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Number input: new `stepper` input on `et-number-input` rendering −/+ buttons with press-and-hold auto-repeat, `min`/`max` clamping and bound-aware disabling; the headless `NumberInputDirective` gains `stepBy(direction)` / `canStepUp` / `canStepDown`. Adds the `et-minus` built-in icon.
312
699
 
313
- - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Password input: new `et-password-input` / `[etPasswordInput]` (`PASSWORD_INPUT_IMPORTS`) — reveal toggle (`revealed` model, `revealable`, `aria-pressed`), opt-in Caps Lock warning (`capsLockWarning`), and a `strength` signal (0–4 typing-feedback heuristic) for composing strength meters. Adds `et-eye` / `et-eye-slash` built-in icons.
700
+ - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Password input: new `et-password-input` / `[etPasswordInput]` (`PASSWORD_INPUT_IMPORTS`) - reveal toggle (`revealed` model, `revealable`, `aria-pressed`), opt-in Caps Lock warning (`capsLockWarning`), and a `strength` signal (0–4 typing-feedback heuristic) for composing strength meters. Adds `et-eye` / `et-eye-slash` built-in icons.
314
701
 
315
702
  - [`36ac99d`](https://github.com/ethlete-io/ethdk/commit/36ac99db8ccf70597d2dda3e845effe4e0687ba9) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: full tag-input ergonomics in custom-value mode (`allowCustomValues`).
316
- - A "Create …" listbox row (label via `createLabel`) now offers the query as a custom value even while options still match — keyboard-reachable via virtual focus; headless compositions use `customValueCandidate()` + `customValueOption`.
317
- - New inputs: `customValueSeparators` (characters that commit while typing and split pastes), `commitCustomValueOnClose` (pending text commits on Tab/outside-click close instead of being discarded), `normalizeCustomValue` (map/reject raw text), and `maxSelection` (caps multi selection and locks the search input while full, exposed as `isFull()`; unselected options render disabled while full — deselecting frees them again).
703
+ - A "Create …" listbox row (label via `createLabel`) now offers the query as a custom value even while options still match - keyboard-reachable via virtual focus; headless compositions use `customValueCandidate()` + `customValueOption`.
704
+ - New inputs: `customValueSeparators` (characters that commit while typing and split pastes), `commitCustomValueOnClose` (pending text commits on Tab/outside-click close instead of being discarded), `normalizeCustomValue` (map/reject raw text), and `maxSelection` (caps multi selection and locks the search input while full, exposed as `isFull()`; unselected options render disabled while full - deselecting frees them again).
318
705
  - `commitCustomValue(raw)` is now public for imperative commits.
319
706
 
320
- - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new `et-select-option-group` / `[etSelectOptionGroup]` for labelled listbox sections. Grouping is presentational — options stay flat for keyboard navigation and typeahead — and a group hides itself once all its options are filtered out under `filterMode="internal"`. `role="group"` + `aria-labelledby`; token `--et-select-option-group-label-font-size`. Error code `ET1009`.
707
+ - [`f005c94`](https://github.com/ethlete-io/ethdk/commit/f005c944f7edf67842d0a3e635d7e35e8de44445) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new `et-select-option-group` / `[etSelectOptionGroup]` for labelled listbox sections. Grouping is presentational - options stay flat for keyboard navigation and typeahead - and a group hides itself once all its options are filtered out under `filterMode="internal"`. `role="group"` + `aria-labelledby`; token `--et-select-option-group-label-font-size`. Error code `ET1009`.
321
708
 
322
- - [`b61ad0f`](https://github.com/ethlete-io/ethdk/commit/b61ad0fbe61ed1b0e7e8cd98e8d673ae91f10ff1) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new `selectOptionsFromV2Query` feeds the async select from a legacy `V2QueryClient` query (or a `createLegacyQueryCreator` interop wrapper) — the `V2QueryClient` counterpart of `selectOptionsFromQuery`, returning the same signal bundle.
709
+ - [`b61ad0f`](https://github.com/ethlete-io/ethdk/commit/b61ad0fbe61ed1b0e7e8cd98e8d673ae91f10ff1) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new `selectOptionsFromV2Query` feeds the async select from a legacy `V2QueryClient` query (or a `createLegacyQueryCreator` interop wrapper) - the `V2QueryClient` counterpart of `selectOptionsFromQuery`, returning the same signal bundle.
323
710
 
324
711
  - [`4f34f1f`](https://github.com/ethlete-io/ethdk/commit/4f34f1fa2ef1809f6b281d52fdc0f037923e88db) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new data-driven `options` input with built-in virtualization for large option lists.
325
- - `options` takes `SelectOptionData[]` (`{ value, label, disabled? }`) — the select renders the rows itself and windows them, so only the rows near the viewport exist in the DOM (2000 options ≈ 15 rendered nodes). Internal filtering, keyboard navigation, typeahead and closed-panel label resolution work across the full data set.
712
+ - `options` takes `SelectOptionData[]` (`{ value, label, disabled? }`) - the select renders the rows itself and windows them, so only the rows near the viewport exist in the DOM (2000 options ≈ 15 rendered nodes). Internal filtering, keyboard navigation, typeahead and closed-panel label resolution work across the full data set.
326
713
  - `etSelectOptionTemplate` customizes the row content of data-driven options, with the source entry (extra fields included) as template context.
327
714
  - Headless: `etSelectViewport` marks the scroll container to window against, `etSelectVirtualOption` renders one windowed item, and `virtualizedItems()` / `virtualWindow` on `[etSelect]` expose the window state.
328
715
  - Breaking for headless consumers of `SelectItem`: `elementRef` is now `element: Signal<HTMLElement | null>` (`null` for a data-driven option outside the rendered window).
@@ -349,7 +736,7 @@
349
736
 
350
737
  - [`f1841b7`](https://github.com/ethlete-io/ethdk/commit/f1841b7ec3a4f6e280c961d072a90fd2ceba75d7) Thanks [@TomTomB](https://github.com/TomTomB)! - Phone input: picking a country prefix now moves focus to the number field instead of back to the prefix toggle (closing the picker with Escape still refocuses the toggle).
351
738
 
352
- - [`57a5104`](https://github.com/ethlete-io/ethdk/commit/57a5104d3805824cf6b28725c5d9aae670af9626) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: rubber-band overscroll (macOS) no longer drags the panel background along with the list, exposing the page behind the overlay — the panel chrome now sits on a non-scrolling element around an inner `.et-select-panel-scroller`.
739
+ - [`57a5104`](https://github.com/ethlete-io/ethdk/commit/57a5104d3805824cf6b28725c5d9aae670af9626) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: rubber-band overscroll (macOS) no longer drags the panel background along with the list, exposing the page behind the overlay - the panel chrome now sits on a non-scrolling element around an inner `.et-select-panel-scroller`.
353
740
 
354
741
  - [`fa0e118`](https://github.com/ethlete-io/ethdk/commit/fa0e1189f46a5359f5018fba15fbb405af646314) Thanks [@TomTomB](https://github.com/TomTomB)! - Select option checkmarks and menu radio/checkbox item indicators now render on the right (trailing) edge of their row instead of the left, so option labels align flush with the row start. Standalone form controls (checkbox, radio, switch, selection lists, cascader check squares) keep their leading position.
355
742
 
@@ -371,11 +758,11 @@
371
758
  - Calendar: month navigation slides the new grid in from the travel direction (skipped under `prefers-reduced-motion`); the headless `[etCalendar]` exposes `navigationDirection` and `visibleMonthKey` for custom transitions. In the bottom sheet the calendar reserves the 6-week height so the sheet never resizes.
372
759
  - Calendar / time picker: keyboard focus is no longer lost when the focused cell/option is re-created mid-interaction (month crossing, an off-step option leaving the list).
373
760
 
374
- - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d651c4c`](https://github.com/ethlete-io/ethdk/commit/d651c4ccacb309db808f71ebc6ceda8e5e0ffe82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-otp-input` control (`OTP_INPUT_IMPORTS`) — segmented one-time-code/PIN entry backed by a single invisible native input for reliable SMS autofill (`autocomplete="one-time-code"`) and native paste. `length`/`charset` (numeric, alphanumeric or RegExp)/`masked` inputs, a `completed` output per full entry, separator-stripping paste handling, and tokens `--et-otp-input-segment-size/-gap/-radius`. Typed characters pop in and the active segment shows a blinking synthetic caret (both respect `prefers-reduced-motion`).
761
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d651c4c`](https://github.com/ethlete-io/ethdk/commit/d651c4ccacb309db808f71ebc6ceda8e5e0ffe82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-otp-input` control (`OTP_INPUT_IMPORTS`) - segmented one-time-code/PIN entry backed by a single invisible native input for reliable SMS autofill (`autocomplete="one-time-code"`) and native paste. `length`/`charset` (numeric, alphanumeric or RegExp)/`masked` inputs, a `completed` output per full entry, separator-stripping paste handling, and tokens `--et-otp-input-segment-size/-gap/-radius`. Typed characters pop in and the active segment shows a blinking synthetic caret (both respect `prefers-reduced-motion`).
375
762
 
376
- - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d651c4c`](https://github.com/ethlete-io/ethdk/commit/d651c4ccacb309db808f71ebc6ceda8e5e0ffe82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-rating` control (star rating, `RATING_IMPORTS`) — `FormValueControl<number | null>` implementing the slider pattern: hover preview, drag/swipe rating (mouse and touch, commits on release), half steps (`allowHalf`), click-again/Backspace to clear, arrow-key stepping, and a custom icon slot (`ng-template[etRatingIcon]`). The fill animates as one continuous sweep. Tokens `--et-rating-icon-size` / `--et-rating-gap`.
763
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d651c4c`](https://github.com/ethlete-io/ethdk/commit/d651c4ccacb309db808f71ebc6ceda8e5e0ffe82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-rating` control (star rating, `RATING_IMPORTS`) - `FormValueControl<number | null>` implementing the slider pattern: hover preview, drag/swipe rating (mouse and touch, commits on release), half steps (`allowHalf`), click-again/Backspace to clear, arrow-key stepping, and a custom icon slot (`ng-template[etRatingIcon]`). The fill animates as one continuous sweep. Tokens `--et-rating-icon-size` / `--et-rating-gap`.
377
764
 
378
- - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d651c4c`](https://github.com/ethlete-io/ethdk/commit/d651c4ccacb309db808f71ebc6ceda8e5e0ffe82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-tag-input` control (`TAG_INPUT_IMPORTS`) — free-text tags as removable chips with an inline field inside the `et-form-field` shell. Commits on configurable `separators` (Enter/comma by default) and blur, `normalizeTag`/`allowDuplicates`/`maxTags`, Backspace removes the last tag, and pastes split on separators and newlines. For tags with suggestions, compose the select (`multiple` + search + `allowCustomValues`) instead.
765
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`d651c4c`](https://github.com/ethlete-io/ethdk/commit/d651c4ccacb309db808f71ebc6ceda8e5e0ffe82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-tag-input` control (`TAG_INPUT_IMPORTS`) - free-text tags as removable chips with an inline field inside the `et-form-field` shell. Commits on configurable `separators` (Enter/comma by default) and blur, `normalizeTag`/`allowDuplicates`/`maxTags`, Backspace removes the last tag, and pastes split on separators and newlines. For tags with suggestions, compose the select (`multiple` + search + `allowCustomValues`) instead.
379
766
 
380
767
  - [#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)! - Forms: three new form-field controls and a small headless API addition.
381
768
  - `et-textarea` (+ headless `TextareaDirective`): multi-line plain-text control with autosize on by default (`rows`, `minRows`, `maxRows`, `resize`).
@@ -383,17 +770,17 @@
383
770
  - `et-color-input` (+ headless `ColorInputDirective`): native color picker as a swatch + hex value, form value `'#rrggbb' | null`; tokens `--et-color-input-swatch-size` / `--et-color-input-swatch-radius`.
384
771
  - `InputDirective` (and the new input directives) now expose a public `nativeControl` signal referencing the native element, for integrations such as input masking.
385
772
 
386
- - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`e0b71b1`](https://github.com/ethlete-io/ethdk/commit/e0b71b19a3a14c2c2250d7a217299f7956bb5c3b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `provideIconOverrides()` to swap the built-in `et-*` icons app-wide (or per subtree) — e.g. with your own Font Awesome set. Overrides are keyed by name/variant and merged on top of each component's own `provideIcons()`, so they reach into components that self-register the same name while leaving unlisted icons on their default. The override `name` autocompletes to the built-in set via the new `ET_BUILT_IN_ICON_NAMES` / `EtBuiltInIconName` exports, and any other string still registers a brand-new icon.
773
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`e0b71b1`](https://github.com/ethlete-io/ethdk/commit/e0b71b19a3a14c2c2250d7a217299f7956bb5c3b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `provideIconOverrides()` to swap the built-in `et-*` icons app-wide (or per subtree) - e.g. with your own Font Awesome set. Overrides are keyed by name/variant and merged on top of each component's own `provideIcons()`, so they reach into components that self-register the same name while leaving unlisted icons on their default. The override `name` autocompletes to the built-in set via the new `ET_BUILT_IN_ICON_NAMES` / `EtBuiltInIconName` exports, and any other string still registers a brand-new icon.
387
774
 
388
- - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`f168303`](https://github.com/ethlete-io/ethdk/commit/f168303bf0a78c559d6733d04c92a1a1c632d42a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: new `et-multi-language-rich-text-editor` — authors the same content in several consumer-defined `languages`, switching between them from a toolbar dropdown that flags which languages are still empty. Its value is a `Record<languageCode, markdown>`, so every translation persists in one form field; bind it with `[formField]` and use the exported `requiredLanguages` validator to require specific translations.
775
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`f168303`](https://github.com/ethlete-io/ethdk/commit/f168303bf0a78c559d6733d04c92a1a1c632d42a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: new `et-multi-language-rich-text-editor` - authors the same content in several consumer-defined `languages`, switching between them from a toolbar dropdown that flags which languages are still empty. Its value is a `Record<languageCode, markdown>`, so every translation persists in one form field; bind it with `[formField]` and use the exported `requiredLanguages` validator to require specific translations.
389
776
 
390
- - [#3024](https://github.com/ethlete-io/ethdk/pull/3024) [`144832a`](https://github.com/ethlete-io/ethdk/commit/144832ae74abfdbe8f084c14d6a903ee2eda18cf) Thanks [@TomTomB](https://github.com/TomTomB)! - Forms: new `et-phone-input` control (`PHONE_INPUT_IMPORTS`) — tel entry with a searchable country picker built on the select's headless core. Value is normalized `+<dial><national>`.
777
+ - [#3024](https://github.com/ethlete-io/ethdk/pull/3024) [`144832a`](https://github.com/ethlete-io/ethdk/commit/144832ae74abfdbe8f084c14d6a903ee2eda18cf) Thanks [@TomTomB](https://github.com/TomTomB)! - Forms: new `et-phone-input` control (`PHONE_INPUT_IMPORTS`) - tel entry with a searchable country picker built on the select's headless core. Value is normalized `+<dial><national>`.
391
778
  - Typing/pasting `+…` (or a `00…` international prefix) re-derives the country by longest dial-code match; manual picks survive shared codes like `+1`, switching countries keeps the national number, and a leading national trunk `0` is stripped (`0171…` → `+49171…`).
392
779
  - Digits are grouped for display while unfocused (cosmetic only); the country picker searches names and dial codes, shows an empty state, keeps a fixed panel width, and takes custom flag art via `ng-template[etPhoneInputFlag]`.
393
780
  - Zero runtime dependency: ISO + dial codes shipped, names via `Intl.DisplayNames`, emoji flags.
394
781
  - The underlying select gained a `mirrorPanelWidth` input (off for compact triggers), with the panel capped at `min(400px, 100vw - 24px)`.
395
782
 
396
- - [#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.
783
+ - [#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.
397
784
 
398
785
  - [#3024](https://github.com/ethlete-io/ethdk/pull/3024) [`144832a`](https://github.com/ethlete-io/ethdk/commit/144832ae74abfdbe8f084c14d6a903ee2eda18cf) Thanks [@TomTomB](https://github.com/TomTomB)! - Rich text editor: mobile toolbar and editing fixes.
399
786
  - On touch devices the static toolbar docks above the on-screen keyboard while editing (tracked via `visualViewport`, staying pinned as the page scrolls and inside a same-origin iframe) instead of sitting at the top under the platform's selection menu; it fades in only once the editor is active and its menus open without stealing keyboard focus. With a mouse/trackpad it stays at the top as before.
@@ -404,19 +791,19 @@
404
791
  - `OverlayRef` gained `afterClosedEvent()`, which also reports how the overlay was closed (`escape`, `outside-pointer`, `api`, …).
405
792
 
406
793
  - [#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:
407
- - Table tool: the grid-size picker supports touch — drag across the grid to size the table and release to insert; when a table's header row was deleted the menu offers **Insert header row**, and inserting a row from the header now lands in the table body.
794
+ - Table tool: the grid-size picker supports touch - drag across the grid to size the table and release to insert; when a table's header row was deleted the menu offers **Insert header row**, and inserting a row from the header now lands in the table body.
408
795
  - The link editor and floating toolbar anchor to the selected text (not the full-width block) so the arrow points at the text, and the link editor now opens correctly in an empty editor.
409
796
  - The trailing space inserted after atomic tokens (mentions, merge fields) and line-ending links is now a no-break space (Chrome dropped the plain one, gluing the next word); it still serializes as a regular space.
410
797
  - Form field: the `inline` label mode now lays out correctly around rich text editors.
411
- - `RichTextEditorToolDefinition` gains an optional `keydown` hook; table caret navigation now ships with `provideRichTextEditorTableTool` via that hook instead of being bundled into every editor (`editorDom.tableExit` / `tableEnter` are removed) — provide the table tool if your content can contain tables.
798
+ - `RichTextEditorToolDefinition` gains an optional `keydown` hook; table caret navigation now ships with `provideRichTextEditorTableTool` via that hook instead of being bundled into every editor (`editorDom.tableExit` / `tableEnter` are removed) - provide the table tool if your content can contain tables.
412
799
 
413
800
  - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`1f03013`](https://github.com/ethlete-io/ethdk/commit/1f03013609e8a734788db5b3b7657973fb430b87) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: toolbar accessibility and pressed-state polish.
414
801
  - Toolbar buttons that open a menu or popover (heading, alignment, table, link) now show their pressed state while the popover is open.
415
802
  - The toolbar is now a single tab stop following the ARIA toolbar pattern: Tab enters it, `ArrowLeft`/`ArrowRight` (plus `Home`/`End`) move focus between buttons, and the next Tab moves on to the editor content.
416
803
  - `et-icon-button` now forwards the `emitAriaPressed` input, so `aria-pressed` can be suppressed on pressed-styled buttons that already expose `aria-expanded`.
417
804
 
418
- - [#3024](https://github.com/ethlete-io/ethdk/pull/3024) [`144832a`](https://github.com/ethlete-io/ethdk/commit/144832ae74abfdbe8f084c14d6a903ee2eda18cf) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new `et-select` form control — a combobox-pattern trigger opening an anchored, width-mirrored listbox panel (`SELECT_IMPORTS`, plus the headless `[etSelect]` / `[etSelectTrigger]` / `ng-template[etSelectSurface]` / `[etSelectListbox]` / `[etSelectOption]` graph and `et-select-panel` / `et-select-option`). Integrates with `et-form-field` (new `select` control type, all label modes).
419
- - Single select: full keyboard model — arrows/Home/End move virtual focus via `aria-activedescendant`, Enter/Space commit, typeahead while open, printable keys commit directly while closed; resolves a preselected value's label without ever opening the panel.
805
+ - [#3024](https://github.com/ethlete-io/ethdk/pull/3024) [`144832a`](https://github.com/ethlete-io/ethdk/commit/144832ae74abfdbe8f084c14d6a903ee2eda18cf) Thanks [@TomTomB](https://github.com/TomTomB)! - Select: new `et-select` form control - a combobox-pattern trigger opening an anchored, width-mirrored listbox panel (`SELECT_IMPORTS`, plus the headless `[etSelect]` / `[etSelectTrigger]` / `ng-template[etSelectSurface]` / `[etSelectListbox]` / `[etSelectOption]` graph and `et-select-panel` / `et-select-option`). Integrates with `et-form-field` (new `select` control type, all label modes).
806
+ - Single select: full keyboard model - arrows/Home/End move virtual focus via `aria-activedescendant`, Enter/Space commit, typeahead while open, printable keys commit directly while closed; resolves a preselected value's label without ever opening the panel.
420
807
  - Multi select (`multiple`): array value, options toggle without closing (`aria-multiselectable`), selection shown as removable `et-chip`s; `deselectOption(...)` and a customizable `ng-template[etSelectValue]`.
421
808
  - Search (`input[etSelectSearch]`): inline searchable combobox; `filterMode` `'internal'` (default) or `'external'` (via the `queryChange` output), `allowCustomValues`, and `selectOptionsFromQuery(...)` to feed options from an `@ethlete/query` query (debounce, `minQueryLength`, `toHasMore` pagination).
422
809
  - Async state inputs `loading` / `error` / `hasMoreItems` render default panel rows (spinner / alert / load-more via `loadMoreRequested`), each overridable through `ng-template[etSelectLoading]` / `[etSelectError]` / `[etSelectEmpty]`.
@@ -426,28 +813,28 @@
426
813
  - Form field exposes `controlFrameElement` on its contract so overlay-based controls can anchor their panels to the visible box.
427
814
 
428
815
  - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`bd8ec82`](https://github.com/ethlete-io/ethdk/commit/bd8ec8205d080bbfad58760dab13d346159b7a1c) Thanks [@github-actions](https://github.com/apps/github-actions)! - New time controls:
429
- - `et-time-picker` (+ headless `[etTimePicker]` column/option directives): inline column-list time picker on `Date` values — columns derive from a date-fns format (12/24h, optional seconds, AM/PM), `minuteStep`/`secondStep`, roving-focus listbox columns with wrapping arrows and type-to-jump.
816
+ - `et-time-picker` (+ headless `[etTimePicker]` column/option directives): inline column-list time picker on `Date` values - columns derive from a date-fns format (12/24h, optional seconds, AM/PM), `minuteStep`/`secondStep`, roving-focus listbox columns with wrapping arrows and type-to-jump.
430
817
  - `et-time-input` (+ headless `[etTimeInput]`): string-valued form control (`TIME_FORMAT` token, default `HH:mm`) with lenient typed parsing (`930` → 09:30, `9pm`, `9.30`) and an anchored time-picker overlay that stays open across part picks.
431
818
 
432
819
  ### Patch Changes
433
820
 
434
821
  - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`56a38d5`](https://github.com/ethlete-io/ethdk/commit/56a38d5f68c3f4a5d866757de23e06d0662aae25) Thanks [@github-actions](https://github.com/apps/github-actions)! - Date & time inputs: the picker trigger buttons now have a 44px tap target (invisible hit-area extension, no visual change). Time picker: options gain visual hierarchy (muted until interacted, tinted roving anchor, column separators) and the columns keep a half-faded number at each edge as a scroll cue.
435
822
 
436
- - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`1d8b757`](https://github.com/ethlete-io/ethdk/commit/1d8b7570f7d65a59616b99a93243b4ba7a9c9d53) Thanks [@github-actions](https://github.com/apps/github-actions)! - Icons: the `@ethlete/components:icons` generator no longer emits a `GENERATED_ICONS` aggregate array — spreading it into `provideIcons()` registered every icon and defeated tree shaking. Import the individual `IconDefinition` constants instead; re-running the generator removes the array from the generated file.
823
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`1d8b757`](https://github.com/ethlete-io/ethdk/commit/1d8b7570f7d65a59616b99a93243b4ba7a9c9d53) Thanks [@github-actions](https://github.com/apps/github-actions)! - Icons: the `@ethlete/components:icons` generator no longer emits a `GENERATED_ICONS` aggregate array - spreading it into `provideIcons()` registered every icon and defeated tree shaking. Import the individual `IconDefinition` constants instead; re-running the generator removes the array from the generated file.
437
824
 
438
825
  - [#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)! - Overlay: anchored arrows (menu, tooltip, toggletip) now match the pane's actual background and border, so an arrow no longer stays a surface elevation too low when its pane sits on a raised surface (e.g. a menu opened from a filled form-field).
439
826
 
440
827
  - [#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.
441
828
 
442
829
  - [#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.
443
- - `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.
830
+ - `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.
444
831
  - 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.
445
832
 
446
- - [#3025](https://github.com/ethlete-io/ethdk/pull/3025) [`416cfb8`](https://github.com/ethlete-io/ethdk/commit/416cfb8c3f370783a96b2fe59b827e981cac7b17) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay sheets: fix the black gap that appeared at the docked edge while a sheet sprang into view. The enter spring overshoots slightly past the docked edge, and the filler meant to cover that gap was an `::after` strip positioned just outside the host — which sheets clip away with their `overflow: hidden` (kept for the rounded corners), so nothing painted and the page background showed through (most visible with sheets whose surface is painted on nested content, e.g. the date picker). The filler is now a solid offset `box-shadow`, which is not clipped by the host's own overflow and needs no change to the corner clipping. Its color is measured from the sheet's actually-painted surface at open time, so it matches even when that surface sits on nested content one elevation above the container host (where the host's own surface token would be a shade off).
833
+ - [#3025](https://github.com/ethlete-io/ethdk/pull/3025) [`416cfb8`](https://github.com/ethlete-io/ethdk/commit/416cfb8c3f370783a96b2fe59b827e981cac7b17) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay sheets: fix the black gap that appeared at the docked edge while a sheet sprang into view. The enter spring overshoots slightly past the docked edge, and the filler meant to cover that gap was an `::after` strip positioned just outside the host - which sheets clip away with their `overflow: hidden` (kept for the rounded corners), so nothing painted and the page background showed through (most visible with sheets whose surface is painted on nested content, e.g. the date picker). The filler is now a solid offset `box-shadow`, which is not clipped by the host's own overflow and needs no change to the corner clipping. Its color is measured from the sheet's actually-painted surface at open time, so it matches even when that surface sits on nested content one elevation above the container host (where the host's own surface token would be a shade off).
447
834
 
448
835
  - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`1fa8e45`](https://github.com/ethlete-io/ethdk/commit/1fa8e4543c976658d0fbee5902ce43b9418932c3) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: the sidebar page component no longer triggers an `NG0912` component ID collision when `@ethlete/cdk` is loaded in the same app.
449
836
 
450
- - [#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 selection (floating) toolbar is now a pointer-device-only enhancement. On touch it fought the platform's native selection menu (Copy/Paste/…) and appeared unreliably, so it is suppressed there — the always-visible static toolbar covers formatting on touch. Mouse/trackpad behavior is unchanged.
837
+ - [#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 selection (floating) toolbar is now a pointer-device-only enhancement. On touch it fought the platform's native selection menu (Copy/Paste/…) and appeared unreliably, so it is suppressed there - the always-visible static toolbar covers formatting on touch. Mouse/trackpad behavior is unchanged.
451
838
 
452
839
  - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`428f971`](https://github.com/ethlete-io/ethdk/commit/428f9718c96038a4aa9fee603b11ea341c7fe99b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor fixes:
453
840
  - The table size picker now supports arrow-key navigation (Enter/Space inserts the selected size, Escape/Tab close the menu from a focused cell).
@@ -463,7 +850,7 @@
463
850
 
464
851
  - [#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)! - Rich text editor: add opt-in, tree-shakeable building-block autocomplete. Add the
465
852
  `etRichTextEditorTriggers` directive (with `RICH_TEXT_EDITOR_TRIGGERS_IMPORTS`) and pass triggers
466
- built with `createRichTextEditorTrigger` — typing a trigger char (e.g. `#`, `@`) opens a
853
+ built with `createRichTextEditorTrigger` - typing a trigger char (e.g. `#`, `@`) opens a
467
854
  caret-anchored, menu-styled popup, and picking an item inserts an atomic `{{type:id}}` token chip.
468
855
  Item sources can be static, `Promise`, or `Observable`. Use `provideRichTextEditorTokenRendering(...)`
469
856
  to render stored token values as chips in read-only contexts, or `createRichTextEditorTriggerWithQuery(...)`
@@ -481,7 +868,7 @@
481
868
 
482
869
  `@ethlete/core`: `markdownToHtml`/`htmlToMarkdown` now round-trip **nested** lists (two-space indentation per level), instead of flattening them.
483
870
 
484
- - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Rich text editor: Markdown autoformat while typing (opt out with `autoformat=false`). Line-start prefixes convert on space — `-`/`*`/`+` into a bulleted list, `1.` into a numbered list, `#`–`###` into a heading — and closing an inline run (`**bold**`, `*italic*`, `` `code` ``, `~~strike~~`, `__`/`_`) converts it into its mark with the caret placed after it. Autoformat is token-aware: registered trigger characters are reserved (a `#` trigger keeps opening its autocomplete instead of becoming a heading) and conversion is suspended while a trigger popup is open.
871
+ - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Rich text editor: Markdown autoformat while typing (opt out with `autoformat=false`). Line-start prefixes convert on space - `-`/`*`/`+` into a bulleted list, `1.` into a numbered list, `#`–`###` into a heading - and closing an inline run (`**bold**`, `*italic*`, `` `code` ``, `~~strike~~`, `__`/`_`) converts it into its mark with the caret placed after it. Autoformat is token-aware: registered trigger characters are reserved (a `#` trigger keeps opening its autocomplete instead of becoming a heading) and conversion is suspended while a trigger popup is open.
485
872
 
486
873
  - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Rich text editor: pasted HTML is now normalized into the editor's own schema (foreign tags, inline styles, classes and scripts never enter the editable DOM; token chips keep their identity), and pressing Enter at the edge of a heading starts a plain paragraph instead of continuing the heading. Shift+Enter always stays a soft line break.
487
874
 
@@ -493,7 +880,7 @@
493
880
 
494
881
  - [#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.
495
882
 
496
- 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.
883
+ 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.
497
884
 
498
885
  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.
499
886
 
@@ -501,22 +888,22 @@
501
888
 
502
889
  ### Patch Changes
503
890
 
504
- - [#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
891
+ - [#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
505
892
  content resizes (baseline captured on first render so the initial layout never plays as a
506
893
  grow-from-0, interruption-safe, respects `prefers-reduced-motion`). `et-menu` and the rich text
507
894
  editor's trigger popup now share it, giving a more consistent, smoother resize.
508
895
 
509
- - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Form field: the disabled treatment (dimmed frame, blocked pointer events, hint color) is now driven by the registered control's disabled state via a `data-disabled` host attribute instead of `:has(:disabled)` — a composite control like the rich text editor can disable individual toolbar buttons without the whole field being dimmed and made unclickable.
896
+ - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Form field: the disabled treatment (dimmed frame, blocked pointer events, hint color) is now driven by the registered control's disabled state via a `data-disabled` host attribute instead of `:has(:disabled)` - a composite control like the rich text editor can disable individual toolbar buttons without the whole field being dimmed and made unclickable.
510
897
 
511
- - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`7e4c883`](https://github.com/ethlete-io/ethdk/commit/7e4c8832493b8c8b505efd80acfa147d90bc9523) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form field: only a `filled` field raises the surface elevation for its contents — a `transparent` field now stays flush with its parent surface instead of bumping elevation without a painted background.
898
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`7e4c883`](https://github.com/ethlete-io/ethdk/commit/7e4c8832493b8c8b505efd80acfa147d90bc9523) Thanks [@github-actions](https://github.com/apps/github-actions)! - Form field: only a `filled` field raises the surface elevation for its contents - a `transparent` field now stays flush with its parent surface instead of bumping elevation without a painted background.
512
899
 
513
900
  Rich text editor: the autocomplete popup no longer renders one elevation too high (it now matches menus), and its "source failed" error state is a centered icon-and-message panel instead of a stray line in an empty box.
514
901
 
515
- Rich text editor: token chips (merge fields, mentions) now render as a tonal accent pill with a hairline ring — and keep their trigger char (`@`, `#`, …) visible as a de-emphasized prefix — so they read clearly as distinct entities in the prose, instead of a faint neutral highlight.
902
+ Rich text editor: token chips (merge fields, mentions) now render as a tonal accent pill with a hairline ring - and keep their trigger char (`@`, `#`, …) visible as a de-emphasized prefix - so they read clearly as distinct entities in the prose, instead of a faint neutral highlight.
516
903
 
517
- Rich text editor: the selection formatting toolbar now mounts through the overlay system (like the autocomplete popup) instead of a manually-positioned fixed element — so it shares the same anchoring, stacking, theming, and enter/leave animation.
904
+ Rich text editor: the selection formatting toolbar now mounts through the overlay system (like the autocomplete popup) instead of a manually-positioned fixed element - so it shares the same anchoring, stacking, theming, and enter/leave animation.
518
905
 
519
- - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`d362747`](https://github.com/ethlete-io/ethdk/commit/d3627470bddd16a6b76577ac8d3dc43d9d7fdd2e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: the anchored arrow now matches the pane it points at — it paints the
906
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`d362747`](https://github.com/ethlete-io/ethdk/commit/d3627470bddd16a6b76577ac8d3dc43d9d7fdd2e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlay: the anchored arrow now matches the pane it points at - it paints the
520
907
  pane's actual background and mirrors its border (including no border when the
521
908
  pane has none), instead of re-deriving a color from surface tokens that could
522
909
  diverge from a custom `panelClass` or themed pane.
@@ -525,7 +912,7 @@
525
912
 
526
913
  - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Rich text editor: the alignment tool now applies to the whole table column (GFM alignment is per column, so a single aligned cell would not survive serialization) and disables itself inside lists, where alignment has no serialized form. Lists swept up by a cross-block selection are skipped instead of receiving a lost `text-align`.
527
914
 
528
- - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`bf72655`](https://github.com/ethlete-io/ethdk/commit/bf7265505ecaf77f2bc239fd945f763655af5b82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: toggling an inline format (bold, italic, underline, strike, code) with **no selection** now works as expected — it sets a pending "stored mark" so the next typed text picks up (or drops) that formatting, instead of doing nothing. The pending state shows in the toolbar and is cleared when you move the caret.
915
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`bf72655`](https://github.com/ethlete-io/ethdk/commit/bf7265505ecaf77f2bc239fd945f763655af5b82) Thanks [@github-actions](https://github.com/apps/github-actions)! - Rich text editor: toggling an inline format (bold, italic, underline, strike, code) with **no selection** now works as expected - it sets a pending "stored mark" so the next typed text picks up (or drops) that formatting, instead of doing nothing. The pending state shows in the toolbar and is cleared when you move the caret.
529
916
 
530
917
  - [`c829986`](https://github.com/ethlete-io/ethdk/commit/c82998628a487effe34d2061811f3cee0fa4f7bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Rich text editor: block alignment is no longer lost when re-tagging between paragraph and heading, and the heading menu now disables itself inside list items (where a heading has no serialized form), matching the table-cell behavior.
531
918
 
@@ -533,7 +920,7 @@
533
920
 
534
921
  - [#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: pressing ArrowRight at the end of an inline code span (or ArrowLeft at its start) now steps the caret outside the code, so continuing to type isn't code.
535
922
 
536
- - [#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: table editing polish — arrow keys now step the caret cleanly across table edges (into the nearest cell when entering, onto a real line when exiting, adding one only when the table is flush against the editor's top/bottom) instead of stranding it at the table border; an empty line directly above a table can be removed with Backspace; and applying an inline format across multiple selected cells now wraps each cell's content within its own cell instead of tearing the table apart.
923
+ - [#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: table editing polish - arrow keys now step the caret cleanly across table edges (into the nearest cell when entering, onto a real line when exiting, adding one only when the table is flush against the editor's top/bottom) instead of stranding it at the table border; an empty line directly above a table can be removed with Backspace; and applying an inline format across multiple selected cells now wraps each cell's content within its own cell instead of tearing the table apart.
537
924
 
538
925
  ## 1.0.0-next.20
539
926
 
@@ -551,7 +938,7 @@
551
938
  - [#3018](https://github.com/ethlete-io/ethdk/pull/3018) [`e8f9bcd`](https://github.com/ethlete-io/ethdk/commit/e8f9bcd65b40724b266aff8949951649afafea36) Thanks [@github-actions](https://github.com/apps/github-actions)! - Move all component styles into the `components` CSS cascade layer (`@layer components`).
552
939
 
553
940
  Component CSS was previously injected unlayered, which meant it beat Tailwind
554
- utility classes (in `@layer utilities`) regardless of specificity — forcing
941
+ utility classes (in `@layer utilities`) regardless of specificity - forcing
555
942
  consumers to reach for `!important` (e.g. `flex!`) to override layout, spacing or
556
943
  sizing on components. Because layer precedence is resolved before specificity,
557
944
  `:where()` could not fix this.
@@ -581,7 +968,7 @@
581
968
  - Overlay configs now merge additively across definition → opener → per-open layers: `bindings`, `providers`, `hostClass`, `backdropClass` and `panelClass` are concatenated instead of the most specific layer silently replacing the rest; scalar options still follow most-specific-wins. The merge is exposed as `mergeOverlayConfigs(...configs)`.
582
969
  - Inside the overlay component, access the typed ref via `definition.injectRef()` (replaces the handler's `injectOverlayRef`). It throws an actionable `RuntimeError` when called outside an open overlay.
583
970
  - `defineQueryParamOverlay` requires the component to expose an `overlayQueryParam` model at compile time (previously a silent runtime requirement), and the opener's `open(value)` is typed from that model's value type. Definition- and opener-level `bindings`/`providers` are now applied on every URL-driven open, so components with additional inputs work with query-param overlays.
584
- - `OverlayHandlerLinkDirective` (`etOverlayHandlerLink` + `etOverlayHandlerQueryParamName`) is replaced by `QueryParamOverlayLinkDirective`: `<a [etQueryParamOverlayLink]="definition" etQueryParamOverlayLinkValue="42">` — the link takes the definition object, so the query param key is no longer duplicated as a string.
971
+ - `OverlayHandlerLinkDirective` (`etOverlayHandlerLink` + `etOverlayHandlerQueryParamName`) is replaced by `QueryParamOverlayLinkDirective`: `<a [etQueryParamOverlayLink]="definition" etQueryParamOverlayLinkValue="42">` - the link takes the definition object, so the query param key is no longer duplicated as a string.
585
972
 
586
973
  Migration:
587
974
 
@@ -609,15 +996,15 @@
609
996
 
610
997
  - [#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.
611
998
 
612
- 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.
999
+ 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.
613
1000
 
614
1001
  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.
615
1002
 
616
1003
  - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`789d765`](https://github.com/ethlete-io/ethdk/commit/789d765e1342f92d1269f1d8a1dbb64e28415708) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: new `et-dropzone` file-upload control with a built-in `@ethlete/query` upload workflow. Import `DROPZONE_IMPORTS`.
617
- - Files are picked via click or drag & drop and uploaded through a consumer-provided query, one query per file. Configure with `createDropzoneUpload({ queryCreator, selectValue, createArgs?, resolveExisting? })` — `selectValue` maps the upload response to the form control value (e.g. `(media) => media.uuid`).
618
- - Signal-forms native (`[formField]`): the control value holds the values of successful uploads (and existing entries) in entry order — `TValue | null` in single mode, `TValue[]` with `multiple`. In-flight and failed uploads never enter the value; block submits via the headless `anyUploading` signal.
1004
+ - Files are picked via click or drag & drop and uploaded through a consumer-provided query, one query per file. Configure with `createDropzoneUpload({ queryCreator, selectValue, createArgs?, resolveExisting? })` - `selectValue` maps the upload response to the form control value (e.g. `(media) => media.uuid`).
1005
+ - Signal-forms native (`[formField]`): the control value holds the values of successful uploads (and existing entries) in entry order - `TValue | null` in single mode, `TValue[]` with `multiple`. In-flight and failed uploads never enter the value; block submits via the headless `anyUploading` signal.
619
1006
  - Built-in UI: per-file progress bars (requires `reportProgress: true` on the query creator and the XHR `HttpClient` backend; degrades to indeterminate otherwise), image previews via object URLs, remove/replace/retry via regular icon buttons, and enter/leave animations (FLIP shift plus scale-out on delete, disabled under `prefers-reduced-motion`). In single mode a successful upload replaces the drop area with a same-size preview (no layout shift).
620
- - Validation lives in the form schema: `required()`/`minLength()`/`maxLength()` cover emptiness and file count, and the new `dropzoneFiles()` schema rule declares file constraints (`accept`, `maxFileSize`, `minFileSize`). Violating files never upload — each violation becomes a regular validation error on the field (customizable via the rule's `message` function) and is emitted via `filesRejected`. Upload failures render as validation-style messages below the field (`uploadErrorMessage` input).
1007
+ - Validation lives in the form schema: `required()`/`minLength()`/`maxLength()` cover emptiness and file count, and the new `dropzoneFiles()` schema rule declares file constraints (`accept`, `maxFileSize`, `minFileSize`). Violating files never upload - each violation becomes a regular validation error on the field (customizable via the rule's `message` function) and is emitted via `filesRejected`. Upload failures render as validation-style messages below the field (`uploadErrorMessage` input).
621
1008
  - Edit forms: values already present in the control render as entries via the `resolveExisting` display resolver.
622
1009
  - Full behavior is available headlessly via the `etDropzone` directive (`entries()`, `lastRejections()`, `selectFiles()`, `removeEntry()`, `retryEntry()`, `clear()`, `isDragOver`, …). Error codes `ET2400`–`ET2499`.
623
1010
 
@@ -627,10 +1014,10 @@
627
1014
 
628
1015
  - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`300afe3`](https://github.com/ethlete-io/ethdk/commit/300afe3f9115f2ff18ca097975a8101690613d24) Thanks [@github-actions](https://github.com/apps/github-actions)! - Grid & Tabs: the previously allocated error codes are now actually enforced, and a nav-tabs composition bug is fixed.
629
1016
  - Tabs (dev mode): `ET2000` when a tab trigger has no enclosing tab bar, `ET2001` when `<et-tab>` / `etTabPanel` sit outside a tab group (an orphan `<et-tab>` used to disappear silently), `ET2002` when a headless tab group has triggers but no panels, `ET2003` when nav-tab pieces are used without `et-nav-tabs`.
630
- - Grid (dev mode): `ET1900` for items outside a grid, `ET1901` for drag/resize handles outside a grid item, `ET1902` for duplicate item ids, `ET1903` when `restoreState()` receives unknown breakpoint names, and the new `GRID_ERROR_CODES.UNKNOWN_ITEM_TYPE` (`ET1904`) when an item's `type` has no registration — previously such items were silently dropped.
1017
+ - Grid (dev mode): `ET1900` for items outside a grid, `ET1901` for drag/resize handles outside a grid item, `ET1902` for duplicate item ids, `ET1903` when `restoreState()` receives unknown breakpoint names, and the new `GRID_ERROR_CODES.UNKNOWN_ITEM_TYPE` (`ET1904`) when an item's `type` has no registration - previously such items were silently dropped.
631
1018
  - Fixed: `<et-nav-tabs-outlet>` placed as a sibling of `<et-nav-tabs>` (the documented composition) crashed with a DI error. It now resolves the tab bar that labels it automatically when exactly one `et-nav-tabs` exists on the page, and still prefers an ancestor tab bar when nested.
632
1019
 
633
- - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`1d324c2`](https://github.com/ethlete-io/ethdk/commit/1d324c2cbdd749cd8b01d52548a5a457a7e462df) Thanks [@github-actions](https://github.com/apps/github-actions)! - Menu: trigger-anchored root menus now render a floating arrow pointing at their trigger, matching the tooltip and toggletip look. The new `arrow` input on `[etMenu]` (default `true`) controls it — set `[arrow]="false"` to opt out — and `arrowPadding` (default `8`) tunes how close the arrow may get to the panel corners. Submenus and context menus (point-anchored) never render an arrow.
1020
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`1d324c2`](https://github.com/ethlete-io/ethdk/commit/1d324c2cbdd749cd8b01d52548a5a457a7e462df) Thanks [@github-actions](https://github.com/apps/github-actions)! - Menu: trigger-anchored root menus now render a floating arrow pointing at their trigger, matching the tooltip and toggletip look. The new `arrow` input on `[etMenu]` (default `true`) controls it - set `[arrow]="false"` to opt out - and `arrowPadding` (default `8`) tunes how close the arrow may get to the panel corners. Submenus and context menus (point-anchored) never render an arrow.
634
1021
  - With the arrow enabled, the `'auto'` offset resolves to `10` so the arrow has room between the panel and its trigger; disabling the arrow restores the previous tight spacing. Submenu and context menu spacing is unchanged.
635
1022
  - The arrow picks up the menu surface theme (`--et-surface-background-solid` / `--et-surface-border-solid`) and can be overridden via `--et-overlay-arrow-background` and `--et-overlay-arrow-border`.
636
1023
 
@@ -638,29 +1025,29 @@
638
1025
  - Borders, separators, muted text (group labels, shortcuts, the search placeholder/spinner) and the search input fill now derive from the surface tokens (`--et-surface-border-solid`, `--et-surface-color-muted-solid`, `--et-surface-interaction-solid`).
639
1026
  - The active menu item highlight is now a `color-mix` tint of `--et-surface-interaction-solid` instead of a fixed white overlay.
640
1027
  - The menu panel resolves its surface via `AutoSurfaceDirective`, automatically picking the next elevation relative to the trigger's surface context.
641
- - Destructive menu items and the search error message now use the app's registered `error` color theme (via `injectErrorTheme()`), so `--et-theme-color-primary-*` resolves to the error palette inside them. The `--et-menu-item-destructive-color` token has been removed — theme the error color theme instead. Like `et-form-field`, `et-menu` now requires color themes (including one with `type: 'error'`) to be registered.
1028
+ - Destructive menu items and the search error message now use the app's registered `error` color theme (via `injectErrorTheme()`), so `--et-theme-color-primary-*` resolves to the error palette inside them. The `--et-menu-item-destructive-color` token has been removed - theme the error color theme instead. Like `et-form-field`, `et-menu` now requires color themes (including one with `type: 'error'`) to be registered.
642
1029
  - Selection item check/radio marks and the search input focus border now use `--et-theme-color-primary-solid` from the surrounding color theme context.
643
- - The active-item highlight now only shows for an actual hover or `:focus-visible` (keyboard) interaction — opening a menu with the mouse no longer highlights the first item, while keyboard-opened menus still do. A trigger item whose submenu is open stays highlighted via `[data-menu-open]`.
644
- - The menu animates its block size (160ms) when its content changes while open — e.g. search filtering items away or the search error line appearing — instead of snapping to the new size. Respects `prefers-reduced-motion`.
645
- - Menu items now have a pressed (`:active`) state — a stronger tint of the surface interaction color (20% vs the 12% highlight) — and transition `background`, `color` and `opacity` (120ms) between their rest, highlighted, pressed and disabled states. The search input transitions its `border-color` and `background`, matching the button's interaction feel.
1030
+ - The active-item highlight now only shows for an actual hover or `:focus-visible` (keyboard) interaction - opening a menu with the mouse no longer highlights the first item, while keyboard-opened menus still do. A trigger item whose submenu is open stays highlighted via `[data-menu-open]`.
1031
+ - The menu animates its block size (160ms) when its content changes while open - e.g. search filtering items away or the search error line appearing - instead of snapping to the new size. Respects `prefers-reduced-motion`.
1032
+ - Menu items now have a pressed (`:active`) state - a stronger tint of the surface interaction color (20% vs the 12% highlight) - and transition `background`, `color` and `opacity` (120ms) between their rest, highlighted, pressed and disabled states. The search input transitions its `border-color` and `background`, matching the button's interaction feel.
646
1033
 
647
1034
  - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`8d5c7dc`](https://github.com/ethlete-io/ethdk/commit/8d5c7dce47c0b04592ebe366354871f177d55f0a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Forms: visual refresh and new options for the selection controls (checkbox group, radio group, segmented button group, switch, choice field).
648
1035
  - Checkbox options and radios: option labels now render in the regular text color at a fixed size, boxes/circles gained hover tint fills, press feedback and a draw-in checkmark animation; the group label is styled like a form-field label (new `--et-<group>-group-label-font-size` tokens).
649
- - Selection-list groups (`et-checkbox-group`, `et-radio-group`, `et-segmented-button-group`) now support a projected `<et-label>` as group label — it shows the required marker (`*`) and wires `aria-labelledby` automatically. The plain `.et-<group>-label` span still works for label text without the marker.
1036
+ - Selection-list groups (`et-checkbox-group`, `et-radio-group`, `et-segmented-button-group`) now support a projected `<et-label>` as group label - it shows the required marker (`*`) and wires `aria-labelledby` automatically. The plain `.et-<group>-label` span still works for label text without the marker.
650
1037
  - Segmented button group: redesigned as a tonal track with a filled active pill that animates between options (flip animation). `--et-segmented-button-border-width` was removed; new tokens `--et-segmented-button-border-radius`, `--et-segmented-button-group-track-padding`, `--et-segmented-button-group-track-radius` and `--et-segmented-button-group-label-font-size`.
651
- - Switch: reworked visuals — the off state uses a neutral tinted track with a smaller muted thumb that grows and slides on toggle, plus a press-stretch effect. Default dimensions changed to a 40×22px track with a 16px thumb.
1038
+ - Switch: reworked visuals - the off state uses a neutral tinted track with a smaller muted thumb that grows and slides on toggle, plus a press-stretch effect. Default dimensions changed to a 40×22px track with a 16px thumb.
652
1039
  - New `size` input (`'sm' | 'md' | 'lg'`, default `'md'`) on `et-checkbox-group`, `et-radio-group`, `et-segmented-button-group` and `et-choice-field`, scaling controls, labels and gaps in line with `et-form-field` sizes.
653
1040
  - Group error states now tint the unchecked control borders with the error color (previously only the error message was colored).
654
1041
  - The control CSS tokens (`--et-checkbox-*`, `--et-checkbox-option-*`, `--et-radio-*`, `--et-segmented-button-*`, `--et-switch-*`) are now registered as inheriting custom properties, so overriding them on the component or a wrapper actually reaches the inner elements that consume them.
655
1042
 
656
- - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`6e9693a`](https://github.com/ethlete-io/ethdk/commit/6e9693a9352d19775f46ab5424cbdea455a14ee5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Button: new split button. `<et-split-button>` groups an action segment (`etSplitButtonAction`) and a trigger segment (`etSplitButtonTrigger`) — both regular surface/icon buttons — into one `role="group"` control with joined corners and a divider between the segments.
1043
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`6e9693a`](https://github.com/ethlete-io/ethdk/commit/6e9693a9352d19775f46ab5424cbdea455a14ee5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Button: new split button. `<et-split-button>` groups an action segment (`etSplitButtonAction`) and a trigger segment (`etSplitButtonTrigger`) - both regular surface/icon buttons - into one `role="group"` control with joined corners and a divider between the segments.
657
1044
  - The segments keep the full button API (variant, size, color, disabled, loading); the trigger typically also carries `etMenuTrigger` to open a menu with related actions.
658
1045
  - The divider color is themeable via `--et-split-button-divider-color` (defaults to `currentColor` at 32%).
659
1046
  - The headless `SplitButtonDirective` (`[etSplitButton]`) plus the segment directives are exported for custom-styled split buttons.
660
1047
  - Missing or misplaced segments throw dev-mode errors in the new `ET23xx` range.
661
1048
 
662
1049
  - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`300afe3`](https://github.com/ethlete-io/ethdk/commit/300afe3f9115f2ff18ca097975a8101690613d24) Thanks [@github-actions](https://github.com/apps/github-actions)! - Stream: theming overhaul and cleanups.
663
- - The PiP chrome now provides a surface theme scope (`type: 'dark'`, elevation 1) — it is mounted into `document.body` and previously had no theme context at all.
1050
+ - The PiP chrome now provides a surface theme scope (`type: 'dark'`, elevation 1) - it is mounted into `document.body` and previously had no theme context at all.
664
1051
  - The PiP window glass background derives from the surface theme (`60%` of `--et-surface-background-solid`) instead of hardcoded `rgba(0, 0, 0, 0.6)`; `--et-pip-bg` remains as an override hook but is no longer a registered `@property`.
665
1052
  - The featured-cell ring in PiP grid mode uses `--et-theme-color-primary-solid` instead of hardcoded `#3b82f6`; `--et-stream-pip-chrome-featured-ring-color` remains as an override hook (no longer a registered `@property`). The hover ring and resize handles now derive from surface tokens too.
666
1053
  - Scrollable: `ScrollableErrorCode` is removed in favor of `SCROLLABLE_ERROR_CODES`, matching every other domain's naming.
@@ -682,7 +1069,7 @@
682
1069
  same fix is applied to the window control button icon.
683
1070
 
684
1071
  - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`7110a06`](https://github.com/ethlete-io/ethdk/commit/7110a068208586f5906da1fc387c5181b2d1ec1a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Menu: the floating arrow no longer affects or overlaps the panel content.
685
- - The overlay arrow is now clipped at the panel edge (it only keeps the outer tip plus the border seam), so the menu no longer adds extra clearance padding on the arrow side — padding is identical regardless of placement.
1072
+ - The overlay arrow is now clipped at the panel edge (it only keeps the outer tip plus the border seam), so the menu no longer adds extra clearance padding on the arrow side - padding is identical regardless of placement.
686
1073
  - `arrowPadding` on `[etMenu]` now defaults to `14` (was `8`) so the arrow can no longer slide into the panel's rounded corners.
687
1074
 
688
1075
  - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`90eeba1`](https://github.com/ethlete-io/ethdk/commit/90eeba1e6dbac11cfaef7cd4c2f0a5fa6234d642) Thanks [@github-actions](https://github.com/apps/github-actions)! - Menu: the anchor arrow no longer overlaps the panel's edge content. The rotated
@@ -696,7 +1083,7 @@
696
1083
  - The iframes created by the Kick, SOOP, Dailymotion and TikTok players now carry a descriptive `title` (`"<Platform> player"`). YouTube, Vimeo, Twitch and Facebook iframes are created by the platform SDKs and cannot be titled from the library.
697
1084
  - The loading overlay is now a `role="status"` region labelled "Loading", the error overlay announces itself via `role="alert"`, and the consent gate is a `role="group"` labelled by its heading.
698
1085
 
699
- - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`1d324c2`](https://github.com/ethlete-io/ethdk/commit/1d324c2cbdd749cd8b01d52548a5a457a7e462df) Thanks [@github-actions](https://github.com/apps/github-actions)! - Text button: the underline is no longer shown in the resting state — it now animates in on hover, focus and press, and sits tight under the label (link-style) instead of hanging below the button's line box. Resting text buttons now align optically with neighboring buttons of the same size.
1086
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`1d324c2`](https://github.com/ethlete-io/ethdk/commit/1d324c2cbdd749cd8b01d52548a5a457a7e462df) Thanks [@github-actions](https://github.com/apps/github-actions)! - Text button: the underline is no longer shown in the resting state - it now animates in on hover, focus and press, and sits tight under the label (link-style) instead of hanging below the button's line box. Resting text buttons now align optically with neighboring buttons of the same size.
700
1087
 
701
1088
  ## 1.0.0-next.17
702
1089
 
@@ -711,10 +1098,10 @@
711
1098
 
712
1099
  - [`11ce5e1`](https://github.com/ethlete-io/ethdk/commit/11ce5e1795249a6b975dab2eab7e8e2a9c9bc979) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix icon directive typing and improve the icon generator config.
713
1100
  - `IconDirective` now explicitly annotates its inputs as `InputSignal<RegisteredIconName>` and `InputSignal<RegisteredIconVariant | undefined>`. Without the annotation the d.ts bundler inlined the registry aliases to `string`, so consumer-side `declare module` augmentation of `EthleteIconNameRegistry` / `EthleteIconVariantRegistry` had no effect. `etIcon`/`variant` are now actually narrowed to the registered names.
714
- - The `@ethlete/components:icons` generator config takes a top-level `variants` list (replacing the singular `defaultVariant`). Bare string entries — and object entries without their own `variant`/`variants` — inherit it, so a set of icons that all share a style no longer needs the variant repeated on every entry.
1101
+ - The `@ethlete/components:icons` generator config takes a top-level `variants` list (replacing the singular `defaultVariant`). Bare string entries - and object entries without their own `variant`/`variants` - inherit it, so a set of icons that all share a style no longer needs the variant repeated on every entry.
715
1102
  - The generator's `source: "auto"` sentinel is now honored when set in the config file (previously only the CLI default auto-detected; a config `"auto"` was treated as a package literally named "auto").
716
1103
 
717
- - [`11ce5e1`](https://github.com/ethlete-io/ethdk/commit/11ce5e1795249a6b975dab2eab7e8e2a9c9bc979) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay routing: a shell that wraps only the router outlet (each route carries its own `et-overlay-main` with header/body/footer) now reliably bounds the outlet to the pane. The shell content grid pins both axes (`grid-template-columns`/`grid-template-rows: minmax(0, 1fr)`), so the outlet fills a fixed-height dialog and the routed page's body scrolls with its header and footer pinned — instead of the whole overlay scrolling. The `minmax(0, ...)` column also stops a wide child (e.g. a rich-text editor) from blowing the grid past the pane width.
1104
+ - [`11ce5e1`](https://github.com/ethlete-io/ethdk/commit/11ce5e1795249a6b975dab2eab7e8e2a9c9bc979) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay routing: a shell that wraps only the router outlet (each route carries its own `et-overlay-main` with header/body/footer) now reliably bounds the outlet to the pane. The shell content grid pins both axes (`grid-template-columns`/`grid-template-rows: minmax(0, 1fr)`), so the outlet fills a fixed-height dialog and the routed page's body scrolls with its header and footer pinned - instead of the whole overlay scrolling. The `minmax(0, ...)` column also stops a wide child (e.g. a rich-text editor) from blowing the grid past the pane width.
718
1105
 
719
1106
  ## 0.1.0-next.16
720
1107
 
@@ -740,7 +1127,7 @@
740
1127
 
741
1128
  - [`efe9cc3`](https://github.com/ethlete-io/ethdk/commit/efe9cc30b61245fd3c7fd1eaeedc3be7b85ed275) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid: prevent text selection inside a grid item when dragging it in
742
1129
  non-readonly mode. `user-select` is now disabled on the item content whenever the
743
- grid is editable, instead of only after a drag has committed — so the initial
1130
+ grid is editable, instead of only after a drag has committed - so the initial
744
1131
  pointer movement before the drag threshold no longer selects the item's text.
745
1132
 
746
1133
  - [`70308a7`](https://github.com/ethlete-io/ethdk/commit/70308a7e0ce81d97c91d55fb7f619f1384a0e3bc) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlay routing: support routes that nest their own `et-overlay-header`/`et-overlay-body`/`et-overlay-footer` (a full `et-overlay-main`) directly inside the router outlet, without a shared shell or sidebar. Previously the active route grew past the overlay, pushing the footer off-screen and preventing the body from scrolling.
@@ -783,13 +1170,13 @@
783
1170
 
784
1171
  ### Minor Changes
785
1172
 
786
- - [`b323ef6`](https://github.com/ethlete-io/ethdk/commit/b323ef66130d196e5c893e844d50ecfc85487373) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid: replace the built-in `✕` remove button and its `showDefaultRemoveAction` config option with `GridItemDefaultActionsComponent` (`et-grid-item-default-actions`) — a toolbar with an icon remove button that is now rendered by default. It is used automatically when the grid config leaves `actionsComponent` unset; set `actionsComponent` to your own component to replace it, or to `null` to render no actions. Its aria label is configurable via the new `removeActionAriaLabel` grid config option (defaults to `'Remove item'`, run through `transformer`).
1173
+ - [`b323ef6`](https://github.com/ethlete-io/ethdk/commit/b323ef66130d196e5c893e844d50ecfc85487373) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid: replace the built-in `✕` remove button and its `showDefaultRemoveAction` config option with `GridItemDefaultActionsComponent` (`et-grid-item-default-actions`) - a toolbar with an icon remove button that is now rendered by default. It is used automatically when the grid config leaves `actionsComponent` unset; set `actionsComponent` to your own component to replace it, or to `null` to render no actions. Its aria label is configurable via the new `removeActionAriaLabel` grid config option (defaults to `'Remove item'`, run through `transformer`).
787
1174
 
788
- Also removes the now-redundant drag-handle slot: the `dragHandleComponent` config option, the `dragHandleAriaLabel` config option, and the `etGridItemDragHandle` projection slot are gone. With whole-item drag the item content is the drag surface, so a dedicated handle is no longer needed — project a decorative grip into the item content instead.
1175
+ Also removes the now-redundant drag-handle slot: the `dragHandleComponent` config option, the `dragHandleAriaLabel` config option, and the `etGridItemDragHandle` projection slot are gone. With whole-item drag the item content is the drag surface, so a dedicated handle is no longer needed - project a decorative grip into the item content instead.
789
1176
 
790
1177
  - [`b323ef6`](https://github.com/ethlete-io/ethdk/commit/b323ef66130d196e5c893e844d50ecfc85487373) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid: add `GridItemToolbarComponent` (`et-grid-item-toolbar`), a themeable container for per-item controls (edit, remove, …). Drop it into an item's action slot and project action buttons (e.g. `IconButtonComponent`) into it. It stops pointerdown so the toolbar is never a drag surface even when the whole item is draggable, and is themeable via the `--et-grid-item-toolbar-background` / `-gap` / `-padding` / `-radius` custom properties. Exported from the grid entrypoint and included in `GridImports`.
791
1178
 
792
- - [`b323ef6`](https://github.com/ethlete-io/ethdk/commit/b323ef66130d196e5c893e844d50ecfc85487373) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid: in edit mode the whole item is now a drag surface — a pointerdown anywhere on the item content starts a drag, instead of only the drag handle slot. Interactive overlays (the actions slot, resize handles, or anything that stops propagation such as `GridItemToolbarComponent`) still win, and read-only grids keep their content inert. Also fixes the `et-grid--readonly` class never being applied to the grid host, so the intended read-only styles (non-interactive drag handle, hidden resize handles) now take effect, and adds a grab/grabbing cursor on the content while editing.
1179
+ - [`b323ef6`](https://github.com/ethlete-io/ethdk/commit/b323ef66130d196e5c893e844d50ecfc85487373) Thanks [@TomTomB](https://github.com/TomTomB)! - Grid: in edit mode the whole item is now a drag surface - a pointerdown anywhere on the item content starts a drag, instead of only the drag handle slot. Interactive overlays (the actions slot, resize handles, or anything that stops propagation such as `GridItemToolbarComponent`) still win, and read-only grids keep their content inert. Also fixes the `et-grid--readonly` class never being applied to the grid host, so the intended read-only styles (non-interactive drag handle, hidden resize handles) now take effect, and adds a grab/grabbing cursor on the content while editing.
793
1180
 
794
1181
  ## 0.1.0-next.12
795
1182