Astryx 0.5.1
Astryx 0.5.1 — all @astryxdesign/* packages ship at this version.
npx astryx upgrade --apply
-
add shape prop ('circle' | 'rounded' | 'square') to Avatar for non-circular form factors (#4205) (#4327)
-
Card: make the
variantaxis theme-extensible through aCardVariantMapinterface (#5551)CardVariantwas a hand-written union backed by a closed style record, so a theme could not add a card variant: an unknown value neither type-checked nor rendered. It is nowkeyof CardVariantMap, an interface exported from@astryxdesign/core/Cardthat a theme build augments — the same shape Button, Badge, Section and the other extensible axes already ship.keyof CardVariantMapresolves to exactly the thirteen valuesCardVarianthad, so no existing call site changes. A variant a theme adds falls through to base styles and the theme's owncard['variant:<name>']rule paints it.On SelectableCard that variant's selection ring is drawn in
--selectable-card-ring-color, defaulting to the accent. No token the component could pick is guaranteed to contrast with a fill the component cannot know, so a theme rule that adds a variant sets the ring colour in the same rule as itsbackgroundColor. -
CheckboxInput and Switch now name their own label as a theme target:
astryx-checkbox-labelandastryx-switch-label, alongside theastryx-field-labelevery label already carries. A theme could previously only reach oneastryx-field-labeltarget, so styling a checkbox's label — which shares a row with its control — meant styling every form field's label above its input too. The control passes the target down, so the name says what the thing is rather than encoding how it is arranged, and nothing can set it untruthfully. (#5183) -
The checkbox indicator now exposes stable theme targets for its two marks —
astryx-checkbox-indicator-check(the checkmark) andastryx-checkbox-indicator-dash(the indeterminate bar) — mirroring the existingastryx-radio-indicator-dot. Both reflectsize. A theme restyling the mark itself (stroke weight, colour, the dash's proportions) previously had to reach it with.astryx-checkbox-indicator > svgand> span, which are element-and-order selectors that break silently on any restructure. Purely additive; no visual change. (#5426) -
ComplexSelector:
onOpenChangereports every open and close of the popup — the trigger, the keyboard, a light dismiss, Escape, content callingclose(), or the imperative handle. Paired with the existinghandleRef, a consumer can drive and observe the surface without reading the shell's DOM. (#5211) -
DateInput uses the platform date picker on touch, with
nativePickerto choose the native or Astryx surface; focused desktop-style native fields reveal their editable segments, the Astryx touch sheet keeps Reset in its header and Save alone in its footer, and both closed surfaces match standard input height (#5261, #5456, #5502, #5534)nativePicker="touch"is the default,"always"uses<input type="date">wherever supported, and"never"keeps Astryx's sheet or popover. Formatting still returns on blur, andmin/maxcontinue to validate native selections. -
Add a coarse-pointer DateTimeInput bottom-sheet picker with separate closed Date/Time segments, direct section opening, and a two-step Save date → Save flow. (#5582)
-
Icon APIs and themes accept namespaced extension keys, and NumberInput steppers use
numberInput:stepperDownwithout widening the requiredIconRegistrykeys (#5466)<Icon icon>,useIcon, anddefineTheme({icons})accept keys such asnumberInput:stepperDownandrichtext:bold; misspelled built-in names remain type errors. NumberInput keeps a compact centered Core fallback, while themes can override its steppers independently from the sharedchevronDownsemantic. -
OverflowListcan now hand its collapsed items to a menu you already render, viaonOverflowChange(overflowItems).overflowRendereronly describes an indicator the list mounts itself, and only while items overflow — so a row that already carries a standing "…" menu had no way to collect the collapsed items into it, and adding an indicator gave the user two menus side by side. Watching from the outside was not reachable either: a reporter component placed insideoverflowRenderermounts twice (the hidden measurement copy always receives every item, so it cannot tell you what is actually collapsed), and nothing fires when the row widens back out and the set empties. The new callback reports the collapsed set whenever its membership or order changes, and leaves the anchor entirely to the caller. It fires once measurement has collapsed something, fires again with an empty array once the row widens back out and everything fits, and is silent while nothing overflows — including on mount, so a list that fits from the start never calls it. It never reports the pre-measurement state, which is an empty set whether or not the row actually overflows; hold the collapsed set in state initialised to[]and it is correct at every moment. Reports run from a layout effect after measurement, so the menu updates in the same frame as the collapse. The measurement container is now observed for size changes, so child-size changes refresh every OverflowList and directuseOverflowconsumer even when the available container width does not change. Keyed membership and order changes are re-measured beforeonOverflowChangereports them. Stable React keys distinguish same-count membership and order changes, while unrelated re-renders and callback identity changes do not re-fire it. Both APIs may be used together; usingonOverflowChangealone adds nothing to the row. (#5199) -
Selector and MultiSelector: configurable panel empty states via
emptyTextandemptySearchText, announced to screen readers as well as shown; a panel with no options now says so instead of rendering blank, and says nothing whileisLoading(#5462) -
SideNavItem: new
actionsslot for row-level secondary controls (icon buttons, menus). Content renders as a sibling of the primary link/button — after the expand/collapse toggle, before nested children in DOM and focus order — so interactive controls never nest inside the primary element and every row control is reachable before focus enters the subtree. Passive content (badges, counts) stays inendContent;actionsis hidden while the rail is collapsed, and stays interactive on disabled items since each supplied control owns its own disabled state. An actions row draws its focus ring as a full-row pill for the primary link or button, while the expand/collapse toggle and each supplied action keep their own — addsfocusOutlineProps.focusWithinFirstChildandfocusOutlineProps.suppressedfor that pairing. Supplied controls inherit the row's control size throughSizeContext, the waySideNavalready cascades one size to its footer icons, so an unsized icon button comes out the same box as the built-in toggle; an explicitsizestill wins. (#4988) (#5005) -
Spinner: the ring's geometry and its two colors are now themeable. The
sizeandshadeprops keep their fixed enums; what each named value resolves to is now a theme's to set, through four public custom properties on thespinnertarget —--spinner-diameterand--spinner-stroke-widthunder a size variant,--spinner-colorand--spinner-track-colorunder a shade variant (or on the base target for all of them at once): (#5214)spinner: { 'size:xl': {'--spinner-diameter': '2.5rem', '--spinner-stroke-width': '0.375rem'}, 'shade:subtle': {'--spinner-track-color': 'transparent'}, }
Any length and any color notation works —
rem,emandcalc()are resolved by the cascade into the radius and stroke the ring is drawn with, and colors acceptvar(),color-mix()andcurrentColor. A stroke width of0is honoured as a zero-width stroke — it paints nothing, rather than being read as "unset" and silently drawing the default. The drawn ring and the box around it come from the same values, so they stay in step, including when a media query or a root font-size change moves them after mount.The two private vars the ring resolves into are registered as
<length>when the module is imported, not when a spinner first mounts. Registering an inherited property with aninitial-valueinvalidates style for the whole document, and a spinner is the loading indicator — it arrives on a page that has already rendered, so paying that there is paying it on the full tree: 29 ms against 12 ms for the same mount on an 11k-element page. A build that never importsSpinnerdrops the module and the registration with it.Output is unchanged for every size and shade unless a theme overrides something, and so is every precedence around the box: it is still sized by an inline
width/heightwritten after the caller'sstyle, as it has always been, with the composed value in place of the number. -
TextArea: the two painted elements inside the wrapper now carry stable theme targets —
astryx-text-area-control(the<textarea>itself) andastryx-text-area-counter(the character counter). Only the wrapper was themeable before, so a theme restyling the control's own typography, placeholder or resize affordance, or the counter's supporting text, had to reach in with structural selectors like.astryx-text-area > textarea. Purely additive: no existing class, data attribute, or style changes. (#5418) Neither carries asizeaxis.sizemoves only the control's block padding (smandmdare empty;lgsetspaddingBlock), and that is the axis apaddingtranslation for this component takes over — so an axis here would be a second way to say the same thing, and the one that stops being true once the translation lands.The start-icon and end-slot overlays are deliberately not targets. They paint nothing — each is
position: absolute; pointer-events: none; display: flex— and they are placed off the wrapper's--_textarea-inline-padding, so a theme that moves the control's inset needs them to move with it rather than to be re-placed one at a time. That inset belongs in apaddingtranslation for the component, which is tracked separately. -
Toast:
renderContenton theshowToastoptions replaces the content of that toast's card with your own layout. (#5428)showToast({ body: 'Your changes have been saved.', renderContent: ({body, endContent, dismiss}) => ( <MyRow> <MyTitle>{body}</MyTitle> {endContent} <Button label="Dismiss notification" onClick={dismiss} /> </MyRow> ), });
Astryx keeps the card, its
astryx-toasttheme target, live-region role and auto-hide behavior. The renderer receives the message,endContent, resolved toast settings and adismisscallback.Custom content owns its complete layout and every control in it. Call
dismissfrom the control that should close the toast; it may be passed through nested components. Astryx does not register an injected component or add a fallback close behind a custom layout.The API is per-toast. An app can share one layout by wrapping
useToast()and passingrenderContenton each call, while other toasts continue to use the ordinary Astryx layout and its translated, themeable dismissButton.New exported types:
ToastContentRenderProps,ToastContentRenderFn. -
Toast now supports touch and pen swipe dismissal toward its configured viewport edge. The vertical axis matches each Toast's top/bottom placement and entrance/exit motion, so the dismissal follows the same spatial model instead of introducing a separate side exit. Native touch scrolling is preserved until movement resolves to the dismiss direction, interactive controls do not start a swipe, and swipe continues to report the existing manual dismissal reason. Pen is included as direct-contact input; mouse drag is excluded because desktop users already have the visible close control and dragging can conflict with text selection. (#5375)
-
Typeahead + Tokenizer: minQueryLength holds the search and the menu until the query is long enough (#5385) Also fixes a stranded loading state that predates the prop: abandoning an in-flight search — by emptying the field, by falling below the threshold, or by selecting an item while the next search is still out — bumps the search generation, which makes that search's own
finallydecline to clear the loading flag. The field kept reporting "Loading" to assistive technology until another search settled.hasCreateis not gated by it. The "Create ..." entry is derived from the typed text rather than fetched for it, so it now reaches the menu through a separate internal path and is offered whatever the threshold says — the threshold exists to avoid a fetch too broad to be worth making, and creating costs no fetch. WithminQueryLength={3}, typingQAoffersCreate "QA"and Enter commits it, while the search source is still never called.One consequence worth naming: the Create entry is appended after the results are cut to
maxMenuItems, so withhasCreatea full menu now shows one option more than the cap — 11 where it used to show 10. The cap bounds how many results a menu shows; creating is a separate capability and is not crowded out by them.
-
AlertDialog lets Dialog preserve and clamp its preferred width, lets whole actions move to another row when needed, and stacks full-width destructive and Cancel actions at 640px and below while preserving standard single-line Button sizing and labels regardless of pointer type. (#5343)
-
Badge: a long label no longer escapes its container. (#5558)
Badgesetwhite-space: nowrapwith nothing to clip it — the one pairing that neither wraps nor truncates. A label wider than the space available rendered outside the badge's container and over whatever sat beside it.<div style={{width: 100}}> <Badge variant="pink" label="Awaiting security review" /> </div>
Measured in Chromium: that badge came out 163px wide in a 100px column, spilling 63px past it; in a fixed-layout table cell it painted 64px over the text in the next cell. The badge now clamps to the width it is given and cuts the label with an ellipsis.
A badge that already fits is untouched — same width, same height, same DOM. Measured before and after, a badge with room to spare is 53px either way; only the cases that were already overflowing change.
Badgeuses no hooks and stays server-renderable.The ellipsis sits on an inner label span rather than the badge itself, because
text-overflowneeds a block container and taking the root offinline-flexto get one would cost the icon its centring. With an icon, the icon holds its place and the label gives way.So that a clipped tail is not simply lost, a string or number label is also carried in the badge's
title— the same shapeBaseTablealready uses for a truncated header cell. That costs no measurement and no hook, soBadgestill renders the same on the server and stays usable in a server component. A richlabelis left alone rather than flattened to a guess.Two gaps remain, both needing runtime measurement, and both tracked in #5585: the
titleis set whether or not the label actually fits, and a nativetitleis a pointer affordance — it answers hover, not keyboard focus, and not touch at all. The refinement is a tooltip shown only when the text is really cut, reachable by hover and by focus, which makesBadgea client component and is its own trade-off to weigh. -
Banner names each dismiss control after its string title, so stacked banners no longer expose identical "Dismiss" buttons to screen readers. Rich titles retain the generic translated name unless the consumer supplies an already-translated
dismissLabel; that override also labels the tooltip. (#5113) -
Seven components now forward the pass-through props promised by
BaseProps(#5563)MetadataListItem,NavHeadingMenu,Timestamp,Token,TopNavMegaMenu,TopNavMenu, andTypeaheadItemnow forward neutralaria-*,id,tabIndex, event-handler, anddata-*props to their rendered DOM element. Styling still merges throughmergeProps, contract-owned attributes retain precedence, and owned handlers compose throughcomposeEventHandlerswith the caller first.MetadataListItemtargets its wrapper<div>when stacked and its<dt>when inline. ATypeaheadItembacked by caller-supplieditem.elementremains unchanged and does not receive forwarded props because that value may not be a cloneable element.This completes #5254 after #5288 by @lexs landed
ListandMarkdownfirst, followed by #5493 by @gonzoblasco forTreeList. -
Buttonnow reflectselevationas a theme target. The prop selected between four StyleX style objects but was missing from the siblingthemeProps('button')call, sodata-elevationnever reached the DOM and no theme could style the axis — the same defect fixed onCardin #5491, and oneButtonGroupalready had right. A button inside aButtonGroupreportsnone, because the group owns the surface's elevation and the member paints flat. Every wrapper that forwardsButtonPropsthrough toButton—IconButton— picks the reflection up with it. (ToggleButtondoes not: its props extendBaseProps, notButtonProps, so it has noelevationto forward and keeps reportingnone.) Nothing about the rendered button changes: 60 of 64 captured frames are byte-identical, and the four that differ do so only inside the loading spinner's own box. (#5552) -
Calendar: announce a cleared range in the provider locale, wrap the two-month layout instead of overflowing a narrow viewport, keep the selected date visible under forced colors (#5453)
-
Card: reflect
elevationas a theme target so a theme can reach it, and correct the documentedpaddingdefault (#5491)elevationpicked a style object but never reached the DOM, soastryx-cardexposeddata-variantand nothing for elevation and a theme could not style the four shadow tiers. It now ridesthemePropsalongsidevariant.The
paddingprop documented4as its default. With the prop omitted the card reads the theme's card padding, and most shipped themes set that to a different step, so writing the documented default explicitly changed the card's size. The prop docs, the JSDoc and the playground default now say that omitting the prop takes the theme's padding and passing a step overrides it. The foureffectivePadding !== 4style branches that encoded the same wrong default in code are gone:container()already sets every variable they set, verified identical across all eleven padding steps on both a bordered and a borderless card. -
Carousel no longer drops keyboard focus to the document body when reaching a scroll edge disables the nav button in use. Focus moves to the opposite arrow instead, on the state transition that disables the button rather than on a prediction from the press, so it holds under reduced motion, under scroll-snap, and on browsers without
scrollend. The scroll container is also now a documented theme target,astryx-carousel-scroller, carrying the gap, padding, snap and edge-fade props it styles, so a theme can reach the spacing and the fade it could not see before. (#5601) -
The 56
--color-data-*defaults now reach runtime CSS and built themes from the same source, while dashboard template fallbacks match those defaults (#5562, #5566) The defaults live once at:rootin@layer astryx-base, so nested themes inherit parent overrides andastryx theme buildmatches<Theme>whilegenerateThemeCSSkeeps its existing return shape.Visual change. A chart or template that previously painted nothing or used a mismatched hex fallback now paints the data token's default. Pin an explicit color to preserve a previous fallback.
-
DateRangeInput: allow a same-day range when
minRangeSpanis 1 (#5581) A repeated click on the range start now commits a one-day range when the configured minimum permits it, including when a maximum span is also set. Longer minimum spans keep the existing cancel behaviour so the user can move the start date. -
Dialog: fullscreen safe-area padding follows writing direction and defers to explicit padding (#5367) Two corrections to the fullscreen safe-area padding that shipped in 0.5.0.
The insets were mapped to the wrong edges in RTL.
env(safe-area-inset-left)andenv(safe-area-inset-right)are physical, but they were assigned straight topadding-inline-startandpadding-inline-end, which are logical. That holds in LTR and inverts in RTL, where inline-start is the right edge — so a device notch on the physical left padded the edge away from it and left the notched edge unprotected. Each physical inset now feeds the logical edge that actually faces it, in both directions.Safe-area protection overrode explicit padding. The
max()was applied to the fullscreen surface unconditionally, so it beat both apaddingprop and a theme'sdialog: {padding: 0}, and a deliberately full-bleed fullscreen dialog could not be expressed. It now sits in the innermost fallback of the same--astryx-dialog-padding*chaincontaineralready resolves, so it applies only when no padding is set anywhere. An explicit value,0included, is honored as written. -
Date formatting now defaults to Gregorian calendar semantics across core, charts, and Schedule while still following the selected locale for language, numbering, and field order. (#5303) The low-level public
plainDateFormathelper continues to honor an explicitly suppliedcalendaroption for compatibility; Astryx components do not expose that display-only exception and remain Gregorian. The deterministic English fallback also prevents server and browser locale differences from producing hydration mismatches when no provider locale is available. Locale-aware parsing only selects day-first or month-first order for ambiguous ASCII numeric dates; it does not parse localized month names, non-ASCII digits, or arbitrary locale-specific strings.Fixes #5074.
-
Labelled HoverCard triggers expose a dialog-popup relationship without flattening rich content into a description, and only roles that support
aria-expandedreceive that state (#5419, #5501) The trigger now usesaria-haspopup="dialog",aria-controls, and a role-gatedaria-expanded;useHoverCardexposes the layeridand open state, whiledescribedByremains as a deprecated alias for compatibility. Unlabelled group cards keep their description relationship. -
Popup triggers no longer fight the browser's own light dismiss: pressing the button of an open Selector, MultiSelector, ComplexSelector, DropdownMenu, or Popover closes it once instead of closing and reopening. MultiSelector's clear and status buttons also keep its popup open when pressed. (#5018)
-
Markdown now applies the same URL safety rule to every image path it parses: reference-style images (
![alt][label]and the shortcut form) and standalone block images pass through the check inline images and links already used, and the render-side guard normalizes control characters before testing so both layers see a URL the way a browser will. (#5522) -
Markdown and List forward the rest of
BaseProps(#5288) Both declareBaseProps, andBasePropsdocuments thatdata-*,aria-*androlereach the element — but each destructured a fixed set of props and forwarded onlydata-testid, so anaria-labela consumer passed silently disappeared.<Markdown aria-label="Release notes">named nothing, and a list could not be labelled by a heading it did not render itself.Consumer props spread first, so what a component sets for itself still wins: the block root stays
role="document", the list keeps the explicitrole="list"that restores Safari/VoiceOver announcements, and a list rendering its own header keeps that association rather than one pointed elsewhere. Thearia-labelledbyfor that header is only written when the header exists — writingundefinedunconditionally would erase a consumer's own label. -
NumberInput parses locale-formatted paste safely and commits one complete draft: grouped numbers and machine decimal points work, arbitrary repeated punctuation is refused, out-of-range values clamp to the nearest bound, and fractional stepping cannot cross a rounded bound (#5152, #5450, #5459, #5510, #5546) Invalid typed or pasted input preserves the prior value instead of committing a valid prefix. Pagination inherits the complete-draft and bound behavior, while inline Table filtering and PowerSearch keep their existing live and Enter-to-save behavior.
-
Popover: theming
popover.borderRadiusnow changes the rendered radius. Theastryx-popovertarget moves onto the popup surface — the box that paints background, radius and elevation — andusePopoverreads the registered--_popover-radiusthere instead of hardcoding--radius-container. Content padding moves with it, so a themedpaddingstill replaces the default instead of nesting inside it. (#5162) -
Ensure pressed overlays override hover across interactive surfaces (#5451) (#5516)
-
Stack DateTimeInput's date and time fields when its container is narrower than 400px. (#5609)
-
Selector: a caller-supplied
idnow drives the trigger's whole identity, not just itsidattribute (#5561)Selectorgenerated its trigger id withuseId()and set it on the trigger button before spreading...rest, so a caller'sid— accepted throughBaseProps— replaced it on the button while the generated value stayed behind as the target of the listbox'saria-labelledbyand of theFieldlabel'shtmlFor. Passingidtherefore left the listbox with no accessible name and the field label pointing at an element that does not exist, silently and with a clean typecheck, lint and build.The internal identity is now derived from the caller's
idwhen there is one, so the button, the listbox'saria-labelledby(both the plain and thehasSearchpanel) andField'sinputIDall name the same element. The trigger's ownidattribute is unchanged in every case; what changes is that references which used to dangle now resolve — including the field label, which consequently regains its native click-to-focus behaviour. With noidsupplied the rendered output is identical to before. -
Selector raw source now compiles when consumer Babel presets lower arrow functions before StyleX extraction (#5508)
-
Platform detection reads the client-hints
Unknownsentinel as no answer, and lives in one place (#5394) Follow-up to #5325, which taughtuseHotkeysandKbdto fall through tonavigator.platformwhenuserAgentData.platformis blank.Unknownis the User-Agent Client Hints spec's own value for "cannot say", and it names a platform no more than''does, yet it still committed to the client-hints branch and answered "not Apple". It now falls through the same way.The two detections were independent copies kept aligned by a docstring. They are now one internal util that both import, so the next change to this logic cannot land on one surface and miss the other. The util is deliberately not named in
utils/index.ts, which would publish it as API. -
SideNavItem: the standalone expand/collapse toggle on a
collapsibleitem with anhreforonClicknow carries the box of asize="sm"icon button. It had no box of its own, so it shrank to the 24px chevron inside it and painted a smaller hover pill than any icon button sitting beside it in the same row. (#4988) (#5005) -
SideNav:
collapsibleandresizableno longer keep two independently initialized copies of the collapse state. Both props are normalized into one internal collapse config with a single owner — the resize hook whenresizableis in play, SideNav's own state otherwise — so the hook can no longer restore itself collapsed while SideNav renders the expanded layout at width 0, which is what made a persisted-collapsed nav come back invisible and unrecoverable (#4790) — that the second independently-initialized boolean is the defect, rather than the restore clamp, is @HelloOjasMutreja's diagnosis from #4853. Passing both props stays supported and every configuration that works today resolves to the same collapse state it does now; when the two props genuinely address the same state (defaultIsCollapsedon both, or a controlledcollapsiblealongside collapse state onresizable)resizablewins and a dev warning names the conflicting keys.useResizablegains the standard controlled/uncontrolled pair,defaultIsCollapsedandisCollapsed, alongside the existingonCollapseChange: uncontrolled it owns collapse as before, controlled the prop wins andcollapse(),expand()and a drag past the threshold report through the callback instead of mutating. Persisted entries now store{size, isCollapsed}wheresizeis the expanded size — the encoding is @AKnassa's from #4824 — so a reload restores the collapsed rail and expanding returns to the width the user had rather thandefaultWidth; legacy entries still load, with a plain number read as a width whose collapse state is unknown and a plain0(written by the old collapse path) read as collapsed, so anyone already stuck with an invisible nav recovers without clearing localStorage.resizablecan now also carry collapse state on its own. Two notification changes ride along: with a single owner,collapsible.onCollapsedChangefires once per toggle on a resizable nav instead of twice; and the hook's collapse callbacks now read the live collapse state rather than the value captured at their last render, so one drag past the threshold reports one collapse instead of one per pointer move, dragging back above the threshold re-expands mid-gesture, andresize()out of the collapsed state reports the implicit expand. That last fix is @AKnassa's, from #5118. (#5075) -
Slider: dragging the thumb with a mouse no longer draws the keyboard focus ring (#5463) The thumb is a
div[role="slider"], and the track'spointerdownhandler callspreventDefault()and then focuses the thumb from script. Chromium treats that script focus as focus-visible, so:focus-visiblematched on mouse-down and every drag came with a 2px accent ring — measured in Chromium, not inferred.:focus-visiblestays the CSS condition; it is now narrowed by the existinginteractionModalityutility, the same way PanelSearchInput and Selector narrow theirs. Keyboard focus rings exactly as before, and a mouse grab of a thumb that already had the ring drops it.One deliberate difference from the text-input cases: a keypress after a mouse drag brings the ring back. A text field has a caret to show where input is going, and a slider thumb has nothing else.
-
Keep useResizable callbacks stable when snap points are omitted. (#5276)
-
Keep useLayer trigger refs and return objects stable when their inputs are unchanged. (#5272)
-
Keep useTheme token resolvers and return values stable when the resolved theme is unchanged. (#5274)
-
Table sticky columns: the pinned-column shadow now reads the theme's
--color-shadowtoken instead of a hardcodedlight-dark()tint, so a theme can retint it. (#5445) The tint waslight-dark(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.32))written in the component, chosen because--color-shadow(10%/30% alpha) read as slightly too faint. A literal in a component is the one place a theme cannot reach: every theme got this exact black regardless of its own shadow colour, and the two-point alpha difference bought nothing for it — rendered, the token version differs by at most 5/255 on any channel in light mode and 1/255 in dark, over the ~0.4% of the frame the two shadow strips occupy.Reading the token instead means the seven bundled themes each tint this shadow with the value they already declare for every other shadow (
chocolate#4a35201A,stone#25252a1a, and so on), and a custom theme gets the same reach. -
Syntax-highlighted punctuation (brackets, commas, semicolons, operators) now meets WCAG 2.1 AA contrast (4.5:1) against the code surface in every bundled theme. (#5414)
--color-syntax-punctuationborrowed--color-text-disabled, a token WCAG deliberately exempts from the normal-text contrast requirement because it marks an inactive control. Punctuation in a code sample is always-active, normal text, and measured well under 4.5:1 in three themes: neutral (2.42:1 light, 2.53:1 dark), chocolate (3.06:1 light, 2.56:1 dark), and matcha (3.83:1 light, 2.73:1 dark). The other four themes (butter, gothic, stone, y2k) already defined their own passing punctuation colour and are untouched.The shared default now points at
--color-text-secondaryinstead (used for--color-syntax-commenttoo, and already verified to clear AA). Neutral, chocolate and matcha each get a dedicated punctuation colour in their own syntax palette, since they define one rather than inheriting the shared default: neutral#6e6e6e/#a0a0a0(4.89:1/7.57:1), chocolate#9e622e/#cb884d(4.84:1/6.12:1), matcha#566a39/#92af6a(5.19:1/7.02:1).Adds
scripts/check-syntax-punctuation-contrast.test.mjs, resolving each theme's--color-syntax-punctuation/--color-syntax-backgroundpair throughlight-dark()/var()indirection (the pattern from #4446's badge contrast guard) and holding every theme, both colour schemes, to AA — so a regression here fails the build instead of shipping. -
Table keeps grouped headings and selected-row washes visible across frozen columns while scrolling sideways (#5454)
useTableGroupedRowspins its default heading and collapse control to the table's start edge.useTableSelectionnow publishes and withdraws the selected-row overlay with the row background, so the wash continues under sticky cells. -
Text, Heading: a truncated label shows one tooltip, not two. (#5559) When
maxLinesclipped the text, both components rendered Astryx'sTooltipand set the nativetitleattribute to the same string. Hovering drew both: the styled tooltip first, then the browser's own unstyled one on top of it a moment later, saying exactly the same thing.The
titlegoes.Tooltipalready wiresaria-describedbyonto the anchor, and the full text is in the DOM either way — CSS clips it visually, so a screen reader was never reading the truncated version. Nothing is lost but the duplicate.Measured on hover, same story, before and after:
2tooltips shown to the user, then1. -
Seven theme target roots that ran a compound component name together are deprecated onto the
<component-kebab>-<part>spelling the component's name implies:codeblock→code-block(with-copy-button,-header,-title),progressbar→progress-bar(with-fill,-mark,-track),hovercard→hover-card,statusdot→status-dot,textarea→text-area,navicon→nav-icon, and Table's second rootbase-table→table(both named the same<table>element). AdefineThemekey that matches no target fails silently — no error, no warning, the rule never emits — so someone who readProgressBarand wrote'progress-bar'got nothing and no explanation. Nothing breaks: every component renders both classes and both keys resolve, including the derived vars a renamed key expands into. The old spellings drop in the next major. (#5449) -
Toast fits narrow and safe-area viewports, aligns wrapped actions and dismissal, uses edge-directed entrance and exit motion, exposes the Notifications landmark only while populated, and keeps exactly the viewport gutter below the final toast (#5353, #5460) Inter-toast spacing is 8px, while the visual bottom no longer adds a trailing toast gap on top of viewport padding. Placement, visible-stack limits, auto-hide defaults, announcement semantics, and dismissal reasons are unchanged.
-
TreeList: forward
aria-label/aria-labelledbyto therole="tree"element so a tree can be named (#5493)TreeListdestructured a fixed set of props with no rest spread, so everyBasePropsattribute (aria-*,role,tabIndex,id, event handlers) was dropped and never reached the DOM. A tree without a visible header could not be named at all - a screen reader announced an unnamed tree with no way to know what it was.The component now spreads the remaining props onto the root element and routes
aria-label/aria-labelledbyonto the<ul role="tree">itself, so<TreeList aria-label="File tree">names the tree. When a visibleheaderis rendered, it keeps naming the tree (AT hears the same name the user sees); a consumer-suppliedaria-labelledbyonly applies on the headerless path. The contractrole="tree"is written after the rest spread so a consumer cannot displace it.
useAnnounce,useTypeahead,useInteractiveRole,useLongPress,useInputStatusIcon,useDevWarninganduseIndicatorFocusRingare now discoverable. The CLI's hook index is built from the.doc.mjsfiles next to each hook, and these seven shipped without one; soastryx hook <name>answered "No hook named",astryx hookomitted them andastryx searchnever returned them, while the package exported them with full TSDoc. Agents following the documented discovery workflow concluded the primitives did not exist and hand-rolled replacements; foruseAnnouncethat means a hand-builtaria-liveregion, which usually does not announce at all. A test now fails when a hook is exported from the barrel without a doc, so the index cannot silently go stale again. (#5109)
-
Component docs can declare structured
usage.accessibilityrequirements, andastryx componentrenders them as a dedicated Accessibility section in full and compact output. Translated and dense documentation overlays preserve the base accessibility guidance unless they explicitly replace it. (#5646) -
Icon APIs and themes accept namespaced extension keys, and NumberInput steppers use
numberInput:stepperDownwithout widening the requiredIconRegistrykeys (#5466)<Icon icon>,useIcon, anddefineTheme({icons})accept keys such asnumberInput:stepperDownandrichtext:bold; misspelled built-in names remain type errors. NumberInput keeps a compact centered Core fallback, while themes can override its steppers independently from the sharedchevronDownsemantic. -
Rebuild the
settings-dialogpage template with searchable navigation, responsive grouped controls, live appearance previews, configurable keyboard shortcuts, and docsite gallery visibility. (#5568) -
New
table-filterpage template: a table page built around a filter token list (#5448) Ports the feature set of the internal XDS table page pattern onto Astryx primitives. The filter row is a token list of quick-filter toggles and field controls —Selector,MultiSelector, and aComplexSelectorwrapping a rangeSlider— that swaps toPowerSearchfor anything the tokens can't express. Both modes read and write the samePowerSearchFilter[], so a filter built in either survives the swap. Controls carry field chrome when unset and a pressed fill once they hold a value, so the row reads as one family whether a clause came from a toggle or a selector.Around that: saved views that capture the filters and the whole table configuration, a bulk-edit bar that slides in on selection, and a view options popover with four panels — a drag-and-drop column transfer list, density, sticky edges, and grouping — that apply instantly. Clicking a row opens a resizable detail panel. The list pages in by infinite scroll against an
IntersectionObserver, with skeleton rows aligned to the table's own column grid standing in for the batch in flight, and empty states for the no-results and no-data paths. The toolbar wraps to a second row under a container query rather than a viewport one, so it responds to the width the detail panel leaves it.Uses the
Table - Filteringcategory, already reserved in theTemplateCategoryunion.
-
build/searchno longer rank a partially-matched template above one matching every term, no longer index TypeScript generic arguments as rendered components, and no longer treat breadth of rendered components as full-strength relevance. (#5614) -
Component and hook names resolve case-exactly on macOS and Windows, matching Linux (#5478)
findComponentReadme,findComponentSourceandfindHookDocprobed candidate paths withfs.existsSync, which answers through the filesystem's own case folding. On a case-insensitive filesystemastryx component buttonresolved toButtoninstead of reporting an unknown component with suggestions, andfindHookDoc(core, 'mediaquery')returned.../hooks/useMediaquery.doc.mjs— a spelling that exists nowhere, and that breaks any consumer reading it on Linux. The probes now verify each path segment against its parent's real directory listing, so these component and hook lookups resolve the same names to the same real paths on every host. The deliberate case-insensitive hook lookup is unchanged; it now returns the file's true casing. -
The 56
--color-data-*defaults now reach runtime CSS and built themes from the same source, while dashboard template fallbacks match those defaults (#5562, #5566) The defaults live once at:rootin@layer astryx-base, so nested themes inherit parent overrides andastryx theme buildmatches<Theme>whilegenerateThemeCSSkeeps its existing return shape.Visual change. A chart or template that previously painted nothing or used a mismatched hex fallback now paints the data token's default. Pin an explicit color to preserve a previous fallback.
-
The theme-showcase page no longer clips its own controls. In the store's product cards the quantity field and "Add to cart" button spilled out of both sides of the card; in the checkout card the card number truncated mid-number (
1234 1234 12), the country selector ellipsized, and the pay button was left with only a few pixels of slack. (#5539) The product-card row is the more visible of the two. It had no width of its own — the enclosing stack centers rather than stretches its children — so it sized to its contents and, being centered, overflowed the card at both edges once those contents outgrew it. That stayed hidden while the quantity field was narrow, and surfaced whenNumberInputmoved totype="text"for formatted display: a text input's defaultsize=20made the field ~200px instead of ~65px, and the template was pinning it with astyleminWidth(a floor, not a cap) plusflexShrink: 0. The field now usesNumberInput'swidthprop, which is what actually sizes a field, and the row is pinned to the card width and allowed to wrap so the button drops to its own full-width line instead of ellipsizing on a narrow card.The checkout sat in a grid track with a 200px minimum, so its width was a fraction of however many tracks happened to fit — it swung between 208px and 328px as the viewport resized, and the narrow end is well under what the form needs. Themes with a large spacing scale suffered most: Matcha's
--spacing-5card padding alone spends 60px of that budget.The checkout and chat panels are now a wrapping flex row. They share a row at roughly 1:2 while both flex bases fit, then the chat drops to its own full-width row, which makes 300px a floor for the checkout rather than an accident of the track count. Raising the track minimum instead would have left a tall gap beside the checkout at mid widths, since a two-track row can't hold a two-track span.
Two narrower fixes ride along, both text the card was breaking rather than fitting: the payment-method grid's minimum goes 70px to 80px so "Google" stops breaking mid-word on Matcha and Y2K, and on phones the card drops one padding step and sheds the card number's decorative start icon, which together buy back the room a 16-digit number needs at 360px.
useAnnounce,useTypeahead,useInteractiveRole,useLongPress,useInputStatusIcon,useDevWarninganduseIndicatorFocusRingare now discoverable. The CLI's hook index is built from the.doc.mjsfiles next to each hook, and these seven shipped without one; soastryx hook <name>answered "No hook named",astryx hookomitted them andastryx searchnever returned them, while the package exported them with full TSDoc. Agents following the documented discovery workflow concluded the primitives did not exist and hand-rolled replacements; foruseAnnouncethat means a hand-builtaria-liveregion, which usually does not announce at all. A test now fails when a hook is exported from the barrel without a doc, so the index cannot silently go stale again. (#5109)- rewrite all 46 page template descriptions to describe layout, container, data shape and behaviour — the things that actually differentiate one template from its siblings — instead of the sample data they happen to ship with, so
buildandsearchretrieve them from a description of the problem rather than a guess at the slug. (#5615)
-
Vite build: Astryx and product styles are split into their own cascade layers, so a theme's component overrides apply in a production build (#5410) StyleX emits every rule it collects into one top-level
@layer priority1…priorityN. The dev server re-served those partitioned by source file — Astryx's own styles intoastryx-base, the app's intoproduct— but a build did neither, so the priority layers landed outside the@layer reset, astryx-base, astryx-theme, productorder and outranked all of it. Everycomponents: {…}override a theme set — a colour, a radius, a public custom property — was silently dropped in the built app while working in dev.The build now runs the same partition the dev server does, from the same helper, so the promised order holds in both: Astryx's styles are overridable by a theme, and an app's own styles still outrank everything.
- Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
- Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
- Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
- Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
- Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
- Stone theme: move
--color-text-secondaryto the canonical T40/T70 pair so normal secondary text meets WCAG AA across the theme's light and dark consumer surfaces (#5505) (#5509) - Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
- Theme packages no longer ship an unused CommonJS
icons.jsartifact. Their root entry keeps its advertised CommonJS and ESM outputs, while the standalone icon companion used by/builtis emitted only asicons.mjs. (#5512)
Thanks to everyone who contributed to this release:
@AKnassa @Astro-Han @bhamodi @cixzhang @ernestt @freddymeta @gonzoblasco @HelloOjasMutreja @imdreamrunner @jiunshinn @josephfarina @lexs @nynexman4464 @rubyycheung
Full Changelog: https://github.com/facebook/astryx/compare/v0.5.0...v0.5.1
v6.3.289
This release contains improvements for accessibility, annotation editing, annotation rendering, font conversion, image decoding, performance, text selection and the viewer.
- Bump the stable version in
pdfjs.configby @timvandermeij in https://github.com/mozilla/pdf.js/pull/21655 - [Editor] Restore pinch-to-resize on an editor which came back from an undo by @calixteman in https://github.com/mozilla/pdf.js/pull/21644
- Use more more optional chaining in the
src/folder by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21661 - Avoid duplicate shared object clones by @calixteman in https://github.com/mozilla/pdf.js/pull/21658
- Avoid mutating source widget parents by @calixteman in https://github.com/mozilla/pdf.js/pull/21660
- Fix the selection rendering when a page has been destroyed and rendered again (bug 2054348) by @calixteman in https://github.com/mozilla/pdf.js/pull/21666
- l10n: Update locale files by @sync-l10n-for-pdf-js[bot] in https://github.com/mozilla/pdf.js/pull/21669
- Sync the viewer chrome with the Firefox design system by @calixteman in https://github.com/mozilla/pdf.js/pull/21665
- [api-minor] Convert
getJSActionsto return data in a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21664 - Use the client coordinates for the pinch-zoom origin by @calixteman in https://github.com/mozilla/pdf.js/pull/21659
- Re-factor the
EventBusto use Map/Set internally by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21673 - Replace simple return
ifstatements with ternary operators by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21672 - Let pointerup/cancel propagate in TouchManager by @calixteman in https://github.com/mozilla/pdf.js/pull/21674
- Shorten the
ViewHistoryclass a little bit by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21678 - Don't throw on an invalid XML character reference by @calixteman in https://github.com/mozilla/pdf.js/pull/21682
- Fix the regex used to normalize css fonts in XFA by @calixteman in https://github.com/mozilla/pdf.js/pull/21680
- Trim the response headers with a backward scan by @calixteman in https://github.com/mozilla/pdf.js/pull/21684
- Find the PDF filename in a URL hash in two linear steps by @calixteman in https://github.com/mozilla/pdf.js/pull/21685
- Scan backwards to delete a word in a text field by @calixteman in https://github.com/mozilla/pdf.js/pull/21687
- Add scripts correctly in
Field.prototype.setAction(PR 12569 follow-up) by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21691 - Update dependencies to the most recent versions by @timvandermeij in https://github.com/mozilla/pdf.js/pull/21689
- Exclude "&" from the XML entity names by @calixteman in https://github.com/mozilla/pdf.js/pull/21692
- [api-minor] Convert
getFieldObjectsto return data in a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21671 - Anchor the regex used to extract the XFA path positions by @calixteman in https://github.com/mozilla/pdf.js/pull/21686
- Don't write numbers in exponential notation when saving a pdf by @calixteman in https://github.com/mozilla/pdf.js/pull/21683
- Bound the email parts in the autolinker regex by @calixteman in https://github.com/mozilla/pdf.js/pull/21693
- Safely serialize CSS font family names by @calixteman in https://github.com/mozilla/pdf.js/pull/21694
- Add a go to first/last menu-item helper method in the
Menuclass by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21690 - Document how to use the viewer to open files by @martinthomson in https://github.com/mozilla/pdf.js/pull/21695
- Add integration tests for the Home/End keys in the
Menuclass by @calixteman in https://github.com/mozilla/pdf.js/pull/21706 - Bump undici from 7.28.0 to 7.29.0 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21701
- Bump github/codeql-action/analyze from 4.37.2 to 4.37.3 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21705
- Bump github/codeql-action/init from 4.37.2 to 4.37.3 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21704
- Bump github/codeql-action/autobuild from 4.37.2 to 4.37.3 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21703
- Shorten the
Menuconstructor a tiny bit by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21700 - Enable the
regexp/no-super-linear-moveESLint rule by @calixteman in https://github.com/mozilla/pdf.js/pull/21708 - Bump fast-uri from 3.1.4 to 3.1.5 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21712
- Remove the ambiguity from the PostScript number regex by @calixteman in https://github.com/mozilla/pdf.js/pull/21709
- Avoid an infinite loop on cyclic field Parent chains by @calixteman in https://github.com/mozilla/pdf.js/pull/21699
- Enable a few more
eslint-plugin-regexprules by @calixteman in https://github.com/mozilla/pdf.js/pull/21710 - Give copied annotations distinct references by @calixteman in https://github.com/mozilla/pdf.js/pull/21707
- Use the
MathClamphelper in thesrc/core/annotation.jsfile by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21715 - Update
PDFViewerApplication._initializeAutoPrintto handlegetJSActionsreturning a Map (PR 21664 follow-up) by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21716 - Move
SCALE_MATRIXintoCanvasGraphicsand initialize itsDOMMatrixlazily (issue 21720) by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21721 - Convert
TranslatedFont.prototype.loadType3Datato an asynchronous method by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21719 - Don't re-encode the
fileparameter in the viewer by @calixteman in https://github.com/mozilla/pdf.js/pull/21718 - Add helper methods for populating
dateActionsCache/scandCachein thesrc/scripting_api/util.jsfile by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21681 - Handle image-only PDF exports by @calixteman in https://github.com/mozilla/pdf.js/pull/21717
- l10n: Update locale files by @sync-l10n-for-pdf-js[bot] in https://github.com/mozilla/pdf.js/pull/21724
- Compute the next ParentTree key correctly by @calixteman in https://github.com/mozilla/pdf.js/pull/21714
- Expose the table structure attributes in the struct tree by @calixteman in https://github.com/mozilla/pdf.js/pull/21702
- Track container touches in TouchManager by @calixteman in https://github.com/mozilla/pdf.js/pull/21722
- Change the inline image cache, in the
Parserclass, to a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21727 - Convert the
charProcOperatorList, used with Type3 fonts, to a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21730 - [api-minor] Convert
getPermissionsto return data in a Set by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21738 - Improve glyph mapping for non-embedded CID fonts by @calixteman in https://github.com/mozilla/pdf.js/pull/21726
- Re-name the
RefSetCacheclass toRefMapby @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21737 - Expose more tagged PDF structure roles by @calixteman in https://github.com/mozilla/pdf.js/pull/21734
- Hide unavailable alt text settings by @calixteman in https://github.com/mozilla/pdf.js/pull/21735
- Keep pinching when the touch set changes by @calixteman in https://github.com/mozilla/pdf.js/pull/21731
- Replace most
toBeTruthy()/toBeFalsy()matchers with more specific ones in the unit-tests by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21739 - Change
RefSetandRefMapto use actually private class fields by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21728 - Improve ink drawing responsiveness by @calixteman in https://github.com/mozilla/pdf.js/pull/21733
- Fix the license text bundled for pdf.js.qcms by @calixteman in https://github.com/mozilla/pdf.js/pull/21747
- Fix the license file for the bundled Liberation fonts by @calixteman in https://github.com/mozilla/pdf.js/pull/21750
- Cache the result of
buildSymbolGlyphIdEncoding(PR 21726 follow-up) by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21740 - Improve some
Array.from()usage by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21742 - Re-use the
stringToByteshelper in theencodeASCIIStringfunction by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21743 - [Editor] End active touch gestures on destroy by @calixteman in https://github.com/mozilla/pdf.js/pull/21744
- Ignore degenerate touch spans when scaling by @calixteman in https://github.com/mozilla/pdf.js/pull/21741
- Remove overridden/duplicated
[$getChildren]methods by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21736 - Remove unnecessary
rectmodification in theCanvasGraphics.prototype.beginAnnotationmethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21729 - Fix intermittent thumbnail dragging integration test by @calixteman in https://github.com/mozilla/pdf.js/pull/21751
- Enable the
unicorn/no-incorrect-query-selectorESLint plugin rule by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21754 - Bump github/codeql-action/init from 4.37.3 to 4.37.6 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21755
- Bump github/codeql-action/autobuild from 4.37.3 to 4.37.6 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21756
- Bump github/codeql-action/analyze from 4.37.3 to 4.37.6 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21757
- Fix intermittent pinch-resize integration test by @calixteman in https://github.com/mozilla/pdf.js/pull/21753
- Fix coalesced-events test at fractional device pixel ratios by @calixteman in https://github.com/mozilla/pdf.js/pull/21758
- Expose PDF alternative text without prohibited ARIA names by @calixteman in https://github.com/mozilla/pdf.js/pull/21759
- Support two-finger panning by @calixteman in https://github.com/mozilla/pdf.js/pull/21752
- Tweak the TR/TR2 check in the
PartialEvaluator.prototype.setGStatemethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21764 - Avoid spilling xref entries into dynamically allocated slots (bug 2060459) by @calixteman in https://github.com/mozilla/pdf.js/pull/21766
- Add a simple integration-test for the "updatedPreference" event by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21767
- Only define the
getRawDataAPI methods when building INTERNAL_VIEWER by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21772 - Remove unnecessary
typeofcheck inField.prototype.currentValueIndicesby @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21774 - Avoid creating a couple of intermediate Arrays by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21773
- Fix the two MathClamp calls the prefer-math-clamp fixer mis-ordered by @Jaybhade in https://github.com/mozilla/pdf.js/pull/21725
- Simplify the
Stepper.prototype.getNextBreakPointmethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21762 - Let the
StructElementNode.prototype.tableAttributesgetter return a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21761 - l10n: Update locale files by @sync-l10n-for-pdf-js[bot] in https://github.com/mozilla/pdf.js/pull/21775
- [Editor] Make HighlightEditor extend DrawingEditor by @calixteman in https://github.com/mozilla/pdf.js/pull/21769
- Normalize the line ending of test/pdfs/issue9186.pdf.link by @calixteman in https://github.com/mozilla/pdf.js/pull/21776
- Add a gulp task for releasing pdf.js in the Firefox git tree by @calixteman in https://github.com/mozilla/pdf.js/pull/21777
- Shorten some
Array.prototype.map()callbacks by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21780 - Use
Array.prototype.filter(Boolean)more, when filtering out truthy values by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21781 - Nova-ify the viewer (bug 2063405) by @calixteman in https://github.com/mozilla/pdf.js/pull/21779
- Modernize the
XRefMockunit-test helper by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21782 - Use the structure tree to position annotations by @calixteman in https://github.com/mozilla/pdf.js/pull/21768
- Update dependencies to the most recent versions by @timvandermeij in https://github.com/mozilla/pdf.js/pull/21784
- Improve Firefox watch builds by @calixteman in https://github.com/mozilla/pdf.js/pull/21783
- Fix flaky hand tool integration test by @calixteman in https://github.com/mozilla/pdf.js/pull/21785
- Enable the
unicorn/no-multiple-promise-resolver-callslinting rule by @timvandermeij in https://github.com/mozilla/pdf.js/pull/21786 - Define the visible-page sort function, used in
getVisibleElements, once by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21787 - Remove unnecessary
!lzwStatecheck inLZWStream.prototype.readBlockby @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21788 - Fix the RTL layout of the views manager header (bug 2060033) by @calixteman in https://github.com/mozilla/pdf.js/pull/21790
- Set the direction of the floating toolbar in RTL locales (bug 2060032) by @calixteman in https://github.com/mozilla/pdf.js/pull/21791
- Fix intermittent reorganize pages integration tests by @calixteman in https://github.com/mozilla/pdf.js/pull/21789
- Use
Uint8Array.fromHexin theCFFParserunit-tests setup by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21793 - Let link annotations own their text by @calixteman in https://github.com/mozilla/pdf.js/pull/21792
- Fix Firefox-only tests in Chrome CI by @calixteman in https://github.com/mozilla/pdf.js/pull/21795
- Downscale large JPEG images with ImageDecoder (bug 2063570) by @calixteman in https://github.com/mozilla/pdf.js/pull/21794
- Remove unused l10n IDs by @calixteman in https://github.com/mozilla/pdf.js/pull/21798
- Avoid creating a couple of intermediate Arrays by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21797
- Improve the
watchScrollhelper function a little bit by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21796 - Auto-close the marked content sections left open in a text object (bug 1898053) by @calixteman in https://github.com/mozilla/pdf.js/pull/18151
- Improve
JpegImage.canUseImageDecoderreturn value consistency by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21800 - Cache the
TextDecoderinstances used by thestringToPDFStringhelper by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21801 - Remove a few unnecessary checks after calling
BaseStream.prototype.getBytesby @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21804 - Cache the
TextDecoder/TextEncoderinstances used when compiling/decompiling font-data by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21806 - Vertically center the text in single-line and comb text fields (bug 2055455) by @calixteman in https://github.com/mozilla/pdf.js/pull/21802
- l10n: Update locale files by @sync-l10n-for-pdf-js[bot] in https://github.com/mozilla/pdf.js/pull/21808
- Avoid zooming during fast two-finger panning by @calixteman in https://github.com/mozilla/pdf.js/pull/21807
- Remove the unused /Decode handling from the
JpegStream/JpegImageclasses by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21809 - Modernize the Node.js
getinfo.mjsexample by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21811 - Remove the unused
key3parameter from the variousDictget-methods by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21815 - Fix inconsistencies with the
Page.prototype.#replaceIdByRefmethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21812 - Add a helper method, in the
PartialEvaluatorclass, for building a transfer map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21816 - Shorten the handling of /A and /a page labels by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21814
- Re-use
computeLuminancein theDOMFilterFactory.prototype.addHCMFiltermethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21813 - Bump github/codeql-action/autobuild from 4.37.6 to 4.37.7 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21823
- Bump github/codeql-action/init from 4.37.6 to 4.37.7 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21822
- Bump github/codeql-action/analyze from 4.37.6 to 4.37.7 by @dependabot[bot] in https://github.com/mozilla/pdf.js/pull/21821
- Shorten the
Parser.prototype.#hasCryptFiltermethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21824 - Remove unused /FS branch from the
FileSpecconstructor by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21819 - Remove the "duplicated"
Page.prototype.createAnnotationEvaluatormethod by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21817 - Add more unit-tests for the
src/core/primitives.jsfile by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21820 - Use ImageDecoder for JPEG dimension mismatches without resizing (bug 2066163) by @calixteman in https://github.com/mozilla/pdf.js/pull/21818
- Change
Word64.prototype.shiftRightto only supportplaces < 32(PR 4938 follow-up) by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21826 - Add a helper function for writing lineTo/curveTo when creating Appearance-streams for Annotations by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21831
- Remove unused
BasePdfManager/LocalPdfManagermethods by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21827 - [api-minor] Convert
documentInfoto return any "Custom" data in a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21828 - Localize the comment dialog save button through its label span by @calixteman in https://github.com/mozilla/pdf.js/pull/21830
- l10n: Update locale files by @sync-l10n-for-pdf-js[bot] in https://github.com/mozilla/pdf.js/pull/21833
- [api-minor] Convert
markInfoto return data in a Map by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21834 - Improve unit-test coverage for the
getViewerPreferencesfunctionality by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21835 - Remove the unused
getOutputLengthmethod from theColorSpaceclasses (PR 21637 follow-up) by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21837 - Tweak the
WorkerTaskclass and thehasJSActionsgetter by @Snuffleupagus in https://github.com/mozilla/pdf.js/pull/21841
Release 2026-08-29 00:36
Release 2026-08-29 00:36
- solid: bump to solid-js 2.0.0-rc.4 and @solidjs/vite-plugin 3.0.0-next.35 (#8189) (22fd367d81) by @brenelz
- @tanstack/solid-router@2.0.0-rc.4
- @tanstack/solid-router-devtools@2.0.0-rc.4
- @tanstack/solid-router-ssr-query@2.0.0-rc.4
- @tanstack/solid-start@2.0.0-rc.4
- @tanstack/solid-start-client@2.0.0-rc.4
- @tanstack/solid-start-server@2.0.0-rc.4
@tanstack/solid-start@2.0.0-rc.4
-
#8189
22fd367- Bump solid-js and @solidjs/web to ^2.0.0-rc.4 and @solidjs/vite-plugin to ^3.0.0-next.35 across the monorepo. -
#8189
22fd367- Patch @rsbuild/plugin-solid's nativesolidloader options for SSR builds. Since 2.0.0-beta.1 the plugin compiles through its own loader (native compiler by default) instead of registering babel-preset-solid, so the babel preset patch never fired and node-target bundles were compiled in dom mode, crashing at import with "Client-only API called on the server side". The rsbuild start plugin now patches the loader'ssolidoptions (generate: 'ssr'on node targets,hydratable: true) alongside the legacy babel preset patch. -
#8189
22fd367- Support per-call AbortSignals for Solid server functions. solid-js 2.0.0-rc.4 added the per-call invocation channel (invoke(fn, { signal }, ...args)) and moved server function id resolution from theX-Server-Functionheader to the request url pathname; the client rpc now rides that channel when asignalis passed to a server function, and the server handler resolves/normalizes ids via the url. The previously skipped abort e2e tests are re-enabled. -
Updated dependencies [
22fd367]:- @tanstack/solid-router@2.0.0-rc.4
- @tanstack/solid-start-client@2.0.0-rc.4
- @tanstack/solid-start-server@2.0.0-rc.4
Release 2026-08-28 23:43
Release 2026-08-28 23:43
- solid-query: rewrite the adapter onto Solid 2.0's native async model (#11308) (c809e09e8) by @ryansolid
- eslint-plugin-query: ignore call targets in exhaustive-deps (#11067) (7ac45ed45) by @Newbie012
- query-devtools: set window.nonce in setupStyleSheet (#10736) (49012dbd5) by @842u
- devtools: add transform: translateZ(0) for Safari overflow rendering (#10638) (ceec8f0a8) by @lihan3238
- query-devtools/utils: scope the 'setupStyleSheet' dedup check to the target so a 'shadowDOMTarget' still receives its own '#_goober' style tag when 'document.head' already has one (#10815) (ecd89c8fa) by @sukvvon
- query-devtools/Devtools: correct the Theme sub-trigger className from 'position' to 'theme' (#10811) (01c763444) by @sukvvon
- query-devtools/PiPContext: reset 'pip_open' in 'localStore' from 'closePipWindow' so the auto-open createEffect does not reopen the window after a programmatic close (#10813) (f5bf180d9) by @sukvvon
- query-devtools/utils: make 'last updated' sort return 0 for queries with equal 'dataUpdatedAt' to follow the standard comparator contract (#10812) (25cdd975f) by @sukvvon
- lit produces dist-js which needs to be a prod build output (#10995) (9cb8eac3f) by @TkDodo
- release: avoid pre dist tag for prereleases (#10986) (e6ad3fc40) by @brenelz
- svelte-query/containers: fix typo from 'Tanstack' to 'TanStack' (#10722) (fcdcf8ac0) by @parkhojeong
- hydration: set dataUpdatedAt when pending query resolves before hydration (#10610) (9eff92ed8) by @DoriAlagem
- special case arrays in partialMatchKey (#11084) (7e3c822a1) by @43081j
- upgrade to solid v2 rc, rename vite-plugin-solid, move branch to rc (19c7623fe) by @brenelz
- update pnpm to 11.9.0 (#10978) (4eb0ed932) by @Sheraff
- @tanstack/angular-query-experimental@5.101.4
- @tanstack/eslint-plugin-query@5.101.4
- @tanstack/lit-query@0.2.11
- @tanstack/preact-query@5.101.4
- @tanstack/preact-query-devtools@5.101.4
- @tanstack/preact-query-persist-client@5.101.4
- @tanstack/query-async-storage-persister@5.101.4
- @tanstack/query-broadcast-client-experimental@5.101.4
- @tanstack/query-core@5.101.4
- @tanstack/query-devtools@5.101.4
- @tanstack/query-persist-client-core@5.101.4
- @tanstack/query-sync-storage-persister@5.101.4
- @tanstack/react-query@5.101.4
- @tanstack/react-query-devtools@5.101.4
- @tanstack/react-query-next-experimental@5.101.4
- @tanstack/react-query-persist-client@5.101.4
- @tanstack/solid-query@6.0.0-rc.1
- @tanstack/solid-query-devtools@6.0.0-rc.1
- @tanstack/solid-query-persist-client@6.0.0-rc.1
- @tanstack/svelte-query@6.1.38
- @tanstack/svelte-query-devtools@6.1.38
- @tanstack/svelte-query-persist-client@6.1.38
- @tanstack/vue-query@5.101.4
- @tanstack/vue-query-devtools@6.1.38