Release prerelease packages (next) - #3041
Merged
Merged
Conversation
Contributor
|
Tick the box to add this pull request to the merge queue (same as
|
github-actions
Bot
force-pushed
the
changeset-release/next
branch
8 times, most recently
from
August 2, 2026 22:04
1c088bd to
46c1b40
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
from
August 2, 2026 22:19
46c1b40 to
91ce99e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated.
nextis currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, runchangeset pre exitonnext.Releases
@ethlete/components@1.0.0-next.33
Major Changes
#3041
df55f32Thanks @github-actions! - Bracket: layouts are opt-in values you register, so an app bundles only the renderers it draws with.Pass factories to
provideBracketConfig({ layouts })or thelayoutsinput on either host. Thelayoutinput andBracketConfig.swissare gone - mirrored is a layout, swiss options live onswissBracketLayout()- and an unregistered mode throwsET3413.#3041
beec05fThanks @github-actions! - Breadcrumb: collapsing the trail is now opt-in. ImportBREADCRUMB_COLLAPSE_IMPORTSand applyetBreadcrumbCollapseto 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.#3041
beec05fThanks @github-actions! - Grid:GridDebugComponentmoved out ofGRID_IMPORTSintoGRID_DEBUG_IMPORTS, so the development-only overlay no longer ships in production bundles. Import that barrel where you use<et-grid-debug />.#3041
caa8c92Thanks @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 withprovideQueryErrorLabels(queryErrorLabelsForLocale)(orGERMAN_QUERY_ERROR_LABELS); themigrate-query-error-labelsgenerator finds affected sites.#3041
6be90f2Thanks @github-actions! - Rich text editor: the link editor popover is opt-in viaprovideRichTextEditorLinkEditor()— withoutit the
linktool falls back toprompt(). Runnx g @ethlete/components:migrate-rich-text-editor-link-editorto find affected editors.#3041
a0e5424Thanks @github-actions! - Rich text editor: the'heading'block-style menu is now an opt-in tool -provideRichTextEditorHeadingTool(), like the align/table/image tools. It stays in the default toolbar,so that call is all it takes; without it no block-style control renders (Markdown
#autoformat isunaffected). It was the only default tool needing the menu system, worth 8.5 kB gz to every editor.
#3041
2c0d3c9Thanks @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. ReplacerenderButtons/buttonPosition/stickyButtonswith[etScrollableButtons](SCROLLABLE_NAVIGATION_IMPORTS),renderNavigationwithetScrollableNavigation,snap/snapOrigin/cursorDragScrollwithetScrollableSnap/etScrollableDrag(SCROLLABLE_DRAG_IMPORTS), anddarkenNonIntersectingItemswithetScrollableDarken(SCROLLABLE_DARKEN_IMPORTS).ScrollableMasksDirective/ScrollableButtonsDirective/ScrollableNavigationDirectiveare renamed to…Component; the directive names now belong to the opt-ins.#3041
beec05fThanks @github-actions! - Stream:STREAM_IMPORTSnow 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) andSTREAM_PIP_IMPORTSfor picture-in-picture - orSTREAM_ALL_IMPORTSto keep the old contents. A YouTube-only app saves ~5 kB gz.Minor Changes
#3041
1f528bdThanks @github-actions! - Accordion: addpreventCloseLastto the group - the header can no longer collapse the last openpanel, so paired with
autoCloseOthersthe group behaves like a radio set.close(),closeAll()and
[(isOpen)]still collapse it.#3041
c796f12Thanks @github-actions! - Bracket: adddensity="compact"- narrower columns, and match cards that answer with a code and ascore, for a full bracket inside an article column. Layout inputs are now overrides on top of it, so
an unbound input resolves through the preset instead of a fixed default.
#3041
568e937Thanks @github-actions! - Bracket:mirroredDoubleEliminationBracketLayout()draws double elimination as stacked winners andlosers blocks, each folded around its own centre on a shared middle column, with the deciding rounds
chained below. Also fixes hovering a card lighting the wrong participant's journey, and a mirrored
bracket drawing its way-back connectors backwards.
#3041
35d4f03Thanks @github-actions! - Bracket: journeys are now per participant. Hovering one side of a card lights that participant's pathalone and marks where they went out, and
[(focusedParticipantId)]pins a path for touch and keyboardEscape. Match cards mark each side withdata-participant-id.#3041
a8dd388Thanks @github-actions! - Bracket: add<et-bracket-rounds-list>, the same source drawn as a vertical round-by-round list(sectioned for double elimination), plus
bracketNaturalWidth()/bracketFitsWidth()to decide whento swap to it on a narrow screen.
#3041
fba7ed8Thanks @github-actions! - Breadcrumb: addetBreadcrumbSeo(BREADCRUMB_SEO_IMPORTS) - opt-inschema.orgBreadcrumbListJSON-LD, which is what earns a site the breadcrumb line in a search result. Crumbs state their own
nameandurlthrough new inputs onetBreadcrumbItemTemplate; loading and unnamed crumbs areskipped, and the last crumb needs no
url.#3041
06a6ba2Thanks @github-actions! - Calendar:comparisonStart/comparisonEndband a compared period under the selection - theanalytics "vs. the previous 30 days" pattern - and the date range input forwards them. It is
presentation only, so picking never writes to it. Cells expose
data-comparison-band, andcomparisons band at the calendar's
precision.#3041
d97e71aThanks @github-actions! - Calendar: the header is replaceable, and now moves with the grid it names.ng-template etCalendarHeaderprojected intoet-calendarrenders instead of the default header,with the headless directive as its context;
et-calendaralso exposes it asheadless.rather than cut, and the picker's bottom sheet keeps one height.
#3041
8ff5062Thanks @github-actions! - Calendar:monthsShownrenders several months side by side - the classic two-month range picker,where a range spanning the turn of a month is one gesture. The span shares one keyboard scope, one
selection and a band that runs through the seam, and stepping moves by a single month. Headless:
monthPages(). The date inputs deliberately don't forward it.#3041
8692c2cThanks @github-actions! - Calendar:mode="multiple"selects a set of unrelated dates into its ownmultipleValuemodel(
Date[], kept ascending). Picking a date again removes it, nothing bands or previews, and the gridis
aria-multiselectable. It composes withprecision. The date inputs have no equivalent - theirvalue is one wire string.
#3041
35c463cThanks @github-actions! - Calendar and date inputs:precision('day' | 'month' | 'year') makes them month or year pickers -picking in that grid writes the value (the start of the unit) instead of drilling further, and ranges
compare, band and complete at the same unit. On
et-date-input/et-date-range-inputit alsoderives the text format, so
displayFormatnow defaults tonull.#3041
c41beecThanks @github-actions! - Calendar:rangeSelectionStrategydecides what a pick means inrangemode, forwarded by the daterange input. A strategy is two pure functions of
(date, currentRange)-select, and the optionalpreviewfor what to band on hover.createWeekRangeStrategy({ weekStartsOn })snaps to whole weeksand
createFixedLengthRangeStrategy({ days })makes every pick a complete span.#3041
d5012e1Thanks @github-actions! - AddstartAtto the calendar: where an empty calendar opens and which day takes theinitial roving focus (e.g. next month for a booking form). A selection or an explicit
activeMonthstill wins over it, and without any of the three the calendar opens ontoday.
et-date-input,et-date-range-inputandet-date-time-inputforward it totheir picker calendar.
#3041
d9b05fcThanks @github-actions! - Calendar: the header label is a button that zooms the day grid out to months and then years, andpicking one drills back in;
startViewdecides where it opens, forwarded by the three date inputs. Acoarse pick only navigates, reported as
monthSelect/yearSelect.min/max/dateFilterand thekeyboard model reach every view, and the new
dateClassputs classes of your own on any cell.#3041
cbd68e0Thanks @github-actions! - Calendar:weekNumbersrenders a leading week-number column on the day grid, forwarded by the date,date-range and date-time inputs. The numbering is localized rather than always ISO, so it names the
rows actually on screen. Each number is its row's
rowheader, and--et-calendar-week-number-sizesizes the column.
#3041
62b03f9Thanks @github-actions! - Carousel & Scrollable: much smoother swiping on a phone - 85% less style recalculation and 88% lesspaint with
transition="wipe", and no observer work during a scroll. Snapping is native CSS scrollsnap (
ScrollableDirective.suspendSnap()holds it off while something writes an offset itself), andthe built-in transitions run as composited keyframes. New
transition="custom"fills--et-carousel-slide-progresswithout applying an effect, for CSS of your own; new--et-carousel-wipe-dim-color;signalElementChildren/signalElementScrollStatetake amutationsoption to narrow their observers.#3041
cb1c5b0Thanks @github-actions! - Bracket: the placeholder cards are now real - compactet-match-cardcells, a hero final card with achampion line, heading round headers (
roundHeaderLevel) and a labelled continue cell. They needprovideBracketConfig({ matchNormalizer })to read your match data (normalizeEthleteBracketMatchshipsfor Ethlete feeds), and
finalColumnWidth/finalMatchHeightnow default to360/200to fit them.#3041
9057738Thanks @github-actions! - Add the match domain behindMATCH_CARD_IMPORTS:<et-match-card>(one card, three container-query layouts -dense row, featured card, wide row;
sizepins one; put it on an<a>to make the whole card the link),<et-match-participant>, the headlessetMatchCarddirective with its score/meta/game-score parts,provideMatchLabels(), andnormalizeEthleteMatch()- cards take aNormalizedMatch, so any backend maps inwith a plain adapter.
#3041
0d30c38Thanks @github-actions! - Match card: live scores now roll when they change - old value out, new value in, with a flash on the sidethat scored - plus a
scoreChangeoutput carrying the side and delta for your own effects. Only while thematch is live, never on first render, instant under reduced motion;
animateScoreChangesturns it off.#3041
fd8ac2fThanks @github-actions! - Add the standings table behindSTANDINGS_IMPORTS:<et-standings>draws a real<table>fromNormalizedStandingRows (any backend maps in;normalizeEthletePlacementships for Ethlete feeds), bandsposition
zonesin your own color themes and draws their legend from the same config, drops columns ratherthan scrolling on narrow widths, and can single out one row.
#3041
26a987fThanks @github-actions! - Form field: an[etIcon]projected into[etInputPrefix]/[etInputSuffix]is now sized by theshell (
--et-form-field-affix-icon-size,16px) - no size class needed, matching the otherin-field icons.
#3041
d97e71aThanks @github-actions! - Icon: add alabelinput. An icon staysaria-hiddenby default - it usually repeats the text besideit - but a lone status glyph is the content, and
labelturns the host into a namedrole="img"sothe meaning survives for a screen reader.
#3041
d97e71aThanks @github-actions! - Menu: addloop(defaulttrue, the current behaviour). Turn it off and the arrow keys stop at theends instead of wrapping, which reads better in a long menu. A menu with a search field is
unaffected - its ends hand focus back to the field either way.
#3041
f0082cdThanks @github-actions! - Notification upgrades:manager.promise(work, { loading, success, error })follows a promise, an observable or an@ethlete/queryquery in one toast.idin the config replaces a live notification instead of stacking a duplicate.icon), plussecondaryActionfor an action pair.swipeToDismiss: false.#3041
0e08bc2Thanks @github-actions! - Pagination: add<et-page-size-select>(PAGE_SIZE_SELECT_IMPORTS) - the "Items per page" controlthat completes the Material-style controls row beside a compact paginator. A native
<select>, so itpulls in nothing; a separate component, because page size is the app's state rather than the
paginator's. Changing the size deliberately does not reset the page. Two new label keys,
pageSizeand
pageSizeOption.#3041
38b3c2bThanks @github-actions! - Rich text editor: undo/redo over the Markdown value, replacing the browser's nativecontenteditablehistory (which could restore states the value never had). Ctrl/Cmd+Z, Ctrl+Y andthe platform's own undo all route into it, plus new
'undo'/'redo'toolbar tools that lead thedefault toolbar. Typing goes back word by word; a paste, autoformat or tool rewrite in one step.
#3041
1c7ad03Thanks @github-actions! - Rich text editor:provideRichTextEditorImageTool({ upload })embeds images as- pick,paste or drop a file, uploaded by your handler (a promise, an observable, or a
createDropzoneUploadconfig for real progress), with a placeholder that never touches the value and a popover for alt text.
Tool definitions gained
paste,dropandclickcontent hooks; without the tool, pasted imagefiles are refused rather than becoming
blob:URLs in the value.#3041
48fbe62Thanks @github-actions! - Rich text editor: pasted text that spells a token out -#First name, the trigger char plus anitem's label or id - comes back as a real chip, for HTML and plain-text clipboards alike (opt out with
parsePastedTokens="false"). A trigger with a staticitemslist no longer needsresolveItemtorender chip labels.
#3041
7e444d6Thanks @github-actions! - Rich text editor: block quote and fenced code block tools ('blockquote'/'codeBlock', alsotyped as
>/```), both in the default toolbar. Quotes nest with Tab/Shift+Tab; a code blockholds literal text, so the marks that can't serialize inside one disable themselves.
htmlToMarkdown/
markdownToHtmlnow round-trip nested quotes (>>).#3041
b3673f3Thanks @github-actions! - Selection lists: add<et-checkbox-group-select-all>, the prebuilt tri-state select-all row that hadto be hand-rolled until now - a real
role="checkbox"witharia-checked="mixed", taking its textfrom the new shared
selectAllform label. Alsoorientation="horizontal"onet-checkbox-groupandet-radio-group, flowing the options in a wrapping row.#3041
84a8d00Thanks @github-actions! - Sliders:orientation="vertical"turnset-slider/et-range-slider(and the headlessetSlider/etRangeSlider) into a bottom→up slider, its length set by--et-slider-vertical-size.marksrenders ticks on the track -
truefor one perstep, or an array of{ value, label? }stops - andsnapToMarksmoves commits and keyboard steps mark to mark instead of along thestepgrid.#3041
41c2683Thanks @github-actions! - Table: add CSV export -TABLE_CSV_EXPORT_IMPORTS/etTableCsvExportfor a button of your own, orinjectTableCsvExport()/tableToCsv()from TypeScript. It writes the visible columns and thetable's own rows by default (
exportValuegives a column its text form),rowsalso takes a providerfunction,
tableCsvRowsFromPages({ fetchPage })walks a paginated endpoint, andfilesaves a CSV theserver built instead. A server-paginated table that would silently export a single page is a dev-mode
error (
ET3506) unless you passpartial: true.#3041
e5ffd4dThanks @github-actions! - Table: addetTableInlineEdit(TABLE_INLINE_EDIT_IMPORTS) - inline cell editing. Mark a columneditableand give it anetTableCellEdittemplate, whose context is the draft as a signal-formsfield, so any of the library's controls is an editor with a plain
[formField]binding. Double-clickor
Enterstarts,Entersaves,Escaperestores,Tabsaves and moves on;cellCommitreports{ row, column, previous, next }and the mutation stays yours.#3041
040bbb3Thanks @github-actions! - Table: addetTableKeyboardNav(TABLE_KEYBOARD_NAV_IMPORTS) - arrow-key navigation over the body'scells following the ARIA grid pattern, with Home/End, Ctrl+Home/End and PageUp/PageDown. The body
becomes a single tab stop;
Enterdrills into a cell's own control andEscapecomes back out.Composes with virtual scrolling.
#3041
255bebcThanks @github-actions! - Time picker:etTimePicker/et-time-pickertakemin,maxandtimeFilter, matching thecalendar's bounds, and
et-time-input/et-date-time-inputforward them asminTime/maxTime/timeFilter. Availability is per column - an hour is disabled only when no minute inside it isselectable - unselectable options stay in place and the keyboard steps over them, and picking a part
moves the finer ones to the first value that works, including the hour behind an AM/PM pick.
Patch Changes
#3041
6c9d38dThanks @github-actions! - Overlay runtime: build anchored strategies withanchoredOverlayPosition({ referenceElement, … })instead of a
{ kind: 'anchored', … }literal - it is what pulls@floating-ui/domin, so appsthat only center dialogs no longer bundle it (~7 kB gz).
autoResize,autoHide,autoCloseIfReferenceHiddenand arrows additionally needenableAnchoredOverlayPositionExtras().#3041
d97e71aThanks @github-actions! - Fix<et-carousel>autoplaying by default:autoplayis the component's own input now and defaultsto
false, which is what it always documented. Addautoplayto a carousel that should play. On theheadless directive, read the new
isEnabled()for what is in effect.#3041
833b579Thanks @github-actions! -et-match-participantnow takes an attribute form (<a et-match-participant>/<button …>), so a player orteam card can be the click target itself. On an interactive host it names itself after the participant - the
link would otherwise read "FC Berlin emblem FC Berlin" - takes the shared focus ring, and drops the button
chrome.
et-match-cardalready worked this way.#3041
8609171Thanks @github-actions! - Docs: add a Sport UI recipes guide - the today's-matches rail (built onet-scrollable, which is whyet-match-listwas never shipped as a component) plus competition, team, player and nation cards, each witha live story to copy from.
#3041
8f0e42aThanks @github-actions! - Form field: the text-field shell, rich-text, textarea, hint and counter CSS now ships with thecontrol that uses it, so a field holding only a checkbox, switch or slider no longer pulls the
whole form-field stylesheet. No API change; chrome renders as before.
#3041
2c0d3c9Thanks @github-actions! - Choice field's card variant, the carousel autoplay chrome and the cascader's bottom-sheetpresentation now inject their CSS only once that feature is actually used.
#3041
353777bThanks @github-actions! - Mark build-tooling peer dependencies (vite,typescript,ts-morph,@nx/devkit,@analogjs/*) and feature-scoped runtime peers (date-fnsin components) as optional viapeerDependenciesMeta. 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.#3041
95c3d2fThanks @github-actions! - Overlay:--et-overlay-body-padding-blocknow 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.#3041
f59128fThanks @github-actions! -createOverlayUnsavedChangesGuardstops 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 - thebeforeunloadlock is on by default, with the title marker / blink / favicon / badge extras available through thetaboption.#3041
2c0d3c9Thanks @github-actions! - Overlay: the default enter/leave animation CSS now ships with the strategy that uses it(
stylesComponenton the breakpoint config), so an app only bundles the animations for the overlaykinds it opens. Overlays that hand-roll a layout
containerClassinstead of using a built-instrategy must now provide their own animation CSS.
#3041
8b13854Thanks @github-actions! - Query client: multi-tab sync and response persistence are opt-infeaturesinstead of defaults - themultiTabSync/persistenceclient options are gone and a client without the features ships neitherengine. Migrate with
nx g @ethlete/query:migrate-query-client-features.withMultiTabSync()shares reads, polls a cache key in one tab for all of them and refreshes theothers after a mutation; per-query
multiTabSync: falsekeeps a query tab-local.withQueryPersistence()keeps public reads in IndexedDB, so a reload renders the last known datawhile it revalidates. Secure responses need an explicit opt-in and are removed on logout.
refreshQueriesInUse()also refreshes GraphQL queries transported over POST; devtools gain Syncand Disk columns.
#3041
8422cf0Thanks @github-actions! - Rich text editor: fix escaping a code block that sits flush against the start or end of the content,where there is no line to move to. ArrowUp off the first line and ArrowDown off the last now create
the paragraph they would move to, and a second Enter on the empty last line leaves the block.
#3041
1c7ad03Thanks @github-actions! - Rich text editor: the docked (touch) toolbar no longer leaves a gap between itself and the on-screenkeyboard, however much the browser over-reports the keyboard's height, and it re-checks while the
keyboard is up in case a viewport event never arrives. A page that opted into the VirtualKeyboard API
gets
env(keyboard-inset-height)instead of the measurement.#3041
42ec970Thanks @github-actions! - DI:createProvider/createRootProvider/createStaticProvider/createStaticRootProvider/createLabelsare replaced bydefineProvider& co., which return a definition you read withtoProvideFn/toInjectFn/toToken;createQueryClient,createBearerAuthProviderandcreateWebSocketClientreturn that definition instead of a tuple. EveryprovideX/injectX/token export keeps its name - run
nx g @ethlete/core:migrate-provider-shapefor your own call sites.Cuts the
@ethlete/componentsimport floor from 89.9 to 2.4 kB gz.@ethlete/contentful@4.0.0-next.7
Major Changes
#3041
9c71ed3Thanks @github-actions! - The built-in embedded components now only exist whenprovideContentfulConfig()is in scope - without it embedded assets are skipped and hyperlinks render as plain<a href>. Apps that render embedded content must add the provider (no arguments is enough). In exchange,ContentfulLinkComponentand text-only rich text no longer bundle the image/video/audio/file components.#3041
9c71ed3Thanks @github-actions! - Rich text: marks now render as semantic elements (<strong>,<em>,<u>,<code>,<s>,<sub>,<sup>) instead of Tailwind classes; marks inside hyperlinks becomeet-contentful-rich-text-mark-*classes on the link'stextClass.marksToClasschanged accordingly,marksToTagsis new.#3041
0817cc8Thanks @github-actions! - Contentful v5: the package peers on@ethlete/componentsinstead of@ethlete/cdk(and drops@angular/cdkandrxjs).et-contentful-imagerenameshasPrioritytopriorityand loses its*Classinputs - style the staticet-picture-*classes instead. The rich text renderer now diffskeyed, so element DOM and embedded component instances survive updates and reorders; the
useTailwindClassesoption is gone. Runnx g @ethlete/contentful:migrate-to-contentful-v5.Patch Changes
#3041
9c71ed3Thanks @github-actions! - Smaller bundles: the rich-text renderer no longer pulls the@contentful/rich-text-typesruntime enums (~2.4 kB gz), and the renderer error codes plusGQL_FRAGMENT_CONTENTFUL_ASSETare now droppable literals.@contentful/rich-text-typesstays a peer dependency for its types.#3041
353777bThanks @github-actions! - Mark build-tooling peer dependencies (vite,typescript,ts-morph,@nx/devkit,@analogjs/*) and feature-scoped runtime peers (date-fnsin components) as optional viapeerDependenciesMeta. 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.#3041
353777bThanks @github-actions! - Adopt the@ethlete/eslint-pluginstyleguide flat configs incore,query,contentfulandtypes, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible toTypeScript consumers: exported
typesshapes aretypealiases rather thaninterfacedeclarations(so they can no longer be extended by declaration merging),
core'sPropsDirective.destroyRefandSeoDirective.parentareprivate, andConsentHandleris atype. The theme name registries stayinterfaces so consumers can keep augmenting them.
@ethlete/core@5.0.0-next.37
Major Changes
#3041
6c9d38dThanks @github-actions! - Overlay runtime: build anchored strategies withanchoredOverlayPosition({ referenceElement, … })instead of a
{ kind: 'anchored', … }literal - it is what pulls@floating-ui/domin, so appsthat only center dialogs no longer bundle it (~7 kB gz).
autoResize,autoHide,autoCloseIfReferenceHiddenand arrows additionally needenableAnchoredOverlayPositionExtras().#3041
6c9d38dThanks @github-actions! -@ethlete/coreno longer depends on@angular/cdk:injectBreakpointObserver()is a plainmatchMediaimplementation (same API), andAnimatedOverlayDirectivemoved to@ethlete/cdk-import it from there.
#3041
42ec970Thanks @github-actions! - DI:createProvider/createRootProvider/createStaticProvider/createStaticRootProvider/createLabelsare replaced bydefineProvider& co., which return a definition you read withtoProvideFn/toInjectFn/toToken;createQueryClient,createBearerAuthProviderandcreateWebSocketClientreturn that definition instead of a tuple. EveryprovideX/injectX/token export keeps its name - run
nx g @ethlete/core:migrate-provider-shapefor your own call sites.Cuts the
@ethlete/componentsimport floor from 89.9 to 2.4 kB gz.Minor Changes
#3041
62b03f9Thanks @github-actions! - Carousel & Scrollable: much smoother swiping on a phone - 85% less style recalculation and 88% lesspaint with
transition="wipe", and no observer work during a scroll. Snapping is native CSS scrollsnap (
ScrollableDirective.suspendSnap()holds it off while something writes an offset itself), andthe built-in transitions run as composited keyframes. New
transition="custom"fills--et-carousel-slide-progresswithout applying an effect, for CSS of your own; new--et-carousel-wipe-dim-color;signalElementChildren/signalElementScrollStatetake amutationsoption to narrow their observers.#3041
7e444d6Thanks @github-actions! - Rich text editor: block quote and fenced code block tools ('blockquote'/'codeBlock', alsotyped as
>/```), both in the default toolbar. Quotes nest with Tab/Shift+Tab; a code blockholds literal text, so the marks that can't serialize inside one disable themselves.
htmlToMarkdown/
markdownToHtmlnow round-trip nested quotes (>>).#3041
30d3dfbThanks @github-actions! -unsavedChanges: a tracker now locks the browser tab while the value differs from its baseline - abeforeunloadlistener attached only while changes exist - through the newtaboption (falseoptsout), with opt-in
titleMarker,flash,faviconandbadgeextras.createUnsavedChangesTabLock()is the same guard standalone, for state that isn't a form.injectUnsavedChangesCoordinator(): one confirm on screen at a time app-wide, plusabandonAll(reason?)for a session that ends underneath a guard.confirmnow receives a{ signal }argument so a dialog can close itself instead of being stranded.applyFaviconOverlay(binding), plus title-storeaddMarker/removeMarkerbehind the public
applyHeadTitleMarker(binding).Patch Changes
#3041
c622e2cThanks @github-actions! - Breakpoint inputs: warn in dev mode when a breakpoint map mixes valid and unknown keys. One bad key (adefaultentry, say) makes the whole map inert - it becomes a plain value, which for an attribute bindingrenders as
[object Object]and does nothing - and that failed silently until now.#3041
fba7ed8Thanks @github-actions! - FixapplyStructuredDataBindingwriting its JSON into atextattribute on the<script>insteadof into the script's content - the tag was emitted, but empty, so no crawler ever read the structured
data. (
StructuredDataComponentwas unaffected.)#3041
353777bThanks @github-actions! - Mark build-tooling peer dependencies (vite,typescript,ts-morph,@nx/devkit,@analogjs/*) and feature-scoped runtime peers (date-fnsin components) as optional viapeerDependenciesMeta. 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.#3041
6c9d38dThanks @github-actions! -RuntimeErrorlogs itsdatadirectly instead of deep-cloning it first, which keeps the clonehelper out of every package's baseline bundle.
#3041
353777bThanks @github-actions! - Adopt the@ethlete/eslint-pluginstyleguide flat configs incore,query,contentfulandtypes, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible toTypeScript consumers: exported
typesshapes aretypealiases rather thaninterfacedeclarations(so they can no longer be extended by declaration merging),
core'sPropsDirective.destroyRefandSeoDirective.parentareprivate, andConsentHandleris atype. The theme name registries stayinterfaces so consumers can keep augmenting them.
@ethlete/query@6.0.0-next.23
Major Changes
#3041
53fcc97Thanks @github-actions! - Bearer auth multi-tab sync and leader election are opt-in:createBearerAuthProvider'smultiTabSyncoption is replaced by
withBearerAuthMultiTabSync()infeatures(~1.4 kB gz off the secure entrywithout it), read back as
provider.features.multiTabSync.isLeader(). Election runs on the Web LocksAPI now rather than a
localStorageheartbeat, so a tab that closes or crashes hands over at once.setupAuthTest()lost itsmultiTabSyncoption. Migrate withnpx nx g @ethlete/query:migrate-query-opt-in-features.#3041
8b13854Thanks @github-actions! - Query client: multi-tab sync and response persistence are opt-infeaturesinstead of defaults - themultiTabSync/persistenceclient options are gone and a client without the features ships neitherengine. Migrate with
nx g @ethlete/query:migrate-query-client-features.withMultiTabSync()shares reads, polls a cache key in one tab for all of them and refreshes theothers after a mutation; per-query
multiTabSync: falsekeeps a query tab-local.withQueryPersistence()keeps public reads in IndexedDB, so a reload renders the last known datawhile it revalidates. Secure responses need an explicit opt-in and are removed on logout.
refreshQueriesInUse()also refreshes GraphQL queries transported over POST; devtools gain Syncand Disk columns.
#3041
53fcc97Thanks @github-actions! - Error-response parsing and the default retry policy are opt-in query client features - without them aclient reads the plain
string/{ message }/{ detail }/string[]ladder and retriesnothing, which takes ~1.4 kB gz out of an app that needs neither. Pick from
withHtmlErrorParsing(),withSymfonyErrors(),withDefaultRetry(),withEthleteApiErrors()(all three, the previousbehavior) and
registerQueryErrorParser()for a body shape the SDK does not know. Runnpx nx g @ethlete/query:migrate-query-opt-in-featuresto keep the old behavior.#3041
42ec970Thanks @github-actions! - DI:createProvider/createRootProvider/createStaticProvider/createStaticRootProvider/createLabelsare replaced bydefineProvider& co., which return a definition you read withtoProvideFn/toInjectFn/toToken;createQueryClient,createBearerAuthProviderandcreateWebSocketClientreturn that definition instead of a tuple. EveryprovideX/injectX/token export keeps its name - run
nx g @ethlete/core:migrate-provider-shapefor your own call sites.Cuts the
@ethlete/componentsimport floor from 89.9 to 2.4 kB gz.Minor Changes
e040432Thanks @github-actions! - Newclient.invalidateQueries()re-runs the queries this client has on screen whose data went stale -after a mutation, or a push message saying something changed server-side - and tells the user's other
tabs to do the same. Narrow it with
url(resolved againstbaseUrl, matched on path boundaries) andfilter, or keep it local withotherTabs: false; reaching other tabs needswithMultiTabSync().See Invalidating after a change.
Patch Changes
#3041
a935328Thanks @github-actions! -logout()now abandons every unsaved-changes guard (injectUnsavedChangesCoordinator().abandonAll('logout')). Pressing logout with a dirty form used to leave a "discard your changes?" dialog floating over the login page the app had already redirected to, plus a tab still locked against closing - over edits that can no longer be saved. Guards created after a re-login work normally again.#3041
353777bThanks @github-actions! - Mark build-tooling peer dependencies (vite,typescript,ts-morph,@nx/devkit,@analogjs/*) and feature-scoped runtime peers (date-fnsin components) as optional viapeerDependenciesMeta. 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.#3041
53fcc97Thanks @github-actions! - Devtools instrumentation is now registered through a hook thatprovideQueryDevtools()installs, soan app without it drops the entry registry, the route stringifier and the client-name derivation
entirely - ~0.5 kB gz off every entry. No API change;
queryDevtoolsEntriesand the<et-query-devtools>contract are unchanged.#3041
42ec970Thanks @github-actions! - Internal: the current generation no longer imports anything from the legacy V2 tree -buildRoute,buildQueryString,buildTimestampFromSeconds,decryptBearer,QueryErrorand the query-stringtypes now live in
http/internal/request-route, andlegacyre-exports them. Every public name isunchanged. Also closes the
http ↔ gqlcycle.#3041
53fcc97Thanks @github-actions! -socket.io-clientis an optional peer dependency. It is only imported bycreateWebSocketClient,and no non-
wspublic type surfaces it, so an app that does not use the realtime client no longerhas to install it.
#3041
353777bThanks @github-actions! - Adopt the@ethlete/eslint-pluginstyleguide flat configs incore,query,contentfulandtypes, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible toTypeScript consumers: exported
typesshapes aretypealiases rather thaninterfacedeclarations(so they can no longer be extended by declaration merging),
core'sPropsDirective.destroyRefandSeoDirective.parentareprivate, andConsentHandleris atype. The theme name registries stayinterfaces so consumers can keep augmenting them.
@ethlete/agent-rules@0.1.0-next.0
Minor Changes
#3041
9808192Thanks @github-actions! - Add@ethlete/agent-rules: the portable Ethlete coding guidance - styleguide, Angularpatterns, signals vs RxJS, theming, query, commits, Storybook verification - packaged
for consumer repos and compiled into Claude Code, Codex (
AGENTS.md), Cursor andCopilot formats from one canonical source.
npx ethlete-agents syncwrites thegenerated files,
checkfails CI on drift, andinitscaffolds the config. Content isfiltered per repo by installed packages (
requires), profile (scope) and configuredtemplate variables.
c6ebe63Thanks @TomTomB! - Add thesdk-docsguide: where the@ethletedocs site and Storybook live, how page URLsmap to libraries and component domains, and the rule that an API is read rather than
inferred from a component's name. Aimed at repos that consume the SDK without its source.
Patch Changes
c6ebe63Thanks @TomTomB! - Render a{% skill:… %}cross-reference as a bare name when the guide it points at wasfiltered out of the target repo, instead of emitting a path to a file that was never
written.
syncnow reports each such reference.@ethlete/eslint-plugin@1.0.0-next.17
Minor Changes
ae18442Thanks @github-actions! - New ruleno-impure-top-level-provider: bans destructuring a factory call at module scope, and - with{ requirePureAnnotation: true }, for publishable library source - requires/* @__PURE__ */onmodule-scope calls. Both shapes are undroppable, so one of them puts everything the call touches into
every consumer's bundle. Fixable.
@ethlete/cdk@5.0.0-next.24
Patch Changes
#3041
6c9d38dThanks @github-actions! -@ethlete/coreno longer depends on@angular/cdk:injectBreakpointObserver()is a plainmatchMediaimplementation (same API), andAnimatedOverlayDirectivemoved to@ethlete/cdk-import it from there.
#3041
353777bThanks @github-actions! - Mark build-tooling peer dependencies (vite,typescript,ts-morph,@nx/devkit,@analogjs/*) and feature-scoped runtime peers (date-fnsin components) as optional viapeerDependenciesMeta. 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.#3041
42ec970Thanks @github-actions! - DI:createProvider/createRootProvider/createStaticProvider/createStaticRootProvider/createLabelsare replaced bydefineProvider& co., which return a definition you read withtoProvideFn/toInjectFn/toToken;createQueryClient,createBearerAuthProviderandcreateWebSocketClientreturn that definition instead of a tuple. EveryprovideX/injectX/token export keeps its name - run
nx g @ethlete/core:migrate-provider-shapefor your own call sites.Cuts the
@ethlete/componentsimport floor from 89.9 to 2.4 kB gz.@ethlete/types@2.0.0-next.7
Patch Changes
353777bThanks @github-actions! - Adopt the@ethlete/eslint-pluginstyleguide flat configs incore,query,contentfulandtypes, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible toTypeScript consumers: exported
typesshapes aretypealiases rather thaninterfacedeclarations(so they can no longer be extended by declaration merging),
core'sPropsDirective.destroyRefandSeoDirective.parentareprivate, andConsentHandleris atype. The theme name registries stayinterfaces so consumers can keep augmenting them.