@feugene/granularity-devtools
Релизы @feugene/granularity-devtools из его CHANGELOG: последние 8 целиком, более ранние — списком версий.
Записи релизов — авторский текст библиотеки, и он английский. Портал его не переводит: журнал изменений — история чужого репозитория, а переписанная история перестаёт быть историей.
v2.1.12026-10-21
Changed
- Пакет токенов —
^2.0.0. Каталог тем без темы по умолчанию и с версиями тем; панель читает тот же каталог и те же данные тем, что и раньше. Peer@feugene/granularity—>=2.4.0 <4.0.0: совместима и с ядром 3.
v2.1.02026-10-21
Changed
- Раздел «Тема» — по текущей теме документа. Режимы и пары берутся у темы, на которую переключено
приложение (
setTheme), а источник «сохранено пользователем» сверяется с ключом выбора (<тема>-<режим>у дополнительной темы,themeSelectionKeygranum). Читает манифест granum 3.8 и состояние темы ядра 2.4: peer@feugene/granum—>=3.8.0 <4.0.0,@feugene/granularity—>=2.4.0 <3.0.0.
v2.0.02026-10-19
Changed
- Peer
@feugene/granularity—>=2.0.0 <3.0.0. Панель читает тему и режим ядра 2 (параdata-theme, манифест режимов granum 3); с ядром 1 ей показывать нечего. - Раздел «Granularity app» показывает тему и режим. Тема сборки, режим с его
colorScheme, набор режимов из манифеста и пара на корне приложения; разошлась пара с режимом состояния — видны обе. Читается новое состояниеuseThemeядра (манифест иmode); источник режима иsystem prefers dark— как прежде.
v1.0.02026-09-28
Привязка к мажору ядра: peer на @feugene/granularity стал >=1.0.0 <2.0.0.
Прежний диапазон (>=0.38.0 <1.0.0) исключал ядро 1.0.0, и после его выкатки
установка этого пакета рядом с ним давала неудовлетворённый peer: у npm
предупреждением, у pnpm и yarn berry со строгими настройками — отказом установки.
Собственный API не менялся. Для потребителя на @feugene/granularity 0.x это
всё равно ломающее изменение: новая версия на старое ядро не встанет — оставайтесь
на предыдущем релизе или обновляйте ядро вместе с ним.
Fixed
- Required props of subcomponents are checked too. The map is generated from the core’s
web-types.json, which used to skip subcomponents; with the core describing them,GrFormErrorBanner,GrUploadErrorBanner(error),GrSidebarItem(label) andGrTabPanel(value) join the map.
v0.3.22026-08-31
Fixed
- Карта обязательных провайдеров пересобрана после переезда
GrCodeBlockиз ядра в@feugene/granularity-code: панель больше не спрашивает провайдер у компонента, которого в ядре нет.
v0.3.12026-08-28
Changed
-
The rationale for “tokens resolving to nothing” is corrected in the README. Preset
0.15.0closed thethemes.tokensFileblind spot the section was justified by — the fix landed on the feedback this package filed. Swapping the token file onapps/playgroundnow movesdoctorfrom 8 findings to 52.What the panel adds is no longer “the static check is blind here” but “the static check answers a different question”: not «does any layer define this token in this configuration» but «is it empty right now, on this element». Measured on the same stand — healthy:
doctor8, panel 0; swapped:doctor52, panel 11. The eight on a healthy stand are tokensGrAlertassigns itself with an inline style, which static analysis cannot tell apart from undefined.
v0.3.02026-08-28
Added
-
“Tokens resolving to nothing” section on the component inspector — a
--gr-*token that a rule of the component reads without a fallback while the browser resolves it to empty. Such a declaration is dropped at computed-value time, so the component renders with no background, no border, square corners — on a green build and valid CSS.The idea comes from
token-undefined, added togranular doctorin preset0.14.0. The static check is blind where applications get it wrong most often:themes.tokensFilereplaces the package’stokens.css, but the doctor treats the union of both files as defined. Measured onapps/playgroundagainst0.14.1, which closed the same gap forthemes.themeFilesbut not forthemes.tokensFile: with the token file swapped,getGranularThemeCssdrops from 22 504 to 15 703 bytes and loses--gr-radius-control, the doctor still reports the same 17 findings as before, and the panel names 11 empty typography and motion tokens.Only
--gr-*counts. UnoCSS reads its own--un-shadow-inset,--un-ring-insetand--un-space-y-reversewithout fallbacks across the utility layer; on a clean stand that is three findings of somebody else’s internal machinery. -
“Tokens the component reads” — four sections by owner:
own,from other components(named, so it is clear whose token a change would also touch),foundationandunregistered. Each row carries the value from computed style and ahas fallbackmark.This is the reverse of the existing “component tokens” section, and neither set contains the other: a declared token may go unconsumed, while what a component consumes is mostly somebody else’s. A live
GrButtonon the playground reads twelve tokens, two of them its own. The chain is visible too —--gr-button-primary-bg, the customisation point, resolves to#e546bdbecause its fallback is--gr-primary, which the app repainted. -
The stylesheet index now also maps class → tokens its rules read, with a per-token “read without a fallback at least once” flag, reusing the same walk that backs “classes without rules”:
@media/@supports/@layerincluded, the lastvar()of a fallback chain counted (empty, it drops the declaration just the same).
v0.2.02026-08-28
Added
-
Console bridge
window.__GR_DEVTOOLS__withsnapshot(),waitFor(predicate, options)andversion. Tests see only the DOM, so “wait until the overlay layer is registered” used to be written as “wait 300 ms”; the bridge answers that from the same snapshot the panel draws for a human. It works without the panel being open: the issue log and the channel subscription now live ininstallGranularityDevtools()rather than inside the DevTools setup, which only runs once someone opens the tab. -
E2E on the showcase covering the bridge — the overlay stack is asserted without a single
waitForTimeout. -
Layers are named after the component that opened them —
GrPromptDialog #3instead ofModal #3— in the tree, in the state and in the timeline. -
Focus section for each layer: whether focus is still inside, whether it will be restored on close and to which element. “Focus is inside” and “focus will be restored” are separate rows on purpose: they diverge for a layer opened with
restoreFocus: false. -
The inspector and the bridge now read the stack on demand via
readLayers()instead of replaying the last event, so focus is shown as it is now rather than as it was when the stack last changed. -
“Granularity toasts” section — the queue behind the visible stack: how many are alive, the ceiling (
maxToasts) above which the oldest are evicted, each toast’s tone, remaining timer and dedupe key. Withoutapp.use(granularityToastPlugin)the queue lives in a module singleton and cannot be read from outside — the section says so instead of showing an empty list that reads as “no toasts”. -
Virtual list section on the component: rendered against total, the window
[start, end), the size estimate and the measured average, with a note when the two drift far enough to make the list jump. Measured on the showcase:GrDataTablewith 10 000 rows renders 14, window[0, 14), estimate 49 px against 45 px measured. -
“Granularity app” section — state that belongs to the application rather than to a component: the theme with its source (saved by the user, system preference, or persistence off — the answer to “why is it dark, I picked light”) and the toast queue.
-
“Classes without rules” section — classes on the component’s root and descendants that no CSS rule matches. This is what a safelist miss looks like from the browser: sizes work, colours are transparent, focus rings are gone. The selector index is built once per session and invalidated when
<style>/<link>nodes change; cross-origin sheets cannot be read, and the section says the list is incomplete instead of staying silent. -
Options:
checks: 'all' | 'off'turns off the missing-required-prop scan that runs on every tree node, andeventLimitsets the depth of the core’s event buffer. -
JSON report action in the overlays section: layers, virtual lists, warnings and versions, copied to the console and — when the browser allows it — to the clipboard.
Changed
- The console interception moved from the “Issues” section to
install, and the log gainedsubscribe(): the section now follows the log instead of filling it. Restoring the console puts back the original functions, notbind-ed copies — the previous version layered a wrapper on every attach cycle.
Более ранние версии
Тела этих релизов не показываются: лента целиком весит больше, чем страница имеет право весить. Файл в репозитории всегда полон.
v0.1.12026-08-27v0.1.02026-08-27