neba 0.0.1 → 1.1.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 +177 -2
- package/dist/components/accordion/Accordion.d.ts +97 -0
- package/dist/components/accordion/Accordion.js +1 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +1 -0
- package/dist/components/alert/Alert.d.ts +47 -0
- package/dist/components/alert/Alert.js +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/badge/Badge.d.ts +80 -0
- package/dist/components/badge/Badge.js +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/blockquote/Blockquote.d.ts +65 -0
- package/dist/components/blockquote/Blockquote.js +1 -0
- package/dist/components/blockquote/index.d.ts +2 -0
- package/dist/components/blockquote/index.js +1 -0
- package/dist/components/box/Box.d.ts +50 -0
- package/dist/components/box/Box.js +1 -0
- package/dist/components/box/index.d.ts +2 -0
- package/dist/components/box/index.js +1 -0
- package/dist/components/button/Button.d.ts +25 -3
- package/dist/components/button/Button.js +1 -1
- package/dist/components/button/index.d.ts +1 -0
- package/dist/components/button-group/ButtonGroup.d.ts +31 -0
- package/dist/components/button-group/ButtonGroup.js +1 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.js +1 -0
- package/dist/components/card/Card.d.ts +45 -0
- package/dist/components/card/Card.js +1 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/carousel/Carousel.d.ts +74 -0
- package/dist/components/carousel/Carousel.js +1 -0
- package/dist/components/carousel/index.d.ts +2 -0
- package/dist/components/carousel/index.js +1 -0
- package/dist/components/checkbox/Checkbox.d.ts +39 -0
- package/dist/components/checkbox/Checkbox.js +1 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/chip/Chip.d.ts +50 -0
- package/dist/components/chip/Chip.js +1 -0
- package/dist/components/chip/index.d.ts +2 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/combobox/Combobox.d.ts +131 -0
- package/dist/components/combobox/Combobox.js +1 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/container/Container.d.ts +55 -0
- package/dist/components/container/Container.js +1 -0
- package/dist/components/container/index.d.ts +2 -0
- package/dist/components/container/index.js +1 -0
- package/dist/components/date-picker/DatePicker.d.ts +75 -0
- package/dist/components/date-picker/DatePicker.js +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-range-picker/DateRangePicker.d.ts +81 -0
- package/dist/components/date-range-picker/DateRangePicker.js +1 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/date-time-picker/DateTimePicker.d.ts +68 -0
- package/dist/components/date-time-picker/DateTimePicker.js +1 -0
- package/dist/components/date-time-picker/index.d.ts +2 -0
- package/dist/components/date-time-picker/index.js +1 -0
- package/dist/components/dialog/Dialog.d.ts +111 -0
- package/dist/components/dialog/Dialog.js +1 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/divider/Divider.d.ts +67 -0
- package/dist/components/divider/Divider.js +1 -0
- package/dist/components/divider/index.d.ts +2 -0
- package/dist/components/divider/index.js +1 -0
- package/dist/components/file-picker/FilePicker.d.ts +103 -0
- package/dist/components/file-picker/FilePicker.js +1 -0
- package/dist/components/file-picker/index.d.ts +2 -0
- package/dist/components/file-picker/index.js +1 -0
- package/dist/components/grid/Grid.d.ts +50 -0
- package/dist/components/grid/Grid.js +1 -0
- package/dist/components/grid/index.d.ts +2 -0
- package/dist/components/grid/index.js +1 -0
- package/dist/components/grid-container/GridContainer.d.ts +79 -0
- package/dist/components/grid-container/GridContainer.js +1 -0
- package/dist/components/grid-container/index.d.ts +2 -0
- package/dist/components/grid-container/index.js +1 -0
- package/dist/components/highlight/Highlight.d.ts +84 -0
- package/dist/components/highlight/Highlight.js +1 -0
- package/dist/components/highlight/index.d.ts +2 -0
- package/dist/components/highlight/index.js +1 -0
- package/dist/components/icon/Icon.d.ts +58 -0
- package/dist/components/icon/Icon.js +1 -0
- package/dist/components/icon/index.d.ts +2 -0
- package/dist/components/icon/index.js +1 -0
- package/dist/components/icon-button/IconButton.d.ts +39 -0
- package/dist/components/icon-button/IconButton.js +1 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/icon-button/index.js +1 -0
- package/dist/components/list/List.d.ts +81 -0
- package/dist/components/list/List.js +1 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.js +1 -0
- package/dist/components/menu/Menu.d.ts +216 -0
- package/dist/components/menu/Menu.js +1 -0
- package/dist/components/menu/index.d.ts +2 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/number-field/NumberField.d.ts +113 -0
- package/dist/components/number-field/NumberField.js +1 -0
- package/dist/components/number-field/index.d.ts +2 -0
- package/dist/components/number-field/index.js +1 -0
- package/dist/components/overlay/Overlay.d.ts +85 -0
- package/dist/components/overlay/Overlay.js +1 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.js +1 -0
- package/dist/components/pagination/Pagination.d.ts +65 -0
- package/dist/components/pagination/Pagination.js +1 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/pill/Pill.d.ts +80 -0
- package/dist/components/pill/Pill.js +1 -0
- package/dist/components/pill/index.d.ts +2 -0
- package/dist/components/pill/index.js +1 -0
- package/dist/components/progress-box/ProgressBox.d.ts +33 -0
- package/dist/components/progress-box/ProgressBox.js +1 -0
- package/dist/components/progress-box/index.d.ts +2 -0
- package/dist/components/progress-box/index.js +1 -0
- package/dist/components/progress-circular/ProgressCircular.d.ts +19 -0
- package/dist/components/progress-circular/ProgressCircular.js +1 -0
- package/dist/components/progress-circular/index.d.ts +2 -0
- package/dist/components/progress-circular/index.js +1 -0
- package/dist/components/progress-linear/ProgressLinear.d.ts +20 -0
- package/dist/components/progress-linear/ProgressLinear.js +1 -0
- package/dist/components/progress-linear/index.d.ts +2 -0
- package/dist/components/progress-linear/index.js +1 -0
- package/dist/components/radio-group/RadioGroup.d.ts +51 -0
- package/dist/components/radio-group/RadioGroup.js +1 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +1 -0
- package/dist/components/segmented-button/SegmentedButton.d.ts +77 -0
- package/dist/components/segmented-button/SegmentedButton.js +1 -0
- package/dist/components/segmented-button/index.d.ts +2 -0
- package/dist/components/segmented-button/index.js +1 -0
- package/dist/components/select/Select.d.ts +76 -0
- package/dist/components/select/Select.js +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/shortcut/Shortcut.d.ts +60 -0
- package/dist/components/shortcut/Shortcut.js +1 -0
- package/dist/components/shortcut/index.d.ts +2 -0
- package/dist/components/shortcut/index.js +1 -0
- package/dist/components/slider/Slider.d.ts +38 -0
- package/dist/components/slider/Slider.js +1 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +1 -0
- package/dist/components/statistic/Statistic.d.ts +91 -0
- package/dist/components/statistic/Statistic.js +1 -0
- package/dist/components/statistic/index.d.ts +2 -0
- package/dist/components/statistic/index.js +1 -0
- package/dist/components/switch/Switch.d.ts +39 -0
- package/dist/components/switch/Switch.js +1 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/Table.d.ts +80 -0
- package/dist/components/table/Table.js +1 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/tabs/Tabs.d.ts +92 -0
- package/dist/components/tabs/Tabs.js +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/text-field/TextField.d.ts +63 -0
- package/dist/components/text-field/TextField.js +1 -0
- package/dist/components/text-field/index.d.ts +2 -0
- package/dist/components/text-field/index.js +1 -0
- package/dist/components/time-picker/TimePicker.d.ts +76 -0
- package/dist/components/time-picker/TimePicker.js +1 -0
- package/dist/components/time-picker/index.d.ts +2 -0
- package/dist/components/time-picker/index.js +1 -0
- package/dist/components/timeline/Timeline.d.ts +98 -0
- package/dist/components/timeline/Timeline.js +1 -0
- package/dist/components/timeline/index.d.ts +2 -0
- package/dist/components/timeline/index.js +1 -0
- package/dist/components/toast/Toast.d.ts +116 -0
- package/dist/components/toast/Toast.js +1 -0
- package/dist/components/toast/index.d.ts +2 -0
- package/dist/components/toast/index.js +1 -0
- package/dist/components/toolbar/Toolbar.d.ts +67 -0
- package/dist/components/toolbar/Toolbar.js +1 -0
- package/dist/components/toolbar/index.d.ts +2 -0
- package/dist/components/toolbar/index.js +1 -0
- package/dist/components/tooltip/Tooltip.d.ts +81 -0
- package/dist/components/tooltip/Tooltip.js +1 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/typography/Typography.d.ts +62 -0
- package/dist/components/typography/Typography.js +1 -0
- package/dist/components/typography/index.d.ts +2 -0
- package/dist/components/typography/index.js +1 -0
- package/dist/index.d.ts +50 -1
- package/dist/index.js +1 -1
- package/dist/internal/button-group.d.ts +25 -0
- package/dist/internal/button-group.js +1 -0
- package/dist/internal/calendar.d.ts +149 -0
- package/dist/internal/calendar.js +1 -0
- package/dist/internal/date.d.ts +170 -0
- package/dist/internal/date.js +1 -0
- package/dist/internal/grid.d.ts +69 -0
- package/dist/internal/grid.js +1 -0
- package/dist/internal/icons.d.ts +79 -0
- package/dist/internal/icons.js +1 -0
- package/dist/internal/menu.d.ts +20 -0
- package/dist/internal/menu.js +1 -0
- package/dist/internal/picker.d.ts +111 -0
- package/dist/internal/picker.js +1 -0
- package/dist/internal/progress.d.ts +122 -0
- package/dist/internal/progress.js +1 -0
- package/dist/internal/sizer.d.ts +33 -0
- package/dist/internal/sizer.js +1 -0
- package/dist/internal/styles.d.ts +257 -0
- package/dist/internal/styles.js +1 -0
- package/dist/styles.css +2 -0
- package/dist/tailwind.css +892 -0
- package/dist/types.d.ts +142 -0
- package/dist/types.js +8 -0
- package/package.json +90 -21
- package/pnpm-workspace.yaml +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Pill}from"./Pill";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type ProgressSharedProps } from '../../internal/progress';
|
|
3
|
+
import type { NebaColor, NebaSize } from '../../types';
|
|
4
|
+
export interface ProgressBoxProps extends ProgressSharedProps {
|
|
5
|
+
/** Size of one plate. */
|
|
6
|
+
size?: NebaSize;
|
|
7
|
+
/** @default 'primary' */
|
|
8
|
+
color?: NebaColor;
|
|
9
|
+
/**
|
|
10
|
+
* How many plates the row is made of.
|
|
11
|
+
*
|
|
12
|
+
* Four by default: enough that the wave reads as a wave, few enough that a
|
|
13
|
+
* determinate row can be counted at a glance rather than measured. Set it to
|
|
14
|
+
* the number of steps when the thing being waited on genuinely has steps.
|
|
15
|
+
* @default 4
|
|
16
|
+
*/
|
|
17
|
+
count?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A row of acrylic plates that light up.
|
|
21
|
+
*
|
|
22
|
+
* The third shape, and the one that is about the material rather than about the
|
|
23
|
+
* quantity. A bar and a ring both say "this much of it is done"; a row of
|
|
24
|
+
* plates says "this is working" in the library's own vocabulary — the same cut
|
|
25
|
+
* sheet, the same hairline, the same fill — which is what makes it the right
|
|
26
|
+
* one for a loading state inside a Neba surface where a foreign grey spinner
|
|
27
|
+
* would look borrowed.
|
|
28
|
+
*
|
|
29
|
+
* It answers a value when it has one: the plates fill left to right, the last
|
|
30
|
+
* one partially, so four plates read as a four-segment bar. Without a value
|
|
31
|
+
* they cycle, each held back by its own index.
|
|
32
|
+
*/
|
|
33
|
+
export declare const ProgressBox: React.ForwardRefExoticComponent<ProgressBoxProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +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},N){const M=o(x,b,p),B=null===M,V=void 0!==y,k=Math.max(1,Math.floor(h));return a(t.Root,{ref:N,value:x??null,min:b,max:p,format:y,getAriaValueText:i(M,V),className:["inline-flex flex-col",u[l],w??""].filter(Boolean).join(" "),style:{...m(d),...j},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(M,e,V)}):null]}):null,e(t.Track,{className:`flex ${n[l]}`,children:Array.from({length:k},(a,t)=>e("span",{className:["relative overflow-hidden bg-(--n-soft)","[box-shadow:var(--neba-plate-glass)]",s[l],r[l],B?"neba-plate-wave":""].filter(Boolean).join(" "),style:B?{"--n-i":t}:void 0,children:B?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*(M*k-t)))}%`}})},t))})]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ProgressBox}from"./ProgressBox";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type ProgressSharedProps } from '../../internal/progress';
|
|
3
|
+
import type { NebaColor, NebaSize } from '../../types';
|
|
4
|
+
export interface ProgressCircularProps extends ProgressSharedProps {
|
|
5
|
+
/** Diameter of the ring. Sits just under the control ladder at every step. */
|
|
6
|
+
size?: NebaSize;
|
|
7
|
+
/** @default 'primary' */
|
|
8
|
+
color?: NebaColor;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A ring that fills, and the one to reach for when there is no room for a bar —
|
|
12
|
+
* inside a button, at the end of a table row, next to a field.
|
|
13
|
+
*
|
|
14
|
+
* The value and the label sit *beside* the ring rather than inside it. A number
|
|
15
|
+
* in the middle of a dial is the picture everyone has of this component, and it
|
|
16
|
+
* only works at two of the five sizes: at `xs` the ring is fourteen pixels
|
|
17
|
+
* across and there is nowhere for "40%" to go. Beside it, every size reads.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ProgressCircular: React.ForwardRefExoticComponent<ProgressCircularProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +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},y){const $=n(h,d,x),N=null===$,w=void 0!==b,j=l[a],V=c[a],B=j/2,D=B-V/2,L=2*Math.PI*D,P=N?`${.28*L} ${L}`:`${L}`,R=N?0:L*(1-$);return r(t.Root,{ref:y,value:h??null,min:d,max:x,format:b,getAriaValueText:s($,w),className:["inline-flex items-center",m[a],f[a],g??""].filter(Boolean).join(" "),style:{...i(u),...v},children:[r("svg",{className:N?"neba-ring-spin shrink-0":"shrink-0",width:j,height:j,viewBox:`0 0 ${j} ${j}`,fill:"none","aria-hidden":"true",children:[e("circle",{cx:B,cy:B,r:D,stroke:"var(--n-soft)",strokeWidth:V}),e("circle",{cx:B,cy:B,r:D,stroke:"var(--n-accent)",strokeWidth:V,strokeLinecap:"round",strokeDasharray:P,strokeDashoffset:R,transform:`rotate(-90 ${B} ${B})`,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($,e,w)}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ProgressCircular}from"./ProgressCircular";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type ProgressSharedProps } from '../../internal/progress';
|
|
3
|
+
import type { NebaColor, NebaSize } from '../../types';
|
|
4
|
+
export interface ProgressLinearProps extends ProgressSharedProps {
|
|
5
|
+
/** Thickness of the groove. Nothing else on a bar has a size. */
|
|
6
|
+
size?: NebaSize;
|
|
7
|
+
/** @default 'primary' */
|
|
8
|
+
color?: NebaColor;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A bar that fills. The workhorse: it is the only one of the three that can
|
|
12
|
+
* show *how much* is left at a glance, because length is the one quantity a
|
|
13
|
+
* reader can compare without counting.
|
|
14
|
+
*
|
|
15
|
+
* Base UI's Progress owns the semantics — `role="progressbar"`, the value and
|
|
16
|
+
* range attributes, `aria-valuetext`, and dropping the value entirely when the
|
|
17
|
+
* bar is indeterminate — and it also computes the fill width, so the determinate
|
|
18
|
+
* case here is a class list and nothing else.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ProgressLinear: React.ForwardRefExoticComponent<ProgressLinearProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +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},j){const v=t(c,d,b),N=null===v,y=void 0!==g;return l(r.Root,{ref:j,value:c??null,min:d,max:b,format:g,getAriaValueText:s(v,y),className:["flex w-full flex-col",u[a],h??""].filter(Boolean).join(" "),style:{...i(f),...w},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(v,e,y)}):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)",N?"neba-sweep":"top-0 [transition:width_var(--neba-duration-fill)_var(--neba-ease)]"].join(" ")})})]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ProgressLinear}from"./ProgressLinear";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Radio as BaseUIRadio } from '@base-ui/react/radio';
|
|
3
|
+
import { RadioGroup as BaseUIRadioGroup } from '@base-ui/react/radio-group';
|
|
4
|
+
import type { NebaColor, NebaOrientation, NebaSize } from '../../types';
|
|
5
|
+
export interface RadioGroupProps extends Omit<React.ComponentPropsWithoutRef<typeof BaseUIRadioGroup>, 'className' | 'style' | 'render'> {
|
|
6
|
+
/** @default 'md' */
|
|
7
|
+
size?: NebaSize;
|
|
8
|
+
/** @default 'primary' */
|
|
9
|
+
color?: NebaColor;
|
|
10
|
+
/**
|
|
11
|
+
* Which way the options stack. Vertical by default — a column of options is
|
|
12
|
+
* scannable at any length, and a row silently becomes unreadable the moment
|
|
13
|
+
* one label is longer than expected.
|
|
14
|
+
* @default 'vertical'
|
|
15
|
+
*/
|
|
16
|
+
orientation?: NebaOrientation;
|
|
17
|
+
/** The question the options answer. Rendered as the group's legend. */
|
|
18
|
+
label?: React.ReactNode;
|
|
19
|
+
/** Helper text under the label. */
|
|
20
|
+
description?: React.ReactNode;
|
|
21
|
+
/** Error message below the options. Its presence also turns the group invalid. */
|
|
22
|
+
error?: React.ReactNode;
|
|
23
|
+
/** Forces the invalid state without a message. Defaults to `!!error`. */
|
|
24
|
+
invalid?: boolean;
|
|
25
|
+
className?: string;
|
|
26
|
+
style?: React.CSSProperties;
|
|
27
|
+
}
|
|
28
|
+
export interface RadioProps extends Omit<React.ComponentPropsWithoutRef<typeof BaseUIRadio.Root>, 'className' | 'style' | 'render' | 'children'> {
|
|
29
|
+
/** The text beside the dot. Wired to it by Base UI's Field. */
|
|
30
|
+
label?: React.ReactNode;
|
|
31
|
+
/** Helper text under the label. */
|
|
32
|
+
description?: React.ReactNode;
|
|
33
|
+
className?: string;
|
|
34
|
+
style?: React.CSSProperties;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One option in a RadioGroup.
|
|
38
|
+
*
|
|
39
|
+
* It has no `size` and no `color` of its own — both come from the group, which
|
|
40
|
+
* is the only place they can be set once and mean the same thing for every
|
|
41
|
+
* option in the set.
|
|
42
|
+
*/
|
|
43
|
+
export declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLElement>>;
|
|
44
|
+
/**
|
|
45
|
+
* A set of options where exactly one is chosen.
|
|
46
|
+
*
|
|
47
|
+
* Base UI owns the roving tab index and the arrow-key navigation, which is the
|
|
48
|
+
* whole reason a radio group is a component at all rather than a `<div>` full of
|
|
49
|
+
* inputs: the set takes one tab stop, and the arrows move within it.
|
|
50
|
+
*/
|
|
51
|
+
export declare const RadioGroup: React.ForwardRefExoticComponent<RadioGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Radio as n}from"@base-ui/react/radio";import{RadioGroup as l}from"@base-ui/react/radio-group";import{Field as o}from"@base-ui/react/field";import{controlTextClasses as i,metaTextClasses as t,surfaceClasses as s,tickDotClasses as d,tickRowLeadingClasses as c,tickSizeClasses as b,transitionClasses as f}from"../../internal/styles";const h=r.createContext({size:"md",color:"primary",readOnly:!1}),m=["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",f,"active:[transition-duration:0ms]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),u=[s,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),p=[s,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),v=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)] shadow-none","data-[checked]:bg-(--neba-disabled-bg)"].join(" ");export const Radio=r.forwardRef(function({label:l,description:s,disabled:f=!1,className:x,style:g,...y},N){const j=r.useContext(h),$=y.readOnly??j.readOnly;return e(o.Root,{disabled:f,className:["flex flex-col",x??""].filter(Boolean).join(" "),style:g,children:a("div",{className:`flex items-start gap-2 ${i[j.size]} ${c}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(n.Root,{ref:N,className:[m,b[j.size],f?v:$?p:u].join(" "),disabled:f,...y,children:e(n.Indicator,{className:`rounded-full bg-current ${d[j.size]}`})})}),l||s?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[l?e(o.Label,{className:["leading-[1.4]",f?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:l}):null,s?e(o.Description,{className:`${t[j.size]} text-(--neba-muted-fg)`,children:s}):null]}):null]})})});export const RadioGroup=r.forwardRef(function({size:n="md",color:i="primary",orientation:s="vertical",label:d,description:c,error:b,invalid:f,disabled:m=!1,readOnly:u=!1,className:p,style:v,children:x,...g},y){const N=null!=b&&!1!==b&&""!==b,j=f??N,$=j?"danger":i,k={"--n-fill":`var(--neba-${$}-fill)`,"--n-fill-hover":`var(--neba-${$}-fill-hover)`,"--n-on-solid":`var(--neba-${$}-on-solid)`,"--n-accent":`var(--neba-${$}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${$}-line)`,"--n-line-hover":`var(--neba-${$}-line-hover)`,"--n-ring":`var(--neba-${$}-ring)`},R=r.useMemo(()=>({size:n,color:$,readOnly:u}),[n,$,u]);return e(h.Provider,{value:R,children:a(o.Root,{disabled:m,invalid:j,className:["flex flex-col gap-1.5",p??""].filter(Boolean).join(" "),style:{...k,...v},children:[d?e(o.Label,{className:[t[n],"font-medium",m?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:d}):null,c?e(o.Description,{className:`${t[n]} text-(--neba-muted-fg)`,children:c}):null,e(l,{ref:y,disabled:m,readOnly:u,className:["flex","horizontal"===s?"flex-row flex-wrap gap-x-5 gap-y-2":"flex-col gap-2"].join(" "),...g,children:x}),N?e(o.Error,{match:!0,className:`${t[n]} text-(--n-accent)`,children:b}):null]})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Radio,RadioGroup}from"./RadioGroup";
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps, NebaVariant } from '../../types';
|
|
3
|
+
/** A segment's value. The same restraint Tabs and Select put on theirs. */
|
|
4
|
+
export type SegmentValue = string | number;
|
|
5
|
+
export interface SegmentedButtonProps extends Omit<NebaStyleProps, 'variant'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
|
|
6
|
+
/**
|
|
7
|
+
* Weight of the trough the segments sit in.
|
|
8
|
+
*
|
|
9
|
+
* - `solid` — a frosted trough with a filled tile riding in it. The loudest,
|
|
10
|
+
* and the one for a control a screen is about to be steered by.
|
|
11
|
+
* - `outline` — the same trough with a hairline around it and a lit tile
|
|
12
|
+
* rather than a filled one. The default.
|
|
13
|
+
* - `text` — no trough at all: the segments sit straight on the page and only
|
|
14
|
+
* the chosen one has a surface.
|
|
15
|
+
* @default 'outline'
|
|
16
|
+
*/
|
|
17
|
+
variant?: NebaVariant;
|
|
18
|
+
/** The chosen segment. Use with `onValueChange` for a controlled set. */
|
|
19
|
+
value?: SegmentValue | null;
|
|
20
|
+
/** Which starts chosen, for an uncontrolled set. */
|
|
21
|
+
defaultValue?: SegmentValue | null;
|
|
22
|
+
onValueChange?: (value: SegmentValue | null) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Drop shadow depth of the trough. `0` (the default) is flat.
|
|
25
|
+
* @default 0
|
|
26
|
+
*/
|
|
27
|
+
elevation?: NebaElevation;
|
|
28
|
+
/** Disables every segment at once. */
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
/** Shows which one is chosen but does not let it be changed. */
|
|
31
|
+
readOnly?: boolean;
|
|
32
|
+
/** Identifies the value when a form is submitted. */
|
|
33
|
+
name?: string;
|
|
34
|
+
/** The segments share the full width, each taking an equal part of it. */
|
|
35
|
+
fullWidth?: boolean;
|
|
36
|
+
children?: React.ReactNode;
|
|
37
|
+
}
|
|
38
|
+
export interface SegmentProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'value' | 'color'> {
|
|
39
|
+
/** Identifies the segment. What `onValueChange` reports. */
|
|
40
|
+
value: SegmentValue;
|
|
41
|
+
/** Content before the label. Sized in `em`, so it tracks the label. */
|
|
42
|
+
startIcon?: React.ReactNode;
|
|
43
|
+
/** Content after the label — a count, a status dot. */
|
|
44
|
+
endIcon?: React.ReactNode;
|
|
45
|
+
/** Unavailable, but still part of the set. */
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
children?: React.ReactNode;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* One choice in a segmented button.
|
|
51
|
+
*
|
|
52
|
+
* It has no `size`, no `color` and no `variant` of its own: all three belong to
|
|
53
|
+
* the set, which is the only place they can be set once and mean the same thing
|
|
54
|
+
* for every segment.
|
|
55
|
+
*/
|
|
56
|
+
export declare const Segment: React.ForwardRefExoticComponent<SegmentProps & React.RefAttributes<HTMLElement>>;
|
|
57
|
+
/**
|
|
58
|
+
* Two or more choices in one pill, exactly one of them taken.
|
|
59
|
+
*
|
|
60
|
+
* Underneath it is a radio group, and that is the whole accessibility argument:
|
|
61
|
+
* a segmented button *is* "exactly one of these", so it gets `role="radiogroup"`,
|
|
62
|
+
* one tab stop for the set, arrow keys within it, and `aria-checked` on the one
|
|
63
|
+
* that is taken. Building it out of `aria-pressed` toggles — which is what a row
|
|
64
|
+
* of buttons would give — would announce four independent switches, three of
|
|
65
|
+
* which happen to be off.
|
|
66
|
+
*
|
|
67
|
+
* The tile slides because its `left`, `top`, `width` and `height` are measured
|
|
68
|
+
* off the chosen segment and animated. Nothing is transformed: the tile is an
|
|
69
|
+
* empty box, and no label is resampled while it travels. That is the same
|
|
70
|
+
* distinction Tabs' indicator draws, and the reason the house no-transform rule
|
|
71
|
+
* survives a component whose entire point is that something moves.
|
|
72
|
+
*
|
|
73
|
+
* `left`, not `inset-inline-start`, for the reason Tabs gives: `offsetLeft` is a
|
|
74
|
+
* distance from the left edge and stays one under RTL. Pairing a physical
|
|
75
|
+
* measurement with a logical property is what would break the direction.
|
|
76
|
+
*/
|
|
77
|
+
export declare const SegmentedButton: React.ForwardRefExoticComponent<SegmentedButtonProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Radio as n}from"@base-ui/react/radio";import{RadioGroup as r}from"@base-ui/react/radio-group";import{controlHeightClasses as s,controlSlots as l,controlTextClasses as o,gapClasses as i,hasContent as d,iconClasses as u,paddingXClasses as c,surfaceClasses as f,transitionClasses as h}from"../../internal/styles";const p=a.createContext({variant:"outline",size:"md",density:"default",fullWidth:!1}),b={solid:`${f} bg-(--n-panel) p-1 [box-shadow:var(--n-elev),var(--neba-plate-glass)]`,outline:`${f} border bg-(--n-panel) p-1 [border-color:var(--n-line)] [box-shadow:var(--n-elev),var(--neba-plate-glass)]`,text:""},m={solid:`${f} bg-(--n-fill) [box-shadow:var(--neba-shadow-1),var(--neba-plate-solid)]`,outline:`${f} bg-(--n-panel-press) [box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]`,text:`${f} bg-(--n-panel-press) [box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]`},v={solid:"data-[checked]:text-(--n-on-solid)",outline:"data-[checked]:text-(--n-accent)",text:"data-[checked]:text-(--n-accent)"};export const Segment=a.forwardRef(function({value:r,startIcon:l,endIcon:f,disabled:b=!1,className:m,children:x,...g},y){const{variant:w,size:k,density:$,fullWidth:R}=a.useContext(p);return t(n.Root,{ref:y,value:r,disabled:b,"data-segment":"",className:["relative z-10 inline-flex shrink-0 cursor-pointer items-center justify-center select-none","whitespace-nowrap font-medium","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",s[k],o[k],i[k],c[$][k],"rounded-full",h,u,"text-(--neba-muted-fg) hover:text-(--neba-fg)",v[w],"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","data-[readonly]:cursor-default",R?"flex-1":"",m??""].filter(Boolean).join(" "),...g,children:[d(l)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:l}):null,x,d(f)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:f}):null]})});export const SegmentedButton=a.forwardRef(function({variant:n="outline",size:s="md",color:o="primary",density:i="default",elevation:d=0,value:u,defaultValue:c=null,onValueChange:f,disabled:v=!1,readOnly:x=!1,name:g,fullWidth:y=!1,className:w,style:k,children:$,...R},j){const[N,z]=a.useState(c),W=void 0!==u,C=W?u:N,P=a.useRef(null),S=a.useRef(null),A=a.useCallback(e=>{const t=P.current,a=S.current;if(!t||!a)return;const n=t.querySelector("[data-segment][data-checked]");if(!n)return;const r=!e||!a.hasAttribute("data-ready");r&&a.removeAttribute("data-ready"),a.style.setProperty("--n-seg-x",`${n.offsetLeft}px`),a.style.setProperty("--n-seg-y",`${n.offsetTop}px`),a.style.setProperty("--n-seg-w",`${n.offsetWidth}px`),a.style.setProperty("--n-seg-h",`${n.offsetHeight}px`),r&&a.offsetWidth,a.setAttribute("data-ready","")},[]);a.useLayoutEffect(()=>{A(!0)},[A,C,n,s,i,y,$]),a.useEffect(()=>{const e=P.current;if(!e)return;const t=new ResizeObserver(()=>A(!1));return t.observe(e),()=>t.disconnect()},[A]);const B=a.useMemo(()=>({variant:n,size:s,density:i,fullWidth:y}),[n,s,i,y]);return e(p.Provider,{value:B,children:t(r,{ref:e=>{P.current=e,"function"==typeof j?j(e):j&&(j.current=e)},value:C,onValueChange:e=>{const t=e??null;W||z(t),f?.(t)},disabled:v,readOnly:x,name:g,className:["relative inline-flex items-center rounded-full",b[n],h,x?"[filter:saturate(0.55)]":"",y?"flex w-full":"",w??""].filter(Boolean).join(" "),style:{...l(o,d,n),...k},...R,children:[null!=C?e("span",{ref:S,"aria-hidden":"true",className:["pointer-events-none absolute rounded-full","left-(--n-seg-x) top-(--n-seg-y) h-(--n-seg-h) w-(--n-seg-w)",m[n],"[transition-property:left,top,width,height]","[transition-timing-function:var(--neba-ease)]","[transition-duration:0ms] data-[ready]:[transition-duration:var(--neba-duration)]"].join(" ")}):null,$]})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Segment,SegmentedButton}from"./SegmentedButton";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* What a Select's value may be.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately not generic over arbitrary objects. A select is a form control,
|
|
7
|
+
* its value is what a form submits, and every escape from that — object values,
|
|
8
|
+
* custom equality, a stringifier for the trigger — buys flexibility by making
|
|
9
|
+
* the common case harder to write. Keep the identifier here and look the object
|
|
10
|
+
* up on the other side.
|
|
11
|
+
*/
|
|
12
|
+
export type SelectValue = string | number;
|
|
13
|
+
export interface SelectOption {
|
|
14
|
+
/** Submitted, and what `value` / `onValueChange` speak in. */
|
|
15
|
+
value: SelectValue;
|
|
16
|
+
/** Shown in the list and in the trigger. Defaults to the value itself. */
|
|
17
|
+
label?: React.ReactNode;
|
|
18
|
+
/** Unavailable, but still listed — the option exists, it just cannot be picked. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface SelectProps extends NebaStyleProps {
|
|
22
|
+
/**
|
|
23
|
+
* The options, as data. There is no `<Select.Option>` to compose: what a
|
|
24
|
+
* caller has is almost always an array already, and the list has to be
|
|
25
|
+
* available to the trigger before the popup has ever been opened.
|
|
26
|
+
*/
|
|
27
|
+
items: readonly SelectOption[];
|
|
28
|
+
/** The chosen value. Use with `onValueChange` for a controlled select. */
|
|
29
|
+
value?: SelectValue | null;
|
|
30
|
+
/** The initially chosen value, for an uncontrolled select. */
|
|
31
|
+
defaultValue?: SelectValue | null;
|
|
32
|
+
onValueChange?: (value: SelectValue | null) => void;
|
|
33
|
+
/** Shown in the trigger while nothing is chosen. */
|
|
34
|
+
placeholder?: React.ReactNode;
|
|
35
|
+
/**
|
|
36
|
+
* Drop shadow depth of the *trigger*. The popup has its own, fixed: it
|
|
37
|
+
* genuinely floats above the page, which is the one case elevation is for.
|
|
38
|
+
* @default 0
|
|
39
|
+
*/
|
|
40
|
+
elevation?: NebaElevation;
|
|
41
|
+
/** Label above the trigger, wired to it by Base UI's Field. */
|
|
42
|
+
label?: React.ReactNode;
|
|
43
|
+
/** Helper text below the trigger. */
|
|
44
|
+
description?: React.ReactNode;
|
|
45
|
+
/** Error message below. Its presence also turns the select invalid. */
|
|
46
|
+
error?: React.ReactNode;
|
|
47
|
+
/** Forces the invalid state without a message. Defaults to `!!error`. */
|
|
48
|
+
invalid?: boolean;
|
|
49
|
+
/** Content placed before the value. Sized in `em`, so it tracks the text. */
|
|
50
|
+
startIcon?: React.ReactNode;
|
|
51
|
+
/** Stretches to the width of the container. */
|
|
52
|
+
fullWidth?: boolean;
|
|
53
|
+
/** Unavailable. */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
/** The value is shown but cannot be changed. */
|
|
56
|
+
readOnly?: boolean;
|
|
57
|
+
/** Whether a value must be chosen before the form is submitted. */
|
|
58
|
+
required?: boolean;
|
|
59
|
+
/** Identifies the field when a form is submitted. */
|
|
60
|
+
name?: string;
|
|
61
|
+
id?: string;
|
|
62
|
+
className?: string;
|
|
63
|
+
style?: React.CSSProperties;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* One value chosen from a list of them.
|
|
67
|
+
*
|
|
68
|
+
* The trigger is a TextField's shell wearing a chevron, on purpose: a form where
|
|
69
|
+
* the select is a different height, radius or colour from the fields around it
|
|
70
|
+
* is a form that looks assembled rather than designed.
|
|
71
|
+
*
|
|
72
|
+
* Base UI owns everything hard about this — the popup's positioning and flipping,
|
|
73
|
+
* the focus trap, typeahead, the hidden input that makes it submit — and the
|
|
74
|
+
* work here is the surface it all wears.
|
|
75
|
+
*/
|
|
76
|
+
export declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Select as l}from"@base-ui/react/select";import{Field as n}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons";import{WidthSizer as s}from"../../internal/sizer";import{controlHeightClasses as o,controlTextLeadingClasses as d,disabledClasses as c,fieldReadOnlyClasses as m,fieldRestClasses as u,focusWithinRingClasses as h,gapClasses as f,hasContent as p,iconClasses as b,metaTextClasses as g,paddingXClasses as x,radiusClasses as v,stackGapClasses as N,surfaceClasses as w,surfaceSlots as j,transitionClasses as y}from"../../internal/styles";const I=["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",y,"focus-within:[transition-duration:0ms]",h,b].join(" "),S=[w,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--n-panel-press) p-1","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]"].join(" "),$=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",y,"data-[highlighted]:bg-(--n-soft-hover) data-[highlighted]:text-(--n-accent)","data-[selected]:text-(--n-accent) data-[selected]:font-medium","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","[outline:none]"].join(" ");export const Select=t.forwardRef(function({variant:h="outline",size:b="md",color:w="primary",density:y="default",elevation:V=0,items:z,value:k,defaultValue:O,onValueChange:P,placeholder:R,label:T,description:q,error:C,invalid:M,startIcon:W,fullWidth:_=!1,disabled:B=!1,readOnly:D=!1,required:E=!1,name:L,id:A,className:F,style:G},H){const J=null!=C&&!1!==C&&""!==C,K=M??J,Q=K?"danger":w,U=t.useMemo(()=>z.map(e=>({label:e.label??String(e.value),value:e.value})),[z]),X=t.useMemo(()=>[...z.map(e=>e.label??String(e.value)),...p(R)?[R]:[]],[z,R]);return a(n.Root,{disabled:B,invalid:K,className:["flex-col align-top",N[b],_?"flex w-full":"inline-flex",F??""].filter(Boolean).join(" "),style:{...j(Q,V),...G},children:[T?e(n.Label,{className:[g[b],"font-medium",B?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:T}):null,a(l.Root,{id:A,name:L,items:U,value:k,defaultValue:O,onValueChange:e=>P?.(e),disabled:B,readOnly:D,required:E,children:[a(l.Trigger,{ref:H,className:[I,o[b],d[b],v[b],f[b],x[y][b],B?c[h]:D?`${m[h]} cursor-default`:u[h]].join(" "),children:[W?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:W}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e(l.Value,{className:["w-full truncate text-start","data-[placeholder]:text-(--neba-muted-fg)"].join(" "),placeholder:R}),e(s,{samples:X})]}),e(l.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)","[transition:rotate_var(--neba-duration)_var(--neba-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(l.Portal,{children:e(l.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(l.Popup,{className:`${S} ${v[b]} ${d[b]}`,style:j(Q,3),children:z.map(t=>a(l.Item,{value:t.value,disabled:t.disabled,className:$,children:[e(l.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(l.ItemText,{className:"truncate",children:t.label??String(t.value)})]},String(t.value)))})})})]}),q?e(n.Description,{className:`${g[b]} text-(--neba-muted-fg)`,children:q}):null,J?e(n.Error,{match:!0,className:`${g[b]} text-(--n-accent)`,children:C}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Select}from"./Select";
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Which keyboard the shortcut is being read on.
|
|
5
|
+
*
|
|
6
|
+
* `auto` asks the browser, which is right for a shortcut a reader is about to
|
|
7
|
+
* press. The three explicit values are for documentation that has to name a
|
|
8
|
+
* platform rather than the reader's own — a support page describing the Windows
|
|
9
|
+
* build, a table comparing the two.
|
|
10
|
+
*/
|
|
11
|
+
export type ShortcutOS = 'auto' | 'mac' | 'windows' | 'linux';
|
|
12
|
+
export interface ShortcutProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'span'>, 'color' | 'children'> {
|
|
13
|
+
/**
|
|
14
|
+
* The keys, innermost punctuation and all.
|
|
15
|
+
*
|
|
16
|
+
* A string is split on `+` — `'Mod+Shift+P'` — which covers everything except
|
|
17
|
+
* a shortcut whose key *is* a plus. For that one, pass the array form:
|
|
18
|
+
* `keys={['Ctrl', '+']}`.
|
|
19
|
+
*/
|
|
20
|
+
keys: string | string[];
|
|
21
|
+
/**
|
|
22
|
+
* Which keyboard to name the modifiers for.
|
|
23
|
+
* @default 'auto'
|
|
24
|
+
*/
|
|
25
|
+
os?: ShortcutOS;
|
|
26
|
+
/**
|
|
27
|
+
* What goes between two keys. Omit it for the platform's own convention: a `+`
|
|
28
|
+
* on Windows and Linux, and nothing at all on macOS, where a shortcut is
|
|
29
|
+
* written as a run of symbols — `⇧⌘P`, never `⇧+⌘+P`.
|
|
30
|
+
*/
|
|
31
|
+
separator?: React.ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Drop shadow depth. `0` (the default) is flat. A key cap is the one place a
|
|
34
|
+
* raised surface is tempting and wrong: this is a picture of a key, not a key.
|
|
35
|
+
* @default 0
|
|
36
|
+
*/
|
|
37
|
+
elevation?: NebaElevation;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A keyboard key, or a combination of them.
|
|
41
|
+
*
|
|
42
|
+
* Two things make this more than a styled `<kbd>`, and both are about the label
|
|
43
|
+
* rather than the box around it.
|
|
44
|
+
*
|
|
45
|
+
* The first is `Mod`. A shortcut written as `Ctrl+K` is wrong for every Mac
|
|
46
|
+
* reader and one written as `⌘K` is wrong for everybody else, so the token that
|
|
47
|
+
* means "the modifier shortcuts are built on" resolves per platform — and `os`
|
|
48
|
+
* is there for the pages that have to name a platform rather than the reader's.
|
|
49
|
+
*
|
|
50
|
+
* The second is that `⌘` is not a word. A screen reader reads it as "place of
|
|
51
|
+
* interest sign", so every key drawn as a glyph carries its name beside it, in
|
|
52
|
+
* the clipped box `srOnlyClasses` describes. What is announced is "Command K",
|
|
53
|
+
* which is what the shortcut is called.
|
|
54
|
+
*
|
|
55
|
+
* The keys are real `<kbd>` elements; the wrapper around them is a `<span>`.
|
|
56
|
+
* Nesting `<kbd>` inside `<kbd>` is allowed and would also be defensible, but a
|
|
57
|
+
* `kbd` wrapper is a second box for a host stylesheet to reach into for no gain
|
|
58
|
+
* — the semantics are carried by the keys themselves either way.
|
|
59
|
+
*/
|
|
60
|
+
export declare const Shortcut: React.ForwardRefExoticComponent<ShortcutProps & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as n,Fragment as e,jsxs as a}from"react/jsx-runtime";import*as o from"react";import{controlHeightClasses as t,controlSlots as r,controlTextClasses as l,paddingXClasses as s,radiusClasses as m,srOnlyClasses as i,surfaceClasses as c,transitionClasses as d}from"../../internal/styles";const w=n=>({symbol:n,name:n}),u={mod:{mac:{symbol:"⌘",name:"Command"},windows:w("Ctrl"),linux:w("Ctrl")},meta:{mac:{symbol:"⌘",name:"Command"},windows:w("Win"),linux:w("Super")},ctrl:{mac:{symbol:"⌃",name:"Control"},windows:w("Ctrl"),linux:w("Ctrl")},alt:{mac:{symbol:"⌥",name:"Option"},windows:w("Alt"),linux:w("Alt")},shift:{mac:{symbol:"⇧",name:"Shift"},windows:w("Shift"),linux:w("Shift")},enter:{mac:{symbol:"↩",name:"Enter"},windows:w("Enter"),linux:w("Enter")},tab:{mac:{symbol:"⇥",name:"Tab"},windows:w("Tab"),linux:w("Tab")},escape:{mac:{symbol:"⎋",name:"Escape"},windows:w("Esc"),linux:w("Esc")},backspace:{mac:{symbol:"⌫",name:"Backspace"},windows:w("Backspace"),linux:w("Backspace")},delete:{mac:{symbol:"⌦",name:"Delete"},windows:w("Del"),linux:w("Del")},capslock:{mac:{symbol:"⇪",name:"Caps Lock"},windows:w("Caps Lock"),linux:w("Caps Lock")}},p={cmdorctrl:"mod",commandorcontrol:"mod",cmd:"meta",command:"meta",super:"meta",win:"meta",windows:"meta",control:"ctrl",option:"alt",opt:"alt",return:"enter",esc:"escape",del:"delete",caps:"capslock"},b={up:{symbol:"↑",name:"Arrow up"},down:{symbol:"↓",name:"Arrow down"},left:{symbol:"←",name:"Arrow left"},right:{symbol:"→",name:"Arrow right"},arrowup:{symbol:"↑",name:"Arrow up"},arrowdown:{symbol:"↓",name:"Arrow down"},arrowleft:{symbol:"←",name:"Arrow left"},arrowright:{symbol:"→",name:"Arrow right"}};function f(){if("undefined"==typeof navigator)return"windows";const n=navigator.userAgentData,e=`${n?.platform??""} ${navigator.platform??""} ${navigator.userAgent??""}`;return/mac|iphone|ipad|ipod/i.test(e)?"mac":/win/i.test(e)?"windows":"linux"}function y(){return()=>{}}function x(){return"windows"}const g={xs:"xs",sm:"xs",md:"sm",lg:"md",xl:"lg"},h={solid:[c,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[c,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft)"},v={xs:"min-w-5.5",sm:"min-w-6.5",md:"min-w-8",lg:"min-w-10",xl:"min-w-12"};export const Shortcut=o.forwardRef(function({variant:c="outline",size:A="md",color:k="secondary",density:C="compact",elevation:j=0,keys:E,os:S="auto",separator:B,className:N,style:D,...L},T){const $=o.useSyncExternalStore(y,f,x),F="auto"===S?$:S,z=g[A],O=function(n){return Array.isArray(n)?n.map(n=>n.trim()).filter(Boolean):n.split("+").map(n=>n.trim()).filter(Boolean)}(E),R=O.map(n=>function(n,e){const a=n.toLowerCase().replace(/[\s_-]/g,""),o=p[a]??a,t=b[o];if(t)return t;const r=u[o];return r?r[e]:w(1===n.length?n.toUpperCase():n)}(n,F)),U=void 0===B?"mac"===F?null:"+":B,W=["inline-flex shrink-0 items-center justify-center","font-mono font-medium leading-none whitespace-nowrap tabular-nums",t[z],l[z],v[z],s[C][z],m[z],h[c],d].join(" ");return n("span",{ref:T,className:["inline-flex max-w-full items-center gap-1 align-middle",N??""].filter(Boolean).join(" "),style:{...r(k,j,c),...D},...L,children:R.map((t,r)=>a(o.Fragment,{children:[r>0&&null!==U?n("span",{"aria-hidden":"true",className:"text-(--neba-muted-fg)",children:U}):null,n("kbd",{className:W,children:t.symbol===t.name?t.symbol:a(e,{children:[n("span",{"aria-hidden":"true",children:t.symbol}),n("span",{className:i,children:t.name})]})})]},r))})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Shortcut}from"./Shortcut";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Slider as BaseUISlider } from '@base-ui/react/slider';
|
|
3
|
+
import type { NebaColor, NebaOrientation, NebaSize } from '../../types';
|
|
4
|
+
type BaseSliderProps = Omit<React.ComponentPropsWithoutRef<typeof BaseUISlider.Root>, 'className' | 'style' | 'render' | 'children' | 'orientation'>;
|
|
5
|
+
export interface SliderProps extends BaseSliderProps {
|
|
6
|
+
/** @default 'md' */
|
|
7
|
+
size?: NebaSize;
|
|
8
|
+
/** @default 'primary' */
|
|
9
|
+
color?: NebaColor;
|
|
10
|
+
/**
|
|
11
|
+
* Which way the slider runs. A vertical slider has no length of its own, so
|
|
12
|
+
* give it a height — the default `h-40` is a starting point, not a rule.
|
|
13
|
+
* @default 'horizontal'
|
|
14
|
+
*/
|
|
15
|
+
orientation?: NebaOrientation;
|
|
16
|
+
/** The label above the track. */
|
|
17
|
+
label?: React.ReactNode;
|
|
18
|
+
/** Helper text below the track. */
|
|
19
|
+
description?: React.ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* Shows the current value beside the label. Pass a function to format it —
|
|
22
|
+
* the raw numbers and Base UI's already-localised strings are both handed in.
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
showValue?: boolean | ((formatted: readonly string[], values: readonly number[]) => React.ReactNode);
|
|
26
|
+
/** Class names for the wrapper, not for the track. */
|
|
27
|
+
className?: string;
|
|
28
|
+
style?: React.CSSProperties;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A value chosen along a range.
|
|
32
|
+
*
|
|
33
|
+
* Pass an array to `value` or `defaultValue` and it becomes a range slider with
|
|
34
|
+
* one thumb per entry — there is no separate `range` prop, because the shape of
|
|
35
|
+
* the value already says which one this is.
|
|
36
|
+
*/
|
|
37
|
+
export declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<HTMLDivElement>>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{Slider as r}from"@base-ui/react/slider";import{metaTextClasses as n,surfaceClasses as s,transitionClasses as o}from"../../internal/styles";const t={xs:"h-1",sm:"h-1.5",md:"h-1.5",lg:"h-2",xl:"h-2.5"},i={xs:"w-1",sm:"w-1.5",md:"w-1.5",lg:"w-2",xl:"w-2.5"},c={xs:"size-3",sm:"size-3.5",md:"size-4",lg:"size-5",xl:"size-6"},d={xs:"h-4",sm:"h-4.5",md:"h-5",lg:"h-6",xl:"h-7"},f={xs:"w-4",sm:"w-4.5",md:"w-5",lg:"w-6",xl:"w-7"},u="rounded-full bg-(--n-soft)",m=`rounded-full bg-(--n-fill) ${o}`,h=["rounded-full border bg-(--neba-surface)",s,"[border-color:var(--n-line-hover)]","[box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]","cursor-grab select-none active:cursor-grabbing",o,"hover:[box-shadow:var(--neba-shadow-2),0_0_0_4px_var(--n-soft)]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2","data-[dragging]:[box-shadow:var(--neba-shadow-1),0_0_0_6px_var(--n-soft-hover)]"].join(" ");export const Slider=a.forwardRef(function({size:a="md",color:s="primary",orientation:o="horizontal",label:b,description:x,showValue:v=!1,disabled:g=!1,className:w,style:p,...$},_){const y="vertical"===o,N={"--n-fill":`var(--neba-${s}-fill)`,"--n-accent":`var(--neba-${s}-accent)`,"--n-soft":`var(--neba-${s}-soft)`,"--n-soft-hover":`var(--neba-${s}-soft-hover)`,"--n-line-hover":`var(--neba-${s}-line-hover)`,"--n-ring":`var(--neba-${s}-ring)`},j=$.value??$.defaultValue,z=Array.isArray(j)?j.length:1;return l(r.Root,{ref:_,orientation:o,disabled:g,className:["flex",y?"w-fit flex-col items-center gap-2":"w-full flex-col gap-1.5",g?"[filter:saturate(0.25)] opacity-70 [&_*]:cursor-not-allowed":"",w??""].filter(Boolean).join(" "),style:{...N,...p},...$,children:[b||v?l("div",{className:`flex w-full items-baseline gap-2 ${n[a]}`,children:[b?e(r.Label,{className:g?"font-medium text-(--neba-disabled-fg)":"font-medium text-(--neba-fg)",children:b}):null,v?e(r.Value,{className:"ms-auto tabular-nums text-(--neba-muted-fg)",children:"function"==typeof v?v:null}):null]}):null,e(r.Control,{className:["flex touch-none select-none items-center justify-center",y?`${f[a]} h-40 flex-col`:`w-full ${d[a]}`].join(" "),children:l(r.Track,{className:[u,y?`${i[a]} h-full`:`${t[a]} w-full`].join(" "),children:[e(r.Indicator,{className:m}),Array.from({length:z},(l,n)=>e(r.Thumb,{index:n,className:`${h} ${c[a]}`},n))]})}),x?e("div",{className:`${n[a]} text-(--neba-muted-fg)`,children:x}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Slider}from"./Slider";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type BoxProps } from '../box/Box';
|
|
3
|
+
import type { NebaAlign } from '../../types';
|
|
4
|
+
export interface StatisticProps extends Omit<BoxProps, 'title' | 'prefix'> {
|
|
5
|
+
/**
|
|
6
|
+
* What the number is. The name of the measure, not a sentence about it —
|
|
7
|
+
* "Active users", "MRR", "이탈률".
|
|
8
|
+
*
|
|
9
|
+
* `label` rather than `title`, which is what Card calls the same slot: this is
|
|
10
|
+
* the name of a *value*, which is the thing the library already spells `label`
|
|
11
|
+
* on every field it has.
|
|
12
|
+
*/
|
|
13
|
+
label?: React.ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* The figure. A number is formatted; a string is printed exactly as given, for
|
|
16
|
+
* the values that are not numbers at all — "3h 42m", "A+", "—".
|
|
17
|
+
*/
|
|
18
|
+
value: number | string;
|
|
19
|
+
/**
|
|
20
|
+
* How to write a numeric `value` — `Intl.NumberFormat` options, the same prop
|
|
21
|
+
* the progress indicators take. Without it a number is grouped by the reader's
|
|
22
|
+
* own locale and otherwise left alone.
|
|
23
|
+
*/
|
|
24
|
+
format?: Intl.NumberFormatOptions;
|
|
25
|
+
/** Set before the figure and never wrapped away from it — a currency sign. */
|
|
26
|
+
prefix?: React.ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* Set after the figure: `%`, `MB`, `명`.
|
|
29
|
+
*
|
|
30
|
+
* A second slot rather than one `adornment` with a side, because the two are
|
|
31
|
+
* typographically different things and always have been — a currency symbol
|
|
32
|
+
* leads its number and a unit follows it, in every locale that has both.
|
|
33
|
+
*/
|
|
34
|
+
unit?: React.ReactNode;
|
|
35
|
+
/** A glyph before the label. An `Icon`, or anything else that draws. */
|
|
36
|
+
icon?: React.ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* The figure this one is being compared against — last month's, last quarter's,
|
|
39
|
+
* the target. Passing it is what makes the delta appear.
|
|
40
|
+
*
|
|
41
|
+
* Only meaningful for a numeric `value`; with a string there is nothing to
|
|
42
|
+
* subtract and the delta is left out.
|
|
43
|
+
*/
|
|
44
|
+
previousValue?: number;
|
|
45
|
+
/**
|
|
46
|
+
* How the difference is written.
|
|
47
|
+
*
|
|
48
|
+
* - `percent` — the change relative to `previousValue`. The default, because a
|
|
49
|
+
* report is nearly always asking "how much has this moved", not "by how many".
|
|
50
|
+
* - `absolute` — the difference itself, in the figure's own units.
|
|
51
|
+
* - `both` — the percentage with the difference after it.
|
|
52
|
+
* - `none` — no delta, even with a `previousValue` given.
|
|
53
|
+
* @default 'percent'
|
|
54
|
+
*/
|
|
55
|
+
delta?: 'percent' | 'absolute' | 'both' | 'none';
|
|
56
|
+
/**
|
|
57
|
+
* Which direction counts as good, and so which way the delta is coloured.
|
|
58
|
+
*
|
|
59
|
+
* `up` for revenue, `down` for churn and error rate and page weight. This is
|
|
60
|
+
* not decoration: green-for-larger on a bounce rate says the opposite of what
|
|
61
|
+
* the report means, and it says it to exactly the reader who is skimming.
|
|
62
|
+
* @default 'up'
|
|
63
|
+
*/
|
|
64
|
+
betterWhen?: 'up' | 'down';
|
|
65
|
+
/** A line under the figure — "vs. last month", "as of 3 July". */
|
|
66
|
+
caption?: React.ReactNode;
|
|
67
|
+
/**
|
|
68
|
+
* Where the block sits in the card. `center` for a row of tiles that read as
|
|
69
|
+
* one band; `start` — the default — for a card with anything else in it.
|
|
70
|
+
* @default 'start'
|
|
71
|
+
*/
|
|
72
|
+
align?: NebaAlign;
|
|
73
|
+
/** Anything below the caption: a sparkline, a ProgressLinear against a target. */
|
|
74
|
+
children?: React.ReactNode;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A number with its name on it, and — when there is something to compare it
|
|
78
|
+
* against — how far it has moved.
|
|
79
|
+
*
|
|
80
|
+
* A Box with a fixed arrangement laid on it, exactly as Card is. The slots are
|
|
81
|
+
* props and not compound sub-components for the reason Card gives: the order
|
|
82
|
+
* never varies, so what a caller wants to decide is what goes in each slot.
|
|
83
|
+
*
|
|
84
|
+
* The delta is a Chip rather than a coloured span, and that is the whole reason
|
|
85
|
+
* it looks right next to everything else — it is the same token the rest of the
|
|
86
|
+
* library uses, at the same step down the control ladder, with the same acrylic
|
|
87
|
+
* on it. It also carries a shape and not only a colour: a report whose "down" is
|
|
88
|
+
* red and nothing else is a report that says nothing to a reader who cannot
|
|
89
|
+
* separate red from green.
|
|
90
|
+
*/
|
|
91
|
+
export declare const Statistic: React.ForwardRefExoticComponent<StatisticProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Box as n}from"../box/Box";import{Chip as a}from"../chip/Chip";import{MinusIcon as r,TrendDownIcon as s,TrendUpIcon as m}from"../../internal/icons";import{hasContent as i,metaTextClasses as o,sheetSectionGapClasses as c}from"../../internal/styles";const u={xs:"text-[1.125rem]/[1.375rem]",sm:"text-[1.375rem]/[1.625rem]",md:"text-[1.75rem]/[2rem]",lg:"text-[2.25rem]/[2.5rem]",xl:"text-[2.875rem]/[3.25rem]"},d={xs:"text-[0.75rem]",sm:"text-[0.875rem]",md:"text-[1rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},x={xs:"gap-y-0.5",sm:"gap-y-0.5",md:"gap-y-1",lg:"gap-y-1",xl:"gap-y-1.5"},f={start:"items-start text-start",center:"items-center text-center",end:"items-end text-end"},p={up:e(m,{}),down:e(s,{}),flat:e(r,{})};export const Statistic=l.forwardRef(function({size:r="md",color:s="primary",density:m="default",label:b,value:h,format:g,prefix:w,unit:N,icon:y,previousValue:v,delta:$="percent",betterWhen:j="up",caption:M,align:z="start",className:B,children:k,...F},I){const C=l.useMemo(()=>new Intl.NumberFormat(void 0,g),[g]),R="number"==typeof h?h:null,S=null===R?h:C.format(R),V=null!==R&&void 0!==v?R-v:null,W=null!==V&&0!==v&&void 0!==v?V/Math.abs(v):null,q=null===V?null:V>0?"up":V<0?"down":"flat";let A=null;if(null!==V&&null!==q&&"none"!==$){const e=V>0?"+":V<0?"-":"",t=`${e}${C.format(Math.abs(V))}`,l=null===W?null:`${e}${(100*Math.abs(W)).toFixed(1).replace(/\.0$/,"")}%`;A="absolute"===$?t:"both"===$?[l,t].filter(Boolean).join(" · "):l??t}const D=null===q||"flat"===q?"secondary":q===j?"success":"danger",E=null!==A||i(M);return t(n,{ref:I,size:r,color:s,density:m,className:["flex flex-col",c[r],f[z],B??""].filter(Boolean).join(" "),...F,children:[i(b)||i(y)?t("div",{className:["flex min-w-0 items-center gap-1.5 font-medium text-(--neba-muted-fg)",o[r]].join(" "),children:[i(y)?e("span",{className:"flex shrink-0 items-center",children:y}):null,i(b)?e("span",{className:"min-w-0 truncate",children:b}):null]}):null,t("div",{className:["flex min-w-0 flex-wrap items-baseline gap-1 font-semibold text-(--neba-fg) tabular-nums",u[r]].join(" "),children:[i(w)?e("span",{className:`font-medium text-(--neba-muted-fg) ${d[r]}`,children:w}):null,e("span",{className:"min-w-0 break-words",children:S}),i(N)?e("span",{className:`font-medium text-(--neba-muted-fg) ${d[r]}`,children:N}):null]}),E?t("div",{className:`flex min-w-0 flex-wrap items-center gap-x-2 ${x[r]}`,children:[null!==A&&null!==q?e(a,{size:r,variant:"text",color:D,startIcon:p[q],className:"tabular-nums",children:A}):null,i(M)?e("span",{className:`min-w-0 text-(--neba-muted-fg) ${o[r]}`,children:M}):null]}):null,k]})});
|