neba 1.3.0 → 1.5.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.
Files changed (135) hide show
  1. package/README.md +7 -7
  2. package/dist/components/alert/Alert.d.ts +9 -1
  3. package/dist/components/alert/Alert.js +1 -1
  4. package/dist/components/area-chart/AreaChart.d.ts +54 -0
  5. package/dist/components/area-chart/AreaChart.js +1 -0
  6. package/dist/components/area-chart/index.d.ts +2 -0
  7. package/dist/components/area-chart/index.js +1 -0
  8. package/dist/components/bar-chart/BarChart.d.ts +63 -0
  9. package/dist/components/bar-chart/BarChart.js +1 -0
  10. package/dist/components/bar-chart/index.d.ts +2 -0
  11. package/dist/components/bar-chart/index.js +1 -0
  12. package/dist/components/bottom-navigation/BottomNavigation.d.ts +111 -0
  13. package/dist/components/bottom-navigation/BottomNavigation.js +1 -0
  14. package/dist/components/bottom-navigation/index.d.ts +1 -0
  15. package/dist/components/bottom-navigation/index.js +1 -0
  16. package/dist/components/breadcrumb/Breadcrumb.d.ts +35 -2
  17. package/dist/components/breadcrumb/Breadcrumb.js +1 -1
  18. package/dist/components/button/Button.d.ts +16 -0
  19. package/dist/components/button/Button.js +1 -1
  20. package/dist/components/carousel/Carousel.d.ts +10 -4
  21. package/dist/components/carousel/Carousel.js +1 -1
  22. package/dist/components/chip/Chip.d.ts +9 -1
  23. package/dist/components/chip/Chip.js +1 -1
  24. package/dist/components/collapsible/Collapsible.d.ts +88 -0
  25. package/dist/components/collapsible/Collapsible.js +1 -0
  26. package/dist/components/collapsible/index.d.ts +1 -0
  27. package/dist/components/collapsible/index.js +1 -0
  28. package/dist/components/combobox/Combobox.d.ts +19 -7
  29. package/dist/components/combobox/Combobox.js +1 -1
  30. package/dist/components/data-table/DataTable.d.ts +323 -0
  31. package/dist/components/data-table/DataTable.js +1 -0
  32. package/dist/components/data-table/index.d.ts +2 -0
  33. package/dist/components/data-table/index.js +1 -0
  34. package/dist/components/dialog/Dialog.d.ts +11 -5
  35. package/dist/components/dialog/Dialog.js +1 -1
  36. package/dist/components/drawer/Drawer.d.ts +11 -5
  37. package/dist/components/drawer/Drawer.js +1 -1
  38. package/dist/components/empty/Empty.d.ts +69 -0
  39. package/dist/components/empty/Empty.js +1 -0
  40. package/dist/components/empty/index.d.ts +2 -0
  41. package/dist/components/empty/index.js +1 -0
  42. package/dist/components/file-picker/FilePicker.d.ts +1 -3
  43. package/dist/components/file-picker/FilePicker.js +1 -1
  44. package/dist/components/floating-action-button/FloatingActionButton.d.ts +146 -0
  45. package/dist/components/floating-action-button/FloatingActionButton.js +1 -0
  46. package/dist/components/floating-action-button/index.d.ts +1 -0
  47. package/dist/components/floating-action-button/index.js +1 -0
  48. package/dist/components/heatmap-chart/HeatmapChart.d.ts +69 -0
  49. package/dist/components/heatmap-chart/HeatmapChart.js +1 -0
  50. package/dist/components/heatmap-chart/index.d.ts +2 -0
  51. package/dist/components/heatmap-chart/index.js +1 -0
  52. package/dist/components/highlight/Highlight.js +1 -1
  53. package/dist/components/line-chart/LineChart.d.ts +74 -0
  54. package/dist/components/line-chart/LineChart.js +1 -0
  55. package/dist/components/line-chart/index.d.ts +2 -0
  56. package/dist/components/line-chart/index.js +1 -0
  57. package/dist/components/mockup/Mockup.d.ts +151 -0
  58. package/dist/components/mockup/Mockup.js +1 -0
  59. package/dist/components/mockup/index.d.ts +2 -0
  60. package/dist/components/mockup/index.js +1 -0
  61. package/dist/components/number-field/NumberField.d.ts +10 -6
  62. package/dist/components/number-field/NumberField.js +1 -1
  63. package/dist/components/overlay/Overlay.d.ts +11 -6
  64. package/dist/components/overlay/Overlay.js +1 -1
  65. package/dist/components/pagination/Pagination.d.ts +28 -6
  66. package/dist/components/pagination/Pagination.js +1 -1
  67. package/dist/components/panes/Panes.js +1 -1
  68. package/dist/components/pie-chart/PieChart.d.ts +58 -0
  69. package/dist/components/pie-chart/PieChart.js +1 -0
  70. package/dist/components/pie-chart/index.d.ts +2 -0
  71. package/dist/components/pie-chart/index.js +1 -0
  72. package/dist/components/popover/Popover.d.ts +11 -5
  73. package/dist/components/popover/Popover.js +1 -1
  74. package/dist/components/progress-box/ProgressBox.js +1 -1
  75. package/dist/components/progress-circular/ProgressCircular.js +1 -1
  76. package/dist/components/progress-linear/ProgressLinear.js +1 -1
  77. package/dist/components/rating/Rating.d.ts +100 -0
  78. package/dist/components/rating/Rating.js +1 -0
  79. package/dist/components/rating/index.d.ts +1 -0
  80. package/dist/components/rating/index.js +1 -0
  81. package/dist/components/scatter-chart/ScatterChart.d.ts +45 -0
  82. package/dist/components/scatter-chart/ScatterChart.js +1 -0
  83. package/dist/components/scatter-chart/index.d.ts +2 -0
  84. package/dist/components/scatter-chart/index.js +1 -0
  85. package/dist/components/select/Select.d.ts +1 -3
  86. package/dist/components/select/Select.js +1 -1
  87. package/dist/components/sparkline/Sparkline.d.ts +67 -0
  88. package/dist/components/sparkline/Sparkline.js +1 -0
  89. package/dist/components/sparkline/index.d.ts +2 -0
  90. package/dist/components/sparkline/index.js +1 -0
  91. package/dist/components/statistic/Statistic.d.ts +7 -0
  92. package/dist/components/statistic/Statistic.js +1 -1
  93. package/dist/components/table/Table.d.ts +13 -2
  94. package/dist/components/table/Table.js +1 -1
  95. package/dist/components/text-link/TextLink.js +1 -1
  96. package/dist/components/time-picker/TimePicker.js +1 -1
  97. package/dist/components/timeline-chart/TimelineChart.d.ts +44 -0
  98. package/dist/components/timeline-chart/TimelineChart.js +1 -0
  99. package/dist/components/timeline-chart/index.d.ts +2 -0
  100. package/dist/components/timeline-chart/index.js +1 -0
  101. package/dist/components/toast/Toast.d.ts +10 -2
  102. package/dist/components/toast/Toast.js +1 -1
  103. package/dist/components/tooltip/Tooltip.d.ts +2 -4
  104. package/dist/components/tooltip/Tooltip.js +1 -1
  105. package/dist/components/tree-view/TreeView.js +1 -1
  106. package/dist/index.d.ts +15 -0
  107. package/dist/index.js +1 -1
  108. package/dist/internal/animate.d.ts +0 -9
  109. package/dist/internal/animate.js +1 -1
  110. package/dist/internal/calendar.js +1 -1
  111. package/dist/internal/chart-frame.d.ts +409 -0
  112. package/dist/internal/chart-frame.js +1 -0
  113. package/dist/internal/chart-line.d.ts +44 -0
  114. package/dist/internal/chart-line.js +1 -0
  115. package/dist/internal/chart.d.ts +456 -0
  116. package/dist/internal/chart.js +1 -0
  117. package/dist/internal/data-table.d.ts +170 -0
  118. package/dist/internal/data-table.js +1 -0
  119. package/dist/internal/date.d.ts +0 -2
  120. package/dist/internal/date.js +1 -1
  121. package/dist/internal/format.d.ts +29 -0
  122. package/dist/internal/format.js +1 -0
  123. package/dist/internal/i18n.d.ts +166 -0
  124. package/dist/internal/i18n.js +1 -1
  125. package/dist/internal/icons.d.ts +2 -0
  126. package/dist/internal/icons.js +1 -1
  127. package/dist/internal/mockup.d.ts +193 -0
  128. package/dist/internal/mockup.js +1 -0
  129. package/dist/internal/picker.d.ts +2 -4
  130. package/dist/internal/picker.js +1 -1
  131. package/dist/internal/progress.d.ts +1 -3
  132. package/dist/styles.css +1 -1
  133. package/dist/tailwind.css +231 -11
  134. package/dist/types.d.ts +214 -0
  135. package/package.json +19 -15
@@ -0,0 +1,100 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaSize } from '../../types';
3
+ export interface RatingProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
4
+ /** How much is rated. Use with `onValueChange` for a controlled Rating. */
5
+ value?: number;
6
+ /**
7
+ * Where an uncontrolled Rating starts.
8
+ * @default 0
9
+ */
10
+ defaultValue?: number;
11
+ /** Called with the new score. `0` is what a cleared Rating reports. */
12
+ onValueChange?: (value: number) => void;
13
+ /**
14
+ * How many stars there are, and therefore the highest score.
15
+ * @default 5
16
+ */
17
+ count?: number;
18
+ /**
19
+ * The smallest step that can be *chosen*, as a fraction of one star — `0.5`
20
+ * gives half stars, `1` whole ones. Anything outside `0 < precision <= 1`
21
+ * falls back to `1`.
22
+ *
23
+ * It bounds what a reader can pick and nothing else: a `value` of `4.3` is
24
+ * drawn as four stars and a third at every precision, because an average is
25
+ * not a choice and rounding it to the nearest half would be reporting a
26
+ * different number from the one it was handed.
27
+ * @default 1
28
+ */
29
+ precision?: number;
30
+ /** The glyph a filled star is drawn with. */
31
+ icon?: React.ReactNode;
32
+ /** And the one an empty star is drawn with. Has to be the same shape. */
33
+ emptyIcon?: React.ReactNode;
34
+ /**
35
+ * Choosing the score that is already chosen clears it back to `0`.
36
+ * @default true
37
+ */
38
+ clearable?: boolean;
39
+ /**
40
+ * Shows the score without letting it be changed — a product's average, a
41
+ * rating somebody else left.
42
+ *
43
+ * This is the one `readOnly` in the library that does not drain the
44
+ * saturation, because it is not a control being held still: there are no
45
+ * inputs at all, and what is left is a picture of a number. A row of grey
46
+ * stars would say the score itself was unavailable.
47
+ * @default false
48
+ */
49
+ readOnly?: boolean;
50
+ /** Unavailable. Drops the colour family for neutral grey. */
51
+ disabled?: boolean;
52
+ /** Identifies the value when a form is submitted. */
53
+ name?: string;
54
+ /** A form will not submit until a star has been chosen. */
55
+ required?: boolean;
56
+ /** Height of one star, on the standalone-glyph ladder. @default 'md' */
57
+ size?: NebaSize;
58
+ /**
59
+ * Semantic colour role. `warning` by default — the amber a star is expected
60
+ * to be — rather than `primary`, which is the one place in the library a
61
+ * component's default colour is chosen by what the object is instead of by
62
+ * what it means.
63
+ * @default 'warning'
64
+ */
65
+ color?: NebaColor;
66
+ /**
67
+ * Which language the accessible names are written in — a BCP 47 tag such as
68
+ * `ko`, `pt-BR` or `zh-Hant`. Unsupported tags fall back to English.
69
+ */
70
+ locale?: string;
71
+ /** Names the whole control. Defaults to the `locale`'s word for "Rating". */
72
+ label?: string;
73
+ /**
74
+ * What one star, and the whole control once it is read only, is called.
75
+ * Defaults to the `locale`'s way of saying "3 out of 5".
76
+ */
77
+ valueLabel?: (value: number, count: number) => string;
78
+ }
79
+ /**
80
+ * A score out of five, as a row of stars.
81
+ *
82
+ * Underneath an interactive Rating is a radio group of real `<input>`s, one per
83
+ * choosable score, each visually hidden under the half-star it stands for. That
84
+ * is the whole accessibility argument: a rating *is* "exactly one of these", so
85
+ * it gets one tab stop for the row, arrow keys within it, `aria-checked` on the
86
+ * one that is taken, and a value in a form submission — none of which a row of
87
+ * `<button>`s or a `<div>` with a click handler would have.
88
+ *
89
+ * The fraction is drawn by laying the filled star over the empty one and
90
+ * clipping it to a percentage of the width. Nothing is transformed and no glyph
91
+ * is scaled, so a half star is the left half of exactly the star beside it. The
92
+ * clip runs from the inline start, so it fills from the right under RTL without
93
+ * anything being told to.
94
+ *
95
+ * `readOnly` is a different component in the same clothes: no inputs, no radio
96
+ * group, and one `role="img"` carrying the score as a sentence. A star display
97
+ * that keeps twenty focusable radios is twenty tab stops on a page that was
98
+ * only reporting a number.
99
+ */
100
+ export declare const Rating: React.ForwardRefExoticComponent<RatingProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as n from"react";import{StarIcon as t,StarOutlineIcon as r}from"../../internal/icons";import{fillMessage as l,useMessages as i}from"../../internal/i18n";import{controlSlots as o,focusWithinRingClasses as s,gapClasses as d,iconSizeClasses as m,radiusClasses as c,srOnlyClasses as u,transitionClasses as h}from"../../internal/styles";const f="flex items-center justify-center";export const Rating=n.forwardRef(function({value:b,defaultValue:p=0,onValueChange:x,count:g=5,precision:y=1,icon:v,emptyIcon:N,clearable:j=!0,readOnly:M=!1,disabled:w=!1,name:k,required:S=!1,size:C="md",color:L="warning",locale:P,label:q,valueLabel:I,className:A,style:B,onPointerLeave:R,...V},z){const E=i(P),F=n.useId(),O=k??F,[D,G]=n.useState(p),H=void 0!==b,J=H?b:D,[K,Q]=n.useState(null),T=Math.max(1,Math.floor(g)),U=y>0&&y<=1?y:1,W=Math.round(1/U),X=Math.max(0,Math.min(T,K??J)),Y=n.useCallback(e=>I?I(e,T):e<=0?E.rating.empty:l(E.rating.value,{value:String(e),max:String(T)}),[I,T,E]),Z=e=>{H||G(e),x?.(e)},$=Array.from({length:T},(n,l)=>{const i=Math.max(0,Math.min(1,X-l));return a("span",{className:["relative inline-flex shrink-0",m[C],c.xs,M||w?"":s].filter(Boolean).join(" "),children:[e("span",{className:[f,m[C],w?"text-(--neba-disabled-fg)":"text-(--n-empty)"].join(" "),children:N??e(r,{})}),e("span",{"aria-hidden":"true",className:"pointer-events-none absolute inset-y-0 start-0 overflow-hidden",style:{width:100*i+"%"},children:e("span",{className:[f,m[C],w?"text-(--neba-disabled-fg)":"text-(--n-fill)",h].join(" "),children:v??e(t,{})})}),M?null:Array.from({length:W},(a,n)=>{const t=Number((l+(n+1)*U).toFixed(4));return e("label",{className:["absolute inset-y-0",w?"cursor-not-allowed":"cursor-pointer"].join(" "),style:{insetInlineStart:100*n/W+"%",width:100/W+"%"},onPointerEnter:()=>{w||Q(t)},children:e("input",{type:"radio",className:u,name:O,value:t,checked:J===t,disabled:w,required:S,"aria-label":Y(t),onChange:()=>Z(t),onClick:()=>{j&&J===t&&Z(0)}})},t)})]},l)}),_=["inline-flex items-center align-middle",d[C],w?"cursor-not-allowed":"",A??""].filter(Boolean).join(" "),ee={...o(L,0,"solid"),"--n-empty":"color-mix(in oklab, var(--neba-muted-fg) 40%, transparent)",...B};return e("div",M?{ref:z,role:"img","aria-label":Y(Math.max(0,Math.min(T,J))),className:_,style:ee,onPointerLeave:R,...V,children:$}:{ref:z,role:"radiogroup","aria-label":q??E.rating.label,"aria-disabled":w||void 0,"aria-required":S||void 0,className:_,style:ee,onPointerLeave:e=>{Q(null),R?.(e)},...V,children:$})});
@@ -0,0 +1 @@
1
+ export * from './Rating';
@@ -0,0 +1 @@
1
+ export*from"./Rating";
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ import { type CartesianChartProps } from '../../internal/chart-frame';
3
+ import { type MarkShape } from '../../internal/chart';
4
+ export interface ScatterChartProps extends CartesianChartProps {
5
+ /**
6
+ * What each mark is drawn as.
7
+ *
8
+ * - `auto` — the default. A circle while colour alone can carry identity, and
9
+ * a shape per series from the fourth on, because past three series it
10
+ * cannot: two of the palette's hues are indistinguishable under
11
+ * deuteranopia, and a shape is the one channel a dot has going spare.
12
+ * - `varied` — a shape per series always, in the fixed order circle, square,
13
+ * triangle, diamond, cross. Reach for it when the chart will be printed or
14
+ * read in greyscale.
15
+ * - one of the five names — every mark the same shape. On four or more series
16
+ * this is opting out of the second channel; do it only when each series
17
+ * carries a `color` of its own.
18
+ * @default 'auto'
19
+ */
20
+ shape?: MarkShape | 'varied' | 'auto';
21
+ /**
22
+ * The radius of a mark with no `z`, in pixels.
23
+ * @default the `size` ladder — 4 at `md`
24
+ */
25
+ pointRadius?: number;
26
+ /**
27
+ * The radius of the largest bubble, in pixels. Everything else is scaled
28
+ * under it by area.
29
+ * @default a twelfth of the chart's height
30
+ */
31
+ maxRadius?: number;
32
+ }
33
+ /**
34
+ * Two numbers per point, and whether they move together.
35
+ *
36
+ * Both axes measure, which is what makes this the only chart in the library
37
+ * with no categories: there is no column a mark belongs to and no order the
38
+ * points could be shuffled out of. A point with a `z` is drawn as a bubble and
39
+ * one without it as a dot, so a scatter and a bubble chart are the same
40
+ * component reading the same data — the third number is simply present or not.
41
+ *
42
+ * `x` must be a number or a `Date`. A string has no place on a number line, and
43
+ * a chart of named things against one measure is a [BarChart](./bar-chart).
44
+ */
45
+ export declare function ScatterChart({ shape, pointRadius, maxRadius, series, categories, size, xAxis, ...props }: ScatterChartProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{CartesianChart as l}from"../../internal/chart-frame";import{bubbleRadius as t,formatCategory as i,markerRadii as s,markGap as o,markPath as n,markShapes as c,plotHeights as u,pointX as d}from"../../internal/chart";import{cx as h,srOnlyClasses as m}from"../../internal/styles";export function ScatterChart({shape:r="auto",pointRadius:i,maxRadius:o,series:h,categories:m,size:p="md",xAxis:b,...v}){const y=i??s[p],g=o??Math.max(y+2,("number"==typeof v.height?v.height:u[p])/12),z=h.reduce((e,r)=>r.color?e:e+1,0),k="auto"===r||"varied"===r?"circle":r,M="varied"===r||"auto"===r&&z>3,j=a.useCallback(e=>M?c[e%c.length]:k,[M,k]),w=a.useCallback(e=>{const r=[];let a=0;return e.values.forEach(e=>{e.forEach(e=>{null!==e.value&&void 0!==e.z&&Number.isFinite(e.z)&&(a=Math.max(a,e.z))})}),e.values.forEach((l,i)=>{e.visible[i]&&l.forEach((l,s)=>{if(null===l.value)return;const o=d(l,s,m);null!==o&&r.push({series:i,index:s,x:e.categoryValuePx(o),y:e.valuePx(l.value),r:void 0===l.z?y:t(l.z,a,g,2)})})}),r},[m,y,g]);return e(l,{...v,series:h,categories:m,size:p,xScale:"value",xAxis:b,marks:w,markInset:g,includeZero:!1,swatch:(r,a)=>e("svg",{viewBox:"0 0 10 10",className:"size-2.5 overflow-visible","aria-hidden":"true",children:e("path",{d:n(j(r),5,5,4),fill:a})}),table:r=>e(f,{id:r,series:h,categories:m,label:v.label,xLabel:b?.label,yLabel:v.yAxis?.label,locale:v.locale,format:v.format}),children:r=>e(x,{context:r,shapeOf:j})})}function x({context:r,shapeOf:l}){const{marks:t,values:i,colors:s,hovered:c,activeMark:u}=r,d=a.useMemo(()=>[...t].sort((e,r)=>r.r-e.r),[t]);return e("g",{children:d.map(r=>{const a=i[r.series]?.[r.index],t=null!==c&&c!==r.series,d=u?.series===r.series&&u?.index===r.index;return e("path",{d:n(l(r.series),r.x,r.y,d?r.r+1:r.r),fill:a?.color??s[r.series],stroke:"var(--neba-chart-gap)",strokeWidth:o,opacity:t?.28:1},`${r.series}-${r.index}`)})})}function f({id:l,series:t,categories:s,label:o,xLabel:n,yLabel:c,locale:u,format:d}){const x=a.useMemo(()=>new Intl.NumberFormat(u,d??{maximumFractionDigits:2}),[u,d]),f=t.some(e=>e.data.some(e=>"object"==typeof e&&null!==e&&void 0!==e.z));return r("table",{id:l,className:h(m),children:[o?e("caption",{children:o}):null,e("thead",{children:r("tr",{children:[e("th",{scope:"col"}),e("th",{scope:"col",children:n??"x"}),e("th",{scope:"col",children:c??"y"}),f?e("th",{scope:"col",children:"z"}):null]})}),e("tbody",{children:t.flatMap((a,l)=>a.data.map((t,o)=>{const n="object"==typeof t&&null!==t?t:null,c=n?n.y:"number"==typeof t?t:null,d=n?.x??s?.[o]??o;return r("tr",{children:[e("th",{scope:"row",children:a.name??l+1}),e("td",{children:i(d,u)}),e("td",{children:null!==c&&Number.isFinite(c)?x.format(c):""}),f?e("td",{children:void 0===n?.z?"":x.format(n.z)}):null]},`${l}-${o}`)}))})]})}
@@ -0,0 +1,2 @@
1
+ export { ScatterChart } from './ScatterChart';
2
+ export type { ScatterChartProps } from './ScatterChart';
@@ -0,0 +1 @@
1
+ export{ScatterChart}from"./ScatterChart";
@@ -18,7 +18,7 @@ export interface SelectOption {
18
18
  /** Unavailable, but still listed — the option exists, it just cannot be picked. */
19
19
  disabled?: boolean;
20
20
  }
21
- export interface SelectProps extends NebaStyleProps {
21
+ export interface SelectProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
22
22
  /**
23
23
  * The options, as data. There is no `<Select.Option>` to compose: what a
24
24
  * caller has is almost always an array already, and the list has to be
@@ -59,8 +59,6 @@ export interface SelectProps extends NebaStyleProps {
59
59
  /** Identifies the field when a form is submitted. */
60
60
  name?: string;
61
61
  id?: string;
62
- className?: string;
63
- style?: React.CSSProperties;
64
62
  }
65
63
  /**
66
64
  * One value chosen from a list of them.
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Select as l}from"@base-ui/react/select";import{Field as n}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons";import{WidthSizer as s}from"../../internal/sizer";import{controlHeightClasses as o,controlTextLeadingClasses as d,disabledClasses as c,fieldReadOnlyClasses as m,fieldRestClasses as u,focusWithinRingClasses as h,gapClasses as f,hasContent as p,iconClasses as b,metaTextClasses as g,paddingXClasses as x,radiusClasses as v,stackGapClasses as N,surfaceClasses as w,surfaceSlots as j,transitionClasses as y}from"../../internal/styles";const I=["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",y,"focus-within:[transition-duration:0ms]",h,b].join(" "),S=[w,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--n-panel-press) p-1","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]"].join(" "),$=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",y,"data-[highlighted]:bg-(--n-soft-hover) data-[highlighted]:text-(--n-accent)","data-[selected]:text-(--n-accent) data-[selected]:font-medium","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","[outline:none]"].join(" ");export const Select=t.forwardRef(function({variant:h="outline",size:b="md",color:w="primary",density:y="default",elevation:V=0,items:z,value:k,defaultValue:O,onValueChange:P,placeholder:R,label:T,description:q,error:C,invalid:M,startIcon:W,fullWidth:_=!1,disabled:B=!1,readOnly:D=!1,required:E=!1,name:L,id:A,className:F,style:G},H){const J=null!=C&&!1!==C&&""!==C,K=M??J,Q=K?"danger":w,U=t.useMemo(()=>z.map(e=>({label:e.label??String(e.value),value:e.value})),[z]),X=t.useMemo(()=>[...z.map(e=>e.label??String(e.value)),...p(R)?[R]:[]],[z,R]);return a(n.Root,{disabled:B,invalid:K,className:["flex-col align-top",N[b],_?"flex w-full":"inline-flex",F??""].filter(Boolean).join(" "),style:{...j(Q,V),...G},children:[T?e(n.Label,{className:[g[b],"font-medium",B?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:T}):null,a(l.Root,{id:A,name:L,items:U,value:k,defaultValue:O,onValueChange:e=>P?.(e),disabled:B,readOnly:D,required:E,children:[a(l.Trigger,{ref:H,className:[I,o[b],d[b],v[b],f[b],x[y][b],B?c[h]:D?`${m[h]} cursor-default`:u[h]].join(" "),children:[W?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:W}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e(l.Value,{className:["w-full truncate text-start","data-[placeholder]:text-(--neba-muted-fg)"].join(" "),placeholder:R}),e(s,{samples:X})]}),e(l.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)","[transition:rotate_var(--neba-duration)_var(--neba-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(l.Portal,{children:e(l.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(l.Popup,{className:`${S} ${v[b]} ${d[b]}`,style:j(Q,3),children:z.map(t=>a(l.Item,{value:t.value,disabled:t.disabled,className:$,children:[e(l.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(l.ItemText,{className:"truncate",children:t.label??String(t.value)})]},String(t.value)))})})})]}),q?e(n.Description,{className:`${g[b]} text-(--neba-muted-fg)`,children:q}):null,J?e(n.Error,{match:!0,className:`${g[b]} text-(--n-accent)`,children:C}):null]})});
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Select as l}from"@base-ui/react/select";import{Field as n}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons";import{WidthSizer as s}from"../../internal/sizer";import{controlHeightClasses as o,controlTextLeadingClasses as d,disabledClasses as c,fieldReadOnlyClasses as m,fieldRestClasses as u,focusWithinRingClasses as h,gapClasses as f,hasContent as p,iconClasses as b,metaTextClasses as g,paddingXClasses as x,radiusClasses as v,stackGapClasses as N,surfaceClasses as w,surfaceSlots as j,transitionClasses as y}from"../../internal/styles";const I=["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",y,"focus-within:[transition-duration:0ms]",h,b].join(" "),S=[w,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--n-panel-press) p-1","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]"].join(" "),$=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",y,"data-[highlighted]:bg-(--n-soft-hover) data-[highlighted]:text-(--n-accent)","data-[selected]:text-(--n-accent) data-[selected]:font-medium","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","[outline:none]"].join(" ");export const Select=t.forwardRef(function({variant:h="outline",size:b="md",color:w="primary",density:y="default",elevation:V=0,items:z,value:k,defaultValue:O,onValueChange:P,placeholder:R,label:T,description:q,error:C,invalid:M,startIcon:W,fullWidth:_=!1,disabled:B=!1,readOnly:D=!1,required:E=!1,name:L,id:A,className:F,style:G,...H},J){const K=null!=C&&!1!==C&&""!==C,Q=M??K,U=Q?"danger":w,X=t.useMemo(()=>z.map(e=>({label:e.label??String(e.value),value:e.value})),[z]),Y=t.useMemo(()=>[...z.map(e=>e.label??String(e.value)),...p(R)?[R]:[]],[z,R]);return a(n.Root,{disabled:B,invalid:Q,className:["flex-col align-top",N[b],_?"flex w-full":"inline-flex",F??""].filter(Boolean).join(" "),style:{...j(U,V),...G},...H,children:[T?e(n.Label,{className:[g[b],"font-medium",B?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:T}):null,a(l.Root,{id:A,name:L,items:X,value:k,defaultValue:O,onValueChange:e=>P?.(e),disabled:B,readOnly:D,required:E,children:[a(l.Trigger,{ref:J,className:[I,o[b],d[b],v[b],f[b],x[y][b],B?c[h]:D?`${m[h]} cursor-default`:u[h]].join(" "),children:[W?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:W}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e(l.Value,{className:["w-full truncate text-start","data-[placeholder]:text-(--neba-muted-fg)"].join(" "),placeholder:R}),e(s,{samples:Y})]}),e(l.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)","[transition:rotate_var(--neba-duration)_var(--neba-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(l.Portal,{children:e(l.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(l.Popup,{className:`${S} ${v[b]} ${d[b]}`,style:j(U,3),children:z.map(t=>a(l.Item,{value:t.value,disabled:t.disabled,className:$,children:[e(l.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(l.ItemText,{className:"truncate",children:t.label??String(t.value)})]},String(t.value)))})})})]}),q?e(n.Description,{className:`${g[b]} text-(--neba-muted-fg)`,children:q}):null,K?e(n.Error,{match:!0,className:`${g[b]} text-(--n-accent)`,children:C}):null]})});
@@ -0,0 +1,67 @@
1
+ import * as React from 'react';
2
+ import type { NebaChartCurve, NebaChartDatum, NebaColor, NebaSize } from '../../types';
3
+ export interface SparklineProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'children'> {
4
+ /** The values. `null` is a gap, exactly as it is on every other chart. */
5
+ data: readonly NebaChartDatum[];
6
+ /**
7
+ * Which mark. A line for a trend, an area for a quantity, bars for a count of
8
+ * discrete things — the same three sentences the full charts say, at a size
9
+ * where nothing else is being said at all.
10
+ * @default 'line'
11
+ */
12
+ shape?: 'line' | 'area' | 'bar';
13
+ /** @default 'linear' */
14
+ curve?: NebaChartCurve;
15
+ /**
16
+ * How tall the strip is. Sized against the line of text it sits beside rather
17
+ * than against the page — a sparkline is a word in a sentence, not a picture.
18
+ * @default 'md'
19
+ */
20
+ size?: NebaSize;
21
+ /**
22
+ * The mark's colour. A `NebaColor` family, or any CSS colour.
23
+ *
24
+ * Unlike the full charts this one takes it directly: a sparkline has exactly
25
+ * one series and no legend, so there is nothing for a palette to hand out.
26
+ * @default the first chart slot
27
+ */
28
+ color?: NebaColor | (string & {});
29
+ /**
30
+ * Puts a dot on the last point. The one direct label a strip this small has
31
+ * room for, and it says where the series ended up.
32
+ * @default false
33
+ */
34
+ endDot?: boolean;
35
+ /**
36
+ * Draws a rule across the strip at this value — a target, a budget, last
37
+ * year's average. The one piece of context a sparkline can carry.
38
+ */
39
+ baseline?: number;
40
+ /**
41
+ * The ends of the scale. Left out, the strip fills itself with its own range,
42
+ * which is what makes a sparkline legible at twenty pixels tall — and what
43
+ * makes two of them side by side incomparable. Pass the same `min` and `max`
44
+ * to a row of them and they become a small-multiples chart.
45
+ */
46
+ min?: number;
47
+ max?: number;
48
+ /** How wide. Fills its container by default. */
49
+ width?: number | string;
50
+ /** A name for the strip, read out in place of it. */
51
+ label?: string;
52
+ }
53
+ /**
54
+ * A chart with everything taken away except the shape.
55
+ *
56
+ * No axes, no grid, no legend, no tooltip — it is not a small chart, it is a
57
+ * different thing: a word-sized picture that goes inside a sentence, beside a
58
+ * [Statistic](./statistic), or in a table cell, and says which way something has
59
+ * been going. Every number it could label is one the surrounding text already
60
+ * has, which is why it labels none of them.
61
+ *
62
+ * It scales itself to its own range, so the strip is always full. That is what
63
+ * makes it readable this small and it is also the trap: two sparklines side by
64
+ * side are drawn on two different scales unless they are given the same `min`
65
+ * and `max`.
66
+ */
67
+ export declare const Sparkline: React.ForwardRefExoticComponent<SparklineProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as a,jsxs as e,Fragment as l}from"react/jsx-runtime";import*as r from"react";import{areaPath as t,barMaxThickness as n,barPath as i,barRadius as o,extentOf as s,lineWidths as h,markerRadii as m,markGap as c,resolveColor as u,sparklineHeights as d,toValue as p}from"../../internal/chart";import{useMeasuredWidth as f}from"../../internal/chart-frame";import{cx as x,srOnlyClasses as v}from"../../internal/styles";import{linePath as b}from"../../internal/chart";export const Sparkline=r.forwardRef(function({data:g,shape:M="line",curve:k="linear",size:y="md",color:w,endDot:$=!1,baseline:j,min:N,max:W,width:C,label:L,className:R,style:z,...B},D){const F=r.useRef(null),G=f(F),I=r.useId().replace(/:/g,""),S=r.useMemo(()=>g.map(p),[g]),q=d[y],A=h[y],E=m[y],H=s([S],!1),J=N??(H?Math.min(H.min,j??H.min):0),K=(W??(H?Math.max(H.max,j??H.max):1))-J||1,O="number"==typeof C?C:G,P=u(w??"var(--neba-chart-1)"),Q="bar"===M?0:A/2+($?E:0),T=Q,U=Math.max(1,q-2*Q),V=a=>T+(1-(a-J)/K)*U,X=S.length>1?O/(S.length-1):O,Y=S.map((a,e)=>null===a.value?null:{x:e*X,y:V(a.value)}),Z=(()=>{for(let a=S.length-1;a>=0;a--)if(null!==S[a].value)return a;return-1})(),_=Math.min(n[y]/2,Math.max(1,O/Math.max(1,S.length)-c));return e("div",{ref:D,className:x("relative block",R??void 0),style:{width:C??"100%",height:q,...z},...B,children:[a("div",{ref:F,className:"absolute inset-0",children:O>0&&S.length>0?e("svg",{width:O,height:q,viewBox:`0 0 ${O} ${q}`,role:L?"img":"presentation","aria-label":L,"aria-hidden":!L||void 0,className:"block overflow-visible",children:["area"===M?e(l,{children:[a("defs",{children:e("linearGradient",{id:`${I}-fill`,x1:"0",y1:"0",x2:"0",y2:"1",children:[a("stop",{offset:"0%",stopColor:`color-mix(in oklab, ${P} 32%, transparent)`}),a("stop",{offset:"100%",stopColor:`color-mix(in oklab, ${P} 2%, transparent)`})]})}),a("path",{d:t(Y,q,k),fill:`url(#${I}-fill)`})]}):null,void 0!==j?a("line",{x1:0,x2:O,y1:V(j),y2:V(j),stroke:"var(--neba-chart-baseline)",strokeWidth:1}):null,"bar"===M?S.map((e,l)=>null===e.value?null:a("path",{d:i(l*(O/Math.max(1,S.length))+(O/Math.max(1,S.length)-_)/2,Math.min(V(e.value),V(Math.max(J,0))),_,Math.max(1,Math.abs(V(e.value)-V(Math.max(J,0)))),o/2,e.value>=0?"up":"down"),fill:e.color??P},l)):a("path",{d:b(Y,k),fill:"none",stroke:P,strokeWidth:A,strokeLinecap:"round",strokeLinejoin:"round"}),$&&Z>=0&&"bar"!==M?a("circle",{cx:Y[Z].x,cy:Y[Z].y,r:E,fill:P,stroke:"var(--neba-chart-gap)",strokeWidth:c}):null]}):null}),L?a("span",{className:v,children:S.map(a=>null===a.value?"—":a.value).join(", ")}):null]})});
@@ -0,0 +1,2 @@
1
+ export { Sparkline } from './Sparkline';
2
+ export type { SparklineProps } from './Sparkline';
@@ -0,0 +1 @@
1
+ export{Sparkline}from"./Sparkline";
@@ -22,6 +22,13 @@ export interface StatisticProps extends Omit<BoxProps, 'title' | 'prefix'> {
22
22
  * own locale and otherwise left alone.
23
23
  */
24
24
  format?: Intl.NumberFormatOptions;
25
+ /**
26
+ * Which language the figure is written in, the same prop every chart takes.
27
+ * A Statistic is the smallest chart on the page and sits next to the others in
28
+ * a dashboard, so a locale set on one of them has to be settable on all.
29
+ * @default the reader's
30
+ */
31
+ locale?: string;
25
32
  /** Set before the figure and never wrapped away from it — a currency sign. */
26
33
  prefix?: React.ReactNode;
27
34
  /**
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Box as n}from"../box/Box";import{Chip as a}from"../chip/Chip";import{MinusIcon as r,TrendDownIcon as s,TrendUpIcon as m}from"../../internal/icons";import{hasContent as i,metaTextClasses as o,sheetSectionGapClasses as c}from"../../internal/styles";const u={xs:"text-[1.125rem]/[1.375rem]",sm:"text-[1.375rem]/[1.625rem]",md:"text-[1.75rem]/[2rem]",lg:"text-[2.25rem]/[2.5rem]",xl:"text-[2.875rem]/[3.25rem]"},d={xs:"text-[0.75rem]",sm:"text-[0.875rem]",md:"text-[1rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},x={xs:"gap-y-0.5",sm:"gap-y-0.5",md:"gap-y-1",lg:"gap-y-1",xl:"gap-y-1.5"},f={start:"items-start text-start",center:"items-center text-center",end:"items-end text-end"},p={up:e(m,{}),down:e(s,{}),flat:e(r,{})};export const Statistic=l.forwardRef(function({size:r="md",color:s="primary",density:m="default",label:b,value:h,format:g,prefix:w,unit:N,icon:y,previousValue:v,delta:$="percent",betterWhen:j="up",caption:M,align:z="start",className:B,children:k,...F},I){const C=l.useMemo(()=>new Intl.NumberFormat(void 0,g),[g]),R="number"==typeof h?h:null,S=null===R?h:C.format(R),V=null!==R&&void 0!==v?R-v:null,W=null!==V&&0!==v&&void 0!==v?V/Math.abs(v):null,q=null===V?null:V>0?"up":V<0?"down":"flat";let A=null;if(null!==V&&null!==q&&"none"!==$){const e=V>0?"+":V<0?"-":"",t=`${e}${C.format(Math.abs(V))}`,l=null===W?null:`${e}${(100*Math.abs(W)).toFixed(1).replace(/\.0$/,"")}%`;A="absolute"===$?t:"both"===$?[l,t].filter(Boolean).join(" · "):l??t}const D=null===q||"flat"===q?"secondary":q===j?"success":"danger",E=null!==A||i(M);return t(n,{ref:I,size:r,color:s,density:m,className:["flex flex-col",c[r],f[z],B??""].filter(Boolean).join(" "),...F,children:[i(b)||i(y)?t("div",{className:["flex min-w-0 items-center gap-1.5 font-medium text-(--neba-muted-fg)",o[r]].join(" "),children:[i(y)?e("span",{className:"flex shrink-0 items-center",children:y}):null,i(b)?e("span",{className:"min-w-0 truncate",children:b}):null]}):null,t("div",{className:["flex min-w-0 flex-wrap items-baseline gap-1 font-semibold text-(--neba-fg) tabular-nums",u[r]].join(" "),children:[i(w)?e("span",{className:`font-medium text-(--neba-muted-fg) ${d[r]}`,children:w}):null,e("span",{className:"min-w-0 break-words",children:S}),i(N)?e("span",{className:`font-medium text-(--neba-muted-fg) ${d[r]}`,children:N}):null]}),E?t("div",{className:`flex min-w-0 flex-wrap items-center gap-x-2 ${x[r]}`,children:[null!==A&&null!==q?e(a,{size:r,variant:"text",color:D,startIcon:p[q],className:"tabular-nums",children:A}):null,i(M)?e("span",{className:`min-w-0 text-(--neba-muted-fg) ${o[r]}`,children:M}):null]}):null,k]})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Box as n}from"../box/Box";import{Chip as a}from"../chip/Chip";import{MinusIcon as r,TrendDownIcon as s,TrendUpIcon as m}from"../../internal/icons";import{numberFormatter as i}from"../../internal/format";import{hasContent as o,metaTextClasses as c,sheetSectionGapClasses as u}from"../../internal/styles";const d={xs:"text-[1.125rem]/[1.375rem]",sm:"text-[1.375rem]/[1.625rem]",md:"text-[1.75rem]/[2rem]",lg:"text-[2.25rem]/[2.5rem]",xl:"text-[2.875rem]/[3.25rem]"},x={xs:"text-[0.75rem]",sm:"text-[0.875rem]",md:"text-[1rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},f={xs:"gap-y-0.5",sm:"gap-y-0.5",md:"gap-y-1",lg:"gap-y-1",xl:"gap-y-1.5"},p={start:"items-start text-start",center:"items-center text-center",end:"items-end text-end"},h={up:e(m,{}),down:e(s,{}),flat:e(r,{})};export const Statistic=l.forwardRef(function({size:l="md",color:r="primary",density:s="default",label:m,value:b,format:g,locale:w,prefix:N,unit:y,icon:$,previousValue:v,delta:j="percent",betterWhen:z="up",caption:B,align:M="start",className:k,children:C,...F},I){const R="number"==typeof b?b:null,S=null===R?b:i(w,g).format(R),V=null!==R&&void 0!==v?R-v:null,W=null!==V&&0!==v&&void 0!==v?V/Math.abs(v):null,q=null===V?null:V>0?"up":V<0?"down":"flat";let A=null;if(null!==V&&null!==q&&"none"!==j){const e=V>0?"+":V<0?"-":"",t=`${e}${i(w,g).format(Math.abs(V))}`,l=null===W?null:`${e}${(100*Math.abs(W)).toFixed(1).replace(/\.0$/,"")}%`;A="absolute"===j?t:"both"===j?[l,t].filter(Boolean).join(" · "):l??t}const D=null===q||"flat"===q?"secondary":q===z?"success":"danger",E=null!==A||o(B);return t(n,{ref:I,size:l,color:r,density:s,className:["flex flex-col",u[l],p[M],k??""].filter(Boolean).join(" "),...F,children:[o(m)||o($)?t("div",{className:["flex min-w-0 items-center gap-1.5 font-medium text-(--neba-muted-fg)",c[l]].join(" "),children:[o($)?e("span",{className:"flex shrink-0 items-center",children:$}):null,o(m)?e("span",{className:"min-w-0 truncate",children:m}):null]}):null,t("div",{className:["flex min-w-0 flex-wrap items-baseline gap-1 font-semibold text-(--neba-fg) tabular-nums",d[l]].join(" "),children:[o(N)?e("span",{className:`font-medium text-(--neba-muted-fg) ${x[l]}`,children:N}):null,e("span",{className:"min-w-0 break-words",children:S}),o(y)?e("span",{className:`font-medium text-(--neba-muted-fg) ${x[l]}`,children:y}):null]}),E?t("div",{className:`flex min-w-0 flex-wrap items-center gap-x-2 ${f[l]}`,children:[null!==A&&null!==q?e(a,{size:l,variant:"text",color:D,startIcon:h[q],className:"tabular-nums",children:A}):null,o(B)?e("span",{className:`min-w-0 text-(--neba-muted-fg) ${c[l]}`,children:B}):null]}):null,C]})});
@@ -50,7 +50,18 @@ export interface TableProps<Row> extends Omit<BoxProps, 'padded' | 'children' |
50
50
  getRowKey?: (row: Row, index: number) => React.Key;
51
51
  /** Shown above the table, and read out as its accessible name. */
52
52
  caption?: React.ReactNode;
53
- /** What to show instead of rows when `items` is empty. */
53
+ /**
54
+ * Which language the empty state is written in — a BCP 47 tag such as `ko`,
55
+ * `pt-BR` or `zh-Hant`. Unsupported tags fall back to English.
56
+ *
57
+ * `empty` writes the line out instead; this is for the far more common case
58
+ * where the page already knows its own language.
59
+ */
60
+ locale?: string;
61
+ /**
62
+ * What to show instead of rows when `items` is empty. Defaults to the
63
+ * `locale`'s wording for a table with nothing in it.
64
+ */
54
65
  empty?: React.ReactNode;
55
66
  /**
56
67
  * Tints every other row. Useful for a wide table where the eye has to track
@@ -77,4 +88,4 @@ export interface TableProps<Row> extends Omit<BoxProps, 'padded' | 'children' |
77
88
  * might sit next to. What Table adds is the part that is genuinely tabular: the
78
89
  * columns, the rows, and the fact that the two cannot drift apart.
79
90
  */
80
- export declare function Table<Row>({ headers, items, getRowKey, caption, empty, striped, hoverable, stickyHeader, onRowClick, size, density, className, ...boxProps }: TableProps<Row>): React.JSX.Element;
91
+ export declare function Table<Row>({ headers, items, getRowKey, caption, locale, empty, striped, hoverable, stickyHeader, onRowClick, size, density, className, ...boxProps }: TableProps<Row>): React.JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{Box as r}from"../box/Box";import{controlTextLeadingClasses as a,metaTextClasses as l,paddingXValues as n}from"../../internal/styles";const o={default:{xs:"0.25rem",sm:"0.375rem",md:"0.625rem",lg:"0.75rem",xl:"0.875rem"},compact:{xs:"0.125rem",sm:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.625rem"}},s=["[--n-row:transparent]","[transition:background-color_var(--neba-duration)_var(--neba-ease)]"].join(" "),i={borderTop:"1px solid var(--n-line)",backgroundColor:"var(--n-row)"};export function Table({headers:d,items:c,getRowKey:m,caption:p,empty:h,striped:b=!1,hoverable:x=!1,stickyHeader:y=!1,onRowClick:g,size:f="md",density:u="default",className:v,...w}){const k=n[u][f],N=o[u][f],j=Boolean(g),$=x||j,B={padding:`${N} ${k}`},C={...B,backgroundColor:"var(--n-panel-press)"};return e(r,{size:f,density:u,padded:!1,className:["overflow-x-auto",v??""].filter(Boolean).join(" "),...w,children:t("table",{className:`w-full text-start ${a[f]} text-(--neba-fg)`,style:{borderCollapse:"collapse"},children:[p?e("caption",{className:`${l[f]} text-(--neba-muted-fg)`,style:{...B,textAlign:"start"},children:p}):null,e("colgroup",{children:d.map(t=>e("col",{style:void 0===t.width?void 0:{width:"number"==typeof t.width?`${t.width}px`:t.width}},t.key))}),e("thead",{children:e("tr",{children:d.map(t=>e("th",{scope:"col",className:["font-semibold whitespace-nowrap text-(--neba-muted-fg)",y?"sticky top-0 z-10 [backdrop-filter:var(--neba-blur)]":""].filter(Boolean).join(" "),style:{...C,textAlign:t.align??"start"},children:t.label??t.key},t.key))})}),e("tbody",{children:0===c.length?e("tr",{className:s,style:i,children:e("td",{colSpan:d.length,className:"text-(--neba-muted-fg)",style:{padding:`2rem ${k}`,textAlign:"center"},children:h??"No data"})}):c.map((t,r)=>e("tr",{className:[s,b&&r%2==1?"[--n-row:var(--n-panel-hover)]":"",$?"hover:[--n-row:var(--n-soft)]":"",j?"cursor-pointer":""].filter(Boolean).join(" "),style:i,onClick:g?()=>g(t,r):void 0,children:d.map(a=>e("td",{style:{...B,textAlign:a.align??"start"},children:a.render?a.render(t,r):t[a.key]},a.key))},m?m(t,r):r))})]})})}
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{Box as r}from"../box/Box";import{useMessages as n}from"../../internal/i18n";import{controlTextLeadingClasses as o,metaTextClasses as l,paddingXValues as a}from"../../internal/styles";const i={default:{xs:"0.25rem",sm:"0.375rem",md:"0.625rem",lg:"0.75rem",xl:"0.875rem"},compact:{xs:"0.125rem",sm:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.625rem"}},s=["[--n-row:transparent]","[transition:background-color_var(--neba-duration)_var(--neba-ease)]"].join(" "),d=["cursor-pointer [outline:none]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]"].join(" "),c={borderTop:"1px solid var(--n-line)",backgroundColor:"var(--n-row)"};export function Table({headers:m,items:p,getRowKey:b,caption:h,locale:u,empty:y,striped:f=!1,hoverable:x=!1,stickyHeader:g=!1,onRowClick:v,size:w="md",density:k="default",className:j,...N}){const $=n(u),B=a[k][w],C=i[k][w],A=Boolean(v),_=x||A,z={padding:`${C} ${B}`},T={...z,backgroundColor:"var(--n-panel-press)"};return e(r,{size:w,density:k,padded:!1,className:["overflow-x-auto",j??""].filter(Boolean).join(" "),...N,children:t("table",{className:`w-full text-start ${o[w]} text-(--neba-fg)`,style:{borderCollapse:"collapse"},children:[h?e("caption",{className:`${l[w]} text-(--neba-muted-fg)`,style:{...z,textAlign:"start"},children:h}):null,e("colgroup",{children:m.map(t=>e("col",{style:void 0===t.width?void 0:{width:"number"==typeof t.width?`${t.width}px`:t.width}},t.key))}),e("thead",{children:e("tr",{children:m.map(t=>e("th",{scope:"col",className:["font-semibold whitespace-nowrap text-(--neba-muted-fg)",g?"sticky top-0 z-10 [backdrop-filter:var(--neba-blur)]":""].filter(Boolean).join(" "),style:{...T,textAlign:t.align??"start"},children:t.label??t.key},t.key))})}),e("tbody",{children:0===p.length?e("tr",{className:s,style:c,children:e("td",{colSpan:m.length,className:"text-(--neba-muted-fg)",style:{padding:`2rem ${B}`,textAlign:"center"},children:y??$.table.empty})}):p.map((t,r)=>e("tr",{className:[s,f&&r%2==1?"[--n-row:var(--n-panel-hover)]":"",_?"hover:[--n-row:var(--n-soft)]":"",A?d:""].filter(Boolean).join(" "),style:c,tabIndex:A?0:void 0,onClick:v?()=>v(t,r):void 0,onKeyDown:v?e=>{e.target===e.currentTarget&&("Enter"!==e.key&&" "!==e.key||(e.preventDefault(),v(t,r)))}:void 0,children:m.map(n=>e("td",{style:{...z,textAlign:n.align??"start"},children:n.render?n.render(t,r):t[n.key]},n.key))},b?b(t,r):r))})]})})}
@@ -1 +1 @@
1
- import{jsx as n,Fragment as e,jsxs as r}from"react/jsx-runtime";import*as i from"react";import{useRender as o}from"@base-ui/react/use-render";import{useMessages as a}from"../../internal/i18n";import{ExternalLinkIcon as t,LinkIcon as l}from"../../internal/icons";import{controlTextLeadingClasses as s,focusRingClasses as c,srOnlyClasses as m}from"../../internal/styles";const d={always:"[&.neba-link]:underline",hover:"[&.neba-link]:no-underline [&.neba-link]:hover:underline",none:"[&.neba-link]:no-underline"},u=["neba-link","cursor-pointer","[&_svg]:pointer-events-none [&_svg]:inline [&_svg]:size-[0.95em] [&_svg]:shrink-0",["[transition-property:color,text-decoration-color]","[transition-duration:var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]"].join(" "),c,"focus-visible:rounded-[0.25rem]"].join(" ");export const TextLink=i.forwardRef(function({href:i,underline:c="always",color:p,size:b,newTab:f=!1,icon:v,locale:h,render:k,className:g,style:x,children:y,...j},w){const _=a(h),N=v??f,T=!0===N?n(f?t:l,{}):N,z=[u,b?s[b]:"",d[c],p?"[&.neba-link]:text-(--n-accent)":"[&.neba-link]:text-inherit",g??""].filter(Boolean).join(" "),C={"--n-underline":"color-mix(in oklab, currentColor 45%, transparent)","--n-underline-hover":"currentColor","--n-ring":`var(--neba-${p??"primary"}-ring)`,...p?{"--n-accent":`var(--neba-${p}-accent)`}:null};return o({render:k??n("a",{}),ref:w,props:{href:i,target:f?"_blank":void 0,rel:f?"noopener noreferrer":void 0,className:z,style:{...C,...x},children:r(e,{children:[y,T?n("span",{className:"ms-[0.25em]",children:T}):null,f?r(e,{children:[" ",n("span",{className:m,children:_.link.newTab})]}):null]}),...j}})});
1
+ import{jsx as n,Fragment as e,jsxs as r}from"react/jsx-runtime";import*as i from"react";import{useRender as o}from"@base-ui/react/use-render";import{useMessages as a}from"../../internal/i18n";import{ExternalLinkIcon as t,LinkIcon as l}from"../../internal/icons";import{controlTextLeadingClasses as s,focusRingClasses as c,srOnlyClasses as m}from"../../internal/styles";const d={always:"[&.neba-link]:underline",hover:"[&.neba-link]:no-underline [&.neba-link]:hover:underline",none:"[&.neba-link]:no-underline"},u=["neba-link","cursor-pointer","[&_svg]:pointer-events-none [&_svg]:inline [&_svg]:size-[0.95em] [&_svg]:shrink-0",["[transition-property:color,text-decoration-color]","[transition-duration:var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]"].join(" "),c,"focus-visible:rounded-[0.25rem]"].join(" ");export const TextLink=i.forwardRef(function({href:i,underline:c="always",color:p,size:b,newTab:f=!1,icon:v,locale:h,render:k,className:g,style:x,children:j,...y},w){const _=a(h),N=v??f,T=!0===N?n(f?t:l,{}):N,z=[u,b?s[b]:"",d[c],p?"[&.neba-link]:text-(--n-accent)":"[&.neba-link]:text-inherit",g??""].filter(Boolean).join(" "),B={"--n-underline":"color-mix(in oklab, currentColor 45%, transparent)","--n-underline-hover":"currentColor","--n-ring":`var(--neba-${p??"primary"}-ring)`,...p?{"--n-accent":`var(--neba-${p}-accent)`}:null},{rel:C,...$}=y,F=f?[...new Set([...(C??"").split(/\s+/).filter(Boolean),"noopener","noreferrer"])].join(" "):C;return o({render:k??n("a",{}),ref:w,props:{href:i,target:f?"_blank":void 0,className:z,style:{...B,...x},children:r(e,{children:[j,T?n("span",{className:"ms-[0.25em]",children:T}):null,f?r(e,{children:[" ",n("span",{className:m,children:_.link.newTab})]}):null]}),...$,rel:F}})});
@@ -1 +1 @@
1
- import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{Button as t}from"../button/Button";import{TimeGrid as l,usePickerLabels as a}from"../../internal/calendar";import{ClockIcon as i}from"../../internal/icons";import{PickerFooter as r,PickerShell as s}from"../../internal/picker";import{displaySamples as c,formatDate as d,isHour12 as u,isValidDate as m,secondsOfDay as p,timeUnitSpan as h,toISOTime as f,withPlaceholder as S,withTime as b}from"../../internal/date";import{cx as g}from"../../internal/styles";export const TimePicker=o.forwardRef(function({value:y,defaultValue:v,onValueChange:x,open:C,defaultOpen:w,onOpenChange:z,referenceDate:k,minTime:D,maxTime:O,shouldDisableTime:T,hour12:j,showSeconds:V=!1,hourStep:B=1,minuteStep:I=1,secondStep:M=1,locale:N,format:R,placeholder:F,clearable:H=!1,showNowButton:P=!0,closeOnSelect:q=!1,labels:A,name:E,size:G="md",color:J="primary",density:K="default",readOnly:L=!1,disabled:Q=!1,startIcon:U,...W},X){const Y=a(A),Z=j??u(N),[$,_]=o.useState(v??null),ee=void 0!==y?y:$,[ne,oe]=o.useState(w??!1),te=C??ne,[le]=o.useState(()=>k??new Date),ae=e=>{e&&(L||Q)||(void 0===C&&oe(e),z?.(e))},ie=e=>{void 0===y&&_(e),x?.(e)},re=o.useCallback((e,n)=>{const[o,t]=h(n,e);return!!(m(D)&&t<p(D))||(!!(m(O)&&o>p(O))||(T?.(e,n)??!1))},[D,O,T]),se=R??{hour:"numeric",minute:"2-digit",...V?{second:"2-digit"}:{}},ce=new Date,de=b(k??le,{hours:ce.getHours(),minutes:ce.getMinutes(),seconds:V?ce.getSeconds():0}),ue=P||H||!q,me=o.useMemo(()=>S(c(N,se),F),[N,se,F]);return e(s,{...W,size:G,color:J,density:K,readOnly:L,disabled:Q,triggerRef:X,startIcon:U??e(i,{}),display:m(ee)?d(ee,N,se):F??"",samples:me,empty:!m(ee),clearable:H,onClear:()=>ie(null),open:te,onOpenChange:ae,labels:Y,hiddenValues:E?[{name:E,value:m(ee)?f(ee,V):""}]:void 0,children:n("div",{className:g("flex flex-col",ue&&"gap-1.5"),children:[e(l,{size:G,density:K,locale:N,value:m(ee)?ee:null,referenceDate:k??le,onChange:e=>{ie(e),q&&ae(!1)},hour12:Z,showSeconds:V,hourStep:B,minuteStep:I,secondStep:M,shouldDisableTime:re,labels:Y,autoFocus:!0}),ue?n(r,{size:G,children:[H?e(t,{variant:"text",size:G,color:J,density:"compact",onClick:()=>{ie(null),ae(!1)},children:Y.clear}):null,P?e(t,{variant:"text",size:G,color:J,density:"compact",disabled:re(de,"second"),onClick:()=>{ie(de),ae(!1)},children:Y.now}):null,q?null:e(t,{variant:"solid",size:G,color:J,density:"compact",onClick:()=>ae(!1),children:Y.done})]}):null]})})});
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{Button as t}from"../button/Button";import{TimeGrid as l,usePickerLabels as a}from"../../internal/calendar";import{ClockIcon as i}from"../../internal/icons";import{PickerFooter as r,PickerShell as s}from"../../internal/picker";import{displaySamples as c,formatDate as d,isHour12 as u,isValidDate as m,secondsOfDay as p,timeUnitSpan as h,toISOTime as f,withPlaceholder as S,withTime as b}from"../../internal/date";import{cx as g}from"../../internal/styles";export const TimePicker=o.forwardRef(function({value:y,defaultValue:v,onValueChange:x,open:C,defaultOpen:w,onOpenChange:z,referenceDate:k,minTime:D,maxTime:O,shouldDisableTime:T,hour12:j,showSeconds:M=!1,hourStep:V=1,minuteStep:B=1,secondStep:I=1,locale:N,format:R,placeholder:F,clearable:H=!1,showNowButton:P=!0,closeOnSelect:q=!1,labels:A,name:E,size:G="md",color:J="primary",density:K="default",readOnly:L=!1,disabled:Q=!1,startIcon:U,...W},X){const Y=a(A),Z=j??u(N),[$,_]=o.useState(v??null),ee=void 0!==y?y:$,[ne,oe]=o.useState(w??!1),te=C??ne,[le]=o.useState(()=>k??new Date),ae=e=>{e&&(L||Q)||(void 0===C&&oe(e),z?.(e))},ie=e=>{void 0===y&&_(e),x?.(e)},re=o.useCallback((e,n)=>{const[o,t]=h(n,e);return!!(m(D)&&t<p(D))||(!!(m(O)&&o>p(O))||(T?.(e,n)??!1))},[D,O,T]),se=o.useMemo(()=>R??{hour:"numeric",minute:"2-digit",...M?{second:"2-digit"}:{}},[R,M]),ce=new Date,de=b(k??le,{hours:ce.getHours(),minutes:ce.getMinutes(),seconds:M?ce.getSeconds():0}),ue=P||H||!q,me=o.useMemo(()=>S(c(N,se),F),[N,se,F]);return e(s,{...W,size:G,color:J,density:K,readOnly:L,disabled:Q,triggerRef:X,startIcon:U??e(i,{}),display:m(ee)?d(ee,N,se):F??"",samples:me,empty:!m(ee),clearable:H,onClear:()=>ie(null),open:te,onOpenChange:ae,labels:Y,hiddenValues:E?[{name:E,value:m(ee)?f(ee,M):""}]:void 0,children:n("div",{className:g("flex flex-col",ue&&"gap-1.5"),children:[e(l,{size:G,density:K,locale:N,value:m(ee)?ee:null,referenceDate:k??le,onChange:e=>{ie(e),q&&ae(!1)},hour12:Z,showSeconds:M,hourStep:V,minuteStep:B,secondStep:I,shouldDisableTime:re,labels:Y,autoFocus:!0}),ue?n(r,{size:G,children:[H?e(t,{variant:"text",size:G,color:J,density:"compact",onClick:()=>{ie(null),ae(!1)},children:Y.clear}):null,P?e(t,{variant:"text",size:G,color:J,density:"compact",disabled:re(de,"second"),onClick:()=>{ie(de),ae(!1)},children:Y.now}):null,q?null:e(t,{variant:"solid",size:G,color:J,density:"compact",onClick:()=>ae(!1),children:Y.done})]}):null]})})});
@@ -0,0 +1,44 @@
1
+ import * as React from 'react';
2
+ import { type CartesianChartProps } from '../../internal/chart-frame';
3
+ import type { NebaChartCategory, NebaTimelineSeries } from '../../types';
4
+ export interface TimelineChartProps extends Omit<CartesianChartProps, 'series' | 'categories' | 'legend'> {
5
+ /**
6
+ * One row per series, and the spans on it. A row's name is what the axis
7
+ * says down the left-hand side.
8
+ */
9
+ series: readonly NebaTimelineSeries[];
10
+ /**
11
+ * Where the time axis starts and ends. Taken from the spans otherwise, and
12
+ * rounded outward to a date a calendar has a name for.
13
+ */
14
+ min?: NebaChartCategory;
15
+ max?: NebaChartCategory;
16
+ /**
17
+ * How thick a bar may get, in pixels. Below the cap the bars fill their share
18
+ * of the row; above it the leftover stays as air.
19
+ * @default the `size` ladder — 24 at `md`
20
+ */
21
+ barSize?: number;
22
+ /**
23
+ * Cuts the corners off a span.
24
+ *
25
+ * Both ends, unlike a [BarChart](./bar-chart), where the baseline end stays
26
+ * square. A span grows from nothing: neither of its ends is a zero, so
27
+ * neither is the one the reader is measuring from.
28
+ * @default true
29
+ */
30
+ rounded?: boolean;
31
+ }
32
+ /**
33
+ * Work against time — a row per thing, a bar per stretch of it.
34
+ *
35
+ * The two axes are a set of rows and a calendar, which makes this a
36
+ * [BarChart](./bar-chart) turned on its side with the baseline taken away:
37
+ * every bar starts where its own data says rather than at zero, so what the
38
+ * chart is about is *when* rather than *how much*.
39
+ *
40
+ * Not to be confused with [Timeline](../display/timeline), which is a list of
41
+ * steps and draws no axis at all. That one is for a sequence of events; this
42
+ * one is for how long each of them took.
43
+ */
44
+ export declare function TimelineChart({ series, min, max, barSize, rounded, size, density, xAxis, yAxis, locale, ...props }: TimelineChartProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as t from"react";import{CartesianChart as o}from"../../internal/chart-frame";import{barBandRatio as r,barMaxThickness as a,barRadius as s,formatTimeTicks as l,formatTimeValue as i,markGap as c,resolveColor as m,seriesColor as d,timeScale as u,toNumber as h}from"../../internal/chart";import{srOnlyClasses as x}from"../../internal/styles";export function TimelineChart({series:n,min:s,max:m,barSize:x,rounded:b=!0,size:y="md",density:k="default",xAxis:g,yAxis:v,locale:$,...C}){const w=t.useMemo(()=>n.map(f),[n]),z=t.useMemo(()=>w.map(e=>e.spans),[w]),A=t.useMemo(()=>{let e=1/0,n=-1/0,t=!1;for(const o of z)for(const r of o)r&&(t=!0,e=Math.min(e,r.from),n=Math.max(n,r.to));return t?{min:e,max:n}:null},[z]),j=t.useMemo(()=>u(A,{min:h(s)??void 0,max:h(m)??void 0,tickCount:v?.tickCount}),[A,s,m,v?.tickCount]),E=t.useMemo(()=>l(j.ticks,j.unit,$),[j,$]),P=t.useMemo(()=>n.map((e,n)=>d(e,n)),[n]),B=t.useMemo(()=>[{data:z.map(e=>e.some(Boolean)?1:null)}],[z]),I=t.useMemo(()=>n.map((e,n)=>e.name??`${n+1}`),[n]),T=x??a[y],F=t.useCallback(e=>{const n=[];return w.forEach((t,o)=>{const r=Math.min(T,Math.max(1,(e.band.band-c*(t.lanes-1))/t.lanes)),a=r*t.lanes+c*(t.lanes-1),s=e.plot.top+e.categoryPx(o)-a/2+r/2;t.spans.forEach((t,a)=>{if(!t)return;const l=e.valuePx(t.from),i=e.valuePx(t.to);n.push({series:o,index:a,x:(l+i)/2,y:s+t.lane*(r+c),r:r/2,rx:Math.max(0,(i-l)/2),ry:r/2})})}),n},[w,T]),N=t.useCallback(e=>{const n=z[e.series]?.[e.index];if(!n)return null;const t=[{seriesIndex:e.series,name:I[e.series],color:n.color??P[e.series],value:n.to-n.from,formatted:`${i(n.from,j.unit,$)} – ${i(n.to,j.unit,$)}`}];return{heading:n.span.label??I[e.series],items:t}},[z,I,P,j.unit,$]);return e(o,{...C,series:B,categories:I,size:y,density:k,locale:$,horizontal:!0,scale:j,xAxis:g,yAxis:{tickFormat:(e,n)=>E[n]??"",...v},legend:!1,bandRatio:r[k],marks:F,markTooltip:N,table:t=>e(M,{id:t,names:I,series:n,spans:z,unit:j.unit,label:C.label,corner:g?.label,locale:$}),children:n=>e(p,{context:n,spans:z,colors:P,rounded:b})})}function f(e){const n=e.data.map(e=>{const n=h(e.start),t=h(e.end);return null===n||null===t?null:{from:Math.min(n,t),to:Math.max(n,t),lane:0,color:e.color?m(e.color):void 0,span:e}}),t=[];return n.map((e,n)=>({one:e,index:n})).filter(e=>Boolean(e.one)).sort((e,n)=>e.one.from-n.one.from).forEach(({one:e})=>{const n=t.findIndex(n=>n<=e.from),o=-1===n?t.length:n;t[o]=e.to,e.lane=o}),{spans:n,lanes:Math.max(1,t.length)}}function p({context:n,spans:t,colors:o,rounded:r}){const{marks:a,activeMark:l,plot:i}=n,c=r?s:0;return e("g",{children:a.map(n=>{const r=t[n.series]?.[n.index];if(!r)return null;const a=l?.series===n.series&&l?.index===n.index,s=n.rx??n.r,m=2*(n.ry??n.r),d=Math.max(i.left,n.x-s),u=Math.min(i.left+i.width,n.x+s);if(u<i.left||d>i.left+i.width)return null;const h=Math.max(1,u-d);return e("rect",{x:d,y:n.y-m/2,width:h,height:m,rx:Math.min(c,h/2,m/2),fill:r.color??o[n.series],opacity:a?1:.92},`${n.series}-${n.index}`)})})}function M({id:t,names:o,series:r,spans:a,unit:s,label:l,corner:c,locale:m}){const d=r.some(e=>e.data.some(e=>void 0!==e.label));return n("table",{id:t,className:x,children:[l?e("caption",{children:l}):null,e("thead",{children:n("tr",{children:[e("th",{scope:"col",children:c??""}),d?e("th",{scope:"col",children:"label"}):null,e("th",{scope:"col",children:"start"}),e("th",{scope:"col",children:"end"})]})}),e("tbody",{children:a.flatMap((t,a)=>t.map((t,l)=>n("tr",{children:[e("th",{scope:"row",children:o[a]}),d?e("td",{children:r[a].data[l]?.label??""}):null,e("td",{children:t?i(t.from,s,m):""}),e("td",{children:t?i(t.to,s,m):""})]},`${a}-${l}`)))})]})}
@@ -0,0 +1,2 @@
1
+ export { TimelineChart } from './TimelineChart';
2
+ export type { TimelineChartProps } from './TimelineChart';
@@ -0,0 +1 @@
1
+ export{TimelineChart}from"./TimelineChart";
@@ -69,7 +69,15 @@ export interface ToastProviderProps extends Pick<NebaStyleProps, 'variant' | 'si
69
69
  limit?: number;
70
70
  /** How wide a toast is allowed to get. Numbers are pixels. @default 380 */
71
71
  width?: number | string;
72
- /** Accessible name of every toast's × button. */
72
+ /**
73
+ * Which language every toast's × is named in — a BCP 47 tag such as `ko`, `pt-BR` or
74
+ * `zh-Hant`. Unsupported tags fall back to English.
75
+ *
76
+ * `closeLabel` write the words out instead; this is for the far more common
77
+ * case where the page already knows its own language.
78
+ */
79
+ locale?: string;
80
+ /** Accessible name of every toast's × button. Defaults to the `locale`'s word. */
73
81
  closeLabel?: string;
74
82
  children?: React.ReactNode;
75
83
  }
@@ -113,4 +121,4 @@ export declare function useToast(): {
113
121
  * limit, the swipe, the F6 focus hotkey, and the live region that makes a
114
122
  * message that appeared out of nowhere reach a screen reader at all.
115
123
  */
116
- export declare function ToastProvider({ variant, size, color, density, position, timeout, limit, width, closeLabel, children }: ToastProviderProps): React.JSX.Element;
124
+ export declare function ToastProvider({ variant, size, color, density, position, timeout, limit, width, locale, closeLabel, children }: ToastProviderProps): React.JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Toast as i}from"@base-ui/react/toast";import{boxPaddingClasses as n}from"../box/Box";import{CloseIcon as s,severityIcons as a}from"../../internal/icons";import{controlSlots as r,focusRingClasses as l,hasContent as c,iconClasses as d,metaTextClasses as p,radiusClasses as u,sheetBodyClasses as m,sheetHeaderGapClasses as f,sheetSectionGapClasses as b,sheetTitleClasses as x,surfaceClasses as v}from"../../internal/styles";const h={"top-start":"top-0 items-start","top-center":"top-0 items-center","top-end":"top-0 items-end","bottom-start":"bottom-0 items-start flex-col-reverse","bottom-center":"bottom-0 items-center flex-col-reverse","bottom-end":"bottom-0 items-end flex-col-reverse"},y={solid:[v,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--neba-shadow-3),var(--neba-plate-solid)]"].join(" "),outline:[v,"border text-(--neba-fg) bg-(--n-panel-press)","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]"].join(" "),text:[v,"text-(--neba-fg) bg-(--n-panel-press)","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]"].join(" ")},g={solid:"",outline:"text-(--n-accent)",text:"text-(--n-accent)"};function w(e){const{color:t,variant:o,icon:i,actionLabel:n,onAction:s,...a}=e;return{...a,data:{color:t,variant:o,icon:i},actionProps:void 0===n?void 0:{children:n,onClick:s}}}export function useToast(){const e=i.useToastManager();return o.useMemo(()=>({add:t=>e.add(w(t)),close:t=>e.close(t),update:(t,o)=>e.update(t,w(o)),promise:(t,o)=>e.promise(t,{loading:w(o.loading),success:e=>w("function"==typeof o.success?o.success(e):o.success),error:e=>w("function"==typeof o.error?o.error(e):o.error)}),toasts:e.toasts}),[e])}function j({toast:o,variant:v,color:h,size:w,density:j,closeLabel:N,swipeDirection:_}){const T=o.data?.variant??v??"outline",z=o.data?.color??h,$=void 0===o.data?.icon?a[z]:o.data.icon,k=g[T],D=c(o.title);return t(i.Root,{toast:o,swipeDirection:_,className:["pointer-events-auto flex w-full items-start",n[j??"default"][w],u[w],b[w],m[w],y[T],d,"[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0","data-[limited]:hidden",l,"[outline:none]"].filter(Boolean).join(" "),style:r(z,3,T),children:[c($)?e("span",{className:`flex h-[1lh] shrink-0 items-center ${k}`,children:$}):null,t("div",{className:`flex min-w-0 flex-1 flex-col ${f[w]}`,children:[e(i.Title,{className:`neba-title font-semibold ${x[w]} ${k}`}),e(i.Description,{className:D?""+("solid"===T?"":"text-(--neba-muted-fg)"):""})]}),e(i.Action,{className:["flex h-[1lh] shrink-0 cursor-pointer items-center rounded-full px-2","font-medium underline-offset-2",k||"text-(--n-on-solid)","hover:underline","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2",p[w]].join(" ")}),e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(i.Close,{"aria-label":N,className:["inline-flex size-[1.15em] cursor-pointer items-center justify-center rounded-full","opacity-70 [transition:opacity_var(--neba-duration)_var(--neba-ease)]","hover:opacity-100 focus-visible:opacity-100","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),children:e(s,{})})})]})}function N(t){const{toasts:o}=i.useToastManager(),{position:n,width:s,...a}=t,r=[n.startsWith("top")?"up":"down","left","right"];return e(i.Portal,{children:e(i.Viewport,{className:["neba-portal pointer-events-none fixed inset-x-0 z-50 flex flex-col gap-2 p-4",h[n]].join(" "),children:o.map(t=>e("div",{className:"w-full",style:{maxWidth:"number"==typeof s?`${s}px`:s},children:e(j,{toast:t,swipeDirection:r,...a})},t.id))})})}export function ToastProvider({variant:o="outline",size:n="md",color:s="primary",density:a="default",position:r="bottom-end",timeout:l=5e3,limit:c=3,width:d=380,closeLabel:p="Close",children:u}){return t(i.Provider,{timeout:l,limit:c,children:[u,e(N,{position:r,variant:o,size:n,color:s,density:a,width:d,closeLabel:p})]})}
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Toast as i}from"@base-ui/react/toast";import{boxPaddingClasses as n}from"../box/Box";import{useMessages as s}from"../../internal/i18n";import{CloseIcon as a,severityIcons as r}from"../../internal/icons";import{controlSlots as l,focusRingClasses as c,hasContent as d,iconClasses as m,metaTextClasses as p,radiusClasses as u,sheetBodyClasses as f,sheetHeaderGapClasses as b,sheetSectionGapClasses as x,sheetTitleClasses as v,surfaceClasses as h}from"../../internal/styles";const y={"top-start":"top-0 items-start","top-center":"top-0 items-center","top-end":"top-0 items-end","bottom-start":"bottom-0 items-start flex-col-reverse","bottom-center":"bottom-0 items-center flex-col-reverse","bottom-end":"bottom-0 items-end flex-col-reverse"},g={solid:[h,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--neba-shadow-3),var(--neba-plate-solid)]"].join(" "),outline:[h,"border text-(--neba-fg) bg-(--n-panel-press)","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]"].join(" "),text:[h,"text-(--neba-fg) bg-(--n-panel-press)","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]"].join(" ")},w={solid:"",outline:"text-(--n-accent)",text:"text-(--n-accent)"};function j(e){const{color:t,variant:o,icon:i,actionLabel:n,onAction:s,...a}=e;return{...a,data:{color:t,variant:o,icon:i},actionProps:void 0===n?void 0:{children:n,onClick:s}}}export function useToast(){const e=i.useToastManager();return o.useMemo(()=>({add:t=>e.add(j(t)),close:t=>e.close(t),update:(t,o)=>e.update(t,j(o)),promise:(t,o)=>e.promise(t,{loading:j(o.loading),success:e=>j("function"==typeof o.success?o.success(e):o.success),error:e=>j("function"==typeof o.error?o.error(e):o.error)}),toasts:e.toasts}),[e])}function N({toast:o,variant:s,color:h,size:y,density:j,closeLabel:N,swipeDirection:_}){const T=o.data?.variant??s??"outline",z=o.data?.color??h,$=void 0===o.data?.icon?r[z]:o.data.icon,k=w[T],D=d(o.title);return t(i.Root,{toast:o,swipeDirection:_,className:["pointer-events-auto flex w-full items-start",n[j??"default"][y],u[y],x[y],f[y],g[T],m,"[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0","data-[limited]:hidden",c,"[outline:none]"].filter(Boolean).join(" "),style:l(z,3,T),children:[d($)?e("span",{className:`flex h-[1lh] shrink-0 items-center ${k}`,children:$}):null,t("div",{className:`flex min-w-0 flex-1 flex-col ${b[y]}`,children:[e(i.Title,{className:`neba-title font-semibold ${v[y]} ${k}`}),e(i.Description,{className:D?""+("solid"===T?"":"text-(--neba-muted-fg)"):""})]}),e(i.Action,{className:["flex h-[1lh] shrink-0 cursor-pointer items-center rounded-full px-2","font-medium underline-offset-2",k||"text-(--n-on-solid)","hover:underline","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2",p[y]].join(" ")}),e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(i.Close,{"aria-label":N,className:["inline-flex size-[1.15em] cursor-pointer items-center justify-center rounded-full","opacity-70 [transition:opacity_var(--neba-duration)_var(--neba-ease)]","hover:opacity-100 focus-visible:opacity-100","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),children:e(a,{})})})]})}function _(t){const{toasts:o}=i.useToastManager(),{position:n,width:s,...a}=t,r=[n.startsWith("top")?"up":"down","left","right"];return e(i.Portal,{children:e(i.Viewport,{className:["neba-portal pointer-events-none fixed inset-x-0 z-50 flex flex-col gap-2 p-4",y[n]].join(" "),children:o.map(t=>e("div",{className:"w-full",style:{maxWidth:"number"==typeof s?`${s}px`:s},children:e(N,{toast:t,swipeDirection:r,...a})},t.id))})})}export function ToastProvider({variant:o="outline",size:n="md",color:a="primary",density:r="default",position:l="bottom-end",timeout:c=5e3,limit:d=3,width:m=380,locale:p,closeLabel:u,children:f}){const b=s(p);return t(i.Provider,{timeout:c,limit:d,children:[f,e(_,{position:l,variant:o,size:n,color:a,density:r,width:m,closeLabel:u??b.action.close})]})}
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { Tooltip as BaseUITooltip } from '@base-ui/react/tooltip';
3
3
  import type { NebaAlign, NebaSide, NebaStyleProps } from '../../types';
4
- export interface TooltipProps extends Pick<NebaStyleProps, 'size' | 'color' | 'density'> {
4
+ export interface TooltipProps extends Pick<NebaStyleProps, 'size' | 'color' | 'density'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'content' | 'children'> {
5
5
  /**
6
6
  * What the tooltip says.
7
7
  *
@@ -46,8 +46,6 @@ export interface TooltipProps extends Pick<NebaStyleProps, 'size' | 'color' | 'd
46
46
  * @default false
47
47
  */
48
48
  disabled?: boolean;
49
- className?: string;
50
- style?: React.CSSProperties;
51
49
  }
52
50
  /**
53
51
  * Shares one delay across a group of tooltips: once any of them has opened, its
@@ -78,4 +76,4 @@ export type TooltipProviderProps = React.ComponentProps<typeof BaseUITooltip.Pro
78
76
  * this component wires both, and drops the reference while it is closed rather
79
77
  * than pointing at an element that is not in the document.
80
78
  */
81
- export declare function Tooltip({ content, children, size, color, density, side, align, sideOffset, delay, closeDelay, arrow, open, defaultOpen, onOpenChange, disabled, className, style }: TooltipProps): React.JSX.Element;
79
+ export declare function Tooltip({ content, children, size, color, density, side, align, sideOffset, delay, closeDelay, arrow, open, defaultOpen, onOpenChange, disabled, className, style, ...props }: TooltipProps): React.JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Tooltip as o}from"@base-ui/react/tooltip";import{controlSlots as i,metaTextClasses as s,paddingXClasses as n,radiusClasses as l,surfaceClasses as r}from"../../internal/styles";export const TooltipProvider=o.Provider;const d=[r,"max-w-64 text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--neba-shadow-3),var(--neba-plate-solid)]","[outline:none]","[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0","data-[instant]:[transition-duration:0ms]"].join(" "),p={xs:"py-0.5",sm:"py-0.5",md:"py-1",lg:"py-1.5",xl:"py-2"},c={xs:6,sm:7,md:8,lg:9,xl:10};export function Tooltip({content:r,children:m,size:h="sm",color:y="secondary",density:f="default",side:x="top",align:b="center",sideOffset:g=6,delay:u,closeDelay:v,arrow:w=!0,open:j,defaultOpen:O,onOpenChange:N,disabled:P=!1,className:T,style:z}){const B=c[h],C=a.useId(),[D,_]=a.useState(O??!1),k=j??D;return t(o.Root,{open:j,defaultOpen:O,onOpenChange:e=>{_(e),N?.(e)},children:[e(o.Trigger,{render:m,delay:u,closeDelay:v,disabled:P,"aria-describedby":k?C:void 0}),e(o.Portal,{children:e(o.Positioner,{className:"neba-portal z-50 [outline:none]",side:x,align:b,sideOffset:g,children:t(o.Popup,{id:C,role:"tooltip",className:[d,l[h],n[f][h],p[h],s[h],T??""].filter(Boolean).join(" "),style:{...i(y,3,"solid"),...z},children:[w?e(o.Arrow,{className:["data-[side=top]:bottom-[-1px]","data-[side=bottom]:top-[-1px] data-[side=bottom]:rotate-180","data-[side=left]:right-[-1px] data-[side=left]:-rotate-90","data-[side=right]:left-[-1px] data-[side=right]:rotate-90"].join(" "),children:e("svg",{width:B,height:B/2,viewBox:"0 0 10 5","aria-hidden":"true",className:"block",children:e("path",{d:"M0 0h10L5 5z",fill:"var(--n-fill)"})})}):null,r]})})})]})}
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Tooltip as o}from"@base-ui/react/tooltip";import{controlSlots as i,metaTextClasses as s,paddingXClasses as n,radiusClasses as l,surfaceClasses as r}from"../../internal/styles";export const TooltipProvider=o.Provider;const d=[r,"max-w-64 text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--neba-shadow-3),var(--neba-plate-solid)]","[outline:none]","[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0","data-[instant]:[transition-duration:0ms]"].join(" "),p={xs:"py-0.5",sm:"py-0.5",md:"py-1",lg:"py-1.5",xl:"py-2"},c={xs:6,sm:7,md:8,lg:9,xl:10};export function Tooltip({content:r,children:m,size:h="sm",color:y="secondary",density:f="default",side:x="top",align:b="center",sideOffset:g=6,delay:u,closeDelay:v,arrow:w=!0,open:j,defaultOpen:O,onOpenChange:N,disabled:P=!1,className:T,style:z,...B}){const C=c[h],D=a.useId(),[_,k]=a.useState(O??!1),A=j??_;return t(o.Root,{open:j,defaultOpen:O,onOpenChange:e=>{k(e),N?.(e)},children:[e(o.Trigger,{render:m,delay:u,closeDelay:v,disabled:P,"aria-describedby":A?D:void 0}),e(o.Portal,{children:e(o.Positioner,{className:"neba-portal z-50 [outline:none]",side:x,align:b,sideOffset:g,children:t(o.Popup,{id:D,role:"tooltip",className:[d,l[h],n[f][h],p[h],s[h],T??""].filter(Boolean).join(" "),style:{...i(y,3,"solid"),...z},...B,children:[w?e(o.Arrow,{className:["data-[side=top]:bottom-[-1px]","data-[side=bottom]:top-[-1px] data-[side=bottom]:rotate-180","data-[side=left]:right-[-1px] data-[side=left]:-rotate-90","data-[side=right]:left-[-1px] data-[side=right]:rotate-90"].join(" "),children:e("svg",{width:C,height:C/2,viewBox:"0 0 10 5","aria-hidden":"true",className:"block",children:e("path",{d:"M0 0h10L5 5z",fill:"var(--n-fill)"})})}):null,r]})})})]})}