2 hours ago
astryx

v0.4.3

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

npx astryx upgrade --apply

@astryxdesign/core

New Features

  • New string utilities: characterCount, firstCharacter, and truncateCharacters — replacements for .length, .charAt(0), and slice-based truncation that measure and cut user-visible strings by whole characters, so an emoji, flag, or accented letter counts as one and never gets split. Built on Intl.Segmenter with a code-point fallback.
  • ComplexSelector: support ghost toolbar triggers, leading icons, popup alignment, and an imperative handleRef (open/close/toggle/isOpen) for programmatic control.
  • useContainerReveal: two ways to control the reveal without reaching into the hook's private custom properties. getContainerProps({hoverDelay}) gates the reveal on pointer dwell — the hover-intent idea Tooltip and HoverCard already have as delay — so a cursor sweeping down a list no longer lights up every row it grazes, and getContainerProps({forceState}) pins the container's trigger state when something else owns the interaction (a scroll, a drag, an open row menu). Per element, getContentRevealProps({forceVisibility}) pins how one child looks regardless of its container. Still CSS-only: no hover state in React, no re-render. Keyboard and touch are untouched — focus always reveals, forceState: 'inactive' and forceVisibility: 'hidden' both yield to :focus-within.

Fixes

  • Banner: a dismissed banner no longer drops focus, a custom status no longer loses its ARIA role, and the info banner paints again under the neutral theme. Dismissing unmounted the focused dismiss button, so focus landed on <body> and a keyboard user lost their place in the page. Banner now records where focus entered from and returns it there, the same handoff ToastViewport makes for a dismissed toast. Measured in Chromium: document.activeElement was BODY, and is now the control the user tabbed in from.

    BannerStatusMap is documented as augmentable, but all four status lookups were closed Record<BannerStatus, ...> maps. Adding the augmentation the docs show produced four TypeScript errors inside Banner.tsx itself, which a consumer cannot fix, and at runtime an unknown status resolved to undefined for its icon, its background and its ARIA role, so the banner stopped being a live region at all. The lookups are partial now: an unrecognized status renders with no status fill, no default glyph and role="status".

    A theme could not reach the banner's radius. --_banner-radius was declared in the doc file and in derivedVarRegistry.ts, but no rule read it, so a theme's borderRadius on the banner target expanded into a variable nothing consumed. The four card-silhouette radii read it now, falling back to --radius-container.

    Under @astryxdesign/theme-neutral the info banner had no background at all, light or dark: the override set background-color directly and forced --color-accent-muted to transparent, and a plain CSS property written by a theme lands in @layer astryx-theme, which StyleX's @layer priority4 outranks. Info now goes through --color-accent-muted like the other three statuses and like the stone theme already did.

    Also in this change: children={false} (the ordinary {cond && <ul/>} idiom) no longer produces an expand toggle that opens an empty box, and description="" no longer leaves an empty 20px row, both via isRenderable; a long unbroken word in the title or description no longer forces the page into horizontal scrolling at a 320px viewport, measured at document.scrollWidth 529px before; and the content area's bottom border uses logical border-block-end alongside its inline siblings.

  • Count and cut text the way people read it: the TextArea character counter (and its over-limit state and screen-reader announcements) counts user-perceived characters — an emoji is 1, not 2; PowerSearch token truncation no longer cuts an emoji or accented letter in half; Table's auto-generated headers capitalize astral-plane letters correctly; Avatar's initials now use the shared character utilities.

  • ComplexSelector: honor the sm, md, and lg element-height tokens exactly.

  • TreeList's variant axis is themeable, and a new guard keeps every extensible axis honest. TreeListVariantMap invites theme packages to add variants — its own JSDoc shows the module augmentation — but themeProps('tree-list', {density}) never passed variant, so a custom variant type-checked, rendered, and produced no selector to style. It is passed now, and documented in the target's visualProps so astryx theme build stops calling it an unknown prop. packages/core/src/theme/extensibleAxes.test.ts is the third theming-drift guard, beside the ones covering targets and vars/derived. Those two check what a component renders against what it documents; neither looked at the open prop unions, which is why this went unnoticed. For every *Map that types a component prop, it now asserts the three places that have to agree: the interface is declared in the index a consumer augments (a re-export is invisible to both module augmentation and the CLI), the prop is reflected through themeProps, and it is documented as a visual prop. It reads the TypeScript AST rather than the type checker, and holds the map's OWNER accountable — a component forwarding actionVariant or statusVariant to the component that owns the map is not separately responsible for it.

    Registry maps that widen a set of NAMES rather than a visual prop (IndicatorMap, IndicatorFamilyMap) are out of scope by construction, not by allowlist: the guard only considers maps whose alias types a prop on a *Props interface.

  • Security: reject javascript:, vbscript: and data:text/html URLs in the Markdown parser, so untrusted markdown can no longer produce an executable link href or image src; and fix escapeRegExp in ChatTokenizedText, whose character class closed early and left ] and \ unescaped, so token values containing them were injected raw into a RegExp

  • extends now reaches the CSS. A theme that extended another built a stylesheet holding only the declarations it stated itself: the base's tokens, component overrides and surface rules were all absent, and because each theme is @scoped to its own data-astryx-theme value, loading the base's stylesheet alongside could not fill the gap either. Every consumer of an inheritance chain silently got stock geometry, elevation and type with a new palette painted over it (#5067). Nothing warned; the loss only showed up by diffing two generated stylesheets token by token. The cause was theme build shadowing its own inputs. It writes <name>.js next to <name>.ts, and the loader resolved a plain ./<name> specifier to that generated artifact before the source — so the second build of a family read the artifact, which carries no components and exports <name>Theme rather than whatever the source exports. A named import that missed became extends: undefined, and defineTheme treated an absent base as no base at all. The loader now resolves source extensions first, which is also the resolution the author's TypeScript sees, so the CSS a build emits matches the theme that type-checked.

    Three things behind it are fixed too, so the failure cannot come back by another route. defineTheme throws when extends is present but is not a theme, naming the likely cause, instead of inheriting nothing — the one behavior change here, and it turns a silent stylesheet into a build error. A theme's onDark/onLight surfaces and its __inputTokens are now inherited like its tokens and components were, so a child no longer reverts its base's inverted-surface customizations to the defaults or loses its [light, dark] tuples. And a built theme module now carries the resolved components and surfaces alongside its tokens, so extending one — the ./built subpath every shipped theme exposes — is no longer lossy. theme build also stopped hand-picking fields when it re-resolves a plain object theme file, which dropped extends, color and syntax on the way in.

    An extended theme is flat: everything it inherits is resolved into its own output, and its stylesheet stands alone. Measured on a 14-theme family (one base, 13 palettes extending it): each palette went from 25 custom properties and no component rules to the base's full 175 and 70, with its own colours still winning.

@astryxdesign/cli

Fixes

  • The unloaded-font advisory is a notice, not a warning. A theme file cannot load a font — Astryx sets --font-family-* and loading is the app's job — so #5045's advisory fires on any theme naming a webfont, including a perfectly correct one. As a warning that made a clean build read as defective, and it put the shipped template permanently in violation of its own "compiles with no warnings" guard (#5079 had to allowlist the template's two font names in that assertion). The theme.build receipt now separates the two: warnings are defects the author should fix, notices are advisories about a correct theme. The font advisory moves to notices and to stdout with the rest of the build's progress; stderr stays for defects. The template guard is back to warnings being empty, and no longer needs to know which fonts the template names.

    Programmatic callers reading data.warnings for font advisories should read data.notices; the message text is unchanged.

  • extends now reaches the CSS. A theme that extended another built a stylesheet holding only the declarations it stated itself: the base's tokens, component overrides and surface rules were all absent, and because each theme is @scoped to its own data-astryx-theme value, loading the base's stylesheet alongside could not fill the gap either. Every consumer of an inheritance chain silently got stock geometry, elevation and type with a new palette painted over it (#5067). Nothing warned; the loss only showed up by diffing two generated stylesheets token by token. The cause was theme build shadowing its own inputs. It writes <name>.js next to <name>.ts, and the loader resolved a plain ./<name> specifier to that generated artifact before the source — so the second build of a family read the artifact, which carries no components and exports <name>Theme rather than whatever the source exports. A named import that missed became extends: undefined, and defineTheme treated an absent base as no base at all. The loader now resolves source extensions first, which is also the resolution the author's TypeScript sees, so the CSS a build emits matches the theme that type-checked.

    Three things behind it are fixed too, so the failure cannot come back by another route. defineTheme throws when extends is present but is not a theme, naming the likely cause, instead of inheriting nothing — the one behavior change here, and it turns a silent stylesheet into a build error. A theme's onDark/onLight surfaces and its __inputTokens are now inherited like its tokens and components were, so a child no longer reverts its base's inverted-surface customizations to the defaults or loses its [light, dark] tuples. And a built theme module now carries the resolved components and surfaces alongside its tokens, so extending one — the ./built subpath every shipped theme exposes — is no longer lossy. theme build also stopped hand-picking fields when it re-resolves a plain object theme file, which dropped extends, color and syntax on the way in.

    An extended theme is flat: everything it inherits is resolved into its own output, and its stylesheet stands alone. Measured on a 14-theme family (one base, 13 palettes extending it): each palette went from 25 custom properties and no component rules to the base's full 175 and 70, with its own colours still winning.

@astryxdesign/theme-butter

Fixes

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

@astryxdesign/theme-chocolate

Fixes

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

@astryxdesign/theme-gothic

Fixes

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

@astryxdesign/theme-matcha

Fixes

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

@astryxdesign/theme-neutral

Fixes

  • Banner: a dismissed banner no longer drops focus, a custom status no longer loses its ARIA role, and the info banner paints again under the neutral theme. Dismissing unmounted the focused dismiss button, so focus landed on <body> and a keyboard user lost their place in the page. Banner now records where focus entered from and returns it there, the same handoff ToastViewport makes for a dismissed toast. Measured in Chromium: document.activeElement was BODY, and is now the control the user tabbed in from.

    BannerStatusMap is documented as augmentable, but all four status lookups were closed Record<BannerStatus, ...> maps. Adding the augmentation the docs show produced four TypeScript errors inside Banner.tsx itself, which a consumer cannot fix, and at runtime an unknown status resolved to undefined for its icon, its background and its ARIA role, so the banner stopped being a live region at all. The lookups are partial now: an unrecognized status renders with no status fill, no default glyph and role="status".

    A theme could not reach the banner's radius. --_banner-radius was declared in the doc file and in derivedVarRegistry.ts, but no rule read it, so a theme's borderRadius on the banner target expanded into a variable nothing consumed. The four card-silhouette radii read it now, falling back to --radius-container.

    Under @astryxdesign/theme-neutral the info banner had no background at all, light or dark: the override set background-color directly and forced --color-accent-muted to transparent, and a plain CSS property written by a theme lands in @layer astryx-theme, which StyleX's @layer priority4 outranks. Info now goes through --color-accent-muted like the other three statuses and like the stone theme already did.

    Also in this change: children={false} (the ordinary {cond && <ul/>} idiom) no longer produces an expand toggle that opens an empty box, and description="" no longer leaves an empty 20px row, both via isRenderable; a long unbroken word in the title or description no longer forces the page into horizontal scrolling at a 320px viewport, measured at document.scrollWidth 529px before; and the content area's bottom border uses logical border-block-end alongside its inline siblings.

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

@astryxdesign/theme-stone

Fixes

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

@astryxdesign/theme-y2k

Fixes

  • The /built entry now loads under Node ESM and externalized SSR (Vite --ssr, Remix / React Router v7): it imports ./icons.mjs instead of the extensionless ./icons Node cannot resolve.

Contributors

Thanks to everyone who contributed to this release:

@AKnassa @cixzhang @ernestt @Sunil56224972

Full Changelog: https://github.com/facebook/astryx/compare/v0.4.2...v0.4.3

2 hours ago
apexcharts.js

💎 Version 6.9.0

A feature release, and the largest in a while. Two ideas run through most of it.

The first: a chart should be able to take the measurements you actually have. Three types now accept raw observations and do the statistics themselves, and rowSeries() hands the individual rows back so a mark can be opened into the data behind it.

The second: one chart type can become another, in place. The cross-type morph engine stops crossfading and starts conserving the ink, so a bar visibly comes apart into the dots it was counting, and every pairing between the mark families is now offered rather than only the ones that had been driven.

Alongside those: nested treemaps, drilldown for line and area plus async levels that survive a real backend, a pluggable layout seam for the unit chart, and spring motion where a fixed tween used to stutter.

One change worth knowing before you upgrade: ApexCharts is no longer dependency-free. It now requires apex-commons at runtime (see Internal). npm resolves it for you and the browser bundles inline it, so no action is needed, but it is a change in the package's shape.

✨ New

chart.type: 'histogram', a chart that takes a sample

Every other type here wants values that were already aggregated. A histogram is the one that does the aggregating: the series carries raw observations, one number per event, and the chart chooses the bin width and counts them.

chart: { type: 'histogram' },
series: [{ name: 'Latency', data: [102, 87, 143, 91, ...] }]

It renders through the bar pathway, like funnel, pyramid, gauge and waffle, so bins are drawn by code that already handles stacking, zoom, export and animation.

plotOptions.histogram.bins takes a rule ('auto' | 'fd' | 'sturges' | 'scott' | 'rice' | 'sqrt') or a fixed count. binWidth pins the boundaries when they carry meaning, range frames the axis independently of the data, normalize switches the y units to percent or density, and cumulative gives a CDF. 'auto' takes the narrower of Freedman-Diaconis and Sturges.

All series share one set of edges derived from their combined extent, so two distributions stay comparable instead of putting different bars at the same x. plotOptions.histogram.overlap (default true) then draws each series across the full bin rather than grouping them beside each other, because comparison is the reason to put two samples on one axis and grouping is the arrangement that misreads it. A single series is unaffected either way.

The binning ships behind apexcharts/features/stats, so it costs nothing if you do not use it.

Box plot and violin take the sample too

A box plot required y: [min, q1, median, q3, max] and a violin required a precomputed density profile. Both asked the caller to do the statistics that give the chart its meaning, which is backwards: the numbers you have are the measurements.

Supply the observations and the library computes the rest. They go in points, the field both types already use for jitter dots, so a sample lives in exactly one place whether you summarise it or we do.

series: [{ data: [{ x: 'Phone', points: [1.2, 1.9, 3.4, ...] }] }]

Quartiles interpolate between ranks (R type 7). Whiskers default to the extremes, so nothing is hidden by default; plotOptions.boxPlot.whiskers: 'tukey' switches to the 1.5 × IQR convention.

rowSeries(), so a mark can name the rows it stands for

A histogram bin, a box and a violin all stand for rows that the chart is already holding. chart.rowSeries() returns them as a series, which makes the summary and the observations two views of one dataset:

chart.updateOptions({ chart: { type: 'unit' }, series: chart.rowSeries() })

It returns null when the current type has no row source. The sources ship with the statistics behind apexcharts/features/stats; core keeps only the lookup.

The cross-type morph conserves the ink

The unit pairings used to read as "the old chart vanished and a new one animated", and the reason was structural: the exit was a photocopy of the whole outgoing chart fading over the incoming one. Frame by frame that is a double exposure, two pictures both half-visible, neither becoming the other. No amount of easing fixes a crossfade.

A morph between one mark and N objects now cuts the mark into exactly N cells and flies every cell to its object, corners rounding off and fill blending on the way. A summary mark is cut along its own silhouette rather than its bounding box, and a wedge along its curve, which is why a donut's hole survives being taken apart.

Beyond that, any two mark families now pair. The engine used to decline combinations simply because nobody had driven them; the only pairing still closed is the dot cluster against a partition, where the divider has no cut for a tile or an arc and the result would fall back to a fade. Treemap and sunburst pair at every level rather than only the leaves, and a box plot unfolds into its violin and folds back.

Every offered transition is now covered by a motion test that asserts the marks actually travel, rather than counting the elements that exist at the end.

Nested treemaps

A treemap could only draw two levels, a series and its rows, so anything deeper had to be flattened by hand, throwing away the structure a market map exists to show. A datum may now carry children to whatever depth the data has.

Squarify became recursive: a branch is laid out inside its parent's rect with a header strip and per-level padding, and a container's area is the sum of its children exactly, so a parent always holds what it contains. Flat inputs are untouched and render identically to the float.

The hierarchy resolver is now shared with the sunburst, including the drilldown: '<id>' adapter, which the treemap opts into with nested.drilldownAsLevels.

Drilldown: line and area, and async levels

Drilldown was wired for line and area but inert, and worse than inert: a real click did nothing in every default configuration while the pointer cursor promised otherwise. With markers.size: 0 there is no element to click, and even with markers shown, core marks line and area markers no-pointer-events so the shared tooltip can track the plot. The feature now supplies a markers.discrete entry per drillable point, so only those points carry a dot and it reads as "these open".

Async levels close the phase that makes drilldown usable against an API. The organising idea is that a failed fetch is ordinary, not exceptional, so it must never strand the view: on a throw, a rejection, or a resolver returning something without a data array, the chart stays where it was, the breadcrumb is untouched, nothing is cached, and drillDownError fires. That last case previously no-opped in silence, which is indistinguishable from "the click did nothing". There is also a loading overlay, theme-aware, role="status" with aria-live="polite", whose spinner flattens to a pulse under prefers-reduced-motion.

A layout for the unit chart can now come from outside

Every arrangement the unit chart could draw was hard-coded, so a new one meant a core edit and the set was closed. plotOptions.unit.layout: 'custom' opens it:

plotOptions: { unit: { layout: 'custom', positions: (objects, rect) => [...] } }

positions takes (objects, rect) => [{ id, x, y, r? }], or the name of a layout registered with ApexCharts.registerUnitLayout. A layout is objects in, positions out, and nothing else: it knows nothing about animation because the engine already tweens position, radius and colour and already keeps a mark's identity across a relayout. Marks the provider omits animate out through the existing exit path; ids matching no mark are ignored.

objects carries identity and data per mark rather than just an index, so a provider can address a specific unit rather than a positional slot.

Unit marks travel on a spring

A fixed-duration tween cannot be interrupted: when the next render lands mid-flight it rebuilds the marks at the slot they had not reached yet and re-animates from a standstill. A dragged slider or a scrubbed storyboard interrupts on almost every frame, so that read as a continuous stutter. The gather now runs on a spring, which retargets and keeps its velocity.

A pie slice that moves instead of changing colour

Both state visuals a pie or donut slice had were recolourings: hover lightened the fill, and a click darkened it and redrew it at a 4px larger radius. Neither says "this slice" as plainly as motion does, and the click one was quietly dishonest, since growing the radius inflates the quantity the slice encodes. A click now slides the slice out along its own mid-angle, and hover traces an outline band. Legend clicks toggle the slice in and out through the same path.

Also new here: plotOptions.pie.borderRadius and plotOptions.pie.spacing, for pie, donut and polar area.

🐛 Fixes

An exported SVG carries its fonts and images (#343)

An exported SVG is a standalone document, and the PNG path rasterizes it through <img src="data:image/svg+xml,...">. An SVG loaded as an image cannot fetch external resources and cannot reach the page's stylesheets or its loaded fonts, so anything the export left as a URL was not merely slow to appear, it was gone. Fonts, images and patterns are now inlined into the download.

A stacked total per group, not per data point

With series[].group each group is its own stack, so a grouped stacked bar should carry one total above each group's bar. It drew one label per data point instead, holding the sum of every series in the chart and centred on the middle of the whole cluster: on two groups of two that meant a single "75" floating between the bars rather than "15" over one and "60" over the other. A 100% stack also now reserves room for the total it otherwise had nowhere to put.

Tooltips and grid chrome measured from the plot origin

Three independent cases where a coordinate was measured from the wrong origin:

  • the hover hit-test and bar centres, so the tooltip could caption the neighbouring bar (#5272). Thanks to @lazerg (#5275).
  • datetime gridlines that fall outside the plot are now skipped rather than drawn on the axis (#5273). Thanks to @lazerg (#5274).
  • an annotation label's background box (#5270). Thanks to @mrash (#5271).

A slice tooltip lands on the slice

tooltip.intersect anchors a pie, donut or polar area tooltip on the arc centroid, which each slice stamps on its path in its own user space. Those were read as if they were SVG-root coordinates, dropping the inner group's translate, and that translate is exactly the offset that centres a pie in a chart wider than it is tall. The caption appeared a couple of hundred pixels to the left of the slice it described. Keyboard navigation had the same arithmetic and the same bug, and now shares one helper with the pointer path.

A chart that changes type behaves like the type it became

Type defaults are applied once, when the chart is first rendered, so updateOptions({ chart: { type } }) left every choice the outgoing type had made for itself in place. A box plot that became a violin kept the five-number tooltip formatter and threw on every hover, which killed the caption and stranded the crosshair on the first category; a bar that became a box plot never acquired that formatter at all and got the plain series tooltip instead of its summary.

The leaves that decide what a chart reads, says, hit-tests or offers as interaction are now re-chosen when the type changes. The ones that decide how it is painted deliberately are not, so changing type does not restyle a chart out from under a morph in flight, and a palette chosen for a bar survives its becoming a line. Anything you set yourself is never re-chosen, including in the same update call.

Others

  • a hidden polar area series gives its slot back, and updates animate in place rather than rebuilding
  • a --apx-surface token change now updates the background it had itself set, so an OS light/dark flip or a host app swapping its design system is picked up
  • a non-array series passed to updateOptions is ignored with a warning instead of poisoning the config and crashing every later update
  • a legend toggle no longer re-bins a histogram's counts, which had made the remaining bars change shape
  • the drilldown breadcrumb reserves a band above the plot, and only the room it actually lacks
  • the walk back to a stacked series' baseline is corrected for line charts
  • unit scatter axis chrome follows the configured axis label colour
  • xaxis.labels.style.fontSize: 'inherit' no longer yields NaN (#5064). Thanks to @waterWang (#5256).
  • a hover arriving after the grid is gone is ignored, and the tooltip arrow parks flush against the marker edge

🔧 Internal

  • ApexCharts now depends on apex-commons (^0.5.0) at runtime. The licence manager had been a vendored fork that had drifted from its origin, making the family's licence contract two implementations kept in step by hand; and the crossfilter engine was never chart-specific, so keeping the only copy inside a charting library meant a map, a grid or a tree had to install ApexCharts just to coordinate a filter. Both now come from the shared package, along with the spring primitives the unit chart uses. The browser bundles inline it, so nothing changes for script-tag users.
  • the e2e calendar is pinned, so date-based sample snapshots stop rotting by the day
  • histogram binning moved out of core, behind apexcharts/features/stats

Full Changelog: https://github.com/apexcharts/apexcharts.js/compare/v6.8.0...v6.9.0

2 hours ago
shaka-player

v5.2.6

5.2.6 (2026-08-15)

Bug Fixes

  • Avoid re-downloading init segments on unbuffered seek (#10428) (01aee9f), closes #10373
  • Dolby Vision: Enable Dolby Vision p8 workaround on encrypted content (#10423) (12e4c49)
  • Fix stuck playback on multiplexed TS content (#10431) (5f4f5d9)
3 hours ago
shaka-player

v5.1.19

5.1.19 (2026-08-15)

Bug Fixes

  • Avoid re-downloading init segments on unbuffered seek (#10428) (eac06cd), closes #10373
  • Dolby Vision: Enable Dolby Vision p8 workaround on encrypted content (#10423) (0f9bc42)
  • Fix stuck playback on multiplexed TS content (#10431) (0220e70)
3 hours ago
shaka-player

v4.16.45

4.16.45 (2026-08-15)

Bug Fixes

3 hours ago
shaka-player

v4.15.56

4.15.56 (2026-08-15)

Bug Fixes

4 hours ago
formatjs

eslint-plugin-formatjs: 6.5.0

6.5.0 (2026-08-16)

What's Changed

Full Changelog: https://github.com/formatjs/formatjs/compare/eslint-plugin-formatjs@6.4.21...eslint-plugin-formatjs@6.5.0

4 hours ago
formatjs

@formatjs/cli-native-win32-x64: 1.1.13

1.1.13 (2026-08-16)

What's Changed

Full Changelog: https://github.com/formatjs/formatjs/compare/@formatjs/cli-native-win32-x64@1.1.12...@formatjs/cli-native-win32-x64@1.1.13

4 hours ago
formatjs

formatjs_cli: 1.4.0

1.4.0 (2026-08-16)

What's Changed

Full Changelog: https://github.com/formatjs/formatjs/compare/formatjs_cli_v1.3.0...formatjs_cli_v1.4.0

Binaries

  • macOS Apple Silicon: formatjs_cli-darwin-arm64
  • Linux ARM64: formatjs_cli-linux-arm64
  • Linux x86_64: formatjs_cli-linux-x64
  • Windows x64: formatjs_cli-win32-x64.exe

Installation

# macOS (Apple Silicon)
curl -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.4.0/formatjs_cli-darwin-arm64
chmod +x formatjs_cli-darwin-arm64
sudo mv formatjs_cli-darwin-arm64 /usr/local/bin/formatjs

# Linux
curl -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.4.0/formatjs_cli-linux-x64
chmod +x formatjs_cli-linux-x64
sudo mv formatjs_cli-linux-x64 /usr/local/bin/formatjs

# Linux ARM64
curl -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.4.0/formatjs_cli-linux-arm64
chmod +x formatjs_cli-linux-arm64
sudo mv formatjs_cli-linux-arm64 /usr/local/bin/formatjs
# Windows x64 (PowerShell)
curl.exe -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.4.0/formatjs_cli-win32-x64.exe

Verification

Verify the checksums:

curl -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.4.0/checksums.txt
shasum -a 256 -c checksums.txt
4 hours ago
formatjs

formatjs_intl: 0.4.0

0.4.0 (2026-08-16)

What's Changed

Full Changelog: https://github.com/formatjs/formatjs/compare/formatjs_intl_v0.3.0...formatjs_intl_v0.4.0

Dependencies

  • The following workspace dependencies were updated
    • dependencies
      • formatjs_intl_macros bumped from 0.1.2 to 0.2.0