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
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as t from"react";import{Button as n}from"@base-ui/react/button";import{ButtonGroupContext as r}from"../../internal/button-group";import{controlHeightClasses as a,controlSlots as l,controlSquareClasses as s,controlTextClasses as i,disabledClasses as d,focusRingClasses as v,gapClasses as c,iconClasses as p,paddingXClasses as x,pressTransitionClasses as b,radiusClasses as u,readOnlyFilterClasses as m,surfaceClasses as g,transitionClasses as h}from"../../internal/styles";const f={xs:`${a.xs} ${c.xs} ${u.xs} ${i.xs}`,sm:`${a.sm} ${c.sm} ${u.sm} ${i.sm}`,md:`${a.md} ${c.md} ${u.md} ${i.md}`,lg:`${a.lg} ${c.lg} ${u.lg} ${i.lg}`,xl:`${a.xl} ${c.xl} ${u.xl} ${i.xl}`},$={xs:`${s.xs} px-0`,sm:`${s.sm} px-0`,md:`${s.md} px-0`,lg:`${s.lg} px-0`,xl:`${s.xl} px-0`},y=["relative inline-flex shrink-0 select-none items-center justify-center","whitespace-nowrap align-middle font-medium leading-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",h,b,v,p].join(" "),w={solid:[g,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[g,"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-transparent"},j={solid:["hover:bg-(--n-fill-hover)","hover:[box-shadow:var(--n-elev-hover),var(--neba-plate-solid)]","active:bg-(--n-fill-active)","active:[box-shadow:var(--n-elev-press),var(--neba-plate-solid)]"].join(" "),outline:["hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","hover:[box-shadow:var(--n-elev-hover),var(--neba-plate-glass)]","active:bg-(--n-panel-press)","active:[box-shadow:var(--n-elev-press),var(--neba-plate-glass)]"].join(" "),text:"hover:bg-(--n-soft) active:bg-(--n-soft-hover)"},k={solid:[g,m,"cursor-default text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--neba-plate-solid)]"].join(" "),outline:[g,m,"cursor-default border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)] [box-shadow:var(--neba-plate-glass)]"].join(" "),text:`${m} cursor-default text-(--n-accent) bg-transparent`};function C(){return o("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",className:"animate-spin",children:[e("circle",{cx:"8",cy:"8",r:"6.5",stroke:"currentColor",strokeOpacity:"0.25",strokeWidth:"2"}),e("path",{d:"M14.5 8A6.5 6.5 0 0 0 8 1.5",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]})}export const Button=t.forwardRef(function({variant:a,size:s,color:i,density:v,elevation:c,startIcon:p,endIcon:b,loading:u=!1,readOnly:m=!1,fullWidth:g=!1,disabled:h,className:P,style:B,children:M,onClick:N,onPointerMove:W,...z},E){const I=t.useContext(r),O=a??I?.variant??"solid",A=s??I?.size??"md",D=i??I?.color??"primary",L=v??I?.density??"default",R=c??I?.elevation??0,T=h??I?.disabled??!1,X=null==M||!1===M,Y=u||m,q=[y,f[A],X?$[A]:x[L][A],T?d[O]:m?k[O]:w[O],T||Y?"":[j[O],"neba-glow","cursor-pointer"].join(" "),u?"cursor-progress":"",g?"w-full":"",P??""].filter(Boolean).join(" ");return o(n,{ref:E,disabled:T,className:q,style:{...l(D,R,O),...B},"aria-disabled":Y||void 0,"aria-busy":u||void 0,"data-loading":u||void 0,"data-readonly":m||void 0,onClick:e=>{if(Y)return e.preventDefault(),void e.stopPropagation();N?.(e)},onPointerMove:e=>{const o=e.currentTarget;o.style.setProperty("--n-mx",`${e.nativeEvent.offsetX}px`),o.style.setProperty("--n-my",`${e.nativeEvent.offsetY}px`),W?.(e)},...z,children:[u?e(C,{}):p,M,b]})});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaOrientation, NebaStyleProps } from '../../types';
|
|
3
|
+
export interface ButtonGroupProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
4
|
+
/**
|
|
5
|
+
* Which way the buttons run. A vertical group is for a stacked menu of equal
|
|
6
|
+
* actions; a horizontal one is the default because that is what a toolbar is.
|
|
7
|
+
* @default 'horizontal'
|
|
8
|
+
*/
|
|
9
|
+
orientation?: NebaOrientation;
|
|
10
|
+
/** Drop shadow depth, passed to every button in the group. @default 0 */
|
|
11
|
+
elevation?: NebaElevation;
|
|
12
|
+
/** Disables every button in the group at once. */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** Stretches to the container and divides the width evenly between buttons. */
|
|
15
|
+
fullWidth?: boolean;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A row of buttons that belong together.
|
|
20
|
+
*
|
|
21
|
+
* Two things are happening here, and only one of them is visual. The corners
|
|
22
|
+
* that face a neighbour are squared off — that is the look. The other half is
|
|
23
|
+
* that `variant`, `size`, `color`, `density`, `elevation` and `disabled` are set
|
|
24
|
+
* once for the set rather than repeated on every button; a group where one
|
|
25
|
+
* button is a size out is the failure this exists to prevent.
|
|
26
|
+
*
|
|
27
|
+
* The buttons stay real `<Button>`s. This is not a segmented control and it does
|
|
28
|
+
* not manage selection — for one-of-a-set use a RadioGroup, which is what that
|
|
29
|
+
* actually is.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ButtonGroup: React.ForwardRefExoticComponent<ButtonGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as o}from"react/jsx-runtime";import*as e from"react";import{ButtonGroupContext as i}from"../../internal/button-group";const n={horizontal:"[&>*:not(:first-child)]:rounded-s-none [&>*:not(:last-child)]:rounded-e-none",vertical:"[&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none"},r={horizontal:"[&>*:not(:first-child)]:-ms-px",vertical:"[&>*:not(:first-child)]:-mt-px"},t=["inline-flex align-middle","[&>*]:relative [&>*:hover]:z-10 [&>*:focus-visible]:z-10","[&>*]:shrink-0"].join(" ");export const ButtonGroup=e.forwardRef(function({variant:l,size:a,color:d,density:s,elevation:c,orientation:f="horizontal",disabled:u,fullWidth:h=!1,className:m,children:v,...x},p){const z=e.useMemo(()=>({variant:l,size:a,color:d,density:s,elevation:c,disabled:u}),[l,a,d,s,c,u]);return o(i.Provider,{value:z,children:o("div",{ref:p,role:"group",className:[t,"vertical"===f?"flex-col":"flex-row",n[f],"outline"===(l??"solid")?r[f]:"",h?"flex w-full [&>*]:flex-1":"",m??""].filter(Boolean).join(" "),...x,children:v})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ButtonGroup}from"./ButtonGroup";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type BoxProps } from '../box/Box';
|
|
3
|
+
export interface CardProps extends Omit<BoxProps, 'title' | 'padded'> {
|
|
4
|
+
/**
|
|
5
|
+
* The card's heading. A plain string is styled as the title; pass a real
|
|
6
|
+
* heading element (`title={<h2>…</h2>}`) when the card needs to appear in the
|
|
7
|
+
* document outline — it inherits the title's typography rather than the
|
|
8
|
+
* browser's.
|
|
9
|
+
*/
|
|
10
|
+
title?: React.ReactNode;
|
|
11
|
+
/** A second line under the title, one step down the type scale and muted. */
|
|
12
|
+
subtitle?: React.ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Content pinned to the end of the header row — a menu button, a status chip.
|
|
15
|
+
* Stays on the title's line while the title wraps beside it.
|
|
16
|
+
*/
|
|
17
|
+
headerAction?: React.ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* The bottom area. Laid out as a wrapping row so a pair of buttons needs no
|
|
20
|
+
* wrapper of its own; anything else can bring its own layout.
|
|
21
|
+
*/
|
|
22
|
+
footer?: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Draws a hairline between the sections instead of separating them with
|
|
25
|
+
* space. The lines run the full width of the sheet, so the padding moves from
|
|
26
|
+
* the card onto each section.
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
dividers?: boolean;
|
|
30
|
+
/** The card's body. */
|
|
31
|
+
children?: React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A Box with the parts a card is made of laid out on it: a title, a subtitle,
|
|
35
|
+
* a body and a footer.
|
|
36
|
+
*
|
|
37
|
+
* The sections are props rather than compound sub-components — `<Card.Header>`,
|
|
38
|
+
* `<Card.Title>` — for the same reason TextField takes `label` and `description`
|
|
39
|
+
* as props: the arrangement is fixed, and the thing a caller wants to decide is
|
|
40
|
+
* what goes in each slot, not what order the slots come in.
|
|
41
|
+
*
|
|
42
|
+
* Every Box prop passes straight through, so a card is styled on exactly the
|
|
43
|
+
* same axes as the box it is.
|
|
44
|
+
*/
|
|
45
|
+
export declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as l,Fragment as t}from"react/jsx-runtime";import*as n from"react";import{Box as a,boxPaddingXClasses as r,boxPaddingYClasses as s}from"../box/Box";import{hasContent as i,metaTextClasses as o,sheetBodyClasses as c,sheetHeaderGapClasses as d,sheetSectionGapClasses as m,sheetTitleClasses as f}from"../../internal/styles";export const Card=n.forwardRef(function({size:n="md",density:u="default",title:x,subtitle:h,headerAction:N,footer:p,dividers:$=!1,className:b,children:v,...y},j){const k=r[u][n],g=s[u][n],w=$?`${k} ${g}`:k,B=i(x)||i(h)||i(N),z=l(t,{children:[i(x)||i(h)?l("div",{className:`flex min-w-0 flex-1 flex-col ${d[n]}`,children:[i(x)?e("div",{className:`neba-title font-semibold ${f[n]}`,children:x}):null,i(h)?e("div",{className:`text-(--neba-muted-fg) ${o[n]}`,children:h}):null]}):null,i(N)?e("div",{className:"ml-auto shrink-0",children:N}):null]}),A=[B?{key:"header",className:"flex items-start gap-3",content:z}:null,i(v)?{key:"content",className:c[n],content:v}:null,i(p)?{key:"footer",className:`flex flex-wrap items-center gap-2 ${c[n]}`,content:p}:null].filter(e=>null!==e);return e(a,{ref:j,size:n,density:u,padded:!1,className:["flex flex-col",$?"":`${g} ${m[n]}`,b??""].filter(Boolean).join(" "),...y,children:A.map((l,t)=>e("div",{className:[w,l.className,$&&t>0?"border-t [border-color:var(--n-line)]":""].filter(Boolean).join(" "),children:l.content},l.key))})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Card}from"./Card";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps } from '../../types';
|
|
3
|
+
export interface CarouselProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
|
|
4
|
+
/**
|
|
5
|
+
* Drop shadow depth of the frame. `0` — the default — is flat.
|
|
6
|
+
* @default 0
|
|
7
|
+
*/
|
|
8
|
+
elevation?: NebaElevation;
|
|
9
|
+
/** Which slide is showing, counted from 0. Use with `onValueChange`. */
|
|
10
|
+
value?: number;
|
|
11
|
+
/** Which starts showing, for an uncontrolled carousel. @default 0 */
|
|
12
|
+
defaultValue?: number;
|
|
13
|
+
onValueChange?: (index: number) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Whether the arrows wrap from the last slide back to the first. With it off
|
|
16
|
+
* they go inert at the ends instead, which is the honest thing for a set that
|
|
17
|
+
* has a beginning and an end — a gallery of three photographs does, a rotating
|
|
18
|
+
* banner does not.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
loop?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Advances on its own.
|
|
24
|
+
*
|
|
25
|
+
* Off by default and deliberately so: a carousel that moves while it is being
|
|
26
|
+
* read is the most complained-about pattern on the web. It pauses on hover,
|
|
27
|
+
* on focus anywhere inside it, while the tab is in the background, and it does
|
|
28
|
+
* not start at all for a reader who has asked for reduced motion.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
autoPlay?: boolean;
|
|
32
|
+
/** How long each slide is held, in milliseconds. @default 5000 */
|
|
33
|
+
interval?: number;
|
|
34
|
+
/** The previous/next buttons. @default true */
|
|
35
|
+
arrows?: boolean;
|
|
36
|
+
/** The row of position dots under the frame. @default true */
|
|
37
|
+
indicators?: boolean;
|
|
38
|
+
/** The carousel's accessible name. @default 'Carousel' */
|
|
39
|
+
label?: string;
|
|
40
|
+
/** @default 'Previous slide' */
|
|
41
|
+
previousLabel?: string;
|
|
42
|
+
/** @default 'Next slide' */
|
|
43
|
+
nextLabel?: string;
|
|
44
|
+
/**
|
|
45
|
+
* How one slide is named to a screen reader, and how its dot is labelled.
|
|
46
|
+
* @default (index, count) => `Slide ${index} of ${count}`
|
|
47
|
+
*/
|
|
48
|
+
slideLabel?: (index: number, count: number) => string;
|
|
49
|
+
/** The slides. Every top-level child becomes one. */
|
|
50
|
+
children?: React.ReactNode;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A strip of slides, one of which is in view.
|
|
54
|
+
*
|
|
55
|
+
* The mechanism is a scroll container with CSS scroll snapping, and everything
|
|
56
|
+
* good about this component follows from that one choice. Swiping on a phone and
|
|
57
|
+
* two-finger dragging on a trackpad both work because they are the browser's own
|
|
58
|
+
* scrolling and not a gesture handler pretending to be it. The strip runs the
|
|
59
|
+
* other way under RTL without being told, because scrolling is directional and
|
|
60
|
+
* `translate` is not. And nothing is transformed — the house rule against moving
|
|
61
|
+
* a surface holds here for free, where a translated track would have had to
|
|
62
|
+
* argue for an exception.
|
|
63
|
+
*
|
|
64
|
+
* The motion is `scroll-behavior: smooth`, which means a reader who has asked
|
|
65
|
+
* for reduced motion gets an instant cut from the same code path rather than
|
|
66
|
+
* from a second one written to remember them.
|
|
67
|
+
*
|
|
68
|
+
* Slides are not a sub-component. Every top-level child is wrapped in its own
|
|
69
|
+
* slide, so `<Carousel><img /><img /></Carousel>` is the whole API — and the
|
|
70
|
+
* wrapper is what carries the snap point, the width and the
|
|
71
|
+
* `role="group"`/`aria-roledescription="slide"` pair a screen reader needs, none
|
|
72
|
+
* of which a caller should have to remember to put on a photograph.
|
|
73
|
+
*/
|
|
74
|
+
export declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{IconButton as n}from"../icon-button/IconButton";import{ChevronIcon as a}from"../../internal/icons";import{radiusClasses as o,srOnlyClasses as i,surfaceClasses as l,surfaceSlots as s,transitionClasses as c}from"../../internal/styles";const u={solid:[l,"text-(--neba-fg) bg-(--n-panel-hover)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[l,"border text-(--neba-fg) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"},d={xs:"start-1 end-1",sm:"start-1.5 end-1.5",md:"start-2 end-2",lg:"start-3 end-3",xl:"start-4 end-4"},f={xs:{rest:"h-1 w-1",current:"h-1 w-3",gap:"gap-1"},sm:{rest:"h-1 w-1",current:"h-1 w-3.5",gap:"gap-1"},md:{rest:"h-1.5 w-1.5",current:"h-1.5 w-4",gap:"gap-1.5"},lg:{rest:"h-1.5 w-1.5",current:"h-1.5 w-5",gap:"gap-2"},xl:{rest:"h-2 w-2",current:"h-2 w-6",gap:"gap-2"}},m=(e,r)=>`Slide ${e} of ${r}`;export const Carousel=t.forwardRef(function({variant:l="outline",size:p="md",color:v="primary",density:h="default",elevation:b=0,value:w,defaultValue:g=0,onValueChange:x,loop:N=!0,autoPlay:y=!1,interval:j=5e3,arrows:k=!0,indicators:C=!0,label:M="Carousel",previousLabel:R="Previous slide",nextLabel:$="Next slide",slideLabel:I=m,className:L,style:P,children:S,..._},z){const B=t.Children.toArray(S),E=B.length,[V,T]=t.useState(g),W=Math.min(Math.max(w??V,0),Math.max(E-1,0)),A=t.useRef(null),F=t.useRef([]),q=t.useRef(!1),D=t.useRef(!1),G=t.useRef(!1),[H,J]=t.useState(!1),K=t.useCallback((e,r=!1)=>{if(0===E)return;const t=N?(e%E+E)%E:Math.min(Math.max(e,0),E-1);q.current=r,void 0===w&&T(t),t!==W&&x?.(t)},[E,N,w,W,x]);t.useEffect(()=>{if(q.current)return void(q.current=!1);if(!D.current)return void(D.current=!0);F.current[W]?.scrollIntoView({block:"nearest",inline:"start"}),G.current=!0;const e=window.setTimeout(()=>{G.current=!1},700);return()=>window.clearTimeout(e)},[W]);t.useEffect(()=>{if(!y||H||E<2)return;if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;const e=window.setInterval(()=>{document.hidden||K(W+1)},j);return()=>window.clearInterval(e)},[y,H,E,j,W,K]);const O=W<=0,Q=W>=E-1;return r("div",{ref:z,role:"region","aria-roledescription":"carousel","aria-label":M,className:["flex flex-col",L??""].filter(Boolean).join(" "),style:{...s(v,b),...P},onPointerEnter:()=>J(!0),onPointerLeave:()=>J(!1),onFocus:()=>J(!0),onBlur:()=>J(!1),..._,children:[r("div",{className:["relative min-w-0 overflow-hidden",o[p],u[l],c].join(" "),children:[e("div",{ref:A,tabIndex:0,role:"group","aria-label":M,className:["flex min-w-0 snap-x snap-mandatory overflow-x-auto scroll-smooth","motion-reduce:scroll-auto","[scrollbar-width:none] [&::-webkit-scrollbar]:hidden","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]"].join(" "),onScroll:()=>{const e=A.current;if(!e||0===e.clientWidth||G.current)return;const r=Math.round(Math.abs(e.scrollLeft)/e.clientWidth);r!==W&&r>=0&&r<E&&K(r,!0)},children:B.map((r,t)=>e("div",{ref:e=>{F.current[t]=e},role:"group","aria-roledescription":"slide","aria-label":I(t+1,E),className:"w-full shrink-0 grow-0 basis-full snap-start",children:r},t))}),k&&E>1?r("div",{className:`pointer-events-none absolute inset-y-0 flex items-center ${d[p]}`,children:[e(n,{variant:"solid",size:p,color:v,density:h,elevation:1,label:R,disabled:!N&&O,className:"pointer-events-auto",icon:e("span",{className:"flex items-center rotate-90 rtl:-rotate-90",children:e(a,{})}),onClick:()=>K(W-1)}),e("span",{className:"flex-1"}),e(n,{variant:"solid",size:p,color:v,density:h,elevation:1,label:$,disabled:!N&&Q,className:"pointer-events-auto",icon:e("span",{className:"flex items-center -rotate-90 rtl:rotate-90",children:e(a,{})}),onClick:()=>K(W+1)})]}):null]}),C&&E>1?e("div",{className:`flex shrink-0 items-center justify-center pt-2 ${f[p].gap}`,children:B.map((r,t)=>e("button",{type:"button","aria-label":I(t+1,E),"aria-current":t===W?"true":void 0,className:["cursor-pointer rounded-full","[transition-property:width,background-color]","[transition-duration:var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2",t===W?`${f[p].current} bg-(--n-accent)`:`${f[p].rest} bg-(--n-line-hover) hover:bg-(--n-accent)`].join(" "),onClick:()=>K(t)},t))}):null,e("span",{className:i,"aria-live":y?"off":"polite",children:E>0?I(W+1,E):""})]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Carousel}from"./Carousel";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Checkbox as BaseUICheckbox } from '@base-ui/react/checkbox';
|
|
3
|
+
import type { NebaColor, NebaSize } from '../../types';
|
|
4
|
+
/**
|
|
5
|
+
* Base UI's own props, minus the ones this component owns: `className` and
|
|
6
|
+
* `style` land on the field wrapper rather than on the tick, and `render` would
|
|
7
|
+
* replace the tick with something that is no longer a checkbox.
|
|
8
|
+
*/
|
|
9
|
+
type BaseCheckboxProps = Omit<React.ComponentPropsWithoutRef<typeof BaseUICheckbox.Root>, 'className' | 'style' | 'render' | 'children'>;
|
|
10
|
+
export interface CheckboxProps extends BaseCheckboxProps {
|
|
11
|
+
/** @default 'md' */
|
|
12
|
+
size?: NebaSize;
|
|
13
|
+
/** @default 'primary' */
|
|
14
|
+
color?: NebaColor;
|
|
15
|
+
/** The text beside the tick. Wired to it by Base UI's Field. */
|
|
16
|
+
label?: React.ReactNode;
|
|
17
|
+
/** Helper text under the label. */
|
|
18
|
+
description?: React.ReactNode;
|
|
19
|
+
/** Error message below. Its presence also turns the checkbox invalid. */
|
|
20
|
+
error?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Forces the invalid state without a message — for when an external form
|
|
23
|
+
* library owns the validity. Defaults to whether `error` has content.
|
|
24
|
+
*/
|
|
25
|
+
invalid?: boolean;
|
|
26
|
+
/** Class names for the field wrapper, not for the tick itself. */
|
|
27
|
+
className?: string;
|
|
28
|
+
style?: React.CSSProperties;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A single yes/no, or one member of a set of them.
|
|
32
|
+
*
|
|
33
|
+
* `label`, `description` and `error` are props rather than children for the same
|
|
34
|
+
* reason they are on TextField: the arrangement is fixed and what a caller wants
|
|
35
|
+
* to decide is what goes in each slot. `children` is not accepted at all —
|
|
36
|
+
* anything a checkbox has to say belongs in one of the three.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLElement>>;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as r from"react";import{Checkbox as a}from"@base-ui/react/checkbox";import{Field as i}from"@base-ui/react/field";import{controlTextClasses as l,metaTextClasses as t,surfaceClasses as o,tickRadiusClasses as s,tickRowLeadingClasses as d,tickSizeClasses as c,transitionClasses as b}from"../../internal/styles";const h=["relative inline-flex shrink-0 items-center justify-center border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",b,"active:[transition-duration:0ms]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),f=[o,"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)","data-[indeterminate]:bg-(--n-fill) data-[indeterminate]:text-(--n-on-solid)","data-[indeterminate]:[border-color:transparent]"].join(" "),m=[o,"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(" "),u=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)]","text-(--neba-disabled-fg) shadow-none","data-[checked]:bg-(--neba-disabled-bg)","data-[indeterminate]:bg-(--neba-disabled-bg)"].join(" ");function v(){return e("svg",{viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:"size-full",children:e("path",{d:"M2 6.2 4.6 8.8 10 3.4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function p(){return e("svg",{viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:"size-full",children:e("path",{d:"M2.5 6h7",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}export const Checkbox=r.forwardRef(function({size:r="md",color:o="primary",label:b,description:g,error:x,invalid:k,disabled:j=!1,readOnly:N=!1,className:$,style:y,...w},z){const C=null!=x&&!1!==x&&""!==x,L=k??C,B=L?"danger":o,R={"--n-fill":`var(--neba-${B}-fill)`,"--n-fill-hover":`var(--neba-${B}-fill-hover)`,"--n-on-solid":`var(--neba-${B}-on-solid)`,"--n-accent":`var(--neba-${B}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${B}-line)`,"--n-line-hover":`var(--neba-${B}-line-hover)`,"--n-ring":`var(--neba-${B}-ring)`},M=[h,c[r],s[r],j?u:N?m:f].join(" ");return n(i.Root,{disabled:j,invalid:L,className:["inline-flex flex-col gap-1 align-top",$??""].filter(Boolean).join(" "),style:{...R,...y},children:[n("div",{className:`flex items-start gap-2 ${l[r]} ${d}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(a.Root,{ref:z,className:M,disabled:j,readOnly:N,...w,children:e(a.Indicator,{className:"flex size-[70%] items-center justify-center",children:w.indeterminate?e(p,{}):e(v,{})})})}),b||g?n("span",{className:"flex min-w-0 flex-col gap-0.5",children:[b?e(i.Label,{className:["leading-[1.4]",j?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:b}):null,g?e(i.Description,{className:`${t[r]} text-(--neba-muted-fg)`,children:g}):null]}):null]}),C?e(i.Error,{match:!0,className:`${t[r]} text-(--n-accent)`,children:x}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Checkbox}from"./Checkbox";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps } from '../../types';
|
|
3
|
+
export interface ChipProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
|
|
4
|
+
/**
|
|
5
|
+
* Drop shadow depth. `0` (the default) is flat. A chip is a token sitting on
|
|
6
|
+
* something else, so this is raised even less often than on a Button.
|
|
7
|
+
* @default 0
|
|
8
|
+
*/
|
|
9
|
+
elevation?: NebaElevation;
|
|
10
|
+
/** Content placed before the label — an icon, a status dot, an avatar. */
|
|
11
|
+
startIcon?: React.ReactNode;
|
|
12
|
+
/** Content placed after the label, before any `count`. */
|
|
13
|
+
endIcon?: React.ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* A number set into the end of the chip. Rendered on its own small plate, so
|
|
16
|
+
* "Errors 12" reads as one token with a count rather than as two words.
|
|
17
|
+
*/
|
|
18
|
+
count?: React.ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Called when the chip's delete affordance is pressed. Passing it is what
|
|
21
|
+
* makes the affordance appear.
|
|
22
|
+
*/
|
|
23
|
+
onDelete?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
24
|
+
/** Accessible name of the delete button. */
|
|
25
|
+
deleteLabel?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Marks the chip as chosen — a filter that is on. `selected` deepens the
|
|
28
|
+
* surface a step rather than changing the colour family, so a row of chips
|
|
29
|
+
* stays one row of chips.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
selected?: boolean;
|
|
33
|
+
/** Unavailable. Drops the colour family for neutral grey, as everywhere else. */
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
children?: React.ReactNode;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A compact token: a tag, a filter, a status, an entity plucked out of a list.
|
|
39
|
+
*
|
|
40
|
+
* The shell is always a `<span>`. What changes is what is inside it: a plain run
|
|
41
|
+
* of content, or — when `onClick` is given — a real `<button>` wrapping that
|
|
42
|
+
* content, plus a second button for `onDelete`. Both are reachable by keyboard,
|
|
43
|
+
* and neither is nested inside the other.
|
|
44
|
+
*
|
|
45
|
+
* An inert `<span>` carrying a click handler is the single most common way a
|
|
46
|
+
* component library loses its keyboard users, and a `<button>` inside a
|
|
47
|
+
* `<button>` is the most common way it invents a chip that Chrome silently
|
|
48
|
+
* rewrites. This shape is what avoids both.
|
|
49
|
+
*/
|
|
50
|
+
export declare const Chip: React.ForwardRefExoticComponent<ChipProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,Fragment as n,jsxs as l}from"react/jsx-runtime";import*as t from"react";import{CloseIcon as o}from"../../internal/icons";import{chipRemoveClasses as i,controlHeightClasses as r,controlSlots as s,controlTextClasses as a,disabledClasses as c,focusRingClasses as d,gapClasses as m,iconClasses as p,paddingXClasses as b,pressTransitionClasses as f,radiusClasses as u,surfaceClasses as h,transitionClasses as v}from"../../internal/styles";const x={xs:"xs",sm:"xs",md:"sm",lg:"md",xl:"lg"},g={solid:[h,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[h,"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)"},j={solid:"bg-(--n-fill-active)",outline:"bg-(--n-panel-press) [border-color:var(--n-line-hover)]",text:"bg-(--n-soft-press)"},w={solid:"hover:bg-(--n-fill-hover) active:bg-(--n-fill-active)",outline:"hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)] active:bg-(--n-panel-press)",text:"hover:bg-(--n-soft-hover) active:bg-(--n-soft-press)"},y=["relative inline-flex max-w-full shrink-0 select-none items-center","align-middle font-medium leading-none whitespace-nowrap","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",v,f,p].join(" "),k=["flex min-w-0 flex-1 cursor-pointer items-center justify-center self-stretch rounded-[inherit]",d].join(" ");export const Chip=t.forwardRef(function({variant:t="outline",size:d="md",color:p="primary",density:f="default",elevation:h=0,startIcon:v,endIcon:N,count:C,onDelete:$,deleteLabel:B="Remove",selected:I=!1,disabled:R=!1,className:z,style:D,children:F,onClick:L,...q},A){const E=Boolean(L)&&!R,G=x[d],H=b[f][G],J=[y,r[G],a[G],m[G],u[G],R?c[t]:g[t],!R&&I?j[t]:"",E?w[t]:"",E?"ps-0":H,$?"pe-1":E?"pe-0":"",z??""].filter(Boolean).join(" "),K=l(n,{children:[v,null!=F&&!1!==F?e("span",{className:"min-w-0 truncate",children:F}):null,N,null!=C&&!1!==C?e("span",{className:["ms-0.5 inline-flex shrink-0 items-center justify-center rounded-full px-1.5 py-px","text-[0.85em] leading-none font-semibold tabular-nums","solid"===t?"bg-(--neba-glow-on-fill) text-(--n-on-solid)":"bg-(--n-soft-press) text-(--n-accent)"].join(" "),children:C}):null]});return l("span",{ref:A,className:J,style:{...s(p,h,t),...D},"aria-disabled":!(!R||E)||void 0,...q,children:[E?e("button",{type:"button","aria-pressed":I,className:`${k} ${m[G]} ${H}`,onClick:L,children:K}):K,$?e("button",{type:"button","aria-label":B,disabled:R,className:i,onClick:$,children:e(o,{})}):null]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Chip}from"./Chip";
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NebaElevation, NebaStyleProps } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* What a Combobox's value may be — the same two types a [Select](../select)
|
|
5
|
+
* submits, and for the same reason: a form control's value is what a form
|
|
6
|
+
* sends, and every escape from that buys flexibility by making the common case
|
|
7
|
+
* harder to write.
|
|
8
|
+
*
|
|
9
|
+
* A value the list does not contain is a `string`: it is what the user typed.
|
|
10
|
+
*/
|
|
11
|
+
export type ComboboxValue = string | number;
|
|
12
|
+
export interface ComboboxOption {
|
|
13
|
+
/** Submitted, and what `value` / `onValueChange` speak in. */
|
|
14
|
+
value: ComboboxValue;
|
|
15
|
+
/**
|
|
16
|
+
* Shown in the list, in the input and on the chip. Defaults to the value.
|
|
17
|
+
*
|
|
18
|
+
* A `string` rather than a `ReactNode`, which is the one place this differs
|
|
19
|
+
* from Select: the label is typed against by the filter and written into a
|
|
20
|
+
* text input, and neither of those can be done to an element.
|
|
21
|
+
*/
|
|
22
|
+
label?: string;
|
|
23
|
+
/** Unavailable, but still listed — the option exists, it just cannot be picked. */
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** One value, or an array of them, depending on `multiple`. */
|
|
27
|
+
type Selection<Multiple extends boolean | undefined> = Multiple extends true ? ComboboxValue[] : ComboboxValue | null;
|
|
28
|
+
export interface ComboboxProps<Multiple extends boolean | undefined = false> extends NebaStyleProps {
|
|
29
|
+
/**
|
|
30
|
+
* The options, as data — the same shape Select takes, and for the same
|
|
31
|
+
* reason: what a caller has is almost always an array already.
|
|
32
|
+
*/
|
|
33
|
+
items: readonly ComboboxOption[];
|
|
34
|
+
/**
|
|
35
|
+
* Whether more than one value may be held. The chosen ones become chips
|
|
36
|
+
* inside the field, and the input goes on filtering after each.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
multiple?: Multiple;
|
|
40
|
+
/** The chosen value. Use with `onValueChange` for a controlled combobox. */
|
|
41
|
+
value?: Selection<Multiple> | null;
|
|
42
|
+
/** The initially chosen value, for an uncontrolled combobox. */
|
|
43
|
+
defaultValue?: Selection<Multiple> | null;
|
|
44
|
+
onValueChange?: (value: Selection<Multiple>) => void;
|
|
45
|
+
/** Called as the text in the input changes — the filter query, not the value. */
|
|
46
|
+
onInputValueChange?: (inputValue: string) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Whether a value the list does not contain may be committed.
|
|
49
|
+
*
|
|
50
|
+
* On by default, and it is what separates this from a searchable Select: the
|
|
51
|
+
* typed text is offered as its own row at the end of the list, so committing
|
|
52
|
+
* it is a choice the user makes rather than something that happens to them on
|
|
53
|
+
* blur. Turn it off for a field whose values are a closed set.
|
|
54
|
+
* @default true
|
|
55
|
+
*/
|
|
56
|
+
allowCustom?: boolean;
|
|
57
|
+
/** What that row says. Receives the trimmed query. */
|
|
58
|
+
customLabel?: (query: string) => React.ReactNode;
|
|
59
|
+
/**
|
|
60
|
+
* Shows a × that empties the field. Off by default — a field that can be
|
|
61
|
+
* cleared in one click is a field that can be emptied by accident.
|
|
62
|
+
* @default false
|
|
63
|
+
*/
|
|
64
|
+
clearable?: boolean;
|
|
65
|
+
/** Shown in the popup when nothing matches and no value may be added. */
|
|
66
|
+
emptyMessage?: React.ReactNode;
|
|
67
|
+
/** The most rows the list will show at once. `-1` is all of them. @default -1 */
|
|
68
|
+
limit?: number;
|
|
69
|
+
/** Shown in the input while nothing is typed. */
|
|
70
|
+
placeholder?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Drop shadow depth of the *field*. The popup has its own, fixed: it
|
|
73
|
+
* genuinely floats above the page, which is the one case elevation is for.
|
|
74
|
+
* @default 0
|
|
75
|
+
*/
|
|
76
|
+
elevation?: NebaElevation;
|
|
77
|
+
/** Label above the field, wired to it by Base UI's Field. */
|
|
78
|
+
label?: React.ReactNode;
|
|
79
|
+
/** Helper text below the field. */
|
|
80
|
+
description?: React.ReactNode;
|
|
81
|
+
/** Error message below. Its presence also turns the combobox invalid. */
|
|
82
|
+
error?: React.ReactNode;
|
|
83
|
+
/** Forces the invalid state without a message. Defaults to `!!error`. */
|
|
84
|
+
invalid?: boolean;
|
|
85
|
+
/** Content placed before the input. Sized in `em`, so it tracks the text. */
|
|
86
|
+
startIcon?: React.ReactNode;
|
|
87
|
+
/** Stretches to the width of the container. */
|
|
88
|
+
fullWidth?: boolean;
|
|
89
|
+
/** Unavailable. */
|
|
90
|
+
disabled?: boolean;
|
|
91
|
+
/** The value is shown but cannot be changed. */
|
|
92
|
+
readOnly?: boolean;
|
|
93
|
+
/** Whether a value must be chosen before the form is submitted. */
|
|
94
|
+
required?: boolean;
|
|
95
|
+
/** Identifies the field when a form is submitted. */
|
|
96
|
+
name?: string;
|
|
97
|
+
/** The popup is open. Use with `onOpenChange` for a controlled popup. */
|
|
98
|
+
open?: boolean;
|
|
99
|
+
/** Whether the popup starts open. */
|
|
100
|
+
defaultOpen?: boolean;
|
|
101
|
+
onOpenChange?: (open: boolean) => void;
|
|
102
|
+
/** Accessible name of the clear button. */
|
|
103
|
+
clearLabel?: string;
|
|
104
|
+
/** Accessible name of a chip's remove button. Receives the chip's label. */
|
|
105
|
+
removeLabel?: (label: string) => string;
|
|
106
|
+
/** A ref to the text input the user types into. */
|
|
107
|
+
inputRef?: React.Ref<HTMLInputElement>;
|
|
108
|
+
id?: string;
|
|
109
|
+
className?: string;
|
|
110
|
+
style?: React.CSSProperties;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A field you can type into and also choose from.
|
|
114
|
+
*
|
|
115
|
+
* The shell is a TextField's, wearing a chevron, exactly as Select's trigger is
|
|
116
|
+
* — the three have to be indistinguishable in a form or the form looks
|
|
117
|
+
* assembled rather than designed. What is different is what the text does: it
|
|
118
|
+
* filters the list, and — unless `allowCustom` is off — it can become the value
|
|
119
|
+
* itself, offered as the last row rather than committed silently on blur.
|
|
120
|
+
*
|
|
121
|
+
* With `multiple` the chosen values become [Chip](../../display/chip)s inside
|
|
122
|
+
* the field and the input goes on filtering after each one, so a set of tags is
|
|
123
|
+
* built without the field ever closing.
|
|
124
|
+
*
|
|
125
|
+
* Base UI owns everything hard about this: the filtering and its collator, the
|
|
126
|
+
* popup's positioning and flipping, the `combobox`/`listbox` wiring, arrow-key
|
|
127
|
+
* navigation across both the list and the chips, and the hidden input that
|
|
128
|
+
* makes the whole thing submit with a form.
|
|
129
|
+
*/
|
|
130
|
+
export declare function Combobox<Multiple extends boolean | undefined = false>({ variant, size, color, density, elevation, items, multiple, value, defaultValue, onValueChange, onInputValueChange, allowCustom, customLabel, clearable, emptyMessage, limit, placeholder, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, name, open, defaultOpen, onOpenChange, clearLabel, removeLabel, inputRef, id, className, style }: ComboboxProps<Multiple>): React.JSX.Element;
|
|
131
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Combobox as n}from"@base-ui/react/combobox";import{Field as t}from"@base-ui/react/field";import{Chip as i}from"../chip/Chip";import{CheckIcon as r,ChevronIcon as o,CloseIcon as s,PlusIcon as c}from"../../internal/icons";import{chipRemoveClasses as d,controlHeightClasses as u,controlTextLeadingClasses as m,disabledClasses as p,fieldReadOnlyClasses as h,fieldRestClasses as b,focusWithinRingClasses as f,gapClasses as g,hasContent as x,iconClasses as v,metaTextClasses as y,paddingXClasses as N,radiusClasses as w,stackGapClasses as C,surfaceClasses as j,surfaceSlots as L,transitionClasses as $}from"../../internal/styles";const I=["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent]",$,"focus-within:[transition-duration:0ms]",f,v].join(" "),S={xs:"min-h-5.5 py-0",sm:"min-h-6.5 py-[2px]",md:"min-h-8 py-[3px]",lg:"min-h-10 py-[4px]",xl:"min-h-12 py-[4px]"},O=[j,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","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(" "),V=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",$,"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(" "),_=["inline-flex h-[1lh] shrink-0 cursor-pointer items-center justify-center","rounded-(--neba-radius-xs) text-(--neba-muted-fg)","[transition:color_var(--neba-duration)_var(--neba-ease)]","hover:text-(--n-accent)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1","disabled:cursor-not-allowed disabled:text-(--neba-disabled-fg)"].join(" ");function z(e){return null==e?[]:Array.isArray(e)?e.slice():[e]}export function Combobox({variant:f="outline",size:v="md",color:j="primary",density:$="default",elevation:A=0,items:R,multiple:k,value:T,defaultValue:q,onValueChange:E,onInputValueChange:F,allowCustom:M=!0,customLabel:P,clearable:B=!1,emptyMessage:D="No matches",limit:G,placeholder:H,label:W,description:J,error:K,invalid:Q,startIcon:U,fullWidth:X=!1,disabled:Y=!1,readOnly:Z=!1,required:ee=!1,name:ae,open:le,defaultOpen:ne,onOpenChange:te,clearLabel:ie="Clear",removeLabel:re=e=>`Remove ${e}`,inputRef:oe,id:se,className:ce,style:de}){const ue=x(K),me=Q??ue,pe=me?"danger":j,he=!0===k,be=l.useMemo(()=>R.map(e=>({value:e.value,label:e.label??String(e.value),disabled:e.disabled})),[R]),[fe,ge]=l.useState(()=>z(q)),xe=void 0===T?fe:z(T),[ve,ye]=l.useState(""),Ne=l.useCallback(e=>be.find(a=>a.value===e)??{value:e,label:String(e),custom:!0},[be]),we=ve.trim(),Ce=we.toLocaleLowerCase(),je=""===we||be.some(e=>e.label.toLocaleLowerCase()===Ce||String(e.value).toLocaleLowerCase()===Ce)||xe.some(e=>String(e).toLocaleLowerCase()===Ce),Le=!M||Z||Y||je?null:we,$e=l.useMemo(()=>null===Le?be:[...be,{value:Le,label:Le,custom:!0}],[be,Le]),Ie=he?xe.map(Ne):xe.length>0?Ne(xe[0]):null;const Se=N[$][v],Oe=[I,m[v],w[v],g[v],he?S[v]:u[v],`${Se} pe-1.5`,Y?p[f]:Z?h[f]:b[f]].join(" "),Ve=["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","placeholder:text-(--neba-muted-fg)","caret-(--n-accent) selection:bg-(--n-soft-press)","disabled:cursor-not-allowed"].join(" "),_e=a=>e(n.Input,{ref:oe,placeholder:H,className:he?`${Ve} min-w-16 ${a?"ms-1.5":""}`:Ve});return a(t.Root,{disabled:Y,invalid:me,className:["flex-col align-top",C[v],X?"flex w-full":"inline-flex",ce??""].filter(Boolean).join(" "),style:{...L(pe,A),...de},children:[W?e(t.Label,{className:[y[v],"font-medium",Y?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:W}):null,a(n.Root,{id:se,name:ae,items:$e,multiple:he,value:Ie,onValueChange:e=>{!function(e){void 0===T&&ge(e),E?.(he?e:e[0]??null)}((null===e?[]:Array.isArray(e)?e:[e]).map(e=>e.value))},onInputValueChange:e=>{ye(e),F?.(e)},open:le,defaultOpen:ne,onOpenChange:e=>te?.(e),autoHighlight:!0,itemToStringLabel:e=>e.label,itemToStringValue:e=>String(e.value),isItemEqualToValue:(e,a)=>e.value===a.value,limit:G,disabled:Y,readOnly:Z,required:ee,children:[a(n.InputGroup,{className:Oe,children:[U?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:U}):null,he?e(n.Chips,{className:"flex min-w-0 flex-1 flex-wrap items-center gap-1",children:e(n.Value,{children:t=>a(l.Fragment,{children:[t.map(a=>e(n.Chip,{render:e(i,{variant:"outline",size:v,color:pe,density:"compact",disabled:Y,endIcon:Z||Y?null:e(n.ChipRemove,{"aria-label":re(a.label),className:d,children:e(s,{})})}),children:a.label},String(a.value))),_e(t.length>0)]})})}):_e(!1),B&&!Z?e(n.Clear,{"aria-label":ie,className:_,children:e(s,{})}):null,e(n.Trigger,{"aria-label":"string"==typeof W?void 0:"Open",className:_,children:e(n.Icon,{className:["flex items-center","[transition:rotate_var(--neba-duration)_var(--neba-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(o,{})})})]}),e(n.Portal,{children:e(n.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:6,children:a(n.Popup,{className:`${O} ${w[v]} ${m[v]}`,style:L(pe,3),children:[e(n.Empty,{className:"px-2 py-1.5 text-(--neba-muted-fg) empty:hidden",children:D}),e(n.List,{children:t=>e(n.Item,{value:t,disabled:t.disabled,className:V,children:t.custom?a(l.Fragment,{children:[e("span",{className:"absolute start-1.5 flex size-4 items-center justify-center text-(--n-accent) [&_svg]:size-4",children:e(c,{})}),e("span",{className:"truncate",children:P?P(t.label):`Add “${t.label}”`})]}):a(l.Fragment,{children:[e(n.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e("span",{className:"truncate",children:t.label})]})},`${t.custom?"custom:":""}${String(t.value)}`)})]})})})]}),J?e(t.Description,{className:`${y[v]} text-(--neba-muted-fg)`,children:J}):null,ue?e(t.Error,{match:!0,className:`${y[v]} text-(--n-accent)`,children:K}):null]})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Combobox}from"./Combobox";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { NebaDensity, NebaSize } from '../../types';
|
|
4
|
+
export interface ContainerProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
5
|
+
/**
|
|
6
|
+
* How wide the content is allowed to get, on the same ladder the breakpoints
|
|
7
|
+
* use — `sm` 40rem, `md` 48rem, `lg` 64rem, `xl` 80rem, `xs` 30rem.
|
|
8
|
+
*
|
|
9
|
+
* `none`, the default, is no limit: a Container's job is the gutter, and a
|
|
10
|
+
* measure is a second decision that a page should have to ask for.
|
|
11
|
+
* @default 'none'
|
|
12
|
+
*/
|
|
13
|
+
maxWidth?: NebaSize | 'none';
|
|
14
|
+
/**
|
|
15
|
+
* The gutter, on the `size`/`density` scale. Turn it off to keep the
|
|
16
|
+
* centring and the measure without the padding.
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
padded?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The gutter's scale. As on Box, `size` here is the size of the *sheet* — it
|
|
22
|
+
* never touches a height or the type scale — and it is independent of
|
|
23
|
+
* `maxWidth`, which is how wide the content gets rather than how far it sits
|
|
24
|
+
* from the edge.
|
|
25
|
+
* @default 'md'
|
|
26
|
+
*/
|
|
27
|
+
size?: NebaSize;
|
|
28
|
+
/** @default 'default' */
|
|
29
|
+
density?: NebaDensity;
|
|
30
|
+
/**
|
|
31
|
+
* Centres the content once `maxWidth` is narrower than the page. No effect
|
|
32
|
+
* while `maxWidth` is `none`, because there is nothing left over to centre in.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
centered?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Renders something other than a `<div>`: `render={<main />}`,
|
|
38
|
+
* `render={<section />}`. Base UI's own escape hatch.
|
|
39
|
+
*/
|
|
40
|
+
render?: useRender.RenderProp;
|
|
41
|
+
children?: React.ReactNode;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Horizontal breathing room, and optionally a measure.
|
|
45
|
+
*
|
|
46
|
+
* Nothing to do with the grid — a Container holds a grid as happily as it holds
|
|
47
|
+
* a single paragraph, and a `GridContainer` needs no Container around it. The
|
|
48
|
+
* two are separate because the questions are separate: how far the content sits
|
|
49
|
+
* from the edge of the window, and how the content divides itself up.
|
|
50
|
+
*
|
|
51
|
+
* It draws no surface for the same reason `GridContainer` does not. The
|
|
52
|
+
* outermost element on a page is the one thing that must not decide what the
|
|
53
|
+
* page looks like.
|
|
54
|
+
*/
|
|
55
|
+
export declare const Container: React.ForwardRefExoticComponent<ContainerProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{boxPaddingXClasses as m}from"../box/Box";const o={xs:"max-w-[30rem]",sm:"max-w-[40rem]",md:"max-w-[48rem]",lg:"max-w-[64rem]",xl:"max-w-[80rem]"};export const Container=e.forwardRef(function({maxWidth:e="none",padded:n=!0,size:a="md",density:t="default",centered:d=!0,render:s,className:i,children:c,...l},x){const f=["block w-full","none"===e?"":o[e],d?"mx-auto":"",n?m[t][a]:"",i??""].filter(Boolean).join(" ");return r({render:s,ref:x,props:{className:f,children:c,...l}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Container}from"./Container";
|