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.
- package/README.md +7 -5
- package/dist/components/alert/Alert.d.ts +9 -1
- package/dist/components/alert/Alert.js +1 -1
- package/dist/components/area-chart/AreaChart.d.ts +54 -0
- package/dist/components/area-chart/AreaChart.js +1 -0
- package/dist/components/area-chart/index.d.ts +2 -0
- package/dist/components/area-chart/index.js +1 -0
- package/dist/components/bar-chart/BarChart.d.ts +63 -0
- package/dist/components/bar-chart/BarChart.js +1 -0
- package/dist/components/bar-chart/index.d.ts +2 -0
- package/dist/components/bar-chart/index.js +1 -0
- package/dist/components/bottom-navigation/BottomNavigation.d.ts +99 -0
- package/dist/components/bottom-navigation/BottomNavigation.js +1 -0
- package/dist/components/bottom-navigation/index.d.ts +1 -0
- package/dist/components/bottom-navigation/index.js +1 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts +35 -2
- package/dist/components/breadcrumb/Breadcrumb.js +1 -1
- package/dist/components/button/Button.d.ts +16 -0
- package/dist/components/button/Button.js +1 -1
- package/dist/components/carousel/Carousel.d.ts +10 -4
- package/dist/components/carousel/Carousel.js +1 -1
- package/dist/components/chip/Chip.d.ts +9 -1
- package/dist/components/chip/Chip.js +1 -1
- package/dist/components/collapsible/Collapsible.d.ts +88 -0
- package/dist/components/collapsible/Collapsible.js +1 -0
- package/dist/components/collapsible/index.d.ts +1 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/combobox/Combobox.d.ts +19 -7
- package/dist/components/combobox/Combobox.js +1 -1
- package/dist/components/dialog/Dialog.d.ts +11 -5
- package/dist/components/dialog/Dialog.js +1 -1
- package/dist/components/drawer/Drawer.d.ts +11 -5
- package/dist/components/drawer/Drawer.js +1 -1
- package/dist/components/file-picker/FilePicker.d.ts +1 -3
- package/dist/components/file-picker/FilePicker.js +1 -1
- package/dist/components/floating-action-button/FloatingActionButton.d.ts +146 -0
- package/dist/components/floating-action-button/FloatingActionButton.js +1 -0
- package/dist/components/floating-action-button/index.d.ts +1 -0
- package/dist/components/floating-action-button/index.js +1 -0
- package/dist/components/floating-bottom-navigation/FloatingBottomNavigation.d.ts +91 -0
- package/dist/components/floating-bottom-navigation/FloatingBottomNavigation.js +1 -0
- package/dist/components/floating-bottom-navigation/index.d.ts +2 -0
- package/dist/components/floating-bottom-navigation/index.js +1 -0
- package/dist/components/heatmap-chart/HeatmapChart.d.ts +69 -0
- package/dist/components/heatmap-chart/HeatmapChart.js +1 -0
- package/dist/components/heatmap-chart/index.d.ts +2 -0
- package/dist/components/heatmap-chart/index.js +1 -0
- package/dist/components/highlight/Highlight.js +1 -1
- package/dist/components/line-chart/LineChart.d.ts +74 -0
- package/dist/components/line-chart/LineChart.js +1 -0
- package/dist/components/line-chart/index.d.ts +2 -0
- package/dist/components/line-chart/index.js +1 -0
- package/dist/components/number-field/NumberField.d.ts +10 -6
- package/dist/components/number-field/NumberField.js +1 -1
- package/dist/components/overlay/Overlay.d.ts +11 -6
- package/dist/components/overlay/Overlay.js +1 -1
- package/dist/components/pagination/Pagination.d.ts +28 -6
- package/dist/components/pagination/Pagination.js +1 -1
- package/dist/components/panes/Panes.js +1 -1
- package/dist/components/pie-chart/PieChart.d.ts +58 -0
- package/dist/components/pie-chart/PieChart.js +1 -0
- package/dist/components/pie-chart/index.d.ts +2 -0
- package/dist/components/pie-chart/index.js +1 -0
- package/dist/components/popover/Popover.d.ts +11 -5
- package/dist/components/popover/Popover.js +1 -1
- package/dist/components/progress-box/ProgressBox.js +1 -1
- package/dist/components/progress-circular/ProgressCircular.js +1 -1
- package/dist/components/progress-linear/ProgressLinear.js +1 -1
- package/dist/components/rating/Rating.d.ts +100 -0
- package/dist/components/rating/Rating.js +1 -0
- package/dist/components/rating/index.d.ts +1 -0
- package/dist/components/rating/index.js +1 -0
- package/dist/components/scatter-chart/ScatterChart.d.ts +45 -0
- package/dist/components/scatter-chart/ScatterChart.js +1 -0
- package/dist/components/scatter-chart/index.d.ts +2 -0
- package/dist/components/scatter-chart/index.js +1 -0
- package/dist/components/scroll-zone/ScrollZone.d.ts +126 -0
- package/dist/components/scroll-zone/ScrollZone.js +1 -0
- package/dist/components/scroll-zone/index.d.ts +2 -0
- package/dist/components/scroll-zone/index.js +1 -0
- package/dist/components/select/Select.d.ts +1 -3
- package/dist/components/select/Select.js +1 -1
- package/dist/components/sparkline/Sparkline.d.ts +67 -0
- package/dist/components/sparkline/Sparkline.js +1 -0
- package/dist/components/sparkline/index.d.ts +2 -0
- package/dist/components/sparkline/index.js +1 -0
- package/dist/components/statistic/Statistic.d.ts +7 -0
- package/dist/components/statistic/Statistic.js +1 -1
- package/dist/components/table/Table.d.ts +13 -2
- package/dist/components/table/Table.js +1 -1
- package/dist/components/text-link/TextLink.js +1 -1
- package/dist/components/time-picker/TimePicker.js +1 -1
- package/dist/components/timeline-chart/TimelineChart.d.ts +44 -0
- package/dist/components/timeline-chart/TimelineChart.js +1 -0
- package/dist/components/timeline-chart/index.d.ts +2 -0
- package/dist/components/timeline-chart/index.js +1 -0
- package/dist/components/toast/Toast.d.ts +10 -2
- package/dist/components/toast/Toast.js +1 -1
- package/dist/components/tooltip/Tooltip.d.ts +2 -4
- package/dist/components/tooltip/Tooltip.js +1 -1
- package/dist/components/tree-view/TreeView.js +1 -1
- package/dist/components/window-pane/WindowPane.d.ts +178 -0
- package/dist/components/window-pane/WindowPane.js +1 -0
- package/dist/components/window-pane/index.d.ts +2 -0
- package/dist/components/window-pane/index.js +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +1 -1
- package/dist/internal/animate.d.ts +0 -9
- package/dist/internal/animate.js +1 -1
- package/dist/internal/bottom-navigation.d.ts +57 -0
- package/dist/internal/bottom-navigation.js +1 -0
- package/dist/internal/calendar.js +1 -1
- package/dist/internal/chart-frame.d.ts +409 -0
- package/dist/internal/chart-frame.js +1 -0
- package/dist/internal/chart-line.d.ts +44 -0
- package/dist/internal/chart-line.js +1 -0
- package/dist/internal/chart.d.ts +456 -0
- package/dist/internal/chart.js +1 -0
- package/dist/internal/date.d.ts +0 -2
- package/dist/internal/date.js +1 -1
- package/dist/internal/format.d.ts +29 -0
- package/dist/internal/format.js +1 -0
- package/dist/internal/i18n.d.ts +143 -0
- package/dist/internal/i18n.js +1 -1
- package/dist/internal/icons.d.ts +2 -0
- package/dist/internal/icons.js +1 -1
- package/dist/internal/picker.d.ts +2 -4
- package/dist/internal/picker.js +1 -1
- package/dist/internal/progress.d.ts +1 -3
- package/dist/internal/window.d.ts +201 -0
- package/dist/internal/window.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +211 -0
- package/dist/types.d.ts +214 -0
- package/package.json +21 -17
|
@@ -10,7 +10,7 @@ import type { NebaAlign, NebaSide, NebaStyleProps } from '../../types';
|
|
|
10
10
|
* the page by definition, so it carries a shadow at level 3 and a prop that
|
|
11
11
|
* could sit it flat would be a prop that could stop it being a popover.
|
|
12
12
|
*/
|
|
13
|
-
export interface PopoverProps extends Pick<NebaStyleProps, 'size' | 'color' | 'density'> {
|
|
13
|
+
export interface PopoverProps extends Pick<NebaStyleProps, 'size' | 'color' | 'density'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title' | 'children'> {
|
|
14
14
|
/**
|
|
15
15
|
* The element the popup hangs off and that opens it. Exactly one element,
|
|
16
16
|
* which must accept a ref and spread props — every Neba component does.
|
|
@@ -69,7 +69,15 @@ export interface PopoverProps extends Pick<NebaStyleProps, 'size' | 'color' | 'd
|
|
|
69
69
|
dismissible?: boolean;
|
|
70
70
|
/** Shows the × in the corner. @default false */
|
|
71
71
|
showClose?: boolean;
|
|
72
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Which language the × 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` writes the word 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 the × button. Defaults to the `locale`'s word for it. */
|
|
73
81
|
closeLabel?: string;
|
|
74
82
|
/**
|
|
75
83
|
* A hard cap on the popup's width, overriding the one `size` implies. Numbers
|
|
@@ -77,8 +85,6 @@ export interface PopoverProps extends Pick<NebaStyleProps, 'size' | 'color' | 'd
|
|
|
77
85
|
* single line of help — rather than for tuning the scale, which is `size`.
|
|
78
86
|
*/
|
|
79
87
|
width?: number | string;
|
|
80
|
-
className?: string;
|
|
81
|
-
style?: React.CSSProperties;
|
|
82
88
|
}
|
|
83
89
|
export type PopoverCloseProps = React.ComponentPropsWithoutRef<typeof BaseUIPopover.Close>;
|
|
84
90
|
/**
|
|
@@ -106,4 +112,4 @@ export declare const PopoverClose: React.ForwardRefExoticComponent<Omit<import("
|
|
|
106
112
|
* the `aria-labelledby` / `aria-describedby` wiring. What is left here is the
|
|
107
113
|
* surface, the width ladder and the header.
|
|
108
114
|
*/
|
|
109
|
-
export declare function Popover({ size, color, density, trigger, title, description, children, side, align, sideOffset, alignOffset, arrow, open, defaultOpen, onOpenChange, modal, dismissible, showClose, closeLabel, width, className, style }: PopoverProps): React.JSX.Element;
|
|
115
|
+
export declare function Popover({ size, color, density, trigger, title, description, children, side, align, sideOffset, alignOffset, arrow, open, defaultOpen, onOpenChange, modal, dismissible, showClose, locale, closeLabel, width, className, style, ...props }: PopoverProps): React.JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Popover as o}from"@base-ui/react/popover";import{boxPaddingXClasses as t,boxPaddingYClasses as n}from"../box/Box";import{CloseIcon as s}from"../../internal/icons";import{hasContent as
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Popover as o}from"@base-ui/react/popover";import{boxPaddingXClasses as t,boxPaddingYClasses as n}from"../box/Box";import{useMessages as i}from"../../internal/i18n";import{CloseIcon as s}from"../../internal/icons";import{hasContent as l,metaTextClasses as r,radiusClasses as d,sheetBodyClasses as c,sheetHeaderGapClasses as m,sheetSectionGapClasses as p,sheetTitleClasses as f,surfaceClasses as u,surfaceSlots as h}from"../../internal/styles";const x={xs:"max-w-56",sm:"max-w-64",md:"max-w-80",lg:"max-w-96",xl:"max-w-lg"},b=[u,"relative flex flex-col","border text-(--neba-fg) bg-(--n-panel-press)","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]","[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),g={xs:8,sm:9,md:10,lg:11,xl:12};export const PopoverClose=o.Close;export function Popover({size:u="md",color:v="primary",density:w="default",trigger:y,title:N,description:_,children:k,side:j="bottom",align:O="center",sideOffset:C=6,alignOffset:P=0,arrow:z=!1,open:$,defaultOpen:B,onOpenChange:L,modal:M=!1,dismissible:T=!0,showClose:W=!1,locale:A,closeLabel:D,width:E,className:R,style:q,...F}){const G=i(A),H=t[w][u],I=n[w][u],J=g[u],K=l(N)||l(_);return a(o.Root,{open:$,defaultOpen:B,modal:M,onOpenChange:(e,a)=>{T||e||"escape-key"!==a.reason&&"outside-press"!==a.reason&&"focus-out"!==a.reason?L?.(e):a.cancel()},children:[y?e(o.Trigger,{render:y}):null,e(o.Portal,{children:e(o.Positioner,{className:"neba-portal z-50 [outline:none]",side:j,align:O,sideOffset:C,alignOffset:P,children:a(o.Popup,{className:[b,d[u],c[u],p[u],H,I,void 0===E?x[u]:"",R??""].filter(Boolean).join(" "),style:{...h(v,3),...void 0===E?null:{maxWidth:"number"==typeof E?`${E}px`:E},...q},...F,children:[z?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:a("svg",{width:J,height:J/2,viewBox:"0 0 10 5","aria-hidden":"true",className:"block",children:[e("path",{d:"M0 0h10L5 5z",fill:"var(--n-panel-press)"}),e("path",{d:"M0 0 5 5 10 0",fill:"none",stroke:"var(--n-line)",strokeWidth:"1",vectorEffect:"non-scaling-stroke"})]})}):null,K||W?a("div",{className:"flex shrink-0 items-start gap-3",children:[a("div",{className:`flex min-w-0 flex-1 flex-col ${m[u]}`,children:[l(N)?e(o.Title,{className:`m-0 font-semibold ${f[u]}`,children:N}):null,l(_)?e(o.Description,{className:`m-0 text-(--neba-muted-fg) ${r[u]}`,children:_}):null]}),W?e(o.Close,{"aria-label":D??G.action.close,className:["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--neba-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--neba-duration)_var(--neba-ease),color_var(--neba-duration)_var(--neba-ease)]","hover:bg-(--n-soft) hover:text-(--neba-fg)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),children:e(s,{})}):null]}):null,l(k)?e("div",{className:"min-w-0",children:k}):null]})})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Progress as t}from"@base-ui/react/progress";import{plateGapClasses as n,plateRadiusClasses as r,plateSizeClasses as s,progressAriaText as i,progressFraction as o,progressSlots as m,progressText as f}from"../../internal/progress";import{metaTextClasses as c,stackGapClasses as u}from"../../internal/styles";export const ProgressBox=l.forwardRef(function({size:l="md",color:d="primary",count:h=4,value:x=null,min:b=0,max:p=100,label:g,showValue:v=!1,format:y,className:w,style:j},
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Progress as t}from"@base-ui/react/progress";import{plateGapClasses as n,plateRadiusClasses as r,plateSizeClasses as s,progressAriaText as i,progressFraction as o,progressSlots as m,progressText as f}from"../../internal/progress";import{metaTextClasses as c,stackGapClasses as u}from"../../internal/styles";export const ProgressBox=l.forwardRef(function({size:l="md",color:d="primary",count:h=4,value:x=null,min:b=0,max:p=100,label:g,showValue:v=!1,format:y,className:w,style:j,...N},M){const B=o(x,b,p),V=null===B,k=void 0!==y,A=Math.max(1,Math.floor(h));return a(t.Root,{ref:M,value:x??null,min:b,max:p,format:y,getAriaValueText:i(B,k),className:["inline-flex flex-col",u[l],w??""].filter(Boolean).join(" "),style:{...m(d),...j},...N,children:[g||v?a("div",{className:["flex items-baseline gap-2",g?"justify-between":"justify-end",c[l]].join(" "),children:[g?e(t.Label,{className:"min-w-0 truncate text-(--neba-fg)",children:g}):null,v?e(t.Value,{className:"shrink-0 tabular-nums text-(--neba-muted-fg)",children:e=>f(B,e,k)}):null]}):null,e(t.Track,{className:`flex ${n[l]}`,children:Array.from({length:A},(a,t)=>e("span",{className:["relative overflow-hidden bg-(--n-soft)","[box-shadow:var(--neba-plate-glass)]",s[l],r[l],V?"neba-plate-wave":""].filter(Boolean).join(" "),style:V?{"--n-i":t}:void 0,children:V?null:e("span",{className:"absolute inset-y-0 start-0 bg-(--n-fill) [transition:width_var(--neba-duration-fill)_var(--neba-ease)]",style:{width:`${Math.min(100,Math.max(0,100*(B*A-t)))}%`}})},t))})]})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{Progress as t}from"@base-ui/react/progress";import{progressAriaText as s,progressFraction as n,progressSlots as i,progressText as o,ringDiameters as l,ringStrokes as c}from"../../internal/progress";import{gapClasses as m,metaTextClasses as f}from"../../internal/styles";export const ProgressCircular=a.forwardRef(function({size:a="md",color:u="primary",value:h=null,min:d=0,max:x=100,label:k,showValue:p=!1,format:b,className:g,style:v}
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{Progress as t}from"@base-ui/react/progress";import{progressAriaText as s,progressFraction as n,progressSlots as i,progressText as o,ringDiameters as l,ringStrokes as c}from"../../internal/progress";import{gapClasses as m,metaTextClasses as f}from"../../internal/styles";export const ProgressCircular=a.forwardRef(function({size:a="md",color:u="primary",value:h=null,min:d=0,max:x=100,label:k,showValue:p=!1,format:b,className:g,style:v,...y},$){const N=n(h,d,x),w=null===N,j=void 0!==b,V=l[a],B=c[a],D=V/2,L=D-B/2,P=2*Math.PI*L,R=w?`${.28*P} ${P}`:`${P}`,W=w?0:P*(1-N);return r(t.Root,{ref:$,value:h??null,min:d,max:x,format:b,getAriaValueText:s(N,j),className:["inline-flex items-center",m[a],f[a],g??""].filter(Boolean).join(" "),style:{...i(u),...v},...y,children:[r("svg",{className:w?"neba-ring-spin shrink-0":"shrink-0",width:V,height:V,viewBox:`0 0 ${V} ${V}`,fill:"none","aria-hidden":"true",children:[e("circle",{cx:D,cy:D,r:L,stroke:"var(--n-soft)",strokeWidth:B}),e("circle",{cx:D,cy:D,r:L,stroke:"var(--n-accent)",strokeWidth:B,strokeLinecap:"round",strokeDasharray:R,strokeDashoffset:W,transform:`rotate(-90 ${D} ${D})`,className:"[transition:stroke-dashoffset_var(--neba-duration-fill)_var(--neba-ease)]"})]}),k?e(t.Label,{className:"min-w-0 truncate text-(--neba-fg)",children:k}):null,p?e(t.Value,{className:"shrink-0 tabular-nums text-(--neba-muted-fg)",children:e=>o(N,e,j)}):null]})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{Progress as r}from"@base-ui/react/progress";import{barThicknessClasses as n,progressAriaText as s,progressFraction as t,progressSlots as i,progressText as o}from"../../internal/progress";import{metaTextClasses as m,stackGapClasses as u}from"../../internal/styles";export const ProgressLinear=a.forwardRef(function({size:a="md",color:f="primary",value:c=null,min:d=0,max:b=100,label:p,showValue:x=!1,format:g,className:h,style:w},
|
|
1
|
+
import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{Progress as r}from"@base-ui/react/progress";import{barThicknessClasses as n,progressAriaText as s,progressFraction as t,progressSlots as i,progressText as o}from"../../internal/progress";import{metaTextClasses as m,stackGapClasses as u}from"../../internal/styles";export const ProgressLinear=a.forwardRef(function({size:a="md",color:f="primary",value:c=null,min:d=0,max:b=100,label:p,showValue:x=!1,format:g,className:h,style:w,...j},v){const N=t(c,d,b),y=null===N,V=void 0!==g;return l(r.Root,{ref:v,value:c??null,min:d,max:b,format:g,getAriaValueText:s(N,V),className:["flex w-full flex-col",u[a],h??""].filter(Boolean).join(" "),style:{...i(f),...w},...j,children:[p||x?l("div",{className:["flex items-baseline gap-2",p?"justify-between":"justify-end",m[a]].join(" "),children:[p?e(r.Label,{className:"min-w-0 truncate text-(--neba-fg)",children:p}):null,x?e(r.Value,{className:"shrink-0 tabular-nums text-(--neba-muted-fg)",children:e=>o(N,e,V)}):null]}):null,e(r.Track,{className:`relative w-full overflow-hidden rounded-full bg-(--n-soft) ${n[a]}`,children:e(r.Indicator,{className:["absolute rounded-full bg-(--n-fill)",y?"neba-sweep":"top-0 [transition:width_var(--neba-duration-fill)_var(--neba-ease)]"].join(" ")})})]})});
|
|
@@ -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 @@
|
|
|
1
|
+
export{ScatterChart}from"./ScatterChart";
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaOrientation, NebaStyleProps } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* When the scroll buttons are drawn.
|
|
5
|
+
*
|
|
6
|
+
* - `auto` — only the one that has somewhere to go, and neither of them while
|
|
7
|
+
* everything fits. The default: a control that cannot do anything is worse
|
|
8
|
+
* than no control, and a row that does not overflow is not a scroller.
|
|
9
|
+
* - `always` — both, from the first paint, with the one that has nowhere to go
|
|
10
|
+
* `disabled` rather than gone. What a row whose content arrives later wants,
|
|
11
|
+
* since the buttons do not appear under the pointer half a second in.
|
|
12
|
+
* - `none` — none at all. Dragging, the wheel and the arrow keys are still
|
|
13
|
+
* there; this is the strip that scrolls the way a phone scrolls.
|
|
14
|
+
*/
|
|
15
|
+
export type ScrollZoneButtons = 'auto' | 'always' | 'none';
|
|
16
|
+
/**
|
|
17
|
+
* What pressing a scroll button does.
|
|
18
|
+
*
|
|
19
|
+
* - `item` — moves to the next child along, `step` of them at a time. The
|
|
20
|
+
* default, and the only one that lands on something rather than between two
|
|
21
|
+
* things.
|
|
22
|
+
* - `page` — moves by everything currently on screen, the way Page Down does.
|
|
23
|
+
* - `hold` — scrolls for as long as the button is held, at `speed` pixels a
|
|
24
|
+
* second. A press too short to be a hold falls back to one `item`, so the
|
|
25
|
+
* button is never dead to a quick tap.
|
|
26
|
+
*/
|
|
27
|
+
export type ScrollZoneMode = 'item' | 'page' | 'hold';
|
|
28
|
+
/**
|
|
29
|
+
* Where the scroll buttons sit, which is also where the strip ends.
|
|
30
|
+
*
|
|
31
|
+
* - `overlay` — over the ends of the strip, which keeps every pixel of the box
|
|
32
|
+
* for content and lets an item pass under a button. The default, and what a
|
|
33
|
+
* shelf of pictures wants.
|
|
34
|
+
* - `inline` — beside the strip, in the layout. The scroller stops where the
|
|
35
|
+
* button starts, so an item is *cut off* at the button's edge rather than
|
|
36
|
+
* sliding beneath it: nothing is ever half-hidden behind a control, and the
|
|
37
|
+
* button is legible over the page rather than over whatever it landed on.
|
|
38
|
+
*
|
|
39
|
+
* The lane an `inline` button sits in is kept even while that button has
|
|
40
|
+
* nowhere to go, or the strip would resize under the pointer every time it
|
|
41
|
+
* reached an end.
|
|
42
|
+
*/
|
|
43
|
+
export type ScrollZoneButtonPlacement = 'overlay' | 'inline';
|
|
44
|
+
export interface ScrollZoneProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
45
|
+
/**
|
|
46
|
+
* Which way the children run, and therefore which way the zone scrolls.
|
|
47
|
+
* @default 'horizontal'
|
|
48
|
+
*/
|
|
49
|
+
orientation?: NebaOrientation;
|
|
50
|
+
/**
|
|
51
|
+
* How many rows a horizontal zone lays its children out in before it starts a
|
|
52
|
+
* new column — and how many columns a vertical one uses. `2` is the shelf
|
|
53
|
+
* that holds twice as much in the same width.
|
|
54
|
+
* @default 1
|
|
55
|
+
*/
|
|
56
|
+
lines?: number;
|
|
57
|
+
/**
|
|
58
|
+
* The gap between children, on Tailwind's spacing scale: `2` is `0.5rem`, the
|
|
59
|
+
* same step `gap-2` is. The same ladder GridContainer's own `spacing` is on.
|
|
60
|
+
* @default 2
|
|
61
|
+
*/
|
|
62
|
+
spacing?: number;
|
|
63
|
+
/** When the scroll buttons are drawn. @default 'auto' */
|
|
64
|
+
buttons?: ScrollZoneButtons;
|
|
65
|
+
/**
|
|
66
|
+
* Whether the buttons sit over the strip or beside it. `inline` is what to
|
|
67
|
+
* reach for when an item disappearing under a button reads as a bug rather
|
|
68
|
+
* than as depth.
|
|
69
|
+
* @default 'overlay'
|
|
70
|
+
*/
|
|
71
|
+
buttonPlacement?: ScrollZoneButtonPlacement;
|
|
72
|
+
/** What pressing one does. @default 'item' */
|
|
73
|
+
mode?: ScrollZoneMode;
|
|
74
|
+
/** How many children one press moves, in `item` mode. @default 1 */
|
|
75
|
+
step?: number;
|
|
76
|
+
/** How fast a held button scrolls, in pixels a second. @default 900 */
|
|
77
|
+
speed?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Snaps the nearest child to the leading edge when the scrolling stops —
|
|
80
|
+
* dragging and the wheel included, not only the buttons.
|
|
81
|
+
* @default false
|
|
82
|
+
*/
|
|
83
|
+
snap?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Lets a mouse or a pen drag the strip along, the way a finger already does.
|
|
86
|
+
* Touch is left to the browser, whose own scrolling is better than anything a
|
|
87
|
+
* handler can imitate: momentum, rubber-banding and the scrollbar all come
|
|
88
|
+
* with it.
|
|
89
|
+
* @default true
|
|
90
|
+
*/
|
|
91
|
+
drag?: boolean;
|
|
92
|
+
/** Shows the native scrollbar. @default false */
|
|
93
|
+
scrollbar?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Which language the buttons name themselves in — a BCP 47 tag such as `ko`,
|
|
96
|
+
* `pt-BR` or `zh-Hant`. Unsupported tags fall back to English.
|
|
97
|
+
*/
|
|
98
|
+
locale?: string;
|
|
99
|
+
/** What the scrollable region is called — "Categories", "Recent files". */
|
|
100
|
+
label?: string;
|
|
101
|
+
/** Overrides the buttons' own names. */
|
|
102
|
+
previousLabel?: string;
|
|
103
|
+
nextLabel?: string;
|
|
104
|
+
/** What is being laid out. Every top-level child is one item of the strip. */
|
|
105
|
+
children?: React.ReactNode;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A strip of anything, laid out in one direction and scrolled in it.
|
|
109
|
+
*
|
|
110
|
+
* The mechanism is an ordinary scroll container, and everything the component
|
|
111
|
+
* offers is a way of driving one. Swiping on a phone, two-finger dragging on a
|
|
112
|
+
* trackpad, the wheel, the arrow keys and the scrollbar are the browser's own
|
|
113
|
+
* and are never intercepted; what is added on top is a pair of buttons for the
|
|
114
|
+
* pointer that has neither a wheel nor a finger, and a mouse drag for the strip
|
|
115
|
+
* that reads as something to pull rather than something to page.
|
|
116
|
+
*
|
|
117
|
+
* Nothing is transformed. A translated track would have to argue for an
|
|
118
|
+
* exception to the house rule; a scroll offset does not, and it is also what
|
|
119
|
+
* makes the strip run the other way under RTL without being told, keeps the
|
|
120
|
+
* scrollbar honest, and lets the browser scroll a focused child into view.
|
|
121
|
+
*
|
|
122
|
+
* `lines` is what separates this from a Carousel: a Carousel is one thing at a
|
|
123
|
+
* time and knows which one, a ScrollZone is a shelf that happens to be longer
|
|
124
|
+
* than the room it is in.
|
|
125
|
+
*/
|
|
126
|
+
export declare const ScrollZone: React.ForwardRefExoticComponent<ScrollZoneProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{IconButton as r}from"../icon-button/IconButton";import{spacingValue as o}from"../../internal/grid";import{useMessages as i}from"../../internal/i18n";import{ChevronIcon as s}from"../../internal/icons";import{cx as l}from"../../internal/styles";const a={xs:"p-1",sm:"p-1.5",md:"p-2",lg:"p-3",xl:"p-4"},c={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-3",xl:"gap-4"};export const ScrollZone=n.forwardRef(function({orientation:u="horizontal",lines:d=1,spacing:m=2,buttons:p="auto",buttonPlacement:f="overlay",mode:v="item",step:b=1,speed:w=900,snap:g=!1,drag:h=!0,scrollbar:y=!1,variant:x="solid",size:k="md",color:L="primary",density:E="default",locale:C,label:R,previousLabel:P,nextLabel:M,className:N,style:T,children:A,...z},j){const D=i(C),S="horizontal"===u,B=Math.max(1,Math.round(d)),F=Math.max(1,Math.round(b)),H=n.useRef(null),I=n.useRef(null),[W,$]=n.useState({back:!1,forward:!1}),q=n.useCallback(()=>{const e=H.current;if(!e)return;const t=S?e.clientWidth:e.clientHeight,n=S?e.scrollWidth:e.scrollHeight,r=Math.abs(S?e.scrollLeft:e.scrollTop);$(e=>{const o=r>1,i=n-t-r>1;return e.back===o&&e.forward===i?e:{back:o,forward:i}})},[S]);n.useEffect(()=>{const e=H.current,t=I.current;if(!e)return;if(q(),"undefined"==typeof ResizeObserver)return;const n=new ResizeObserver(q);return n.observe(e),t&&n.observe(t),()=>n.disconnect()},[q]);const O=n.useCallback(()=>{const e=H.current;return e&&S&&"rtl"===getComputedStyle(e).direction?-1:1},[S]),X=n.useCallback((e,t)=>{const n=H.current;if(!n)return;const r=t?"undefined"!=typeof window&&window.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth":"auto";n.scrollBy(S?{left:e,behavior:r}:{top:e,behavior:r})},[S]),Y=n.useCallback(()=>{const e=H.current,t=I.current;if(!e||!t)return[];const n=S&&"rtl"===getComputedStyle(e).direction,r=S?n?"right":"left":"top",o=n?-1:1,i=e.getBoundingClientRect()[r],s=[];for(const e of Array.from(t.children)){const t=Math.round((e.getBoundingClientRect()[r]-i)*o);s.includes(t)||s.push(t)}return s.sort((e,t)=>e-t)},[S]),_=n.useCallback((e,t=v)=>{const n=H.current;if(!n)return;const r=O(),o=S?n.clientWidth:n.clientHeight;if("page"===t)return void X(o*(e?1:-1)*r,!0);const i=Y(),s=i.filter(e=>e>1),l=i.filter(e=>e<-1),a=e?s[F-1]:l[l.length-F];X(void 0!==a?a*r:o*(e?1:-1)*r,!0)},[O,S,Y,F,v,X]),K=n.useRef(null);n.useEffect(()=>()=>K.current?.(),[]);const V=n.useCallback((e,t)=>{if(K.current)return;const n=O(),r=performance.now();let o=r,i=0;const s=t=>{const r=t-o;o=t,X(w*r/1e3*(e?1:-1)*n,!1),i=requestAnimationFrame(s)};i=requestAnimationFrame(s);const l=()=>{cancelAnimationFrame(i),K.current=null,window.removeEventListener(t,l),window.removeEventListener("pointercancel",l),window.removeEventListener("blur",l),performance.now()-r<140&&_(e,"item")};K.current=l,window.addEventListener(t,l),window.addEventListener("pointercancel",l),window.addEventListener("blur",l)},[_,O,X,w]),Z=n.useRef(null);function G(e){return"hold"!==v?{onClick:()=>_(e)}:{onPointerDown:t=>{0===t.button&&V(e,"pointerup")},onKeyDown:t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),V(e,"keyup"))}}}n.useEffect(()=>()=>Z.current?.(),[]);const J="none"!==p&&("always"===p||W.back||W.forward),Q="inline"===f;function U(t){const n=t?W.forward:W.back;if("auto"===p&&!n&&!Q)return e("span",{});const o=S?t?"-rotate-90 rtl:rotate-90":"rotate-90 rtl:-rotate-90":t?"":"rotate-180",i="auto"===p&&!n,a=e(r,{variant:x,size:k,color:L,density:E,elevation:1,label:t?M??D.scroll.next:P??D.scroll.previous,disabled:!n,className:"pointer-events-auto",icon:e("span",{className:l("flex items-center",o),children:e(s,{})}),...G(t)});return Q?e("span",{className:l("flex shrink-0 items-center justify-center",i?"invisible":""),inert:i,children:a}):a}return t("div",{ref:j,className:l("relative flex min-w-0",Q&&S?"flex-row items-stretch":"flex-col",Q?c[k]:"",N),style:{"--n-ring":`var(--neba-${L}-ring)`,...T},...z,children:[J&&Q?U(!1):null,e("div",{ref:H,tabIndex:0,role:R?"group":void 0,"aria-label":R,className:l("min-h-0 min-w-0 grow",S?"overflow-x-auto overflow-y-hidden":"overflow-y-auto overflow-x-hidden",g?S?"snap-x snap-mandatory":"snap-y snap-mandatory":"",y?"":"[scrollbar-width:none] [&::-webkit-scrollbar]:hidden",h&&(W.back||W.forward)?"cursor-grab data-[dragging]:cursor-grabbing":"","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]"),onScroll:q,onPointerDown:function(e){if(!h||"touch"===e.pointerType||0!==e.button)return;Z.current?.();const t=e.currentTarget,n=e.clientX,r=e.clientY,o=t.scrollLeft,i=t.scrollTop;let s=!1;const l=document.body.style.getPropertyValue("-webkit-user-select"),a=e=>{const l=e.clientX-n,a=e.clientY-r;if(!s){if(Math.abs(S?l:a)<4)return;s=!0,t.setPointerCapture(e.pointerId),t.dataset.dragging="true",document.body.style.setProperty("-webkit-user-select","none")}S?t.scrollLeft=o-l:t.scrollTop=i-a},c=()=>{Z.current=null,t.removeEventListener("pointermove",a),t.removeEventListener("pointerup",u),t.removeEventListener("pointercancel",c),delete t.dataset.dragging,l?document.body.style.setProperty("-webkit-user-select",l):document.body.style.removeProperty("-webkit-user-select")},u=()=>{const e=s;if(c(),!e)return;const n=e=>{e.stopPropagation(),e.preventDefault()};t.addEventListener("click",n,{capture:!0,once:!0}),window.setTimeout(()=>t.removeEventListener("click",n,!0),0)};Z.current=c,t.addEventListener("pointermove",a),t.addEventListener("pointerup",u),t.addEventListener("pointercancel",c)},children:e("div",{ref:I,className:l(g?"[&>*]:snap-start":""),style:{display:"grid",gap:o(m),gridAutoFlow:S?"column":"row",...S?{width:"max-content",gridTemplateRows:`repeat(${B}, auto)`,gridAutoColumns:"max-content"}:{gridTemplateColumns:`repeat(${B}, minmax(0, 1fr))`,gridAutoRows:"max-content"}},children:A})}),J&&Q?U(!0):null,J&&!Q?t("div",{className:l("pointer-events-none absolute inset-0 flex justify-between",S?"items-center":"flex-col items-center",a[k]),children:[U(!1),U(!0)]}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ScrollZone}from"./ScrollZone";
|
|
@@ -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},
|
|
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 @@
|
|
|
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
|
|
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
|
-
/**
|
|
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;
|