v0.6.2

playcanvas/enginev0.6.2Sep 15, 2026by cixzhang

Upgrading?

AI Summary

Astryx 0.6.2 adds opt-in math rendering for Markdown, exposes new theme targets for DialogHeader, DateRangeInput, Slider, and FileInput, and fixes CLI issues related to peer dependencies and theme name handling.

Key Highlights

  • Markdown now supports opt-in math rendering via `components.math`.
  • Exposed theme targets for DialogHeader gaps, DateRangeInput, Slider, and FileInput icon.
  • Added `--spinner-arc-fraction` CSS variable to Spinner for customization.
  • CLI fixes for peer dependency checking and theme name identifier generation.

New Features

  • Markdown math renderer (`InlineNodeWithMath`, `BlockNodeWithMath`).
  • Theme targets for `DialogHeader` (header gap, title/subtitle gap, close-icon size).
  • Theme target for `DateRangeInput`.
  • Theme target for `Slider`.
  • Theme target for `FileInput` upload icon.
  • `--spinner-arc-fraction` public CSS variable.

Full Release Notes

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

```bash
npx astryx upgrade --apply
```

## @astryxdesign/core

### New Features

- Markdown: add an opt-in math renderer (#6312)
  Supply `components.math` to parse `$…$` inline math and `$$…$$` display math. The renderer receives the delimiter-free expression as `value` and its placement as `display: 'inline' | 'block'`, so applications can connect their preferred math typesetter without preprocessing Markdown or accepting raw HTML.

  Math is off unless the renderer is present. Direct parser callers can opt in with `MathParseOptions` (`{math: true}`) and incremental callers create `IncrementalParseState<true>` via `createIncrementalState<true>()`. Those overloads return `InlineNodeWithMath` or `BlockNodeWithMath`; default, legacy-set, `math: false`, and `ParseOptions`- annotated calls retain the existing `InlineNode` and `BlockNode` unions, so exhaustive consumers do not gain a case unless they opt in. Existing Markdown parsing and rendering stay unchanged by default; code stays opaque, escaped and unmatched delimiters stay literal, and inline plugins skip math. Incremental parsing preserves full-parse results when display math is nested in ordinary or task lists and blockquotes, including quote-depth transitions, with LF or CRLF and with source ranges enabled.

- DialogHeader exposes theme targets for its header gap, title/subtitle gap, and close-icon size. (#6240)
- Expose DateRangeInput preset theming targets (#6223)
- Expose the Slider interactive control as a theme target (#6225)
- Expose FileInput's upload icon as a mode-aware theme target (#5417)
- Add a `--spinner-arc-fraction` public var to Spinner, so a theme can change how much of the ring the moving arc covers (defaults to 0.375, a 135deg sweep), the same way it already retheme diameter, stroke width, and color. (#5845)

### Fixes

- Adds the `@astryx.chatTypingIndicator.*` catalog keys so the lab ChatTypingIndicator can build its typing status from the translation runtime instead of English literals, joining names with `Intl.ListFormat` for the active locale. English output is unchanged. (#6220)
- Spinner: the default assistive label now comes from the translation catalog (`@astryx.spinner.loading`) instead of a literal `"Loading"` in component source, so a localized app translates the status. An explicit `aria-label` and a visible string label still take precedence, in that order. (#6217)

## @astryxdesign/cli

### New Features

- Add `muse` preset to `astryx init --agent` targeting `AGENTS.md` for Muse Code. (#6045)
- Build one keyed artifact trio for a selected theme family (#6268)

### Fixes

- doctor: range-check every peer against the project's own node_modules, so a peer that is only reachable from the ambient environment no longer reads as installed (#5327)
  `checkPeerDeps` resolved each peer with `require.resolve(name, {paths: [cwd]})`. Node folds `NODE_PATH` into that lookup regardless of `paths`, so a peer merely reachable from the ambient environment resolved, and doctor reported nothing while the project itself was missing it. It now walks the project's own `node_modules` and reads each `package.json` off disk, so a missing peer is reported and an installed one is checked against the declared range.

  Yarn Plug'n'Play projects have no `node_modules` for that walk to find, so the lookup asks the PnP runtime when the walk comes up empty. PnP resolves from the project's own dependency graph and ignores `NODE_PATH`, which keeps the answer project-local. A PnP project now gets its peers range-checked too — previously `require.resolve` could confirm a peer was present there but not read its version, because Core does not export `./package.json`.

- Component loader now reads default-export `.doc.mjs` files (the shape `integration add component` writes), fixing a crash where `component` and `search` could not load generated docs. Human `component` detail and list views now use the API-resolved import specifier instead of recomputing from core, so integration components report their package-authored import. `pack --check` now reports an error when a component doc cannot be loaded instead of silently approving. (#6291)
- Fix `theme build` emitting invalid JS identifiers for theme names containing hyphens or dots followed by digits. The output identifier is now derived deterministically from `theme.name` by camelCasing across `-` and `.` separators (underscores are preserved as valid identifier characters). Names like `chaos-07` correctly produce `chaos07Theme` instead of the unparseable `chaos-07Theme`. (#6289)
- Make staged writes portable across filesystems that reject hard links.
  The create-only publisher now falls back from `linkSync` to `copyFileSync` with `COPYFILE_EXCL` for `EPERM` and `EXDEV`, while preserving no-clobber, concurrent-creator safety, compare-and-swap replacements, symlink rejection, rollback, and temporary-file cleanup. (#6287)
- theme build: only treat a core the theme's own node_modules chain can reach as one a CommonJS dependency could reach, so an ambient-only core no longer fails the build with ERR_CORE_INCOMPATIBLE (#5327)
  `patchCommonJs` required `@astryxdesign/core` from the theme file to see whether it could wrap `defineTheme` for `.cjs` dependencies. `require` folds `NODE_PATH` in, and pnpm's isolated layout puts every package in `node_modules/.pnpm/node_modules`, so a core no dependency of the theme could reach answered that lookup. Wrapping it fails on a `require(esm)` namespace, and the reported coverage gap then rejected any theme whose lineage was unobserved. The lookup now walks the theme's own `node_modules` chain first, the same way `doctor` resolves peers.

## Contributors

Thanks to everyone who contributed to this release:

@athz @cixzhang @freddymeta @Han5991 @HelloOjasMutreja @josephfarina @ksying @Kyujenius @oliprovscode

**Full Changelog**: https://github.com/facebook/astryx/compare/v0.6.1...v0.6.2

Related Repositories