neba 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -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/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/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/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 +48 -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/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/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/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/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/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/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/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 +32 -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/icons.d.ts +48 -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/progress.d.ts +122 -0
- package/dist/internal/progress.js +1 -0
- package/dist/internal/styles.d.ts +224 -0
- package/dist/internal/styles.js +1 -0
- package/dist/styles.css +758 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.js +8 -0
- package/package.json +75 -19
- package/pnpm-workspace.yaml +0 -2
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps } from '../../types';
|
|
3
|
+
export interface PaginationProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'nav'>, 'color' | 'onChange'> {
|
|
4
|
+
/** How many pages there are. Fewer than two and the whole control renders nothing. */
|
|
5
|
+
count: number;
|
|
6
|
+
/** The current page, 1-based. Use with `onPageChange` for a controlled set. */
|
|
7
|
+
page?: number;
|
|
8
|
+
/** Which page starts current, for an uncontrolled one. @default 1 */
|
|
9
|
+
defaultPage?: number;
|
|
10
|
+
onPageChange?: (page: number) => void;
|
|
11
|
+
/**
|
|
12
|
+
* How many pages are always shown on either side of the current one.
|
|
13
|
+
* @default 1
|
|
14
|
+
*/
|
|
15
|
+
siblingCount?: number;
|
|
16
|
+
/**
|
|
17
|
+
* How many pages are always shown at each end, whatever the current page is.
|
|
18
|
+
* `0` drops the first and last page from the row, leaving only the window.
|
|
19
|
+
* @default 1
|
|
20
|
+
*/
|
|
21
|
+
boundaryCount?: number;
|
|
22
|
+
/** Shows the jump-to-first and jump-to-last steppers. @default false */
|
|
23
|
+
showEdges?: boolean;
|
|
24
|
+
/** Shows the previous and next steppers. @default true */
|
|
25
|
+
showArrows?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Drop shadow depth of the page buttons. `0` (the default) is flat.
|
|
28
|
+
* @default 0
|
|
29
|
+
*/
|
|
30
|
+
elevation?: NebaElevation;
|
|
31
|
+
/** Unavailable. Every button in the row stops answering. */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/** Accessible name of the `<nav>`. @default 'Pagination' */
|
|
34
|
+
label?: string;
|
|
35
|
+
/** Accessible name of a page button. @default `Page ${page}` */
|
|
36
|
+
pageLabel?: (page: number) => string;
|
|
37
|
+
/** @default 'Previous page' */
|
|
38
|
+
previousLabel?: string;
|
|
39
|
+
/** @default 'Next page' */
|
|
40
|
+
nextLabel?: string;
|
|
41
|
+
/** @default 'First page' */
|
|
42
|
+
firstLabel?: string;
|
|
43
|
+
/** @default 'Last page' */
|
|
44
|
+
lastLabel?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A row of page numbers.
|
|
48
|
+
*
|
|
49
|
+
* Every button in it is a real `Button`, which is the point: a pagination is not
|
|
50
|
+
* a new kind of control, it is buttons in a row that happen to know about each
|
|
51
|
+
* other. Reusing the component means the row inherits the acrylic surface, the
|
|
52
|
+
* press-instant/release-slow signature, the focus ring and every future change
|
|
53
|
+
* to any of them for free — and it means a `lg` pagination lines up with a `lg`
|
|
54
|
+
* button beside it, because it *is* one.
|
|
55
|
+
*
|
|
56
|
+
* `variant` sets how the pages at rest look; the current page is always `solid`,
|
|
57
|
+
* which is the one thing the row has to say without being read. That is why the
|
|
58
|
+
* default here is `text` rather than the `solid` a lone Button takes — nine
|
|
59
|
+
* filled buttons in a row say that all nine are the primary action.
|
|
60
|
+
*
|
|
61
|
+
* The markup is a `<nav>` around a `<ul>` because that is what a screen reader
|
|
62
|
+
* needs to hear: a named landmark it can skip, holding a list whose length says
|
|
63
|
+
* how far the pages go, with `aria-current="page"` marking where it is.
|
|
64
|
+
*/
|
|
65
|
+
export declare const Pagination: React.ForwardRefExoticComponent<PaginationProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Button as n}from"../button/Button";import{ChevronIcon as i}from"../../internal/icons";import{controlTextClasses as r,gapClasses as l,srOnlyClasses as o}from"../../internal/styles";function s(e,t){return Array.from({length:Math.max(0,t-e+1)},(t,a)=>e+a)}function m(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const c={xs:"h-5.5 min-w-5.5",sm:"h-6.5 min-w-6.5",md:"h-8 min-w-8",lg:"h-10 min-w-10",xl:"h-12 min-w-12"};export const Pagination=a.forwardRef(function({variant:d="text",size:u="md",color:h="primary",density:f="compact",elevation:p=0,count:x,page:g,defaultPage:b=1,onPageChange:v,siblingCount:M=1,boundaryCount:w=1,showEdges:N=!1,showArrows:y=!0,disabled:L=!1,label:j="Pagination",pageLabel:$=e=>`Page ${e}`,previousLabel:k="Previous page",nextLabel:C="Next page",firstLabel:P="First page",lastLabel:z="Last page",className:B,children:A,...E},F){const[I,R]=a.useState(b),S=Math.min(Math.max(g??I,1),Math.max(x,1)),W=e=>{const t=Math.min(Math.max(e,1),x);t!==S&&(void 0===g&&R(t),v?.(t))};if(x<2)return null;const q=function(e,t,a,n){const i=s(1,Math.min(n,e)),r=s(Math.max(e-n+1,n+1),e),l=Math.max(Math.min(t-a,e-n-2*a-1),n+2),o=Math.min(Math.max(t+a,n+2*a+2),r.length>0?r[0]-2:e-1);return[...i,...l>n+2?["start-ellipsis"]:n+1<e-n?[n+1]:[],...s(l,o),...o<e-n-1?["end-ellipsis"]:e-n>n?[e-n]:[],...r]}(x,S,M,w),D=S<=1,G=S>=x,H=(t,a,i,r,l,o)=>e("li",{className:"flex",children:e(n,{variant:d,size:u,color:h,density:f,elevation:p,disabled:L||r,"aria-label":a,startIcon:e("span",{className:`flex items-center ${l}`,children:o}),onClick:()=>W(i)})},t);return t("nav",{ref:F,"aria-label":j,className:["flex items-center",B??""].filter(Boolean).join(" "),...E,children:[t("ul",{role:"list",className:`m-0 flex list-none items-center p-0 ${l[u]}`,children:[N?H("first",P,1,D,"rotate-180 rtl:rotate-0",e(m,{})):null,y?H("previous",k,S-1,D,"rotate-90 rtl:-rotate-90",e(i,{})):null,q.map((t,a)=>"number"==typeof t?e("li",{className:"flex",children:e(n,{variant:t===S?"solid":d,size:u,color:h,density:f,elevation:p,disabled:L,"aria-label":$(t),"aria-current":t===S?"page":void 0,className:"tabular-nums",onClick:()=>W(t),children:t})},t):e("li",{"aria-hidden":"true",className:["flex select-none items-center justify-center","text-(--neba-muted-fg)",r[u],c[u]].join(" "),children:"…"},`${t}-${a}`)),y?H("next",C,S+1,G,"-rotate-90 rtl:rotate-90",e(i,{})):null,N?H("last",z,x,G,"rtl:rotate-180",e(m,{})):null]}),e("span",{className:o,"aria-live":"polite",children:`${$(S)} of ${x}`}),A]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Pagination}from"./Pagination";
|
|
@@ -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,tickSizeClasses as d,transitionClasses as c}from"../../internal/styles";const b=r.createContext({size:"md",color:"primary",readOnly:!1}),f=["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",c,"active:[transition-duration:0ms]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),h=[s,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)]","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]:[box-shadow:var(--neba-plate-solid)]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),p=[s,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)] [filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),m=["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:c=!1,className:u,style:v,...x},g){const y=r.useContext(b),N=x.readOnly??y.readOnly;return e(o.Root,{disabled:c,className:["flex flex-col",u??""].filter(Boolean).join(" "),style:v,children:a("div",{className:`flex items-start gap-2 ${i[y.size]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(n.Root,{ref:g,className:[f,d[y.size],c?m:N?p:h].join(" "),disabled:c,...x,children:e(n.Indicator,{className:"size-[38%] rounded-full bg-current"})})}),l||s?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[l?e(o.Label,{className:["leading-[1.4]",c?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:l}):null,s?e(o.Description,{className:`${t[y.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:f,invalid:h,disabled:p=!1,readOnly:m=!1,className:u,style:v,children:x,...g},y){const N=null!=f&&!1!==f&&""!==f,j=h??N,k=j?"danger":i,w={"--n-fill":`var(--neba-${k}-fill)`,"--n-fill-hover":`var(--neba-${k}-fill-hover)`,"--n-on-solid":`var(--neba-${k}-on-solid)`,"--n-accent":`var(--neba-${k}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${k}-line)`,"--n-line-hover":`var(--neba-${k}-line-hover)`,"--n-ring":`var(--neba-${k}-ring)`},$=r.useMemo(()=>({size:n,color:k,readOnly:m}),[n,k,m]);return e(b.Provider,{value:$,children:a(o.Root,{disabled:p,invalid:j,className:["flex flex-col gap-1.5",u??""].filter(Boolean).join(" "),style:{...w,...v},children:[d?e(o.Label,{className:[t[n],"font-medium",p?"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:p,readOnly:m,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:f}):null]})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Radio,RadioGroup}from"./RadioGroup";
|
|
@@ -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{controlHeightClasses as o,controlTextLeadingClasses as s,disabledClasses as d,fieldReadOnlyClasses as c,fieldRestClasses as u,focusWithinRingClasses as m,gapClasses as h,iconClasses as f,metaTextClasses as p,paddingXClasses as b,radiusClasses as g,stackGapClasses as x,surfaceClasses as v,surfaceSlots as N,transitionClasses as j}from"../../internal/styles";const w=["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",j,"focus-within:[transition-duration:0ms]",m,f].join(" "),y=[v,"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(" "),I=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",j,"data-[highlighted]:bg-(--n-soft-hover)","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:m="outline",size:f="md",color:v="primary",density:j="default",elevation:$=0,items:S,value:V,defaultValue:k,onValueChange:z,placeholder:O,label:P,description:R,error:T,invalid:q,startIcon:C,fullWidth:W=!1,disabled:_=!1,readOnly:B=!1,required:D=!1,name:E,id:L,className:M,style:A},F){const G=null!=T&&!1!==T&&""!==T,H=q??G,J=H?"danger":v,K=t.useMemo(()=>S.map(e=>({label:e.label??String(e.value),value:e.value})),[S]);return a(n.Root,{disabled:_,invalid:H,className:["flex-col align-top",x[f],W?"flex w-full":"inline-flex",M??""].filter(Boolean).join(" "),style:{...N(J,$),...A},children:[P?e(n.Label,{className:[p[f],"font-medium",_?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:P}):null,a(l.Root,{id:L,name:E,items:K,value:V,defaultValue:k,onValueChange:e=>z?.(e),disabled:_,readOnly:B,required:D,children:[a(l.Trigger,{ref:F,className:[w,o[f],s[f],g[f],h[f],b[j][f],_?d[m]:B?`${c[m]} cursor-default`:u[m]].join(" "),children:[C?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:C}):null,e(l.Value,{className:["min-w-0 flex-1 truncate text-start","data-[placeholder]:text-(--neba-muted-fg)"].join(" "),placeholder:O}),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:`${y} ${g[f]} ${s[f]}`,children:S.map(t=>a(l.Item,{value:t.value,disabled:t.disabled,className:I,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)))})})})]}),R?e(n.Description,{className:`${p[f]} text-(--neba-muted-fg)`,children:R}):null,G?e(n.Error,{match:!0,className:`${p[f]} text-(--n-accent)`,children:T}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Select}from"./Select";
|
|
@@ -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,39 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Switch as BaseUISwitch } from '@base-ui/react/switch';
|
|
3
|
+
import type { NebaColor, NebaSize } from '../../types';
|
|
4
|
+
/** Which side of the track the label sits on. */
|
|
5
|
+
export type SwitchLabelPlacement = 'start' | 'end';
|
|
6
|
+
type BaseSwitchProps = Omit<React.ComponentPropsWithoutRef<typeof BaseUISwitch.Root>, 'className' | 'style' | 'render' | 'children'>;
|
|
7
|
+
export interface SwitchProps extends BaseSwitchProps {
|
|
8
|
+
/** @default 'md' */
|
|
9
|
+
size?: NebaSize;
|
|
10
|
+
/** @default 'primary' */
|
|
11
|
+
color?: NebaColor;
|
|
12
|
+
/** The text beside the track. Wired to it by Base UI's Field. */
|
|
13
|
+
label?: React.ReactNode;
|
|
14
|
+
/** Helper text under the label. */
|
|
15
|
+
description?: React.ReactNode;
|
|
16
|
+
/** Error message below. Its presence also turns the switch invalid. */
|
|
17
|
+
error?: React.ReactNode;
|
|
18
|
+
/** Forces the invalid state without a message. Defaults to `!!error`. */
|
|
19
|
+
invalid?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Which side the label sits on. `end` reads as a caption for the control;
|
|
22
|
+
* `start` is for a settings list, where the labels form a column and every
|
|
23
|
+
* switch lines up on the right.
|
|
24
|
+
* @default 'end'
|
|
25
|
+
*/
|
|
26
|
+
labelPlacement?: SwitchLabelPlacement;
|
|
27
|
+
/** Class names for the field wrapper, not for the track. */
|
|
28
|
+
className?: string;
|
|
29
|
+
style?: React.CSSProperties;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* An immediate on/off.
|
|
33
|
+
*
|
|
34
|
+
* The difference from a Checkbox is not visual, it is temporal: a checkbox is a
|
|
35
|
+
* value that gets submitted with a form, a switch takes effect the moment it
|
|
36
|
+
* moves. If there is a Save button underneath, it should have been a checkbox.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Switch: React.ForwardRefExoticComponent<SwitchProps & React.RefAttributes<HTMLElement>>;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as a,Fragment as r}from"react/jsx-runtime";import*as n from"react";import{Switch as l}from"@base-ui/react/switch";import{Field as o}from"@base-ui/react/field";import{controlTextClasses as t,metaTextClasses as i,surfaceClasses as c}from"../../internal/styles";const s={xs:"h-3.5 w-6",sm:"h-4 w-7",md:"h-5 w-9",lg:"h-6 w-11",xl:"h-7 w-13"},d={xs:"data-[checked]:left-[calc(100%-0.75rem)]",sm:"data-[checked]:left-[calc(100%-0.875rem)]",md:"data-[checked]:left-[calc(100%-1.125rem)]",lg:"data-[checked]:left-[calc(100%-1.375rem)]",xl:"data-[checked]:left-[calc(100%-1.625rem)]"},b=["relative inline-flex shrink-0 border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","rounded-full","[transition-property:background-color,border-color,box-shadow]","[transition-duration:var(--neba-duration-fill),var(--neba-duration),var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),h=[c,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)]","hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","data-[checked]:bg-(--n-fill) data-[checked]:[border-color:transparent]","data-[checked]:[box-shadow:var(--neba-plate-solid)]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),f=[c,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)] [filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:[border-color:transparent]"].join(" "),m=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)] shadow-none","data-[checked]:bg-(--neba-disabled-bg)"].join(" "),v=["absolute inset-y-0.5 left-0.5 aspect-square rounded-full bg-(--neba-surface)","[box-shadow:var(--neba-shadow-1)]","[transition:left_var(--neba-duration)_var(--neba-ease)]"].join(" ");export const Switch=n.forwardRef(function({size:n="md",color:c="primary",label:u,description:p,error:g,invalid:x,labelPlacement:w="end",disabled:k=!1,readOnly:j=!1,className:$,style:N,...y},_){const R=null!=g&&!1!==g&&""!==g,B=x??R,O=B?"danger":c,S={"--n-fill":`var(--neba-${O}-fill)`,"--n-fill-hover":`var(--neba-${O}-fill-hover)`,"--n-accent":`var(--neba-${O}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${O}-line)`,"--n-line-hover":`var(--neba-${O}-line-hover)`,"--n-ring":`var(--neba-${O}-ring)`},q=e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:_,className:[b,s[n],k?m:j?f:h].join(" "),disabled:k,readOnly:j,...y,children:e(l.Thumb,{className:`${v} ${d[n]}`})})}),z=u||p?a("span",{className:["flex min-w-0 flex-col gap-0.5","start"===w?"flex-1":""].filter(Boolean).join(" "),children:[u?e(o.Label,{className:["leading-[1.4]",k?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:u}):null,p?e(o.Description,{className:`${i[n]} text-(--neba-muted-fg)`,children:p}):null]}):null;return a(o.Root,{disabled:k,invalid:B,className:["inline-flex flex-col gap-1 align-top",$??""].filter(Boolean).join(" "),style:{...S,...N},children:[e("div",{className:`flex items-start gap-2.5 ${t[n]}`,children:a(r,"start"===w?{children:[z,q]}:{children:[q,z]})}),R?e(o.Error,{match:!0,className:`${i[n]} text-(--n-accent)`,children:g}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Switch}from"./Switch";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type BoxProps } from '../box/Box';
|
|
3
|
+
import type { NebaAlign } from '../../types';
|
|
4
|
+
/** Which edge the text in a column lines up against. */
|
|
5
|
+
export type TableAlign = NebaAlign;
|
|
6
|
+
/**
|
|
7
|
+
* A column: its heading, its default width, and how to get a cell out of a row.
|
|
8
|
+
*
|
|
9
|
+
* This is the whole reason Table takes data rather than markup. A `<td>` written
|
|
10
|
+
* out per row can silently disagree with the `<th>` above it about how many
|
|
11
|
+
* there are or what order they come in; a column list cannot.
|
|
12
|
+
*/
|
|
13
|
+
export interface TableColumn<Row> {
|
|
14
|
+
/**
|
|
15
|
+
* Identifies the column, and — unless `render` says otherwise — names the
|
|
16
|
+
* property to read off each row.
|
|
17
|
+
*/
|
|
18
|
+
key: string;
|
|
19
|
+
/** The heading. Defaults to the `key`, which is usually not what you want. */
|
|
20
|
+
label?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* The column's default width. A number is pixels; a string is any CSS length
|
|
23
|
+
* (`'30%'`, `'12rem'`, `'minmax(...)'` is not — this is a `<col>`, not a grid).
|
|
24
|
+
*
|
|
25
|
+
* "Default" is meant: the table still balances the columns to fill its width,
|
|
26
|
+
* so this is a starting proportion rather than a guarantee.
|
|
27
|
+
*/
|
|
28
|
+
width?: number | string;
|
|
29
|
+
/**
|
|
30
|
+
* Text alignment. Numbers usually want `end` so their digits line up in a
|
|
31
|
+
* column; everything else wants `start`.
|
|
32
|
+
* @default 'start'
|
|
33
|
+
*/
|
|
34
|
+
align?: TableAlign;
|
|
35
|
+
/**
|
|
36
|
+
* Renders the cell. Without it the cell is `row[key]` rendered as-is, which
|
|
37
|
+
* covers strings and numbers and nothing else.
|
|
38
|
+
*/
|
|
39
|
+
render?: (row: Row, index: number) => React.ReactNode;
|
|
40
|
+
}
|
|
41
|
+
export interface TableProps<Row> extends Omit<BoxProps, 'padded' | 'children' | 'render' | 'title'> {
|
|
42
|
+
/** The columns, in the order they appear. */
|
|
43
|
+
headers: readonly TableColumn<Row>[];
|
|
44
|
+
/** The rows. */
|
|
45
|
+
items: readonly Row[];
|
|
46
|
+
/**
|
|
47
|
+
* A stable key per row. Defaults to the row's index, which is fine for a
|
|
48
|
+
* static table and wrong for one that sorts or filters.
|
|
49
|
+
*/
|
|
50
|
+
getRowKey?: (row: Row, index: number) => React.Key;
|
|
51
|
+
/** Shown above the table, and read out as its accessible name. */
|
|
52
|
+
caption?: React.ReactNode;
|
|
53
|
+
/** What to show instead of rows when `items` is empty. */
|
|
54
|
+
empty?: React.ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* Tints every other row. Useful for a wide table where the eye has to track
|
|
57
|
+
* across; noise on a narrow one.
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
striped?: boolean;
|
|
61
|
+
/** Lights the row under the pointer. @default false */
|
|
62
|
+
hoverable?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Pins the header while the body scrolls. Only does anything if something
|
|
65
|
+
* around the table actually constrains its height.
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
stickyHeader?: boolean;
|
|
69
|
+
/** Makes rows activatable. Also turns on the hover treatment. */
|
|
70
|
+
onRowClick?: (row: Row, index: number) => void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A grid of data.
|
|
74
|
+
*
|
|
75
|
+
* The sheet is a Box — `variant`, `size`, `color`, `density` and `elevation` all
|
|
76
|
+
* pass straight through, so a table is styled on the same axes as everything it
|
|
77
|
+
* might sit next to. What Table adds is the part that is genuinely tabular: the
|
|
78
|
+
* columns, the rows, and the fact that the two cannot drift apart.
|
|
79
|
+
*/
|
|
80
|
+
export declare function Table<Row>({ headers, items, getRowKey, caption, empty, striped, hoverable, stickyHeader, onRowClick, size, density, className, ...boxProps }: TableProps<Row>): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{Box as r}from"../box/Box";import{controlTextLeadingClasses as a,metaTextClasses as l,paddingXValues as n}from"../../internal/styles";const o={default:{xs:"0.25rem",sm:"0.375rem",md:"0.625rem",lg:"0.75rem",xl:"0.875rem"},compact:{xs:"0.125rem",sm:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.625rem"}},s=["[--n-row:transparent]","[transition:background-color_var(--neba-duration)_var(--neba-ease)]"].join(" "),i={borderTop:"1px solid var(--n-line)",backgroundColor:"var(--n-row)"};export function Table({headers:d,items:c,getRowKey:m,caption:p,empty:h,striped:b=!1,hoverable:x=!1,stickyHeader:y=!1,onRowClick:g,size:f="md",density:u="default",className:v,...w}){const k=n[u][f],N=o[u][f],j=Boolean(g),$=x||j,B={padding:`${N} ${k}`},C={...B,backgroundColor:"var(--n-panel-press)"};return e(r,{size:f,density:u,padded:!1,className:["overflow-x-auto",v??""].filter(Boolean).join(" "),...w,children:t("table",{className:`w-full text-start ${a[f]} text-(--neba-fg)`,style:{borderCollapse:"collapse"},children:[p?e("caption",{className:`${l[f]} text-(--neba-muted-fg)`,style:{...B,textAlign:"start"},children:p}):null,e("colgroup",{children:d.map(t=>e("col",{style:void 0===t.width?void 0:{width:"number"==typeof t.width?`${t.width}px`:t.width}},t.key))}),e("thead",{children:e("tr",{children:d.map(t=>e("th",{scope:"col",className:["font-semibold whitespace-nowrap text-(--neba-muted-fg)",y?"sticky top-0 z-10 [backdrop-filter:var(--neba-blur)]":""].filter(Boolean).join(" "),style:{...C,textAlign:t.align??"start"},children:t.label??t.key},t.key))})}),e("tbody",{children:0===c.length?e("tr",{className:s,style:i,children:e("td",{colSpan:d.length,className:"text-(--neba-muted-fg)",style:{padding:`2rem ${k}`,textAlign:"center"},children:h??"No data"})}):c.map((t,r)=>e("tr",{className:[s,b&&r%2==1?"[--n-row:var(--n-panel-hover)]":"",$?"hover:[--n-row:var(--n-soft)]":"",j?"cursor-pointer":""].filter(Boolean).join(" "),style:i,onClick:g?()=>g(t,r):void 0,children:d.map(a=>e("td",{style:{...B,textAlign:a.align??"start"},children:a.render?a.render(t,r):t[a.key]},a.key))},m?m(t,r):r))})]})})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Table}from"./Table";
|