neba 1.4.0 → 1.6.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 -5
  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 +99 -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/dialog/Dialog.d.ts +11 -5
  31. package/dist/components/dialog/Dialog.js +1 -1
  32. package/dist/components/drawer/Drawer.d.ts +11 -5
  33. package/dist/components/drawer/Drawer.js +1 -1
  34. package/dist/components/file-picker/FilePicker.d.ts +1 -3
  35. package/dist/components/file-picker/FilePicker.js +1 -1
  36. package/dist/components/floating-action-button/FloatingActionButton.d.ts +146 -0
  37. package/dist/components/floating-action-button/FloatingActionButton.js +1 -0
  38. package/dist/components/floating-action-button/index.d.ts +1 -0
  39. package/dist/components/floating-action-button/index.js +1 -0
  40. package/dist/components/floating-bottom-navigation/FloatingBottomNavigation.d.ts +91 -0
  41. package/dist/components/floating-bottom-navigation/FloatingBottomNavigation.js +1 -0
  42. package/dist/components/floating-bottom-navigation/index.d.ts +2 -0
  43. package/dist/components/floating-bottom-navigation/index.js +1 -0
  44. package/dist/components/heatmap-chart/HeatmapChart.d.ts +69 -0
  45. package/dist/components/heatmap-chart/HeatmapChart.js +1 -0
  46. package/dist/components/heatmap-chart/index.d.ts +2 -0
  47. package/dist/components/heatmap-chart/index.js +1 -0
  48. package/dist/components/highlight/Highlight.js +1 -1
  49. package/dist/components/line-chart/LineChart.d.ts +74 -0
  50. package/dist/components/line-chart/LineChart.js +1 -0
  51. package/dist/components/line-chart/index.d.ts +2 -0
  52. package/dist/components/line-chart/index.js +1 -0
  53. package/dist/components/number-field/NumberField.d.ts +10 -6
  54. package/dist/components/number-field/NumberField.js +1 -1
  55. package/dist/components/overlay/Overlay.d.ts +11 -6
  56. package/dist/components/overlay/Overlay.js +1 -1
  57. package/dist/components/pagination/Pagination.d.ts +28 -6
  58. package/dist/components/pagination/Pagination.js +1 -1
  59. package/dist/components/panes/Panes.js +1 -1
  60. package/dist/components/pie-chart/PieChart.d.ts +58 -0
  61. package/dist/components/pie-chart/PieChart.js +1 -0
  62. package/dist/components/pie-chart/index.d.ts +2 -0
  63. package/dist/components/pie-chart/index.js +1 -0
  64. package/dist/components/popover/Popover.d.ts +11 -5
  65. package/dist/components/popover/Popover.js +1 -1
  66. package/dist/components/progress-box/ProgressBox.js +1 -1
  67. package/dist/components/progress-circular/ProgressCircular.js +1 -1
  68. package/dist/components/progress-linear/ProgressLinear.js +1 -1
  69. package/dist/components/rating/Rating.d.ts +100 -0
  70. package/dist/components/rating/Rating.js +1 -0
  71. package/dist/components/rating/index.d.ts +1 -0
  72. package/dist/components/rating/index.js +1 -0
  73. package/dist/components/scatter-chart/ScatterChart.d.ts +45 -0
  74. package/dist/components/scatter-chart/ScatterChart.js +1 -0
  75. package/dist/components/scatter-chart/index.d.ts +2 -0
  76. package/dist/components/scatter-chart/index.js +1 -0
  77. package/dist/components/scroll-zone/ScrollZone.d.ts +126 -0
  78. package/dist/components/scroll-zone/ScrollZone.js +1 -0
  79. package/dist/components/scroll-zone/index.d.ts +2 -0
  80. package/dist/components/scroll-zone/index.js +1 -0
  81. package/dist/components/select/Select.d.ts +1 -3
  82. package/dist/components/select/Select.js +1 -1
  83. package/dist/components/sparkline/Sparkline.d.ts +67 -0
  84. package/dist/components/sparkline/Sparkline.js +1 -0
  85. package/dist/components/sparkline/index.d.ts +2 -0
  86. package/dist/components/sparkline/index.js +1 -0
  87. package/dist/components/statistic/Statistic.d.ts +7 -0
  88. package/dist/components/statistic/Statistic.js +1 -1
  89. package/dist/components/table/Table.d.ts +13 -2
  90. package/dist/components/table/Table.js +1 -1
  91. package/dist/components/text-link/TextLink.js +1 -1
  92. package/dist/components/time-picker/TimePicker.js +1 -1
  93. package/dist/components/timeline-chart/TimelineChart.d.ts +44 -0
  94. package/dist/components/timeline-chart/TimelineChart.js +1 -0
  95. package/dist/components/timeline-chart/index.d.ts +2 -0
  96. package/dist/components/timeline-chart/index.js +1 -0
  97. package/dist/components/toast/Toast.d.ts +10 -2
  98. package/dist/components/toast/Toast.js +1 -1
  99. package/dist/components/tooltip/Tooltip.d.ts +2 -4
  100. package/dist/components/tooltip/Tooltip.js +1 -1
  101. package/dist/components/tree-view/TreeView.js +1 -1
  102. package/dist/components/window-pane/WindowPane.d.ts +178 -0
  103. package/dist/components/window-pane/WindowPane.js +1 -0
  104. package/dist/components/window-pane/index.d.ts +2 -0
  105. package/dist/components/window-pane/index.js +1 -0
  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/bottom-navigation.d.ts +57 -0
  111. package/dist/internal/bottom-navigation.js +1 -0
  112. package/dist/internal/calendar.js +1 -1
  113. package/dist/internal/chart-frame.d.ts +409 -0
  114. package/dist/internal/chart-frame.js +1 -0
  115. package/dist/internal/chart-line.d.ts +44 -0
  116. package/dist/internal/chart-line.js +1 -0
  117. package/dist/internal/chart.d.ts +456 -0
  118. package/dist/internal/chart.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 +143 -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/picker.d.ts +2 -4
  128. package/dist/internal/picker.js +1 -1
  129. package/dist/internal/progress.d.ts +1 -3
  130. package/dist/internal/window.d.ts +201 -0
  131. package/dist/internal/window.js +1 -0
  132. package/dist/styles.css +1 -1
  133. package/dist/tailwind.css +211 -0
  134. package/dist/types.d.ts +214 -0
  135. package/package.json +21 -17
@@ -0,0 +1,91 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { BottomNavigationLabels, BottomNavigationValue } from '../../internal/bottom-navigation';
4
+ import type { NebaElevation, NebaPosition, NebaStyleProps } from '../../types';
5
+ /**
6
+ * Where a floating bar sits, with one value the shared vocabulary does not have.
7
+ *
8
+ * `absolute` is not a second spelling of anything in `NebaPosition` — it is the
9
+ * fourth CSS value, and it is the one that makes the bar belong to a *region*
10
+ * rather than to the window: a bar inside a Mockup's screen, inside a card,
11
+ * inside a preview. The same addition FloatingActionButton makes, for the same
12
+ * reason.
13
+ */
14
+ export type FloatingBottomNavigationPosition = NebaPosition | 'absolute';
15
+ export interface FloatingBottomNavigationProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'nav'>, 'color' | 'defaultValue' | 'onChange'> {
16
+ /** The destination the reader is on. Use with `onValueChange` for a controlled bar. */
17
+ value?: BottomNavigationValue | null;
18
+ /** Which starts current, for an uncontrolled bar. */
19
+ defaultValue?: BottomNavigationValue | null;
20
+ onValueChange?: (value: BottomNavigationValue) => void;
21
+ /**
22
+ * How the bar sits in the page's scroll. `fixed` — the default — holds it
23
+ * against the bottom of the window; `sticky` holds it against the bottom of
24
+ * whatever is scrolling; `absolute` holds it against the bottom of the
25
+ * nearest positioned ancestor, which is what a bar inside a screen of its own
26
+ * wants; `static` puts it back in the flow, centred.
27
+ * @default 'fixed'
28
+ */
29
+ position?: FloatingBottomNavigationPosition;
30
+ /**
31
+ * How far the bar floats above the bottom edge — a number in pixels or any
32
+ * CSS length. This is the whole difference between this component and
33
+ * [BottomNavigation]: the gap under it is what makes the page keep going
34
+ * underneath rather than stop at a bar.
35
+ * @default 16
36
+ */
37
+ offset?: number | string;
38
+ /**
39
+ * Which names are drawn. `selected` here, against the `all` a full-width bar
40
+ * defaults to: this bar is only as wide as what is in it, so five drawn names
41
+ * would stretch it across the screen and it would stop being a lozenge.
42
+ * @default 'selected'
43
+ */
44
+ labels?: BottomNavigationLabels;
45
+ /**
46
+ * Adds `env(safe-area-inset-bottom)` to `offset`, so the bar clears a phone's
47
+ * home indicator rather than sitting on it. Unlike on BottomNavigation this
48
+ * moves the whole sheet: there is nothing under it to keep covered.
49
+ * @default true
50
+ */
51
+ safeArea?: boolean;
52
+ /**
53
+ * Drop shadow depth. `2` here, against the `0` everything else defaults to
54
+ * and against BottomNavigation's own `0`, for the reason Pill's is `2`: this
55
+ * bar is defined by not being part of the page. A lozenge floating flat over
56
+ * the content it is floating over reads as a mistake.
57
+ * @default 2
58
+ */
59
+ elevation?: NebaElevation;
60
+ /** Every destination stops answering. */
61
+ disabled?: boolean;
62
+ /** The name the bar is announced by — "Main", "Sections". */
63
+ label?: string;
64
+ /**
65
+ * Renders something other than a `<nav>`. Base UI's own escape hatch, and
66
+ * rarely what you want here: a row of destinations is navigation.
67
+ */
68
+ render?: useRender.RenderProp;
69
+ /** The BottomNavigationItems. The same item both bars take. */
70
+ children?: React.ReactNode;
71
+ }
72
+ /**
73
+ * A row of destinations floating clear of the bottom edge of the window.
74
+ *
75
+ * It is [BottomNavigation] lifted off the page: the same `<nav>`, the same
76
+ * `aria-current`, the same BottomNavigationItem children, and deliberately not
77
+ * a `role="tablist"` for the same reason — a bottom navigation changes what the
78
+ * page is, not which panel of one is showing.
79
+ *
80
+ * What differs is the shape, and everything about the shape follows from
81
+ * `offset`. Because the page keeps going underneath, the sheet is a stadium
82
+ * rather than a bar with two corners, it is only as wide as its destinations,
83
+ * it carries a shadow, and it names only the destination the reader is on —
84
+ * five drawn names would stretch it back into a bar.
85
+ *
86
+ * The stadium is the exception the house radius rule is drawn against, exactly
87
+ * as Pill is: a control is held short of the 50% that would make it a pill
88
+ * because the flat run along its edge is what reads as a sheet with the corners
89
+ * cut off. Nothing here is lying on the page.
90
+ */
91
+ export declare const FloatingBottomNavigation: React.ForwardRefExoticComponent<FloatingBottomNavigationProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{useRender as n}from"@base-ui/react/use-render";import{barMinHeightClasses as r,BottomNavigationContext as o}from"../../internal/bottom-navigation";import{cx as s,surfaceClasses as l,surfaceSlots as i,transitionClasses as f}from"../../internal/styles";const u={solid:[l,"text-(--neba-fg) bg-(--n-panel-press)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[l,"border text-(--neba-fg) bg-(--n-panel-hover)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"},d={static:"relative mx-auto w-fit",absolute:"absolute inset-x-0 bottom-(--n-nav-offset) z-30 mx-auto w-fit",sticky:"sticky bottom-(--n-nav-offset) z-30 mx-auto w-fit",fixed:"fixed inset-x-0 bottom-(--n-nav-offset) z-40 mx-auto w-fit"},p={default:{xs:"p-1",sm:"p-1",md:"p-1.5",lg:"p-1.5",xl:"p-2"},compact:{xs:"p-0.5",sm:"p-0.5",md:"p-1",lg:"p-1",xl:"p-1"}},c={solid:`${l} bg-(--n-panel-hover) [box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]`,outline:`${l} bg-(--n-soft-hover) [box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]`,text:"bg-(--n-soft-hover)"},b={xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"};export const FloatingBottomNavigation=a.forwardRef(function({variant:l="outline",size:v="md",color:m="primary",density:x="default",elevation:g=2,value:y,defaultValue:h=null,onValueChange:w,position:$="fixed",offset:z=16,labels:j="selected",safeArea:k=!0,disabled:P=!1,label:A,render:C,className:N,style:R,children:E,...L},S){const[V,W]=a.useState(h),q=void 0!==y,B=q?y:V,F=a.useCallback(e=>{q||W(e),w?.(e)},[q,w]),H=a.useMemo(()=>({value:B??null,change:F,size:v,density:x,labels:j,disabled:P,floating:!0}),[B,F,v,x,j,P]),M=a.useRef(null),O=a.useRef(null),T=a.useCallback(e=>{M.current=e,"function"==typeof S?S(e):S&&(S.current=e)},[S]),D=a.useCallback(e=>{const t=M.current,a=O.current;if(!t||!a)return;const n=t.querySelector("[data-nav-item][aria-current]");if(!n)return;const r=!e||!a.hasAttribute("data-ready");r&&a.removeAttribute("data-ready"),a.style.setProperty("--n-nav-x",`${n.offsetLeft}px`),a.style.setProperty("--n-nav-y",`${n.offsetTop}px`),a.style.setProperty("--n-nav-w",`${n.offsetWidth}px`),a.style.setProperty("--n-nav-h",`${n.offsetHeight}px`),r&&a.offsetWidth,a.setAttribute("data-ready","")},[]);a.useLayoutEffect(()=>{D(!0)},[D,B,l,v,x,j,E]),a.useEffect(()=>{const e=M.current;if(!e)return;const t=new ResizeObserver(()=>D(!1));return t.observe(e),()=>t.disconnect()},[D]);const G="number"==typeof z?`${z}px`:z,I=s("flex max-w-full min-w-0 items-center rounded-full",r[v],p[x][v],b[v],u[l],d[$],f,N);return n({render:C??e("nav",{}),ref:T,props:{"aria-label":A,className:I,style:{...i(m,g),"--n-nav-offset":k?`calc(${G} + env(safe-area-inset-bottom))`:G,...R},children:t(o.Provider,{value:H,children:[null!=B?e("span",{ref:O,"aria-hidden":"true",className:s("pointer-events-none absolute rounded-full","top-(--n-nav-y) left-(--n-nav-x) h-(--n-nav-h) w-(--n-nav-w)",c[l],"[transition-property:left,top,width,height]","[transition-timing-function:var(--neba-ease)]","[transition-duration:0ms] data-[ready]:[transition-duration:var(--neba-duration)]","motion-reduce:[transition-duration:0ms]")}):null,E]}),...L}})});
@@ -0,0 +1,2 @@
1
+ export { FloatingBottomNavigation } from './FloatingBottomNavigation';
2
+ export type { FloatingBottomNavigationPosition, FloatingBottomNavigationProps } from './FloatingBottomNavigation';
@@ -0,0 +1 @@
1
+ export{FloatingBottomNavigation}from"./FloatingBottomNavigation";
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ import { type ChartScaleKind } from '../../internal/chart';
3
+ import type { NebaChartCategory, NebaChartLegend, NebaChartSeries } from '../../types';
4
+ import type { ChartBaseProps } from '../../internal/chart-frame';
5
+ export interface HeatmapChartProps extends Omit<ChartBaseProps, 'legend'> {
6
+ /**
7
+ * The rows. Each series is a row of the grid or a group of the treemap, and
8
+ * each datum a cell or a tile.
9
+ *
10
+ * `y` is the magnitude and `x` names the column. A `null` is a gap: the cell
11
+ * is left as surface rather than drawn as the bottom of the scale, because
12
+ * "nothing happened" and "the least of anything" are not the same reading.
13
+ */
14
+ series: readonly NebaChartSeries[];
15
+ /** The column names. Points may carry their own `x` instead. */
16
+ categories?: readonly NebaChartCategory[];
17
+ /**
18
+ * - `grid` — a cell per row and column, which is the shape for two
19
+ * categorical axes and one magnitude: hours against weekdays, a cohort
20
+ * against a week.
21
+ * - `treemap` — a tile per datum, sized by its share and packed to fill the
22
+ * box. For parts of a whole where the parts are grouped and there are more
23
+ * of them than a [PieChart](./pie-chart) can hold.
24
+ * @default 'grid'
25
+ */
26
+ shape?: 'grid' | 'treemap';
27
+ /**
28
+ * How the magnitude is coloured.
29
+ *
30
+ * - `sequential` — one hue, pale to deep. The default, and right whenever
31
+ * more is simply more.
32
+ * - `diverging` — two hues either side of a neutral, for a value with a
33
+ * *middle* that means something: over and under target, gained and lost.
34
+ * Reached for on a plain magnitude it invents a boundary the data has none
35
+ * of.
36
+ * @default 'sequential'
37
+ */
38
+ scale?: ChartScaleKind;
39
+ /** Where a `diverging` scale turns over. @default 0 */
40
+ midpoint?: number;
41
+ /** Where the scale starts and ends. Taken from the data otherwise. */
42
+ min?: number;
43
+ max?: number;
44
+ /**
45
+ * Writes each cell's value on it, where the cell is big enough for the text
46
+ * to fit with room either side. A label that does not fit is dropped rather
47
+ * than clipped — the tooltip and the table still have it.
48
+ * @default 'none'
49
+ */
50
+ valueLabels?: 'none' | 'all';
51
+ /** Where the scale legend sits. `false` leaves it off. */
52
+ legend?: boolean | Pick<NebaChartLegend, 'side' | 'align'>;
53
+ }
54
+ /**
55
+ * A magnitude per cell, coloured rather than measured.
56
+ *
57
+ * Two shapes of the same idea. A `grid` is the one to reach for when both axes
58
+ * are categorical and the question is *where* — which hour of which day, which
59
+ * cohort in which week; a bar chart of the same data would be forty bars nobody
60
+ * can scan. A `treemap` is for parts of a whole with more parts than a
61
+ * [PieChart](./pie-chart) can hold, and it is the same component because the
62
+ * data is the same shape: a row of a heatmap and a group of a treemap are both
63
+ * a named series of named magnitudes.
64
+ *
65
+ * Colour here encodes *size* and not identity, so it comes off a one-hue ramp
66
+ * rather than off the categorical palette — a heatmap in eight hues says its
67
+ * cells are eight unrelated things.
68
+ */
69
+ export declare function HeatmapChart({ series, categories, shape, scale, midpoint, min, max, valueLabels, height, format, locale, label, legend, tooltip, empty, size, variant, padded, className, ...box }: HeatmapChartProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{ChartScaleLegend as n,ChartSurface as i,ChartTooltipPanel as a,useMeasuredWidth as r}from"../../internal/chart-frame";import{categoryAt as o,chartFontSizes as d,compactNumber as h,formatCategory as c,markGap as s,plotHeights as m,rampFill as u,rampInk as x,rampStep as f,rampSteps as g,squarify as p,textWidth as v,toValues as w,truncate as b}from"../../internal/chart";import{numberFormatter as y}from"../../internal/format";import{cx as M,metaTextClasses as k,srOnlyClasses as A}from"../../internal/styles";import{useMessages as N}from"../../internal/i18n";export function HeatmapChart({series:z,categories:E,shape:S="grid",scale:j="sequential",midpoint:B=0,min:C,max:I,valueLabels:_="none",height:D,format:L,locale:P,label:R,legend:q,tooltip:H,empty:K,size:U="md",variant:W="text",padded:F=!1,className:G,...J}){const O=l.useRef(null),Q=r(O),T=N(P),V=l.useId(),[X,Y]=l.useState(null),Z=l.useCallback(e=>L?y(P,L).format(e):h(e,P),[L,P]),ee=l.useMemo(()=>w(z),[z]),te=ee.reduce((e,t)=>Math.max(e,t.length),0),le=l.useMemo(()=>Array.from({length:te},(e,t)=>o(t,E,ee)),[te,E,ee]),ne=l.useMemo(()=>z.map((e,t)=>e.name??`${t+1}`),[z]),ie=l.useMemo(()=>{let e=1/0,t=-1/0,l=!1;for(const n of ee)for(const i of n)null!==i.value&&(l=!0,e=Math.min(e,i.value),t=Math.max(t,i.value));return l?{min:e,max:t}:null},[ee]),ae=C??ie?.min??0,re=I??ie?.max??1,oe=l.useCallback(e=>f(e,ae,re,j,B),[ae,re,j,B]),de="number"==typeof D?D:m[U]??220,he=d[U],ce=!0===q||void 0===q||!1===q?{}:q,se=!1!==q,me=ce.side??"bottom",ue=!1===H?{mode:"none"}:!0===H||void 0===H?{}:H,xe="none"===ue.mode,fe=null===ie||0===te||0===z.length,ge=l.useMemo(()=>{if("treemap"===S||Q<=0)return{texts:[],band:0};const e=Math.min(150,.25*Q),t=ne.map(t=>b(t,e,he));return{texts:t,band:t.reduce((e,t)=>Math.max(e,v(t,he)),0)+10}},[S,ne,Q,he]),pe="treemap"===S?0:he+8,ve={left:ge.band,width:Math.max(0,Q-ge.band),height:Math.max(0,de-pe)},we=l.useMemo(()=>{if(ve.width<=0||ve.height<=0)return[];if("treemap"===S){const e=[];return ee.forEach((t,l)=>t.forEach((t,n)=>{null!==t.value&&e.push({row:l,index:n,cell:t})})),p(e.map(e=>Math.max(0,e.cell.value??0)),ve.width,ve.height).map(t=>({row:e[t.index].row,index:e[t.index].index,cell:e[t.index].cell,x:ve.left+t.x,y:t.y,width:t.width,height:t.height}))}const e=ve.height/Math.max(1,z.length),t=ve.width/Math.max(1,te),l=[];return ee.forEach((n,i)=>n.forEach((n,a)=>{null!==n.value&&l.push({row:i,index:a,cell:n,x:ve.left+a*t,y:i*e,width:t,height:e})})),l},[S,ee,z.length,te,ve.left,ve.width,ve.height]),be=l.useCallback(e=>c(e.cell.x??E?.[e.index]??le[e.index]??e.index,P),[E,le,P]),ye=null===X?null:we.find(e=>e.row===X.row&&e.index===X.index)??null,Me=null===ye?[]:[{seriesIndex:ye.row,color:ye.cell.color??u(oe(ye.cell.value??0),j),value:ye.cell.value,formatted:Z(ye.cell.value??0),label:ye.cell.label}],ke=Array.from({length:g},(e,t)=>u(t,j));return e(i,{...J,size:U,variant:W,padded:F,className:G,legendSide:me,legend:se&&!fe?e(n,{steps:ke,from:Z("diverging"===j?-$(ae,re,B)+B:ae),to:Z("diverging"===j?$(ae,re,B)+B:re),middle:"diverging"===j?Z(B):void 0,align:ce.align??"center",vertical:"left"===me||"right"===me,size:U}):null,table:fe?null:t("table",{id:V,className:A,children:[R?e("caption",{children:R}):null,e("thead",{children:t("tr",{children:[e("th",{scope:"col"}),le.map((t,l)=>e("th",{scope:"col",children:c(t,P)},l))]})}),e("tbody",{children:ee.map((l,n)=>t("tr",{children:[e("th",{scope:"row",children:ne[n]}),le.map((t,n)=>{const i=l[n];return e("td",{children:void 0!==i?.label?i.label:null==i?.value?"":Z(i.value)},n)})]},n))})]}),children:t("div",{ref:O,role:"img",tabIndex:fe?void 0:0,"aria-label":R,"aria-describedby":fe?void 0:V,onPointerLeave:()=>Y(null),onBlur:()=>Y(null),onKeyDown:e=>{if(xe||0===we.length)return;const t=null===X?-1:we.findIndex(e=>e.row===X.row&&e.index===X.index);if("ArrowRight"===e.key||"ArrowDown"===e.key){const e=we[Math.min(we.length-1,t+1)];Y({row:e.row,index:e.index})}else if("ArrowLeft"===e.key||"ArrowUp"===e.key){const e=we[Math.max(0,(-1===t?we.length:t)-1)];Y({row:e.row,index:e.index})}else{if("Escape"!==e.key)return;Y(null)}e.preventDefault()},className:M("relative w-full rounded-(--neba-radius-xs)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"),style:{height:de},children:[fe?e("div",{className:M("flex h-full items-center justify-center text-(--neba-muted-fg)",k[U]),children:K??T.empty.title}):Q>0?t("svg",{width:Q,height:de,viewBox:`0 0 ${Q} ${de}`,"aria-hidden":"true",className:"block",children:[we.map(l=>{const n=oe(l.cell.value??0),i=X?.row===l.row&&X?.index===l.index,a=Math.max(0,l.width-s),r=Math.max(0,l.height-s);if(a<=0||r<=0)return null;const o=Z(l.cell.value??0),d="treemap"===S?"all"===_?[be(l),o]:[be(l)]:"all"===_?[o]:[],h=d.filter(e=>function(e,t,l,n){return l>=1.8*n&&t>=Math.min(v(e,n),2.5*n)+8}(e,a,r/d.length,he)),c=l.cell.color?"var(--neba-surface)":x(n,j);return t("g",{children:[e("rect",{x:l.x+s/2,y:l.y+s/2,width:a,height:r,rx:Math.min(3,a/2,r/2),fill:l.cell.color??u(n,j),opacity:i?1:.94,onPointerEnter:xe?void 0:()=>Y({row:l.row,index:l.index}),className:"[transition:opacity_var(--neba-duration)_var(--neba-ease)]"}),h.map((t,n)=>e("text",{x:l.x+l.width/2,y:l.y+l.height/2+(n-(h.length-1)/2)*(he+2),textAnchor:"middle",dominantBaseline:"central",fontSize:he,fontWeight:0===n?500:400,fill:c,opacity:0===n?1:.85,pointerEvents:"none",className:0===n&&"treemap"===S?void 0:"tabular-nums",children:b(t,l.width-8,he)},n))]},`${l.row}-${l.index}`)}),"grid"===S?ge.texts.map((t,l)=>e("text",{x:ve.left-8,y:(l+.5)*ve.height/Math.max(1,z.length),textAnchor:"end",dominantBaseline:"central",fontSize:he,fill:"var(--neba-muted-fg)",children:t},`row-${l}`)):null,"grid"===S?le.map((t,l)=>{const n=ve.width/Math.max(1,te),i=c(t,P);return l%Math.max(1,Math.ceil((v(i,he)+8)/Math.max(1,n)))!==0?null:e("text",{x:ve.left+(l+.5)*n,y:ve.height+he,textAnchor:"middle",fontSize:he,fill:"var(--neba-muted-fg)",children:i},`col-${l}`)}):null]}):null,ye&&!xe?ue.render?e("div",{className:"pointer-events-none absolute z-10",style:{left:ye.x+ye.width/2,top:ye.y},children:ue.render({index:ye.index,category:ye.cell.x??le[ye.index]??ye.index,items:Me})}):e(a,{heading:`${ne[ye.row]} · ${be(ye)}`,items:Me,x:ye.x+ye.width/2,y:ye.y,flip:ye.x+ye.width/2>.6*Q,size:U}):null]})})}function $(e,t,l){return Math.max(Math.abs(t-l),Math.abs(l-e))}
@@ -0,0 +1,2 @@
1
+ export { HeatmapChart } from './HeatmapChart';
2
+ export type { HeatmapChartProps } from './HeatmapChart';
@@ -0,0 +1 @@
1
+ export{HeatmapChart}from"./HeatmapChart";
@@ -1 +1 @@
1
- import{jsx as n}from"react/jsx-runtime";import*as e from"react";import{transitionClasses as t}from"../../internal/styles";const r={solid:"bg-(--n-fill) text-(--n-on-solid)",outline:"border bg-(--n-panel) text-(--n-accent) [border-color:var(--n-line)]",text:"bg-transparent text-(--n-accent)"},o={regular:"font-normal",medium:"font-medium",semibold:"font-semibold",bold:"font-bold"},l=/[\p{L}\p{N}_]/u;function i(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function a(n,e,t){const r=e>0?n[e-1]:"",o=t<n.length?n[t]:"";return!l.test(r)&&!l.test(o)}function s(n,e,t,r){e.lastIndex=0;const o=[];let l,i=0;for(;null!==(l=e.exec(n));){if(""===l[0]){e.lastIndex+=1;continue}const s=l.index,c=s+l[0].length;t&&!a(n,s,c)||(s>i&&o.push(n.slice(i,s)),o.push(r(l[0],`${s}`)),i=c)}return 0===o.length?n:(i<n.length&&o.push(n.slice(i)),o)}function c(n,t,r,o){if("string"==typeof n)return s(n,t,r,o);if("number"==typeof n)return s(String(n),t,r,o);if(Array.isArray(n))return e.Children.map(n,n=>c(n,t,r,o));if(e.isValidElement(n)){const l=n.props.children;return void 0===l||"function"==typeof l?n:e.cloneElement(n,void 0,c(l,t,r,o))}return n}export const Highlight=e.forwardRef(function({query:l,variant:a="solid",color:s="warning",caseSensitive:u=!1,wholeWord:f=!1,underline:d=!1,weight:m,className:p,style:g,children:h,...b},x){const y=e.useMemo(()=>function(n,e){if(n instanceof RegExp)return n.global?n:new RegExp(n.source,`${n.flags}g`);const t=(Array.isArray(n)?n:[n]).map(n=>n.trim()).filter(Boolean).sort((n,e)=>e.length-n.length);return 0===t.length?null:new RegExp(t.map(i).join("|"),e?"gu":"giu")}(l,u),[l,u]),v=["rounded-[0.25rem] px-0.5 -mx-0.5","box-decoration-clone",r[a],d?"underline decoration-2 underline-offset-2":"",m?o[m]:"",t].filter(Boolean).join(" "),$=y?c(h,y,f,(e,t)=>n("mark",{className:v,children:e},t)):h;return n("span",{ref:x,className:p,style:{"--n-fill":`var(--neba-${s}-fill)`,"--n-on-solid":`var(--neba-${s}-on-solid)`,"--n-accent":`var(--neba-${s}-accent)`,"--n-panel":`var(--neba-${s}-panel)`,"--n-line":`var(--neba-${s}-line)`,...g},...b,children:$})});
1
+ import{jsx as n}from"react/jsx-runtime";import*as e from"react";import{transitionClasses as t}from"../../internal/styles";const r={solid:"bg-(--n-fill) text-(--n-on-solid)",outline:"border bg-(--n-panel) text-(--n-accent) [border-color:var(--n-line)]",text:"bg-transparent text-(--n-accent)"},o={regular:"font-normal",medium:"font-medium",semibold:"font-semibold",bold:"font-bold"},l=/[\p{L}\p{N}_]/u;function i(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function a(n,e,t){const r=e>0?n[e-1]:"",o=t<n.length?n[t]:"";return!l.test(r)&&!l.test(o)}function s(n,e,t,r){e.lastIndex=0;const o=[];let l,i=0;for(;null!==(l=e.exec(n));){if(""===l[0]){e.lastIndex+=1;continue}const s=l.index,c=s+l[0].length;t&&!a(n,s,c)||(s>i&&o.push(n.slice(i,s)),o.push(r(l[0],`${s}`)),i=c)}return 0===o.length?n:(i<n.length&&o.push(n.slice(i)),o)}function c(n,t,r,o){if("string"==typeof n)return s(n,t,r,o);if("number"==typeof n)return s(String(n),t,r,o);if(Array.isArray(n))return e.Children.map(n,n=>c(n,t,r,o));if(e.isValidElement(n)){const l=n.props.children;return void 0===l||"function"==typeof l?n:e.cloneElement(n,void 0,c(l,t,r,o))}return n}export const Highlight=e.forwardRef(function({query:l,variant:a="solid",color:s="warning",caseSensitive:u=!1,wholeWord:f=!1,underline:d=!1,weight:m,className:g,style:p,children:h,...b},x){const y=e.useMemo(()=>function(n,e){if(n instanceof RegExp)return new RegExp(n.source,n.global?n.flags:`${n.flags}g`);const t=(Array.isArray(n)?n:[n]).map(n=>n.trim()).filter(Boolean).sort((n,e)=>e.length-n.length);return 0===t.length?null:new RegExp(t.map(i).join("|"),e?"gu":"giu")}(l,u),[l,u]),v=["rounded-[0.25rem] px-0.5 -mx-0.5","box-decoration-clone",r[a],d?"underline decoration-2 underline-offset-2":"",m?o[m]:"",t].filter(Boolean).join(" "),$=y?c(h,y,f,(e,t)=>n("mark",{className:v,children:e},t)):h;return n("span",{ref:x,className:g,style:{"--n-fill":`var(--neba-${s}-fill)`,"--n-on-solid":`var(--neba-${s}-on-solid)`,"--n-accent":`var(--neba-${s}-accent)`,"--n-panel":`var(--neba-${s}-panel)`,"--n-line":`var(--neba-${s}-line)`,...p},...b,children:$})});
@@ -0,0 +1,74 @@
1
+ import * as React from 'react';
2
+ import { type CartesianChartProps } from '../../internal/chart-frame';
3
+ import { type ChartMarkers } from '../../internal/chart-line';
4
+ import type { NebaChartCurve, NebaChartValueLabels } from '../../types';
5
+ export interface LineChartProps extends CartesianChartProps {
6
+ /**
7
+ * How the line gets from one point to the next.
8
+ *
9
+ * - `linear` — straight segments. The default, and the only one that claims
10
+ * nothing the data did not say.
11
+ * - `smooth` — a monotone cubic. Curved, but it will not dip below a value
12
+ * that both of its neighbours are above; a plain spline would.
13
+ * - `step` — held at each value until the next one. What a rate, a tier or a
14
+ * setting actually did between two readings, rather than a diagonal
15
+ * pretending it drifted.
16
+ * @default 'linear'
17
+ */
18
+ curve?: NebaChartCurve;
19
+ /**
20
+ * Dots on the points.
21
+ *
22
+ * `auto` — the default — draws them while there are few enough points for a
23
+ * dot to mean something, and stops at fourteen. Whatever this says, the point
24
+ * under the pointer always gets one: that is what tells the reader which
25
+ * column the tooltip is about.
26
+ * @default 'auto'
27
+ */
28
+ markers?: ChartMarkers;
29
+ /**
30
+ * Fades the line from a paler step of its own hue at the start to the full
31
+ * colour at the end, so the recent end of a long series is the loud one.
32
+ * @default false
33
+ */
34
+ gradient?: boolean;
35
+ /**
36
+ * Draws the line straight through a `null` instead of breaking at it.
37
+ *
38
+ * Off, and it should stay off unless the gap is an artefact of how the data
39
+ * was collected. A bridged gap is a number the chart made up.
40
+ * @default false
41
+ */
42
+ connectNulls?: boolean;
43
+ /**
44
+ * Which values are written on the line. `last` is the one to reach for — it
45
+ * names where each series ended up, which is the question a line chart is
46
+ * usually being asked.
47
+ * @default 'none'
48
+ */
49
+ valueLabels?: NebaChartValueLabels;
50
+ /**
51
+ * Stacks the series, each line riding on the total of the ones below it.
52
+ *
53
+ * Rare on a line chart and worth thinking twice about: the reader can follow
54
+ * the bottom series and the top total, and nothing in between. An
55
+ * [AreaChart](./area-chart) is the shape that makes stacking legible.
56
+ * @default false
57
+ */
58
+ stacked?: boolean;
59
+ }
60
+ /**
61
+ * A value against time, or against anything else with an order to it.
62
+ *
63
+ * The line is the mark that says *change*: it claims the space between two
64
+ * points is a journey rather than two separate facts, which is true of a
65
+ * temperature and false of four product categories. Reach for a
66
+ * [BarChart](./bar-chart) when the categories could be shuffled without losing
67
+ * anything.
68
+ *
69
+ * Everything around the line — the axes, the grid, the crosshair, the legend,
70
+ * the tooltip and the table a screen reader gets instead of the picture — comes
71
+ * from the shared frame, which is what makes a LineChart and a BarChart on one
72
+ * dashboard read as one drawing rather than two.
73
+ */
74
+ export declare function LineChart({ curve, markers, gradient, connectNulls, valueLabels, stacked, ...props }: LineChartProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e}from"react/jsx-runtime";import*as r from"react";import{CartesianChart as t}from"../../internal/chart-frame";import{LineSeries as n}from"../../internal/chart-line";export function LineChart({curve:a="linear",markers:o="auto",gradient:c=!1,connectNulls:i=!1,valueLabels:l="none",stacked:s=!1,...m}){const u=r.useId().replace(/:/g,"");return e(t,{...m,stacked:s,inset:!0,includeZero:!1,headroom:"none"===l?0:10,children:r=>e(n,{context:r,curve:a,filled:!1,stacked:s,markers:o,valueLabels:l,connectNulls:i,gradient:c,idPrefix:u})})}
@@ -0,0 +1,2 @@
1
+ export { LineChart } from './LineChart';
2
+ export type { LineChartProps } from './LineChart';
@@ -0,0 +1 @@
1
+ export{LineChart}from"./LineChart";
@@ -14,7 +14,7 @@ import type { NebaElevation, NebaStyleProps } from '../../types';
14
14
  * nobody hits.
15
15
  */
16
16
  export type NumberFieldSteppers = 'end' | 'split' | 'none';
17
- export interface NumberFieldProps extends NebaStyleProps {
17
+ export interface NumberFieldProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
18
18
  /**
19
19
  * Drop shadow depth. `0` (the default) is flat — a field is a well, not a
20
20
  * surface that floats.
@@ -57,11 +57,17 @@ export interface NumberFieldProps extends NebaStyleProps {
57
57
  * reports `1240`.
58
58
  */
59
59
  format?: Intl.NumberFormatOptions;
60
- /** Which locale the number is written and parsed in. Defaults to the runtime's. */
60
+ /**
61
+ * Which locale the number is written and parsed in. Defaults to the runtime's.
62
+ *
63
+ * A plain BCP 47 string also names the two steppers, since a field that reads
64
+ * its digits in one language should not read its buttons in another.
65
+ * `incrementLabel` and `decrementLabel` write those words out instead.
66
+ */
61
67
  locale?: Intl.LocalesArgument;
62
68
  /** Where the steppers sit, or `none` for a field without them. @default 'end' */
63
69
  steppers?: NumberFieldSteppers;
64
- /** Accessible name of the increment button. */
70
+ /** Accessible name of the increment button. Defaults to the `locale`'s word. */
65
71
  incrementLabel?: string;
66
72
  /** Accessible name of the decrement button. */
67
73
  decrementLabel?: string;
@@ -93,8 +99,6 @@ export interface NumberFieldProps extends NebaStyleProps {
93
99
  /** Placeholder shown while the field is empty. */
94
100
  placeholder?: string;
95
101
  id?: string;
96
- className?: string;
97
- style?: React.CSSProperties;
98
102
  }
99
103
  /**
100
104
  * A field that only holds a number.
@@ -110,4 +114,4 @@ export interface NumberFieldProps extends NebaStyleProps {
110
114
  * clamping, the press-and-hold repeat on the steppers, and the hidden input
111
115
  * that submits with a form.
112
116
  */
113
- export declare function NumberField({ variant, size, color, density, elevation, value, defaultValue, onValueChange, onValueCommitted, min, max, step, largeStep, smallStep, snapOnStep, allowWheelScrub, format, locale, steppers, incrementLabel, decrementLabel, label, description, error, invalid, startIcon, endIcon, fullWidth, disabled, readOnly, required, name, placeholder, id, className, style }: NumberFieldProps): React.JSX.Element;
117
+ export declare function NumberField({ variant, size, color, density, elevation, value, defaultValue, onValueChange, onValueCommitted, min, max, step, largeStep, smallStep, snapOnStep, allowWheelScrub, format, locale, steppers, incrementLabel, decrementLabel, label, description, error, invalid, startIcon, endIcon, fullWidth, disabled, readOnly, required, name, placeholder, id, className, style, ...props }: NumberFieldProps): React.JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as n}from"react/jsx-runtime";import{NumberField as t}from"@base-ui/react/number-field";import{Field as a}from"@base-ui/react/field";import{MinusIcon as l,PlusIcon as i}from"../../internal/icons";import{controlHeightClasses as r,controlTextLeadingClasses as s,disabledClasses as o,fieldReadOnlyClasses as c,fieldRestClasses as d,focusWithinRingClasses as m,gapClasses as u,hasContent as p,iconClasses as f,metaTextClasses as b,paddingXClasses as h,radiusClasses as x,stackGapClasses as g,surfaceSlots as v,transitionClasses as N}from"../../internal/styles";const j=["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent]",N,"focus-within:[transition-duration:0ms]",m,f].join(" "),w=["inline-flex size-[1.7em] shrink-0 cursor-pointer items-center justify-center","rounded-(--neba-radius-xs) text-(--neba-muted-fg) select-none","[&_svg]:size-[0.9em] [&_svg]:shrink-0","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","[transition:background-color_var(--neba-duration)_var(--neba-ease),color_var(--neba-duration)_var(--neba-ease)]","active:[transition-duration:0ms]","hover:bg-(--n-soft) hover:text-(--n-accent)","active:bg-(--n-soft-press)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1","disabled:cursor-not-allowed disabled:bg-transparent disabled:text-(--neba-disabled-fg)"].join(" ");export function NumberField({variant:m="outline",size:f="md",color:N="primary",density:k="default",elevation:y=0,value:S,defaultValue:_,onValueChange:V,onValueCommitted:I,min:C,max:O,step:z,largeStep:D,smallStep:L,snapOnStep:W,allowWheelScrub:$=!1,format:q,locale:B,steppers:F="end",incrementLabel:R="Increase",decrementLabel:E="Decrease",label:G,description:A,error:H,invalid:J,startIcon:K,endIcon:M,fullWidth:P=!1,disabled:Q=!1,readOnly:T=!1,required:U=!1,name:X,placeholder:Y,id:Z,className:ee,style:ne}){const te=p(H),ae=J??te,le=ae?"danger":N,ie=h[k][f],re={end:`${ie} pe-1`,split:"px-1",none:ie},se=e(t.Decrement,{"aria-label":E,className:w,children:e(l,{})}),oe=e(t.Increment,{"aria-label":R,className:w,children:e(i,{})}),ce="none"!==F&&!T;return n(a.Root,{disabled:Q,invalid:ae,className:["flex-col align-top",g[f],P?"flex w-full":"inline-flex",ee??""].filter(Boolean).join(" "),style:{...v(le,y),...ne},children:[G?e(a.Label,{className:[b[f],"font-medium",Q?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:G}):null,e(t.Root,{id:Z,name:X,className:"contents",value:S,defaultValue:_,onValueChange:e=>V?.(e),onValueCommitted:e=>I?.(e),min:C,max:O,step:z,largeStep:D,smallStep:L,snapOnStep:W,allowWheelScrub:$,format:q,locale:B,disabled:Q,readOnly:T,required:U,children:n(t.Group,{className:[j,r[f],s[f],x[f],u[f],ce?re[F]:ie,Q?o[m]:T?c[m]:d[m]].join(" "),children:[ce&&"split"===F?se:null,K?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:K}):null,e(t.Input,{placeholder:Y,className:["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","tabular-nums","split"===F&&ce?"text-center":"","placeholder:text-(--neba-muted-fg)","caret-(--n-accent) selection:bg-(--n-soft-press)","disabled:cursor-not-allowed"].filter(Boolean).join(" ")}),M?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:M}):null,ce&&"end"===F?n("span",{className:"flex shrink-0 items-center gap-0.5",children:[se,oe]}):null,ce&&"split"===F?oe:null]})}),A?e(a.Description,{className:`${b[f]} text-(--neba-muted-fg)`,children:A}):null,te?e(a.Error,{match:!0,className:`${b[f]} text-(--n-accent)`,children:H}):null]})}
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import{NumberField as t}from"@base-ui/react/number-field";import{Field as a}from"@base-ui/react/field";import{useMessages as l}from"../../internal/i18n";import{MinusIcon as i,PlusIcon as r}from"../../internal/icons";import{controlHeightClasses as s,controlTextLeadingClasses as o,disabledClasses as c,fieldReadOnlyClasses as d,fieldRestClasses as m,focusWithinRingClasses as u,gapClasses as p,hasContent as f,iconClasses as b,metaTextClasses as h,paddingXClasses as x,radiusClasses as g,stackGapClasses as v,surfaceSlots as N,transitionClasses as j}from"../../internal/styles";const w=["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent]",j,"focus-within:[transition-duration:0ms]",u,b].join(" "),y=["inline-flex size-[1.7em] shrink-0 cursor-pointer items-center justify-center","rounded-(--neba-radius-xs) text-(--neba-muted-fg) select-none","[&_svg]:size-[0.9em] [&_svg]:shrink-0","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","[transition:background-color_var(--neba-duration)_var(--neba-ease),color_var(--neba-duration)_var(--neba-ease)]","active:[transition-duration:0ms]","hover:bg-(--n-soft) hover:text-(--n-accent)","active:bg-(--n-soft-press)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1","disabled:cursor-not-allowed disabled:bg-transparent disabled:text-(--neba-disabled-fg)"].join(" ");export function NumberField({variant:u="outline",size:b="md",color:j="primary",density:k="default",elevation:S=0,value:_,defaultValue:V,onValueChange:C,onValueCommitted:I,min:O,max:z,step:L,largeStep:W,smallStep:$,snapOnStep:q,allowWheelScrub:B=!1,format:D,locale:F,steppers:R="end",incrementLabel:E,decrementLabel:G,label:A,description:H,error:J,invalid:K,startIcon:M,endIcon:P,fullWidth:Q=!1,disabled:T=!1,readOnly:U=!1,required:X=!1,name:Y,placeholder:Z,id:ee,className:ne,style:te,...ae}){const le=l("string"==typeof F?F:void 0),ie=f(J),re=K??ie,se=re?"danger":j,oe=x[k][b],ce={end:`${oe} pe-1`,split:"px-1",none:oe},de=e(t.Decrement,{"aria-label":G??le.number.decrease,className:y,children:e(i,{})}),me=e(t.Increment,{"aria-label":E??le.number.increase,className:y,children:e(r,{})}),ue="none"!==R&&!U;return n(a.Root,{disabled:T,invalid:re,className:["flex-col align-top",v[b],Q?"flex w-full":"inline-flex",ne??""].filter(Boolean).join(" "),style:{...N(se,S),...te},...ae,children:[A?e(a.Label,{className:[h[b],"font-medium",T?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:A}):null,e(t.Root,{id:ee,name:Y,className:"contents",value:_,defaultValue:V,onValueChange:e=>C?.(e),onValueCommitted:e=>I?.(e),min:O,max:z,step:L,largeStep:W,smallStep:$,snapOnStep:q,allowWheelScrub:B,format:D,locale:F,disabled:T,readOnly:U,required:X,children:n(t.Group,{className:[w,s[b],o[b],g[b],p[b],ue?ce[R]:oe,T?c[u]:U?d[u]:m[u]].join(" "),children:[ue&&"split"===R?de:null,M?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:M}):null,e(t.Input,{placeholder:Z,className:["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","tabular-nums","split"===R&&ue?"text-center":"","placeholder:text-(--neba-muted-fg)","caret-(--n-accent) selection:bg-(--n-soft-press)","disabled:cursor-not-allowed"].filter(Boolean).join(" ")}),P?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:P}):null,ue&&"end"===R?n("span",{className:"flex shrink-0 items-center gap-0.5",children:[de,me]}):null,ue&&"split"===R?me:null]})}),H?e(a.Description,{className:`${h[b]} text-(--neba-muted-fg)`,children:H}):null,ie?e(a.Error,{match:!0,className:`${h[b]} text-(--n-accent)`,children:J}):null]})}
@@ -25,7 +25,7 @@ export type OverlayTone = 'scrim' | 'blur' | 'solid' | 'clear';
25
25
  * no `elevation` either: the overlay *is* the plane everything else floats
26
26
  * above, and a scrim with a drop shadow is a scrim with an edge.
27
27
  */
28
- export interface OverlayProps {
28
+ export interface OverlayProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'children'> {
29
29
  /** The overlay is shown. Use with `onOpenChange` for a controlled overlay. */
30
30
  open?: boolean;
31
31
  /** Whether the overlay starts shown, for an uncontrolled one. */
@@ -57,17 +57,22 @@ export interface OverlayProps {
57
57
  size?: NebaSize;
58
58
  /** Semantic colour role. Reaches the focus ring and whatever the content reads. */
59
59
  color?: NebaColor;
60
+ /**
61
+ * Which language the overlay is named in — a BCP 47 tag such as `ko`, `pt-BR` or
62
+ * `zh-Hant`. Unsupported tags fall back to English.
63
+ *
64
+ * `label` writes the word out instead; this is for the far more common
65
+ * case where the page already knows its own language.
66
+ */
67
+ locale?: string;
60
68
  /**
61
69
  * The accessible name of the overlay. An overlay that holds nothing readable
62
70
  * — a bare spinner, a `clear` sheet — still has to say what it is, so this
63
- * has a default rather than being optional.
64
- * @default 'Overlay'
71
+ * falls back to the `locale`'s word for it rather than to nothing.
65
72
  */
66
73
  label?: string;
67
74
  /** What sits on top of the scrim — a spinner, a line of text, a small card. */
68
75
  children?: React.ReactNode;
69
- className?: string;
70
- style?: React.CSSProperties;
71
76
  }
72
77
  /**
73
78
  * A sheet over the whole page that stops it being used.
@@ -82,4 +87,4 @@ export interface OverlayProps {
82
87
  * held inside, the page behind going inert, and focus returning to wherever it
83
88
  * came from when the overlay closes.
84
89
  */
85
- export declare function Overlay({ open, defaultOpen, onOpenChange, tone, dismissible, modal, align, size, color, label, className, style, children }: OverlayProps): React.JSX.Element;
90
+ export declare function Overlay({ open, defaultOpen, onOpenChange, tone, dismissible, modal, align, size, color, locale, label, className, style, children, ...props }: OverlayProps): React.JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Dialog as r}from"@base-ui/react/dialog";import{surfaceSlots as n}from"../../internal/styles";const t={scrim:"bg-(--neba-scrim) [backdrop-filter:blur(2px)]",blur:"[background-color:color-mix(in_oklab,var(--neba-scrim)_55%,transparent)] [backdrop-filter:blur(14px)_saturate(1.4)]",solid:"bg-(--neba-surface)",clear:""},l={start:"items-start",center:"items-center",end:"items-end"},i={xs:"p-3",sm:"p-4",md:"p-6",lg:"p-8",xl:"p-10"},s=["[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" ");export function Overlay({open:o,defaultOpen:c,onOpenChange:p,tone:m="scrim",dismissible:d=!1,modal:b=!0,align:f="center",size:u="md",color:x="primary",label:y="Overlay",className:g,style:h,children:j}){return e(r.Root,{open:o,defaultOpen:c,modal:b,disablePointerDismissal:!d,onOpenChange:(e,a)=>{d||e||"escape-key"!==a.reason?p?.(e):a.cancel()},children:a(r.Portal,{children:[e(r.Backdrop,{className:`neba-portal fixed inset-0 z-50 ${s} ${t[m]}`}),e(r.Viewport,{className:["neba-portal fixed inset-0 z-50 flex justify-center",l[f],i[u]].join(" "),children:e(r.Popup,{"aria-label":y,className:["flex max-h-full max-w-full flex-col items-center justify-center","[outline:none]",s,g??""].filter(Boolean).join(" "),style:{...n(x,0),...h},children:j})})]})})}
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Dialog as r}from"@base-ui/react/dialog";import{useMessages as n}from"../../internal/i18n";import{surfaceSlots as l}from"../../internal/styles";const t={scrim:"bg-(--neba-scrim) [backdrop-filter:blur(2px)]",blur:"[background-color:color-mix(in_oklab,var(--neba-scrim)_55%,transparent)] [backdrop-filter:blur(14px)_saturate(1.4)]",solid:"bg-(--neba-surface)",clear:""},i={start:"items-start",center:"items-center",end:"items-end"},o={xs:"p-3",sm:"p-4",md:"p-6",lg:"p-8",xl:"p-10"},s=["[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" ");export function Overlay({open:c,defaultOpen:m,onOpenChange:p,tone:d="scrim",dismissible:b=!1,modal:f=!0,align:u="center",size:x="md",color:y="primary",locale:g,label:h,className:j,style:k,children:v,...O}){const _=n(g);return e(r.Root,{open:c,defaultOpen:m,modal:f,disablePointerDismissal:!b,onOpenChange:(e,a)=>{b||e||"escape-key"!==a.reason?p?.(e):a.cancel()},children:a(r.Portal,{children:[e(r.Backdrop,{className:`neba-portal fixed inset-0 z-50 ${s} ${t[d]}`}),e(r.Viewport,{className:["neba-portal fixed inset-0 z-50 flex justify-center",i[u],o[x]].join(" "),children:e(r.Popup,{"aria-label":h??_.overlay.label,className:["flex max-h-full max-w-full flex-col items-center justify-center","[outline:none]",s,j??""].filter(Boolean).join(" "),style:{...l(y,0),...k},...O,children:v})})]})})}
@@ -30,17 +30,39 @@ export interface PaginationProps extends NebaStyleProps, Omit<React.ComponentPro
30
30
  elevation?: NebaElevation;
31
31
  /** Unavailable. Every button in the row stops answering. */
32
32
  disabled?: boolean;
33
- /** Accessible name of the `<nav>`. @default 'Pagination' */
33
+ /**
34
+ * The address of a page, which turns every number in the row into a real
35
+ * link.
36
+ *
37
+ * Without it the row is buttons, and a crawler cannot press one — so a paged
38
+ * list of articles, products or search results exists for a reader and stops
39
+ * at page one for everything else. With it the numbers are `<a href>`, the
40
+ * two arrows carry `rel="prev"` / `rel="next"`, and the browser's own
41
+ * behaviour comes back: open in a new tab, copy the address, see where a
42
+ * press is going before making it.
43
+ *
44
+ * `onPageChange` still fires and the press is still cancelled first, so a
45
+ * client-side router keeps the page it already has. A link with nowhere to go
46
+ * — the current page, a stepper at the end of the row — stays a `<button>`,
47
+ * because `disabled` is not something an `<a>` can be.
48
+ */
49
+ getPageHref?: (page: number) => string;
50
+ /**
51
+ * Which language the row names itself in — a BCP 47 tag such as `ko`, `pt-BR`
52
+ * or `zh-Hant`. Unsupported tags fall back to English.
53
+ *
54
+ * Every string below writes one of these out instead; this is for the far more
55
+ * common case where the page already knows its own language. Nothing here is
56
+ * ever drawn, so without it a Korean page reads its pages out in English.
57
+ */
58
+ locale?: string;
59
+ /** Accessible name of the `<nav>`. Defaults to the `locale`'s word for it. */
34
60
  label?: string;
35
- /** Accessible name of a page button. @default `Page ${page}` */
61
+ /** Accessible name of a page button. Defaults to the `locale`'s wording. */
36
62
  pageLabel?: (page: number) => string;
37
- /** @default 'Previous page' */
38
63
  previousLabel?: string;
39
- /** @default 'Next page' */
40
64
  nextLabel?: string;
41
- /** @default 'First page' */
42
65
  firstLabel?: string;
43
- /** @default 'Last page' */
44
66
  lastLabel?: string;
45
67
  }
46
68
  /**
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Button as n}from"../button/Button";import{ChevronIcon as r}from"../../internal/icons";import{controlTextClasses as i,gapClasses as l,srOnlyClasses as o}from"../../internal/styles";function s(e,t){return Array.from({length:Math.max(0,t-e+1)},(t,a)=>e+a)}function m(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const c={xs:"h-5.5 min-w-5.5",sm:"h-6.5 min-w-6.5",md:"h-8 min-w-8",lg:"h-10 min-w-10",xl:"h-12 min-w-12"};export const Pagination=a.forwardRef(function({variant:d="text",size:u="md",color:h="primary",density:f="compact",elevation:p=0,count:x,page:g,defaultPage:b=1,onPageChange:v,siblingCount:M=1,boundaryCount:w=1,showEdges:N=!1,showArrows:y=!0,disabled:L=!1,label:j="Pagination",pageLabel:k=e=>`Page ${e}`,previousLabel:C="Previous page",nextLabel:P="Next page",firstLabel:$="First page",lastLabel:z="Last page",className:B,children:A,...E},F){const[I,R]=a.useState(b),S=Math.min(Math.max(g??I,1),Math.max(x,1)),W=e=>{const t=Math.min(Math.max(e,1),x);t!==S&&(void 0===g&&R(t),v?.(t))};if(x<2)return null;const q=function(e,t,a,n){const r=s(1,Math.min(n,e)),i=s(Math.max(e-n+1,n+1),e),l=Math.max(Math.min(t-a,e-n-2*a-1),n+2),o=Math.min(Math.max(t+a,n+2*a+2),i.length>0?i[0]-2:e-1);return[...r,...l>n+2?["start-ellipsis"]:n+1<e-n?[n+1]:[],...s(l,o),...o<e-n-1?["end-ellipsis"]:e-n>n?[e-n]:[],...i]}(x,S,M,w),D=S<=1,G=S>=x,H=(t,a,r,i,l,o)=>e("li",{className:"flex",children:e(n,{variant:d,size:u,color:h,density:f,elevation:p,disabled:L||i,"aria-label":a,startIcon:e("span",{className:`flex items-center ${l}`,children:o}),onClick:()=>W(r)})},t);return t("nav",{ref:F,"aria-label":j,className:["flex items-center",B??""].filter(Boolean).join(" "),...E,children:[t("ul",{role:"list",className:`m-0 flex list-none items-center p-0 ${l[u]}`,children:[N?H("first",$,1,D,"rotate-180 rtl:rotate-0",e(m,{})):null,y?H("previous",C,S-1,D,"rotate-90 rtl:-rotate-90",e(r,{})):null,q.map((t,a)=>e("li","number"==typeof t?{className:"flex",children:e(n,{variant:t===S?"solid":d,size:u,color:h,density:f,elevation:p,disabled:L,"aria-label":k(t),"aria-current":t===S?"page":void 0,className:"tabular-nums",onClick:()=>W(t),children:t})}:{"aria-hidden":"true",className:["flex select-none items-center justify-center","text-(--neba-muted-fg)",i[u],c[u]].join(" "),children:"…"},`slot-${a}`)),y?H("next",P,S+1,G,"-rotate-90 rtl:rotate-90",e(r,{})):null,N?H("last",z,x,G,"rtl:rotate-180",e(m,{})):null]}),e("span",{className:o,"aria-live":"polite",children:`${k(S)} of ${x}`}),A]})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Button as n}from"../button/Button";import{fillMessage as i,useMessages as r}from"../../internal/i18n";import{ChevronIcon as l}from"../../internal/icons";import{controlTextClasses as o,gapClasses as s,srOnlyClasses as m}from"../../internal/styles";function c(e,t){return Array.from({length:Math.max(0,t-e+1)},(t,a)=>e+a)}function u(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const d={xs:"h-5.5 min-w-5.5",sm:"h-6.5 min-w-6.5",md:"h-8 min-w-8",lg:"h-10 min-w-10",xl:"h-12 min-w-12"};export const Pagination=a.forwardRef(function({variant:h="text",size:p="md",color:f="primary",density:g="compact",elevation:x=0,count:b,page:v,defaultPage:y=1,onPageChange:M,siblingCount:w=1,boundaryCount:N=1,showEdges:j=!1,showArrows:L=!0,disabled:k=!1,getPageHref:C,locale:K,label:P,pageLabel:S,previousLabel:z,nextLabel:B,firstLabel:$,lastLabel:A,className:D,children:E,...H},I){const R=r(K),W=S??(e=>i(R.pagination.page,{page:String(e)})),[q,F]=a.useState(y),G=Math.min(Math.max(v??q,1),Math.max(b,1));if(b<2)return null;const J=function(e,t,a,n){const i=c(1,Math.min(n,e)),r=c(Math.max(e-n+1,n+1),e),l=Math.max(Math.min(t-a,e-n-2*a-1),n+2),o=Math.min(Math.max(t+a,n+2*a+2),r.length>0?r[0]-2:e-1);return[...i,...l>n+2?["start-ellipsis"]:n+1<e-n?[n+1]:[],...c(l,o),...o<e-n-1?["end-ellipsis"]:e-n>n?[e-n]:[],...r]}(b,G,w,N),O=G<=1,Q=G>=b,T=(t,a,n)=>C&&!a?{render:e("a",{href:C(t),rel:n})}:null,U=(e,t)=>{e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||C&&!M||(e.preventDefault(),(e=>{const t=Math.min(Math.max(e,1),b);t!==G&&(void 0===v&&F(t),M?.(t))})(t))},V=(t,a,i,r,l,o,s)=>e("li",{className:"flex",children:e(n,{variant:h,size:p,color:f,density:g,elevation:x,disabled:k||r,"aria-label":a,startIcon:e("span",{className:`flex items-center ${l}`,children:o}),onClick:e=>U(e,i),...T(i,k||r,s)})},t);return t("nav",{ref:I,"aria-label":P??R.pagination.label,className:["flex items-center",D??""].filter(Boolean).join(" "),...H,children:[t("ul",{role:"list",className:`m-0 flex list-none items-center p-0 ${s[p]}`,children:[j?V("first",$??R.pagination.first,1,O,"rotate-180 rtl:rotate-0",e(u,{})):null,L?V("previous",z??R.pagination.previous,G-1,O,"rotate-90 rtl:-rotate-90",e(l,{}),"prev"):null,J.map((t,a)=>e("li","number"==typeof t?{className:"flex",children:e(n,{variant:t===G?"solid":h,size:p,color:f,density:g,elevation:x,disabled:k,"aria-label":W(t),"aria-current":t===G?"page":void 0,className:"tabular-nums",onClick:e=>U(e,t),...T(t,k||t===G),children:t})}:{"aria-hidden":"true",className:["flex select-none items-center justify-center","text-(--neba-muted-fg)",o[p],d[p]].join(" "),children:"…"},`slot-${a}`)),L?V("next",B??R.pagination.next,G+1,Q,"-rotate-90 rtl:rotate-90",e(l,{}),"next"):null,j?V("last",A??R.pagination.last,b,Q,"rtl:rotate-180",e(u,{})):null]}),e("span",{className:m,"aria-live":"polite",children:i(R.pagination.status,{page:String(G),total:String(b)})}),E]})});
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{cx as r,transitionClasses as o}from"../../internal/styles";const i=n.createContext({basis:null}),a={xs:"basis-1",sm:"basis-1.5",md:"basis-2",lg:"basis-2.5",xl:"basis-3"},s={xs:4,sm:6,md:8,lg:10,xl:12};function l(e,t,n){if(null==e)return;if("number"==typeof e)return t*e/100;const r=/^\s*(-?[\d.]+)\s*(px|rem|em|%)\s*$/.exec(e);if(!r)return;const o=Number(r[1]);if(!Number.isNaN(o))switch(r[2]){case"px":return o;case"%":return t*o/100;case"rem":return o*parseFloat(getComputedStyle(document.documentElement).fontSize||"16");case"em":return o*parseFloat(n&&getComputedStyle(n).fontSize||"16");default:return}}export const Panes=n.forwardRef(function({orientation:c="horizontal",resizable:u=!0,color:d="primary",size:m="md",onResize:f,onResizeEnd:p,className:h,style:g,children:v,...x},b){const y=n.Children.toArray(v).filter(n.isValidElement),z=y.length,w=n.useRef(null),S=n.useCallback(e=>{w.current=e,"function"==typeof b?b(e):b&&(b.current=e)},[b]),R=n.useRef([]);R.current=y.map(e=>e.props);const[C,E]=n.useState(null),N=C&&C.length===z?C:null,M=n.useRef(null);M.current=N;const L="horizontal"===c,$=s[m]*Math.max(0,z-1);function k(e){const t=w.current,n=M.current;if(!u||!t||!n||void 0===n[e+1])return null;const r=t.getBoundingClientRect(),o=(L?r.width:r.height)-$;if(o<=0)return null;const i=R.current[e],a=R.current[e+1],s=n[e]*o,c=s+n[e+1]*o,d=Math.max(l(i?.minSize,o,t)??0,c-(l(a?.maxSize,o,t)??c)),m=Math.min(l(i?.maxSize,o,t)??c,c-(l(a?.minSize,o,t)??0));return m<d?null:{root:t,current:n,extent:o,start:s,pair:c,resize(t){const r=Math.min(m,Math.max(d,s+t)),i=[...n];return i[e]=r/o,i[e+1]=(c-r)/o,E(i),f?.(i.map(e=>100*e)),i}}}n.useEffect(()=>{const e=w.current;if(!e)return;const t=()=>{const t=e.getBoundingClientRect(),n=(L?t.width:t.height)-$;n<=0||E(t=>t&&t.length===z?t:function(e,t,n){const r=e.map(e=>l(e.defaultSize,t,n)),o=r.reduce((e,t)=>e+(t??0),0),i=r.filter(e=>void 0===e).length,a=i>0?Math.max(0,t-o)/i:0,s=r.map(e=>Math.max(0,e??a)),c=s.reduce((e,t)=>e+t,0);return c<=0?s.map(()=>1/Math.max(1,s.length)):s.map(e=>e/c)}(R.current,n,e))};t();const n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[z,L,$]);const A=r("group/handle relative z-1 flex shrink-0 grow-0 items-center justify-center",a[m],o,"[outline:none] focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-0",u?r(L?"cursor-col-resize":"cursor-row-resize","hover:bg-(--n-soft) data-[dragging]:bg-(--n-soft)"):"");return e("div",{ref:S,className:r("flex h-full w-full",L?"flex-row":"flex-col","min-h-0 min-w-0",h),style:{"--n-accent":`var(--neba-${d}-accent)`,"--n-soft":`var(--neba-${d}-soft)`,"--n-ring":`var(--neba-${d}-ring)`,...g},...x,children:y.map((a,s)=>t(n.Fragment,{children:[s>0?e("div",{role:"separator","aria-orientation":L?"vertical":"horizontal","aria-valuenow":N?Math.round(100*N[s-1]):void 0,"aria-valuemin":0,"aria-valuemax":100,"aria-disabled":!u||void 0,tabIndex:u?0:-1,className:A,onPointerDown:e=>{0===e.button&&function(e,t){const n=k(e);if(!n)return;const r=t.currentTarget;r.setPointerCapture(t.pointerId),r.dataset.dragging="true";const o=document.body.style.userSelect;document.body.style.userSelect="none";const i=L?t.clientX:t.clientY,a=L&&"rtl"===getComputedStyle(n.root).direction?-1:1;let s=n.current;const l=e=>{const t=L?e.clientX:e.clientY;s=n.resize((t-i)*a)},c=()=>{r.removeEventListener("pointermove",l),r.removeEventListener("pointerup",c),r.removeEventListener("pointercancel",c),delete r.dataset.dragging,document.body.style.userSelect=o,p?.(s.map(e=>100*e))};r.addEventListener("pointermove",l),r.addEventListener("pointerup",c),r.addEventListener("pointercancel",c)}(s-1,e)},onKeyDown:e=>{const t=L?"ArrowLeft":"ArrowUp",n=L?"ArrowRight":"ArrowDown";e.key!==t&&e.key!==n||(e.preventDefault(),function(e,t){const n=k(e);if(!n)return;const r=n.resize(t);p?.(r.map(e=>100*e))}(s-1,e.key===n?16:-16))},children:e("span",{"aria-hidden":"true",className:r("pointer-events-none bg-(--neba-border)",o,L?"h-full w-px":"h-px w-full",u?"group-hover/handle:bg-(--n-accent) group-focus-visible/handle:bg-(--n-accent) group-data-[dragging]/handle:bg-(--n-accent)":"")})}):null,e(i.Provider,{value:{basis:N?`calc((100% - ${$}px) * ${N[s].toFixed(6)})`:null},children:a})]},a.key??s))})});export const Pane=n.forwardRef(function({defaultSize:t,minSize:o,maxSize:a,className:s,style:l,children:c,...u},d){const{basis:m}=n.useContext(i);return e("div",{ref:d,className:r("relative min-h-0 min-w-0 overflow-auto",s),style:{flex:m?`0 0 ${m}`:"1 1 0%",...l},...u,children:c})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{cx as r,transitionClasses as o}from"../../internal/styles";const i=n.createContext({basis:null}),s={xs:"basis-1",sm:"basis-1.5",md:"basis-2",lg:"basis-2.5",xl:"basis-3"},a={xs:4,sm:6,md:8,lg:10,xl:12};function l(e,t,n){if(null==e)return;if("number"==typeof e)return t*e/100;const r=/^\s*(-?[\d.]+)\s*(px|rem|em|%)\s*$/.exec(e);if(!r)return;const o=Number(r[1]);if(!Number.isNaN(o))switch(r[2]){case"px":return o;case"%":return t*o/100;case"rem":return o*parseFloat(getComputedStyle(document.documentElement).fontSize||"16");case"em":return o*parseFloat(n&&getComputedStyle(n).fontSize||"16");default:return}}export const Panes=n.forwardRef(function({orientation:c="horizontal",resizable:u=!0,color:d="primary",size:m="md",onResize:f,onResizeEnd:p,className:g,style:h,children:v,...b},x){const y=n.Children.toArray(v).filter(n.isValidElement),w=y.length,z=n.useRef(null),S=n.useCallback(e=>{z.current=e,"function"==typeof x?x(e):x&&(x.current=e)},[x]),R=n.useRef([]);R.current=y.map(e=>e.props);const[E,k]=n.useState(null),C=E&&E.length===w?E:null,N=n.useRef(null);N.current=C;const M="horizontal"===c,P=a[m]*Math.max(0,w-1);function L(e){const t=z.current,n=N.current;if(!u||!t||!n||void 0===n[e+1])return null;const r=t.getBoundingClientRect(),o=(M?r.width:r.height)-P;if(o<=0)return null;const i=R.current[e],s=R.current[e+1],a=n[e]*o,c=a+n[e+1]*o,d=Math.max(l(i?.minSize,o,t)??0,c-(l(s?.maxSize,o,t)??c)),m=Math.min(l(i?.maxSize,o,t)??c,c-(l(s?.minSize,o,t)??0));return m<d?null:{root:t,current:n,extent:o,start:a,pair:c,resize(t){const r=Math.min(m,Math.max(d,a+t)),i=[...n];return i[e]=r/o,i[e+1]=(c-r)/o,k(i),f?.(i.map(e=>100*e)),i}}}n.useEffect(()=>{const e=z.current;if(!e)return;const t=()=>{const t=e.getBoundingClientRect(),n=(M?t.width:t.height)-P;n<=0||k(t=>t&&t.length===w?t:function(e,t,n){const r=e.map(e=>l(e.defaultSize,t,n)),o=r.reduce((e,t)=>e+(t??0),0),i=r.filter(e=>void 0===e).length,s=i>0?Math.max(0,t-o)/i:0,a=r.map(e=>Math.max(0,e??s)),c=a.reduce((e,t)=>e+t,0);return c<=0?a.map(()=>1/Math.max(1,a.length)):a.map(e=>e/c)}(R.current,n,e))};t();const n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[w,M,P]);const $=n.useRef(null);n.useEffect(()=>()=>$.current?.(),[]);const A=r("group/handle relative z-1 flex shrink-0 grow-0 items-center justify-center",s[m],o,"[outline:none] focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-0",u?r(M?"cursor-col-resize":"cursor-row-resize","hover:bg-(--n-soft) data-[dragging]:bg-(--n-soft)"):"");return e("div",{ref:S,className:r("flex h-full w-full",M?"flex-row":"flex-col","min-h-0 min-w-0",g),style:{"--n-accent":`var(--neba-${d}-accent)`,"--n-soft":`var(--neba-${d}-soft)`,"--n-ring":`var(--neba-${d}-ring)`,...h},...b,children:y.map((s,a)=>t(n.Fragment,{children:[a>0?e("div",{role:"separator","aria-orientation":M?"vertical":"horizontal","aria-valuenow":C?Math.round(100*C[a-1]):void 0,"aria-valuemin":0,"aria-valuemax":100,"aria-disabled":!u||void 0,tabIndex:u?0:-1,className:A,onPointerDown:e=>{0===e.button&&function(e,t){const n=L(e);if(!n)return;const r=t.currentTarget;r.setPointerCapture(t.pointerId),r.dataset.dragging="true";const o=document.body.style.getPropertyValue("-webkit-user-select");document.body.style.setProperty("-webkit-user-select","none");const i=M?t.clientX:t.clientY,s=M&&"rtl"===getComputedStyle(n.root).direction?-1:1;let a=n.current;const l=e=>{const t=M?e.clientX:e.clientY;a=n.resize((t-i)*s)},c=()=>{$.current=null,r.removeEventListener("pointermove",l),r.removeEventListener("pointerup",u),r.removeEventListener("pointercancel",u),delete r.dataset.dragging,o?document.body.style.setProperty("-webkit-user-select",o):document.body.style.removeProperty("-webkit-user-select")},u=()=>{c(),p?.(a.map(e=>100*e))};$.current=c,r.addEventListener("pointermove",l),r.addEventListener("pointerup",u),r.addEventListener("pointercancel",u)}(a-1,e)},onKeyDown:e=>{const t=M?"ArrowLeft":"ArrowUp",n=M?"ArrowRight":"ArrowDown";e.key!==t&&e.key!==n||(e.preventDefault(),function(e,t){const n=L(e);if(!n)return;const r=n.resize(t);p?.(r.map(e=>100*e))}(a-1,e.key===n?16:-16))},children:e("span",{"aria-hidden":"true",className:r("pointer-events-none bg-(--neba-border)",o,M?"h-full w-px":"h-px w-full",u?"group-hover/handle:bg-(--n-accent) group-focus-visible/handle:bg-(--n-accent) group-data-[dragging]/handle:bg-(--n-accent)":"")})}):null,e(i.Provider,{value:{basis:C?`calc((100% - ${P}px) * ${C[a].toFixed(6)})`:null},children:s})]},s.key??a))})});export const Pane=n.forwardRef(function({defaultSize:t,minSize:o,maxSize:s,className:a,style:l,children:c,...u},d){const{basis:m}=n.useContext(i);return e("div",{ref:d,className:r("relative min-h-0 min-w-0 overflow-auto",a),style:{flex:m?`0 0 ${m}`:"1 1 0%",...l},...u,children:c})});
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+ import { type ChartBaseProps } from '../../internal/chart-frame';
3
+ import type { NebaChartCategory, NebaChartDatum } from '../../types';
4
+ export interface PieChartProps extends ChartBaseProps {
5
+ /**
6
+ * The slices. Numbers, or points that carry their own name and colour.
7
+ *
8
+ * One series and not an array of them, because that is what a pie *is*: the
9
+ * slices are the entities here, so each one takes a palette slot of its own
10
+ * and the legend lists them rather than listing series.
11
+ */
12
+ data: readonly NebaChartDatum[];
13
+ /** What each slice is called. Points may carry their own `x` instead. */
14
+ categories?: readonly NebaChartCategory[];
15
+ /**
16
+ * - `pie` — a filled disc. The default.
17
+ * - `donut` — a ring, with room in the middle for the total.
18
+ * - `semi` — half a ring, opened along the bottom. For a gauge, or for a
19
+ * dashboard tile that is wider than it is tall.
20
+ * @default 'pie'
21
+ */
22
+ shape?: 'pie' | 'donut' | 'semi';
23
+ /**
24
+ * Where the first slice starts, in degrees clockwise from twelve o'clock.
25
+ * Ignored by `semi`, which is defined by where it opens.
26
+ * @default 0
27
+ */
28
+ startAngle?: number;
29
+ /**
30
+ * What goes in the hole. A `donut` or a `semi` with nothing in the middle is
31
+ * a pie with a bite out of it; the total, or the one figure the chart is
32
+ * about, is what the ring was drawn around.
33
+ */
34
+ center?: React.ReactNode;
35
+ /**
36
+ * Writes each slice's share on it, where the slice is wide enough for the
37
+ * text to fit with room either side. A label that does not fit is dropped
38
+ * rather than clipped — the tooltip and the table still have it.
39
+ *
40
+ * The number written is the **share**, not the value: a share is what a pie
41
+ * is a picture of, and the value is one hover away.
42
+ * @default 'none'
43
+ */
44
+ valueLabels?: 'none' | 'all';
45
+ }
46
+ /**
47
+ * Parts of a whole, at a glance.
48
+ *
49
+ * The narrowest chart in the library and the easiest one to misuse. An angle is
50
+ * a poor thing to compare — two slices within a few percent of each other are
51
+ * indistinguishable, and a reader cannot rank six of them — so the pie is right
52
+ * for exactly one question: *is one of these most of it?* Anything finer than
53
+ * that, and anything past six slices, is a [BarChart](./bar-chart).
54
+ *
55
+ * A slice's colour follows the slice and not its size, so a chart that is
56
+ * refiltered or resorted keeps every category the colour it had.
57
+ */
58
+ export declare function PieChart({ data, categories, shape, startAngle, center, valueLabels, height, format, locale, label, legend, tooltip, empty, size, variant, padded, className, ...box }: PieChartProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{ChartDataTable as n,ChartLegendBar as l,ChartSurface as i,ChartTooltipPanel as r,useMeasuredWidth as o,useVisibility as s}from"../../internal/chart-frame";import{arcPath as d,categoryAt as u,chartFontSizes as m,compactNumber as c,formatCategory as h,markGap as v,plotHeights as f,seriesColor as p,toValue as x}from"../../internal/chart";import{numberFormatter as b}from"../../internal/format";import{cx as g,metaTextClasses as y}from"../../internal/styles";import{useMessages as M}from"../../internal/i18n";const N={pie:0,donut:.62,semi:.62};export function PieChart({data:w,categories:I,shape:P="pie",startAngle:z=0,center:j,valueLabels:k="none",height:A,format:$,locale:L,label:S,legend:_,tooltip:B,empty:E,size:R="md",variant:C="text",padded:D=!1,className:O,...K}){const V=a.useRef(null),W=o(V),q=M(L),F=a.useId(),G=a.useCallback(e=>$?b(L,$).format(e):c(e,L),[$,L]),H=a.useMemo(()=>w.map(x),[w]),J=a.useMemo(()=>H.map((e,t)=>({name:h(u(t,I,[H]),L),data:[w[t]],color:e.color})),[H,I,w,L]),Q=s(J),[T,U]=a.useState(null),X=J.map((e,t)=>p(e,t)),Y=H.reduce((e,t,a)=>Q.visible[a]&&null!==t.value?e+Math.abs(t.value):e,0),Z="semi"===P,ee="number"==typeof A?A:f[R],te=m[R],ae=!1===_?{interactive:!1}:!0===_||void 0===_?{}:_,ne=!1!==_&&J.length>1,le=ae.side??"bottom",ie=!1===B?{mode:"none"}:!0===B||void 0===B?{}:B,re="none"===ie.mode,oe=W/2,se=Math.max(0,Math.min(W/2,Z?ee:ee/2)-2),de=Z?Math.min(ee,ee/2+se/2):ee/2,ue=se*N[P],me=Y<=0||se<=0,ce=se>0?Math.min(4,v/se*(180/Math.PI)):0,he=Z?180:360,ve=[];let fe=Z?-90:z;H.forEach((e,t)=>{if(!Q.visible[t]||null===e.value||0===e.value)return;const a=Math.abs(e.value)/Y,n=a*he;ve.push({index:t,start:fe,end:fe+n,value:e.value,share:a}),fe+=n});const pe=null===T?[]:[{seriesIndex:T,name:J[T]?.name,color:H[T]?.color??X[T],value:H[T]?.value??null,formatted:`${G(H[T]?.value??0)} · ${Math.round(10*(Math.abs(H[T]?.value??0)/Y*100+Number.EPSILON))/10}%`,label:H[T]?.label}];return e(i,{...K,size:R,variant:C,padded:D,className:O,legendSide:le,legend:ne?e(l,{series:J,colors:X,options:ae,visibility:Q,size:R,values:ae.showValue?H.map(e=>null===e.value?void 0:G(e.value)):void 0}):null,table:me?null:e(n,{id:F,caption:S,categories:J.map(e=>e.name??""),series:[{name:S,data:w}],values:[H],format:G,locale:L}),children:t("div",{ref:V,role:"img",tabIndex:me?void 0:0,"aria-label":S,"aria-describedby":me?void 0:F,onPointerLeave:()=>U(null),onBlur:()=>U(null),onKeyDown:e=>{if("ArrowRight"!==e.key&&"ArrowLeft"!==e.key)return;const t=ve.map(e=>e.index);if(0===t.length)return;const a=null===T?-1:t.indexOf(T),n="ArrowRight"===e.key?a+1:a-1;U(t[(n+t.length)%t.length]),e.preventDefault()},className:g("relative w-full rounded-(--neba-radius-xs)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"),style:{height:ee},children:[me?e("div",{className:g("flex h-full items-center justify-center text-(--neba-muted-fg)",y[R]),children:E??q.empty.title}):W>0?t("svg",{width:W,height:ee,viewBox:`0 0 ${W} ${ee}`,"aria-hidden":"true",className:"block",children:[ve.map(t=>{const a=null!==Q.hovered&&Q.hovered!==t.index||null!==T&&T!==t.index,n=t.end-t.start>2*ce?ce/2:0;return e("path",{d:d(oe,de,se,ue,t.start+n,t.end-n),fill:H[t.index].color??X[t.index],opacity:a?.32:1,onPointerEnter:re?void 0:()=>U(t.index),className:"[transition:opacity_var(--neba-duration)_var(--neba-ease)]"},t.index)}),"all"===k?ve.map(t=>{const a=((t.start+t.end)/2-90)*(Math.PI/180),n=ue>0?(ue+se)/2:.68*se,l=`${Math.round(100*t.share)}%`;return(t.end-t.start)*(Math.PI/180)*n<2*te||se-ue<1.6*te?null:e("text",{x:oe+n*Math.cos(a),y:de+n*Math.sin(a),textAnchor:"middle",dominantBaseline:"central",fontSize:te,fontWeight:600,fill:"var(--neba-surface)",className:"tabular-nums",children:l},t.index)}):null]}):null,j&&ue>0?e("div",{className:"pointer-events-none absolute flex flex-col items-center justify-center text-center",style:{left:oe-ue,top:de-ue,width:2*ue,height:Z?ue:2*ue},children:j}):null,null===T||re?null:ie.render?e("div",{className:"pointer-events-none absolute top-0 left-1/2 z-10",children:ie.render({index:T,category:J[T]?.name??T,items:pe})}):e(r,{heading:J[T]?.name,items:pe,x:oe,y:8,flip:!1,size:R})]})})}
@@ -0,0 +1,2 @@
1
+ export { PieChart } from './PieChart';
2
+ export type { PieChartProps } from './PieChart';
@@ -0,0 +1 @@
1
+ export{PieChart}from"./PieChart";