<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>VueCraft NPM — What's new</title>
  <subtitle>A chronological changelog of every VueCraft package: what shipped and when, by date and version.</subtitle>
  <id>https://npm.vuecraft.ru/en/changelog/</id>
  <link rel="self" href="https://npm.vuecraft.ru/en/changelog/feed.xml"/>
  <link href="https://npm.vuecraft.ru/en/changelog/"/>
  <updated>2026-10-09T00:00:00Z</updated>
  <entry>
    <title>DevToolz 0.5.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-devtoolz-0-5-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-devtoolz-0-5-0"/>
    <updated>2026-10-09T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Changed: the image commands &lt;code&gt;image-hash&lt;/code&gt; and &lt;code&gt;image-batch&lt;/code&gt;, and their modules in &lt;code&gt;devtoolz ui&lt;/code&gt;, moved to their own package, &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/&quot;&gt;MediaToolz&lt;/a&gt;. In DevToolz both commands are left as stubs: they print &lt;code&gt;image-batch has moved to @macrulez/mediatoolz — run it with: npx @macrulez/mediatoolz image-batch …&lt;/code&gt; and exit with code 2, so a script that still calls them fails loudly. The stubs will be removed in one of the next versions. To move over, install &lt;code&gt;@macrulez/mediatoolz&lt;/code&gt;, use the same commands and flags, and move the folder &lt;code&gt;.devtoolz/image-batch/&lt;/code&gt; to &lt;code&gt;.mediatoolz/image-batch/&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/installation.html#moving-from-devtoolz&quot;&gt;Moving from DevToolz&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Changed: &lt;code&gt;devtoolz ui&lt;/code&gt; keeps two modules, the code checks and the cleanup, and the folder browser lists folders only.&lt;/li&gt;
&lt;li&gt;Changed: DevToolz no longer depends on &lt;code&gt;hazehash&lt;/code&gt;, &lt;code&gt;blurhash&lt;/code&gt;, &lt;code&gt;thumbhash&lt;/code&gt; and &lt;code&gt;sharp&lt;/code&gt;, so it installs lighter and never offers to install a native image library. The programmatic API no longer exports &lt;code&gt;runImageHash&lt;/code&gt;, &lt;code&gt;runImageBatch&lt;/code&gt; and the related types; they are exported by &lt;code&gt;@macrulez/mediatoolz&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.4.3</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-devtoolz-0-4-3</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-devtoolz-0-4-3"/>
    <updated>2026-10-09T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Changed: in the interface, &lt;strong&gt;Convert&lt;/strong&gt; has a &lt;strong&gt;Resize the images&lt;/strong&gt; switch, off by default. Until it is turned on, the images are only converted to the chosen format and the size fields are hidden (a run without any size never resizes; see &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-batch.html#size-methods&quot;&gt;Size methods&lt;/a&gt;); before, a width list (&lt;code&gt;800, 1600&lt;/code&gt;) was filled in from the start and every image was resized twice.&lt;/li&gt;
&lt;li&gt;Changed: in the interface, &lt;strong&gt;Image Hash&lt;/strong&gt; starts with hazehash and dominant color ticked; blurhash and thumbhash are off.&lt;/li&gt;
&lt;li&gt;Added: &lt;code&gt;--no-resize&lt;/code&gt; switches off the sizes of a saved config for one run.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>MediaToolz 0.1.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-mediatoolz-0-1-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-mediatoolz-0-1-1"/>
    <updated>2026-10-09T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Changed: the native &lt;code&gt;sharp&lt;/code&gt; image library is now installed with the package, so &lt;code&gt;image-hash&lt;/code&gt;, &lt;code&gt;image-batch&lt;/code&gt; and &lt;code&gt;mediatoolz ui&lt;/code&gt; work right after &lt;code&gt;npm install -g @macrulez/mediatoolz&lt;/code&gt;, with no warning and no question on the first run. The offer to install &lt;code&gt;sharp&lt;/code&gt; into &lt;code&gt;~/.mediatoolz/deps&lt;/code&gt; remains only for the rare case when its binary is missing (an install with &lt;code&gt;--omit=optional&lt;/code&gt;, an unsupported platform). See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/installation.html&quot;&gt;Installation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>MediaToolz 0.1.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-mediatoolz-0-1-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-mediatoolz-0-1-0"/>
    <updated>2026-10-09T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: the package. &lt;code&gt;image-hash&lt;/code&gt;, &lt;code&gt;image-batch&lt;/code&gt; and &lt;code&gt;ui&lt;/code&gt; moved here from &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/&quot;&gt;DevToolz&lt;/a&gt; 0.4.3 as they were, with the same commands, flags and settings. What changed with the move: the command is &lt;code&gt;mediatoolz&lt;/code&gt;, configs and sharpening presets live in &lt;code&gt;.mediatoolz/image-batch/&lt;/code&gt;, the managed copy of &lt;code&gt;sharp&lt;/code&gt; in &lt;code&gt;~/.mediatoolz/deps&lt;/code&gt;, and the default cache file of &lt;code&gt;image-hash&lt;/code&gt; is &lt;code&gt;.mediatoolz-image-hash-cache.json&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/installation.html#moving-from-devtoolz&quot;&gt;Moving from DevToolz&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Polyrepo 1.3.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-polyrepo-cli-1-3-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-09-polyrepo-cli-1-3-1"/>
    <updated>2026-10-09T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: the Publish form and the Release wizard show the version a package has on npm next to the local one, with the filter &lt;strong&gt;Only ahead of npm&lt;/strong&gt;, so it is clear what is worth publishing. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/polyrepo-cli/guide/ui.html#commands&quot;&gt;Web Interface&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: when a publish fails because npm wants a sign-in link, a security key or a passkey, the report offers &lt;strong&gt;Publish in a terminal&lt;/strong&gt;: a terminal window opens in the package folder with the publish command, where npm can take the sign-in. Before, the interface could only ask for a one-time code. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/polyrepo-cli/guide/ui.html#signing-in-by-a-link-a-key-or-a-passkey&quot;&gt;Signing in by a link, a key or a passkey&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: rows in the package list are tinted by status: red for local changes, yellow for a version ahead of npm, and the accent color for a package that is not on npm.&lt;/li&gt;
&lt;li&gt;New: a &lt;strong&gt;Refresh&lt;/strong&gt; button above the package list of every command form and of the Release wizard rereads the branches, the git state and the npm versions without reloading the page.&lt;/li&gt;
&lt;li&gt;Changed: the button that starts a command stays pinned to the bottom of the page, and so do the buttons of the Release wizard.&lt;/li&gt;
&lt;li&gt;Changed: the cards of a run that has several steps (a tag and then a release, for example) are stacked one under the other at the full width.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.4.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-devtoolz-0-4-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-devtoolz-0-4-2"/>
    <updated>2026-10-08T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: &lt;code&gt;devtoolz ui&lt;/code&gt; starts a local web interface and opens it in the browser. It is part of the package and listens on &lt;code&gt;127.0.0.1&lt;/code&gt; only, behind a one-time token in the printed address; requests with a foreign &lt;code&gt;Host&lt;/code&gt; or &lt;code&gt;Origin&lt;/code&gt; are refused. &lt;code&gt;--port&lt;/code&gt;, &lt;code&gt;--host&lt;/code&gt;, &lt;code&gt;--no-open&lt;/code&gt;, &lt;code&gt;--token&lt;/code&gt; and &lt;code&gt;--cwd&lt;/code&gt; adjust it. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/ui.html&quot;&gt;Web Interface&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Code checks&lt;/strong&gt; runs eleven checks (dead exports, empty catch blocks, orphan tests, import case, circular imports, TODO comments, stale &lt;code&gt;@ts-ignore&lt;/code&gt;, unused dependencies, &lt;code&gt;package.json&lt;/code&gt; exports, README samples, npm scripts in the docs) on any folder you choose. An overview runs them all and shows a card for each. Findings are grouped by file, can be filtered, and open next to the code, with syntax highlighting, the line marked, and a link to the editor. Import cycles can also be shown as a graph.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Code cleanup&lt;/strong&gt; removes comments or &lt;code&gt;console&lt;/code&gt; calls with a review first: a scan lists the files and shows a real diff for each, nothing is selected by default, and only the files you tick are changed, after a confirmation. A file that changed after the scan is skipped. The originals are copied outside the project first, and the cleanup can be undone.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Image Hash&lt;/strong&gt; in the interface — pick folders in a file browser with thumbnails, see how many images they hold, choose the placeholders and get a gallery that shows each image next to the placeholders decoded from its hashes, with the output ready to copy, download or write to a file.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Image Batch&lt;/strong&gt; in the interface — converting with quick settings or a saved config, with a preview of the plan, progress, and before and after thumbnails; a form editor for configs with a JSON tab and live validation; sharpening presets with a preview that compares the image before and after; and the backups of replaced originals, with a restore.&lt;/li&gt;
&lt;li&gt;Changed: &lt;code&gt;image-batch&lt;/code&gt; accepts a &lt;code&gt;--size&lt;/code&gt; box as a run override in the programmatic API, and each result of a run now carries the absolute paths of its source and output.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.4.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-devtoolz-0-4-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-devtoolz-0-4-1"/>
    <updated>2026-10-08T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: &lt;code&gt;sharpen&lt;/code&gt; adds output sharpening after the resize, in the manner of Lightroom: &lt;code&gt;for&lt;/code&gt; (&lt;code&gt;screen&lt;/code&gt;, &lt;code&gt;matte&lt;/code&gt; or &lt;code&gt;glossy&lt;/code&gt;) and &lt;code&gt;amount&lt;/code&gt; (&lt;code&gt;low&lt;/code&gt;, &lt;code&gt;standard&lt;/code&gt; or &lt;code&gt;high&lt;/code&gt;) pick the values from a table, and the fine settings &lt;code&gt;radius&lt;/code&gt;, &lt;code&gt;flat&lt;/code&gt;, &lt;code&gt;jagged&lt;/code&gt; and &lt;code&gt;threshold&lt;/code&gt; replace any of them. Each is checked against the range sharp accepts, and a wrong value is reported with the field and the range before anything is written. A recipe that does not name &lt;code&gt;sharpen&lt;/code&gt; is not sharpened. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-batch.html#sharpening&quot;&gt;Sharpening&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-batch sharpen&lt;/code&gt; saves sharpening presets and manages them (&lt;code&gt;sharpen new|list|show|rm&lt;/code&gt;; without a subcommand a terminal opens a list to show, edit, copy or delete). A preset is used by its name: &lt;code&gt;&amp;quot;sharpen&amp;quot;: &amp;quot;web-crisp&amp;quot;&lt;/code&gt; or &lt;code&gt;{ &amp;quot;preset&amp;quot;: &amp;quot;web-crisp&amp;quot;, &amp;quot;amount&amp;quot;: &amp;quot;high&amp;quot; }&lt;/code&gt; in a config, &lt;code&gt;--sharpen web-crisp&lt;/code&gt; on the command line. Presets live in &lt;code&gt;.devtoolz/image-batch/sharpen/&lt;/code&gt; of the project or in &lt;code&gt;~/.devtoolz/image-batch/sharpen/&lt;/code&gt; for all projects. Six built-in presets (&lt;code&gt;web-light&lt;/code&gt;, &lt;code&gt;web-crisp&lt;/code&gt;, &lt;code&gt;web-detail&lt;/code&gt;, &lt;code&gt;thumbnail&lt;/code&gt;, &lt;code&gt;print-matte&lt;/code&gt;, &lt;code&gt;print-glossy&lt;/code&gt;) work without creating anything. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-batch.html#sharpening-presets&quot;&gt;Sharpening presets&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: the flags &lt;code&gt;--sharpen&lt;/code&gt;, &lt;code&gt;--sharpen-for&lt;/code&gt;, &lt;code&gt;--sharpen-amount&lt;/code&gt;, &lt;code&gt;--sharpen-radius&lt;/code&gt;, &lt;code&gt;--sharpen-flat&lt;/code&gt;, &lt;code&gt;--sharpen-jagged&lt;/code&gt; and &lt;code&gt;--sharpen-threshold&lt;/code&gt; for &lt;code&gt;image-batch&lt;/code&gt;, &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;sharpen new&lt;/code&gt;. The &lt;code&gt;init&lt;/code&gt; wizard asks about sharpening and offers the saved presets, and the recipe editor of &lt;code&gt;config&lt;/code&gt; chooses a preset or custom values.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.4.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-devtoolz-0-4-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-devtoolz-0-4-0"/>
    <updated>2026-10-08T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: the &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-batch.html&quot;&gt;&lt;code&gt;image-batch&lt;/code&gt;&lt;/a&gt; command resizes, converts and recompresses raster images in bulk by rules. The rules live in a reusable config (or in flags); the folders to read and the place for the results are chosen on every run, so one config serves any project. It uses the same &lt;code&gt;sharp&lt;/code&gt; library as &lt;code&gt;image-hash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New: three places for the results — &lt;code&gt;-o &amp;lt;dir&amp;gt;&lt;/code&gt; (a separate folder that repeats the source structure, &lt;code&gt;--flat&lt;/code&gt; drops it), &lt;code&gt;--beside&lt;/code&gt; (next to each source) and &lt;code&gt;--replace&lt;/code&gt; (over the source files, each in its own format, to shrink oversized originals or recompress them in place). Exactly one of them is given.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;--replace&lt;/code&gt; is guarded. It asks for a confirmation (&lt;code&gt;--yes&lt;/code&gt; without a terminal), copies the originals to &lt;code&gt;.image-batch-backup/&amp;lt;date&amp;gt;/&lt;/code&gt; with a &lt;code&gt;journal.json&lt;/code&gt; first (&lt;code&gt;--backup &amp;lt;dir&amp;gt;&lt;/code&gt;, &lt;code&gt;--no-backup&lt;/code&gt;), replaces a file only when the result is smaller (&lt;code&gt;--no-only-if-smaller&lt;/code&gt;), never processes the same file twice with the same settings, and &lt;code&gt;--dry-run&lt;/code&gt; shows the real before and after sizes. &lt;code&gt;image-batch restore &amp;lt;backup&amp;gt;&lt;/code&gt; puts the originals back.&lt;/li&gt;
&lt;li&gt;New: sizes by &lt;code&gt;widths&lt;/code&gt;, &lt;code&gt;heights&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt; with a &lt;code&gt;fit&lt;/code&gt;, &lt;code&gt;scale&lt;/code&gt; (&lt;code&gt;@2x&lt;/code&gt;), and by the long side (&lt;code&gt;longEdge&lt;/code&gt;, &lt;code&gt;--long&lt;/code&gt;), the short side (&lt;code&gt;shortEdge&lt;/code&gt;, &lt;code&gt;--short&lt;/code&gt;), area in megapixels (&lt;code&gt;megapixels&lt;/code&gt;, &lt;code&gt;--megapixels&lt;/code&gt;) and percentage (&lt;code&gt;percent&lt;/code&gt;, &lt;code&gt;--percent&lt;/code&gt;). The long and short side do not depend on the orientation, so one setting fits a gallery of landscape and portrait shots. &lt;code&gt;matchOrientation&lt;/code&gt; (&lt;code&gt;--match-orientation&lt;/code&gt;) turns a width × height box around for images of the other orientation. Sizes above the source size are not enlarged unless &lt;code&gt;withoutEnlargement&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;maxBytes&lt;/code&gt; (&lt;code&gt;--max-size 200KB&lt;/code&gt;) limits the size of every file: the quality is lowered as little as needed, and a file that cannot reach the limit is reported instead of being written. It works for jpg, webp, avif, heif, jp2 and a png with a palette.&lt;/li&gt;
&lt;li&gt;New: formats jpg, png, webp, avif, gif, tiff, jp2 and heif, with the options that matter for each (&lt;code&gt;quality&lt;/code&gt;, &lt;code&gt;mozjpeg&lt;/code&gt;, a png &lt;code&gt;palette&lt;/code&gt;, webp &lt;code&gt;lossless&lt;/code&gt;, avif &lt;code&gt;effort&lt;/code&gt;, …) set in a config or with &lt;code&gt;--codec&lt;/code&gt;, and quality levels &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt; and &lt;code&gt;best&lt;/code&gt; that expand to a number per format. Lossy settings are never switched on silently, and a wrong option or value is reported with a hint before anything is written.&lt;/li&gt;
&lt;li&gt;New: file names from a template — &lt;code&gt;{name}&lt;/code&gt;, &lt;code&gt;{ext}&lt;/code&gt;, &lt;code&gt;{orig}&lt;/code&gt;, &lt;code&gt;{dir}&lt;/code&gt;, &lt;code&gt;{format}&lt;/code&gt;, &lt;code&gt;{width}&lt;/code&gt;, &lt;code&gt;{height}&lt;/code&gt;, &lt;code&gt;{size}&lt;/code&gt;, &lt;code&gt;{long}&lt;/code&gt;, &lt;code&gt;{short}&lt;/code&gt;, &lt;code&gt;{mp}&lt;/code&gt;, &lt;code&gt;{percent}&lt;/code&gt;, &lt;code&gt;{scale}&lt;/code&gt;, &lt;code&gt;{index:3}&lt;/code&gt;, &lt;code&gt;{hash}&lt;/code&gt;, &lt;code&gt;{date}&lt;/code&gt; — with a sensible default for every size method. A template that would go outside the output folder, an unknown variable, or two results with the same name is an error before anything is written.&lt;/li&gt;
&lt;li&gt;New: choosing the files — &lt;code&gt;-r&lt;/code&gt;, &lt;code&gt;--include&lt;/code&gt;, &lt;code&gt;--exclude&lt;/code&gt;, &lt;code&gt;--files-from&lt;/code&gt;, globs, &lt;code&gt;--list&lt;/code&gt;, and &lt;code&gt;-i, --select&lt;/code&gt;, an interactive list in which you untick the files you do not want.&lt;/li&gt;
&lt;li&gt;New: results an earlier run already made are skipped; for any other existing file a terminal asks once (overwrite this, overwrite all, skip, skip all, quit), and without a terminal the files are skipped with exit code 1, or &lt;code&gt;--overwrite&lt;/code&gt;, &lt;code&gt;--skip-existing&lt;/code&gt; and &lt;code&gt;--no-overwrite&lt;/code&gt; decide.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;--hazehash&lt;/code&gt; (&lt;code&gt;--budget&lt;/code&gt;), &lt;code&gt;--blurhash&lt;/code&gt;, &lt;code&gt;--thumbhash&lt;/code&gt; and &lt;code&gt;--dominant-color&lt;/code&gt; with &lt;code&gt;--emit &amp;lt;file&amp;gt;&lt;/code&gt; write a manifest of everything produced, with the placeholders, in the shape of a &lt;code&gt;vue-image-kit&lt;/code&gt; placeholders manifest.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;init&lt;/code&gt; creates a config, and &lt;code&gt;config&lt;/code&gt; (&lt;code&gt;config list|show|rm|new&lt;/code&gt;) shows, edits, copies and deletes configs. They are kept in &lt;code&gt;.devtoolz/image-batch/&lt;/code&gt; of the project or in &lt;code&gt;~/.devtoolz/image-batch/&lt;/code&gt; for all projects, and the size method and the formats are chosen from lists.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Polyrepo 1.3.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-polyrepo-cli-1-3-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-polyrepo-cli-1-3-0"/>
    <updated>2026-10-08T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: &lt;code&gt;polyrepo commit&lt;/code&gt; commits what &lt;code&gt;npm audit fix&lt;/code&gt;, &lt;code&gt;npm update&lt;/code&gt; or &lt;code&gt;sync-deps&lt;/code&gt; left in the working tree (&lt;code&gt;package.json&lt;/code&gt; and the lock files, or every tracked change with &lt;code&gt;--scope all&lt;/code&gt;) without stumbling over branch rules. On a feature branch the commit goes there. On the default branch polyrepo reads the host's rules (GitHub rulesets and branch protection, GitLab protected branches and your role): if direct commits are allowed it commits and pushes; if a pull/merge request is required, or the rules cannot be read, it creates a branch, commits there, pushes it, opens a PR/MR and leaves the default branch untouched. A direct push that the host refuses anyway moves the commit to a branch for you. &lt;code&gt;--message&lt;/code&gt;, &lt;code&gt;--mode&lt;/code&gt;, &lt;code&gt;--branch&lt;/code&gt;, &lt;code&gt;--no-push&lt;/code&gt;, &lt;code&gt;--no-pr&lt;/code&gt;, &lt;code&gt;--stay&lt;/code&gt;, &lt;code&gt;--dry-run&lt;/code&gt;, &lt;code&gt;--packages&lt;/code&gt; and &lt;code&gt;--yes&lt;/code&gt; adjust it. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/polyrepo-cli/guide/commit.html&quot;&gt;Committing Changes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: the interface shows a partly fixed &lt;code&gt;npm audit fix&lt;/code&gt; as &lt;strong&gt;Partly done&lt;/strong&gt; instead of a failure, with &lt;strong&gt;What is left&lt;/strong&gt; grouped by the update that fixes each vulnerability, and buttons to preview &lt;code&gt;--force&lt;/code&gt;, audit production dependencies only, update one dependency, or apply &lt;code&gt;--force&lt;/code&gt; after a confirmation. Audit and outdated reports have one colored block per package with a prominent &lt;strong&gt;Fix vulnerabilities…&lt;/strong&gt; / &lt;strong&gt;Update dependencies…&lt;/strong&gt; button. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/polyrepo-cli/guide/ui.html#fixing-what-a-run-found&quot;&gt;Fixing what a run found&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: after a command that changes dependencies, the interface shows what changed in &lt;code&gt;package.json&lt;/code&gt; and the lock files, with the change to &lt;code&gt;package.json&lt;/code&gt; as a diff, and offers &lt;strong&gt;Commit…&lt;/strong&gt; (the dialog reads the branch rules and recommends a direct commit or a branch and a PR/MR), &lt;strong&gt;Discard…&lt;/strong&gt; and &lt;strong&gt;Run tests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;New: under every warning and failure the report suggests the next steps for that situation (commit or stash a dirty working tree, check the npm sign-in, publish again with a one-time password, switch to the default branch, run again, and more), and a finished bump, tag, publish, commit or clone suggests what usually comes next. A cancelled or interrupted run offers to run again and to check your setup, a run that did nothing is marked &lt;strong&gt;Needs attention&lt;/strong&gt;, and the page says so when the server was stopped.&lt;/li&gt;
&lt;li&gt;New: after a command that changes repos, the Packages table refreshes just the packages it touched, in the background.&lt;/li&gt;
&lt;li&gt;New: URLs in reports and logs are clickable.&lt;/li&gt;
&lt;li&gt;Changed: one button style across the interface: neutral, primary, danger (outlined) and critical (solid, for irreversible confirmations), with icons and a soft shadow.&lt;/li&gt;
&lt;li&gt;Changed: report cards with long output take the full width, and the output of a failed command opens by itself. The Packages page and the reports show a centered spinner while they load, and no longer flash an empty state when you come back to Packages.&lt;/li&gt;
&lt;li&gt;Changed: the package is published without its tests and interface sources, and the web interface is rebuilt automatically before every publish.&lt;/li&gt;
&lt;li&gt;Fixed: on Windows an argument with spaces, such as the message of &lt;code&gt;git commit -m &amp;quot;chore: bump version&amp;quot;&lt;/code&gt;, was split into several arguments, which broke commits made by &lt;code&gt;bump&lt;/code&gt; and other commands. &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;gh&lt;/code&gt;, &lt;code&gt;glab&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; are now started directly, and every other command gets properly quoted arguments.&lt;/li&gt;
&lt;li&gt;Fixed: commands started from the interface no longer print the &lt;code&gt;NO_COLOR … is ignored due to FORCE_COLOR&lt;/code&gt; warning.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Polyrepo 1.2.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-polyrepo-cli-1-2-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-08-polyrepo-cli-1-2-0"/>
    <updated>2026-10-08T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: &lt;code&gt;polyrepo ui&lt;/code&gt; starts a local web interface and opens it in the browser. It is part of the package and listens on &lt;code&gt;127.0.0.1&lt;/code&gt; only, behind a one-time token in the printed address; requests with a foreign &lt;code&gt;Host&lt;/code&gt; or &lt;code&gt;Origin&lt;/code&gt; are refused, and anything that changes a repo needs an explicit confirmation. &lt;code&gt;--port&lt;/code&gt;, &lt;code&gt;--host&lt;/code&gt;, &lt;code&gt;--no-open&lt;/code&gt; and &lt;code&gt;--token&lt;/code&gt; adjust it. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/polyrepo-cli/guide/ui.html&quot;&gt;Web Interface&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Packages&lt;/strong&gt; shows every package in one table, with the problems counted and clickable as filters (local changes, off the main branch, not on npm or behind it, different from origin, stale dependencies). Monorepos are colored blocks that fold and select all their packages at once, branch and status are chips, and the selection opens Bump, Publish, Tag, Sync deps, Switch branch or Run command with the packages ticked.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Commands&lt;/strong&gt; has a form for each command, with the same options as the flags. The package list shows the branch and whether a repo has local changes, can be filtered, and remembers named sets. &lt;strong&gt;Review and run&lt;/strong&gt; shows a summary of what will change, with &lt;strong&gt;Preview (dry run)&lt;/strong&gt;; a finished preview offers &lt;strong&gt;Run for real…&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;New: the &lt;strong&gt;Release&lt;/strong&gt; wizard goes through packages, version, options and a review, and runs &lt;code&gt;bump&lt;/code&gt; with a preview first if you want one.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Runs&lt;/strong&gt; show a report, the first thing for a finished run: counts, a &lt;strong&gt;Needs attention&lt;/strong&gt; list with the problems that are new since the previous run, a card per check part or per package, and the tables of the read-only commands with &lt;strong&gt;Update…&lt;/strong&gt; and &lt;strong&gt;Fix…&lt;/strong&gt; actions. The full log is searchable, can be limited to problems, folded and saved. The questions of a command arrive as dialogs, a run can be cancelled, and the history keeps the runs with their logs.&lt;/li&gt;
&lt;li&gt;New: &lt;strong&gt;Settings&lt;/strong&gt; edits the config (roots, extra packages, GitLab hosts) with a folder picker and a live list of found packages, and shows who &lt;code&gt;gh&lt;/code&gt;, &lt;code&gt;glab&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; are signed in as and which tools were found. The color range for monorepo blocks, saved package sets and desktop notifications are set here too.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;Ctrl+K&lt;/code&gt; opens a palette for a page, a command, a recent run or a package.&lt;/li&gt;
&lt;li&gt;New: the Publish form and the Release wizard accept a one-time password for an npm account with two-factor authentication. It is never written to the run history.&lt;/li&gt;
&lt;li&gt;Changed: commands report their progress through a small runtime instead of printing directly. The terminal output and the prompts are the same as before.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.3.3</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-07-devtoolz-0-3-3</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-07-devtoolz-0-3-3"/>
    <updated>2026-10-07T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: &lt;code&gt;image-hash&lt;/code&gt; generates &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/overview.html&quot;&gt;hazehash&lt;/a&gt; with &lt;code&gt;-t hazehash&lt;/code&gt; (or &lt;code&gt;-t all&lt;/code&gt;). At the same size it is more accurate than blurhash and thumbhash, and it keeps the aspect ratio and, only when the image has transparent pixels, the alpha channel. In every list of hash types and in every output (JSON, CSV, the &lt;code&gt;--dry-run&lt;/code&gt; table) it comes first, before blurhash. The default, &lt;code&gt;-t both&lt;/code&gt;, is still blurhash and thumbhash. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-hash.html#what-is-generated&quot;&gt;Image Hash&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;--budget &amp;lt;bytes&amp;gt;&lt;/code&gt; sets the most one hazehash may take, from 7 to 48 bytes (default &lt;code&gt;28&lt;/code&gt;; 16–48 is the range the format is tuned for). It is a ceiling: a flat or smooth image needs fewer bytes. A budget too small for an image with transparency (under 9 bytes) is reported as a problem for that image, and a value outside 7–48 exits with code 2.&lt;/li&gt;
&lt;li&gt;Note: &lt;code&gt;--cache&lt;/code&gt; now also remembers the budget, so a cache file written by an earlier version is recomputed once.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.7.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-07-vue-image-kit-1-7-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-07-vue-image-kit-1-7-1"/>
    <updated>2026-10-07T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: the preview now behaves exactly like the image it stands for. The idle placeholder of a &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; used to be an empty &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; with inline &lt;code&gt;width: 100%&lt;/code&gt; and &lt;code&gt;height: auto&lt;/code&gt;, so with &lt;code&gt;width: 50%&lt;/code&gt;, a fixed height or a parent that shrinks to its content it differed in size from the loaded image, and the layout jumped when loading started. It is now an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; with the same &lt;code&gt;width&lt;/code&gt;/&lt;code&gt;height&lt;/code&gt; attributes and classes (a transparent image of the same size as &lt;code&gt;src&lt;/code&gt;, the hash as its background), and the browser sizes it by the same rules and CSS as the real image. The box also stays the same while the file downloads: until its first bytes arrive the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; carries &lt;code&gt;contain-intrinsic-size&lt;/code&gt; of its &lt;code&gt;width&lt;/code&gt;×&lt;code&gt;height&lt;/code&gt;. If you looked for the placeholder as a &lt;code&gt;span&lt;/code&gt; in a test or a stylesheet, look for &lt;code&gt;img[aria-hidden=&amp;quot;true&amp;quot;]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.7.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-07-vue-image-kit-1-7-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-07-vue-image-kit-1-7-0"/>
    <updated>2026-10-07T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;HazeHash placeholders, the preferred ones: new &lt;code&gt;hazehash&lt;/code&gt; prop on &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; and &lt;code&gt;hazehash&lt;/code&gt; in &lt;code&gt;SourcePlaceholder&lt;/code&gt;, &lt;code&gt;ImageMeta&lt;/code&gt; and manifest entries. A 7–48 byte string (28 by default) from the optional peer &lt;code&gt;hazehash&lt;/code&gt; decodes to a blurred preview with the right aspect ratio and alpha channel. &lt;code&gt;hazehash&lt;/code&gt; wins over &lt;code&gt;blurhash&lt;/code&gt;, &lt;code&gt;thumbhash&lt;/code&gt; and &lt;code&gt;placeholder&lt;/code&gt;; &lt;code&gt;v-lazy-img&lt;/code&gt; and &lt;code&gt;useBackgroundImage()&lt;/code&gt; use it too. The package loads on demand; without it one warning is logged and the next placeholder is used.&lt;/li&gt;
&lt;li&gt;The build tools make HazeHash: &lt;code&gt;mode: 'hazehash'&lt;/code&gt; for the Vite plugin and the Nuxt option, &lt;code&gt;placeholders --mode hazehash&lt;/code&gt;, &lt;code&gt;generate --hazehash&lt;/code&gt;, the &lt;code&gt;?hazehash&lt;/code&gt; and &lt;code&gt;?placeholder=hazehash&lt;/code&gt; imports.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;tuning.budget&lt;/code&gt; (&lt;code&gt;--budget&lt;/code&gt;, &lt;code&gt;&amp;amp;budget=&lt;/code&gt; in an import): the size of a HazeHash string in bytes, 7–48, default 28.&lt;/li&gt;
&lt;li&gt;Changed: the default placeholder mode is &lt;code&gt;hazehash&lt;/code&gt; when the &lt;code&gt;hazehash&lt;/code&gt; package is installed, &lt;code&gt;blurhash&lt;/code&gt; otherwise. To keep BlurHash, set &lt;code&gt;mode: 'blurhash'&lt;/code&gt;; install &lt;code&gt;hazehash&lt;/code&gt; in the app, because the browser decodes the hashes.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>HazeHash 0.1.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-06-hazehash-0-1-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-06-hazehash-0-1-1"/>
    <updated>2026-10-06T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;First release: three packages, &lt;code&gt;hazehash&lt;/code&gt;, &lt;code&gt;hazehash-vue&lt;/code&gt; and &lt;code&gt;hazehash-nuxt&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/overview.html&quot;&gt;Overview&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hazehash&lt;/code&gt; turns an image into a hash of 16–48 bytes (28 by default) and back into a blurred preview, with the aspect ratio and an optional alpha channel inside. At 28 bytes the mean perceptual error is 49% lower than BlurHash and 20% lower than ThumbHash. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/encoding.html&quot;&gt;Encoding Images&lt;/a&gt;, &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/decoding.html&quot;&gt;Decoding Hashes&lt;/a&gt; and &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/benchmark.html&quot;&gt;Benchmark&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Entry points for the decoder (&lt;code&gt;hazehash&lt;/code&gt;, &lt;code&gt;hazehash/decode&lt;/code&gt;), the encoder (&lt;code&gt;hazehash/encode&lt;/code&gt;), a canvas helper (&lt;code&gt;hazehash/canvas&lt;/code&gt;) and Node.js file helpers (&lt;code&gt;hazehash/node&lt;/code&gt;, with the optional peer &lt;code&gt;sharp&lt;/code&gt;). See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/canvas.html&quot;&gt;Drawing to a Canvas&lt;/a&gt; and &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/node-files.html&quot;&gt;Encoding Files in Node.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;hazehash&lt;/code&gt; command with &lt;code&gt;encode&lt;/code&gt;, &lt;code&gt;decode&lt;/code&gt; and &lt;code&gt;info&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/cli-encode.html&quot;&gt;Encode Command&lt;/a&gt; and &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/cli-decode-info.html&quot;&gt;Decode and Info Commands&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hazehash-vue&lt;/code&gt;: the &lt;code&gt;PlaceholderImage&lt;/code&gt; component and the &lt;code&gt;usePlaceholder()&lt;/code&gt; composable, with server markup that cannot mismatch on hydration. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/placeholder-image.html&quot;&gt;PlaceholderImage Component&lt;/a&gt; and &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/use-placeholder.html&quot;&gt;Placeholder State&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hazehash-nuxt&lt;/code&gt;: a module that registers the component and generates hashes for your images during the build, with a cache by file size and modification time. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/nuxt-module.html&quot;&gt;Nuxt Module&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The version 1 format will not change: a hash decodes the same way in every future release. The format is documented on &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/hazehash/guide/hash-format.html&quot;&gt;Hash Format&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.6.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-05-vue-image-kit-1-6-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-05-vue-image-kit-1-6-2"/>
    <updated>2026-10-05T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: with &lt;code&gt;sources&lt;/code&gt; or a &lt;code&gt;src&lt;/code&gt; object &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; renders a &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;, and the &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;style&lt;/code&gt; and other attributes given to the component went onto the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; instead of the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; that shows the image — so &lt;code&gt;border-radius&lt;/code&gt;, &lt;code&gt;object-fit&lt;/code&gt; and similar rules from the user's own class had no visible effect, while the same class on a plain &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; worked. Attributes now always land on the element that shows the image: the placeholder, the error box or the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, also inside a &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;. The &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; itself is rendered with &lt;code&gt;display: contents&lt;/code&gt;, so it takes no part in the layout and the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; lays out as if it stood alone. Event listeners given to &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; (&lt;code&gt;@click&lt;/code&gt;, …) are bound to the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; too and work next to the component's own &lt;code&gt;load&lt;/code&gt;/&lt;code&gt;error&lt;/code&gt; handling. If a stylesheet or a test targeted the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; through a class or &lt;code&gt;data-*&lt;/code&gt; attribute set on &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt;, target the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; or a parent element instead. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/responsive-images.html#layout-without-a-wrapper&quot;&gt;Layout without a wrapper&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.6.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-05-vue-image-kit-1-6-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-05-vue-image-kit-1-6-1"/>
    <updated>2026-10-05T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: since 1.6.0 &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; rendered a fragment on the server, so the &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;style&lt;/code&gt; and other attributes given to it were not applied to the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, and Vue warned &lt;code&gt;Extraneous non-props attributes (class) were passed to component but could not be automatically inherited because component renders fragment or text or teleport root nodes&lt;/code&gt;. A fragment is now rendered only for the one case that needs it — a lazy image with &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vimage.html#ssrplaceholder&quot;&gt;&lt;code&gt;ssrPlaceholder&lt;/code&gt;&lt;/a&gt; and a ready preview — and there the attributes are passed to the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; explicitly. Every other server and client state is a single element again.&lt;/li&gt;
&lt;li&gt;Fixed: the &lt;code&gt;class&lt;/code&gt; is also put on the image inside the &lt;code&gt;&amp;lt;noscript&amp;gt;&lt;/code&gt; fallback of a deferred image, so it is laid out the same without JavaScript.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.3.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-devtoolz-0-3-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-devtoolz-0-3-2"/>
    <updated>2026-10-03T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: every option that takes a comma-separated list (&lt;code&gt;--ext&lt;/code&gt;, &lt;code&gt;--type&lt;/code&gt;, &lt;code&gt;--tags&lt;/code&gt;, &lt;code&gt;--methods&lt;/code&gt;, &lt;code&gt;--lang&lt;/code&gt;, &lt;code&gt;--test-suffix&lt;/code&gt;, &lt;code&gt;--source-ext&lt;/code&gt;) now also accepts spaces, and &lt;code&gt;image-hash&lt;/code&gt; accepts space-separated paths. PowerShell passes &lt;code&gt;a,b&lt;/code&gt; to a program as one argument &lt;code&gt;a b&lt;/code&gt;, which these options used to reject, so &lt;code&gt;devtoolz image-hash -t blurhash,thumbhash,color&lt;/code&gt; failed there.&lt;/li&gt;
&lt;li&gt;Fixed: the package is now built automatically before every publish (&lt;code&gt;prepublishOnly&lt;/code&gt;). Version 0.3.1 shipped a stale build without the fix above.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.3.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-devtoolz-0-3-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-devtoolz-0-3-1"/>
    <updated>2026-10-03T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Note: this release was published with a build that predates the list fix described under 0.3.2, so the fix is not in it. Use 0.3.2.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.3.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-devtoolz-0-3-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-devtoolz-0-3-0"/>
    <updated>2026-10-03T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: the &lt;code&gt;image-hash&lt;/code&gt; command generates &lt;a href=&quot;https://blurha.sh&quot; target=&quot;_blank&quot; rel=&quot;noreferrer&quot;&gt;blurhash&lt;/a&gt; and &lt;a href=&quot;https://evanw.github.io/thumbhash/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer&quot;&gt;thumbhash&lt;/a&gt; placeholders for raster images. It takes files and/or directories (comma-separated too, &lt;code&gt;-r&lt;/code&gt; for subdirectories) and prints to stdout, writes one file (&lt;code&gt;-o&lt;/code&gt;), or writes a file per image (&lt;code&gt;--per-file&lt;/code&gt;, &lt;code&gt;--out-dir&lt;/code&gt;, with &lt;code&gt;--suffix&lt;/code&gt; and &lt;code&gt;--out-ext&lt;/code&gt; for the names, for example &lt;code&gt;photo.jpg.blurhash.txt&lt;/code&gt;). Formats are &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;plain&lt;/code&gt;, &lt;code&gt;csv&lt;/code&gt;, &lt;code&gt;ts&lt;/code&gt; and &lt;code&gt;js&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-hash.html&quot;&gt;Image Hash&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-hash&lt;/code&gt; needs the native &lt;code&gt;sharp&lt;/code&gt; library, which is not installed with devtoolz. The first run offers to install it into &lt;code&gt;~/.devtoolz/deps&lt;/code&gt; (&lt;code&gt;-y&lt;/code&gt;/&lt;code&gt;--yes&lt;/code&gt; agrees up front; without a terminal and without &lt;code&gt;-y&lt;/code&gt; the command stops with a message). A &lt;code&gt;sharp&lt;/code&gt; already installed next to devtoolz is used as is.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-hash&lt;/code&gt; can also produce the dominant color (&lt;code&gt;color&lt;/code&gt;) and a tiny PNG data URI (&lt;code&gt;preview&lt;/code&gt;) with &lt;code&gt;-t&lt;/code&gt;, and picks blurhash components by aspect ratio with &lt;code&gt;--components auto&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-hash&lt;/code&gt; accepts &lt;code&gt;http(s)&lt;/code&gt; URLs and a path list from a file or stdin (&lt;code&gt;--files-from&lt;/code&gt;), and reshapes the keys in its output with &lt;code&gt;--key-base&lt;/code&gt; and &lt;code&gt;--key-prefix&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-hash --cache&lt;/code&gt; skips unchanged images, &lt;code&gt;--update&lt;/code&gt; merges into an existing output file and &lt;code&gt;--prune&lt;/code&gt; drops entries whose image is gone, and &lt;code&gt;--check&lt;/code&gt; fails (exit 1) when output files are missing or stale — made for CI. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/mediatoolz/guide/image-hash.html#keeping-an-output-file-up-to-date&quot;&gt;Keeping an output file up to date&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-hash&lt;/code&gt; shows a progress counter in a terminal, finds a &lt;code&gt;sharp&lt;/code&gt; already installed in the project it runs in, hashes CMYK images correctly, refuses truncated files and images over &lt;code&gt;--max-pixels&lt;/code&gt;, and explains such failures in plain words.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;image-hash --dry-run&lt;/code&gt; writes nothing and shows the result as a table, with the files that would be written listed under it.&lt;/li&gt;
&lt;li&gt;New: colored output for every command, from one shared palette — paths, &lt;code&gt;:line:column&lt;/code&gt; positions, names, headings, hints and the &lt;code&gt;full-check&lt;/code&gt; status icons each have their own color. &lt;code&gt;--color&lt;/code&gt; (or &lt;code&gt;FORCE_COLOR&lt;/code&gt;) forces color when output is piped or in CI; &lt;code&gt;NO_COLOR&lt;/code&gt;, &lt;code&gt;TERM=dumb&lt;/code&gt; and &lt;code&gt;--plain&lt;/code&gt; keep it off. The text of every report is unchanged, only escape codes are added. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/overview.html#output-colors&quot;&gt;Output &amp;amp; colors&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Changed: &lt;code&gt;--quiet&lt;/code&gt; no longer turns color off, it only drops the banner and the output of a clean run. &lt;code&gt;--plain&lt;/code&gt; still turns off color, banner and celebration copy together.&lt;/li&gt;
&lt;li&gt;Added to the programmatic API: &lt;code&gt;runImageHash&lt;/code&gt; and &lt;code&gt;renderImageHashReport&lt;/code&gt;, with their option, report and entry types.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.6.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-vue-image-kit-1-6-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-vue-image-kit-1-6-0"/>
    <updated>2026-10-03T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Automatic placeholders for imported images. &lt;code&gt;placeholders: { imports: true }&lt;/code&gt; (in Nuxt: &lt;code&gt;vueImageKit: { placeholders: { imports: true } }&lt;/code&gt;) computes a placeholder at build time for every image a script or single-file component imports with a default &lt;code&gt;import&lt;/code&gt; — including the imports Vue generates from &lt;code&gt;src=&amp;quot;…&amp;quot;&lt;/code&gt; in a template and the ones &lt;code&gt;import.meta.glob(…, { eager: true })&lt;/code&gt; expands to. No &lt;code&gt;?placeholder&lt;/code&gt; query and no template edits: the placeholder is registered under the imported value itself (the dev URL or the hashed build URL), so &lt;code&gt;&amp;lt;VImage :src=&amp;quot;hero&amp;quot; /&amp;gt;&lt;/code&gt; finds its blur and size on its own, in dev, in the build and during server rendering. &lt;code&gt;mode&lt;/code&gt;, &lt;code&gt;extensions&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt; tune it. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#a-placeholder-for-every-imported-image&quot;&gt;A placeholder for every imported image&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New export &lt;code&gt;registerPlaceholder(src, data)&lt;/code&gt;. &lt;code&gt;VImage&lt;/code&gt;, &lt;code&gt;v-lazy-img&lt;/code&gt; and &lt;code&gt;useBackgroundImage()&lt;/code&gt; look a &lt;code&gt;src&lt;/code&gt; up in that registry after the &lt;code&gt;placeholders&lt;/code&gt; manifest, so no manifest has to be provided.&lt;/li&gt;
&lt;li&gt;A corrupt raster image no longer fails the build when its placeholder is computed through the rewritten imports: it logs a warning and gets none.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; prop &lt;code&gt;ssrPlaceholder&lt;/code&gt; (opt-in, default &lt;code&gt;false&lt;/code&gt;). The server-rendered &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; gets a ready preview (a &lt;code&gt;data:&lt;/code&gt; URL from &lt;code&gt;placeholder&lt;/code&gt;, &lt;code&gt;image.placeholder&lt;/code&gt; or the registry) as its CSS background, so the picture has a blur before any JavaScript runs; without the prop nothing changes. A lazy image is also held back: the server sends a transparent pixel instead of the real &lt;code&gt;src&lt;/code&gt; and puts the real &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; into a &lt;code&gt;&amp;lt;noscript&amp;gt;&lt;/code&gt;, so the heavy file is only downloaded when the image nears the viewport, while crawlers and visitors without JavaScript still get it (an eager image — &lt;code&gt;lazy=&amp;quot;false&amp;quot;&lt;/code&gt; or &lt;code&gt;priority&lt;/code&gt; — keeps its &lt;code&gt;src&lt;/code&gt;). The preview keeps showing under the image after hydration, and server and client render the same output, so there is no hydration mismatch. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/placeholders.html#preview-in-the-server-rendered-html&quot;&gt;Preview in the server-rendered HTML&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New option &lt;code&gt;placeholders.imports.preview&lt;/code&gt; (&lt;code&gt;true&lt;/code&gt;, or a list of path patterns: a directory, an exact file, a part of a path or a glob such as &lt;code&gt;src/**/hero-*.webp&lt;/code&gt;, compared with the file's real path from the project root, so aliased imports work). &lt;code&gt;exclude&lt;/code&gt; takes the same patterns. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#choosing-images-by-path&quot;&gt;Choosing images by path&lt;/a&gt;. The plugin also renders a ready preview for the imported images and registers it, so &lt;code&gt;&amp;lt;VImage :src=&amp;quot;hero&amp;quot; ssr-placeholder /&amp;gt;&lt;/code&gt; is all a template needs. Off by default; needs the &lt;code&gt;thumbhash&lt;/code&gt; package at build time. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#a-ready-preview-for-server-rendering&quot;&gt;A ready preview for server rendering&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The registry entries and &lt;code&gt;registerPlaceholder()&lt;/code&gt; accept a ready preview (&lt;code&gt;placeholder&lt;/code&gt; or &lt;code&gt;preview&lt;/code&gt;). The registry lives in &lt;code&gt;globalThis&lt;/code&gt;, so the server and the client copy of the package share it.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.5.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-vue-image-kit-1-5-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-vue-image-kit-1-5-0"/>
    <updated>2026-10-03T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Placeholder imports take a list of fields. &lt;code&gt;?placeholder=color,blurhash&lt;/code&gt; returns exactly those fields; the fields are &lt;code&gt;blurhash&lt;/code&gt;, &lt;code&gt;thumbhash&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;preview&lt;/code&gt; (a tiny PNG as a data URI), &lt;code&gt;aspect&lt;/code&gt; (&lt;code&gt;width / height&lt;/code&gt;) and &lt;code&gt;all&lt;/code&gt;, in any order. &lt;code&gt;&amp;amp;shape=raw&lt;/code&gt; returns the names as listed (with &lt;code&gt;size&lt;/code&gt; as an object) instead of &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; prop names. The older single values (&lt;code&gt;?placeholder&lt;/code&gt;, &lt;code&gt;=blurhash&lt;/code&gt;, &lt;code&gt;=thumbhash&lt;/code&gt;, &lt;code&gt;=color&lt;/code&gt;) keep their shape. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#choosing-what-to-compute&quot;&gt;Choosing what to compute&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;One value at a time: &lt;code&gt;?color&lt;/code&gt;, &lt;code&gt;?size&lt;/code&gt;, &lt;code&gt;?aspect&lt;/code&gt; and &lt;code&gt;?preview&lt;/code&gt; next to the existing &lt;code&gt;?blurhash&lt;/code&gt; and &lt;code&gt;?thumbhash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Settings for one import: &lt;code&gt;?blurhash&amp;amp;components=6x4&lt;/code&gt;, &lt;code&gt;&amp;amp;sample=64&lt;/code&gt;, &lt;code&gt;&amp;amp;strategy=average&lt;/code&gt;. They never touch the shared cache or the manifest.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;types&lt;/code&gt; option of the Vite plugin. A TypeScript module pattern allows a single &lt;code&gt;*&lt;/code&gt;, so an import with a list or with settings cannot be typed by the bundled declarations; with &lt;code&gt;types: true&lt;/code&gt; the plugin writes &lt;code&gt;src/vik-imports.d.ts&lt;/code&gt; for every such import it sees (a path can be given instead), typed loosely with optional fields.&lt;/li&gt;
&lt;li&gt;The bundled declarations (&lt;code&gt;@macrulez/vue-image-kit/vite/client&lt;/code&gt;) gain &lt;code&gt;?color&lt;/code&gt;, &lt;code&gt;?size&lt;/code&gt;, &lt;code&gt;?preview&lt;/code&gt; and &lt;code&gt;?aspect&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A new scalar name is taken only as a bare flag (&lt;code&gt;?size&lt;/code&gt;, not &lt;code&gt;?size=large&lt;/code&gt;), so another plugin's parameter with the same name is left alone.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.4.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-vue-image-kit-1-4-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-03-vue-image-kit-1-4-1"/>
    <updated>2026-10-03T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: in &lt;code&gt;vite dev&lt;/code&gt; the plugin could regenerate images in an endless loop. A hot update ran &lt;code&gt;generate()&lt;/code&gt; for any image file that changed, including the files &lt;code&gt;generate()&lt;/code&gt; itself wrote to &lt;code&gt;output&lt;/code&gt;, and with &lt;code&gt;incremental: false&lt;/code&gt; every run rewrote them, which started the next run — hundreds of runs a second. A hot update now runs only for an image inside &lt;code&gt;input&lt;/code&gt; and never for one inside &lt;code&gt;output&lt;/code&gt;, and runs no longer overlap: changes that arrive during a run collapse into one follow-up run. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html&quot;&gt;Vite Plugin&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Fixed: an &lt;code&gt;output&lt;/code&gt; folder inside &lt;code&gt;input&lt;/code&gt; is skipped when &lt;code&gt;input&lt;/code&gt; is scanned, instead of being fed back in as source images.&lt;/li&gt;
&lt;li&gt;Fixed: the dev server no longer reloads the page for every generated file; the placeholders manifest watches only the folders listed in &lt;code&gt;placeholders.dirs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fixed: a huge SVG (for example 30000×30000) made &lt;code&gt;?placeholder&lt;/code&gt; fail with sharp's pixel limit. The size is now read from the file's own &lt;code&gt;width&lt;/code&gt;/&lt;code&gt;height&lt;/code&gt;/&lt;code&gt;viewBox&lt;/code&gt;, and the color is computed from a small render.&lt;/li&gt;
&lt;li&gt;Fixed: a corrupt SVG failed the whole build on &lt;code&gt;?placeholder&lt;/code&gt;. It now warns and returns the declared size (or an empty object); a corrupt raster image still fails.&lt;/li&gt;
&lt;li&gt;Changed: &lt;code&gt;?blurhash&lt;/code&gt; and &lt;code&gt;?thumbhash&lt;/code&gt; on an SVG print a warning that a vector has only a color and point to &lt;code&gt;?placeholder&lt;/code&gt;, instead of silently returning an empty string.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Responsive Media 2.2.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-2-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-2-2"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Changed: the shared &lt;code&gt;responsiveState&lt;/code&gt; object, created once for the whole package, used to be created the moment any part of the package was loaded, so a bundler could not remove it. It is now created in a separate source file, and the package declares &lt;code&gt;sideEffects: false&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;. A bundler no longer keeps the shared state when only a part of the package is imported: &lt;code&gt;useMediaQuery&lt;/code&gt; from &lt;code&gt;responsive-media/vue&lt;/code&gt; fell from about 6.7 kB to 0.6 kB minified, and &lt;code&gt;responsive-media/container&lt;/code&gt; from 7.7 kB to 6.8 kB. Behavior and public API are unchanged.&lt;/li&gt;
&lt;li&gt;Added: &lt;code&gt;npm run size&lt;/code&gt; in the package repository measures every entry point and typical imports. A test guards the tree-shaking result. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/reference.html&quot;&gt;Reference&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Responsive Media 2.2.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-2-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-2-1"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: with deferred hydration, a component that hydrates later than the first tick after mounting — an async component, a lazily hydrated section — met the real state instead of the server's and mismatched. The Vue plugin now takes &lt;code&gt;commit: 'manual'&lt;/code&gt;: the server's values stay until &lt;code&gt;commitHydration()&lt;/code&gt; is called, with &lt;code&gt;commitTimeout&lt;/code&gt; (10 seconds by default) as a fallback, and &lt;code&gt;defineResponsive()&lt;/code&gt; returns &lt;code&gt;commitHydration&lt;/code&gt; next to &lt;code&gt;plugin&lt;/code&gt;. The Nuxt module uses it: it commits when Nuxt reports &lt;code&gt;app:suspense:resolve&lt;/code&gt;, that is, when the page has finished hydrating. The default for plain Vue stays &lt;code&gt;'auto'&lt;/code&gt;, the next tick after mounting. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/ssr-hydration.html&quot;&gt;SSR &amp;amp; Hydration&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Responsive Media 2.2.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-2-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-2-0"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: hydration without a mismatch. In Vue, &lt;code&gt;defineResponsive()&lt;/code&gt; takes &lt;code&gt;hydration: 'deferred'&lt;/code&gt;: while the app mounts over server-rendered markup, the plugin keeps the server's values and applies the real ones on the next tick, so Vue reports no hydration mismatch. A client-only app is never deferred. In React the hooks now return the server snapshot (&lt;code&gt;getSsrState()&lt;/code&gt;) as &lt;code&gt;getServerSnapshot&lt;/code&gt;, so hydration no longer ends in a recoverable error when the browser's size differs from &lt;code&gt;ssrState&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/ssr-hydration.html&quot;&gt;SSR &amp;amp; Hydration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: request hints for the server. &lt;code&gt;resolveSsrState(config, input, options?)&lt;/code&gt; chooses the server state from a &lt;code&gt;cookie&lt;/code&gt; (the browser's own &lt;code&gt;&amp;lt;width&amp;gt;x&amp;lt;height&amp;gt;&lt;/code&gt;) and a &lt;code&gt;user-agent&lt;/code&gt; (&lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;tablet&lt;/code&gt; or &lt;code&gt;desktop&lt;/code&gt;), with &lt;code&gt;detectDevice()&lt;/code&gt;, &lt;code&gt;serializeViewportCookie()&lt;/code&gt;, &lt;code&gt;parseViewportCookie()&lt;/code&gt;, &lt;code&gt;statesFromSize()&lt;/code&gt; and &lt;code&gt;getSsrState()&lt;/code&gt; as the pieces. In Vue the plugin takes the result as &lt;code&gt;app.use(plugin, { ssrState })&lt;/code&gt;, and on the server it gives every app its own state, so concurrent requests no longer share one.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;useMediaQuery()&lt;/code&gt; in Vue accepts a string, a ref or a getter, and re-subscribes when the query changes.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;useResponsiveValue(map, fallback?)&lt;/code&gt; in Vue and React — the value of the first active breakpoint in &lt;code&gt;map&lt;/code&gt;; typed by the config when it comes from &lt;code&gt;defineResponsive()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;useUserPreferences()&lt;/code&gt; in Vue and React — &lt;code&gt;dark&lt;/code&gt;, &lt;code&gt;light&lt;/code&gt;, &lt;code&gt;reducedMotion&lt;/code&gt;, &lt;code&gt;highContrast&lt;/code&gt;, &lt;code&gt;lowContrast&lt;/code&gt;, &lt;code&gt;noHover&lt;/code&gt;, &lt;code&gt;coarsePointer&lt;/code&gt;, &lt;code&gt;forcedColors&lt;/code&gt; and &lt;code&gt;print&lt;/code&gt; over the accessibility preset, with nothing to configure; and &lt;code&gt;getUserPreferencesState()&lt;/code&gt; for plain JavaScript.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;useViewportSize(options?)&lt;/code&gt; in Vue and React, and &lt;code&gt;getViewportSize()&lt;/code&gt; / &lt;code&gt;subscribeViewportSize()&lt;/code&gt; in the core — the window size as numbers, throttled.&lt;/li&gt;
&lt;li&gt;New: CSS from the same config — &lt;code&gt;toMediaQueries()&lt;/code&gt;, &lt;code&gt;toScssModule()&lt;/code&gt;, &lt;code&gt;toScssMap()&lt;/code&gt;, &lt;code&gt;toCustomMedia()&lt;/code&gt; and &lt;code&gt;toTailwindScreens()&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/css-integration.html&quot;&gt;CSS Integration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;responsive-media/testing&lt;/code&gt; — &lt;code&gt;createViewportMock()&lt;/code&gt; replaces &lt;code&gt;window.matchMedia&lt;/code&gt; with a controllable viewport (&lt;code&gt;setViewport()&lt;/code&gt;, &lt;code&gt;setFeature()&lt;/code&gt;), and &lt;code&gt;evaluateMediaQuery()&lt;/code&gt; is the evaluator on its own. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/testing.html&quot;&gt;Testing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New in the Nuxt module: &lt;code&gt;hydration&lt;/code&gt; (default &lt;code&gt;'deferred'&lt;/code&gt;), &lt;code&gt;ssrHints&lt;/code&gt; (&lt;code&gt;'cookie'&lt;/code&gt;, &lt;code&gt;'user-agent'&lt;/code&gt;), &lt;code&gt;ssrDevices&lt;/code&gt;, &lt;code&gt;cookie&lt;/code&gt;, &lt;code&gt;devBadge&lt;/code&gt; (a breakpoint badge in development) and &lt;code&gt;css&lt;/code&gt; (&lt;code&gt;scss&lt;/code&gt;, &lt;code&gt;customMedia&lt;/code&gt; — generated stylesheet files). &lt;code&gt;useResponsiveValue&lt;/code&gt;, &lt;code&gt;useUserPreferences&lt;/code&gt; and &lt;code&gt;useViewportSize&lt;/code&gt; are auto-imported too. The &lt;code&gt;responsive&lt;/code&gt; key of &lt;code&gt;nuxt.config.ts&lt;/code&gt; is now typed, so the editor completes and checks it. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/nuxt-integration.html&quot;&gt;Nuxt Integration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Changed: the Nuxt module now defaults to &lt;code&gt;hydration: 'deferred'&lt;/code&gt;, so the first client render uses the server's values and the real ones arrive right after mounting. Set &lt;code&gt;hydration: 'immediate'&lt;/code&gt; to keep the 2.1 behavior.&lt;/li&gt;
&lt;li&gt;Fixed: React &lt;code&gt;useResponsive()&lt;/code&gt; returned the real state as its server snapshot, which made hydration mismatch whenever the browser's size differed from the server's guess. It now returns the server snapshot.&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/other-frameworks.html&quot;&gt;Other Frameworks&lt;/a&gt; shows Svelte, Solid and Angular on the existing state object, which already follows the store contract.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Responsive Media 2.1.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-1-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-responsive-media-2-1-0"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: the &lt;code&gt;responsive-media/nuxt&lt;/code&gt; Nuxt module. Describe your breakpoints once in
the &lt;code&gt;responsive&lt;/code&gt; key of &lt;code&gt;nuxt.config.ts&lt;/code&gt; (&lt;code&gt;breakpoints&lt;/code&gt;, &lt;code&gt;order&lt;/code&gt;, &lt;code&gt;debounce&lt;/code&gt;,
&lt;code&gt;ssrState&lt;/code&gt;); &lt;code&gt;useResponsive()&lt;/code&gt; and &lt;code&gt;useBreakpoints()&lt;/code&gt; are auto-imported and
typed from those breakpoints, &lt;code&gt;useMediaQuery()&lt;/code&gt; and &lt;code&gt;useContainerState()&lt;/code&gt; are
auto-imported too, and a plugin installs the shared state on the app. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/responsive-media/guide/nuxt-integration.html&quot;&gt;Nuxt Integration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;defineResponsive(config, options?)&lt;/code&gt; in &lt;code&gt;responsive-media/vue&lt;/code&gt; and
&lt;code&gt;responsive-media/react&lt;/code&gt;. It applies the config and returns &lt;code&gt;useResponsive&lt;/code&gt; and
&lt;code&gt;useBreakpoints&lt;/code&gt; (plus a &lt;code&gt;plugin&lt;/code&gt; in Vue) whose state and breakpoint keys are
inferred from &lt;code&gt;config&lt;/code&gt;, so a typo such as &lt;code&gt;isAbove('nope')&lt;/code&gt; is a compile error
and no generic has to be written by hand.&lt;/li&gt;
&lt;li&gt;New: the &lt;code&gt;ssrState&lt;/code&gt; option of &lt;code&gt;SetConfigOptions&lt;/code&gt;. Whenever &lt;code&gt;matchMedia&lt;/code&gt; or
&lt;code&gt;ResizeObserver&lt;/code&gt; is unavailable — on the server — the listed keys take these
values instead of &lt;code&gt;false&lt;/code&gt;, so the server can render a layout. It works for
&lt;code&gt;createResponsiveState()&lt;/code&gt;, &lt;code&gt;createContainerState()&lt;/code&gt;, &lt;code&gt;setResponsiveConfig()&lt;/code&gt; and
the Nuxt module.&lt;/li&gt;
&lt;li&gt;Types: &lt;code&gt;useContainerState()&lt;/code&gt; infers the keys of its returned state from the
config (Vue and React), and &lt;code&gt;BreakpointHelpers&lt;/code&gt; takes an optional key type,
&lt;code&gt;BreakpointHelpers&amp;lt;K extends string = string&amp;gt;&lt;/code&gt;. Existing code keeps compiling.&lt;/li&gt;
&lt;li&gt;Fixed: the Vue &lt;code&gt;useBreakpoints()&lt;/code&gt; ignored the configured &lt;code&gt;order&lt;/code&gt; when the state
was provided by &lt;code&gt;ResponsivePlugin&lt;/code&gt;, and fell back to the order of the config
keys — so &lt;code&gt;current&lt;/code&gt; could name the wrong breakpoint when the two orders
differed. The configured &lt;code&gt;order&lt;/code&gt; is now used.&lt;/li&gt;
&lt;li&gt;New optional peer dependency: &lt;code&gt;@nuxt/kit&lt;/code&gt; (&lt;code&gt;^3.9.0 || ^4.0.0&lt;/code&gt;), needed only for
&lt;code&gt;responsive-media/nuxt&lt;/code&gt;; Nuxt already provides it.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Visual Linker 0.4.3</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-3</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-3"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Changed (default behavior): &lt;code&gt;hover&lt;/code&gt; and &lt;code&gt;highlight&lt;/code&gt; are now opt-in.&lt;/strong&gt; A line used to react to the pointer in every diagram: it took the &lt;code&gt;hover&lt;/code&gt; state with a width bump, showed a pointer cursor over its click area, and hovering a block lit up its connections. Now none of that happens until you turn it on, so a diagram that is only looked at stays still. The pointer cursor appears on a line only when hover is on for it or when it is selectable. To get the previous behavior, set &lt;code&gt;interaction: { hover: true, highlight: true }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New: &lt;code&gt;interaction.hover&lt;/code&gt; and &lt;code&gt;interaction.highlight&lt;/code&gt;.&lt;/strong&gt; Two independent flags, both &lt;code&gt;false&lt;/code&gt; by default. &lt;code&gt;hover&lt;/code&gt; is the pointer over a line, &lt;code&gt;highlight&lt;/code&gt; is the pointer over a block lighting up its connections. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/states.html#turning-hover-and-highlight-on&quot;&gt;Visual States&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New: &lt;code&gt;hoverable&lt;/code&gt; on a connection and &lt;code&gt;highlightable&lt;/code&gt; on a block.&lt;/strong&gt; Each turns its mode on or off for one entity, and the local value wins over the global one. &lt;code&gt;highlightable&lt;/code&gt; is also an option of &lt;code&gt;v-vl-block&lt;/code&gt;, a field of the &lt;code&gt;blocks&lt;/code&gt; prop and the &lt;code&gt;data-vl-highlightable&lt;/code&gt; attribute.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unchanged:&lt;/strong&gt; the events &lt;code&gt;connection:mouseenter&lt;/code&gt;, &lt;code&gt;connection:mouseleave&lt;/code&gt;, &lt;code&gt;connection:click&lt;/code&gt;, &lt;code&gt;block:mouseenter&lt;/code&gt; and &lt;code&gt;block:mouseleave&lt;/code&gt; fire as before, and the &lt;code&gt;selected&lt;/code&gt; and &lt;code&gt;focus&lt;/code&gt; states, selection and keyboard operation do not depend on the new flags. A &lt;code&gt;hover&lt;/code&gt; or &lt;code&gt;highlight&lt;/code&gt; bucket does nothing while its mode is off. Both flags can be changed with &lt;code&gt;setConfig&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Visual Linker 0.4.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-2"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A port anchored to a block is no longer pinned by a clipping wrapper inside that block.&lt;/strong&gt; For a port with &lt;code&gt;anchorBlockId&lt;/code&gt; or &lt;code&gt;anchorEl&lt;/code&gt;, the point is drawn on the border of the anchor, but whether it is clipped was decided by that point. A row inside an element with &lt;code&gt;overflow: hidden&lt;/code&gt; — a rounded segmented control, a card — inside a padded block, anchored to the block's bottom border, has its point below the wrapper, so its line was pulled up to the wrapper's edge and lost its marker and port dot. Whether such a port is clipped is now decided by its own element: a row that is visible keeps its point on the anchor's border, and a row that has scrolled out of view is pinned as before. Ports without an anchor are unchanged. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/scrolling-containers.html&quot;&gt;Scrolling Containers&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Visual Linker 0.4.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-1"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strings are accepted wherever an enum was.&lt;/strong&gt; The types of &lt;code&gt;lines.curve&lt;/code&gt;, a marker's &lt;code&gt;shape&lt;/code&gt; and &lt;code&gt;orient&lt;/code&gt;, and a port's &lt;code&gt;side&lt;/code&gt; were unions of enum members, so TypeScript rejected &lt;code&gt;curve: 'straight'&lt;/code&gt; or &lt;code&gt;shape: 'arrow'&lt;/code&gt; with &lt;code&gt;Type '&amp;quot;straight&amp;quot;' is not assignable to type 'ConnectionCurve'&lt;/code&gt;, although both worked at runtime. They are now the plain string unions (&lt;code&gt;'bezier' | 'straight' | 'smoothstep'&lt;/code&gt;, &lt;code&gt;'circle' | 'square' | 'diamond' | 'arrow'&lt;/code&gt;, &lt;code&gt;'top' | 'right' | 'bottom' | 'left'&lt;/code&gt;, &lt;code&gt;'auto' | 'fixed'&lt;/code&gt;) and still accept the enum members, so existing code keeps compiling. &lt;code&gt;VLConnectionCurveEnum&lt;/code&gt;, &lt;code&gt;VLMarkerShapeEnum&lt;/code&gt;, &lt;code&gt;VLFixedSideEnum&lt;/code&gt; and &lt;code&gt;VLOrientEnum&lt;/code&gt; are still exported. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/configuration.html&quot;&gt;Configuration&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Visual Linker 0.4.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-02-visual-linker-0-4-0"/>
    <updated>2026-10-02T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (all packages):&lt;/strong&gt; the flat &lt;code&gt;VisualLinkerOptions&lt;/code&gt; is replaced by one structured &lt;code&gt;VisualLinkerConfig&lt;/code&gt;, grouped by what it styles: &lt;code&gt;theme&lt;/code&gt;, &lt;code&gt;lines&lt;/code&gt;, &lt;code&gt;markers&lt;/code&gt;, &lt;code&gt;ports&lt;/code&gt;, &lt;code&gt;labels&lt;/code&gt;, &lt;code&gt;blocks&lt;/code&gt; and &lt;code&gt;interaction&lt;/code&gt;. Every &lt;code&gt;defaultXxx&lt;/code&gt; option is gone; each setting has a place in a group. A connection's &lt;code&gt;style&lt;/code&gt; has the same shape as the &lt;code&gt;lines&lt;/code&gt; group, plus &lt;code&gt;markers: { start, end }&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/configuration.html&quot;&gt;Configuration&lt;/a&gt;. The old names map to the new ones like this:&lt;/p&gt;
&lt;table tabindex=&quot;0&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;0.3.x&lt;/th&gt;
&lt;th&gt;0.4.0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultCurve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lines.curve&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultCurvature&lt;/code&gt;, &lt;code&gt;defaultCurveMinReach&lt;/code&gt;, &lt;code&gt;defaultCurveMaxReach&lt;/code&gt;, &lt;code&gt;defaultCurveAngleBlend&lt;/code&gt;, &lt;code&gt;defaultCurveAngleMaxOffset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lines.bezier.curvature&lt;/code&gt;, &lt;code&gt;minReach&lt;/code&gt;, &lt;code&gt;maxReach&lt;/code&gt;, &lt;code&gt;angleBlend&lt;/code&gt;, &lt;code&gt;angleMaxOffset&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultCornerRadius&lt;/code&gt;, &lt;code&gt;defaultMaxTrunkReach&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lines.smoothstep.cornerRadius&lt;/code&gt;, &lt;code&gt;lines.smoothstep.maxTrunkReach&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;avoidObstacles&lt;/code&gt;, &lt;code&gt;obstaclePadding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lines.routing.avoidObstacles&lt;/code&gt;, &lt;code&gt;lines.routing.padding&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jumps&lt;/code&gt;, &lt;code&gt;defaultAnimated&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lines.jumps&lt;/code&gt;, &lt;code&gt;lines.animated&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showPorts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ports.show&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultPortRadius&lt;/code&gt;, &lt;code&gt;defaultPortColor&lt;/code&gt;, &lt;code&gt;defaultPortStrokeColor&lt;/code&gt;, &lt;code&gt;defaultPortStrokeWidth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ports.radius&lt;/code&gt;, &lt;code&gt;ports.fill&lt;/code&gt;, &lt;code&gt;ports.stroke&lt;/code&gt;, &lt;code&gt;ports.strokeWidth&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultPortSpread&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ports.spread&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultCircleMarkerSize&lt;/code&gt;, &lt;code&gt;defaultSquareMarkerSize&lt;/code&gt;, &lt;code&gt;defaultDiamondMarkerSize&lt;/code&gt;, &lt;code&gt;defaultArrowMarkerSize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;markers.sizes.circle&lt;/code&gt;, &lt;code&gt;square&lt;/code&gt;, &lt;code&gt;diamond&lt;/code&gt;, &lt;code&gt;arrow&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draggable&lt;/code&gt;, &lt;code&gt;dragGridSize&lt;/code&gt;, &lt;code&gt;dragBounds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;blocks.draggable&lt;/code&gt;, &lt;code&gt;blocks.drag.grid&lt;/code&gt;, &lt;code&gt;blocks.drag.bounds&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;selectable&lt;/code&gt;, &lt;code&gt;clipToScrollParents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;interaction.selectable&lt;/code&gt;, &lt;code&gt;interaction.clipToScrollParents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style.curvature&lt;/code&gt;, &lt;code&gt;curveMinReach&lt;/code&gt;, &lt;code&gt;curveMaxReach&lt;/code&gt;, &lt;code&gt;curveAngleBlend&lt;/code&gt;, &lt;code&gt;curveAngleMaxOffset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style.bezier.curvature&lt;/code&gt;, &lt;code&gt;minReach&lt;/code&gt;, &lt;code&gt;maxReach&lt;/code&gt;, &lt;code&gt;angleBlend&lt;/code&gt;, &lt;code&gt;angleMaxOffset&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style.cornerRadius&lt;/code&gt;, &lt;code&gt;style.maxTrunkReach&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style.smoothstep.cornerRadius&lt;/code&gt;, &lt;code&gt;style.smoothstep.maxTrunkReach&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style.avoidObstacles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style.routing.avoidObstacles&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style.startMarker&lt;/code&gt;, &lt;code&gt;style.endMarker&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style.markers.start&lt;/code&gt;, &lt;code&gt;style.markers.end&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style.hoverStyle&lt;/code&gt;, &lt;code&gt;style.selectedStyle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style.hover&lt;/code&gt;, &lt;code&gt;style.selected&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hoverStyle.markerSize&lt;/code&gt;, &lt;code&gt;selectedStyle.markerSize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;size&lt;/code&gt; in the marker's own &lt;code&gt;hover&lt;/code&gt; and &lt;code&gt;selected&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VisualLinkerOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;VisualLinkerConfig&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (Vue):&lt;/strong&gt; the &lt;code&gt;options&lt;/code&gt; prop of &lt;code&gt;&amp;lt;VisualLinker&amp;gt;&lt;/code&gt; is now &lt;code&gt;config&lt;/code&gt;, and the &lt;code&gt;UseVisualLinkerOptions&lt;/code&gt; of &lt;code&gt;useVisualLinker()&lt;/code&gt; no longer extends the engine's options: it has &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;blocks&lt;/code&gt; and &lt;code&gt;connections&lt;/code&gt;. &lt;code&gt;config&lt;/code&gt; is reactive, so changing it redraws the diagram. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/component.html#config&quot;&gt;VisualLinker Component&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (Vue):&lt;/strong&gt; the shared configuration moves from a global object to Vue's &lt;code&gt;provide&lt;/code&gt;/&lt;code&gt;inject&lt;/code&gt;. &lt;code&gt;setVisualLinkerDefaults()&lt;/code&gt;, &lt;code&gt;resetVisualLinkerDefaults()&lt;/code&gt;, &lt;code&gt;visualLinkerDefaults&lt;/code&gt; and the &lt;code&gt;VisualLinkerDefaults&lt;/code&gt; type are removed. Pass the configuration to &lt;code&gt;app.use(VisualLinkerPlugin, { config })&lt;/code&gt;, and change it later through &lt;code&gt;useVisualLinkerConfig()&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/shared-config.html&quot;&gt;Shared Configuration&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (Nuxt):&lt;/strong&gt; the module options are the engine's configuration itself — the same &lt;code&gt;theme&lt;/code&gt;, &lt;code&gt;lines&lt;/code&gt;, &lt;code&gt;markers&lt;/code&gt;, &lt;code&gt;ports&lt;/code&gt;, &lt;code&gt;labels&lt;/code&gt;, &lt;code&gt;blocks&lt;/code&gt; and &lt;code&gt;interaction&lt;/code&gt; groups — instead of a separate flat list (&lt;code&gt;defaultCurve&lt;/code&gt;, &lt;code&gt;portRadius&lt;/code&gt;, &lt;code&gt;curvature&lt;/code&gt;, …). They must be JSON-serializable. The four settings the old list could not reach (&lt;code&gt;defaultCornerRadius&lt;/code&gt;, &lt;code&gt;defaultMaxTrunkReach&lt;/code&gt;, &lt;code&gt;draggable&lt;/code&gt;, &lt;code&gt;dragBounds&lt;/code&gt;) are now ordinary fields. The client-only plugin is gone; one universal plugin registers the directives and installs the configuration. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/nuxt-module.html&quot;&gt;Nuxt Module&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (core):&lt;/strong&gt; a marker configured in &lt;code&gt;markers.start&lt;/code&gt; or &lt;code&gt;markers.end&lt;/code&gt; replaces the built-in port dot at that end of every connection, as a marker set on a single connection always did. Marker colors now follow the theme's line colors too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; visual states for every visual entity. Lines, markers, ports and labels take &lt;code&gt;highlight&lt;/code&gt;, &lt;code&gt;hover&lt;/code&gt;, &lt;code&gt;selected&lt;/code&gt; and &lt;code&gt;focus&lt;/code&gt; buckets with the fields of the entity itself, stacked in that order over the base. A marker can change its &lt;code&gt;shape&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, colors, outline, &lt;code&gt;arrow&lt;/code&gt; or whole &lt;code&gt;svg&lt;/code&gt; in a state; a port can grow, a label can change its fill. Markers, ports and labels follow the state of their connection. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/states.html&quot;&gt;Visual States&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; the &lt;code&gt;highlight&lt;/code&gt; state. A hovered block now puts its connections into &lt;code&gt;highlight&lt;/code&gt;, apart from &lt;code&gt;hover&lt;/code&gt;, the pointer over the line itself. Until a &lt;code&gt;highlight&lt;/code&gt; bucket is set it looks the same as &lt;code&gt;hover&lt;/code&gt;, so existing configurations look as before.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;opacity&lt;/code&gt; for lines, markers, ports and labels, also per state. A marker without its own &lt;code&gt;opacity&lt;/code&gt; fades with its line, and an animated line multiplies it with its dimming.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; themes. A &lt;code&gt;theme&lt;/code&gt; is a set of color tokens — &lt;code&gt;line&lt;/code&gt;, &lt;code&gt;lineHover&lt;/code&gt;, &lt;code&gt;lineSelected&lt;/code&gt;, &lt;code&gt;selectedHalo&lt;/code&gt;, &lt;code&gt;focusRing&lt;/code&gt;, &lt;code&gt;portFill&lt;/code&gt;, &lt;code&gt;portStroke&lt;/code&gt;, &lt;code&gt;labelBackground&lt;/code&gt;, &lt;code&gt;labelBorder&lt;/code&gt;, &lt;code&gt;labelText&lt;/code&gt; — written to CSS variables. &lt;code&gt;lightTheme&lt;/code&gt;, &lt;code&gt;darkTheme&lt;/code&gt; and &lt;code&gt;defineTheme(overrides, base)&lt;/code&gt; are exported. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/themes.html&quot;&gt;Themes&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;labels&lt;/code&gt; group — &lt;code&gt;background&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;fontSize&lt;/code&gt;, &lt;code&gt;paddingX&lt;/code&gt;, &lt;code&gt;paddingY&lt;/code&gt; and &lt;code&gt;opacity&lt;/code&gt; of library-drawn labels, with states — and &lt;code&gt;ports.side&lt;/code&gt; and &lt;code&gt;ports.offset&lt;/code&gt; as the defaults for ports that set none of their own.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; the configuration can be changed while the engine runs. &lt;code&gt;setConfig(patch)&lt;/code&gt; deep-merges (a key set to &lt;code&gt;undefined&lt;/code&gt; is removed), &lt;code&gt;replaceConfig(next)&lt;/code&gt; replaces, &lt;code&gt;getConfig()&lt;/code&gt; returns a copy. Dragging and selection are attached or detached to match, and everything is redrawn. Also exported: &lt;code&gt;mergeConfig&lt;/code&gt;, &lt;code&gt;patchConfig&lt;/code&gt; and &lt;code&gt;mergeMarkerInputs&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; the shared configuration. &lt;code&gt;VisualLinkerPlugin&lt;/code&gt; takes &lt;code&gt;{ config }&lt;/code&gt;; &lt;code&gt;useVisualLinkerConfig()&lt;/code&gt; returns the reactive object; &lt;code&gt;provideVisualLinkerConfig(initial?)&lt;/code&gt; scopes one to a subtree; &lt;code&gt;installVisualLinkerConfig&lt;/code&gt;, &lt;code&gt;createSharedConfig&lt;/code&gt; and &lt;code&gt;VISUAL_LINKER_CONFIG_KEY&lt;/code&gt; serve integrations. Every diagram merges it under its own &lt;code&gt;config&lt;/code&gt;, and a change to it redraws all of them. Nothing is global, so several apps on a page do not interfere.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changed (core):&lt;/strong&gt; the &lt;code&gt;block:mouseenter&lt;/code&gt; event puts the block's connections into &lt;code&gt;highlight&lt;/code&gt; rather than &lt;code&gt;hover&lt;/code&gt;, and the line under the pointer is the only one in &lt;code&gt;hover&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.4.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-4-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-4-0"/>
    <updated>2026-10-01T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Placeholders for whole folders. &lt;code&gt;npx vue-image-kit placeholders --dir public/images&lt;/code&gt; computes every image of a folder, recursively, and adds it to
the manifest under the URL it is served at, so an image whose &lt;code&gt;src&lt;/code&gt; is built
at runtime (&lt;code&gt;:src=&amp;quot;category.image&amp;quot;&lt;/code&gt;) gets its placeholder too.
&lt;code&gt;--dir src/img=/assets/img&lt;/code&gt; maps a folder that is served from another URL,
and &lt;code&gt;--url&lt;/code&gt; adds a single remote or CDN image without &lt;code&gt;--remote&lt;/code&gt;. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/cli-placeholders.html#folders-and-urls&quot;&gt;Folders and URLs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Vite plugin builds the same manifest by itself. With
&lt;code&gt;vueImageKit({ generate: false, placeholders: { dirs: [...] } })&lt;/code&gt; it is the
virtual module &lt;code&gt;virtual:vue-image-kit/placeholders&lt;/code&gt;, rebuilt when a file in
those folders changes and cached between builds. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#placeholders-manifest-from-folders&quot;&gt;Placeholders manifest from folders&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Nuxt module registers it all. &lt;code&gt;vueImageKit: { placeholders: { dirs: [...] } }&lt;/code&gt; adds the Vite plugin and gives the manifest to every &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; —
no command to run and no entry in &lt;code&gt;vite.plugins&lt;/code&gt;. The old string form, a
path to a manifest file, still works, and &lt;code&gt;manifest&lt;/code&gt; merges such a file in.
See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/nuxt-module.html#module-options&quot;&gt;Module options&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New Vite imports that compute only a placeholder and write no files.
&lt;code&gt;import placeholder from './photo.jpg?placeholder'&lt;/code&gt; returns
&lt;code&gt;{ blurhash, placeholderColor, width, height }&lt;/code&gt; — the props of &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt;
itself, so &lt;code&gt;&amp;lt;VImage v-bind=&amp;quot;placeholder&amp;quot; /&amp;gt;&lt;/code&gt; is enough.
&lt;code&gt;?placeholder=thumbhash&lt;/code&gt; returns a ThumbHash instead of a BlurHash,
&lt;code&gt;?placeholder=color&lt;/code&gt; only the dominant color and the size, and the new
&lt;code&gt;?blurhash&lt;/code&gt; import returns just the BlurHash string, like &lt;code&gt;?thumbhash&lt;/code&gt;. They
also work through &lt;code&gt;import.meta.glob(..., { query: '?placeholder' })&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;generate: false&lt;/code&gt; option of the Vite plugin. The plugin then no longer
processes the whole &lt;code&gt;input&lt;/code&gt; folder on start and on hot updates; it only
answers &lt;code&gt;?vik&lt;/code&gt;, &lt;code&gt;?placeholder&lt;/code&gt;, &lt;code&gt;?blurhash&lt;/code&gt;, &lt;code&gt;?thumbhash&lt;/code&gt; and the virtual
manifest. &lt;code&gt;input&lt;/code&gt; doesn't have to exist. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#placeholders-only-no-resizing&quot;&gt;Placeholders only, no resizing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The hashes can be tuned: &lt;code&gt;--components 4x3&lt;/code&gt; (BlurHash components),
&lt;code&gt;--sample 100&lt;/code&gt; (the size the image is downscaled to before hashing) and
&lt;code&gt;--color dominant|average&lt;/code&gt; on the command, and &lt;code&gt;tuning: { components, sample, color }&lt;/code&gt; in the config file, the Vite plugin and the Nuxt module. The cache is
dropped when the tuning changes. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/vite-plugin.html#tuning-the-hashes&quot;&gt;Tuning the hashes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Vite plugin caches placeholders in the same file the &lt;code&gt;placeholders&lt;/code&gt;
command uses, so a repeated build only reads the images that changed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v-lazy-img&lt;/code&gt; and &lt;code&gt;useBackgroundImage()&lt;/code&gt; read the placeholders manifest. With
no &lt;code&gt;placeholder&lt;/code&gt; of their own they show the decoded blur and the dominant
color of the entry for their &lt;code&gt;src&lt;/code&gt; while the image loads, and the
&lt;code&gt;placeholders&lt;/code&gt; command fills the manifest for their static usages. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/cli-placeholders.html#v-lazy-img-and-usebackgroundimage&quot;&gt;v-lazy-img and useBackgroundImage()&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?thumbhash&lt;/code&gt; and &lt;code&gt;?blurhash&lt;/code&gt; now compute their values the same way as the
&lt;code&gt;placeholders&lt;/code&gt; command — BlurHash over a white background, ThumbHash fitted
into 100×100 — so the same image gets the same hash from either.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.3.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-3-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-3-2"/>
    <updated>2026-10-01T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;sources&lt;/code&gt; entry (art direction) can now carry its own placeholder —
&lt;code&gt;blurhash&lt;/code&gt;, &lt;code&gt;thumbhash&lt;/code&gt;, &lt;code&gt;placeholder&lt;/code&gt; or &lt;code&gt;placeholderColor&lt;/code&gt; next to &lt;code&gt;src&lt;/code&gt;,
or an &lt;code&gt;ImageMeta&lt;/code&gt; from a &lt;code&gt;?vik&lt;/code&gt; import. While that entry's breakpoint is
active, &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; shows its placeholder at its proportions instead of the
root image's, so a blurhash of a vertical photo is no longer stretched into
a horizontal tablet box. The matching entry replaces the root's whole
placeholder set; entries without a placeholder, and breakpoints with no
matching entry, keep using the root's. Placeholders manifest entries are
looked up by the source's &lt;code&gt;src&lt;/code&gt; as well. New exported type:
&lt;code&gt;SourcePlaceholder&lt;/code&gt;. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/responsive-images.html#per-breakpoint-placeholders&quot;&gt;Per-breakpoint placeholders&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx vue-image-kit placeholders&lt;/code&gt; now fills in &lt;code&gt;sources&lt;/code&gt; entries too. Every
statically resolvable entry of a literal &lt;code&gt;:sources=&amp;quot;{ … }&amp;quot;&lt;/code&gt; gets a
placeholder, even when the image's own &lt;code&gt;src&lt;/code&gt; is dynamic — through the
manifest, or written into the literal. Entries that already have a
placeholder are left alone. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/cli-placeholders.html#art-direction-sources&quot;&gt;Art-direction sources&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.3.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-3-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-3-1"/>
    <updated>2026-10-01T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npx vue-image-kit placeholders&lt;/code&gt; has a new &lt;code&gt;--replace&lt;/code&gt; flag. Until now the
command skipped every &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; that already had a placeholder. With
&lt;code&gt;--replace&lt;/code&gt;, it swaps that placeholder for a new one of the kind set by
&lt;code&gt;--mode&lt;/code&gt;. Only attributes with a plain value are replaced: &lt;code&gt;blurhash&lt;/code&gt;,
&lt;code&gt;thumbhash&lt;/code&gt;, &lt;code&gt;placeholder&lt;/code&gt;, &lt;code&gt;placeholder-color&lt;/code&gt; and &lt;code&gt;placeholder-mode&lt;/code&gt;.
Bound values (such as &lt;code&gt;:thumbhash=&amp;quot;item.hash&amp;quot;&lt;/code&gt;) and &lt;code&gt;:image&lt;/code&gt; stay as they
are. See
&lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/cli-placeholders.html#replacing-existing-placeholders&quot;&gt;Replacing existing placeholders&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.3.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-3-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-vue-image-kit-1-3-0"/>
    <updated>2026-10-01T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New &lt;strong&gt;&lt;code&gt;npx vue-image-kit scan&lt;/code&gt;&lt;/strong&gt; command — a report of how vue-image-kit is
used across the project. It finds every &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; (in templates, JSX and
&lt;code&gt;h()&lt;/code&gt; calls, including locally renamed imports), every &lt;code&gt;v-lazy-img&lt;/code&gt; and
every &lt;code&gt;useImage()&lt;/code&gt;/&lt;code&gt;useBackgroundImage()&lt;/code&gt; call, works out where each image
comes from — a local import, a &lt;code&gt;public/&lt;/code&gt; path (checking the file exists), a
CDN URL with its provider, a remote URL, a &lt;code&gt;?vik&lt;/code&gt; import, or a dynamic
value — and prints usage per source and per file, prop statistics, and
warnings such as a missing &lt;code&gt;alt&lt;/code&gt;, no size, no placeholder or a missing
file. Reports can be written as JSON, Markdown or CSV, and &lt;code&gt;--fail-on&lt;/code&gt;
turns it into a CI check. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/cli-scan.html&quot;&gt;CLI — Usage Report&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New &lt;strong&gt;&lt;code&gt;npx vue-image-kit placeholders&lt;/code&gt;&lt;/strong&gt; command — computes a BlurHash, a
ThumbHash or the image's dominant color, plus its original size, for every
&lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; that has no placeholder yet. Local and &lt;code&gt;public/&lt;/code&gt; images are read
from disk; CDN and remote images are downloaded only with &lt;code&gt;--remote&lt;/code&gt;. The
result goes into a placeholders manifest for images the app can look up by
&lt;code&gt;src&lt;/code&gt;, or straight into the template — for local imports, and for the whole
project when no manifest is registered. Files with uncommitted changes are
never edited. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/vue-image-kit/guide/cli-placeholders.html&quot;&gt;CLI — Placeholders for Existing Images&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; can now take its placeholder and size from a &lt;strong&gt;placeholders
manifest&lt;/strong&gt; registered once with &lt;code&gt;app.use(VImageKitPlugin, { placeholders })&lt;/code&gt;
or the Nuxt module's new &lt;code&gt;placeholders&lt;/code&gt; option, instead of from per-usage
props. Explicit props and the &lt;code&gt;image&lt;/code&gt; prop still take precedence; apps
without a manifest are unaffected. New exports: &lt;code&gt;PLACEHOLDERS_KEY&lt;/code&gt;,
&lt;code&gt;PlaceholderEntry&lt;/code&gt;, &lt;code&gt;PlaceholderManifest&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;detectCdnProvider()&lt;/code&gt; in &lt;code&gt;@macrulez/vue-image-kit/cdn&lt;/code&gt; — names which
auto-detected CDN a URL belongs to.&lt;/li&gt;
&lt;li&gt;The CLI is now organized into commands — &lt;code&gt;generate&lt;/code&gt; (still the default),
&lt;code&gt;scan&lt;/code&gt; and &lt;code&gt;placeholders&lt;/code&gt; — each with its own &lt;code&gt;--help&lt;/code&gt;. When &lt;code&gt;sharp&lt;/code&gt; or
&lt;code&gt;thumbhash&lt;/code&gt; is missing, the CLI now shows the install command for npm,
pnpm and yarn.&lt;/li&gt;
&lt;li&gt;Fixed: ThumbHash generation (&lt;code&gt;generate --thumbhash&lt;/code&gt; and the Vite plugin's
&lt;code&gt;?thumbhash&lt;/code&gt;/&lt;code&gt;?vik&lt;/code&gt; imports) failed for portrait images — the image was
shrunk to 100px wide only, so anything taller than wide stayed over the
100×100 limit ThumbHash allows. Images are now fitted inside 100×100.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Visual Linker 0.3.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-visual-linker-0-3-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-10#2026-10-01-visual-linker-0-3-0"/>
    <updated>2026-10-01T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;selectable&lt;/code&gt; option — connections become focusable buttons (Tab order = the order of &lt;code&gt;connections&lt;/code&gt;) that can be selected by click or Enter/Space, with Ctrl/Cmd/Shift toggling within a multi-selection; Escape or a pointer press elsewhere clears the selection. Delete/Backspace emits &lt;code&gt;connection:delete-request&lt;/code&gt; and never removes data itself. New: &lt;code&gt;setSelectedConnections(ids)&lt;/code&gt;, the &lt;code&gt;connection:selectionchange&lt;/code&gt; event, &lt;code&gt;ConnectionStyle.selectedStyle&lt;/code&gt; and the &lt;code&gt;--vl-selected-color&lt;/code&gt; / &lt;code&gt;--vl-focus-color&lt;/code&gt; CSS variables. Every line now carries &lt;code&gt;role=&amp;quot;img&amp;quot;&lt;/code&gt; and an &lt;code&gt;aria-label&lt;/code&gt; (&lt;code&gt;ConnectionDescriptor.ariaLabel&lt;/code&gt;, by default &amp;quot;Connection: a → b&amp;quot;). See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/selection.html&quot;&gt;Selection &amp;amp; Accessibility&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;ConnectionDescriptor.labels&lt;/code&gt; — any number of labels anywhere along a line (&lt;code&gt;position&lt;/code&gt;: &lt;code&gt;'start'&lt;/code&gt;, &lt;code&gt;'middle'&lt;/code&gt;, &lt;code&gt;'end'&lt;/code&gt; or a 0..1 fraction; &lt;code&gt;offset&lt;/code&gt;, &lt;code&gt;rotate&lt;/code&gt;, &lt;code&gt;className&lt;/code&gt;). A label with &lt;code&gt;text&lt;/code&gt; is drawn by the library as an SVG pill (&lt;code&gt;--vl-label-bg&lt;/code&gt;, &lt;code&gt;--vl-label-border&lt;/code&gt;, &lt;code&gt;--vl-label-color&lt;/code&gt;); one without is only a position. &lt;code&gt;ConnectionLayout.labels&lt;/code&gt; carries every label's resolved point and angle. New types: &lt;code&gt;ConnectionLabel&lt;/code&gt;, &lt;code&gt;LabelLayout&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/connection-labels.html&quot;&gt;Connection Labels&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;ConnectionStyle.animated&lt;/code&gt; / &lt;code&gt;defaultAnimated&lt;/code&gt; — a pattern of dashes or dots travelling along a line (&lt;code&gt;speed&lt;/code&gt;, &lt;code&gt;direction&lt;/code&gt;, &lt;code&gt;shape&lt;/code&gt;, &lt;code&gt;dash&lt;/code&gt;, &lt;code&gt;gap&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;), drawn as a separate CSS-only overlay and switched off for &lt;code&gt;prefers-reduced-motion&lt;/code&gt;. New type: &lt;code&gt;ConnectionFlow&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/animated-flow.html&quot;&gt;Animated Flow&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;avoidObstacles&lt;/code&gt; / &lt;code&gt;obstaclePadding&lt;/code&gt; (and &lt;code&gt;ConnectionStyle.avoidObstacles&lt;/code&gt;) — &lt;code&gt;smoothstep&lt;/code&gt; lines are routed around other blocks instead of through them, re-routing live while blocks are dragged; a line whose plain route is already clear is unchanged, and when no route exists the plain one is kept. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/routing.html&quot;&gt;Routing and Crossings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;jumps&lt;/code&gt; (and &lt;code&gt;ConnectionStyle.jumps&lt;/code&gt;) — a &lt;code&gt;smoothstep&lt;/code&gt; line makes a small semicircular hop where it crosses another connection's line, like on electrical schematics. New type: &lt;code&gt;JumpsOption&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/routing.html#hops-at-crossings&quot;&gt;Routing and Crossings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;clipToScrollParents&lt;/code&gt; — a port scrolled out of view inside a clipping ancestor (a row in a scrolling list, &lt;code&gt;overflow: hidden&lt;/code&gt;) no longer leaves a line dangling over other content: by default &lt;code&gt;'pin'&lt;/code&gt; pulls that end to the edge of the visible area and drops its marker and port dot, &lt;code&gt;'hide'&lt;/code&gt; hides the connection, &lt;code&gt;false&lt;/code&gt; restores the previous behavior. &lt;code&gt;ConnectionLayout&lt;/code&gt; gains &lt;code&gt;fromClipped&lt;/code&gt; / &lt;code&gt;toClipped&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/scrolling-containers.html&quot;&gt;Scrolling Containers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (core):&lt;/strong&gt; port spreading — &lt;code&gt;BlockDescriptor.portSpread&lt;/code&gt;, &lt;code&gt;PortDescriptor.spread&lt;/code&gt; and &lt;code&gt;defaultPortSpread&lt;/code&gt; (&lt;code&gt;true&lt;/code&gt; or &lt;code&gt;{ gap, padding }&lt;/code&gt;, defaults 16 and 8) give every connection that shares a port side its own virtual port, ordered so the lines don't cross. New types: &lt;code&gt;PortSpread&lt;/code&gt;, &lt;code&gt;PortSpreadOptions&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/visual-linker/guide/port-spreading.html&quot;&gt;Port Spreading&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; the &lt;code&gt;selected&lt;/code&gt; prop (&lt;code&gt;v-model:selected&lt;/code&gt;) and the &lt;code&gt;connection-selectionchange&lt;/code&gt;, &lt;code&gt;connection-delete-request&lt;/code&gt; and &lt;code&gt;update:selected&lt;/code&gt; events.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; &lt;code&gt;#connection-label&lt;/code&gt; is called once per label that has no &lt;code&gt;text&lt;/code&gt; — &lt;code&gt;{ connection, label, point, angle, rotation, from, to }&lt;/code&gt; — and positions the label at its point, rotated by &lt;code&gt;rotation&lt;/code&gt;. Without &lt;code&gt;labels&lt;/code&gt; it behaves as before: one label at the line's midpoint.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; &lt;code&gt;portSpread&lt;/code&gt; on &lt;code&gt;v-vl-block&lt;/code&gt; and the &lt;code&gt;blocks&lt;/code&gt; entries, &lt;code&gt;spread&lt;/code&gt; on &lt;code&gt;v-vl-port&lt;/code&gt;, and the &lt;code&gt;data-vl-port-spread&lt;/code&gt; / &lt;code&gt;data-vl-spread&lt;/code&gt; attributes (&lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;true&amp;quot;&lt;/code&gt; on, &lt;code&gt;&amp;quot;false&amp;quot;&lt;/code&gt; off, &lt;code&gt;&amp;quot;24&amp;quot;&lt;/code&gt; for the gap, &lt;code&gt;&amp;quot;24 4&amp;quot;&lt;/code&gt; for the gap and padding).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Changed (Vue):&lt;/strong&gt; the &lt;code&gt;#marker&lt;/code&gt; slot is not rendered for a connection end pinned to the edge of a scrolling container.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New (Nuxt):&lt;/strong&gt; the module options &lt;code&gt;portSpread&lt;/code&gt;, &lt;code&gt;clipToScrollParents&lt;/code&gt;, &lt;code&gt;animated&lt;/code&gt;, &lt;code&gt;avoidObstacles&lt;/code&gt;, &lt;code&gt;obstaclePadding&lt;/code&gt; and &lt;code&gt;jumps&lt;/code&gt;, applied as defaults to every &lt;code&gt;&amp;lt;VisualLinker&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Visual Linker 0.2.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-30-visual-linker-0-2-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-30-visual-linker-0-2-0"/>
    <updated>2026-09-30T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (Vue):&lt;/strong&gt; &lt;code&gt;&amp;lt;VisualLinker&amp;gt;&lt;/code&gt; no longer renders a wrapper &lt;code&gt;&amp;lt;div class=&amp;quot;vl-block&amp;quot;&amp;gt;&lt;/code&gt; per block around a &lt;code&gt;#block-&amp;lt;id&amp;gt;&lt;/code&gt; slot. It now wraps your own markup in its default slot, and blocks are discovered in it at any depth, inside any wrapper components. Migrate by moving the slot content into the default slot and marking each block element with &lt;code&gt;v-vl-block=&amp;quot;id&amp;quot;&lt;/code&gt; (or &lt;code&gt;data-vl-block=&amp;quot;id&amp;quot;&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;language-vue&quot;&gt;&lt;button title=&quot;Copy code&quot; data-copied=&quot;Copied&quot; class=&quot;copy&quot;&gt;&lt;/button&gt;&lt;span class=&quot;lang&quot;&gt;vue&lt;/span&gt;&lt;pre&gt;&lt;!--::markdown-it-async::oz3m9g7msfi0rn0vh75jgdp::--&gt;&lt;code&gt;&amp;lt;!-- 0.1.x --&amp;gt;
&amp;lt;VisualLinker :blocks=&amp;quot;blocks&amp;quot; :connections=&amp;quot;connections&amp;quot;&amp;gt;
  &amp;lt;template v-for=&amp;quot;b in blocks&amp;quot; #[`block-${b.id}`]=&amp;quot;{}&amp;quot; :key=&amp;quot;b.id&amp;quot;&amp;gt;
    &amp;lt;MyCard :data=&amp;quot;b&amp;quot; /&amp;gt;
  &amp;lt;/template&amp;gt;
&amp;lt;/VisualLinker&amp;gt;

&amp;lt;!-- 0.2.0 --&amp;gt;
&amp;lt;VisualLinker :connections=&amp;quot;connections&amp;quot;&amp;gt;
  &amp;lt;MyCard v-for=&amp;quot;b in blocks&amp;quot; :key=&amp;quot;b.id&amp;quot; v-vl-block=&amp;quot;b.id&amp;quot; :data=&amp;quot;b&amp;quot; /&amp;gt;
&amp;lt;/VisualLinker&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Breaking (Vue):&lt;/strong&gt; the &lt;code&gt;blocks&lt;/code&gt; prop is now optional. An entry can register an element directly through a new &lt;code&gt;el&lt;/code&gt; field (a template ref, getter, element, or CSS selector), or — without &lt;code&gt;el&lt;/code&gt; — only add config (ports, drag options) to a block already marked in the template.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; &lt;code&gt;v-vl-block&lt;/code&gt; / &lt;code&gt;v-vl-port&lt;/code&gt; directives, exported as &lt;code&gt;vVlBlock&lt;/code&gt; / &lt;code&gt;vVlPort&lt;/code&gt;. A port attaches to the nearest block around it, or to the one named by its &lt;code&gt;block&lt;/code&gt; option.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; plain &lt;code&gt;data-vl-*&lt;/code&gt; attributes as a JavaScript-free way to mark blocks and ports (&lt;code&gt;data-vl-block&lt;/code&gt;, &lt;code&gt;data-vl-draggable&lt;/code&gt;, &lt;code&gt;data-vl-drag-handle&lt;/code&gt;, &lt;code&gt;data-vl-drag-bounds&lt;/code&gt;, &lt;code&gt;data-vl-port&lt;/code&gt;, &lt;code&gt;data-vl-port-block&lt;/code&gt;, &lt;code&gt;data-vl-side&lt;/code&gt;, &lt;code&gt;data-vl-offset&lt;/code&gt;, &lt;code&gt;data-vl-anchor&lt;/code&gt;, &lt;code&gt;data-vl-linker&lt;/code&gt;); the names are exported as &lt;code&gt;VL_ATTR&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; live discovery — blocks and ports added, removed, or re-marked after mount (&lt;code&gt;v-if&lt;/code&gt;, &lt;code&gt;v-for&lt;/code&gt;, third-party markup) are picked up automatically.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; &lt;code&gt;scope&lt;/code&gt; prop — &lt;code&gt;'container'&lt;/code&gt; (default) or &lt;code&gt;'page'&lt;/code&gt;, which links elements anywhere in the document and draws in a &lt;code&gt;position: fixed&lt;/code&gt; layer teleported to &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; &lt;code&gt;name&lt;/code&gt; prop plus the directives' &lt;code&gt;linker&lt;/code&gt; option / &lt;code&gt;data-vl-linker&lt;/code&gt; attribute, to assign an element to a specific &lt;code&gt;&amp;lt;VisualLinker&amp;gt;&lt;/code&gt;; &lt;code&gt;zIndex&lt;/code&gt; prop for the drawing layer. Other attributes passed to &lt;code&gt;&amp;lt;VisualLinker&amp;gt;&lt;/code&gt; now land on its root element.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Vue):&lt;/strong&gt; &lt;code&gt;VisualLinkerPlugin&lt;/code&gt; — &lt;code&gt;app.use()&lt;/code&gt; registers &lt;code&gt;&amp;lt;VisualLinker&amp;gt;&lt;/code&gt; and both directives globally. &lt;code&gt;VisualLinkerScope&lt;/code&gt;, &lt;code&gt;BlockDirectiveOptions&lt;/code&gt;, &lt;code&gt;BlockDirectiveValue&lt;/code&gt;, &lt;code&gt;PortDirectiveOptions&lt;/code&gt;, &lt;code&gt;PortDirectiveValue&lt;/code&gt;, &lt;code&gt;RefFriendlyDragBounds&lt;/code&gt; and &lt;code&gt;RefFriendlyElement&lt;/code&gt; types are exported too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changed (Vue):&lt;/strong&gt; the drawing layer is rendered only client-side after mount, keeping the server render identical to the hydration pass.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (Nuxt):&lt;/strong&gt; &lt;code&gt;v-vl-block&lt;/code&gt; / &lt;code&gt;v-vl-port&lt;/code&gt; are registered by a universal plugin — on the server too, so the &lt;code&gt;data-vl-*&lt;/code&gt; attributes are already in the server-rendered HTML.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New (core):&lt;/strong&gt; &lt;code&gt;MarkerConfig.arrow&lt;/code&gt; — &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;{ color?, gap? }&lt;/code&gt; (new &lt;code&gt;MarkerArrowConfig&lt;/code&gt; type) draws an arrowhead right before a circle/square/diamond marker, its tip stopping exactly on the shape's outer edge, outline included. A marker carrying an arrow always uses &lt;code&gt;orient: 'auto'&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changed (core):&lt;/strong&gt; while a connection is highlighted it's painted above its siblings, and other connections ending on the same point hide their marker there, so resting-size markers no longer overlap the highlighted one.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fixed (core):&lt;/strong&gt; a connection with an explicit &lt;code&gt;style.width&lt;/code&gt; lost its hover/highlight width bump — the explicit inline width outranked the CSS rule. The bump is now applied inline too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changed (core):&lt;/strong&gt; dragging moves a block through the standalone CSS &lt;code&gt;translate&lt;/code&gt; property instead of &lt;code&gt;transform&lt;/code&gt;, so it composes with a transform the block already has instead of overwriting it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>InView 0.3.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-26-inview-0-3-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-26-inview-0-3-0"/>
    <updated>2026-09-26T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;createRevealController&lt;/code&gt;'s stagger delay now skips itself entirely under
&lt;code&gt;prefers-reduced-motion: reduce&lt;/code&gt; — the class/attribute toggle still
happens normally, only the staggered &lt;em&gt;timing&lt;/em&gt; is skipped.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;createElementTracker&lt;/code&gt; (and the &lt;code&gt;useElementViewport&lt;/code&gt;/&lt;code&gt;useParallaxLayer&lt;/code&gt;
composables/hooks built on it, Vue and React) accepts a &lt;code&gt;root&lt;/code&gt; element to
measure &lt;code&gt;viewportProgress&lt;/code&gt;/&lt;code&gt;distanceFromCenter&lt;/code&gt; against a scrollable
container instead of the window — for a parallax layer or viewport
tracker living inside &lt;code&gt;overflow: auto&lt;/code&gt; (a dashboard panel, a modal). The
returned &lt;code&gt;rect&lt;/code&gt; itself stays window-relative either way.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useElementVisibility&lt;/code&gt;'s options are now reactive in both adapters.
&lt;strong&gt;Vue:&lt;/strong&gt; &lt;code&gt;threshold&lt;/code&gt;/&lt;code&gt;rootMargin&lt;/code&gt;/&lt;code&gt;root&lt;/code&gt;/&lt;code&gt;once&lt;/code&gt; accept a ref/getter —
&lt;code&gt;threshold&lt;/code&gt;/&lt;code&gt;rootMargin&lt;/code&gt;/&lt;code&gt;root&lt;/code&gt; changing re-subscribes for real, &lt;code&gt;once&lt;/code&gt;
updates live without tearing down the subscription. &lt;strong&gt;React:&lt;/strong&gt;
&lt;code&gt;once&lt;/code&gt;/&lt;code&gt;onEnter&lt;/code&gt;/&lt;code&gt;onLeave&lt;/code&gt; now update live across re-renders (previously
frozen at the render that first created the subscription), and a fresh
inline &lt;code&gt;threshold&lt;/code&gt; array literal every render no longer forces a
needless re-subscribe.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New Vue composables:&lt;/strong&gt; &lt;code&gt;useRevealController&lt;/code&gt; (creates
&lt;code&gt;createRevealController&lt;/code&gt; on mount, destroys it on unmount),
&lt;code&gt;usePrefersReducedMotion&lt;/code&gt; (a reactive &lt;code&gt;Ref&amp;lt;boolean&amp;gt;&lt;/code&gt;, unlike the static
&lt;code&gt;prefersReducedMotion()&lt;/code&gt;), &lt;code&gt;useStagger&lt;/code&gt;, &lt;code&gt;useScrollTo&lt;/code&gt;, &lt;code&gt;useScrollSpy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New React hooks:&lt;/strong&gt; &lt;code&gt;useReveal&lt;/code&gt; (the equivalent of Vue's &lt;code&gt;v-reveal&lt;/code&gt; —
toggles a class/attribute automatically), &lt;code&gt;useRevealController&lt;/code&gt;,
&lt;code&gt;usePrefersReducedMotion&lt;/code&gt;, &lt;code&gt;useStagger&lt;/code&gt;, &lt;code&gt;useScrollTo&lt;/code&gt;, &lt;code&gt;useScrollSpy&lt;/code&gt; —
same shape as the Vue composables above.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New in &lt;code&gt;@macrulez/inview-core&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;createScrollSpy&lt;/code&gt; (tracks which of a
list of targets sits in an &amp;quot;active&amp;quot; band near the viewport's vertical
center, for nav-highlight UIs) and &lt;code&gt;scrollToElement&lt;/code&gt; (smooth-scrolls a
target so an element lands at its edge, with a px offset).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;createRevealController&lt;/code&gt;'s returned controller gained &lt;code&gt;observe(el)&lt;/code&gt;/
&lt;code&gt;unobserve(el)&lt;/code&gt; (for elements outside the &lt;code&gt;selector&lt;/code&gt; scan) and
&lt;code&gt;refresh(selector?)&lt;/code&gt; (a one-off scan with a different selector, on top
of the existing no-argument &lt;code&gt;refresh()&lt;/code&gt;). Per-element
&lt;code&gt;data-reveal-attribute&lt;/code&gt; now overrides &lt;code&gt;activeAttribute&lt;/code&gt; for one element,
the same way &lt;code&gt;data-reveal-class&lt;/code&gt; already did for &lt;code&gt;activeClass&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Nuxt's auto-import list now includes &lt;code&gt;useRevealController&lt;/code&gt;,
&lt;code&gt;usePrefersReducedMotion&lt;/code&gt;, &lt;code&gt;useStagger&lt;/code&gt;, &lt;code&gt;useScrollTo&lt;/code&gt;, &lt;code&gt;useScrollSpy&lt;/code&gt;,
&lt;code&gt;createScrollSpy&lt;/code&gt;, and &lt;code&gt;scrollToElement&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.2.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-devtoolz-0-2-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-devtoolz-0-2-1"/>
    <updated>2026-09-25T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: the &lt;code&gt;full-check&lt;/code&gt; command runs every other command in one sweep, each in its own safe read-only mode, and shows one summary table. The three commands that can write (&lt;code&gt;strip-comments&lt;/code&gt;, &lt;code&gt;console-strip&lt;/code&gt;, &lt;code&gt;case-check&lt;/code&gt;) are always called as a preview. A bare run in a real terminal asks about &lt;code&gt;stale-ts-ignore&lt;/code&gt;, the one slow command; &lt;code&gt;--skip&lt;/code&gt; and &lt;code&gt;--no-prompt&lt;/code&gt; control that. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/full-check.html&quot;&gt;Full Check&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Added to the programmatic API: &lt;code&gt;runFullCheck&lt;/code&gt;, &lt;code&gt;renderFullCheckReport&lt;/code&gt; and their types. &lt;code&gt;full-check&lt;/code&gt; itself composes the other commands' own &lt;code&gt;run*()&lt;/code&gt; functions, which the package root already exported.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.2.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-devtoolz-0-2-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-devtoolz-0-2-0"/>
    <updated>2026-09-25T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New: &lt;code&gt;unused-deps&lt;/code&gt; finds &lt;code&gt;package.json&lt;/code&gt; dependencies nothing imports, and &amp;quot;phantom&amp;quot; dependencies that are imported but never declared. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/dependency-graph.html#unused-deps&quot;&gt;Dependency Graph&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;circular-imports&lt;/code&gt; finds import cycles and shows each as its full chain; cycles made only of &lt;code&gt;import type&lt;/code&gt; are hidden unless &lt;code&gt;--include-types&lt;/code&gt; is given. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/dependency-graph.html#circular-imports&quot;&gt;Dependency Graph&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;empty-catch&lt;/code&gt; finds &lt;code&gt;catch&lt;/code&gt; blocks that swallow the error, including ones that only log it. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/code-hygiene.html#empty-catch&quot;&gt;Code Hygiene&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;todo-report&lt;/code&gt; collects &lt;code&gt;TODO&lt;/code&gt;/&lt;code&gt;FIXME&lt;/code&gt;/&lt;code&gt;HACK&lt;/code&gt; comments with their text, with &lt;code&gt;--tags&lt;/code&gt; and a &lt;code&gt;--max&lt;/code&gt; ratchet. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/code-hygiene.html#todo-report&quot;&gt;Code Hygiene&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;scripts-check&lt;/code&gt; cross-checks &lt;code&gt;package.json&lt;/code&gt; scripts against README/docs and CI workflows, and &lt;code&gt;orphan-tests&lt;/code&gt; finds test files whose source disappeared. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/consistency-checks.html&quot;&gt;Consistency Checks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;New: &lt;code&gt;stale-ts-ignore&lt;/code&gt; finds a &lt;code&gt;@ts-ignore&lt;/code&gt; that no longer suppresses anything, by comparing two real project-wide typechecks. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/stale-ts-ignore.html&quot;&gt;Stale @ts-ignore&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Added to the programmatic API: the &lt;code&gt;run*()&lt;/code&gt; and &lt;code&gt;render*Report()&lt;/code&gt; functions of the new commands.&lt;/li&gt;
&lt;li&gt;Changed: the import graph and the real-comment detection moved out of single commands into shared utilities, now used by several; &lt;code&gt;readme-check&lt;/code&gt;'s &lt;code&gt;tsconfig.json&lt;/code&gt; loader was shared the same way.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>DevToolz 0.1.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-devtoolz-0-1-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-devtoolz-0-1-0"/>
    <updated>2026-09-25T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;First release: one &lt;code&gt;devtoolz&lt;/code&gt; binary with six commands. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/overview.html&quot;&gt;Overview&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strip-comments&lt;/code&gt; and &lt;code&gt;console-strip&lt;/code&gt; remove comments and leftover &lt;code&gt;console.log&lt;/code&gt;/&lt;code&gt;debugger&lt;/code&gt; statements, with a preview by default, &lt;code&gt;-y&lt;/code&gt; to write and &lt;code&gt;--diff&lt;/code&gt; for a unified diff per file. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/cleanup.html&quot;&gt;Code Cleanup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dead-exports&lt;/code&gt; finds named exports nothing imports, aware of a package's public entry points, re-export chains and workspaces. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/dead-exports.html&quot;&gt;Dead Exports&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;case-check&lt;/code&gt; finds imports whose case does not match the file on disk, with &lt;code&gt;--fix&lt;/code&gt;. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/case-check.html&quot;&gt;Case Check&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exports-doctor&lt;/code&gt; and &lt;code&gt;readme-check&lt;/code&gt; verify a package from a consumer's side: declared &lt;code&gt;package.json&lt;/code&gt; paths against the disk, and README code blocks against the package's own types. See &lt;a href=&quot;https://npm.vuecraft.ru/en/packages/devtoolz/guide/package-checks.html&quot;&gt;Package Checks&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Network Dashboard 0.4.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-vue-network-dashboard-0-4-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-vue-network-dashboard-0-4-2"/>
    <updated>2026-09-25T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Several &lt;code&gt;addMock&lt;/code&gt;/&lt;code&gt;addMockToGroup&lt;/code&gt; examples in the README and the
Mocking guide omitted the required &lt;code&gt;enabled&lt;/code&gt; field — copy-pasted as
written, the rule would have failed to typecheck, and if that were
bypassed, the mock would have been silently skipped at runtime
(&lt;code&gt;addMock&lt;/code&gt;/&lt;code&gt;addMockToGroup&lt;/code&gt; check &lt;code&gt;rule.enabled&lt;/code&gt; before applying it).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addMockToGroup&lt;/code&gt;'s documented signature listed
&lt;code&gt;rule: Partial&amp;lt;MockRule&amp;gt;&lt;/code&gt; — the real type is &lt;code&gt;Omit&amp;lt;MockRule, 'id'&amp;gt;&lt;/code&gt;,
every field but &lt;code&gt;id&lt;/code&gt; is still required.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Responsive Media 2.0.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-responsive-media-2-0-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-responsive-media-2-0-2"/>
    <updated>2026-09-25T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;The Vue integration guide's &lt;code&gt;useContainerState&lt;/code&gt; example called
&lt;code&gt;useTemplateRef('card')&lt;/code&gt; without an explicit type argument — Vue's own
default (&lt;code&gt;unknown&lt;/code&gt;) doesn't satisfy &lt;code&gt;useContainerState&lt;/code&gt;'s
&lt;code&gt;Ref&amp;lt;Element | null&amp;gt;&lt;/code&gt; parameter, so the example as written never
actually compiled. Now shows &lt;code&gt;useTemplateRef&amp;lt;HTMLDivElement&amp;gt;('card')&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>State Machine 0.2.7</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-vue-state-machine-0-2-7</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-25-vue-state-machine-0-2-7"/>
    <updated>2026-09-25T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;The README's code examples still imported the unscoped
&lt;code&gt;vue-state-machine&lt;/code&gt; in five places instead of the real published name
&lt;code&gt;@macrulez/vue-state-machine&lt;/code&gt; — a leftover from before the package was
moved under the scope.&lt;/li&gt;
&lt;li&gt;The Wizards guide's &lt;code&gt;CheckoutCtx&lt;/code&gt; example declared it with &lt;code&gt;interface&lt;/code&gt;
— TypeScript doesn't give an &lt;code&gt;interface&lt;/code&gt; the implicit index signature
&lt;code&gt;Ctx&lt;/code&gt; (&lt;code&gt;Record&amp;lt;string, unknown&amp;gt;&lt;/code&gt;) needs, so &lt;code&gt;WizardStep&amp;lt;CheckoutCtx&amp;gt;&lt;/code&gt;
never actually type-checked as written. Switched to a &lt;code&gt;type&lt;/code&gt; alias,
matching the pattern already used elsewhere in the same doc.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Color Value Tools 1.2.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-color-value-tools-1-2-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-color-value-tools-1-2-2"/>
    <updated>2026-09-24T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;New subpath imports by function group: &lt;code&gt;color-value-tools/parse&lt;/code&gt;,
&lt;code&gt;/convert&lt;/code&gt;, &lt;code&gt;/manipulate&lt;/code&gt;, &lt;code&gt;/palette&lt;/code&gt;, &lt;code&gt;/a11y&lt;/code&gt; and &lt;code&gt;/cache&lt;/code&gt;. They work
with both &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;require&lt;/code&gt; and ship their own TypeScript types.
Importing from the package root works exactly as before.&lt;/li&gt;
&lt;li&gt;ESM consumers now get ESM type declarations; previously the ESM build
used the CommonJS &lt;code&gt;.d.ts&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;The package is marked &lt;code&gt;sideEffects: false&lt;/code&gt;, so bundlers can drop unused
code more reliably.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;cvt&lt;/code&gt; CLI now uses the package's own build instead of shipping a
second copy of the library. Commands and output are unchanged.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.2.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-vue-image-kit-1-2-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-vue-image-kit-1-2-0"/>
    <updated>2026-09-24T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sources&lt;/code&gt; entries can now carry their own &lt;code&gt;width&lt;/code&gt;/&lt;code&gt;height&lt;/code&gt; for art-direction
breakpoints whose crop has a different aspect ratio than the root image —
either as &lt;code&gt;{ src, width, height }&lt;/code&gt; or by passing a build-time &lt;code&gt;ImageMeta&lt;/code&gt;
object directly (e.g. from a &lt;code&gt;?vik&lt;/code&gt; import). Give a breakpoint its own
dimensions and &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; reserves the placeholder — and the blurhash
preview — at &lt;em&gt;that&lt;/em&gt; breakpoint's own proportions instead of always falling
back to the root image's, so switching breakpoints no longer causes a
layout shift once the real photo loads. Entries without &lt;code&gt;width&lt;/code&gt;/&lt;code&gt;height&lt;/code&gt;
keep working exactly as before.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;sources&lt;/code&gt; key that doesn't match any registered breakpoint now warns in
development, naming the key and the breakpoints that are available,
instead of silently doing nothing.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.1.8</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-vue-image-kit-1-1-8</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-vue-image-kit-1-1-8"/>
    <updated>2026-09-24T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; no longer forces &lt;code&gt;display&lt;/code&gt;/box-sizing/&lt;code&gt;object-fit&lt;/code&gt; as inline
styles when it doesn't need to — inline styles always beat a class your
app applies to the same element, regardless of specificity. An explicit
&lt;code&gt;fit&lt;/code&gt; prop is still applied inline (guaranteed to win). Left unset, the
&lt;code&gt;object-fit: cover&lt;/code&gt; default now comes from a plain, overridable CSS class
— applied only when the image box is actually constrained (&lt;code&gt;layout&lt;/code&gt;
&lt;code&gt;&amp;quot;fill&amp;quot;&lt;/code&gt;/&lt;code&gt;&amp;quot;fixed&amp;quot;&lt;/code&gt;, or both &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; given), and omitted
otherwise since it has no effect without a constrained box. The same
applies to the base &lt;code&gt;display&lt;/code&gt;/sizing styles — &lt;code&gt;width: 100%; height: auto&lt;/code&gt;
is now only applied when both &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; are given (there's no
intrinsic ratio to preserve otherwise), so a bare &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; sized purely
through your own &lt;code&gt;max-height&lt;/code&gt;/&lt;code&gt;max-width&lt;/code&gt; CSS keeps its natural aspect
ratio instead of being stretched to the container's full width.&lt;/li&gt;
&lt;li&gt;Fixed: the package's stylesheet (the shimmer placeholder's animation, and
now the classes above) was never reachable via &lt;code&gt;import '@macrulez/vue-image-kit/style.css'&lt;/code&gt; — it wasn't declared in the
package's &lt;code&gt;exports&lt;/code&gt;, so &lt;code&gt;placeholderMode=&amp;quot;shimmer&amp;quot;&lt;/code&gt; shipped
non-functional everywhere. The Nuxt module now registers the stylesheet
automatically.&lt;/li&gt;
&lt;li&gt;Fixed: 1.1.7's wrapper removal caused &lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; to trigger a Vue
hydration mismatch warning on every server-rendered page — the check it
used to decide what to render couldn't tell &amp;quot;the server&amp;quot; from &amp;quot;the
client's very first render during hydration&amp;quot;, so the two never actually
matched. It's now hydration-safe.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>InView 0.2.3</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-inview-0-2-3</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-24-inview-0-2-3"/>
    <updated>2026-09-24T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed: &lt;code&gt;createRevealController&lt;/code&gt;'s stagger delay (&lt;code&gt;--reveal-delay&lt;/code&gt; / the
inline &lt;code&gt;transition-delay&lt;/code&gt; it sets) used to stay on the element forever
after it appeared — so any other transition on that same element, like a
hover effect on a &lt;code&gt;.reveal&lt;/code&gt; link, silently inherited the same delay too.
The delay is now automatically removed once the reveal-in transition
actually finishes (or, if it never runs — &lt;code&gt;prefers-reduced-motion&lt;/code&gt;, no
matching CSS &lt;code&gt;transition&lt;/code&gt; — after a short fallback timer), so later
transitions on the element are unaffected. No configuration needed, this
is just how it behaves now.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.1.7</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-23-vue-image-kit-1-1-7</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-23-vue-image-kit-1-1-7"/>
    <updated>2026-09-23T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt; no longer renders inside a wrapper &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;. Every earlier
version wrapped the real &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; (and, while loading, whichever blurhash
&lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;/LQIP-ThumbHash &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;/solid-color or shimmer &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;
placeholder was active) in a persistent positioning &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;, which made
the component awkward to drop into markup that expects to own the
element it's styling directly. Every placeholder kind is now painted as
a CSS background directly on the same element that goes on to show the
real photo — an idle placeholder element before loading starts, swapped
outright (not nested) for the real &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; once it does.
&lt;code&gt;class&lt;/code&gt;/&lt;code&gt;style&lt;/code&gt;/&lt;code&gt;data-*&lt;/code&gt;/other attributes now land on that one real
element. The smooth &amp;quot;blur visible through a fading-in sharp photo&amp;quot;
crossfade isn't possible anymore — swapping is an instant cut; the new
&lt;code&gt;fadeIn&lt;/code&gt; prop (below) is a different, simpler effect, not a replacement
for the old one.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;VImage&amp;gt;&lt;/code&gt;'s new &lt;code&gt;fadeIn&lt;/code&gt; prop (default &lt;code&gt;false&lt;/code&gt;) opts into a ~0.3s
opacity fade-in on mount.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Color Value Tools 1.2.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-color-value-tools-1-2-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-color-value-tools-1-2-1"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isReadableOnBackground()&lt;/code&gt;'s &lt;code&gt;wcagLevel&lt;/code&gt; now uses the same effective
background color as &lt;code&gt;minContrastRatio&lt;/code&gt;/&lt;code&gt;readable&lt;/code&gt; for
&lt;code&gt;'semi-transparent'&lt;/code&gt;/&lt;code&gt;'gradient'&lt;/code&gt; backgrounds, instead of always
&lt;code&gt;'#ffffff'&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Command Palette 0.2.9</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-command-palette-0-2-9</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-command-palette-0-2-9"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bindShortcuts&lt;/code&gt; now binds hotkeys for nested &lt;code&gt;subCommand&lt;/code&gt;s too, not
just top-level commands.&lt;/li&gt;
&lt;li&gt;The hotkey fallback executor (&lt;code&gt;runFallback&lt;/code&gt;, used with no
&lt;code&gt;&amp;lt;CommandPalette&amp;gt;&lt;/code&gt; mounted) now correctly opens &lt;code&gt;page&lt;/code&gt;-only commands
and handles &lt;code&gt;confirm&lt;/code&gt;/frecency tracking like the real &lt;code&gt;executeCommand&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CommandItem&lt;/code&gt;'s match highlighting now reuses the diacritic-aware
&lt;code&gt;FuzzySearch&lt;/code&gt; scorer instead of a separate, less accurate
implementation.&lt;/li&gt;
&lt;li&gt;The Nuxt module now registers the package's components via
&lt;code&gt;addComponent&lt;/code&gt; and auto-imports every composable/factory, not just 3
of them.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isLoading&lt;/code&gt; in &lt;code&gt;CommandPalette.vue&lt;/code&gt; is now a ref-count across
concurrent search pipelines, instead of one shared boolean that could
clear prematurely.&lt;/li&gt;
&lt;li&gt;Async result merging now replaces an already-merged sync result with a
better-scoring async result of the same id, instead of
&amp;quot;first-registered wins&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PaletteProvider&lt;/code&gt; (testing.ts) now also provides
&lt;code&gt;PALETTE_REGISTRY_KEY&lt;/code&gt; — named-instance lookups
(&lt;code&gt;useCommandPalette('name')&lt;/code&gt;) now resolve correctly under it.&lt;/li&gt;
&lt;li&gt;Unified the global hotkey toggle (&lt;code&gt;installPalette&lt;/code&gt;) and
&lt;code&gt;useCommandPalette()&lt;/code&gt;'s own &lt;code&gt;toggle()&lt;/code&gt;/&lt;code&gt;open()&lt;/code&gt;/&lt;code&gt;close()&lt;/code&gt; onto one
open/close implementation (including &lt;code&gt;history&lt;/code&gt; clearing).&lt;/li&gt;
&lt;li&gt;Function-valued Nuxt module options (&lt;code&gt;vCommandPalette&lt;/code&gt;: &lt;code&gt;onOpen&lt;/code&gt;,
&lt;code&gt;onError&lt;/code&gt;, &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;onSearch&lt;/code&gt;, etc.) are no longer serialized into
the client &lt;code&gt;runtimeConfig.public&lt;/code&gt; — only the serializable subset
crosses that boundary.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>CSS Magic Gradient 1.3.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-css-magic-gradient-1-3-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-css-magic-gradient-1-3-1"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Added reactive &lt;code&gt;useMonochromaticGradient&lt;/code&gt;/&lt;code&gt;useHueWheelGradient&lt;/code&gt; hooks
to both &lt;code&gt;css-magic-gradient/vue&lt;/code&gt; and &lt;code&gt;css-magic-gradient/react&lt;/code&gt; —
previously these two generators were only available as plain
functions, with no reactive wrapper, unlike the package's other 8
generators.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Error Boundary Kit 0.3.5</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-error-boundary-kit-0-3-5</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-error-boundary-kit-0-3-5"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;AsyncBoundary&amp;gt;&lt;/code&gt; is now auto-registered as a global component by the
Nuxt module, alongside &lt;code&gt;&amp;lt;ErrorBoundary&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;createHttpReporter&lt;/code&gt; now returns a cleanup function to remove its
&lt;code&gt;pagehide&lt;/code&gt; listener.&lt;/li&gt;
&lt;li&gt;The Nuxt module's &lt;code&gt;autoImports&lt;/code&gt; list now covers every composable/
factory in the package, not just 3 of them.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Feature Toggles 0.2.0</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-feature-toggles-0-2-0</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-feature-toggles-0-2-0"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;'live'&lt;/code&gt; to the &lt;code&gt;FlagSource&lt;/code&gt; type for SSE/WebSocket-pushed flag
updates.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Feature&amp;gt;&lt;/code&gt; with neither &lt;code&gt;name&lt;/code&gt; nor &lt;code&gt;group&lt;/code&gt; now logs a dev-mode warning
instead of silently rendering nothing.&lt;/li&gt;
&lt;li&gt;The Nuxt module now accepts &lt;code&gt;loader&lt;/code&gt;/&lt;code&gt;rules&lt;/code&gt; in its own config and
auto-imports the package's composables.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Form Schema 0.2.8</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-form-schema-0-2-8</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-form-schema-0-2-8"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@macrulez/nuxt-vue-form-schema&lt;/code&gt; is now either published for real or no
longer referenced as installable.&lt;/li&gt;
&lt;li&gt;An async &lt;code&gt;options()&lt;/code&gt; function on a field no longer re-runs on every
form value change — only when its own &lt;code&gt;optionsDeps&lt;/code&gt; change.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isValid&lt;/code&gt; now accounts for a still-pending async validator, instead of
only &lt;code&gt;submit()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The default &lt;code&gt;persistKey&lt;/code&gt; is no longer a plain comma-joined field-name
list — two unrelated forms with identically-named fields no longer
silently share persisted storage.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remove&lt;/code&gt;/&lt;code&gt;move&lt;/code&gt;/&lt;code&gt;swap&lt;/code&gt; on &lt;code&gt;useFieldArray&lt;/code&gt; now correctly renumber
&lt;code&gt;form.errors&lt;/code&gt;/&lt;code&gt;form.touched&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The Vue DevTools panel is now wired up automatically by the plugin's
&lt;code&gt;install()&lt;/code&gt; — no manual &lt;code&gt;installFormDevtools(app)&lt;/code&gt; call needed.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>i18n Kit 0.4.12</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-i18n-kit-0-4-12</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-i18n-kit-0-4-12"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;I18nKitConfig&lt;/code&gt;, &lt;code&gt;LocaleConfig&lt;/code&gt;, and &lt;code&gt;LocaleMeta&lt;/code&gt; are now exported from
&lt;code&gt;vue-i18n-kit/config&lt;/code&gt;, so they can type-check a hand-written
&lt;code&gt;i18n-kit.config.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Removed dead code &lt;code&gt;src/cli/commands/init.ts&lt;/code&gt; (&lt;code&gt;runInit&lt;/code&gt;) — unused by
the CLI and by any test, and using a plural syntax incompatible with
the package's own ICU engine.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Image Kit 1.1.6</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-image-kit-1-1-6</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-image-kit-1-1-6"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;v-lazy-img&lt;/code&gt; now shares the same pooled &lt;code&gt;IntersectionObserver&lt;/code&gt; every
other lazy-loading path uses, instead of creating its own per element.&lt;/li&gt;
&lt;li&gt;Unset &lt;code&gt;layout&lt;/code&gt; now gets the same auto-&lt;code&gt;sizes&lt;/code&gt; heuristic as
&lt;code&gt;layout=&amp;quot;responsive&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Blurhash and a LQIP/thumbhash placeholder can no longer mount
simultaneously when both props are supplied — restored a single
either/or precedence.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>InView 0.2.2</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-inview-0-2-2</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-inview-0-2-2"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Added the missing &lt;code&gt;&amp;lt;InView&amp;gt;&lt;/code&gt; component and &lt;code&gt;setViewportDefaults&lt;/code&gt;/
&lt;code&gt;viewportDefaults&lt;/code&gt; registration to the Nuxt module (previously only
composables/utilities/&lt;code&gt;v-reveal&lt;/code&gt; were wired up).&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Network Dashboard 0.4.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-network-dashboard-0-4-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-vue-network-dashboard-0-4-1"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;Fixed the package's own &lt;code&gt;npm run type-check&lt;/code&gt; — broadened the &lt;code&gt;*.vue&lt;/code&gt;
module shim to also declare &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;'s named type exports
(e.g. &lt;code&gt;NetworkDebuggerProps&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Cleaned up the dead/divergent &lt;code&gt;useHotkey.ts&lt;/code&gt;/&lt;code&gt;useLogFilter.ts&lt;/code&gt;
composables that duplicated &lt;code&gt;NetworkDebugger.vue&lt;/code&gt;'s own inline logic.&lt;/li&gt;
&lt;li&gt;Closed a dormant cross-test &lt;code&gt;localStorage&lt;/code&gt; leak from a missing mock
reset in the &lt;code&gt;persistToStorage&lt;/code&gt; tests.&lt;/li&gt;
&lt;li&gt;Fixed subpath import examples in JSDoc comments (&lt;code&gt;devtools.ts&lt;/code&gt;,
&lt;code&gt;adapters/sentry.ts&lt;/code&gt;, &lt;code&gt;adapters/opentelemetry.ts&lt;/code&gt;) — all three symbols
are only reachable from the package root.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>OS Detect 2.2.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-os-detect-2-2-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-os-detect-2-2-1"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;detectIsiOS()&lt;/code&gt; (deprecated alias) now logs its deprecation warning
once instead of on every call.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useIsWindows11()&lt;/code&gt; (Vue and React) no longer calls its setter/assigns
its ref after the component has unmounted.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;detectIsWindows11()&lt;/code&gt; is now memoized like every other detector, with
&lt;code&gt;resetDetectionCache()&lt;/code&gt; support.&lt;/li&gt;
&lt;li&gt;Synced &lt;code&gt;package-lock.json&lt;/code&gt;'s version with &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Responsive Media 2.0.1</title>
    <id>https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-responsive-media-2-0-1</id>
    <link href="https://npm.vuecraft.ru/en/changelog/2026-09#2026-09-12-responsive-media-2-0-1"/>
    <updated>2026-09-12T00:00:00Z</updated>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isAbove(key)&lt;/code&gt; now correctly returns &lt;code&gt;false&lt;/code&gt; for an unrecognized
breakpoint key — fixed in the core, Vue, and React implementations.&lt;/li&gt;
&lt;li&gt;Unified the two independent &lt;code&gt;isSSR()&lt;/code&gt; implementations into one,
stricter check (&lt;code&gt;window&lt;/code&gt; and &lt;code&gt;window.matchMedia&lt;/code&gt; both present).&lt;/li&gt;
&lt;li&gt;Vue's &lt;code&gt;useBreakpoints()&lt;/code&gt; now honors &lt;code&gt;inject()&lt;/code&gt;/DI, matching
&lt;code&gt;useResponsive()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Vue's &lt;code&gt;useMediaQuery()&lt;/code&gt; can no longer leak its &lt;code&gt;matchMedia&lt;/code&gt; listener
when called outside an active component — the composable now always
returns a stop function.&lt;/li&gt;
&lt;li&gt;React's &lt;code&gt;useContainerState()&lt;/code&gt; now recreates its &lt;code&gt;ResizeObserver&lt;/code&gt; if
&lt;code&gt;ref.current&lt;/code&gt; was &lt;code&gt;null&lt;/code&gt; on the first effect run (e.g. an element
behind a later-mounted conditional/portal).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hydrate(initialState)&lt;/code&gt; no longer silently drops keys missing from the
live state — it now warns.&lt;/li&gt;
&lt;li&gt;Added baseline automated test coverage for the Vue and React adapters
(previously only the framework-agnostic core was tested).&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
</feed>
