@feugene/granularity
Релизы @feugene/granularity из его CHANGELOG: последние 8 целиком, более ранние — списком версий.
Записи релизов — авторский текст библиотеки, и он английский. Портал его не переводит: журнал изменений — история чужого репозитория, а переписанная история перестаёт быть историей.
v1.1.12026-10-16
Fixed
- Манифест знает части составных компонентов. Пакет собран granum 2.1: его
сборка записывает в манифест 22 части у их владельцев (
GrListItemуGrList,GrTabPanelуGrTabPanels, восемь частейGrDropdownMenu) — полеsubcomponents. Приложение на granum 2.1 сводит подпуть части к владельцу: часть, импортированная при селекции без владельца, —ComponentOutsideSelectionErrorна владельце,components: 'imports'берёт владельца в селекцию, аgranum doctorбольше не предупреждаетsubcomponents-missing(с нимdoctor --strictу приложения на 2.1 падал). Peer granum прежний —>=2.0.0 <3.0.0: granum 2.0 поле не читает и судит импорт части, как раньше.
v1.1.02026-10-16
Переезд на @feugene/granum 2.0 и @feugene/fint-i18n 0.9. Приложению — поднять
@feugene/granum и @feugene/granum-engine-wind до ^2.0.0 и пройти раздел
«From 1.x to 2.0» в MIGRATION.md granum: неизвестный ключ granum.config там
стал ошибкой. @feugene/fint-i18n, если стоит, — ^0.9.0.
Changed
- Peer
@feugene/granum—>=2.0.0 <3.0.0. Пакет собран granum 2.0. Формат манифеста прежний, но рецепты темизации и запрет корневого импорта, на которые опирается документация, работают только с 2.0. - Компонент из корня пакета — ошибка сборки приложения. С granum 2.0
import { GrButton } from '@feugene/granularity'даётComponentRootImportErrorподjs.guard: селекция видит компонент только по подпути, а корень тянет весь пакет. Компоненты берут из@feugene/granularity/components/<Имя>илиvirtual:granum/components; утилиты, плагины, константы и типы из корня — можно. README и документация переведены на подпути. - Необязательный peer
@feugene/fint-i18n—>=0.9.0 <1.0.0. Пакет тестируется на 0.9; на 0.7 и 0.8 он не проверялся, и обещать их диапазон было нечем. Ломающее в fint 0.8 (beforeLoadBlockполучает{ block, locale }) пакет не задевает. - Контракт адаптера переводов — необязательное поле
setLocale. Так язык меняет инстанс@feugene/fint-i18n, который подключается адаптером как есть.
Fixed
distне импортирует granum. Дескрипторы компонентов тянули@feugene/granum/contractв рантайм, и SSR-сервер с внешними пакетами, задеплоенный с--omit=dev, падал на первом компоненте сERR_MODULE_NOT_FOUND. Сборка granum 2.0 встраивает контракт вdist/granum/contract.js; снаружи у чанков остались толькоvueи@floating-ui/dom.- Рецепты темизации действуют.
themes.tokenOverridesиthemes.define.<тема>.tokensRefвстают после файла темы пакета под его селектор и побеждают;themes.define.<имя>сextends: 'dark'наследует значения тёмной темы. granum 1.x ставил эти блоки раньше файлов тем, и рецепты не действовали. Ключ с--вtokenOverrides—InvalidConfigError, а не----gr-*. localeуGrConfigProviderпереключает язык инстанса fint-i18n. Провайдер звал толькоsyncLocaleиз контракта адаптера, а уFintI18nтакого метода нет — язык там меняетsetLocale().<GrConfigProvider locale="en">при рекомендованном стеке молча ничего не делал. Теперь безsyncLocaleпровайдер зовётsetLocale; это закреплено тестом с настоящимcreateFintI18n.
Docs
localization.md: раздел «Своё i18n: адаптер» — поля контракта и проверенный пример дляvue-i18n; версия fint-i18n — 0.9; смена языка —setLocale()или пропlocaleуGrConfigProvider.theming.md:define.<тема>.tokensRefне заменяет файл пакета, а ложится поверх него — файлу достаточно изменённых ролей; третья тема —defineсextends; ключthemes.themeFilesпресета v1 убран отовсюду.getting-started.md: голому Node инлайнserver.deps.inlineне нужен — чанки не импортируют ни.css, ни granum; авто-импорт — одинGranularityResolver().unplugin.md,companion-packages.md: единый резолвер на ядро и спутники, своему пакету./resolverне нужен.installation.md,granum.md,components.md,README.md: granum 2.0,distбез granum, компоненты — из подпутей.
v1.0.212026-10-13
Fixed
- Подсказка пустого нативного
GrSelect— цветом подсказки. Опция-подсказка из 1.0.20 и опция очистки рисовались цветом значения и читались выбранными. Пока поле пустое, текст<select>—--gr-muted-fg, как::placeholderуGrInput, а опции раскрытого списка — обычным цветом. Пустое поле помеченоdata-gr-select-empty. Цвет ставится стилем в строке: утилиты с теми же телами сливались с общими правилами и сдвигали их порядок — у элементов с двумя классами цвета менялся победитель.
v1.0.202026-10-13
Fixed
- Пустой нативный
GrSelectбезclearableне показывает первую опцию. Пустую опцию поле рисовало только сclearable; без неё и без выбранной опции браузер ставил первую сам — поле показывало «Germany» при пустой модели,select.valueуходил в форму «DE», а форма из схемы писала «This field is required» прямо под «Germany». Теперь пустая модель одиночного нативного выбора показывает опцию-подсказку<option value="" disabled hidden selected>с текстомplaceholderили переведённым «Select…»; выбрать её обратно нельзя, а сclearableостаётся прежняя опция очистки.
Added
- Строка
gr.select.placeholder— подсказка пустого нативного выбора: «Select…», «Выберите…», «Seleccione…».
v1.0.192026-10-13
Fixed
- Цвет динамики
GrStatisticследует полярности. Строка под значением красила рост зелёным, а падение красным при любойpolarity: растущий отток получал зелёную стрелку, падающая просрочка — красную. Теперь тон динамики считаетdeltaTone(направление, полярность):negative-goodкраситupвdanger,down— вsuccess,none— без тона. Без полярности рост по-прежнему хорош.
Added
trendPolarityуGrStatistic. Полярность только для динамики: абсолютному показателю (отток 2.4 %) знака у значения нет, иpolarityкрасила бы само число красным за то, что оно положительное. СtrendPolarity="negative-good"значение остаётся нейтральным, а «↑ +0.6 п. п.» — красным. Не задан — берётсяpolarity; настраивается и черезGrConfigProvider.
v1.0.182026-10-07
Fixed
- Значения
GrJsonViewerв узкой панели не пропадают. Ключ не сжимался и в глубоком узле на 232px забирал всю строку: значение обрезалось до нуля, и уamount_paidне было видно ничего. Теперь ключ и значение сжимаются вместе (ключ — охотнее), а у значения остаётся минимум в 5 знаков; остальное уходит в многоточие.
v1.0.172026-10-07
Fixed
- Поиск в панели
GrTreeSelectне забирает контекстGrFormField. Внутри поля сrequiredи ошибкой поиск получал id контрола — тот же, что у триггера (дубль в DOM навсегда: поиск живёт в DOM и при закрытой панели), — а с ним подсказку и ошибку вaria-describedby,aria-requiredиaria-invalid: скринридер объявлял поиск «обязательным, с ошибкой». Теперь вспомогательные поля внутри контролов стоят за границей контекста поля и называются сами: поискGrTreeSelectиGrSelect, поискGrTransfer, hex уGrColorPicker. - Подсказка поиска видна.
GrInputгасил placeholder на фокусе, а панельGrTreeSelectуводит фокус в поиск сразу — «Search…» не был виден ни разу. Уtype="search"placeholder теперь остаётся, пока поле пустое; у прочих полей — как прежде. - Строки дерева в панели
GrTreeSelect— на шаге контрола. Наmdдерево наследовало кегль страницы, и строки в панели были 16px против 14px у поля. Теперь панель набирается кеглем контрола своего размера. - Заголовок группы
GrTreeSectionsбез внешних отступов. СheadingLevelон — настоящий<h2>…<h6>, и базовый слой страницы (h2 { margin-block: 2.5rem 1rem }) раздвигал группы: секция на 147px при заголовке в 21px. Теперь у заголовкаm-0, отступы задаютgapкорня и секции.
v1.0.162026-10-07
Changed
GrTextareaвсегда в обёртке. Раньше без кнопки, признака и счётчиков корнем был сам<textarea>. Теперь корень — обёрткаdata-gr-textarea-wrap:classиstyleпотребителя ложатся на неё, остальные атрибуты (aria-*,data-*,spellcheck) — на<textarea>, как уGrInput. Селекторы потребителя видаtextarea.my-classстоит заменить на.my-class textarea.- В вертикальном
GrTabsсодержимое вкладки — у начала. Колонка разделов настроек («Profile / Security 1 / Notifications / Delete account») с центрированным содержимым ставила значки рваной линией и читалась меню из кнопок. Теперь в колонке значки — ровной линией, подпись занимает остаток, бейдж и крестик — у конца; в ряду вкладки центрированы, как прежде. То же правило, что у вертикальногоGrSegmented;GrTabsWithPanelsполучает его вместе сGrTabs.
Fixed
GrTextareaне теряет фокус посреди набора. Обёртка появлялась вместе с признаком состояния, кнопкой очистки или счётчиком, и<textarea>пересоздавался: на «1100-445»stateстановилсяsuccess, фокус уходил на<body>, и «␣Lisboa» не набиралось никуда. Теперь разметка одна и та же, соседи лишь появляются рядом с полем; поле внутри блочное, и высота с ними и без них одинакова (раньше под строчным<textarea>оставался зазор базовой линии в 5px).- Первая строка
GrTextarea clearableне уходит под «×». Поле держало обычный отступ справа, а кнопка шириной 24px лежала поверх текста. Теперь место под кнопку (и под признак состояния рядом с ней) зарезервировано, пока кнопка может появиться. DeleteуGrTabsзакрывает вкладку под фокусом, а не выбранную. Обработчик брал индекс из роверного ключа, который отставал от фокуса: при программном фокусе и вactivation-mode="manual", где фокус и выбор законно расходятся,Deleteна «payment-failed.mjml» эмитилclose('invoice-paid.mjml'). Теперь вкладка берётся из самого события — тот же путь и уEnter/Spaceв ручном режиме.- Закрытый последний тост не роняет фокус на
<body>. Пришедший в стекGrToasterпоF6и закрывший тостDeleteоказывался в начале документа. Теперь фокус переходит на соседний тост, а когда тостов не осталось — туда, откуда пришли в стек (его запоминаютF6иfocus()), если тот элемент ещё в документе. Так же — крестик и кнопки действий сdismissOnClick, когда фокус на них. - Выключенный
GrTooltipне держит таб-стоп. Обёртка вокруг нефокусируемого триггера оставалась остановкойTabи сdisabled: список клиентов, где подсказка включена только у обрезанного имени, давал по остановке на каждую строку. Теперь без подсказки обёртка снимаетtabindexиaria-describedby. Заодноblockприжимает содержимое триггера к началу, как строку списка, а не к центру.
Более ранние версии
Тела этих релизов не показываются: лента целиком весит больше, чем страница имеет право весить. Файл в репозитории всегда полон.
v1.0.152026-10-07v1.0.142026-10-07v1.0.132026-10-07v1.0.122026-10-07v1.0.112026-10-06v1.0.102026-10-06v1.0.92026-10-06v1.0.82026-10-06v1.0.72026-10-06v1.0.62026-10-06v1.0.52026-10-06v1.0.42026-10-06v1.0.32026-10-06v1.0.22026-10-05v1.0.12026-09-29v1.0.02026-09-28v0.53.12026-09-11v0.53.02026-09-11v0.52.02026-09-10v0.51.02026-09-10v0.50.02026-09-09v0.49.02026-09-06v0.48.02026-09-06v0.47.02026-09-05v0.46.02026-09-04v0.45.02026-09-03v0.44.02026-09-03v0.43.02026-09-02v0.42.02026-09-01v0.41.02026-08-31v0.40.02026-08-30v0.39.02026-08-29v0.38.02026-08-28v0.37.02026-08-27v0.36.02026-08-27v0.35.02026-08-25v0.34.22026-08-25v0.34.12026-08-25v0.34.02026-08-25v0.33.02026-08-25v0.32.02026-08-24v0.31.12026-08-23v0.31.02026-08-23v0.30.02026-08-23v0.29.12026-08-22v0.29.02026-08-22v0.28.42026-08-22v0.28.32026-08-22v0.28.22026-08-22v0.28.12026-08-22v0.27.22026-08-20v0.27.12026-08-19v0.27.02026-08-19v0.26.02026-08-18v0.25.02026-08-18v0.24.12026-08-18v0.24.02026-08-18v0.23.02026-08-17v0.22.02026-08-17v0.21.12026-08-17v0.21.02026-08-17v0.20.02026-08-13v0.19.02026-08-13v0.18.02026-08-12v0.17.02026-08-12v0.16.02026-08-11v0.15.02026-08-07v0.14.02026-08-05v0.13.02026-07-28v0.12.02026-07-20v0.11.02026-07-19v0.10.02026-07-17v0.9.42026-06-23v0.9.32026-06-09v0.9.22026-06-08v0.9.12026-06-07v0.9.02026-06-02v0.8.02026-06-01v0.1.0