Marta Ruiz
Product Designer
Email: marta.ruiz@example.com
Phone: +34 600 111 222
Таблица данных и постраничный список для Angular с серверной пагинацией, сортировкой, фильтрацией, выбором, шаблонами и CSS-переменными.
Последнее обновление 20 сент. 2026 г.
Используйте эту библиотеку таблицы данных и постраничного списка для Angular, когда нужны серверные операции, выбор, фильтрация и переиспользуемый рендеринг списков без переписывания логики таблиц в каждом проекте.
npm install ng-hub-ui-paginableng-hub-ui-paginable ориентирована на команды Angular, создающие админ-панели, результаты поиска, CRM-экраны и управленческие back-office. Она сочетает переиспользуемый слой таблицы и списка с операциями, которые обычно важнее всего в продакшене: пагинацией, фильтрацией, сортировкой, выбором и пользовательскими шаблонами.
Основной рендеринг таблицы и пагинация.
Базовое использование таблицы
ID | Name | Email | Role |
|---|---|---|---|
| 1 | John Doe | john@example.com | Admin |
| 2 | Jane Smith | jane@example.com | Editor |
| 3 | Bob Johnson | bob@example.com | User |
| 4 | Alice Brown | alice@example.com | Editor |
Агностические элементы формы
ID | Name | Email | Role | Department |
|---|---|---|---|---|
| 1 | John Doe | john.doe@example.com | Admin | IT |
| 2 | Jane Smith | jane.smith@example.com | Editor | Marketing |
| 3 | Bob Johnson | bob.johnson@example.com | User | Sales |
| 4 | Alice Brown | alice.brown@example.com | Editor | IT |
| 5 | Charlie Wilson | charlie.wilson@example.com | User | HR |
Search and rows-per-page are rendered by ng-hub-ui-forms (hub-input / hub-select). Remove the provider and they fall back to native controls.
Пагинация таблицы
ID | Name | Department | Position | Salary | Email |
|---|---|---|---|---|---|
| 1 | John Doe | Engineering | Senior Developer | 85000 | john.doe@company.com |
| 2 | Jane Smith | Marketing | Marketing Manager | 72000 | jane.smith@company.com |
| 3 | Bob Johnson | Engineering | Frontend Developer | 65000 | bob.johnson@company.com |
| 4 | Alice Brown | HR | HR Specialist | 58000 | alice.brown@company.com |
| 5 | Charlie Wilson | Sales | Sales Representative | 55000 | charlie.wilson@company.com |
Переменные CSS таблицы
ID | Name | Email | Role |
|---|---|---|---|
| 1 | John Doe | john@example.com | Admin |
| 2 | Jane Smith | jane@example.com | Editor |
| 3 | Bob Johnson | bob@example.com | User |
| 4 | Alice Brown | alice@example.com | Reviewer |
ID | Name | Email | Role |
|---|---|---|---|
| 1 | John Doe | john@example.com | Admin |
| 2 | Jane Smith | jane@example.com | Editor |
| 3 | Bob Johnson | bob@example.com | User |
| 4 | Alice Brown | alice@example.com | Reviewer |
Сортировка, фильтрация, выбор и серверные операции.
Базовая сортировка и фильтрация
ID | Name | Role | Status |
|---|---|---|---|
| 4 | Alice Brown | Editor | Active |
| 3 | Bob Johnson | User | Pending |
| 5 | Charlie Wilson | User | Deleted |
| 2 | Jane Smith | Editor | Inactive |
| 1 | John Doe | Admin | Active |
Продвинутая фильтрация (диапазоны и списки)
ID | Product | Price ($) | Added Date | Category |
|---|---|---|---|---|
| 1 | Laptop | 1200 | Sun Oct 01 2023 00:00:00 GMT+0000 (Coordinated Universal Time) | Electronics |
| 2 | Mouse | 25 | Wed Nov 15 2023 00:00:00 GMT+0000 (Coordinated Universal Time) | Electronics |
| 3 | Keyboard | 75 | Mon Nov 20 2023 00:00:00 GMT+0000 (Coordinated Universal Time) | Electronics |
| 4 | Desk Lamp | 45 | Tue Dec 05 2023 00:00:00 GMT+0000 (Coordinated Universal Time) | Office |
| 5 | Chair | 250 | Sun Dec 10 2023 00:00:00 GMT+0000 (Coordinated Universal Time) | Office |
Выбор и пакетные действия
ID | Name | Email | Role | |
|---|---|---|---|---|
| 1 | John Doe | john@example.com | Admin | |
| 2 | Jane Smith | jane@example.com | Editor | |
| 3 | Bob Johnson | bob@example.com | User | |
| 4 | Alice Brown | alice@example.com | Editor | |
| 5 | Charlie Wilson | charlie@example.com | User |
Пакетные действия (batchActions)
ID | Name | Email | Status | |
|---|---|---|---|---|
| 1 | John Doe | john.doe@example.com | Active | |
| 2 | Jane Smith | jane.smith@example.com | Active | |
| 3 | Bob Johnson | bob.johnson@example.com | Inactive | |
| 4 | Alice Brown | alice.brown@example.com | Active | |
| 5 | Charlie Wilson | charlie.wilson@example.com | Inactive |
Операции на стороне сервера
ID | Name | Email | Role | Status |
|---|---|---|---|---|
| 1 | John Doe | user1@example.com | Admin | Active |
| 2 | Jane Smith | user2@example.com | Editor | Inactive |
| 3 | Bob Johnson | user3@example.com | User | Pending |
| 4 | Alice Brown | user4@example.com | Moderator | Active |
| 5 | Charlie Wilson | user5@example.com | Admin | Inactive |
| 6 | Diana Martinez | user6@example.com | Editor | Pending |
| 7 | Edward Taylor | user7@example.com | User | Active |
| 8 | Fiona Anderson | user8@example.com | Moderator | Inactive |
| 9 | George Lee | user9@example.com | Admin | Pending |
| 10 | Hannah White | user10@example.com | Editor | Active |
Раскрывающиеся строки, пользовательские шаблоны, адаптивная компоновка и динамическая стилизация.
Раскрываемые строки и закреплённые столбцы
ID | Name | Role | Email | Actions | |
|---|---|---|---|---|---|
| 1 | John Doe | Admin | john@example.com | ||
| 2 | Jane Smith | Editor | jane@example.com | ||
| 3 | Bob Johnson | User | bob@example.com | ||
| 4 | Alice Brown | Editor | alice@example.com |
Несколько закреплённых столбцов
ID | Full Name | Email Address | Department | Position | Office Location | Salary | Status |
|---|---|---|---|---|---|---|---|
| 1 | John Doe | john.doe@example.com | Engineering | Senior Developer | New York | $120,000 | Active |
| 2 | Jane Smith | jane.smith@example.com | Marketing | Marketing Manager | Los Angeles | $95,000 | Active |
| 3 | Bob Johnson | bob.johnson@example.com | Sales | Sales Representative | Chicago | $75,000 | On leave |
| 4 | Alice Brown | alice.brown@example.com | Engineering | Technical Lead | San Francisco | $140,000 | Active |
| 5 | Charlie Wilson | charlie.wilson@example.com | HR | HR Specialist | Boston | $65,000 | Active |
Тематизируемая шапка и разделитель
Invoice | Client | Amount | Status |
|---|---|---|---|
| INV-1001 | Acme Corp | $3,200 | Paid |
| INV-1002 | Globex | $1,750 | Pending |
| INV-1003 | Initech | $980 | Paid |
| INV-1004 | Umbrella | $5,410 | Overdue |
Закреплённая шапка при прокрутке
[stickyHeader] inside a plain scroll div, the second via the built-in options.scrollable frame. [stickyHeader] (any scroll container)ID | Name | Department | Location | Status |
|---|---|---|---|---|
| 1 | Employee 1 | Engineering | New York | On leave |
| 2 | Employee 2 | Marketing | London | Active |
| 3 | Employee 3 | Sales | Berlin | Active |
| 4 | Employee 4 | HR | Tokyo | Active |
| 5 | Employee 5 | Engineering | New York | Active |
| 6 | Employee 6 | Marketing | London | On leave |
| 7 | Employee 7 | Sales | Berlin | Active |
| 8 | Employee 8 | HR | Tokyo | Active |
| 9 | Employee 9 | Engineering | New York | Active |
| 10 | Employee 10 | Marketing | London | Active |
options.scrollable (built-in frame)ID | Name | Department | Location | Status |
|---|---|---|---|---|
| 1 | Employee 1 | Engineering | New York | On leave |
| 2 | Employee 2 | Marketing | London | Active |
| 3 | Employee 3 | Sales | Berlin | Active |
| 4 | Employee 4 | HR | Tokyo | Active |
| 5 | Employee 5 | Engineering | New York | Active |
| 6 | Employee 6 | Marketing | London | On leave |
| 7 | Employee 7 | Sales | Berlin | Active |
| 8 | Employee 8 | HR | Tokyo | Active |
| 9 | Employee 9 | Engineering | New York | Active |
| 10 | Employee 10 | Marketing | London | Active |
Тёмная ретематизация через селектор тега
hub-table tag selector — no!important. ID | Name | Email | Role |
|---|---|---|---|
| 1 | John Doe | john@example.com | Admin |
| 2 | Jane Smith | jane@example.com | Editor |
| 3 | Bob Johnson | bob@example.com | User |
| 4 | Alice Brown | alice@example.com | Reviewer |
Настраиваемые значки раскрытия
--hub-table-icon-caret-up / --hub-table-icon-caret-down. Product | SKU | Price | Stock | |
|---|---|---|---|---|
| Wireless Mouse | WM-100 | $24.99 | 132 | |
| Mechanical Keyboard | MK-220 | $89.00 | 47 | |
| USB-C Hub | UH-330 | $39.50 | 88 |
Свой набор значков
--hub-table-icon-* variable. Тема одним миксином
Code | Name | Owner | |
|---|---|---|---|
| A-01 | Alpha | Ada | |
| B-02 | Bravo | Alan | |
| C-03 | Charlie | Grace |
Настройка с помощью шаблонов
ID | Name | Role | Status |
|---|---|---|---|
| 1 | John Doe | Active | |
| 2 | Jane Smith | Active | |
| 3 | Bob Johnson | Inactive |
Адаптивный макет и состояния
ID | Name | Role |
|---|---|---|
| 1 | John Doe | Admin |
| 2 | Jane Smith | Editor |
Компоненты состояния по умолчанию
ID | Name | Role |
|---|---|---|
| 1 | John Doe | Admin |
| 2 | Jane Smith | Editor |
| 3 | Bob Johnson | User |
Динамические стили строк (rowClass)
ID | Name | Email | Role | Status |
|---|---|---|---|---|
| 1 | John Doe | john.doe@example.com | Admin | active |
| 2 | Jane Smith | jane.smith@example.com | Editor | inactive |
| 3 | Bob Johnson | bob.johnson@example.com | User | pending |
| 4 | Alice Brown | alice.brown@example.com | Editor | active |
| 5 | Charlie Wilson | charlie.wilson@example.com | User | deleted |
Выбор «мастер — деталь» (rowClass)
Order | Customer | Total | Status |
|---|---|---|---|
| 1001 | Ada Lovelace | $1,240.00 | Paid |
| 1002 | Alan Turing | $890.50 | Pending |
| 1003 | Grace Hopper | $2,415.00 | Paid |
| 1004 | Katherine Johnson | $540.75 | Refunded |
| 1005 | Edsger Dijkstra | $1,975.20 | Paid |
Click a row to open its detail — the active row shows the tint + accent bar.
Select an order to see its detail.
Интернационализация (i18n)
ID | Name | Email | Role |
|---|---|---|---|
| 1 | John Doe | john@example.com | Admin |
| 2 | Jane Smith | jane@example.com | Editor |
| 3 | Bob Johnson | bob@example.com | User |
| 4 | Alice Brown | alice@example.com | Moderator |
| 5 | Charlie Wilson | charlie@example.com | Admin |
| 6 | Diana Martinez | diana@example.com | Editor |
| 7 | Edward Taylor | edward@example.com | User |
| 8 | Fiona Anderson | fiona@example.com | Moderator |
| 9 | George Lee | george@example.com | Admin |
| 10 | Hannah White | hannah@example.com | Editor |
| 11 | Ivan Clark | ivan@example.com | User |
| 12 | Julia Scott | julia@example.com | Moderator |
Дизайн RTL (справа налево)
ID | Name | Email | Role | |
|---|---|---|---|---|
| 1 | John Doe | john@example.com | Admin | |
| 2 | Jane Smith | jane@example.com | Editor | |
| 3 | Bob Johnson | bob@example.com | User | |
| 4 | Alice Brown | alice@example.com | Reviewer |
Порядок нижней панели (переменные CSS)
ID | Name | Role |
|---|---|---|
| 1 | John Doe | Admin |
| 2 | Jane Smith | Editor |
| 3 | Bob Johnson | User |
Гибкие представления списков с теми же мощными возможностями пагинации и выбора.
Список с пагинацией и выбором
Связанный список (таймлайн)
Выбираемый список
pointer cursor; tick the checkbox to select. []nullБез карточек — список, а не стопка карточек
Each row is its own surface. On a page, that is what separates it from the page.
Inside a dialog the frame is already drawn, so the rows only need a rule between them.
Outer border, radius and head rule go; the row divider and the cell padding stay, because those are what keep a table readable across its columns.
Room | Kind | Rate |
|---|---|---|
| Despacho 1 | Office | from 900,00 € / month |
| Sala Timple | Meeting room | from 90,00 € / day |
| Zona compartida | Coworking | from 180,00 € / month |
Редактируемая — поля как в таблице
Product | Quantity | Unit |
|---|---|---|
u. | box | |
u. | box | |
u. | kg |
flushFields — the same controls, read as a sheetProduct | Quantity | Unit |
|---|---|---|
u. | box | |
u. | box | |
u. | kg |
Выбор дерева и что передаёт клик
[](none yet)Переменные CSS списка
hub-list-theme() mixinСписок в виде карточек
Product Designer
Email: marta.ruiz@example.com
Phone: +34 600 111 222
Frontend Engineer
Email: carlos.vega@example.com
Phone: +34 600 333 444
Engineering Manager
Email: lucia.moreno@example.com
Phone: +34 600 555 666
QA Lead
Email: pablo.serra@example.com
Phone: +34 600 777 888
Вложенные списки
Состояния списка: загрузка, ошибка и пусто
fixed: The empty-state notice paints itself, and follows the theme. It was an alert alert-info borrowed from Bootstrap, which this family does not ship: without Bootstrap the notice rendered as bare text with its icon stacked above the sentence, and with Bootstrap it stayed a pale blue panel with dark blue text in a dark theme. It is built from the design system informative roles now, and the sentence measures 14.3:1 in light and 14.6:1 in dark.
added: Eight tokens for that notice, so it can be themed like everything else the table draws: --hub-table-no-data-bg, --hub-table-no-data-color, --hub-table-no-data-border-color, --hub-table-no-data-border-width, --hub-table-no-data-border-radius, --hub-table-no-data-padding, --hub-table-no-data-margin and --hub-table-no-data-gap.
fixed: The table follows the dark theme. Every surface it paints — the cells, the header, the toolbar, the search field, the filter controls — fell back to --hub-ref-color-white, and a reference token is the one thing no theme redefines, so a dark application got light text on white cells with nothing in the console to say so. Those surfaces fall back to --hub-sys-surface-page now, and the quiet ones in the list and the paginator to --hub-sys-surface-elevated. In the light theme both resolve to the same values the literals carried, so nothing moves there; a --hub-table-bg set by the application still wins.
fixed: A header cell keeps its title, its sort control and its filter on one line. The row was laid out by Bootstrap utility classes written in the template, and this family ships no Bootstrap, so in an application without it the three stacked one under another in every sortable column. The cell carries its own rules now — --hub-table-header-cell-gap and --hub-table-header-cell-actions-gap hold the spacing — and the same seam is closed on a row action button, with --hub-table-cell-buttons-gap and --hub-table-cell-btn-content-gap.
added: Three tokens to give the paging bar air, off by default. The bar sits flush against the grid and against its own edges, and justify-content cannot change that: space-around shares the free space out between the items and leaves none outside them, so the paginator ends up against one edge and the row count against the other however it is set. --hub-table-bottom-bar-padding-block, --hub-table-bottom-bar-padding-inline and --hub-table-bottom-bar-spacing hold the gutter, and hub-table-theme() takes them as $footer-padding-block, $footer-padding-inline and $footer-spacing. All three are 0, so no existing table moves.
changed: Repository, issue and README links follow the move to the hub-env organization. Issues for every Hub UI package are now gathered in hub-env/hub-ui, and the repository and bugs fields of the manifest point at the new addresses. No code, types or styles change.
changed: The icon component is HubPaginableIconComponent, and hub-icon is no longer one of its element names. ng-hub-ui-icons exports a HubIconComponent matching hub-icon too, so the two packages claimed one class name and one tag — and a component importing both and writing hub-icon did not compile at all, rejected with NG8023, which reads as a bug in the application rather than as two libraries colliding. The tag now belongs to ng-hub-ui-icons alone; this component keeps ng-hub-ui-icon, which it has always matched, and gains hub-paginable-icon. The class is exported under its new name with HubIconComponent kept as a deprecated alias that goes in 23.0.0, and the component itself is unchanged. Breaking for a template writing hub-icon — see BREAKING_CHANGES.md.
added: placement on hub-paginator, so two paginators are not one name twice. A nav is a landmark, and with paginationPosition="both" the table drew two of them announcing the same "Pagination": a screen reader listed two identical regions and offered no way to choose between them. Each bar now says which end of the table it sits at, translated in every dictionary the package ships, while a lone paginator keeps the plain name it always had. The input is optional and unset by default.
fixed: The JSDoc of five components reaches the published .d.ts. ListComponent, TableComponent, PaginatorComponent, ResizableComponent and PaginableTableRangeInputComponent carried their class documentation between the decorator and the class, where TypeScript associates it with nothing, so it never reached the type declarations and a consumer hovering any of them saw no description at all. The comments sit above the decorator now and travel with the build. Nothing about the API changes.
removed: The TooltipDirective re-export. The directive lived in ng-hub-ui-utils and was forwarded here for the consumers who had imported it from this package before it moved; ng-hub-ui-utils 22.14.0 removes it, because a bare [tooltip] selector is a name in the application namespace rather than a library one, so the forward has nothing left to point at. The table's own tooltips are drawn by HubTableTooltipDirective and are unaffected. Breaking for an application importing TooltipDirective from ng-hub-ui-paginable — see BREAKING_CHANGES.md.
changed: The documentation says where the keyboard marks a row. With selectWhileSelecting on and no clickFn the row carries no tabindex, which reads as a keyboard hole and was reported as one. It is not: every row of a selectable table already draws its own checkbox, a native control that sits in the natural tab order and marks the row when it is ticked, so the row click is a pointer shortcut for a path the keyboard has had all along. Giving the row a stop of its own would double the tab stops of a two-hundred-row table to reach something already reachable. Nothing in the behaviour changes; the input documentation, both READMEs and FUNCTIONALITIES.md now say it, and a test pins it.
changed: Single selection draws a radio, not a checkbox. With [selectable]="true" and no [multiple], the table drew a checkbox per row and then released the previous pick when a second one was ticked: a checkbox says the rows are independent, so the control described something the table does not do, and a screen reader announced it that way too. hub-list in this same package has always drawn a radio here. The radios of one table share a name of that table own, so two single-selection tables on a page do not fight over one choice, and clicking the chosen radio again still clears the selection, which a native radio cannot do on its own. Multiple selection is untouched; the change is announced in BREAKING_CHANGES.md because a stylesheet reaching the box through input[type="checkbox"] stops matching.
fixed: The select-all box in the header lines up with the boxes in the rows again. 22.18.0 gave the row checkbox the whole cell as its hit area, wrapped in a label that centres it, and the header kept a bare input: the two were centred by different rules and the selection column read as two columns that did not quite meet. The header now wears the same label, which also gives the select-all box the generous hit area the row boxes got.
added: The table and the list accept a resource whole, through [resource]. It is typed by its shape rather than by importing ResourceRef, so the package keeps supporting Angular from 18 onwards: any object exposing value, isLoading and error as no-argument functions will do. The value goes through the same reading that [data] already used, so an array becomes rows and a paginated object also sets the page, the size and the total. Bound alongside [data] the resource wins, and changing page does not reload it: the load cycle stays where the consumer put it. A failure is read before the value and the value only when there is none, because a resource in the error state has nothing to hand over and says so by rethrowing from value(); the rows of the last good load stay behind the error state, so a refresh that fails does not cost the reader the table they were looking at.
added: selectWhileSelecting makes a row click mark the row while a selection is under way. Off by default, because changing it for everybody would break consumers who navigate while selecting, and on the desktop a click that suddenly does nothing is more confusing than one that acts. With the input on and at least one row marked, clicking a row toggles it instead of invoking clickFn, and Enter and Space follow the same rule. The mode holds no state of its own: it starts when the first box is ticked and ends when the last one is cleared.
added: A clickable row can be reached and activated from the keyboard. A row given clickFn is a control in every way except the one that matters to somebody not holding a mouse: it had no tab stop and answered to no key, so the action was not there for them. The row now takes focus when clickFn is set and runs on Enter and Space, and it keeps its implicit row role rather than taking role=button, which would nest interactive controls and cost the table its grid semantics. The handler acts only when the row itself has focus, so ticking a checkbox with the keyboard no longer opens the record too.
added: hub-ui-paginator is a name the paginator answers to. The hub-ui- spelling was on the table, the list and the dropdown but not on the paginator, so a template that reached for it matched nothing and rendered an empty element, and this repository CSS reference had been teaching that spelling for as long as it was wrong. hub-paginator and paginable-table-paginator are untouched, and it is the only alias added: nothing documents one for the element names left.
changed: BREAKING - searchFn and compareFn do what the table has been publishing them as. Both were declared inputs the component never read, so binding either changed nothing. searchFn now decides whether a row survives the global search in client mode, and compareFn decides when two selection values are the same record, in markSelected and in both toggles. searchFn changes shape to do it: (a, b) => boolean could not drive a search because it never received a term, so it is now (item, term) => boolean, the same contract hub-list already honours, with the term already trimmed and lowercased. Neither input changes anything while unbound. See BREAKING_CHANGES.md.
changed: BREAKING - every remaining @Input() is a signal input, and the host bindings live in the metadata. ListComponent items, options and batchActions, MenuFilterComponent header, HubIconComponent config and PaginableTableDropdownComponent options were accessor inputs whose setters wrote sibling fields, so those fields were only ever right in the order the setters happened to run. They are inputs with a transform now, and what used to be written by hand is derived. Template bindings are unchanged; reading any of them from TypeScript means calling it. Every component also declares OnPush explicitly, which buys nothing on Angular 22 but puts consumers on Angular 18 to 21 on the strategy the components are written and tested for. See BREAKING_CHANGES.md.
deprecated: HubUITableModule, and the TableModule alias it is exported under. The module declares and exports nothing, so all it does today is carry providers through forRoot(); providePaginable() does that in one line and works in a route providers as well as at bootstrap. Nothing about its behaviour changes, and it is removed in 23.0.0, the release that moves this family to Angular 23. See BREAKING_CHANGES.md.
fixed: Missing the row checkbox by a few pixels no longer opens the row. Only the input stopped the click from reaching the row, and a native checkbox is a fraction of the cell it sits in, so a pointer landing anywhere else in that cell ran the consumer clickFn instead. That commonly navigates, which took the selection built up so far with it. The whole selection cell now stops the click and the control fills it, so there is no near-miss left to catch.
changed: The filter panel, the dropdown and the legacy row-actions menu answer to names this library owns. .filter__* became hub-filter__*, .dropdown__* became hub-dropdown__* and .table-dropdown__* became hub-table-dropdown__*, in line with the hub-table__* and hub-list__* blocks migrated before them. The internal menu-filter element is hub-menu-filter for the same reason: an un-prefixed element name is a global name, and this one was never exported for a consumer to use. See BREAKING_CHANGES.md.
fixed: The package declares a styles entry point, so the theming mixins can be reached the way the README says they can. package.json carried no exports map at all, which left the styles folder ng-packagr copies into the distribution undeclared: the only thing a consumer could import by name was the JavaScript entry. ng-hub-ui-paginable/styles now forwards hub-table-theme and hub-list-theme from one place, and each partial keeps its own subpath.
fixed: The filter panel, the dropdown and the row menus draw themselves, in a product with Bootstrap or without it. They named their appearance after Bootstrap classes, and that failed in both directions at once: without Bootstrap the names resolved to nothing, so the column filter came out as bare text on a transparent box; with Bootstrap the host application owned the appearance of the library internals, and a theme change there reshaped them unasked. Each surface now ships the rules it used to borrow, drawn from the system tokens.
fixed: The paginator speaks the language it was configured in. Its first, previous, next and last controls are icon-only, so the aria-label is the entire accessible name a screen reader gets, and in nine of the eleven shipped languages that name fell through to English because only en and es ever defined those keys. Someone browsing in Catalan or German heard the English words announced with no marked language change. The nine remaining dictionaries now carry their own wording.
fixed: The styling section of the README no longer sends readers to a file that never existed. It told them to import a paginable.scss that is nowhere in the repository, under a src/lib layout the published package does not have, while a later section of the same document gave the path that works.
fixed: paginationInfo actually hides the "showing X of Y" line. The input existed, read the application-wide default and was documented as a working switch, but the template never consulted it, so the line was drawn whatever the consumer asked for.
fixed: paginationPosition puts the pagination bar where it says it does. The READMEs, the functionality table and the playground control all described its three values as placements, but the template drew a single bar under the rows and asked the input only whether to put a paginator inside it: top deleted the paginator instead of moving it, and both was indistinguishable from bottom. The bar is one template now — paginator, page-size selector and row count together — drawn above the rows for top, under them for bottom and in both places for both, each carrying a hub-table__bottom-bar--top or --bottom modifier. No signature changes, and bottom renders exactly what it did before.
fixed: Opening a hub-dropdown no longer writes to the browser console. A debug console.warn about a missing content template fired on every open where the projected content had not landed yet, with no environment guard and no once-only flag.
added: The list, the column filter panel and the row-actions menu publish icon variables of their own. All three drew their glyphs with the table's, so a product that wanted another chevron in the list had to redefine a variable named after the table and got the table changed along with it. Each component declares its own family now, with classes to match: --hub-list-icon-* and .hub-list__icon--*, --hub-filter-icon-* and .hub-filter__icon--*, --hub-table-dropdown-icon-* and .hub-table-dropdown__icon--*. Every default is the glyph that was already there, and the list's magnifier, which had no variable at all, is --hub-list-icon-search.
fixed: The glyphs of the list, the filter panel and the row-actions menu are drawn at all. They asked for hub-table__icon, and a component stylesheet is scoped to that component's own view: the class reached the table and nothing else. The trigger that folds a group of list items was an empty box, the loading, error and no-results messages had no symbol in front of them, the filter panel's add and remove rules were bare words, and the row-actions menu had no dots to click.
fixed: Two arrow glyphs were drawn with a control point on the wrong side of the curve. --hub-table-icon-chevron-down was the mirror of chevron-up in nine of its ten segments, and in the tenth a minus sign was missing, so one arm opened wider than the other. --hub-paginator-icon-angle-double-right, on the last-page button of every paginated table and list, had every vertical offset negated in the closing curve of its second chevron, which hooked that chevron's lower arm upwards. A spec now walks each arrow pair into points and reflects one onto the other, so the next dropped sign fails a test.
fixed: The token catalogue stops promising eight table glyph variables that theme nothing. --hub-table-icon-chevron-up, -down, -left, -right, -angle-left, -angle-right, -angle-double-left and -angle-double-right are each consumed by a .hub-table__icon--* rule, but no template in the package paints those classes and the rules are scoped to the table's own view, so a consumer cannot reach them either. Overriding any of the eight changes nothing on screen, and the reference now says so. The variables stay: removing published API is a decision for a release, not for a documentation pass.
fixed: The column-filter row is visible again. Its controls were dressed in form-control / form-select and the clear button in btn btn-outline-danger — Bootstrap names that resolve to nothing in a product that does not ship Bootstrap, so the row rendered as bare text on the header surface and a filterable column looked exactly like one that offers no filter. The row is now drawn from the table own tokens, exactly as the search field beside it already was.
fixed: The filter row draws its controls on the first render. They are built from filtersFG, and addControl is invisible to change detection: the cells asked the group once, got null, and kept the empty answer until some unrelated event redrew the table. The set of controls is published as a signal now, so a cell appears when its control does.
added: A clear affordance in the search box. While the box holds a term an × appears between the field and the magnifier and empties it in one click, including the keystroke still inside the debounce window. Themed through --hub-table-search-clear-*, labelled by the new CLEAR_SEARCH key in all eleven shipped languages.
added: A filter that holds a value says so: the cell takes hub-table__filter-cell--active and the field wears the same green the menu-filter trigger already uses. An emptied range reads as inactive, so clearing a filter clears its state too.
added: The --hub-table-filter-row-bg / --hub-table-filter-cell-* / --hub-table-filter-control-* families for the filter row and its fields, --hub-table-delete-filters-* for the clear-filters button (toolbar chrome at rest, destructive under the cursor) and --hub-table-search-clear-* with --hub-table-icon-close for the new affordance.
added: provideHubPaginableActions, so the table row buttons and menus are drawn by a real component library instead of by the table itself. What the table drew was markup in Bootstrap class names, which resolve to nothing in a product that does not ship Bootstrap: the menu trigger fell back to the browser default grey button and the panel was a transparent box with no border, shadow or padding. Rather than restyle a second dropdown implementation, the table now describes what a row offers and an adapter draws it. Same arrangement as provideHubPaginableFormControls, and with the same consequence: no new dependency in either direction. Nothing changes in how actions are declared.
added: hidden and disabled on PaginableTableDropdown, so a menu can be refused on a row like any other action.
deprecated: PaginableTableDropdownComponent, and the built-in markup the table falls back to when no adapter is registered. Both still work and nothing breaks by upgrading; the table says so once per application, in production builds, naming the one line that fixes it.
added: disabled on a row action (PaginableActionButton.disabled), boolean or predicate, shaped exactly like hidden. hidden was the only thing you could say about an action that does not apply, and it says the wrong thing half the time: a cancelled payment is not a row where editing does not exist, it is a row where editing has nothing left to act on. Forced to choose, consumers hid the action — so the column changed shape row by row and nothing on screen said why. It reaches the rendered button, so the browser refuses the click and announces the state, and the tooltip still shows, which is where the reason belongs. Row actions only: a batch action is refused by an empty selection, and the predicate is handed a row a batch action does not have.
added: --hub-table-action-disabled-opacity, how far a refused action is faded. The table draws its own buttons, so the browser default never reached them: a disabled action kept its full tint and its pointer and read as pressable. The hover response is cancelled with it.
fixed: The search field's geometry actually reaches it. 22.14.0 claimed this and shipped it inert: the rule was written as ::ng-deep and nested by accident inside the right-to-left block, compiling to a selector confined to a direction most tables are not in and unmatchable even there. It is not a ::ng-deep rule any more, and that is the repair rather than a corrected selector — reaching into a component this table does not own was the wrong shape. Custom properties inherit, so the container states the radius on its own element and whatever fills it reads it; nothing names the control.
added: variant and color on a row action, so it can look like the buttons beside it. The table draws these buttons itself, and hub-buttons styles appearance through :host(...), which matches nothing on an element the primitive did not create — so a consumer who wanted a tinted row action rebuilt the tint in its own stylesheet.
changed: A row action's colour is resolved, not enumerated. color is typed to accept any string on purpose, but the accent arrived as a class the stylesheet matched against seven built-in names: anything else produced a class matching no rule and a button with no accent, no error and no warning. It is a value now, written through resolveHubAccent, so both system roles and a consumer's own colours resolve.
added: flushFields on hub-table: the controls in the cells drawn as a spreadsheet, not as a form. The fields lose their border and surface, a static addon reads as its own content rather than as a chip, and a projected button stops being welded to its neighbour — corners back, a gap, and its own border colour, since two actions in a cell are two things to press. Done by assigning ng-hub-ui-forms tokens to the cells, which is why it reaches your own cell templates; it needs forms 22.21.0 for the seam tokens.
fixed: `flush` keeps the horizontal padding, in the list and in the table. The variant zeroed `--hub-list-item-padding-x` and `--hub-table-cell-padding-x` along with the border, the radius and the surface, which left a checkbox hard against one edge and ran the table columns into each other. Flush drops the chrome, not the space to read in; a consumer who does want the text bleeding to the edge sets the padding token to 0 from outside.
removed: An XML namespace that was declared and never used: the loading spinner carried `xmlns:xlink` on its inline SVG and `xlink:href` appears nowhere in the library. It surfaced as a supply-chain scanner reporting the URL; `http://www.w3.org/2000/svg` stays, because the icons are `data:image/svg+xml` URLs parsed as XML and would not render without it.
fixed: A group row gets no radio in single selection. The control was drawn on every row, so in a list grouped with `bindChildren` a heading became one of the things to choose — picking a building answered with a building, which nobody can book. Only leaves carry a radio now, which is the single-selection twin of the cascade 22.12.0 gave `multiple`.
changed: BREAKING — `clickFn` hands over the item, not the internal wrapper. `ListClickEvent.item` carried the form group wrapping each row (`{selected, collapsed, data, children}`) while the published type said `item: T`, so a consumer reading `event.item.<field>` by the types got `undefined`: no error, no warning, every guard silently false. It is the item now; `value` reads `bindLabel` from the item rather than from the wrapper, and a new `children: T[]` hands over a group's children as items. Adding an alias and deprecating `item` was rejected: it would leave the library carrying, for ever, a field documented as the item that is not one, to protect code depending on a contradiction between the runtime and the type.
changed: BREAKING — a group row selects its children instead of itself. With `bindChildren`, a group's checkbox put the group's own value into the selection and left its children alone, so ticking a building meant "the building", which nobody can book, and a building with one room chosen looked exactly like one with none. Ticking a group now takes everything under it, a partly-selected group renders indeterminate, and only leaves travel in the value.
fixed: Rebuilding `items` no longer clears the selection, nor claims the user did. The setter emptied the form and published the empty selection through the CVA, so a list that merely re-read its data dropped the choice and told the consumer the user had cleared it, with no way to tell a refresh from an edit. The selection is carried across and matched by `bindValue`, only what the new items no longer offer falls out, and nothing is published unless something really went.
fixed: `setDisabledState` disables. It assigned a flag the template never read, so a disabled list still changed its selection. It now disables the form, reaching every `selected` control however deep — through the form and not a `[disabled]` binding, because Angular ignores that binding on a reactive control: it warns and the box stays live.
fixed: `options.searchable` searches. The component rendered a search box wired to a `filter()` whose body was entirely commented out. It filters now, with a `searchTerm` model and an optional `searchFn` — the same two names `hub-table` uses, so the components do not disagree about what "searchable" means. A group survives while any descendant matches, and submitting returns to the first page.
added: `flush` on `hub-list` and `hub-table`: the collection drawn as a list rather than as a stack of cards. Every row wears its own border, radius and surface by default — right for a collection standing on a page, wrong for a list of choices inside a dialog, where a bordered box per row reads as a region of its own and the surface has already drawn the frame. It had to be an input rather than something CSS can reach, and the reason is a trap the whole token catalogue shares: the defaults are declared on the host, which is the very element a consumer puts a class on, so their assignment ties on specificity and loses on source order — silently, which reads as "the token does nothing". Two tokens come with it, read only under the variant: --hub-list-divider-width and --hub-list-divider-color, the rule that stands in for the gap. It falls between siblings only, a group and the collection it opens keep none, and the cards display gets none at all because a grid separated by rules would draw them across the gaps. On the table the row divider survives on purpose.
fixed: The single-selection radio has a rule. It shipped with the mode in 22.10.0 and had no CSS at all — .hub-list__radio matched nothing in the component — so the control rendered at the browser's own size beside a themed list, visibly not part of it. It now takes --hub-list-radio-size, defaulting to the checkbox's since the two are the same control wearing a different rule about how many may be on, and the list's accent.
added: hub-list single selection actually selects. selectable has enumerated single since it shipped and nothing read the value, so a consumer writing selectable="single" got a pointer cursor and silence. Single now renders a radio per row, grouped per list instance so two lists on one page cannot fight over one selection, and it emits the bare value rather than a list of one.
fixed: A value written by the form repainted nothing in single mode. writeValue runs outside the component change detection and the radio is a plain [checked] binding, so patching the control from the consumer form moved the selection internally and left the rendered choice behind.
added: provideHubTableTooltip, to give the table own controls a themed tooltip. Row actions and dropdown entries are drawn from the headers configuration, so their labels were stuck on the native title; registering an adapter routes them to whatever tooltip the application already uses, and without one the native title stays exactly as before.
fixed: Icon-only row actions had no accessible name — title was quietly serving as it. The text is now mirrored to aria-label, but only where the control renders no text of its own, since overriding a visible label with different words breaks WCAG 2.5.3.
fixed: Row-action icons sat low in their buttons. The button took its height from the line box of the glyph, and an icon font glyph is an inline-block resting on the baseline, so a 16px glyph in a 24px line box left the descender gap underneath — 4px above and 8px below on a 28px button. The content row now carries an explicit height and centres the glyph in it: 28px tall, 6/6 exactly. Worth recording that both obvious repairs make it worse — display: flex on the button or the icon host removes the line box that sets the height and collapses it to 20px, and vertical-align: middle overshoots to 7.78/4.22.
changed: Translation lookups now resolve HUBUI.PAGINABLE.* before the legacy flat keys. The table, list and paginator provide the namespace through HUB_TRANSLATION_PREFIX, so an application dictionary can feed them via provideHubTranslationAdapter() without reserving generic top-level keys. Existing flat dictionaries keep working — the bare key is still the fallback.
added: README documentation for the application-wide translation adapter (provideHubTranslationAdapter() from ng-hub-ui-utils).
removed: Removed the @angular/animations peer dependency and the unused table fadeInOut trigger declaration. The package is deprecated upstream and the trigger was never bound in the template. Applications that installed it only for ng-hub-ui-paginable can drop it.
fixed: Documentation links now point at the canonical localized URLs. The README linked to https://hubui.dev/<path> with no locale prefix and no trailing slash, and both forms are 301-redirected, so every reader arriving from npm or GitHub landed on a redirect instead of the canonical page.
added: --hub-table-head-border-width — the header's bottom-border thickness, defaulting to the shared --hub-table-border-width (zero visual change); set it to calc(var(--hub-table-border-width) * 2) for the Bootstrap-style thicker header and it keeps following the base width.
added: --hub-table-head-text-transform (none) and --hub-table-head-letter-spacing (normal) on the header titles — uppercase or tracked column headers without reaching for a th rule.
fixed: Importing the package no longer crashes under SSR: the module-scope navigator access behind DEFAULT_LANGUAGE is now guarded.
removed: Dead internal ViewsService (never exported; its only working method threw 'not developed').
fixed: Table: `[stickyHeader]` now pins the header inside a consumer’s OWN scroll container. The built-in container no longer traps the sticky header (new `--hub-table-container-overflow`, flipped to `visible` when `[stickyHeader]` is set), so a `max-height`/`overflow:auto` box you own keeps the header pinned.
fixed: Table: row/cell background is re-themeable by a plain `hub-table { --hub-table-bg: … }` tag selector (dark mode). The surface tokens are no longer declared on `:host` (which out-ranked the tag rule); each consumption site reads them as `var(--hub-table-bg, <default>)`, so a consumer’s tag rule reaches the cells with NO `!important`, and the sticky header stays opaque via the same fallback.
added: Table: optional selected-row accent bar — `--hub-table-selected-bar-width` (default `0`, no visual change) and `--hub-table-selected-bar-color`. With the `hub-table__row--selected` tint it gives the master-detail “active row” look (tint + leading bar) entirely through tokens and `[rowClass]`. RTL-aware.
added: Table: `[stickyHeader]` input pins the header while the body scrolls, decoupled from the built-in scroll frame — it works inside any consumer `max-height`/`overflow:auto` container. Overridable via `--hub-table-head-position` (default `sticky`).
added: Table: themeable header typography and padding — `--hub-table-head-font-size`, `--hub-table-head-font-weight`, `--hub-table-head-padding-x`, `--hub-table-head-padding-y` (surface/text already existed as `--hub-table-head-bg`/`--hub-table-head-color`). All default to existing values (no visual change).
changed: Table: the selected-row tint now also applies to a consumer-set `hub-table__row--selected` class, so a product can drive the selected look from its own state via `[rowClass]` instead of repainting the row.
added: Table: themeable header, row divider and scroll/sticky-header slots — `--hub-table-head-bg`/`--hub-table-head-color`, `--hub-table-row-divider-color`, and `--hub-table-container-max-block-size`/`--hub-table-head-sticky-top` (a fixed-height scroll body with `options.scrollable` now engages a sticky header). All default to existing values (no visual change).
added: Table: overridable row-expander caret icons via `--hub-table-icon-caret-up`/`--hub-table-icon-caret-down` (same var indirection as the sort icons).
added: List: opt-in item connector (timeline/pipeline) via the `connected` input, themed with `--hub-list-connector-color`/`-width`/`-style`/`-offset`. Default-off, list display only.
fixed: List (cards): long labels no longer overflow their card/grid track — `.hub-list__label` gets `min-width: 0` and wraps unbreakable tokens in cards mode.
changed: Hardcoded style values now read the matching design-system tokens, with the previous literals kept as fallbacks — no visual change. The CSS variables reference was resynchronised with what the code declares, and is guarded from then on by the workspace `tokens-parity` check.
added: Table: automatic client-side pagination. With a plain array in `[data]`, `paginate` true and no `totalItems`, the table searches, filters, sorts and slices the data entirely in memory and computes the total itself.
added: App-wide input defaults via `providePaginable({ defaults })` (`PaginableDefaults`): `paginate`, `perPage`, `perPageOptions`, `paginationPosition`, `paginationInfo`, `searchable`, `debounce`. Instance inputs still win; unset keys keep each component default.
changed: Table: the `paginate` input is now functional (previously inert) — it gates the client-side mode. Passing a `PaginationState` or setting `[totalItems]` keeps server mode. Set `[paginate]="false"` to render a full array unpaginated.
added: Agnostic form-controls integration: the table’s search input and rows-per-page select can be rendered by an external library via `provideHubPaginableFormControls()` and the `HUB_PAGINABLE_FORM_CONTROLS` token, with native `<input>` / `<select>` as the zero-dependency fallback.
changed: `--hub-table-accent` and `--hub-list-accent` became local accent slots: each derives its own `-emphasis`, `-subtle` and `-on` roles on the spot with `color-mix(in oklch, …)`, so overriding the single slot at runtime recomputes the whole family and any accent works — including one of your own, through the theming mixins or a plain `:host` rule.
changed: The semantic `variant` set opened to the nine ng-hub-ui-ds variants (`primary`, `secondary`, `success`, `danger`, `warning`, `info`, `neutral`, `light`, `dark`); it was five.
changed: The selected list item takes its text colour from the derived `--hub-list-accent-on` contrast token instead of a hard-wired white, so a light or custom accent keeps the label legible.
fixed: Design-token consistency pass: inline fallback defaults aligned with the canonical ng-hub-ui-ds values, and hardcoded z-index, font-weight, line-height, radii and theme-aware colours routed through their `--hub-sys-*` / `--hub-ref-*` tokens, so they follow the active theme. No visual change when the ds tokens are loaded.
added: List: native drag-and-drop reordering behind `[sortable]`, in the list and cards layouts and in nested trees, with cross-list transfer between lists sharing a `[dragGroup]`, a Pointer Events fallback for touch, opt-in keyboard reordering via `[keyboardSortable]`, and a typed `(sorted)` output carrying `ListSortEvent<T>`. Projected `[hubListDragHandle]`, `[hubListDragPlaceholder]` and `[hubListDragPreview]` directives and the `HubListDragService` coordinator came with it.
added: `hub-table-theme()` and `hub-list-theme()` Sass mixins: colours, borders, density and footer layout in one call. Every parameter is optional, so only the ones you pass are emitted as `--hub-table-*` / `--hub-list-*` overrides.
added: Semantic `variant` accent on table and list: `options.variant` re-bases a single accent through the `--hub-sys-color-<variant>` family, and the selected row gained styling of its own — until then the `--selected` class carried no CSS at all.
changed: `TooltipDirective` moved to ng-hub-ui-utils so other libraries can reuse it, and is only re-exported here. Its base class changed from `.ng-tooltip` to `.hub-tooltip` and it is themeable through `--hub-tooltip-*`.
added: Table: new `[loadingComponent]`, `[errorComponent]` and `[noResultsComponent]` inputs accept a `PaginableStateDefault` (eager component, lazy loader, or descriptor with input factory).
added: List: same `[loadingComponent]`, `[errorComponent]` and `[noResultsComponent]` inputs added to `hub-list`.
added: `providePaginable({ states })` — global app-level defaults for loading, error and no-results states shared across every paginable component.
added: `PaginableStateOutlet` internal outlet renders the resolved state component with the injected context inputs.
added: `PaginableLoadingDirective` (`loadingTpt`) and `PaginableErrorDirective` (`errorTpt`) exported for per-instance template-based state overrides.
fixed: List: a nested children list rendered flush against its parent item content. A top margin now separates a nested collection from its parent, in the default list and in the card layout.
added: `--hub-list-children-gap`, defaulting to `var(--hub-list-item-padding-y)`, controls that separation.
changed: List: the BEM block now lives on the host element and the <ul> becomes .hub-list__items; backgrounds are controlled via --hub-list-bg (host) and --hub-list-item-bg (items).
added: List: new --hub-list-gap, --hub-list-items-bg and --hub-list-item-bg CSS variables.
fixed: The list card variables (--hub-list-cards-*) and --hub-paginator-font-size were documented but never applied; they now take effect. CSS variables reference fully synced (EN/ES).
removed: Breaking: renamed list --hub-list-container-* variables and removed the non-functional table --hub-table-breakpoint-* variables.
added: Paginator: the previously hard-coded link geometry exposed as CSS variables — `--hub-paginator-link-padding-x/y`, `--hub-paginator-link-border-width`, `--hub-paginator-link-focus-shadow`, `--hub-paginator-transition` and `--hub-paginator-select-border-width`.
added: Table: CSS variables for the filter button geometry and for the active-filter count badge, plus `--hub-table-batch-actions-btn-icon-gap`.
changed: The paginator focus ring derives from `--hub-sys-focus-ring-width` / `-color`, and the filter button and count badge read their colours from design-system tokens instead of Bootstrap variables and literal hexes, so both follow the active theme.
added: List: a dedicated `--hub-list-cards-*` set so the card layout can be themed independently of the list layout, plus `--hub-list-cards-columns`, `-row-gap`, `-column-gap` and `--hub-list-item-border-width`.
changed: Card items consume those variables, with defaults inherited from the existing `--hub-list-item-*` values, so the rendered output is unchanged until they are overridden.
changed: The table dropdown menu uses the native `[style]` binding instead of the soft-deprecated `ngStyle` directive.
added: List: `options.display = "cards"` renders the root items as a card grid, with tokens for column sizing and card spacing.
changed: List: root rendering tracks by `bindValue`, `id` or index, and the internal markup and state classes were normalised so the list and card layouts share them.
fixed: Table: the bottom pagination bar is rendered only when pagination is enabled, instead of leaving an empty wrapper behind.
added: Library BEM classes for table, list and dropdown action buttons when no class list is given, plus CSS variables for the list action buttons and the top bar.
changed: `color` was removed from `PaginableActionButton` to keep the action configuration CSS-framework agnostic; appearance travels through `classlist` and the normalised class helpers.
removed: The legacy `RowButton` and `ListButton` interfaces, superseded by the unified `PaginableActionButton`.
added: More locale dictionaries, and a bottom-bar ordering example covering table and list together.
changed: Table and list bottom bars share one structure and behaviour (paginator, settings, info) with mirrored layout tokens, and the context pagination tokens `--hub-table-pagination-*` / `--hub-list-pagination-*` map onto the paginator styles.
fixed: The list per-page handler accepts both a plain number and an event.
changed: Version aligned with Angular 21. `PaginableListComponent` was renamed to `ListComponent` and `PaginableTableNotFoundDirective` to `PaginableNoResultsDirective`; both former names are still exported, and `BREAKING_CHANGES.md` documents the migration.
added: List: a per-page selector and pagination info of its own, matching the table.
changed: The paginable styles were consolidated around `src/lib/styles/paginable.scss`, and the styling sections of both READMEs now point at the CSS variables reference instead of restating it.
fixed: List: `ngModel` selected items match the visual selection again, root-level pagination renders only the current slice, and the paginator arrows reappeared after its icon tokens were mapped to the shared icon variables.
added: `tooltip` on the row button interface, and `Observable<string>` accepted for `title` and `tooltip` on `PaginableTableDropdown`, so a menu can be translated reactively.
changed: Row buttons prefer `label` over `title` for the visible text, and every label, title and tooltip is unwrapped through `unwrapAsync`, so an Observable value updates in place.
added: Table: the `rowClass` input, taking a fixed string or a function of the row, for dynamic row styling.
fixed: `items` and the dropdown, list-button and pagination-state interfaces accept `ReadonlyArray`, so an immutable data source no longer fails to type-check.
changed: List: `bindValue`, `bindLabel`, `bindChildren`, `selectable`, `clickFn` and the content queries migrated to signal inputs.
fixed: `ListComponent`’s `items` input and `PaginationService.generate` accept a readonly array alongside a mutable one.
changed: The ng-hub-ui-utils peer dependency moved to 1.2.0.
changed: The translation service is `HubTranslationService`, replacing the paginable-specific one, and the list implementation was repaired alongside it.
fixed: The build consumes the compiled ng-hub-ui-utils from `dist/` rather than its sources, `PaginableTableConfig` is exported from the public API again, and the conflicting `package.json` entries behind the ng-packagr warnings are gone.
added: Unit test coverage across components, directives, services and utilities.
changed: The shared utility pipes moved to ng-hub-ui-utils, and the table template and the list, dropdown, paginator and resizable styles were cleaned up.
removed: The Storybook configuration, the local copies of the shared pipes and the legacy `table2` stylesheet.
fixed: Template typing errors resolved, so the library builds again.
added: Ability to customize rows with templates
changed: Replaced Lodash function calls with custom functions
added: Ability to control pagination by passing a Laravel pagination object
added: Result sorting and sort events
ng-hub-ui-paginable создана для серверных данных: вместо массива вы передаёте функцию, которая получает текущую страницу, размер страницы, сортировку и фильтры и возвращает подходящие строки вместе с общим количеством. Компонент держит пагинатор, состояние сортировки и фильтры в согласии с тем, что вернул ваш API.
Отметьте колонки, которые нужно закрепить, и заголовок останется видимым, пока тело прокручивается. В ng-hub-ui-paginable есть также HubStickyColumnsDirective для закрепления колонок в начале или в конце таблицы — это нужно широким таблицам, где первая колонка определяет строку.
Да. PaginableTableCellDirective позволяет взять отрисовку любой колонки на себя, поэтому в ячейке могут быть значки, кнопки, ссылки или целый компонент вместо простого текста. Колонка сохраняет сортировку и фильтрацию, а вы управляете только тем, что нарисовано.
Объявите фильтр в описании колонки — PaginableTableHeader поддерживает текстовые фильтры, выпадающие списки, логические значения и диапазоны для каждой колонки. Активные фильтры уходят в ваш источник данных вместе со страницей и сортировкой, поэтому фильтрация работает одинаково и с локальными данными, и с данными из API.