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.
Files changed (141) hide show
  1. package/README.md +169 -2
  2. package/dist/components/accordion/Accordion.d.ts +97 -0
  3. package/dist/components/accordion/Accordion.js +1 -0
  4. package/dist/components/accordion/index.d.ts +2 -0
  5. package/dist/components/accordion/index.js +1 -0
  6. package/dist/components/alert/Alert.d.ts +47 -0
  7. package/dist/components/alert/Alert.js +1 -0
  8. package/dist/components/alert/index.d.ts +2 -0
  9. package/dist/components/alert/index.js +1 -0
  10. package/dist/components/badge/Badge.d.ts +80 -0
  11. package/dist/components/badge/Badge.js +1 -0
  12. package/dist/components/badge/index.d.ts +2 -0
  13. package/dist/components/badge/index.js +1 -0
  14. package/dist/components/box/Box.d.ts +50 -0
  15. package/dist/components/box/Box.js +1 -0
  16. package/dist/components/box/index.d.ts +2 -0
  17. package/dist/components/box/index.js +1 -0
  18. package/dist/components/button/Button.d.ts +25 -3
  19. package/dist/components/button/Button.js +1 -1
  20. package/dist/components/button/index.d.ts +1 -0
  21. package/dist/components/button-group/ButtonGroup.d.ts +31 -0
  22. package/dist/components/button-group/ButtonGroup.js +1 -0
  23. package/dist/components/button-group/index.d.ts +2 -0
  24. package/dist/components/button-group/index.js +1 -0
  25. package/dist/components/card/Card.d.ts +45 -0
  26. package/dist/components/card/Card.js +1 -0
  27. package/dist/components/card/index.d.ts +2 -0
  28. package/dist/components/card/index.js +1 -0
  29. package/dist/components/checkbox/Checkbox.d.ts +39 -0
  30. package/dist/components/checkbox/Checkbox.js +1 -0
  31. package/dist/components/checkbox/index.d.ts +2 -0
  32. package/dist/components/checkbox/index.js +1 -0
  33. package/dist/components/chip/Chip.d.ts +50 -0
  34. package/dist/components/chip/Chip.js +1 -0
  35. package/dist/components/chip/index.d.ts +2 -0
  36. package/dist/components/chip/index.js +1 -0
  37. package/dist/components/combobox/Combobox.d.ts +131 -0
  38. package/dist/components/combobox/Combobox.js +1 -0
  39. package/dist/components/combobox/index.d.ts +2 -0
  40. package/dist/components/combobox/index.js +1 -0
  41. package/dist/components/dialog/Dialog.d.ts +111 -0
  42. package/dist/components/dialog/Dialog.js +1 -0
  43. package/dist/components/dialog/index.d.ts +2 -0
  44. package/dist/components/dialog/index.js +1 -0
  45. package/dist/components/divider/Divider.d.ts +48 -0
  46. package/dist/components/divider/Divider.js +1 -0
  47. package/dist/components/divider/index.d.ts +2 -0
  48. package/dist/components/divider/index.js +1 -0
  49. package/dist/components/file-picker/FilePicker.d.ts +103 -0
  50. package/dist/components/file-picker/FilePicker.js +1 -0
  51. package/dist/components/file-picker/index.d.ts +2 -0
  52. package/dist/components/file-picker/index.js +1 -0
  53. package/dist/components/list/List.d.ts +81 -0
  54. package/dist/components/list/List.js +1 -0
  55. package/dist/components/list/index.d.ts +2 -0
  56. package/dist/components/list/index.js +1 -0
  57. package/dist/components/menu/Menu.d.ts +216 -0
  58. package/dist/components/menu/Menu.js +1 -0
  59. package/dist/components/menu/index.d.ts +2 -0
  60. package/dist/components/menu/index.js +1 -0
  61. package/dist/components/number-field/NumberField.d.ts +113 -0
  62. package/dist/components/number-field/NumberField.js +1 -0
  63. package/dist/components/number-field/index.d.ts +2 -0
  64. package/dist/components/number-field/index.js +1 -0
  65. package/dist/components/overlay/Overlay.d.ts +85 -0
  66. package/dist/components/overlay/Overlay.js +1 -0
  67. package/dist/components/overlay/index.d.ts +2 -0
  68. package/dist/components/overlay/index.js +1 -0
  69. package/dist/components/pagination/Pagination.d.ts +65 -0
  70. package/dist/components/pagination/Pagination.js +1 -0
  71. package/dist/components/pagination/index.d.ts +2 -0
  72. package/dist/components/pagination/index.js +1 -0
  73. package/dist/components/progress-box/ProgressBox.d.ts +33 -0
  74. package/dist/components/progress-box/ProgressBox.js +1 -0
  75. package/dist/components/progress-box/index.d.ts +2 -0
  76. package/dist/components/progress-box/index.js +1 -0
  77. package/dist/components/progress-circular/ProgressCircular.d.ts +19 -0
  78. package/dist/components/progress-circular/ProgressCircular.js +1 -0
  79. package/dist/components/progress-circular/index.d.ts +2 -0
  80. package/dist/components/progress-circular/index.js +1 -0
  81. package/dist/components/progress-linear/ProgressLinear.d.ts +20 -0
  82. package/dist/components/progress-linear/ProgressLinear.js +1 -0
  83. package/dist/components/progress-linear/index.d.ts +2 -0
  84. package/dist/components/progress-linear/index.js +1 -0
  85. package/dist/components/radio-group/RadioGroup.d.ts +51 -0
  86. package/dist/components/radio-group/RadioGroup.js +1 -0
  87. package/dist/components/radio-group/index.d.ts +2 -0
  88. package/dist/components/radio-group/index.js +1 -0
  89. package/dist/components/select/Select.d.ts +76 -0
  90. package/dist/components/select/Select.js +1 -0
  91. package/dist/components/select/index.d.ts +2 -0
  92. package/dist/components/select/index.js +1 -0
  93. package/dist/components/slider/Slider.d.ts +38 -0
  94. package/dist/components/slider/Slider.js +1 -0
  95. package/dist/components/slider/index.d.ts +2 -0
  96. package/dist/components/slider/index.js +1 -0
  97. package/dist/components/switch/Switch.d.ts +39 -0
  98. package/dist/components/switch/Switch.js +1 -0
  99. package/dist/components/switch/index.d.ts +2 -0
  100. package/dist/components/switch/index.js +1 -0
  101. package/dist/components/table/Table.d.ts +80 -0
  102. package/dist/components/table/Table.js +1 -0
  103. package/dist/components/table/index.d.ts +2 -0
  104. package/dist/components/table/index.js +1 -0
  105. package/dist/components/tabs/Tabs.d.ts +92 -0
  106. package/dist/components/tabs/Tabs.js +1 -0
  107. package/dist/components/tabs/index.d.ts +2 -0
  108. package/dist/components/tabs/index.js +1 -0
  109. package/dist/components/text-field/TextField.d.ts +63 -0
  110. package/dist/components/text-field/TextField.js +1 -0
  111. package/dist/components/text-field/index.d.ts +2 -0
  112. package/dist/components/text-field/index.js +1 -0
  113. package/dist/components/toast/Toast.d.ts +116 -0
  114. package/dist/components/toast/Toast.js +1 -0
  115. package/dist/components/toast/index.d.ts +2 -0
  116. package/dist/components/toast/index.js +1 -0
  117. package/dist/components/tooltip/Tooltip.d.ts +81 -0
  118. package/dist/components/tooltip/Tooltip.js +1 -0
  119. package/dist/components/tooltip/index.d.ts +2 -0
  120. package/dist/components/tooltip/index.js +1 -0
  121. package/dist/components/typography/Typography.d.ts +62 -0
  122. package/dist/components/typography/Typography.js +1 -0
  123. package/dist/components/typography/index.d.ts +2 -0
  124. package/dist/components/typography/index.js +1 -0
  125. package/dist/index.d.ts +32 -1
  126. package/dist/index.js +1 -1
  127. package/dist/internal/button-group.d.ts +25 -0
  128. package/dist/internal/button-group.js +1 -0
  129. package/dist/internal/icons.d.ts +48 -0
  130. package/dist/internal/icons.js +1 -0
  131. package/dist/internal/menu.d.ts +20 -0
  132. package/dist/internal/menu.js +1 -0
  133. package/dist/internal/progress.d.ts +122 -0
  134. package/dist/internal/progress.js +1 -0
  135. package/dist/internal/styles.d.ts +224 -0
  136. package/dist/internal/styles.js +1 -0
  137. package/dist/styles.css +758 -0
  138. package/dist/types.d.ts +77 -0
  139. package/dist/types.js +8 -0
  140. package/package.json +75 -19
  141. package/pnpm-workspace.yaml +0 -2
@@ -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,2 @@
1
+ export { Card } from './Card';
2
+ export type { CardProps } from './Card';
@@ -0,0 +1 @@
1
+ export{Card}from"./Card";
@@ -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 a}from"react/jsx-runtime";import*as n from"react";import{Checkbox as r}from"@base-ui/react/checkbox";import{Field as l}from"@base-ui/react/field";import{controlTextClasses as i,metaTextClasses as o,surfaceClasses as t,tickRadiusClasses as s,tickSizeClasses as d,transitionClasses as c}from"../../internal/styles";const b=["relative inline-flex shrink-0 items-center justify-center 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=[t,"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)","data-[indeterminate]:bg-(--n-fill) data-[indeterminate]:text-(--n-on-solid)","data-[indeterminate]:[border-color:transparent]"].join(" "),f=[t,"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(" "),v=["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 m(){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=n.forwardRef(function({size:n="md",color:t="primary",label:c,description:u,error:g,invalid:x,disabled:k=!1,readOnly:j=!1,className:N,style:w,...$},y){const z=null!=g&&!1!==g&&""!==g,C=x??z,L=C?"danger":t,B={"--n-fill":`var(--neba-${L}-fill)`,"--n-fill-hover":`var(--neba-${L}-fill-hover)`,"--n-on-solid":`var(--neba-${L}-on-solid)`,"--n-accent":`var(--neba-${L}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${L}-line)`,"--n-line-hover":`var(--neba-${L}-line-hover)`,"--n-ring":`var(--neba-${L}-ring)`},R=[b,d[n],s[n],k?v:j?f:h].join(" ");return a(l.Root,{disabled:k,invalid:C,className:["inline-flex flex-col gap-1 align-top",N??""].filter(Boolean).join(" "),style:{...B,...w},children:[a("div",{className:`flex items-start gap-2 ${i[n]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(r.Root,{ref:y,className:R,disabled:k,readOnly:j,...$,children:e(r.Indicator,{className:"flex size-[70%] items-center justify-center",children:$.indeterminate?e(p,{}):e(m,{})})})}),c||u?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[c?e(l.Label,{className:["leading-[1.4]",k?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:c}):null,u?e(l.Description,{className:`${o[n]} text-(--neba-muted-fg)`,children:u}):null]}):null]}),z?e(l.Error,{match:!0,className:`${o[n]} text-(--n-accent)`,children:g}):null]})});
@@ -0,0 +1,2 @@
1
+ export { Checkbox } from './Checkbox';
2
+ export type { CheckboxProps } from './Checkbox';
@@ -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,2 @@
1
+ export { Chip } from './Chip';
2
+ export type { ChipProps } from './Chip';
@@ -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 I}from"../../internal/styles";const S=["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent]",I,"focus-within:[transition-duration:0ms]",f,v].join(" "),$={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",I,"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(" "),_=["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:I="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,Ie=l.useMemo(()=>null===Le?be:[...be,{value:Le,label:Le,custom:!0}],[be,Le]),Se=he?xe.map(Ne):xe.length>0?Ne(xe[0]):null;const $e=N[I][v],Oe=[S,m[v],w[v],g[v],he?$[v]:u[v],`${$e} 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=e(n.Input,{ref:oe,placeholder:H,className:he?`${Ve} min-w-16 h-[1lh]`: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:Ie,multiple:he,value:Se,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]})})}):_e,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]}`,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,2 @@
1
+ export { Combobox } from './Combobox';
2
+ export type { ComboboxOption, ComboboxProps, ComboboxValue } from './Combobox';
@@ -0,0 +1 @@
1
+ export{Combobox}from"./Combobox";
@@ -0,0 +1,111 @@
1
+ import * as React from 'react';
2
+ import { Dialog as BaseUIDialog } from '@base-ui/react/dialog';
3
+ import type { NebaStyleProps } from '../../types';
4
+ /**
5
+ * A dialog takes `size`, `color` and `density` and stops there.
6
+ *
7
+ * There is no `variant`: the three weights answer "how much does this surface
8
+ * assert itself against the page around it", and a modal has already taken the
9
+ * page. There is no `elevation` either — see `popupClasses`.
10
+ */
11
+ export interface DialogProps extends Pick<NebaStyleProps, 'size' | 'color' | 'density'> {
12
+ /** The dialog is shown. Use with `onOpenChange` for a controlled dialog. */
13
+ open?: boolean;
14
+ /** Whether the dialog starts open, for an uncontrolled one. */
15
+ defaultOpen?: boolean;
16
+ onOpenChange?: (open: boolean) => void;
17
+ /**
18
+ * The element that opens the dialog, wired up by Base UI. Optional — a
19
+ * controlled dialog opened from somewhere else in the app needs no trigger at
20
+ * all, and passing one here is only a convenience for the common case.
21
+ */
22
+ trigger?: React.ReactElement;
23
+ /** The heading. Rendered as the `<h2>` that names the dialog. */
24
+ title?: React.ReactNode;
25
+ /** A line under the title, and the dialog's accessible description. */
26
+ description?: React.ReactNode;
27
+ /**
28
+ * The bottom row. Laid out end-aligned, so a pair of buttons needs no wrapper
29
+ * of its own — and `DialogClose` is what makes one of them dismiss.
30
+ */
31
+ actions?: React.ReactNode;
32
+ /**
33
+ * Draws a hairline between the header, the body and the actions instead of
34
+ * separating them with space. Worth turning on the moment the body scrolls:
35
+ * the lines are what say the header stayed put.
36
+ * @default false
37
+ */
38
+ dividers?: boolean;
39
+ /**
40
+ * Shows the × in the corner.
41
+ *
42
+ * On by default, unlike most booleans in the library. A modal dialog takes the
43
+ * page away until it is answered, and the visible way out should not have to
44
+ * be remembered.
45
+ * @default true
46
+ */
47
+ showClose?: boolean;
48
+ /** Accessible name of the × button. */
49
+ closeLabel?: string;
50
+ /**
51
+ * A hard cap on the sheet's width, overriding the one `size` implies. Numbers
52
+ * are pixels. For the dialog whose content decides its width — a wide table,
53
+ * a narrow confirmation — rather than for tuning the scale, which is `size`.
54
+ */
55
+ width?: number | string;
56
+ /**
57
+ * The sheet takes the full width its `size` allows.
58
+ *
59
+ * On by default, which is the other way round from every other component.
60
+ * Elsewhere `fullWidth` means "fill the container"; a dialog's container is
61
+ * the viewport, and a dialog that shrank to fit two words would be a tooltip.
62
+ * @default true
63
+ */
64
+ fullWidth?: boolean;
65
+ /** Fills the viewport edge to edge. For a mobile-sized screen, or an editor. */
66
+ fullScreen?: boolean;
67
+ /**
68
+ * Whether the page behind is taken away. `'trap-focus'` keeps the page
69
+ * scrollable and clickable while still holding focus inside.
70
+ * @default true
71
+ */
72
+ modal?: boolean | 'trap-focus';
73
+ /**
74
+ * Whether pressing Escape or clicking outside closes the dialog. Turn it off
75
+ * for the dialog that has to be answered — and then give it actions that
76
+ * answer it, because there will be no other way out.
77
+ * @default true
78
+ */
79
+ dismissible?: boolean;
80
+ /** The body. */
81
+ children?: React.ReactNode;
82
+ className?: string;
83
+ style?: React.CSSProperties;
84
+ }
85
+ export type DialogCloseProps = React.ComponentPropsWithoutRef<typeof BaseUIDialog.Close>;
86
+ /**
87
+ * Closes the dialog it is inside.
88
+ *
89
+ * Exported because an uncontrolled dialog has no `setOpen` for its Cancel
90
+ * button to call, and the alternative — making every dialog controlled — is a
91
+ * piece of state per dialog that exists only to answer a button.
92
+ *
93
+ * `render` is Base UI's own escape hatch, so a real Neba button dismisses:
94
+ * `<DialogClose render={<Button variant="text">Cancel</Button>} />`.
95
+ */
96
+ export declare const DialogClose: React.ForwardRefExoticComponent<Omit<import("@base-ui/react").AlertDialogCloseProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
97
+ /**
98
+ * A sheet that takes the page away until it is answered.
99
+ *
100
+ * The sections are props rather than compound sub-components, exactly as they
101
+ * are on Card: the arrangement of a dialog is fixed — heading, description,
102
+ * body, actions — and what a caller wants to decide is what goes in each slot.
103
+ * Base UI owns everything hard about it: the focus trap, the scroll lock, the
104
+ * `aria-labelledby` / `aria-describedby` wiring, restoring focus to the trigger,
105
+ * and the inert page behind.
106
+ *
107
+ * What is left here is the surface, the width ladder and the scroll behaviour —
108
+ * the header and the actions stay put while only the body scrolls, which is why
109
+ * `dividers` matters more here than on a Card.
110
+ */
111
+ export declare function Dialog({ size, color, density, open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers, showClose, closeLabel, width, fullWidth, fullScreen, modal, dismissible, className, style, children }: DialogProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Dialog as l}from"@base-ui/react/dialog";import{boxPaddingXClasses as n,boxPaddingYClasses as i}from"../box/Box";import{CloseIcon as o}from"../../internal/icons";import{hasContent as r,metaTextClasses as t,radiusClasses as s,sheetBodyClasses as d,sheetHeaderGapClasses as c,sheetSectionGapClasses as m,sheetTitleClasses as f,surfaceClasses as u,surfaceSlots as p}from"../../internal/styles";const x={xs:"max-w-80",sm:"max-w-96",md:"max-w-lg",lg:"max-w-2xl",xl:"max-w-4xl"},b=[u,"relative flex w-full flex-col overflow-hidden","border text-(--neba-fg) bg-(--n-panel-press)","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]","[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),h=["fixed inset-0 z-50 bg-(--neba-scrim)","[backdrop-filter:blur(2px)]","[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),g="border-t [border-color:var(--n-line)]";export const DialogClose=l.Close;export function Dialog({size:u="md",color:v="primary",density:y="default",open:w,defaultOpen:j,onOpenChange:$,trigger:_,title:N,description:k,actions:C,dividers:z=!1,showClose:B=!0,closeLabel:D="Close",width:O,fullWidth:P=!0,fullScreen:T=!1,modal:W=!0,dismissible:L=!0,className:R,style:S,children:V}){const q=n[y][u],A=i[y][u],E=z?`${q} ${A}`:q,F=r(N)||r(k),G=r(C);return a(l.Root,{open:w,defaultOpen:j,modal:W,disablePointerDismissal:!L,onOpenChange:(e,a)=>{L||e||"escape-key"!==a.reason?$?.(e):a.cancel()},children:[_?e(l.Trigger,{render:_}):null,a(l.Portal,{children:[e(l.Backdrop,{className:`neba-portal ${h}`}),e(l.Viewport,{className:["neba-portal fixed inset-0 z-50 flex justify-center",T?"items-stretch":"items-center p-4"].join(" "),children:a(l.Popup,{className:[b,d[u],T?"h-full max-w-none rounded-none":`max-h-full ${s[u]} ${void 0===O?x[u]:""}`,T||P?"":"w-auto",z?"":`${A} ${m[u]}`,R??""].filter(Boolean).join(" "),style:{...p(v,3),...void 0===O?null:{maxWidth:"number"==typeof O?`${O}px`:O},...S},children:[F||B?a("div",{className:`flex shrink-0 items-start gap-3 ${E}`,children:[a("div",{className:`flex min-w-0 flex-1 flex-col ${c[u]}`,children:[r(N)?e(l.Title,{className:`font-semibold ${f[u]} m-0`,children:N}):null,r(k)?e(l.Description,{className:`m-0 text-(--neba-muted-fg) ${t[u]}`,children:k}):null]}),B?e(l.Close,{"aria-label":D,className:["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--neba-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--neba-duration)_var(--neba-ease),color_var(--neba-duration)_var(--neba-ease)]","hover:bg-(--n-soft) hover:text-(--neba-fg)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),children:e(o,{})}):null]}):null,r(V)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",E,z&&(F||B)?g:""].filter(Boolean).join(" "),children:V}):null,G?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",E,z?g:""].filter(Boolean).join(" "),children:C}):null]})})]})]})}
@@ -0,0 +1,2 @@
1
+ export { Dialog, DialogClose } from './Dialog';
2
+ export type { DialogCloseProps, DialogProps } from './Dialog';
@@ -0,0 +1 @@
1
+ export{Dialog,DialogClose}from"./Dialog";
@@ -0,0 +1,48 @@
1
+ import * as React from 'react';
2
+ import type { NebaAlign, NebaColor, NebaOrientation, NebaSize } from '../../types';
3
+ /** Where the label sits along a labelled divider. Ignored without a label. */
4
+ export type DividerTextAlign = NebaAlign;
5
+ export interface DividerProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'children'> {
6
+ /**
7
+ * Which way the line runs. A vertical divider has no height of its own — it
8
+ * stretches to its flex parent, the way a rule between two toolbar groups
9
+ * should.
10
+ * @default 'horizontal'
11
+ */
12
+ orientation?: NebaOrientation;
13
+ /**
14
+ * Semantic colour role. Only the hairline is coloured, and only faintly: this
15
+ * is the same `--n-line` a Card scores its sections with, so a standalone
16
+ * divider and a card's internal one are the same line.
17
+ * @default 'primary'
18
+ */
19
+ color?: NebaColor;
20
+ /** Type scale of the label. Nothing else on a divider has a size. */
21
+ size?: NebaSize;
22
+ /** A label set into the line — "OR" between two sign-in options. */
23
+ children?: React.ReactNode;
24
+ /**
25
+ * Where the label sits. `center` splits the line in half; `start` and `end`
26
+ * leave a short stub on the near side so the label still reads as set *into*
27
+ * the rule rather than floating above it.
28
+ * @default 'center'
29
+ */
30
+ textAlign?: DividerTextAlign;
31
+ }
32
+ /**
33
+ * A rule between two things.
34
+ *
35
+ * With no children it is Base UI's `Separator` and nothing else — a real
36
+ * `role="separator"` with the right `aria-orientation`. With children the line
37
+ * breaks around the label.
38
+ *
39
+ * `separator` is not a name-from-content role, so the visible label does *not*
40
+ * become the accessible name on its own: a screen reader would announce a bare
41
+ * "separator" and the word "OR" would be read as loose text somewhere nearby.
42
+ * A string label is therefore copied into `aria-label`. Anything richer is left
43
+ * alone — only the caller knows which part of it is the name.
44
+ *
45
+ * There is no `variant` and no `elevation`: a divider is not a surface. It has
46
+ * no acrylic, catches no light and casts no shadow.
47
+ */
48
+ export declare const Divider: React.ForwardRefExoticComponent<DividerProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{Separator as a}from"@base-ui/react/separator";import{metaTextClasses as l}from"../../internal/styles";const n="[border-color:var(--n-line)]",i={horizontal:{start:["w-4 shrink-0","flex-1"],center:["flex-1","flex-1"],end:["flex-1","w-4 shrink-0"]},vertical:{start:["h-4 shrink-0","flex-1"],center:["flex-1","flex-1"],end:["flex-1","h-4 shrink-0"]}},o={xs:"gap-1.5",sm:"gap-2",md:"gap-3",lg:"gap-3.5",xl:"gap-4"};export const Divider=t.forwardRef(function({orientation:t="horizontal",color:s="primary",size:c="md",textAlign:f="center",className:m,style:d,children:h,...p},x){const u="vertical"===t,w={"--n-line":`var(--neba-${s}-line)`};if(!(null!=h&&!1!==h&&""!==h))return e(a,{ref:x,orientation:t,className:[u?"w-0 self-stretch border-l":"h-0 w-full border-t",n,m??""].filter(Boolean).join(" "),style:{...w,...d},...p});const[g,b]=i[t][f],v=u?"w-0 border-l":"h-0 border-t";return r(a,{ref:x,orientation:t,"aria-label":"string"==typeof h?h:void 0,className:["flex items-center",u?"w-auto flex-col self-stretch":"w-full",o[c],m??""].filter(Boolean).join(" "),style:{...w,...d},...p,children:[e("span",{"aria-hidden":"true",className:`${v} ${g} ${n}`}),e("span",{className:["shrink-0 whitespace-nowrap text-(--neba-muted-fg)",l[c],u?"[writing-mode:vertical-rl]":""].filter(Boolean).join(" "),children:h}),e("span",{"aria-hidden":"true",className:`${v} ${b} ${n}`})]})});
@@ -0,0 +1,2 @@
1
+ export { Divider } from './Divider';
2
+ export type { DividerProps, DividerTextAlign } from './Divider';
@@ -0,0 +1 @@
1
+ export{Divider}from"./Divider";
@@ -0,0 +1,103 @@
1
+ import * as React from 'react';
2
+ import type { NebaElevation, NebaStyleProps } from '../../types';
3
+ /** Why a file was turned away. One reason per file, in the order they are checked. */
4
+ export type FileRejectionReason = 'type' | 'size' | 'count';
5
+ export interface FileRejection {
6
+ file: File;
7
+ reason: FileRejectionReason;
8
+ }
9
+ export interface FilePickerProps extends NebaStyleProps {
10
+ /**
11
+ * Drop shadow depth. `0` (the default) is flat.
12
+ * @default 0
13
+ */
14
+ elevation?: NebaElevation;
15
+ /**
16
+ * Which files the browser's own picker offers, in the `accept` grammar —
17
+ * `'image/*,.pdf'`. Dropped files are checked against it too, which the
18
+ * attribute alone does not do.
19
+ */
20
+ accept?: string;
21
+ /** Whether more than one file may be chosen. @default false */
22
+ multiple?: boolean;
23
+ /** The largest a single file may be, in bytes. */
24
+ maxSize?: number;
25
+ /**
26
+ * How many files may be held at once. Implies `multiple`, and is checked
27
+ * against what is already chosen rather than against one drop.
28
+ */
29
+ maxFiles?: number;
30
+ /** The chosen files. Use with `onFilesChange` for a controlled picker. */
31
+ value?: readonly File[];
32
+ /** The initially chosen files, for an uncontrolled one. */
33
+ defaultValue?: readonly File[];
34
+ onFilesChange?: (files: File[]) => void;
35
+ /**
36
+ * Called with everything that was turned away, and why. Without it a rejected
37
+ * file disappears silently, which is the single worst thing a dropzone does.
38
+ */
39
+ onReject?: (rejections: FileRejection[]) => void;
40
+ /** Label above the box. */
41
+ label?: React.ReactNode;
42
+ /** Helper text below the box. */
43
+ description?: React.ReactNode;
44
+ /** Error message below. Its presence also turns the picker invalid. */
45
+ error?: React.ReactNode;
46
+ /** Forces the invalid state without a message. Defaults to `!!error`. */
47
+ invalid?: boolean;
48
+ /** The line inside the box. Defaults to an English sentence. */
49
+ title?: React.ReactNode;
50
+ /** The line under it — what is accepted, how big, how many. */
51
+ hint?: React.ReactNode;
52
+ /** The glyph above the title. Pass `null` for a box with no picture in it. */
53
+ icon?: React.ReactNode;
54
+ /**
55
+ * Lists the chosen files under the box, each with a way to remove it.
56
+ * @default true
57
+ */
58
+ showList?: boolean;
59
+ /** Accessible name of a file's remove button. Receives the file's name. */
60
+ removeLabel?: (name: string) => string;
61
+ /** Stretches to the width of the container. @default true */
62
+ fullWidth?: boolean;
63
+ /** Unavailable. */
64
+ disabled?: boolean;
65
+ /** The files are shown but cannot be added to or removed. */
66
+ readOnly?: boolean;
67
+ /** Whether a file must be chosen before the form is submitted. */
68
+ required?: boolean;
69
+ /** Identifies the field when a form is submitted. */
70
+ name?: string;
71
+ id?: string;
72
+ className?: string;
73
+ style?: React.CSSProperties;
74
+ }
75
+ /**
76
+ * `1.4 MB`, in the units a person reading a file list expects.
77
+ *
78
+ * Base 1000 rather than 1024, and `MB` rather than `MiB`: it is the number every
79
+ * operating system's file browser shows, and a picker that disagrees with the
80
+ * Finder about how big the file is has picked a fight it cannot win.
81
+ */
82
+ export declare function formatFileSize(bytes: number): string;
83
+ /**
84
+ * A box you drop files on, or click to open the file dialog.
85
+ *
86
+ * There is no Base UI primitive under this, and the fallback the library allows
87
+ * — plain React and DOM — is the right one: a dropzone is a `<div>` listening
88
+ * for four drag events and an `<input type="file">` it clicks for you. There is
89
+ * no popup to position, no focus to trap and no roving anything.
90
+ *
91
+ * What that leaves is the part every hand-rolled dropzone gets wrong. The drag
92
+ * counter is one of them: `dragenter` and `dragleave` both fire as the pointer
93
+ * crosses a *child* of the zone, so a zone that toggles a boolean flickers the
94
+ * whole time a file is being dragged across its own contents. Counting them is
95
+ * the fix. The other is `accept`, which the browser enforces on its own dialog
96
+ * and never on a drop, so a dropzone that only sets the attribute accepts
97
+ * anything the moment a file arrives by drag.
98
+ *
99
+ * The shell is a `<div>` and the pressable area inside it is a real `<button>`,
100
+ * with the file list outside that button — the same shape Chip and ListItem
101
+ * use, because the remove buttons cannot be nested inside the browse button.
102
+ */
103
+ export declare const FilePicker: React.ForwardRefExoticComponent<FilePickerProps & React.RefAttributes<HTMLInputElement>>;