@umituz/web-dashboard 4.6.3 → 4.6.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/web-dashboard",
3
- "version": "4.6.3",
3
+ "version": "4.6.5",
4
4
  "description": "Installable app skeleton for the fleet — layouts, auth, onboarding, analytics (dependency-free SVG charts), calendar, i18n injection, permissions/session/module registry; ships its own udb-* stylesheet and --u-* tokens",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -82,7 +82,7 @@ export function Sparkline({
82
82
  width = 110,
83
83
  color = 'currentColor',
84
84
  }: {
85
- data: number[];
85
+ data: readonly number[];
86
86
  height?: number;
87
87
  width?: number;
88
88
  color?: string;
@@ -143,8 +143,8 @@ export function HBars({ rows, formatValue = (n: number) => String(n) }: { rows:
143
143
  export interface BarSeries {
144
144
  key?: string;
145
145
  label: string;
146
- values?: number[];
147
- data?: number[];
146
+ values?: readonly number[];
147
+ data?: readonly number[];
148
148
  tone?: string;
149
149
  color?: string;
150
150
  }
@@ -156,7 +156,7 @@ export function BarChart({
156
156
  formatValue = (v: number) => String(v),
157
157
  formatLabel = (l: string) => l,
158
158
  }: {
159
- labels: string[];
159
+ labels: readonly string[];
160
160
  series: BarSeries[];
161
161
  height?: number;
162
162
  formatValue?: (v: number) => string;
@@ -304,8 +304,8 @@ export function Donut({
304
304
  export interface LineSeries {
305
305
  key?: string;
306
306
  label: string;
307
- values?: number[];
308
- data?: number[];
307
+ values?: readonly number[];
308
+ data?: readonly number[];
309
309
  tone?: string;
310
310
  color?: string;
311
311
  kind?: 'line' | 'bars';
@@ -329,8 +329,8 @@ export function LineChart({
329
329
  yLabelLeft,
330
330
  yLabelRight,
331
331
  }: {
332
- points?: LineChartPoint[];
333
- labels?: string[];
332
+ points?: readonly LineChartPoint[];
333
+ labels?: readonly string[];
334
334
  series: LineSeries[];
335
335
  height?: number;
336
336
  formatLeft?: (v: number) => string;
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { renderToString } from 'react-dom/server';
3
+ import { PageHeader } from './PageHeader';
4
+
5
+ describe('PageHeader markup smoke', () => {
6
+ it('renders kicker before title and omits it when undefined', () => {
7
+ const html = renderToString(
8
+ <PageHeader kicker="Customer area" title="Policies" subtitle="Your coverage at a glance" />,
9
+ );
10
+ const kickerAt = html.indexOf('udb-pageheader__kicker');
11
+ const titleAt = html.indexOf('udb-pageheader__title');
12
+ expect(kickerAt).toBeGreaterThan(-1);
13
+ expect(kickerAt).toBeLessThan(titleAt);
14
+ expect(html).toContain('Customer area');
15
+
16
+ const bare = renderToString(<PageHeader title="Policies" />);
17
+ expect(bare).not.toContain('udb-pageheader__kicker');
18
+ });
19
+
20
+ it('renders actions and breadcrumb nodes in their slots', () => {
21
+ const html = renderToString(
22
+ <PageHeader
23
+ title="Claims"
24
+ breadcrumbs={<a href="/policies">Policies</a>}
25
+ actions={<button type="button">New claim</button>}
26
+ />,
27
+ );
28
+ expect(html).toContain('udb-pageheader__breadcrumbs');
29
+ expect(html).toContain('udb-pageheader__actions');
30
+ expect(html).toContain('New claim');
31
+ });
32
+ });
@@ -6,6 +6,7 @@ export interface PageHeaderCrumb {
6
6
  }
7
7
 
8
8
  export interface PageHeaderProps {
9
+ kicker?: ReactNode;
9
10
  title?: ReactNode;
10
11
  subtitle?: ReactNode;
11
12
  description?: ReactNode;
@@ -17,7 +18,7 @@ export interface PageHeaderProps {
17
18
  const isCrumbList = (value: ReactNode | readonly PageHeaderCrumb[]): value is readonly PageHeaderCrumb[] =>
18
19
  Array.isArray(value) && value.every((item) => typeof item === "object" && item !== null && "label" in item);
19
20
 
20
- export const PageHeader = ({ title, subtitle, description, breadcrumbs, actions, className }: PageHeaderProps) => {
21
+ export const PageHeader = ({ kicker, title, subtitle, description, breadcrumbs, actions, className }: PageHeaderProps) => {
21
22
  const crumbNode =
22
23
  breadcrumbs === undefined
23
24
  ? undefined
@@ -32,6 +33,7 @@ export const PageHeader = ({ title, subtitle, description, breadcrumbs, actions,
32
33
  <div className={`udb-pageheader${className ? ` ${className}` : ""}`}>
33
34
  {crumbNode !== undefined && <div className="udb-pageheader__breadcrumbs">{crumbNode}</div>}
34
35
  <div className="udb-pageheader__main">
36
+ {kicker !== undefined && <p className="udb-pageheader__kicker">{kicker}</p>}
35
37
  {title !== undefined && <h1 className="udb-pageheader__title">{title}</h1>}
36
38
  {(subtitle ?? description) !== undefined && (
37
39
  <p className="udb-pageheader__subtitle">{subtitle ?? description}</p>
@@ -3196,6 +3196,15 @@
3196
3196
  min-width: 0;
3197
3197
  }
3198
3198
 
3199
+ .udb-pageheader__kicker {
3200
+ margin: 0 0 0.25rem;
3201
+ font-size: 0.6875rem;
3202
+ font-weight: 600;
3203
+ letter-spacing: 0.08em;
3204
+ text-transform: uppercase;
3205
+ color: var(--color-muted-foreground);
3206
+ }
3207
+
3199
3208
  .udb-pageheader__title {
3200
3209
  margin: 0;
3201
3210
  font-size: 1.375rem;