2 hours ago
snapdom

v3.7.1

What's Changed

New Contributors

Full Changelog: https://github.com/zumerlab/snapdom/compare/v3.7.0...v3.7.1

3 hours ago
d3

v7.9.2

  • Revert d3-delaunay’s fix for collinear diagrams.
3 hours ago
paper.js

v0.17.0

Added

  • Add PathItem#offset(distance, options), which grows, shrinks or offsets paths and compound paths with miter, round or bevel corners (#371).
  • Add PathItem#outline(options), which turns the stroke of a path item into a filled path item, with its joins, caps and dashes (#371).
  • Add PathItem#dash(options), which cuts a stroke into its dashes as the canvas draws them, as a group of open paths.
  • Add stroke profiles, Path#strokeProfile: stops along a path that change the width, aspect and angle of the pen that draws its stroke, see StrokeProfileStop. Not yet supported: compound paths, strokeScaling off, and offset(), boolean operations, interpolate() and SVG (#2505, #2506, #2507).
  • Add live effects, Item#effects, which change what an item draws without changing the item, starting with offset and outline. Effect defines new ones, and Item#previewBounds measures what they draw.
  • Add pattern colors from a PatternDefinition, which tiles a raster or any other item, for fills and strokes, also in SVG and JSON (#829).
  • Add Color#aspect for elliptical radial gradients, and transform gradients exactly with their items, also when these scale unevenly or shear (#1744).
  • Add Group#buffered, which keeps a group's drawing in a canvas until the group changes, for large groups that rarely do (#377).
  • Add Item#onDraw and Item#onDrawSelection, which draw beneath an item or its selection, or replace them, also as class-level handlers such as Path.onDraw.
  • Add PathItem#arcAround(center, angle) and PathItem#arcTowards(to) (#1052).
  • Support options in PathItem#simplify(), with tolerance and a range of segments through from and to, as in PathItem#smooth() (#2501).
  • Export and import the names and data of segments in SVG, as a data-paper-segments attribute (#2398).
  • Add Project#onActivate and Project#onDeactivate, also as Project.onActivate and Project.onDeactivate for all projects.
  • Pass the import attributes of import … with { … } in PaperScript on to the loader in options.load of PaperScript.execute().
  • Hosted projects, see Project#host:
    • Share symbol and pattern definitions between items, referred to by their keys in JSON, and let scripts create new ones.
    • Load the pixels of rasters from the host on first access.
    • Load items in full when they move into a project with another host.
    • Call Item#onDraw and Item#onDrawSelection, through Project#draw().

Changed

  • Run the library in strict mode, which makes Path#getNearestPoint() about 14% and Item#hitTest() about 6% faster. PaperScript still runs in sloppy mode.
  • Draw items with opacity, blend modes or shadows about twice as fast (#377).
  • Make PaperScope#project an accessor, so that PaperScript's project follows the active project, as view does.
  • Emit deactivate when the active project or tool is removed.
  • Write the definition of symbol items to JSON as definition instead of symbol, which still loads.
  • Let hosted linked text that moves into a project with another host bring a copy of its story along (#2462, #2463).

Fixed

  • Fix boolean operations that could lose areas or whole results, at straight curves, near-coincident crossings, curves running back and forth along a line, shallow crossings and merged vertices.
  • Measure curve lengths precisely near cusps, where Curve#getLength() and Path#getPointAt() were off by up to 6%.
  • Find the nearest point on curves that cover a lot of ground between their samples, in #getNearestPoint() and the methods using it.
  • Fix PathItem#smooth() with a negative to on closed paths, which threw.
  • Fix PathItem#arcTo() with tiny arcs, which missed their end point.
  • Keep the attributes of compound paths in CompoundPath#reduce() when a single child is left.
  • Return false from CompoundPath#simplify() without children.
  • Keep the stripes of linear gradients across them when transforming them unevenly (#1744).
  • Export the gradients of items that keep their matrix to SVG in the coordinates of their elements (#2410).
  • Honor the bounds and matrix options of Item#exportSVG().
  • Keep Group#isolated and Group#buffered in clones.
  • Keep the content of rasters when setting Raster#size.
  • Load new Raster(source) from a string where there is no document, as in workers.
  • Draw the segments of selected paths again by default (#1899).
  • Count the duration of Item#tween() from the first frame.
  • PaperScript: compile ++ and -- correctly wherever they appear, keep keywords apart from replaced expressions in minified code, report the right lines in stack traces on V8, and return an object from compile() for empty code.
  • Hosted projects: leave items that moved away out of Project#takeChanges(), and turn off View#autoUpdate when setting Project#host.
  • Let Angular's esbuild builder bundle Paper.js for browsers (#2035).
3 hours ago
next.js

v16.5.0-canary.39

Core Changes

  • Strip internal middleware cookie headers from edge responses: #101109
  • Fix stale compressed framing for forwarded fetch responses: #101108
  • [use cache] Fix cache key when binary args are used: #101107
  • Fix shared shell poisoning from request-supplied placeholder params: #101106
  • [next/image] Fix false-positive AVIF/HEIC detection: #101105
  • Fix unstable_cache leaking cold 'use cache' fills across root params: #101104
  • Fix outer 'use cache' entries reused across root param values: #101103

Misc Changes

  • Turbopack: keep CSS Modules when a loader rule's as adds an existing extension: #101065
  • Add segment config parity regression tests: #100881
  • Turbopack: cleanup ReferencedAssetIdent: #101095
  • [test] Fix flaky resume data cache tests: #101088
  • docs: fix import.meta.glob base docs: #101085
  • create-next-app: remove unused webpack bundler option: #101081
  • [experiment] [turbopack-cli] compile .go files: #99980

Credits

Huge thanks to @eps1lon, @lukesandberg, @mischnic, @unstubbable, @icyJoseph, and @timneutkens for helping!

5 hours ago
electron

electron v44.10.2

Release Notes for v44.10.2

Fixes

  • Fixed a crash when using hidden window as the parent in Wayland. #55572 (Also in 43, 45, 46)

Other Changes

  • Backported fixes from upstream ANGLE, Chromium, libaom, libvpx, PDFium, Skia, V8 and WebRTC. #55515
  • Updated Node.js to v24.22.2. #55473
5 hours ago
electron

electron v45.2.2

Release Notes for v45.2.2

Fixes

  • Fixed a crash when using hidden window as the parent in Wayland. #55571 (Also in 43, 44, 46)
  • Fixed removeInsertedCSS() not removing cssOrigin: 'user' stylesheets. #55538 (Also in 46)

Other Changes

  • Updated Chromium to 156.0.8078.80. #55512
  • Updated Node.js to v24.22.2. #55474
5 hours ago
electron

electron v43.8.7

Release Notes for v43.8.7

Fixes

  • Fixed a crash when using hidden window as the parent in Wayland. #55569 (Also in 44, 45, 46)
5 hours ago
astryx

Astryx v0.7.7

Astryx 0.7.7 — all @astryxdesign/* packages ship at this version.

OLD_VERSION=0.7.6  # replace with the Core version your project uses today
npm install @astryxdesign/core@0.7.7 @astryxdesign/cli@0.7.7  # plus every other @astryxdesign/* package you use, at 0.7.7
npx @astryxdesign/cli upgrade --from "$OLD_VERSION" --apply --path .

@astryxdesign/core

New Components

  • Promote InfoTip from Lab to Core, imported from @astryxdesign/core/InfoTip or the package root: an info-icon button whose press pins its help. Hover and keyboard focus preview the help, and a click, tap, Enter, or Space pins it open until Escape, a second press, a press outside, or focus leaving. Its default name is the translated "More information", and under a coarse pointer it takes taps out toward 44 px without taking a neighbour's. The @astryxdesign/lab InfoTip export is now a deprecated re-export of the Core component and is removed in the next release: import it from @astryxdesign/core instead.

New Features

  • AppShell keeps its header items and the end of its content inside the device's safe area on a phone page that opts into the full screen (viewport-fit=cover). A header region or the phone top bar reaches under the status bar and out to the screen's sides while its items stay clear of the status bar, the Dynamic Island and a landscape notch. In height="auto", a phone top bar below a banner sticks under the top inset instead of at the top edge, so its items stay clear when the page scrolls. The main content ends clear of the home indicator (its block-end padding is contentPadding plus the bottom inset, so a child that fills it ends above the indicator), in the page or in the main region's own scroller. A shell with no header region or phone top bar takes no top inset, so its content keeps its own top padding there. In landscape only the header is inset, not an inline SideNav or the content's sides. Without viewport-fit=cover the insets are zero and nothing moves. The AppShell docs say how a page and an installed web app opt in.

  • ChatComposerInput's Return key says Send on a touch keyboard. Enter already sends the message; the editor now sets enterkeyhint="send", so iOS shows its Send key instead of a plain Return. A new enterKeyHint prop, typed by the exported closed union EnterKeyHint, takes another label, such as enter for a composer whose onKeyDown makes Enter insert a line break on touch keyboards.

  • Dialog (and so AlertDialog and CommandPalette), Drawer and MobileNav no longer blur the page behind the modal, under every pointer: the 2px full-viewport backdrop blur is costly to repaint. The dim keeps the theme's --color-overlay, and in forced colors the modal keeps an edge so it still stands apart from the page. BottomSheet never blurred. A theme keeps the blur by setting backdropFilter: 'blur(2px)' on the component's modal backdrop: components.dialog.base['::backdrop'], components['mobile-nav'].base['::backdrop'], and for Drawer components.drawer.base[':modal::backdrop'], which leaves a non-modal drawer (hasScrim={false}) unblurred.

  • Under reduced motion, an indeterminate ProgressBar no longer slides: on every pointer its fill spans the whole track and gently pulses its opacity in place, from full down to 84% and back, two seconds each way. A theme's tempo does not change the pulse, and in the default light and dark themes every fill tone that stands out from the track at 3:1 still does at the pulse's lowest point.

  • Under a finger (a coarse primary pointer, on every touch device), a determinate ProgressBar moves to a new value the way iOS's progress view does: linearly, taking one second per full track of change at the theme's default tempo (0.8 s from 10% to 90%), and from wherever the fill is drawn when the value changes again mid-way. A theme's tempo scales that time. Above zero the fill never draws shorter than two track heights, and at zero it is not drawn. The motion runs on the compositor, so it keeps going while a script runs; under reduced motion, or with forced colors on, a new value lands at once. A mouse or trackpad keeps the theme's duration and easing.

  • Search fields ask a touch keyboard for its Search key and no autocorrection. The search inputs of Typeahead, Tokenizer (and so PowerSearch), CommandPaletteInput and the Selector and MultiSelector search row now carry enterkeyhint="search" and autocorrect="off". A phone keyboard then shows a Search key instead of Return and leaves names and identifiers as typed. The key is only a label: Enter does what it did before in each field.

  • SegmentedControl: under a finger, on a touch device (a coarse primary pointer), the control tracks the touch. Dragging the selected segment carries the selection along with the finger, and the segment under the finger is chosen when it lets go (onChange fires once, at the lift); letting go outside the control selects nothing. While the selection is dragged, the selected label's colour follows it, with a margin around each boundary so a finger resting on one never flickers; label weights change only at the lift, so nothing reflows under the finger. A tap selects through the browser's own click, and a pressed segment shows the shared pressed overlay; nothing lifts or dims. A vertical drag that starts on the control still scrolls the page. A commit the item's onClick vetoes sends the selection back at once; one a controlled parent adopts later lands without a bounce. With Reduce Motion the selection still follows the finger, with no chase, and only the lift cross-fades. Keyboard and assistive technology keep the click; no element is added.

  • SegmentedControl: a mouse or a pen drags the selection as a finger does. A drag from the selected segment carries it with the pointer, and the release commits the segment under the pointer (onChange fires once, at the release). A release outside the control selects nothing, and a drag that starts on another segment commits where it lifts. Under a mouse or a pen, every change slides the selection on the theme's duration and easing, not UIKit's spring, and a click slides it too. With Reduce Motion, a mouse's or a pen's drag still carries the selection, and its release lands at once. Keyboard and assistive technology keep the click.

  • SegmentedControl: under a finger the selection slides to the new segment on UIKit's spring, whether a tap, an arrow key or a new value moved it. The selection indicator is the control's own pseudo-element, so no element is added. The motion runs on the compositor and keeps moving while the main thread is busy. With Reduce Motion nothing travels or scales: the old selection fades out where it is as the new one fades in. The spring is UIKit's measured one, an internal motion role no theme retunes, and no theme value lengthens the Reduce Motion fade. With a mouse or a pen it slides on the theme's duration and easing instead.

  • Switch's press and drag work with a mouse and a pen as well as a finger: a drag past the flip point toggles the switch at the release, unless the pointer came back past where it pressed. A mouse or pen press released away from the switch leaves it alone, flipped or not, as a checkbox does. With a mouse the switch keeps its desktop look, and the value moves the thumb. On a touchscreen laptop a finger flips it by the same rule, with the desktop look.

  • Under a finger, on every touch screen, Switch moves like the iOS switch. A press lifts the thumb a little, with a soft shadow, and a horizontal drag moves it with the finger and flips the switch once the finger has travelled most of the track; lifting the finger commits. A tap toggles through the browser's own click, and a hold or a short drag toggles at the lift. The thumb stays inside the track however far the finger drags past either end, in either writing direction. A press slid off the switch and lifted outside still toggles it, as on iOS. A vertical drag scrolls the page and the switch lets go. The motion runs on the compositor, so it stays smooth while scripts run. The thumb keeps its circle and its size on every device, and under a coarse pointer the switch's invisible hit area grows toward 44 × 44 px with nothing visible added, stopping halfway to any neighbouring control so a tap goes to the nearer one. The track keeps its theme's fill, and the colour change crossfades over it. With reduced motion on, a change cross-fades instead of moving on a touch screen and is immediate with a mouse. A press shows the pressed overlay, through a drag too, and a still hold selects no text. Keyboard and assistive technology behave as before. In Chromium, a Switch retargeted right after a tap, such as one tapped again mid-travel, turns around from where it is, with no step back to the start of its travel. Switch joins Slider on the shared press tracking and touch negotiation.

Fixes

  • A Dialog with purpose="info", a Drawer's scrim, and CommandPalette now close on a backdrop press only when the press both starts and ends on the backdrop. Selecting text in a field and releasing past the edge no longer closes it and loses the input. A press on the backdrop alone still closes it, with a mouse, a pen, or a finger.

  • BottomSheet: in WebKit, including iOS Safari, a sheet at a set height whose content sits directly in it keeps its bottom padding at the end of its scroll (0 → 16 px), instead of ending flush with the last line.

  • BottomSheet: the open sheet's dialog places its panel with a flex row instead of a grid. In desktop WebKit, measured in Playwright, an update inside an open sheet lays out faster; the iOS simulator showed no difference. A percentage height (for example '50%') now takes that share of the screen at the bottom edge; before, a short sheet was cut short and a long one hung from the top of the screen.

  • BottomSheet: a sheet closed from a control inside it, such as a Done button, a Selector's search field or a menu row, marked itself inert and aria-hidden while that control still had focus. The browser then dropped focus to the page, or screen readers were left in a hidden subtree, for the length of the exit. Now a standalone sheet that closes with focus inside it stays out of inert and aria-hidden while that focus stays, and ignores pointer and keyboard activation during its exit; when the exit ends, it closes and returns focus to its opener. The exit still plays. A sheet that closes with focus elsewhere, or that focus leaves during the exit, goes inert at once, as before.

  • BottomSheet: a sheet that a Suspense boundary hid while it was closing, and then showed again, never finished closing. Its dialog stayed open, modal and inert, so the whole page under it ignored taps, clicks and focus until a reload. This happens, for example, when a sheet's action navigates to a route that suspends. Now the sheet finishes closing when it is shown again, and the page is usable.

  • A BreadcrumbItem link or button inside the AppShell mobile drawer now closes the drawer after it runs onClick, like the TopNavItem and SideNavItem rows beside it. Before, a crumb navigated and left the drawer open over the new page. A crumb marked isCurrent, which goes nowhere, leaves the drawer open. (#9465)

  • Button, IconButton: a tooltip that repeated the button's accessible name was also added as its description, so screen readers read the same words twice ("Close, button, Close"). Astryx's own close, pagination, copy and collapse buttons did this by default. Now a tooltip whose trimmed text equals the accessible name still shows, but adds no description, when Button can read that name: its aria-label, or its label when any icon or end content is a decorative Icon. A tooltip that says more, or a Button named another way (aria-labelledby, or text in its icon or end content), keeps the description.

  • A CheckboxList with an error status now makes every checkbox aria-invalid, so a screen reader announces the list as invalid as each checkbox takes focus, as Switch and the text inputs already do. The message still renders once, from the list.

  • After a gesture takes a touch, the page no longer sees that touch's late mousedown and mouseup. WebKit sends them a few milliseconds after a held tap's cancelled touchend, aimed at whatever is under the finger by then; they now go with the click.

  • Avatar, BreadcrumbItem, Button, Lightbox, SegmentedControlItem, Tab, Tokenizer: a slot whose value is 0 showed a stray "0" beside its slot, or, in SegmentedControlItem's and Tab's icons and Tab's end content, was dropped. That covers startIcon, icon, endContent, a Lightbox caption and selectedIcon. Now each slot follows the shared presence check. Empty values (null, false, '') render no slot, as an omitted one does, and 0 renders inside its slot as content. A Tab whose selectedIcon is 0 shows it while selected instead of falling back to icon. An Avatar whose status is 0 no longer shows a stray "0"; its status slot still renders only for a truthy value.

  • Pressing Enter in the typable date field of a DateInput or DateTimeInput (the pointer surface) now submits the surrounding form when nothing is typed, as in any text field. Typed text is still committed first, and that Enter does not submit. A disabled or busy field still does nothing on Enter.

  • DateRangeInput: with presets, the popover overflowed a phone-width screen. The calendar was cut off on the right, so the Saturday column and the end of a selected range were hidden, and on screens under about 364 px Next month was out of reach too. Now, when the presets and a one-month calendar do not fit side by side, the presets stack above the calendar, and the calendar and its navigation stay inside the popover. On a short screen the popover's content scrolls. Where the presets fit beside a one-month calendar, the layout does not change.

  • Dialog (and AlertDialog, CommandPalette): a dialog that unmounts while it is open, for example one rendered only while open ({isEditing && <Dialog isOpen …>}) or removed with the rest of a view, now returns focus to the control that opened it instead of dropping it to the page.

  • Opening a Drawer without its scrim from the keyboard no longer throws an InvalidStateError when its first control has a tooltip, such as a DrawerHeader close button. The tooltip now opens once the drawer is shown.

  • A toast shown while a modal Drawer is open now appears inside the drawer, above it, and can be pressed and reached with Tab, as it already does over a Dialog or a BottomSheet. Before, the toast stayed outside the drawer's modal dialog: it was inert there (a press on Undo did nothing, and Tab never reached it), and a wide drawer hid it completely. Toasts go back to the page as the drawer starts to close. A drawer without a scrim is unchanged.

  • A toast shown before a Drawer without its scrim (hasScrim={false}) opens now stays above the drawer, as it already does above a scrimless BottomSheet. Before, the drawer painted over it, so where the drawer covered the toast's corner its action could not be seen or pressed.

  • A data-mode DropdownMenu that opens as a bottom sheet from a renderTrigger now titles the sheet, and names its dialog, after the menu's aria-label, else the trigger's own name, as its popover does. It no longer reads "Menu" for every such sheet. (#9525)

  • A window blur during a pen's press, or during a press by a finger read from its pointer events, now ends it with nothing acting at the later lift, on every surface: a Switch no longer toggles at that pen's click. Where fingers come from pointer events, a second finger leaves both to the page's pinch even when the first rests on plain page. A disabled recognizer brings no blocking listener.

  • With Reduce Motion on, a layer that opens under a finger fades in over 200 ms on easeInOut, the motion foundation's Reduce Motion values, instead of the theme's fast duration and curve. Under a mouse it still appears at once.

  • A Link rendered as a button (with onClick and no href) lines up its wrapped text like the text around it, as an href Link does, instead of centring its second and later lines.

  • A disabled CheckboxList or RadioList now sets aria-disabled="true" on its group, so a screen reader announces the group itself as unavailable, not only each option, and the dimmed group label counts as the label of an inactive control.

  • A finger's tap that a DropdownMenu (or any menu on the press model) tracks now cancels that touch's touchend, on every device, so the browser sends no click and no compatibility mouse events for it. Before, a busy main thread could hold that click past the 400 ms click guard window. After a tap that drilled into a sub-menu, the late click picked the sub-menu row that had come under the finger and closed the menu. A mouse or pen release keeps the 400 ms window.

  • With Reduce Motion on (design:reduced-motion), the month arrows in the DateInput and DateTimeInput bottom-sheet calendars, Reset, and a keyboard move into another month no longer scroll the months: on a computer with a mouse or trackpad the month changes at once, and on a touch screen it changes through a short opacity dip. A second step during the dip replaces the first, and unmounting the calendar during the dip scrolls nothing.

  • Every Outline link is now in the normal Tab order, and Tab moves from link to link, as the Outline record says. Before, the outline was one Tab stop on the current heading, with arrow, Home and End keys moving between links, so a keyboard user who did not know those keys reached only one link. The arrow, Home and End keys no longer move focus between links. (#9001)

  • Popover and usePopover: in the anchored presentation, initial focus now lands within the tap or click that opens the popover, so on iOS a text or number field in it raises the on-screen keyboard at once. Focus that onShow moves inside the popover is no longer pulled back to the first control.

  • PowerSearch: Clear all keeps read-only filters. It removes only the filters the user can edit, the clear button shows only while an editable filter exists, Backspace on an empty input no longer removes a read-only filter, and Clear all announces "Editable filters removed" while a read-only filter remains. For callers, Clear all now calls onChange with the read-only filters and remove at the first removed index (0 when no filter is read-only) instead of [] at the last filter's index.

  • PowerSearch: in a read-only field (isReadOnly), Backspace on an empty input no longer removes the last filter. A read-only field now removes no filter, as its isReadOnly docs promise.

  • PowerSearch: in the popover presentation, a built-in filter token's button was named by its field and operator only ("Status: is") and gave no sign that it opens an editor. Two filters on one field sounded the same, and the visible value was missing from the name. Now the token is named by all its visible text ("Status: is Open"), has aria-haspopup="dialog" and aria-expanded, and opens an editor that is a dialog of the same name. Its remove button is "Remove Status: is Open". Token: aria-haspopup and aria-expanded now reach a clickable token's inner button, beside aria-labelledby and aria-describedby.

  • Under Reduce Motion on a touch screen, a step on a DateInput, TimeInput or DateTimeInput wheel, and a month step in the touch calendar, change under their cross-fade even on a busy page. Before, the change landed on a timer at the fade's middle, and a busy page could fire it after the fade had ended, so the rows or the month moved fully visible. Now the change lands when the fade-out ends, on the fade's own timeline, and the fade-in starts only after it, so it never shows at full opacity. The month's dip now eases each half, as the wheels' does.

  • A ResizeHandle whose resizable prop goes away in the middle of a drag now ends the drag as it does on unmount: it releases the page's resize cursor and text selection, and the region hears that its gesture is over.

  • A Selector's option list no longer fades in when Reduce Motion is on with a mouse or trackpad; it appears at once. On a touch screen it uses the shared Reduce Motion cross-fade.

  • In an open Selector, MultiSelector, CommandPalette, DateTimeInput time list or Chat trigger menu, a key that scrolls the list (End, Home, PageDown, type-to-select) keeps the highlight where the key put it, even when the mouse is resting over the list. Before, the row that scrolled under the still pointer took the highlight. A mouse that moves or presses still takes it.

  • Slider: every pointer drags a thumb by its travel, as UISlider does. A press on a thumb no longer jumps the value to the pointer: once the pointer has moved 10 px, the value follows its further travel along the track. A finger or a pen claims the drag only along the track, so a swipe across the slider scrolls the page; a mouse claims in any direction. On a touch screen each thumb takes a finger or a pen through a 48 px target, capped at half the gap to a range's other thumb, and the held thumb lifts. After a finger's flick the thumb coasts on UISlider's measured spring for about 0.6 s, onChange firing through the coast, and onChangeEnd reports the value once it settles; a slow drag, a mouse drag and a pen drag end at the release. A tap on the track sets the value when the finger lifts, and a mouse click where it lands; a right click and a macOS ctrl-click change nothing. Under reduced motion the thumb does not lift and a tap's value applies at once.

  • Toast: a toast raised while the window is in the background now starts with its auto-hide timer paused, so it can no longer disappear before the user returns to the tab.

  • A removable Token that its width cuts off now keeps its 16 by 16 remove button. The button used to shrink to 12 px wide, so its focus ring drew as an oval and its press target narrowed to 20 by 24 px. Only the label is cut now. (#9599)

  • Tooltip, HoverCard: a tap-opened tooltip or hover card whose trigger renders in another document, such as an iframe, now closes on a scroll that starts outside in that document, and on a tap outside there when the trigger takes no focus.

  • Typeahead: with focus entries on, an open list whose focus entries come back empty, or fail to load (for example after the query is cleared), now closes instead of staying open and empty. A typed search with no results still shows its message.

  • Typeahead: pressing Escape while editing the selected value now restores the value and moves focus to its token, instead of dropping focus to the page. With the list shown, the first Escape only hides the list.

  • useMediaQuery returns its server default where the window has no matchMedia, as in a test DOM, instead of throwing. Components that read it, such as Slider, now render in such a DOM; SegmentedControl, which reads it from this release, keeps rendering there.

  • A picker wheel that stops on a value outside the bounds now settles on the nearest value inside them. Before, it bounced back to the value it started from. This applies to the wheels in the TimeInput, DateTimeInput and DateInput bottom sheets. For example, with min="09:00", dragging the hour wheel from 10 to 7 settles on 9, as the iOS time picker does. A stop on a value inside the bounds is unchanged. Opening a sheet on a value outside the bounds commits nothing. When a bound changes a wheel's value while the sheet is open, as when the meridiem wheel turns past the maximum, that wheel turns onto the new value instead of jumping there. Under reduced motion, the wheel's own scrolls no longer glide. On a touch screen this travel, the step from an arrow key and a click on a row cross-fade, the rows landing while they are faded out; with a mouse or a trackpad they land at once, except the travel after a touch drag, which cross-fades on any screen.

Performance

  • Opening a Selector's list or moving its highlight re-renders only the options whose highlight or selection changes, not every option, so a long list opens sooner and arrow keys respond faster.

  • Opening a Selector with a long option list is faster: the list no longer restyles every option a second time on its first open to switch to its scrolling touch behavior.

Documentation

  • Hook docs for useOutlineFromMarkdown, so astryx hook useOutlineFromMarkdown and astryx search return it, and a useOutlineFromMarkdown — Docs Article example block: a Markdown article and an Outline built from the same string through the hook, with a button that adds a section and its linked entry.

    Also released in @astryxdesign/cli.

Other Changes

  • Internal: the touch presentations' animator carries a channel on from the screen when a rebase, a set or a retarget that starts now rebuilds it after its call's first frame came late and left the start unread. The channel leaves that call with a start of its own, dated from that frame, instead of starting its curve again; the call's other channels keep waiting for the browser's start. Not exported from the package entry point.

  • Internal: the touch presentations' animator reads a call whose first frame came late, and left its start unread, as started at that frame. A retarget or a read before the browser reports the start, of now or of a later time, continues near where the screen has it instead of from the call's first value. A rebase or set that rebuilds one channel's animation in that window reads that channel's first value until the frame that commits it, and the call's other channels keep reading from the first frame. The browser's start, once read, still decides. Not exported from the package entry point.

  • Internal: ChatMessage's avatar offset variable now has the private literal name --_chat-avatar-offset instead of a hashed name, so the published stylesheet no longer declares an internal variable that looks public. The avatar's offset is unchanged. Not exported from the package entry point. (#9602)

  • Internal: a mouse or pen drag that a gesture claims takes no new text selection and keeps the page's existing one, from the claim of whichever recognizer makes it (a swipe or a recognizer waiting on another's failure included), and a drag that starts on selectable text is left to the browser, which selects that text. Not exported from the package entry point.

  • Internal: a pan follows a trackpad's two-finger scroll where its owner allows it (allowedScrollTypes: ['continuous'], UIKit's allowedScrollTypesMask; none by default), along its own axis and after the scrollers under the pointer, and never a mouse wheel's notches, which scroll what is under the pointer; the screen-edge pan takes none; and a pinch takes a ctrl-wheel from a trackpad or a mouse (AST-094 FR43, DEC-24). A watcher pan never takes the wheel, and a wheel another handler already prevented stays the page's. Input the deltas cannot place, Shift+wheel included, reads as a mouse wheel; a trackpad scroll a pan follows keeps moving at the fingers' speed until their lift is read, ends there still moving, and the momentum never moves it. Not exported from the package entry point.

  • ResizeHandle's pointer drag, keys and double-click move into one internal module, with no behavior change.

  • Internal: when a main-thread stall delivers a late trackpad wheel and bunched wheels after it, a followed pan reads the fingers' speed over the late wheel's interval, so a flick no longer coasts short. The reading never passes the speed before the stall. Not exported from the package entry point.

  • Internal: a followed trackpad pan takes no speed from a wheel within 1.5 ms of the one before, so bunched wheels after a main-thread stall no longer carry it past the fingers' travel, at 60 to 500 Hz. Not exported from the package entry point.

  • Internal: the trackpad splitter reads a bunched wheel, one within 1.5 ms of the one before as a main-thread stall delivers it, as the steps it merged. During momentum a bunched wheel is not a jump, so momentum no longer restarts a followed pan, and the steps after it no longer read as a lift. Not exported from the package entry point.

  • Internal: a pager for touch presentations that pages like a UIKit paging scroll view. A horizontal pan moves the pages one to one and rubber-bands at the ends. The release picks the page with UIKit's rule and settles on UIKit's paging curve on the compositor, and a finger can catch it mid-flight. It takes every pointer: a mouse drags it as a finger does, and its pan follows a trackpad's horizontal scroll, at most one page per swipe. A mouse wheel's scroll stays the page's. Its motion values are internal constants. Not exported from the package entry point.

  • Internal: UIKit's paging values and math for touch presentations, measured on iOS 26.2: the thresholds that pick the page a release settles on, the settle that carries it there and setContentOffset(animated:). The settle and setContentOffset(animated:) replay the recorded frames to under half a pixel. The unused projection rule (selectPage and scroll.paging) is gone, so the measured thresholds are the one paging rule. Not exported from the package entry point.

  • Internal: UISwitch's values measured on iOS 26.2 (its geometry, the springs of the thumb's lift, settle, travel and drag, the track colour, its minimum lift time and its flip distance) join the UIKit constants table as internal constants, with the rule a switch's drag follows as a pure function: the finger flips the switch once it has travelled the track width minus the thumb width from where it landed, coming back past that point flips it back, and lifting the finger commits the side shown, or toggles when nothing flipped. Not exported from the package entry point, and no theme sets them. Switch's touch presentation plays them.

@astryxdesign/richtext

Fixes

  • RichTextEditorToolbar: Insert link with nothing selected did not insert a link at the caret. In an empty paragraph nothing was inserted, and with the caret inside text the whole text around it was linked, while the dialog closed as if it had worked. Now, with the caret outside a link, Insert link inserts the entered URL as link text at the caret; with a non-empty selection it links the selected text, and with the caret inside a link it updates that link, as before.

Performance

  • Typing in a RichTextEditor code block no longer re-tokenizes the whole block. In TypeScript, JavaScript, Python, and shell code, an edit inside one line re-tokenizes that line, plus at most the line above it, and replaces only the color ranges inside the text node it edited, so a keystroke in a 2,000-line block tokenizes as little code as one in a short block. Edits that open or close a string or comment across lines, and other languages, still re-tokenize the whole block. Colors are unchanged, except that a block whose text nodes are replaced by others with the same text is now recolored instead of left uncolored.

@astryxdesign/cli

New Components

  • astryx discover no longer lists InfoTip among the components @astryxdesign/lab contributes: InfoTip is a Core component now, described by astryx component InfoTip.

Performance

  • With TypeScript 5.3 or later, validateIntegration(), integrationComponentConflicts() and integrationCheck() from @astryxdesign/cli/api, and the commands that run them, reuse each TypeScript file a check parsed for later checks in the same process that parse it the same way, while the file is unchanged, instead of parsing it again for every check. Their results are unchanged.

Documentation

  • The usePressFeedback — Pressable Card example now shows a small card in real playing-card proportions, with corner indices, a full face and a patterned back, and a line under it that says what to try: press and hold to see the press, tap, click, Enter or Space to flip. Copying the example (astryx template, the docsite's Code tab and Install) still gives you only the hook on a Card (width={120}, padding={1}) with one <Text> placeholder: the hint line is left out, not replaced.

  • A new useCombobox — Assign To Field example block spreads the field, listbox and option props from useCombobox onto a TextInput and a list of Item rows: typing filters a list of teammates, ArrowUp and ArrowDown move the active option while focus stays in the input, Enter or a press picks one, and Escape closes the list. Copy it with astryx template useComboboxHookUsage <path>.

  • A new useGridFocus — Color Swatch Grid example block wires useGridFocus to a color swatch picker in rows of eight: the grid has one Tab stop, the arrow keys move focus cell to cell, Home and End jump within a row, Ctrl+Home and Ctrl+End jump to the corners. Each swatch is a button, so Enter or a click picks it. Copy it with astryx template useGridFocusHookUsage <path>.

  • A new useListFocus — Recent Files example block gives a list of buttons keyboard navigation from useListFocus: ArrowUp and ArrowDown move between rows, Home and End jump to the first and last row, focus wraps at the ends, and only one row is in the tab order. Copy it with astryx template useListFocusHookUsage <path>.

  • A new useOverflow — Editor Toolbar example block shows the hook on its own: eight toolbar actions sit in a card you can resize, a hidden copy of the row holds every action plus the More menu marked data-overflow-indicator, and the actions that do not fit move into the More menu with no flicker. Copy it with astryx template useOverflowHookUsage <path>.

@astryxdesign/build

New Features

  • withAstryx() builds Astryx from source under Turbopack instead of refusing to. It points each package's documented entry points at their source (Core, Lab, Charts and Rich Text), compiles that source with the settings the prebuilt stylesheets use, and keeps the app's own Turbopack rules off it. The new PostCSS plugin @astryxdesign/build/next/postcss replaces an @astryx; rule with each source-built package's prebuilt stylesheet, compiled from that source: the same rules and selectors, in the same order, inside @layer astryx-base. To set it up, list @astryxdesign/build/next/postcss in the app's PostCSS config and put one @astryx; rule in the app's global stylesheet (option cwd, the app root, defaults to the working directory). Under Turbopack, the webpack setup's @astryxdesign/build/postcss refuses to run beside withAstryx(), since its rules never match the classes Turbopack renders. In this source build, an installed Astryx package with a malformed package.json fails the build instead of being left out. The webpack setup is unchanged: it builds Core and Lab from source, and Rich Text and Charts keep their prebuilt stylesheets there.

Other Changes

  • The prebuilt stylesheet build and the Turbopack source build share one module walk, compile and layer block, so a source build prints the prebuilt rules by construction. Every prebuilt stylesheet keeps its bytes.

Contributors

Thanks to everyone who contributed to this release:

@cixzhang @duytbp @emilyhorsman @ernestt @HelloOjasMutreja @hskl18 @imdreamrunner @kyu-rong @maheshrijal @vjeux

Full Changelog: https://github.com/meta/astryx/compare/v0.7.6...v0.7.7