@ceebee/ui 0.5.2 → 1.0.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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, AnchorHTMLAttributes, ReactElement } from 'react';
2
+ import { ReactNode } from 'react';
3
3
 
4
4
  /** Joins class names, dropping falsy values. No merge logic: the library never emits
5
5
  * conflicting utility classes, so the "last wins" problem tailwind-merge solves does not exist. */
@@ -29,7 +29,7 @@ interface SurfaceProps {
29
29
  }
30
30
  /**
31
31
  * The panel every raised or tinted thing is built on. Glass and gradient live here as
32
- * variants rather than being baked into the brand (ADR 0002), so one Skin reproduces the
32
+ * variants rather than being baked into the brand, so one Skin reproduces the
33
33
  * reference board and another produces something sober without touching a component.
34
34
  */
35
35
  declare function Surface({ variant, glassStyle, tone, hue, elevation, radius, padding, bordered, className, children, asSection, }: SurfaceProps): react.JSX.Element;
@@ -81,184 +81,32 @@ interface HeadingProps {
81
81
  /** Level and size are separate on purpose: document structure is not a font size. */
82
82
  declare function Heading({ level, size, className, children }: HeadingProps): react.JSX.Element;
83
83
 
84
- interface LinkButtonProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'color'> {
85
- variant?: 'solid' | 'soft' | 'outline' | 'ghost';
86
- tone?: Tone;
87
- size?: Size;
88
- iconStart?: ReactNode;
89
- iconEnd?: ReactNode;
90
- children?: ReactNode;
91
- /**
92
- * Render something else in the anchor's place — a router's own Link, which has
93
- * to stay itself or client-side navigation is lost. It receives the classes
94
- * and the tone; everything else it keeps. The same `render` seam Base UI uses
95
- * elsewhere in this library.
96
- */
97
- render?: ReactElement;
98
- }
99
- /**
100
- * A link wearing a button's clothes.
101
- *
102
- * Not a `Button` with an `href`. A link navigates and a button acts, and the
103
- * difference is not decoration: a link can be opened in a new tab, copied,
104
- * dragged to a bookmark bar and reached by a screen reader's list of links,
105
- * while a button can be disabled and submit a form. Those are different
106
- * contracts, so they are different components (ADR 0014).
107
- *
108
- * What they share is the look, and that is shared literally — the same
109
- * `cb-button` classes rather than a second set that would agree today and drift
110
- * apart later. It is server-safe: an anchor needs no hook, no handler and no
111
- * motion, so it stays a Server Component (ADR 0004). The press animation is
112
- * Button's alone, which is honest: a link does not depress, it goes somewhere.
113
- */
114
- declare function LinkButton({ variant, tone, size, iconStart, iconEnd, className, children, render, ...rest }: LinkButtonProps): react.JSX.Element;
115
-
116
- interface DividerProps {
117
- /** A word or two sitting in the rule, for a section break that names itself. */
118
- children?: ReactNode;
119
- orientation?: 'horizontal' | 'vertical';
120
- className?: string;
121
- }
122
- /**
123
- * A rule between things.
124
- *
125
- * `<hr>` when it separates content, because that is what the element means and
126
- * a screen reader announces it. With a label it becomes a `<div>` carrying the
127
- * rule in its borders instead — an `<hr>` may not contain anything, and a
128
- * separator that says which section is starting is worth more than the element.
129
- */
130
- declare function Divider({ children, orientation, className }: DividerProps): react.JSX.Element;
131
-
132
- interface BadgeProps {
133
- children: ReactNode;
134
- tone?: Tone;
135
- variant?: 'soft' | 'solid' | 'outline';
136
- size?: 'sm' | 'md';
137
- /** Leading dot — for status, where the colour alone would be the only signal. */
138
- dot?: boolean;
139
- className?: string;
140
- }
141
- /** A label, not a button. If it can be clicked or removed, it is a Tag and needs a control. */
142
- declare function Badge({ children, tone, variant, size, dot, className }: BadgeProps): react.JSX.Element;
143
-
144
- interface EmptyStateProps {
145
- title: ReactNode;
146
- description?: ReactNode;
147
- icon?: ReactNode;
148
- actions?: ReactNode;
149
- /** `search` reads as "nothing matched", `first-run` as "nothing here yet" — they differ. */
150
- variant?: 'first-run' | 'search' | 'error';
151
- className?: string;
152
- }
153
- declare function Empty({ title, description, icon, actions, variant, className }: EmptyStateProps): react.JSX.Element;
154
-
155
- interface SpinnerProps {
156
- size?: 'sm' | 'md' | 'lg';
157
- tone?: Tone;
158
- /** Accessible name. Omit only when a nearby live region already says what is loading. */
159
- label?: string;
160
- className?: string;
161
- }
162
- /** Server-safe: a CSS animation, no state. It stops turning under reduced motion. */
163
- declare function Spin({ size, tone, label, className }: SpinnerProps): react.JSX.Element;
164
- interface ProgressBarProps {
165
- /** Omit for an indeterminate bar — "something is happening, duration unknown". */
166
- value?: number;
167
- max?: number;
168
- tone?: Tone;
169
- size?: 'sm' | 'md';
170
- label: string;
171
- /** Prints the percentage at the end of the track. */
172
- showValue?: boolean;
173
- className?: string;
174
- }
175
- declare function ProgressBar({ value, max, tone, size, label, showValue, className }: ProgressBarProps): react.JSX.Element;
176
-
177
- interface TimelineEntry {
178
- /** When it happened. Already formatted — the library does not decide date format. */
179
- time: ReactNode;
180
- title: ReactNode;
181
- description?: ReactNode;
182
- icon?: ReactNode;
183
- tone?: Tone;
184
- }
185
- interface TimelineProps {
186
- entries: TimelineEntry[];
187
- className?: string;
188
- }
189
- /**
190
- * An ordered list of things that happened. Server-safe, and an `<ol>` rather than divs, so the
191
- * order is a fact a screen reader reads out rather than a visual convention.
192
- */
193
- declare function TimelineRoot({ entries, className }: TimelineProps): react.JSX.Element;
194
- interface TimelineSkeletonProps {
195
- entries?: number;
196
- className?: string;
197
- }
198
- declare function TimelineSkeleton({ entries, className }: TimelineSkeletonProps): react.JSX.Element;
199
- declare const Timeline: typeof TimelineRoot & {
200
- Skeleton: typeof TimelineSkeleton;
201
- };
202
-
203
- interface SkeletonProps {
204
- width?: string;
205
- height?: string;
206
- radius?: 'sm' | 'md' | 'lg' | 'full';
207
- className?: string;
208
- }
209
- declare function box({ width, height, radius, className }: SkeletonProps): react.JSX.Element;
210
- interface SkeletonTextProps {
84
+ interface PageContainerSkeletonProps {
85
+ breadcrumb?: boolean;
86
+ subtitle?: boolean;
87
+ extra?: boolean;
88
+ tabs?: boolean;
211
89
  lines?: number;
212
- /** Width of the last line, which is short in real text and should be short here too. */
213
- lastLineWidth?: string;
214
- className?: string;
90
+ containerSize?: ContainerProps['size'];
215
91
  }
216
- declare function text({ lines, lastLineWidth, className }: SkeletonTextProps): react.JSX.Element;
217
- declare function circle({ size, className }: {
218
- size?: string;
219
- className?: string;
220
- }): react.JSX.Element;
221
- /**
222
- * Placeholder shapes. Free-form cases use these; every Composition also ships its own
223
- * `.Skeleton` built from the same tokens as the real thing, so the two cannot drift (ADR 0009).
224
- */
225
- declare const Skeleton: typeof box & {
226
- Text: typeof text;
227
- Circle: typeof circle;
228
- Rect: typeof box;
229
- };
92
+ declare function PageContainerSkeleton({ breadcrumb, subtitle, extra, tabs, lines, containerSize }: PageContainerSkeletonProps): react.JSX.Element;
230
93
 
231
- interface ProgressRingProps {
232
- value: number;
233
- max?: number;
234
- size?: number;
235
- thickness?: number;
236
- tone?: Tone;
237
- hue?: DecorHue;
238
- /** Content in the middle of the ring. Defaults to the rounded percentage. */
94
+ interface PageContainerProps {
95
+ breadcrumb?: ReactNode;
96
+ title?: ReactNode;
97
+ subtitle?: ReactNode;
98
+ extra?: ReactNode;
99
+ tabs?: ReactNode;
239
100
  children?: ReactNode;
240
- /** Accessible name; required because a bare percentage tells a screen reader nothing. */
241
- label: string;
242
- className?: string;
243
- }
244
- /**
245
- * The 84%-style ring the reference board leans on. Hand-written SVG, no charting
246
- * dependency — it has no axis and no scale, so it is a Widget, not a Chart (ADR 0007).
247
- */
248
- declare function ProgressRing({ value, max, size, thickness, tone, hue, children, label, className, }: ProgressRingProps): react.JSX.Element;
249
-
250
- /** The ring's geometry, kept out of the component so it can be asserted (ADR 0012). */
251
- interface RingGeometry {
252
- radius: number;
253
- circumference: number;
254
- /** Stroke offset that renders `value` of `max` as a filled arc. */
255
- dashOffset: number;
256
- /** Value clamped into range, for the accessible label and the printed number. */
257
- clamped: number;
101
+ containerSize?: ContainerProps['size'];
258
102
  }
259
- declare function ringGeometry(value: number, max: number, size: number, thickness: number): RingGeometry;
103
+ /** Server-safe page frame. Routing, data, title level, action behaviour, and tab state remain external. */
104
+ declare function PageContainerRoot({ breadcrumb, title, subtitle, extra, tabs, children, containerSize }: PageContainerProps): react.JSX.Element;
105
+ declare const PageContainer: typeof PageContainerRoot & {
106
+ Skeleton: typeof PageContainerSkeleton;
107
+ };
260
108
 
261
- /** Donut arithmetic, kept pure so the awkward inputs are asserted (ADR 0012). */
109
+ /** Donut arithmetic, kept pure so the awkward inputs are asserted. */
262
110
  interface DonutSlice {
263
111
  value: number;
264
112
  label: string;
@@ -289,7 +137,7 @@ interface DonutProps {
289
137
  label: string;
290
138
  className?: string;
291
139
  }
292
- /** A proportion widget, not a chart: no axis, no scale, no tooltip (ADR 0007). */
140
+ /** A proportion widget, not a chart: no axis, no scale, no tooltip. */
293
141
  declare function Donut({ slices, size, thickness, hues, children, label, className }: DonutProps): react.JSX.Element;
294
142
 
295
143
  interface SparklineProps {
@@ -305,7 +153,7 @@ interface SparklineProps {
305
153
  label: string;
306
154
  className?: string;
307
155
  }
308
- /** Trend at a glance. No axis, no scale, so it is a Widget rather than a Chart (ADR 0007). */
156
+ /** Trend at a glance. No axis, no scale, so it is a Widget rather than a Chart. */
309
157
  declare function Sparkline({ values, width, height, tone, hue, filled, showLast, label, className, }: SparklineProps): react.JSX.Element;
310
158
  interface BarMiniProps {
311
159
  values: number[];
@@ -361,108 +209,6 @@ interface LeaderboardProps {
361
209
  * fact a screen reader reads out rather than a column of numbers it has to infer.
362
210
  */
363
211
  declare function LeaderboardRoot({ entries, label, medals, className }: LeaderboardProps): react.JSX.Element;
364
- interface LeaderboardSkeletonProps {
365
- rows?: number;
366
- className?: string;
367
- }
368
- /** Same row geometry as the real list, so the panel does not resize on load (ADR 0009). */
369
- declare function LeaderboardSkeleton({ rows, className }: LeaderboardSkeletonProps): react.JSX.Element;
370
- declare const Leaderboard: typeof LeaderboardRoot & {
371
- Skeleton: typeof LeaderboardSkeleton;
372
- };
373
-
374
- interface AvatarProps {
375
- /** The person or thing. Used for the accessible name, the initials, and the fallback hue. */
376
- name: string;
377
- src?: string;
378
- size?: 'sm' | 'md' | 'lg' | 'xl';
379
- /** Overrides the hue derived from the name. */
380
- hue?: DecorHue;
381
- /** Presence dot. */
382
- status?: 'online' | 'busy' | 'away' | 'offline';
383
- className?: string;
384
- }
385
- /**
386
- * Server-safe: no image-load state, no hooks. The initials render underneath and the image
387
- * covers them when it loads, so a broken URL degrades to initials without JavaScript.
388
- */
389
- declare function Avatar({ name, src, size, hue, status, className }: AvatarProps): react.JSX.Element;
390
- interface AvatarGroupProps {
391
- children: ReactNode;
392
- /** Rendered as "+N" after the stack. */
393
- overflow?: number;
394
- size?: AvatarProps['size'];
395
- className?: string;
396
- }
397
- declare function AvatarGroup({ children, overflow, size, className }: AvatarGroupProps): react.JSX.Element;
398
-
399
- /**
400
- * First letter of the first and last word. Two letters at most, because three stop fitting
401
- * in the small size and a clipped initial reads as a rendering bug.
402
- */
403
- declare function initialsOf(name: string): string;
404
- /** Stable hue per name, so the same person keeps their colour across sessions and devices. */
405
- declare function hueForName(name: string): DecorHue;
406
-
407
- interface Crumb {
408
- label: ReactNode;
409
- href?: string;
410
- onClick?: () => void;
411
- }
412
- interface BreadcrumbsProps {
413
- items: Crumb[];
414
- /** Collapses the middle when the trail is longer than this. */
415
- maxItems?: number;
416
- className?: string;
417
- }
418
- /**
419
- * Server-safe. The last crumb is the current page: it is text with `aria-current`, not a link,
420
- * because a link to where you already are is a dead end for keyboard and screen reader users.
421
- */
422
- declare function Breadcrumb({ items, maxItems, className }: BreadcrumbsProps): react.JSX.Element;
423
-
424
- interface Step {
425
- label: ReactNode;
426
- description?: ReactNode;
427
- }
428
- interface StepperProps {
429
- steps: Step[];
430
- /** Zero-based index of the step in progress. */
431
- current: number;
432
- orientation?: 'horizontal' | 'vertical';
433
- className?: string;
434
- }
435
- /**
436
- * Progress through an ordered sequence — the thing Tabs must not be used for. Server-safe:
437
- * it displays position, it does not navigate.
438
- */
439
- declare function Steps({ steps, current, orientation, className }: StepperProps): react.JSX.Element;
440
-
441
- interface StatCardProps {
442
- label: string;
443
- value: ReactNode;
444
- /** Signed change, e.g. `+12.4%`. Direction decides the colour, not the caller. */
445
- delta?: {
446
- value: string;
447
- direction: 'up' | 'down' | 'flat';
448
- };
449
- caption?: string;
450
- hue?: DecorHue;
451
- icon?: ReactNode;
452
- /** A Widget (ProgressRing, Sparkline) shown to the side. */
453
- visual?: ReactNode;
454
- className?: string;
455
- }
456
- /** The tinted metric tile the reference board repeats on every dashboard. */
457
- declare function Statistic({ label, value, delta, caption, hue, icon, visual, className }: StatCardProps): react.JSX.Element;
458
- declare namespace Statistic {
459
- var Skeleton: typeof StatCardSkeleton;
460
- }
461
- interface StatCardSkeletonProps {
462
- withVisual?: boolean;
463
- className?: string;
464
- }
465
- /** Built from Statistic's own spacing, so the tile does not resize when data arrives (ADR 0009). */
466
- declare function StatCardSkeleton({ withVisual, className }: StatCardSkeletonProps): react.JSX.Element;
212
+ declare const Leaderboard: typeof LeaderboardRoot;
467
213
 
468
- export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Badge, type BadgeProps, BarMini, type BarMiniProps, Breadcrumb, type BreadcrumbsProps, Container, type ContainerProps, type Crumb, type DecorHue, Divider, type DividerProps, Donut, type DonutArc, type DonutProps, type DonutSlice, Empty, type EmptyStateProps, Flex, type GlassStyle, Grid, type GridProps, Heading, type HeadingProps, Leaderboard, type LeaderboardEntry, type LeaderboardProps, type LeaderboardSkeletonProps, LinkButton, type LinkButtonProps, ProgressBar, type ProgressBarProps, ProgressRing, type ProgressRingProps, type RingGeometry, type Size, Skeleton, type SkeletonProps, type SkeletonTextProps, Sparkline, type SparklineGeometry, type SparklineProps, Spin, type SpinnerProps, type StackProps, type StatCardProps, type StatCardSkeletonProps, Statistic, type Step, type StepperProps, Steps, Surface, type SurfaceProps, type SurfaceVariant, Text, type TextProps, Timeline, type TimelineEntry, type TimelineProps, type TimelineSkeletonProps, type Tone, cn, donutArcs, hueForName, initialsOf, ringGeometry, sparklineGeometry };
214
+ export { BarMini, type BarMiniProps, Container, type ContainerProps, type DecorHue, Donut, type DonutArc, type DonutProps, type DonutSlice, Flex, type GlassStyle, Grid, type GridProps, Heading, type HeadingProps, Leaderboard, type LeaderboardEntry, type LeaderboardProps, PageContainer, type PageContainerProps, PageContainerSkeleton, type PageContainerSkeletonProps, type Size, Sparkline, type SparklineGeometry, type SparklineProps, type StackProps, Surface, type SurfaceProps, type SurfaceVariant, Text, type TextProps, type Tone, cn, donutArcs, sparklineGeometry };