@feugene/granularity-charts

  • With components
  • releases: 20
  • v1.1.0

Releases of @feugene/granularity-charts from its CHANGELOG: the latest 8 in full, the earlier ones as a list of versions.

core tag v1.1.1

On this page

v1.1.02026-10-16

Changed

  • Peer @feugene/granum — >=2.0.0 <3.0.0. Пакет собран granum 2.0: dist не импортирует granum — контракт встроен в dist/granum/contract.js, и SSR-сервер с внешними пакетами, задеплоенный с --omit=dev, больше не падает с ERR_MODULE_NOT_FOUND. Приложению — @feugene/granum и @feugene/granum-engine-wind ^2.0.0.
  • Компонент из корня пакета — ComponentRootImportError у приложения на granum 2.0. Компоненты берут из <пакет>/components/<Имя>.
  • Авто-импорт — один GranularityResolver() из @feugene/unplugin-granularity 1.1: он находит пакет в package.json приложения сам, порядок резолверов больше не важен. Собственный ./resolver остаётся для уже написанных конфигов.
  • Необязательный peer @feugene/fint-i18n — >=0.9.0 <1.0.0. Пакет тестируется на 0.9 вместе с ядром; на 0.7 и 0.8 он не проверялся.

v1.0.42026-10-06

Fixed

  • Ось значений горизонтальных GrChartWaterfall и GrChartBar прореживается по ширине. Правило «влезает — или шаг крупнее», которое уже действовало на оси X вертикальных графиков, на оси значений горизонтальных не применялось: на узком холсте 0 500 1,000 1,500 2,000 сливалось в «0 5001,0001,5002,000». Теперь подписи, которые не помещаются, пропускаются через одну, а первая и последняя остаются.
  • Шаги узкого вертикального GrChartWaterfall не сжимаются в огрызки. На 210px пять коротких подписей усекались до «Pr…», «V…», «C…» — двухбуквенный обрубок не называет ничего. Теперь сначала перенос на две строки; если и так какая-то подпись теряет больше, чем оставляет четыре знака, подписи встают в шахматку — соседние в разные ряды, каждой ширина двух шагов, крайним — до края холста. Усечённая подпись держит не меньше четырёх знаков, полный текст — в <title>.

v1.0.32026-10-06

Fixed

  • Пустой график держит заданную height. Заглушка «нет данных» сжимала область построения до min(height, 8rem): GrChartArea с :height="260" занимал с данными 260px, а на периоде без данных — 128px, и карточка вокруг прыгала (скелет загрузки высоту держал). Теперь данные, загрузка и пустота — series: [] или empty — занимают одну height у всех графиков на общей раме: GrChartArea, GrChartBar, GrChartLine, GrChartPie, GrChartRadar, GrChartFunnel, GrChartHeatmap, GrChartWaterfall, GrChartBullet. Хук --gr-chart-frame-empty-height остался — по умолчанию он равен height и сжимает заглушку, если его задать; выше height она по-прежнему не растёт.
  • Подпись оси значений не срезается краем холста. Отступ под ось считался по отформатированной подписи, но оценка ширины была уже настоящей: цифры шли по 0.55 кегля, «1» — по 0.32, «%» — по 0.68, тогда как в Inter, первом шрифте --gr-font-ui, это 0.6–0.65, 0.41 и 0.98. В итоге yTickFormat с «100%» получал на ~6px меньше, и подпись читалась как «l00%». Оценка (estimateTextWidth) теперь ошибается вверх: классы символов — потолок по шрифтам стека (Inter, системный, Arial/Helvetica), отдельно цифры и знаки валют, отдельно самые широкие (%, m, M, W, Ж, Ш…), заглавные — по регистру, в том числе кириллица. Поверх оценки — запас в 2px. Касается левой и правой (dualAxis) оси значений, подписей оси X и всех графиков на общей раме.
  • Имена категорий горизонтального GrChartBar читаются целиком. Колонка подписей была ограничена 96px на любом холсте, и «Delivered after the promised date» на графике в 550px превращалась в «Delivered af…», хотя полосам места хватало с избытком. Теперь потолок — 40% ширины области построения (но не меньше 96px), многоточие появляется только за ним, полное имя остаётся в <title>, тултипе и скрытой таблице. Так же считаются подписи шагов горизонтального GrChartWaterfall и строк GrChartHeatmap; строка теплокарты шире потолка теперь кончается многоточием с полным текстом в <title>, а не уезжает за край холста.
  • Подписи колонок GrChartHeatmap не налезают друг на друга. Подписи стояли по центру ячеек целиком при любой ширине: в матрице шириной 213px с колонками «Starter», «Team», «Business» ячейки по 31px, и подписи сливались в «StarterTeamBusiness». Теперь подпись, которая не помещается в ячейку, усекается многоточием (полный текст — в <title>), пока от неё остаются хотя бы три знака; дальше ряд прореживается с первой и последней колонкой, и каждая подпись занимает место только до середины пути к соседям. Имя строки «Recurring invoices» больше не срезается краем холста — это часть правки оценки ширины выше.
  • Подписи оси X не налезают друг на друга. Число делений выбирала шкала, а ширина подписей в выбор не входила: GrChartLine на карточке в 250px с двадцатью пятью получасами категориями рисовал «00:0030:0001:00…», месяцы — «NoDecJanFebMar…», даты помесячно — «Jan 2026Apr 2026Jul 2026Oct 2026». Теперь рама после выбора делений проверяет подписи по оценке ширины и, если соседние сталкиваются, показывает каждую k-ю с первой и последней — на любой шкале: категориальной, временной и числовой. Сетка остаётся на всех делениях. Касается GrChartLine, GrChartArea, GrChartBar и вертикального GrChartWaterfall.
  • xTickCount работает у категориальной оси — как потолок числа подписей (не задан — двенадцать, как прежде). Умолчание пропа у GrChartLine, GrChartArea и GrChartBar теперь undefined; для числовой и временной оси это по-прежнему шесть делений.
  • Ось времени не схлопывается в одно деление. Лестница шагов прыгала с квартала сразу на год, и xTickCount: 4 на одиннадцати месяцах давал одно деление «Dec». В лестнице появились шаги в 2 и 6 месяцев, а ступень выбирается по настоящему числу делений после выравнивания: не больше xTickCount и не меньше двух, если диапазон их вмещает.
  • Слот #center у GrChartPie можно поставить в центр. Слот рисуется внутри холста, а получал только total и formattedTotal: своё SVG («92%» и «on time» вместо суммы) ложилось в начало координат холста, а не в дырку. Теперь слот получает и геометрию: cx, cy, innerRadius, valueFont, labelFont — по ним стоит и содержимое по умолчанию. Пример — на странице компонента. formattedTotal форматируется по valueFormat, как и раньше.
  • Ось значений GrChartWaterfall — по накоплениям, а не по шагам. Ряд рамы нёс собственные значения шагов, и дельты попадали в домен: у отчёта о прибылях 1240 → −410 → 830 → … ось уходила до −500, у складского моста — до −1000, хотя накопление нигде не опускалось ниже нуля. Теперь стороны домена — основания и вершины столбцов вместе с нулём; yDomain потребителя сильнее.
  • С yDomain, чей низ выше нуля, столбцы моста не вылезают за область. Итоговый столбец от нуля уходил под ось поверх подписей «Start of Sep», «End of Sep». Теперь концы столбцов прижимаются к краю домена — обрыв виден, — а соединители и нулевые шаги вне домена не рисуются.
  • Каждый шаг моста назван, и подписи не налезают. Подписи шагов стояли целиком: восемь шагов на 510px и пять на 210px сливались. Прореживать их, как у категорий, нельзя — мост без имени шага не прочитать, — поэтому рама в режиме xLabelFit: 'wrap' переносит подпись по словам на две строки, дальше усекает её многоточием с <title>; нижнее поле растёт на строку. Все шаги подписаны и сверх двенадцати.
  • Горизонтальный мост оставляет место под последнюю подпись оси значений — «2,000» больше не срезается до «2,00» краем холста, как уже было у горизонтальных столбцов.
  • Паутина GrChartRadar не отдаёт радиус подписям. Отступ под самую длинную подпись резервировался с каждой стороны: в карточке 213×260 с осями «System design», «Go», «SQL», «On-call», «Mentoring» паутина сжималась до 25px под наползающим текстом, а при axis-scale="per-axis" («Orders a day · 200») пропадала совсем. Теперь радиус — наибольший, при котором каждая подпись помещается со своей стороны, но не меньше половины от возможного; имя шире четверти холста переносится на две строки, дальше — многоточие с полным текстом в <title>. Потолок оси при per-axis стоит второй строкой («max 200») и не усекается. Подписи колец переехали с первой спицы на биссектрису между первой и второй: внешнее кольцо налезало на имя верхней оси.
  • Гидрация радара и круга без расхождений. Координаты из тригонометрии писались полным числом, и сервер с браузером расходились в последнем знаке (229.37383539249433 против …436). Теперь спицы, кольца, вершины, дуги, выноски и центр круга идут через svgCoord с двумя знаками.
  • Подсказка графика прячется, когда точка уехала из вида. Курсор, поставленный программно (v-model:active-index у пары графиков), оставлял подсказку прижатой к краю вьюпорта поверх чужого содержимого, а до первого расчёта позиции — в левом верхнем углу. Рама включает hideWhenDetached у useFloating ядра; работает с ядром 1.0.10 и новее.
  • Воронка подписывает ступени именами. GrChartFunnel не рисовал имён ступеней вовсе — какая полоса что значит, знали только тултип и скрытая таблица. Теперь у вертикали имена стоят колонкой слева (до 40% ширины, не уже 96px), у горизонтали — строкой под ступенями; длинное имя кончается многоточием с полным текстом в <title>.
  • Подпись значения воронки не пропадает на узкой ступени. Подпись, которая не помещалась внутри, не рисовалась: у воронки 12400 → 3180 → 1420 → 612 с labels="share-first" последняя ступень оставалась без «5%», у 940 → 1360 → 410 → 0 пропадали «410» и обещанный документацией «0». Теперь такая подпись стоит рядом со ступенью — справа от её середины у вертикали, над ней у горизонтали — цветом подписи рамы.
  • tooltip: false прячет только панель. Флаг выключал всё слежение за указателем: график с :tooltip="false" в паре на одном v-model:active-index не двигал курсор под мышью, не излучал update:activeIndex и pointHover — синхронизация шла только в одну сторону. Теперь курсор, активные марки, вертикаль и события работают, пока график интерактивен; картинкой его делает только interactive: false. Поведение описано в JSDoc пропа tooltip у всех графиков.
  • Появились описания у пропов, событий и слотов всех графиков, которые в API, подсказках IDE и на портале были пустыми: у общих пропов (height, yDomain, includeZero, yDomainRight, yTickFormatRight, valueFormatRight, xTickCount, yTickCount, xTickFormat, yTickFormat, valueFormat, curve, showPoints, showGrid, showLegend, legendPosition, tooltip, loading, empty, emptyText, dataTable, size, locale, ariaLabel, ariaDescription) и у своих — min и orientation буллета, stages воронки, xLabels, yLabels и цветов шкалы теплокарты, variant круга и спарклайна, fill радара, steps, showConnectors и barRadius моста; у событий update:*, *Click, *Hover, legendToggle и слотов tooltip, legend, empty, header.

v1.0.22026-10-06

Changed

  • Safelist компонентов пуст. Все записи лежали в коде целыми литералами — в шаблонах и .ts-хелперах, включая раму GrChartFrame. granum извлекает такие классы сам, обходя от входа компонента все его чанки, общие включительно, и вычищал записи из манифеста как уже извлечённые. Списки пережили UnoCSS-пресет, который общий чанк не сканировал. Набор классов не изменился — проверено сверкой манифестов по селекции каждого компонента; расходятся только случайные токены, которые экстрактор выхватывает из минифицированного кода.
  • Удалены chartFrameSafelist и internal/classTokens.ts: они служили только спискам. Что рама доходит до каждого графика по графу бандла, теперь проверяет frameOwnership.test.ts.
  • Подключён гейт defineSafelistGate из test-kit: запись safelist, которая лежит целым литералом в коде компонента, он называет лишней. Нужен safelist только классу, собранному в рантайме из частей.

v1.0.12026-09-29

Гигиена сборки. Артефакт пакета не изменился — проверено побайтно.

Changed

  • libInjectCss убран из конфига сборки. Плагин вписывал в JS-чанк компонента import '../styles.css'; до granum это был единственный канал доставки стилей, а с granum тот же файл приезжает приложению через манифест — и потребитель получал два экземпляра, причём второй вне слоёв granum.* и потому сильнее всей библиотеки.

    У этого пакета компонентного CSS нет, и плагин стоял вхолостую: сборка с ним и без него совпадает побайтно, числа в docs/entry-sizes.md не сдвинулись. Убран до того, как появится первый компонент со стилями — тогда ловушка захлопнулась бы молча.

    Ядро сняло плагин при переезде на granum, granularity-editor и granularity-code — в 1.0.1, где он уже стрелял. Диагностика css-double-delivery, которая обязана была это назвать, не работала вовсе; починена в @feugene/granum 1.0.2.

  • vite-plugin-lib-inject-css убран из devDependencies: больше не импортируется.

v1.0.02026-09-28

Переезд на @feugene/granum 1.0 и первый мажор пакета.

Публичная поверхность не менялась — ломающий тут сам конвейер: peer-зависимость уезжает с @feugene/unocss-preset-granular на @feugene/granum (>=1.0.0 <2.0.0), а приложение переходит с uno.config.ts на granum.config.ts. Версия выровнена с ядром: @feugene/granularity 1.0.0.

Перед обновлением стоит прочитать руководство по переезду в granum — в частности про каскадные слои и сброс браузерных стилей, который теперь нужно импортировать в слой.

Changed

  • yarn doctor is granum doctor --strict, without a wrapper script. scripts/granum-doctor.mjs existed for two reasons and both are gone. It muted token-undefined through the monorepo’s token registry — granum 0.4.0 derives the same verdict from the code itself (a use with a fallback, a token the component assigns itself and dynamicTokens are not findings), so the registry is unnecessary. And it kept recorded debt from failing the gate — that is now --allow=<codes>. Findings across the eight packages went from 861 to 1, and that one is the deliberate !important on the drag cursor in GrTransfer, recorded through --allow.
  • Safelists in the manifests shrank from 3479 entries to 430 (zero in every companion): granum drops entries that static extraction already covers. Nothing in the sources changed and the CSS is byte-for-byte identical — the safelist there is derived from the component’s own class constants, and whether extraction sees a given class is decided by chunking, not by the author.
  • The utility engine changed: @feugene/granum-engine-wind ^0.4.0 instead of @feugene/granum-engine-mini. It vendors preset-wind3 rather than preset-mini, so the vocabulary gained border-collapse, list-none, touch-none, table-fixed and scroll-p* — utilities that existed neither in preset-mini nor in the former extra rules, which is why a class in the markup silently produced no CSS. The package dialect is now unocss/preset-wind3+granum@66, and the peer on the core moved to >=0.3.0 <1.0.0. A consumer swaps the pair in dev dependencies and replaces miniEngine() with windEngine() in granum.config.*.
  • The package is built by @feugene/granum, not by the @feugene/unocss-preset-granular preset. The dist layout and the component entries are driven by the granumProvider({ provider, engine: miniEngine(), entries }) plugin: it builds them from the provider registry, extracts the classes and the consumed tokens by walking the bundle graph, and writes a machine-generated granum.manifest.json next to dist. The package’s own build.lib, granularChunkFileNames and hand-written component entries are gone from vite.config.ts.
  • The manifest is exported as ./granum.manifest.json. An application resolves it through exactly that subpath — without the export the package’s provider cannot be wired up. granum never scans node_modules: the component classes are computed when the package is built.
  • The peer changed: @feugene/granum >=0.2.0 <1.0.0 instead of the preset. The utility engine comes from the application (@feugene/granum-engine-mini sits in the package’s dev dependencies), while the package declares a vocabulary dialect in the manifest — unocss/preset-mini+granum@66, the vocabulary its component classes are written against. An application running an engine of a different vocabulary gets provider-dialect-mismatch and every lost class listed by name instead of silently half-drawn components.
  • The descriptor contract was renamed without a change of meaning. defineGranularComponent → defineGranumComponent, defineGranularProvider → defineGranumProvider, imported from @feugene/granum/contract. Donors are declared as strings (dependencies: ['@feugene/granularity']) rather than instances: an instance would pull the donor into the graph in object form and make the application scan its dist instead of reading the manifest. packageBaseUrl is gone — the manifest’s directory is the base — so granular-provider/node is now a plain alias of the browser entry.
  • granular.options.mjs was replaced by granum.config.mjs, and yarn doctor runs granum doctor against the package’s manifests.

v0.11.02026-08-30

Added

  • Chart components declare the layer tokens their frame reads. The tooltip of GrChartFrame is positioned by the core’s useFloating: the layer name is passed to it as a parameter and the var() is assembled at runtime inside the core’s overlayStack.ts. Neither var(--gr-z-tooltip) nor var(--gr-z-modal) appears anywhere in this package.

    Measured with granular prune before the change: gr-z-tooltip survived only because the GrChartFrame group ships its shared SFC into a scanned directory, while gr-z-modal was removed outright — a chart opened inside a modal would have lost its tooltip stacking. Nine components now declare both.

    Gated by src/__tests__/dynamicTokens.test.ts, which scans the component directory together with the shared directory of its group, since it is the frame that calls the composable.

v0.10.12026-08-27

Fixed

  • Development warnings never reached the browser: the __GR_DEV__ guard included a typeof process check, and process is undefined in the browser, so the whole expression collapsed to false in development too. The guard now matches the core package. Production bundles are unaffected — the branch is still dropped.

Earlier versions

The bodies of these releases are not shown: the full feed weighs more than a page is allowed to. The file in the repository is always complete.

  • v0.10.02026-08-27
  • v0.9.02026-08-20
  • v0.8.12026-08-20
  • v0.8.02026-08-20
  • v0.7.02026-08-19
  • v0.6.02026-08-19
  • v0.5.22026-08-19
  • v0.5.12026-08-18
  • v0.5.02026-08-18
  • v0.4.02026-08-17
  • v0.3.02026-08-14
  • v0.2.02026-08-13

The package CHANGELOG in full