najm-kit 2.9.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,174 +1,263 @@
1
- # Changelog
2
-
3
- ## 2.9.0 - 2026-08-09
4
-
5
- - Added `najm-kit/server`, a pure UI bootstrap loader. `createUiBootstrapLoader()`
6
- takes the application's own fetcher, endpoint paths, payload parsers, and
7
- factory values, then runs the resources concurrently, unwraps the `{ data }`
8
- envelope (or one the application selects), and falls back per resource so a
9
- branding outage never discards a valid appearance. Failures are reported
10
- through an optional structured `onDiagnostic` callback carrying resource,
11
- reason, path, and status never a response body, header, cookie, or raw
12
- thrown value. A `fallback()` that throws stays a visible error. The entry
13
- imports no React, no Next.js, and no Node built-in, and re-exports
14
- `parseNajmDesignConfig` so an appearance payload can be parsed without
15
- reaching the root barrel.
16
- - Added `najm-kit/server/react`, the React Server Component adapter.
17
- `createReactServerUiBootstrap()` memoizes one bootstrap per request with
18
- React's `cache()` and derives the per-resource accessors from it, so a root
19
- layout, a nested layout, and a page share one resolution and one stable
20
- snapshot for the whole render. Resolution is request-scoped only: separate
21
- requests share no snapshot, failure, or diagnostic, and a transient outage is
22
- retried on the next request. The `browser` export condition resolves to a
23
- module that throws, so importing the adapter from a Client Component fails at
24
- build time instead of shipping the application's fetcher and factory values
25
- into a browser bundle.
26
- - The root `najm-kit`, `najm-kit/next`, and `najm-kit/app` entries are unchanged
27
- and do not reach either server entry.
28
-
29
- ## 2.8.2 - 2026-08-08
30
-
31
- - Added the framework-neutral `najm-kit/person-images` subpath. It ships a
32
- built-in resolver for `child`, `adult`, `parent`, and `family` roles with
33
- the seven WebP illustrations embedded as base64 data URLs, plus
34
- `createPersonImageResolver` so an application can declare its own role
35
- names (`teacher`, `student`, `doctor`, `driver`, …) and TypeScript catches
36
- unknown role strings at the call site. The root `najm-kit` entry stays
37
- unchanged and does not pull in the person images.
38
-
39
- ## 2.8.1 - 2026-08-08
40
-
41
- - Added schema-driven form development tools to `NajmAppProvider`. Passing
42
- `formDevTools` enables F8 filling for every `NForm` and `WizardForm` without
43
- an application helper or additional provider.
44
- - Added built-in Zod 4 form-value generation with per-form overrides for
45
- relation fields and other application-owned values. Existing explicit
46
- `devTools.enabled` and `devTools.fill` usage remains supported.
47
-
48
- ## 2.8.0 - 2026-08-08
49
-
50
- - Added server-safe `najm-kit/format` helpers for currency minor units,
51
- numbers, percentages, dates, times, relative time, tokens, local date inputs,
52
- and slugs. Client applications can use the same contract reactively through
53
- `NajmFormatProvider` and `useNajmFormat`.
54
- - Added the server-safe `najm-kit/pagination` offset protocol, including bounded
55
- page creation, total-aware continuation, probe-row continuation for APIs
56
- without totals, and query cleanup that preserves meaningful `false` and `0`.
57
- - Added the optional-peer `najm-kit/query` entry with offset infinite-query and
58
- responsive paged/card-list hooks, plus shared card-pagination adapters and
59
- localized continuation labels.
60
- - Extended `NajmAppProvider` with formatting locale, currency, and placeholder
61
- configuration so applications can bind language, time zone, and formatting
62
- without another host bridge provider.
63
- - Added shared media-query/card-viewport helpers and avatar-source utilities.
64
-
65
- ## 2.6.2
66
-
67
- - Added `NSidebarProvider` and `useNSidebar`, so sidebar state can be read from a distance. `NSidebar` renders beside the page content rather than around it, which left applications hand-rolling a context to hand `setMobileOpen` down to a page header — a wrapper component plus an aliased import at every call site. Wrap the shell in `NSidebarProvider` and `NPageHeader` now resolves both `onSidebarOpen` and `mobileBreakpoint` from it, so a header nested anywhere below renders a working mobile trigger with no props threaded to it. Also exports the `NSidebarContextValue` type.
68
- - `NSidebar` resolves its open and collapsed state as explicit prop → surrounding provider → internal state. Passing `collapsed`, `mobileOpen`, `onCollapsedChange`, or `onMobileOpenChange` keeps behaving exactly as before, and a sidebar with no provider around it still owns its own state, so this is additive for every existing consumer.
69
- - `logo` accepts a render prop, `({ collapsed, isMobile }) => ReactNode`, alongside the existing node. It receives the state the sidebar actually resolved — including whatever `autoCollapseAt` decided — which consumers previously had to approximate with their own responsive classes, guessing at a breakpoint the sidebar had already computed. The mobile drawer always reports `collapsed: false`, matching how it renders. Exported as `SidebarLogoRender`.
70
-
71
- ## 2.6.1
72
-
73
- - Fixed the non-card `NPageHeader` bleed never taking effect. 2.6.0 cancelled the page padding with the Tailwind utilities `-mt-[var(--najm-section-gap,0px)]` and `-mx-[var(--najm-page-gutter,0px)]`, which only work if the consuming app's Tailwind build happens to emit those arbitrary classes — they exist nowhere but inside this package's bundle, so a consumer could load a stylesheet without them and the header stayed exactly where it was. The offsets are inline styles now and no longer depend on the consumer's CSS pipeline.
74
-
75
- ## 2.6.0
76
-
77
- - Added `NThemePresets`, and wired it into `NThemeCustomizer` through `presets`, `selectedPresetId`, `presetsStatus`, `savedDesign`, `onPresetSelect`, `onPresetSave`, `onPresetDelete`, and `presetLabels`. The picker renders only when a host supplies both `presets` and `onPresetSelect`. It is presentational: the host owns where presets live and what saving one means, and selecting a row hands the design back so it can be previewed before anything is stored. Each row draws a swatch strip from the design's own `sidebar`, `primary`, `secondary`, `accent`, and `background` tokens; the selected row's check sits left in the success colour and per-row delete sits right. Omit `onPresetSave` or `onPresetDelete` to hide those controls. Deleting is pointer-only — Radix owns roving focus inside the listbox.
78
- - **`NPageHeader` in non-card mode is now flush.** It rendered as a full-bleed bar (`border-b`, no radius) but still sat inside the padding `NPageLayout` applies, so it floated below and inside the page gutter and its bottom rule never met the sidebar header's. It now cancels that padding, and its base height goes `min-h-12` → `min-h-14` to match `NSidebarHeader`. **Non-card page headers move up and out to the page edges, and grow 8px below `sm`.** Card mode is unchanged.
79
- - `NPageLayout` publishes its resolved spacing as `--najm-page-gutter` and `--najm-section-gap`. Descendants could not previously cancel the page padding: a design config resolves the gutter to a literal, so the pre-existing `--page-gutter` / `--section-gap` variables only ever held the fallbacks. Full-bleed children should negate these, with `0px` fallbacks so they stay inert outside `NPageLayout`.
80
- - Fixed `SelectInput` discarding `SelectItemType.icon`. The prop was declared but `renderItems` rendered the label alone, so every per-item icon was silently dropped. Items with an icon now render it before a truncating label; items without one are unchanged.
81
-
82
- ## 2.5.0
83
-
84
- - Added `NTableDefaultsProvider`, so an application supplies `paginationLabels` once instead of at every table. Labels merge per key, most specific first: a table's own `paginationLabels` override the provider's for the keys it sets, the provider covers the rest, and anything neither supplies falls back to the packaged English. Also exports `useNTableDefaults` and the `NTableDefaults` type.
85
- - `value` is passed through the provider unmemoized; memoize it in the caller, or every table below re-renders with the shell.
86
-
87
- ## 2.4.0
88
-
89
- - `NTablePagination` renders numbered page buttons instead of `Page X of Y`. The window shows the first and last page, the current page, and one page either side, collapsing the rest into at most two gaps. The slot count is constant for any result longer than the window, so the bar does not change width as the reader pages through it, and a gap never stands in for a single page — that slot goes to the page instead.
90
- - Added `paginationVariant`, defaulting to `"numbered"`. Pass `"compact"` to keep the previous position text with first/previous/next/last controls. **This changes the default appearance of every paginated `NTable`.**
91
- - The numbered variant drops the first/last double chevrons, because page 1 and page N are now single-click targets of their own. Previous and next remain. The compact variant is unchanged.
92
- - Numbered pages fall back to compact on their own when the page count is not trustworthy — that is, under `manualPagination` with no `pageCount` supplied, where TanStack infers a count from the rows it happens to hold rather than from a result total. Numbering that would invite clicks on pages that may not exist is not rendered.
93
- - Below the `sm` breakpoint the numbers give way to the position text; seven page buttons plus the rows-per-page select do not fit a phone.
94
- - Added `paginationLabels` so the bar can be localized: `rowsPerPage`, `pagination`, `goToPage`, `currentPage`, `firstPage`, `previousPage`, `nextPage`, `lastPage`, `pageOf`, and `rowsSelected`. All optional, all falling back to the previous English strings.
95
- - Pagination chevrons now mirror under `dir="rtl"`. They previously pointed against the reading direction in right-to-left layouts.
96
- - The page controls are wrapped in a labelled `nav`, and the current page carries `aria-current="page"`.
97
- - Exported `buildPageItems` and `NTablePageItem` for consumers that need the same windowing outside the table.
98
-
99
- ## 2.2.1
100
-
101
- - Fixed a regression in 2.2.0: the dynamic page size reported under `manualPagination` could oscillate. Card row height is measured from rendered cards, so it grows as images decode; feeding that back into the page size refetched, re-rendered, re-measured, and refetched again. A list visibly settled from one page size to another with the loading skeleton flashing twice. The report is now allowed once per container geometry, which does not depend on the rows inside it, so it terminates. A resize still re-arms it, and the debounce still waits for the measurement to settle before reporting.
102
-
103
- ## 2.2.0
104
-
105
- - Added `cardPagination` mode `infinite`: card lists continue on scroll instead of behind a button. No control and no end-of-list element render while the list is healthy. The continuation button appears only after an append failure, as the retry target.
106
- - Infinite continuation is owned by `NTableCards`, so the sentinel lives inside the card list's own `NajmScroll` viewport and uses it as the observer root. An appending page renders shaped card placeholders at the grid tail rather than a spinner in a fixed strip, and the polite `aria-live` announcement of appended row counts is preserved.
107
- - `cardPagination: { mode: "all" }` is now honored in table mode as well as cards: every supplied row renders and no pagination controls are shown.
108
- - `dynamicHeight` now takes effect under `manualPagination`. The measured page size is reported through the ordinary `onPaginationChange` callback, debounced, so server-paginated tables fill their container while the consumer keeps ownership of fetching. `maxHeight` stays caller-owned under manual pagination, and no page size is reported before the first measurement.
109
- - Added `calculateCardPageSize`, floored to whole card rows, published as `calculatedCardPageSize`. A card grid page no longer ends in a ragged partial row. This deliberately differs from `calculateCardSkeletonCount`, which ceils because overfilling placeholders is harmless.
110
- - Removed the deprecated `baseUrl` compiler option from the package tsconfig; `paths` resolves relative to the config file.
111
-
112
- ## 2.1.56
113
-
114
- - Honor `showIcon` on NTable `select` and `combobox` filters. The leading filter icon is still shown by default; pass `showIcon: false` on a filter to hide it.
115
-
116
- ## 2.1.55
117
-
118
- - Added controlled remote-search and loading-state props to `ComboboxInput` and `FormInput type="combobox"` while preserving client filtering by default.
119
-
120
- ## 2.1.53 - 2026-08-05
121
-
122
- - Add typed `NBarChart`, `NLineChart`, `NPieChart`, and `NStatusBreakdown`
123
- components with caller-formatted generic data, accessible summaries, empty
124
- states, responsive RTL-safe layouts, and shape-matched loading skeletons.
125
- - Default chart colors to the live `--chart-1` through `--chart-5` theme
126
- variables, cycle deterministically after five items, and retain explicit
127
- per-series/item color overrides.
128
- - Add preset and numeric chart diameter contracts to `NPieChart` and
129
- `NDonutCard`, including narrow-container shrinking without clipped legends.
130
- - Make `NDonutCard` item colors optional and add accessible loading states to
131
- `NDonutCard` and `NStatCard`.
132
- - Add public API tests, component tests, README guidance, and playground
133
- examples for the chart and loading contracts.
134
-
135
- ## 2.1.49 - 2026-08-04
136
-
137
- ### ImageInput and AvatarInput
138
-
139
- - Add `previewAlt`, `fallbackImage`, `fallbackAlt`, `unavailableContent`,
140
- `imageClassName`, `onPreviewError`, `replaceAriaLabel`, and `clearAriaLabel`
141
- to `ImageInputProps`. `AvatarInput` forwards every new prop unchanged.
142
- - Preview sources resolve in this priority order: `value`, `fallbackImage`,
143
- `defaultImage`. Candidate URLs are deduplicated so a failing primary URL is
144
- never retried through multiple stages. When every candidate fails, the
145
- broken `<img>` is unmounted and `unavailableContent` (or a neutral default)
146
- is rendered in its place.
147
- - `imageVersion` is appended safely to relative, absolute, queried, and
148
- fragmented URLs. `data:`, `blob:`, `javascript:`, and `file:` URLs are
149
- left unchanged.
150
- - Expose `data-image-input-state="empty" | "preview" | "fallback" | "unavailable"`
151
- on the preview container for styling, testing, and consumer diagnostics.
152
- - File selection is race-safe: stale `FileReader` completions cannot replace
153
- a newer value. Object URLs created by the component are tracked so
154
- consumer-owned blob URLs are never revoked.
155
- - Replace and clear controls are real `<button>` elements, are reachable
156
- with the keyboard, and stay visible on touch and coarse-pointer devices.
157
- Only on `(hover: hover) and (pointer: fine)` desktops do the controls fall
158
- back to a hover/focus reveal. `focus-visible` always restores visibility.
159
- - Use logical positioning (`end-*`) so the clear button works correctly in
160
- RTL layouts.
161
- - Re-export `ImageInputPreviewSource` and `ImageInputPreviewError` from
162
- `najm-kit/components/inputs` and the package root.
163
-
164
- ## 2.1.48 - 2026-08-04
165
-
166
- - Keep responsive card row actions visible on phone, tablet, and touch input,
167
- while retaining hover and keyboard-focus reveal on fine-pointer desktops.
168
- - Size table and card loading skeletons from the measured body and active grid,
169
- and keep loading borders, radius, color, and shadow aligned with loaded
170
- surfaces.
171
- - Add the exported `NTableCardPagination` and `NTableLoadMorePagination`
172
- contracts for paged, complete supplied-data, and explicit server-backed Load
173
- more card presentation, including guarded append/retry behavior and accessible
174
- loading, result, error, and terminal feedback.
1
+ # Changelog
2
+
3
+ ## 2.11.0 - 2026-08-10
4
+
5
+ - Gave every keyboard-focusable primitive a visible focus ring, from one shared
6
+ source: `focusRingClasses` and `focusRingWithinClasses`, exported from the
7
+ root barrel so consumers stop hand-rolling app-level focus CSS. `TabsContent`
8
+ is keyboard-focusable (Radix sets `tabIndex={0}`) and previously showed no
9
+ indicator at all; `CollapsibleTrigger` now carries its own ring rather than
10
+ relying on whatever it wraps. `BaseInput` paints the ring on the wrapper via
11
+ `has-[:focus-visible]:`, which is what finally gives `NumberInput` and the
12
+ multi-select trigger an indicator both suppress the inner control's ring,
13
+ so focusing the child element used to change only the border colour.
14
+ - Fixed `Dialog` focus restoration. The opener is captured in
15
+ `onOpenAutoFocus` and refocused on close when focus would otherwise land on
16
+ `<body>`, so dismissing a dialog with Escape returns the keyboard to the
17
+ control that opened it (WCAG 2.4.3) instead of stranding it at the top of
18
+ the document. A caller that calls `preventDefault()` on the close event still
19
+ owns focus entirely.
20
+ - Added `NCredentialsCard`, a one-time handover surface for freshly generated
21
+ secrets. Renders a description list of fields with monospaced, break-all
22
+ values, an optional header icon that defaults to a check mark, an optional
23
+ consumer `actions` slot, and a built-in Copy button. The Copy action resolves
24
+ text through `copyText` when supplied or joins `${label}: ${value}` with
25
+ `\n` in field order otherwise. The button is disabled while a clipboard
26
+ write is pending; on success it swaps to a check icon and `copiedLabel`,
27
+ on failure to a warning icon and `copyErrorLabel`, and either state reverts
28
+ to idle after roughly two seconds. Header and field icons are marked
29
+ decorative, status is announced through a polite `aria-live` region, and
30
+ the Copy button renders before consumer actions so a Done-style dismiss
31
+ stays the last tab stop. The component never rethrows: a missing
32
+ `navigator.clipboard`, a rejected or synchronously thrown `writeText`, and
33
+ a synchronously thrown `copyText` all land in the error state with
34
+ `onCopyError` invoked. State updates and revert timers are guarded so
35
+ unmounting during a pending copy, or starting a second copy while the
36
+ first success state is still showing, never fire stale setters. Logical
37
+ spacing properties keep the layout correct under `dir="rtl"` without a
38
+ consumer override, and each value carries `dir="auto"` so it resolves its own
39
+ text direction: credentials are weak-directionality strings, and inheriting an
40
+ ambient `rtl` paints `+1 555 0100` as `0100 555 1+` and `p@ssw0rd!` as
41
+ `!p@ssw0rd` while the DOM and the copied text stay correct. A genuinely Arabic
42
+ value still renders right-to-left. Packaged English fallbacks ship for the three action
43
+ labels only; every field label, title, and description is the consumer's
44
+ text. Exported as `NCredentialsCard`, `NCredentialField`,
45
+ `NCredentialsCardProps`, and `NCredentialsCardClassNames` from the root
46
+ barrel and from `packages/najm-kit/src/components/data-display`.
47
+ - Added a shared `surface` contract across `NLoadingState`, `NErrorState`, and
48
+ `NEmptyState`. `inline` (default) preserves existing behavior; `panel` adds a
49
+ centered minimum-height frame for table, card, dialog, and sheet bodies
50
+ without a page gutter or a landmark; `page` uses the configured page
51
+ spacing through `NPageLayout as="div"` so it never introduces a nested
52
+ `<main>`. `NLoadingState.fullScreen` keeps precedence over `surface`.
53
+ - Added `NForbiddenState` and `NNotFoundState` as first-class generic Kit
54
+ components. Both default to the page surface, ship token-backed default
55
+ icons (`ShieldOff`, `Compass`), and resolve title and description through
56
+ the new provider defaults. Neither knows the dashboard URL, renders a Next
57
+ `Link`, redirects, or writes route metadata.
58
+ - Added `feedbackDefaults` to `NajmUIProvider`. It is inherited by
59
+ `NajmNextUIProvider` and `NajmAppProvider` through TypeScript — no second
60
+ adapter prop or translation source. Labels resolve through the existing
61
+ structural `t` (most specific: explicit prop > literal default > translated
62
+ key > packaged English). Generic error body copy and empty description
63
+ deliberately have no packaged fallback so the no-provider render is
64
+ unchanged.
65
+ - Exported the new feedback components and props (`NLoadingStateProps`,
66
+ `NErrorStateProps`, `NEmptyStateProps`, `NForbiddenStateProps`,
67
+ `NNotFoundStateProps`, `NFeedbackSurface`, `NFeedbackDefaults`,
68
+ `NFeedbackLabels`, `NFeedbackLabelKeys`, `NFeedbackIconSize`) from the root
69
+ barrel and re-exported them directly from `najm-kit/app` so a Next Server
70
+ Component route can render them without authoring a local `"use client"`
71
+ wrapper. The root entry stays free of `"use client"` and continues to
72
+ share a single `NFeedbackDefaultsContext` across `index` and the adapters.
73
+
74
+ ## 2.10.0 - 2026-08-10
75
+
76
+ - Added a shared, failure-aware media source chain for `NAvatar`, `NImage`, and
77
+ the new Next-only `NNextImage` export. Sources reset cleanly when inputs or
78
+ cache versions change, duplicate candidates are tried once, consumer event
79
+ handlers are preserved, and failed avatars return to initials without a
80
+ broken-image glyph.
81
+ - `NAvatar` now uses a native lazy-loaded image so loading and error events are
82
+ observable, keeps initials visible until the image paints, supports native
83
+ `imageProps`, and actually tries `fallbackSrc` after a primary failure.
84
+ - Added provider-level status badge defaults and the public
85
+ `normalizeStatusToken` helper. Applications can configure translated status
86
+ labels, colors, icons, look, shape, and size once while explicit badge props
87
+ retain precedence.
88
+ - Added `NNextImage` and `NNextImageProps` to `najm-kit/next` only, preserving
89
+ Next Image `fill`, `sizes`, optimizer, and `unoptimized` controls without
90
+ adding Next.js to the root runtime graph.
91
+
92
+ ## 2.9.0 - 2026-08-09
93
+
94
+ - Added `najm-kit/server`, a pure UI bootstrap loader. `createUiBootstrapLoader()`
95
+ takes the application's own fetcher, endpoint paths, payload parsers, and
96
+ factory values, then runs the resources concurrently, unwraps the `{ data }`
97
+ envelope (or one the application selects), and falls back per resource so a
98
+ branding outage never discards a valid appearance. Failures are reported
99
+ through an optional structured `onDiagnostic` callback carrying resource,
100
+ reason, path, and status — never a response body, header, cookie, or raw
101
+ thrown value. A `fallback()` that throws stays a visible error. The entry
102
+ imports no React, no Next.js, and no Node built-in, and re-exports
103
+ `parseNajmDesignConfig` so an appearance payload can be parsed without
104
+ reaching the root barrel.
105
+ - Added `najm-kit/server/react`, the React Server Component adapter.
106
+ `createReactServerUiBootstrap()` memoizes one bootstrap per request with
107
+ React's `cache()` and derives the per-resource accessors from it, so a root
108
+ layout, a nested layout, and a page share one resolution and one stable
109
+ snapshot for the whole render. Resolution is request-scoped only: separate
110
+ requests share no snapshot, failure, or diagnostic, and a transient outage is
111
+ retried on the next request. The `browser` export condition resolves to a
112
+ module that throws, so importing the adapter from a Client Component fails at
113
+ build time instead of shipping the application's fetcher and factory values
114
+ into a browser bundle.
115
+ - The root `najm-kit`, `najm-kit/next`, and `najm-kit/app` entries are unchanged
116
+ and do not reach either server entry.
117
+
118
+ ## 2.8.2 - 2026-08-08
119
+
120
+ - Added the framework-neutral `najm-kit/person-images` subpath. It ships a
121
+ built-in resolver for `child`, `adult`, `parent`, and `family` roles with
122
+ the seven WebP illustrations embedded as base64 data URLs, plus
123
+ `createPersonImageResolver` so an application can declare its own role
124
+ names (`teacher`, `student`, `doctor`, `driver`, …) and TypeScript catches
125
+ unknown role strings at the call site. The root `najm-kit` entry stays
126
+ unchanged and does not pull in the person images.
127
+
128
+ ## 2.8.1 - 2026-08-08
129
+
130
+ - Added schema-driven form development tools to `NajmAppProvider`. Passing
131
+ `formDevTools` enables F8 filling for every `NForm` and `WizardForm` without
132
+ an application helper or additional provider.
133
+ - Added built-in Zod 4 form-value generation with per-form overrides for
134
+ relation fields and other application-owned values. Existing explicit
135
+ `devTools.enabled` and `devTools.fill` usage remains supported.
136
+
137
+ ## 2.8.0 - 2026-08-08
138
+
139
+ - Added server-safe `najm-kit/format` helpers for currency minor units,
140
+ numbers, percentages, dates, times, relative time, tokens, local date inputs,
141
+ and slugs. Client applications can use the same contract reactively through
142
+ `NajmFormatProvider` and `useNajmFormat`.
143
+ - Added the server-safe `najm-kit/pagination` offset protocol, including bounded
144
+ page creation, total-aware continuation, probe-row continuation for APIs
145
+ without totals, and query cleanup that preserves meaningful `false` and `0`.
146
+ - Added the optional-peer `najm-kit/query` entry with offset infinite-query and
147
+ responsive paged/card-list hooks, plus shared card-pagination adapters and
148
+ localized continuation labels.
149
+ - Extended `NajmAppProvider` with formatting locale, currency, and placeholder
150
+ configuration so applications can bind language, time zone, and formatting
151
+ without another host bridge provider.
152
+ - Added shared media-query/card-viewport helpers and avatar-source utilities.
153
+
154
+ ## 2.6.2
155
+
156
+ - Added `NSidebarProvider` and `useNSidebar`, so sidebar state can be read from a distance. `NSidebar` renders beside the page content rather than around it, which left applications hand-rolling a context to hand `setMobileOpen` down to a page header — a wrapper component plus an aliased import at every call site. Wrap the shell in `NSidebarProvider` and `NPageHeader` now resolves both `onSidebarOpen` and `mobileBreakpoint` from it, so a header nested anywhere below renders a working mobile trigger with no props threaded to it. Also exports the `NSidebarContextValue` type.
157
+ - `NSidebar` resolves its open and collapsed state as explicit prop → surrounding provider → internal state. Passing `collapsed`, `mobileOpen`, `onCollapsedChange`, or `onMobileOpenChange` keeps behaving exactly as before, and a sidebar with no provider around it still owns its own state, so this is additive for every existing consumer.
158
+ - `logo` accepts a render prop, `({ collapsed, isMobile }) => ReactNode`, alongside the existing node. It receives the state the sidebar actually resolved — including whatever `autoCollapseAt` decided — which consumers previously had to approximate with their own responsive classes, guessing at a breakpoint the sidebar had already computed. The mobile drawer always reports `collapsed: false`, matching how it renders. Exported as `SidebarLogoRender`.
159
+
160
+ ## 2.6.1
161
+
162
+ - Fixed the non-card `NPageHeader` bleed never taking effect. 2.6.0 cancelled the page padding with the Tailwind utilities `-mt-[var(--najm-section-gap,0px)]` and `-mx-[var(--najm-page-gutter,0px)]`, which only work if the consuming app's Tailwind build happens to emit those arbitrary classes — they exist nowhere but inside this package's bundle, so a consumer could load a stylesheet without them and the header stayed exactly where it was. The offsets are inline styles now and no longer depend on the consumer's CSS pipeline.
163
+
164
+ ## 2.6.0
165
+
166
+ - Added `NThemePresets`, and wired it into `NThemeCustomizer` through `presets`, `selectedPresetId`, `presetsStatus`, `savedDesign`, `onPresetSelect`, `onPresetSave`, `onPresetDelete`, and `presetLabels`. The picker renders only when a host supplies both `presets` and `onPresetSelect`. It is presentational: the host owns where presets live and what saving one means, and selecting a row hands the design back so it can be previewed before anything is stored. Each row draws a swatch strip from the design's own `sidebar`, `primary`, `secondary`, `accent`, and `background` tokens; the selected row's check sits left in the success colour and per-row delete sits right. Omit `onPresetSave` or `onPresetDelete` to hide those controls. Deleting is pointer-only — Radix owns roving focus inside the listbox.
167
+ - **`NPageHeader` in non-card mode is now flush.** It rendered as a full-bleed bar (`border-b`, no radius) but still sat inside the padding `NPageLayout` applies, so it floated below and inside the page gutter and its bottom rule never met the sidebar header's. It now cancels that padding, and its base height goes `min-h-12` `min-h-14` to match `NSidebarHeader`. **Non-card page headers move up and out to the page edges, and grow 8px below `sm`.** Card mode is unchanged.
168
+ - `NPageLayout` publishes its resolved spacing as `--najm-page-gutter` and `--najm-section-gap`. Descendants could not previously cancel the page padding: a design config resolves the gutter to a literal, so the pre-existing `--page-gutter` / `--section-gap` variables only ever held the fallbacks. Full-bleed children should negate these, with `0px` fallbacks so they stay inert outside `NPageLayout`.
169
+ - Fixed `SelectInput` discarding `SelectItemType.icon`. The prop was declared but `renderItems` rendered the label alone, so every per-item icon was silently dropped. Items with an icon now render it before a truncating label; items without one are unchanged.
170
+
171
+ ## 2.5.0
172
+
173
+ - Added `NTableDefaultsProvider`, so an application supplies `paginationLabels` once instead of at every table. Labels merge per key, most specific first: a table's own `paginationLabels` override the provider's for the keys it sets, the provider covers the rest, and anything neither supplies falls back to the packaged English. Also exports `useNTableDefaults` and the `NTableDefaults` type.
174
+ - `value` is passed through the provider unmemoized; memoize it in the caller, or every table below re-renders with the shell.
175
+
176
+ ## 2.4.0
177
+
178
+ - `NTablePagination` renders numbered page buttons instead of `Page X of Y`. The window shows the first and last page, the current page, and one page either side, collapsing the rest into at most two gaps. The slot count is constant for any result longer than the window, so the bar does not change width as the reader pages through it, and a gap never stands in for a single page — that slot goes to the page instead.
179
+ - Added `paginationVariant`, defaulting to `"numbered"`. Pass `"compact"` to keep the previous position text with first/previous/next/last controls. **This changes the default appearance of every paginated `NTable`.**
180
+ - The numbered variant drops the first/last double chevrons, because page 1 and page N are now single-click targets of their own. Previous and next remain. The compact variant is unchanged.
181
+ - Numbered pages fall back to compact on their own when the page count is not trustworthy — that is, under `manualPagination` with no `pageCount` supplied, where TanStack infers a count from the rows it happens to hold rather than from a result total. Numbering that would invite clicks on pages that may not exist is not rendered.
182
+ - Below the `sm` breakpoint the numbers give way to the position text; seven page buttons plus the rows-per-page select do not fit a phone.
183
+ - Added `paginationLabels` so the bar can be localized: `rowsPerPage`, `pagination`, `goToPage`, `currentPage`, `firstPage`, `previousPage`, `nextPage`, `lastPage`, `pageOf`, and `rowsSelected`. All optional, all falling back to the previous English strings.
184
+ - Pagination chevrons now mirror under `dir="rtl"`. They previously pointed against the reading direction in right-to-left layouts.
185
+ - The page controls are wrapped in a labelled `nav`, and the current page carries `aria-current="page"`.
186
+ - Exported `buildPageItems` and `NTablePageItem` for consumers that need the same windowing outside the table.
187
+
188
+ ## 2.2.1
189
+
190
+ - Fixed a regression in 2.2.0: the dynamic page size reported under `manualPagination` could oscillate. Card row height is measured from rendered cards, so it grows as images decode; feeding that back into the page size refetched, re-rendered, re-measured, and refetched again. A list visibly settled from one page size to another with the loading skeleton flashing twice. The report is now allowed once per container geometry, which does not depend on the rows inside it, so it terminates. A resize still re-arms it, and the debounce still waits for the measurement to settle before reporting.
191
+
192
+ ## 2.2.0
193
+
194
+ - Added `cardPagination` mode `infinite`: card lists continue on scroll instead of behind a button. No control and no end-of-list element render while the list is healthy. The continuation button appears only after an append failure, as the retry target.
195
+ - Infinite continuation is owned by `NTableCards`, so the sentinel lives inside the card list's own `NajmScroll` viewport and uses it as the observer root. An appending page renders shaped card placeholders at the grid tail rather than a spinner in a fixed strip, and the polite `aria-live` announcement of appended row counts is preserved.
196
+ - `cardPagination: { mode: "all" }` is now honored in table mode as well as cards: every supplied row renders and no pagination controls are shown.
197
+ - `dynamicHeight` now takes effect under `manualPagination`. The measured page size is reported through the ordinary `onPaginationChange` callback, debounced, so server-paginated tables fill their container while the consumer keeps ownership of fetching. `maxHeight` stays caller-owned under manual pagination, and no page size is reported before the first measurement.
198
+ - Added `calculateCardPageSize`, floored to whole card rows, published as `calculatedCardPageSize`. A card grid page no longer ends in a ragged partial row. This deliberately differs from `calculateCardSkeletonCount`, which ceils because overfilling placeholders is harmless.
199
+ - Removed the deprecated `baseUrl` compiler option from the package tsconfig; `paths` resolves relative to the config file.
200
+
201
+ ## 2.1.56
202
+
203
+ - Honor `showIcon` on NTable `select` and `combobox` filters. The leading filter icon is still shown by default; pass `showIcon: false` on a filter to hide it.
204
+
205
+ ## 2.1.55
206
+
207
+ - Added controlled remote-search and loading-state props to `ComboboxInput` and `FormInput type="combobox"` while preserving client filtering by default.
208
+
209
+ ## 2.1.53 - 2026-08-05
210
+
211
+ - Add typed `NBarChart`, `NLineChart`, `NPieChart`, and `NStatusBreakdown`
212
+ components with caller-formatted generic data, accessible summaries, empty
213
+ states, responsive RTL-safe layouts, and shape-matched loading skeletons.
214
+ - Default chart colors to the live `--chart-1` through `--chart-5` theme
215
+ variables, cycle deterministically after five items, and retain explicit
216
+ per-series/item color overrides.
217
+ - Add preset and numeric chart diameter contracts to `NPieChart` and
218
+ `NDonutCard`, including narrow-container shrinking without clipped legends.
219
+ - Make `NDonutCard` item colors optional and add accessible loading states to
220
+ `NDonutCard` and `NStatCard`.
221
+ - Add public API tests, component tests, README guidance, and playground
222
+ examples for the chart and loading contracts.
223
+
224
+ ## 2.1.49 - 2026-08-04
225
+
226
+ ### ImageInput and AvatarInput
227
+
228
+ - Add `previewAlt`, `fallbackImage`, `fallbackAlt`, `unavailableContent`,
229
+ `imageClassName`, `onPreviewError`, `replaceAriaLabel`, and `clearAriaLabel`
230
+ to `ImageInputProps`. `AvatarInput` forwards every new prop unchanged.
231
+ - Preview sources resolve in this priority order: `value`, `fallbackImage`,
232
+ `defaultImage`. Candidate URLs are deduplicated so a failing primary URL is
233
+ never retried through multiple stages. When every candidate fails, the
234
+ broken `<img>` is unmounted and `unavailableContent` (or a neutral default)
235
+ is rendered in its place.
236
+ - `imageVersion` is appended safely to relative, absolute, queried, and
237
+ fragmented URLs. `data:`, `blob:`, `javascript:`, and `file:` URLs are
238
+ left unchanged.
239
+ - Expose `data-image-input-state="empty" | "preview" | "fallback" | "unavailable"`
240
+ on the preview container for styling, testing, and consumer diagnostics.
241
+ - File selection is race-safe: stale `FileReader` completions cannot replace
242
+ a newer value. Object URLs created by the component are tracked so
243
+ consumer-owned blob URLs are never revoked.
244
+ - Replace and clear controls are real `<button>` elements, are reachable
245
+ with the keyboard, and stay visible on touch and coarse-pointer devices.
246
+ Only on `(hover: hover) and (pointer: fine)` desktops do the controls fall
247
+ back to a hover/focus reveal. `focus-visible` always restores visibility.
248
+ - Use logical positioning (`end-*`) so the clear button works correctly in
249
+ RTL layouts.
250
+ - Re-export `ImageInputPreviewSource` and `ImageInputPreviewError` from
251
+ `najm-kit/components/inputs` and the package root.
252
+
253
+ ## 2.1.48 - 2026-08-04
254
+
255
+ - Keep responsive card row actions visible on phone, tablet, and touch input,
256
+ while retaining hover and keyboard-focus reveal on fine-pointer desktops.
257
+ - Size table and card loading skeletons from the measured body and active grid,
258
+ and keep loading borders, radius, color, and shadow aligned with loaded
259
+ surfaces.
260
+ - Add the exported `NTableCardPagination` and `NTableLoadMorePagination`
261
+ contracts for paged, complete supplied-data, and explicit server-backed Load
262
+ more card presentation, including guarded append/retry behavior and accessible
263
+ loading, result, error, and terminal feedback.