@feugene/granularity-charts
Releases of @feugene/granularity-charts from its CHANGELOG: the latest 8 in full, the earlier ones as a list of versions.
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-granularity1.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/granum1.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 doctorisgranum doctor --strict, without a wrapper script.scripts/granum-doctor.mjsexisted for two reasons and both are gone. It mutedtoken-undefinedthrough 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 anddynamicTokensare 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!importanton the drag cursor inGrTransfer, 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.0instead of@feugene/granum-engine-mini. It vendorspreset-wind3rather thanpreset-mini, so the vocabulary gainedborder-collapse,list-none,touch-none,table-fixedandscroll-p*— utilities that existed neither inpreset-mininor in the former extra rules, which is why a class in the markup silently produced no CSS. The package dialect is nowunocss/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 replacesminiEngine()withwindEngine()ingranum.config.*. - The package is built by
@feugene/granum, not by the@feugene/unocss-preset-granularpreset. Thedistlayout and the component entries are driven by thegranumProvider({ 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-generatedgranum.manifest.jsonnext todist. The package’s ownbuild.lib,granularChunkFileNamesand hand-written component entries are gone fromvite.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 scansnode_modules: the component classes are computed when the package is built. - The peer changed:
@feugene/granum>=0.2.0 <1.0.0instead of the preset. The utility engine comes from the application (@feugene/granum-engine-minisits 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 getsprovider-dialect-mismatchand 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 itsdistinstead of reading the manifest.packageBaseUrlis gone — the manifest’s directory is the base — sogranular-provider/nodeis now a plain alias of the browser entry. granular.options.mjswas replaced bygranum.config.mjs, andyarn doctorrunsgranum doctoragainst the package’s manifests.
v0.11.02026-08-30
Added
-
Chart components declare the layer tokens their frame reads. The tooltip of
GrChartFrameis positioned by the core’suseFloating: the layer name is passed to it as a parameter and thevar()is assembled at runtime inside the core’soverlayStack.ts. Neithervar(--gr-z-tooltip)norvar(--gr-z-modal)appears anywhere in this package.Measured with
granular prunebefore the change:gr-z-tooltipsurvived only because theGrChartFramegroup ships its shared SFC into a scanned directory, whilegr-z-modalwas 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 atypeof processcheck, andprocessis undefined in the browser, so the whole expression collapsed tofalsein 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-27v0.9.02026-08-20v0.8.12026-08-20v0.8.02026-08-20v0.7.02026-08-19v0.6.02026-08-19v0.5.22026-08-19v0.5.12026-08-18v0.5.02026-08-18v0.4.02026-08-17v0.3.02026-08-14v0.2.02026-08-13