Astryx v0.6.0
Astryx 0.6.0 — all @astryxdesign/* packages ship at this version.
npx astryx upgrade --apply
-
Remove deprecated focus-direction overrides, the hooks-path
isImeKeyEventre-export, and Resizable pixel-bound aliases. Codemod: Runnpx astryx upgrade --applybefore updating to 0.6.0. It removes focus-hookisRtl, movesisImeKeyEventimports to@astryxdesign/core/utils, and renamesminSizePx/maxSizePxtominSize/maxSize. -
Stop emitting deprecated bare prop and state classes such as
.primary,.sm, and.checked. Components retain their stableastryx-*target classes and reflect visual props and runtime states through explicitdata-*attributes; generated runtime and built theme CSS now uses that same selector contract. Runastryx upgrade --applyto migrate safely identifiable selectors in.cssfiles when a known Astryx target and v0.5.4 value have one or more known meanings. For example:.astryx-button.primary→.astryx-button:is(.primary, [data-variant="primary"]).astryx-button.sm→.astryx-button:is(.sm, [data-size="sm"]).astryx-switch.checked→.astryx-switch:is(.checked, [data-checked="checked"])
The codemod parses CSS selector syntax and never rewrites declarations, comments, JavaScript/TypeScript strings, unqualified classes, or custom/unknown qualified classes. Each known value becomes a specificity-preserving
:is(...)union containing the original class arm plus every v0.5.4 reflected data-attribute arm. The class arm keeps consumer-suppliedclassNamematches working; the attribute arms match v0.6 props and states. You can narrow the union later when class provenance or prop-axis intent is known. Search for unqualified old value selectors such as.primaryor.smand migrate those manually only where Astryx usage is confirmed. Migrate selectors embedded in JavaScript or TypeScript manually with the same rules.Semantic
defineTheme({components})keys such asvariant:primaryandcheckeddo not change. If you prebuild a custom theme, rerunastryx theme build <theme-file>after upgrading and deploy the regenerated.css,.js,.d.ts, and optional.variants.d.tsartifacts together. A built theme is marked__built: true, so the runtime intentionally does not regenerate stale CSS.Exported theme helpers keep their return/container shapes but intentionally return different selector bytes:
themePropsreturns the stable target class (plus target-name compatibility aliases), without bare prop/state classes; its reflecteddata-*attributes are unchanged.parseStyleKeyreturns data-attribute selector suffixes instead of.value,.prop-N, or.statesuffixes.generateThemeRuleskeeps its array contract and ordering; non-base component selectors use reflected attributes.generateThemeRulesSplitkeeps{component, prose};componentselector bytes change andproseis unchanged.generateOnMediaCSSkeeps its scoped string contract; component selector bytes change.generateThemeCSSkeeps{prose, component}and the same layers/scopes;componentinherits the new selectors andproseis unchanged.
-
Restrict
Stepper'shorizontalOptions.minimumStepWidthto a pixel number and remove compact-layout implementation fields fromuseStepperContext. Replace CSS-length thresholds such as'7rem'with their intended pixel number. CallregisterStep(index, {getIsDisabled})instead of passing a disabled boolean; the options object is optional.StepperContextValuekeeps transition history and step registration, while step count, compact state, summary-portal coordination, and threshold measurement remain package-internal. -
Add ordered environmental adaptations to
defineThemeThemes can now opt into CSS-first token, theme-local token, and component changes for named viewport widths, primary-pointer precision, contrast preference, and motion preference:defineTheme({ name: 'acme', adaptations: { widthBreakpoints: {sm: 640, md: 768, lg: 1024, xl: 1280, '2xl': 1536}, rules: [ { when: {width: {from: 'lg', below: 'xl'}, pointer: 'coarse'}, value: {tokens: {'--size-element-md': '44px'}}, }, ], }, });
Condition fields are ANDed.
width.fromis inclusive,width.belowis exclusive, and rules cascade in declaration order so later matching writes win. Theme extension preserves the effective breakpoint map and inherited rule order; static builds retain the metadata needed for source-equivalent extension.AppShellnow acceptsxland2xlformobileNav.breakpointand resolves all five names through the nearest Theme. Mobile mode now uses the documented exclusive boundary (width < breakpoint), so an AppShell exactly at the named point renders the wider layout instead of the mobile layout.defineThemenow validates the token values authored inside an adaptation rule, rejecting non-string scalars and arrays with a length other than two instead of emitting them. Root and on-media token input keeps its existing acceptance unchanged, so themes that pass values through casts or spreads keep building. It also validates the combined portable and theme-local token graph for every reachable set of matching adaptation rules, rejecting cycles before CSS is emitted. Component writes in a rule use the same target, axis, value-domain, and extension validation as rootcomponents; a rule may not be the only place a custom value is enrolled, because generated type augmentation is unconditional.astryx theme buildtreats the adaptation generator as a core capability rather than a baseline requirement, so a theme with no adaptation intent still builds against an older installed@astryxdesign/coreand emits the same CSS as before. A theme that does carry adaptation intent — valid rules, a customwidthBreakpointsmap, or present-but-malformed adaptation metadata — fails against such a core before any output is written, withERR_CORE_INCOMPATIBLEnaming the missinggenerateAdaptationCSSexport. A complete default width map with no rules asks for nothing and still builds. Where an older core'sdefineThemedrops adaptations while resolving, the build records each rawdefineTheme()input and associates it with the theme it produced, so only the selected theme's lineage decides. An unobservable selected ancestor (including a CommonJS source package whose ESM core namespace cannot be wrapped) fails closed; an unused adaptive theme elsewhere in the import graph does not affect a plain build. The same capture preserves raw typography, color, radius, and motion axis metadata in old-core-built artifacts, allowing later current-core children to resolve partial adaptation axes exactly as if they extended the source theme.
- Banner exposes a
banner-frametheme target on the visible frame that owns whole-banner elevation and the elevated-card silhouette. The target reflectscontainerandelevation; existing Banner targets and default rendering are unchanged. CollapsibleandCollapsibleGroupacceptchevronPosition="start" | "end". The default remainsend, preserving the released trailing chevron.startmoves the disclosure arrow ahead of the label for tree/file-browser-style rows: it points inward toward content when collapsed, mirrors under RTL, and turns downward when expanded. Set the position onCollapsibleGroupwhen direct items should share it. An individualCollapsiblemay override the group, while a Collapsible nested inside an item's content starts a new presentation scope and keeps its own default.- Add a named font-weight override to Heading with precedence over its visual type and semantic-level defaults.
- Add an
autoCompleteprop to TextInput and TextArea, forwarded to the native control unchanged.
- ChatComposerInput: drop
aria-multilineonce triggers make the editable a comboboxaria-multilinewas hardcoded on the contenteditable element whileuseTriggerMenuowns its role, so configuringtriggersswitched the role tocombobox— which ARIA 1.2 does not listaria-multilineunder — and axe flaggedaria-allowed-attr(critical) on the 8 ChatComposerInput trigger stories and the 2 ChatLayout stories that render one. Moves the attribute into the hook'sariaProps, where the role and the attributes whose validity depends on it are decided together. - CheckboxListItem: the visible
descriptionis now the checkbox's accessible description, so the browser computes a distinct description instead of none. Item ids the description element it already renders and publishes that id to the content it renders in a slot, which keeps a plain string description's automatic single-line truncation. CheckboxInput now merges a consumer-suppliedaria-describedbywith its own description, status, and disabled-reason ids rather than replacing it. No public API changes. - CheckboxListItem: a ReactNode
labelnow names the checkbox from its visible text througharia-labelledby, the way RadioListItem already does, instead of falling back to the generic name "Checkbox".aria-labelstill replaces that name; a rich label with no text at all needs it, as it does for RadioListItem. The dev-time warning that asked foraria-labelon every rich label is gone. - Prevented removed Resizable bounds from being silently ignored and kept ambiguous spread migrations behavior-preserving (#6124)
- Keep hover from auto-scrolling open option lists (#6077) In a scrollable listbox whose highlight follows the pointer, scrolling the highlighted option into view moved the next option under the stationary pointer, whose mouseenter re-highlighted and scrolled again — an endless loop with no user input. This was already fixed for DropdownMenu and Chat; it now covers the remaining combobox-style paths through a shared highlight owner: Selector, MultiSelector, Typeahead, DateTimeInput, and CommandPalette hover highlights move only the highlight, while keyboard navigation still scrolls the highlighted option into view.
- Slider keeps its focus ring hidden for modifier-only key presses after a pointer drag while preserving keyboard navigation (#5469)
- Layout: keep content scrollbars at the content area's outer edge when
contentWidthis set. Without panels,LayoutContentspans the available Layout width and aligns its children tocontentWidthinternally. With exactly one panel, the panel stays aligned to thecontentWidthframe while content extends across the opposite open area. A two-panel layout keeps the complete composition constrained. - Popover: apply same-gesture reopen protection through every opening path, focus genuine caller content regardless of activation modality, and keep the generated fallback close control hidden until keyboard users reach it.
- SideNavItem: a consumer-provided
aria-labelno longer gets overwritten by the collapsed-rail fallback, in both the icon-only and popover-trigger paths.
-
Add ordered environmental adaptations to
defineThemeThemes can now opt into CSS-first token, theme-local token, and component changes for named viewport widths, primary-pointer precision, contrast preference, and motion preference:defineTheme({ name: 'acme', adaptations: { widthBreakpoints: {sm: 640, md: 768, lg: 1024, xl: 1280, '2xl': 1536}, rules: [ { when: {width: {from: 'lg', below: 'xl'}, pointer: 'coarse'}, value: {tokens: {'--size-element-md': '44px'}}, }, ], }, });
Condition fields are ANDed.
width.fromis inclusive,width.belowis exclusive, and rules cascade in declaration order so later matching writes win. Theme extension preserves the effective breakpoint map and inherited rule order; static builds retain the metadata needed for source-equivalent extension.AppShellnow acceptsxland2xlformobileNav.breakpointand resolves all five names through the nearest Theme. Mobile mode now uses the documented exclusive boundary (width < breakpoint), so an AppShell exactly at the named point renders the wider layout instead of the mobile layout.defineThemenow validates the token values authored inside an adaptation rule, rejecting non-string scalars and arrays with a length other than two instead of emitting them. Root and on-media token input keeps its existing acceptance unchanged, so themes that pass values through casts or spreads keep building. It also validates the combined portable and theme-local token graph for every reachable set of matching adaptation rules, rejecting cycles before CSS is emitted. Component writes in a rule use the same target, axis, value-domain, and extension validation as rootcomponents; a rule may not be the only place a custom value is enrolled, because generated type augmentation is unconditional.astryx theme buildtreats the adaptation generator as a core capability rather than a baseline requirement, so a theme with no adaptation intent still builds against an older installed@astryxdesign/coreand emits the same CSS as before. A theme that does carry adaptation intent — valid rules, a customwidthBreakpointsmap, or present-but-malformed adaptation metadata — fails against such a core before any output is written, withERR_CORE_INCOMPATIBLEnaming the missinggenerateAdaptationCSSexport. A complete default width map with no rules asks for nothing and still builds. Where an older core'sdefineThemedrops adaptations while resolving, the build records each rawdefineTheme()input and associates it with the theme it produced, so only the selected theme's lineage decides. An unobservable selected ancestor (including a CommonJS source package whose ESM core namespace cannot be wrapped) fails closed; an unused adaptive theme elsewhere in the import graph does not affect a plain build. The same capture preserves raw typography, color, radius, and motion axis metadata in old-core-built artifacts, allowing later current-core children to resolve partial adaptation axes exactly as if they extended the source theme.
- Let integration manifests add managed agent guidance
- Add an authoring-time OKLCH palette generator with a pure API, terminal and HTML previews, typed palette output, custom stops, deterministic receipts, and overwrite protection. [feat] Expose exact solid black and white values as
neutralPalettes.blackandneutralPalettes.whitefor use in semantic theme tokens. - Every command now reports what it returned in its debug logs, and a new command cannot skip it. A command's action returns a
CommandResult— either{kind: 'results', count, resultKind, ...}or{kind: 'none'}for the commands whose work is an effect (build, init, upgrade, doctor). The CommandDoc converter records it centrally, soresultCount,emptyResult,resultKind, anddirectMatchare now populated forcomponent,docs,hook,template,theme list/add/targets,discover,blog,swizzle --list,upgrade --list,layout grammar, andmanifest, not justsearchandbuild.resultKindgainstheme,integration,migration,command, andnone; a null now means the run never reached an answer rather than "this command has nothing to say". That is a change of meaning on an existing field, so recorded runs are nowschemaVersion: 3— a consumer that counted nulls as "commands with nothing to report" should branch on the version before mixing old rows with new ones. - Add
doctor integrationchecks for structural validation and Core template, component, and doc overlaps (#6173). - Add an experimental shadcn Registry compatibility guide and doc-derived registry identity metadata. It explains the package boundary, stable organized paths, copied composition model, upgrade behavior, and when to use the richer Astryx CLI.
- Add
astryx upgradetransforms for the Core 0.6 deprecated-API removals: focus direction overrides, the hooks-path IME helper import, and Resizable pixel-bound aliases.
- Prevented removed Resizable bounds from being silently ignored and kept ambiguous spread migrations behavior-preserving (#6124)
- Add a conservative
astryx upgrade --applymigration for the Core bare selector-class removal. The transform parses.cssselector syntax, rewrites exact v0.5.4 target/value pairs to behavior-preserving old-class/data-attribute unions, covers unbounded values that v0.5.4 emitted, and leaves unknown consumer classes unchanged. - Preserve
@pathagent doc imports and remove previously duplicated managed blocks (#6164) - Refresh the Collapsible block templates with complete, current examples for single, multiple, controlled, divided, standalone, and grouped usage. The controlled step example keeps one valid step open so its progress label and Previous/Next actions never enter an invalid “Step 0” state.
- Report the fixture path when a template demo asset has an unsupported format (#6039)
- Align Doctor help and README examples with the shipped command tree and output format (#6197).
- Clarify how to build themes with imported icon registries, including the current omission of inline registries and the separate registry compilation step. The theme guide distinguishes a missing compiled registry from an extensionless source import: the former breaks both loading and bundling, while the latter can resolve in a bundler when the source remains beside the generated module. English, dense, and Chinese guidance now explains how output paths and
--icons-specifieraffect resolution.
withAstryx()refuses a Turbopack config instead of building an unstyled app. Every alias the helper installs lives innextConfig.webpack, which Turbopack never calls, so the app resolved@astryxdesign/*to dist while PostCSS compiled the library from source — disjoint class names, an exit code of 0, and an unstyled page. It now throws, naming both ways out:--webpack, or drop the helper and consume the pre-built package. Also warns when the merged alias map claims none of the packages, which reaches the same unstyled state by another route. (#6109)
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
- Add an authoring-time OKLCH palette generator with a pure API, terminal and HTML previews, typed palette output, custom stops, deterministic receipts, and overwrite protection. [feat] Expose exact solid black and white values as
neutralPalettes.blackandneutralPalettes.whitefor use in semantic theme tokens.
- Align Neutral light-mode foreground colors to darker palette stops.
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
- Requires
@astryxdesign/core@0.6.0as part of the coordinated stable release. Upgrade Core and this theme together.
Thanks to everyone who contributed to this release:
@cixzhang @ernestt @faga295 @freddymeta @Hashim1999164 @HelloOjasMutreja @imdreamrunner @jiunshinn @joaodotwork @josephfarina @kentonquatman @Kyujenius @rubyycheung
Full Changelog: https://github.com/facebook/astryx/compare/v0.5.4...v0.6.0
@formatjs/editor: 1.4.0
- feat(@formatjs/editor): add browser tests and shared visual modules by @longlho in https://github.com/formatjs/formatjs/pull/7323
- feat(@formatjs/editor): add editor UI with design-system context by @longlho in https://github.com/formatjs/formatjs/pull/7329
Full Changelog: https://github.com/formatjs/formatjs/compare/@formatjs/editor@1.3.0...@formatjs/editor@1.4.0
6.0.2
- Fix cross-origin XSS through the postMessage API by validating iframe preview URLs
- Fix Markdown attributes targeting the last list item instead of the whole list when separated by a blank line #3931
- Prevent offscreen slides from receiving keyboard focus #1587
- Fix pinch-to-zoom gestures incorrectly triggering slide changes
- Improve slide layout and scroll view performance
- Fix slides repeatedly loading and unloading while scrolling
- Scale navigation controls, progress bars and media buttons for mobile viewports
- Round slide scale to two decimal places
- Update dependencies to address security vulnerabilities. Building and developing reveal.js now requires Node.js 22.12 or later
Full Changelog: https://github.com/hakimel/reveal.js/compare/6.0.1...6.0.2
quasar-v2.32.0
[!IMPORTANT] Behavior changes worth checking before you upgrade:
- QImg now renders its
<img>into the SSR/SSG HTML whenever the box shape is known (ratio,initial-ratioorheightset), instead of waiting for hydration. The markup a crawler or a no-JS client sees changes accordingly. Images with none of the three keep deferring to the client, unless you opt in with the newssr-prerenderprop.- The
.q-responsive__fillerelement no longer exists, and neither does QImg's filler node: the ratio now sits on the component root through CSSaspect-ratio. A QVideo with an explicit width resolves its ratio against that width instead of the parent's, and a QResponsive inside a height-clamped parent keeps its ratio by narrowing rather than squishing its content (Chromium and Firefox; WebKit keeps the previous full-width box).- QExpansionItem and QTree no longer render a QSlideTransition around their content; they drive the slide on the content element themselves, so the two extra component instances per item (per tree node) are gone from the tree. Their
durationprop is now a realNumberprop on the component itself rather than a passthrough to the child.- On Chromium, QSlideTransition, QExpansionItem, QTree and the vertical QStep no longer write inline
height/transitionstyles while sliding: the slide runs as a Web Animation over acalc-size(auto, size)keyframe. Onlyoverflow-yis written during the slide. Firefox and Safari keep the previous measuring CSS transition unchanged.- QInput autogrow textareas are sized by the browser through CSS
field-sizing: contentwhere it is supported (Chromium 123+, Safari 26+), so no inlineheight/overflowstyles appear on the textarea any more and amax-heightscrolls natively. Older engines keep the JS measuring fallback.- QParallax registers no scroll or resize listener and no IntersectionObserver where it can ride a view timeline (currently everything but Firefox). The
scrollevent and thecontentslot scope still work, but they are what forces the JS tracking back on, so use the slot only where you need its scope.
- feat(QImg): render the image in the SSR HTML; new prop ->
ssr-prerender-> until now QImg only set the image source once the client had mounted, so under SSR/SSG the browser started fetching it after the JS bundle had downloaded and the app had hydrated: the preload scanner never saw it, crawlers and no-JS clients got an empty box, and any hero image behind QImg was a late LCP by construction. The server and the pre-hydration client now render the<img>themselves, visible from the first paint like a native image, with the placeholder underneath; on mount the component reconciles against the element it finds instead of trusting load events, so an image that finished before hydration still goes through the regular load (or error) path. Only images whose box shape is known (ratio,initial-ratioorheight) are server-rendered by default, since otherwise the box would visibly snap from the default ratio to the natural one at hydration; the newssr-prerenderBoolean prop opts the rest in - feat(QDrawer):
panevent with the stage of the swipe gestures -> the swipe-to-open and swipe-to-close gestures ran silently: an app could only learn that the drawer had opened or closed after the fact, through the model and theshow/hideevents, never that a swipe was in progress, so content mounted on open only came in once the drawer had already been dragged fully into view and the swipe itself showed an empty panel. QDrawer now emitspanwith the gesturetype('open'or'close') and itsstage:'start'once the pan is detected,'end'when it crossed the threshold andshow()/hide()ran,'cancel'when the finger let go short of it and the drawer sprang back - feat(QParallax):
refresh()method -> everything the component settles at mount (the scrolling container and the way the media is moved along it, the media size, the position) was only re-checked on the events it listens to, so an ancestor changing itsoverflow, a media swapped without a load event or ascroll-targetthat only appears later left it stale with no way to tell it so.refresh()re-runs all three
- perf(QParallax): the media moves on a view timeline where the browser has one -> the media now rides an
Element.animate()on aViewTimelineof the component root wherever the API exists and nothing scrollable sits between the root and its scroll target. The browser then moves it on its own thread, in step with the scroll whatever the main thread is doing, where the JS tracking wrote its transform a frame behind (one scroll step off in every other compositor frame) and stalled together with the main thread; the keyframes carry the exact numbers the JS tracking used, so the movement itself is unchanged. On that path the component registers no scroll or resize listener and no IntersectionObserver at all, the tracking being created only where thescrollevent or thecontentslot needs the percentage, and there it reads the timeline's own progress instead of measuring. Firefox, and any layout the timeline cannot express (anoverflow: hiddenwrapper, ascroll-targetthat is not the nearest scroll container), keep the JS tracking, itself now measuring once per frame instead of once per scroll event. The media is also no longer left hidden until the first measurement, and a media without a natural size yet no longer measures adisplay: nonebox - perf(QSlideTransition): slide on a Web Animation where
calc-size()is supported -> the height slide (so QExpansionItem, QTree and the vertical QStep) measured the content on every toggle, onescrollHeightread on show and two on hide, each forcing a layout: toggling N nodes in one tick (QTree expand/collapse all, filtering) forced N layouts on show and 2N on hide. Where the engine sizes acalc-size(auto, size)keyframe at layout (Chromium 129+) the slide is now anElement.animate()between 0 and that keyframe: no measurement, no forced layout, the height tracked live while sliding, and an interrupted slide of a kept element played backwards. Engines withoutcalc-size()keep the measuring CSS transition, untouched. Chromium 153 headless, 200 boxes toggled in one tick: forced layouts on show 219 -> 20 and on hide 418 -> 19, layout time 13.7ms -> 8.4ms and 22.2ms -> 6.3ms - perf(QExpansionItem/QTree): slide the content directly, without QSlideTransition -> both components own their content element and its visibility, so the QSlideTransition + Transition pair per item (two component instances, per tree node) only relayed the slide hooks to a
v-show. They now call the slide engine on the element themselves. Chromium 153 headless, a QTree with 780 nodes (155 parents) mounted expanded, median of 12 mounts: 43.1ms -> 32.3ms - perf(QInput): size autogrow textareas with CSS
field-sizingwhere supported -> autogrow textareas now getfield-sizing: contentand skip the JS measuring routine entirely on browsers that implement the property: no rAF layout thrash per keystroke, no inline height/overflow writes, noscrollTopjuggling, and the browser handles amax-heightwith native scrolling. Browsers below the property's floor (Chromium before 123, Safari before 26) keep the routine, which also coalesces to one measurement per frame now (a keystroke used to schedule two) and cancels a pending frame when autogrow turns off or the component unmounts. Height parity between the two paths was verified in Chromium, Firefox and WebKit across plain, labeled, outlined, filled, dense, max-height and custom font-size cases - refactor(ui): size QImg, QResponsive and QVideo ratio boxes with CSS
aspect-ratio-> thepadding-bottompercentage hack needed a dedicated filler element in QImg and QResponsive (plus a width-inheriting wrapper in the latter) and a zero-height root in QVideo.aspect-ratiois under the Baseline floor, so the ratio now sits on the root element itself and those nodes are gone: one element fewer per QImg, two fewer per QResponsive. See the note at the top - perf(use-position-engine): resolve the CSS anchor verdict once at import -> a QMenu or QTooltip setup now reads a boolean constant instead of calling into a cached support probe
Quasar Framework is an open-source MIT-licensed project made possible due to the generous contributions by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:
v0.5.0-rc.0
First release candidate for the 0.5.0 minor. This is an opt-in prerelease published to npm next; latest remains on the stable release.
npm install vgpu@next
All seven public packages are versioned together at 0.5.0-rc.0.
- Explicit, unified texture creation:
kind, spatialsize, arraylayers, and nonemptyusage, with immutable creation metadata. - Texture readback supports explicit mip selection, mip-relative regions, and every selected layer or slice, with early allocation and usage validation.
- Safer texture replacement and resource lifetime handling, including stale bundle detection and separate compute/draw cache ownership.
- Linux Node rendering defaults to Vulkan, avoiding Dawn's restricted-mip-view/storage-write defect on OpenGL. macOS, Windows, and browser defaults are unchanged.
- Atmosphere & Clouds example with temporally accumulated haze, filtered near cloud shadows, and smoothed scene controls.
This pre-1.0 minor includes breaking API changes: Texture.resize() and Target/Surface read delegates are removed. Replace texture allocations explicitly, and read from a selected attachment with texture.read({ mipLevel: 0, region: "all" }) or readFloats(options).
See the texture API migration guide for before/after examples.
Linux installations need a usable Vulkan driver or an installed portable CPU renderer (npx vgpu install-software-renderer). Auto mode does not silently fall back to OpenGL or download drivers. Explicit OpenGL overrides remain available with the documented upstream limitation.
Please validate texture creation/replacement, cropped and layered readback, and Linux rendering in your applications before stable promotion.