neba 1.0.0 → 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.
Files changed (102) hide show
  1. package/README.md +23 -15
  2. package/dist/components/blockquote/Blockquote.d.ts +65 -0
  3. package/dist/components/blockquote/Blockquote.js +1 -0
  4. package/dist/components/blockquote/index.d.ts +2 -0
  5. package/dist/components/blockquote/index.js +1 -0
  6. package/dist/components/carousel/Carousel.d.ts +74 -0
  7. package/dist/components/carousel/Carousel.js +1 -0
  8. package/dist/components/carousel/index.d.ts +2 -0
  9. package/dist/components/carousel/index.js +1 -0
  10. package/dist/components/checkbox/Checkbox.js +1 -1
  11. package/dist/components/combobox/Combobox.js +1 -1
  12. package/dist/components/container/Container.d.ts +55 -0
  13. package/dist/components/container/Container.js +1 -0
  14. package/dist/components/container/index.d.ts +2 -0
  15. package/dist/components/container/index.js +1 -0
  16. package/dist/components/date-picker/DatePicker.d.ts +75 -0
  17. package/dist/components/date-picker/DatePicker.js +1 -0
  18. package/dist/components/date-picker/index.d.ts +2 -0
  19. package/dist/components/date-picker/index.js +1 -0
  20. package/dist/components/date-range-picker/DateRangePicker.d.ts +81 -0
  21. package/dist/components/date-range-picker/DateRangePicker.js +1 -0
  22. package/dist/components/date-range-picker/index.d.ts +2 -0
  23. package/dist/components/date-range-picker/index.js +1 -0
  24. package/dist/components/date-time-picker/DateTimePicker.d.ts +68 -0
  25. package/dist/components/date-time-picker/DateTimePicker.js +1 -0
  26. package/dist/components/date-time-picker/index.d.ts +2 -0
  27. package/dist/components/date-time-picker/index.js +1 -0
  28. package/dist/components/dialog/Dialog.js +1 -1
  29. package/dist/components/divider/Divider.d.ts +19 -0
  30. package/dist/components/divider/Divider.js +1 -1
  31. package/dist/components/grid/Grid.d.ts +50 -0
  32. package/dist/components/grid/Grid.js +1 -0
  33. package/dist/components/grid/index.d.ts +2 -0
  34. package/dist/components/grid/index.js +1 -0
  35. package/dist/components/grid-container/GridContainer.d.ts +79 -0
  36. package/dist/components/grid-container/GridContainer.js +1 -0
  37. package/dist/components/grid-container/index.d.ts +2 -0
  38. package/dist/components/grid-container/index.js +1 -0
  39. package/dist/components/highlight/Highlight.d.ts +84 -0
  40. package/dist/components/highlight/Highlight.js +1 -0
  41. package/dist/components/highlight/index.d.ts +2 -0
  42. package/dist/components/highlight/index.js +1 -0
  43. package/dist/components/icon/Icon.d.ts +58 -0
  44. package/dist/components/icon/Icon.js +1 -0
  45. package/dist/components/icon/index.d.ts +2 -0
  46. package/dist/components/icon/index.js +1 -0
  47. package/dist/components/icon-button/IconButton.d.ts +39 -0
  48. package/dist/components/icon-button/IconButton.js +1 -0
  49. package/dist/components/icon-button/index.d.ts +2 -0
  50. package/dist/components/icon-button/index.js +1 -0
  51. package/dist/components/pagination/Pagination.js +1 -1
  52. package/dist/components/pill/Pill.d.ts +80 -0
  53. package/dist/components/pill/Pill.js +1 -0
  54. package/dist/components/pill/index.d.ts +2 -0
  55. package/dist/components/pill/index.js +1 -0
  56. package/dist/components/radio-group/RadioGroup.js +1 -1
  57. package/dist/components/segmented-button/SegmentedButton.d.ts +77 -0
  58. package/dist/components/segmented-button/SegmentedButton.js +1 -0
  59. package/dist/components/segmented-button/index.d.ts +2 -0
  60. package/dist/components/segmented-button/index.js +1 -0
  61. package/dist/components/select/Select.js +1 -1
  62. package/dist/components/shortcut/Shortcut.d.ts +60 -0
  63. package/dist/components/shortcut/Shortcut.js +1 -0
  64. package/dist/components/shortcut/index.d.ts +2 -0
  65. package/dist/components/shortcut/index.js +1 -0
  66. package/dist/components/statistic/Statistic.d.ts +91 -0
  67. package/dist/components/statistic/Statistic.js +1 -0
  68. package/dist/components/statistic/index.d.ts +2 -0
  69. package/dist/components/statistic/index.js +1 -0
  70. package/dist/components/switch/Switch.js +1 -1
  71. package/dist/components/time-picker/TimePicker.d.ts +76 -0
  72. package/dist/components/time-picker/TimePicker.js +1 -0
  73. package/dist/components/time-picker/index.d.ts +2 -0
  74. package/dist/components/time-picker/index.js +1 -0
  75. package/dist/components/timeline/Timeline.d.ts +98 -0
  76. package/dist/components/timeline/Timeline.js +1 -0
  77. package/dist/components/timeline/index.d.ts +2 -0
  78. package/dist/components/timeline/index.js +1 -0
  79. package/dist/components/toolbar/Toolbar.d.ts +67 -0
  80. package/dist/components/toolbar/Toolbar.js +1 -0
  81. package/dist/components/toolbar/index.d.ts +2 -0
  82. package/dist/components/toolbar/index.js +1 -0
  83. package/dist/index.d.ts +18 -0
  84. package/dist/index.js +1 -1
  85. package/dist/internal/calendar.d.ts +149 -0
  86. package/dist/internal/calendar.js +1 -0
  87. package/dist/internal/date.d.ts +170 -0
  88. package/dist/internal/date.js +1 -0
  89. package/dist/internal/grid.d.ts +69 -0
  90. package/dist/internal/grid.js +1 -0
  91. package/dist/internal/icons.d.ts +31 -0
  92. package/dist/internal/icons.js +1 -1
  93. package/dist/internal/picker.d.ts +111 -0
  94. package/dist/internal/picker.js +1 -0
  95. package/dist/internal/sizer.d.ts +33 -0
  96. package/dist/internal/sizer.js +1 -0
  97. package/dist/internal/styles.d.ts +33 -0
  98. package/dist/internal/styles.js +1 -1
  99. package/dist/styles.css +2 -758
  100. package/dist/tailwind.css +892 -0
  101. package/dist/types.d.ts +65 -0
  102. package/package.json +18 -5
@@ -0,0 +1,68 @@
1
+ import * as React from 'react';
2
+ import { type PickerLabels } from '../../internal/calendar';
3
+ import { type PickerShellProps } from '../../internal/picker';
4
+ import { type TimeUnit } from '../../internal/date';
5
+ import type { NebaWeekday } from '../../types';
6
+ export interface DateTimePickerProps extends PickerShellProps {
7
+ /** The chosen moment. Use with `onValueChange` for a controlled picker. */
8
+ value?: Date | null;
9
+ defaultValue?: Date | null;
10
+ onValueChange?: (value: Date | null) => void;
11
+ open?: boolean;
12
+ defaultOpen?: boolean;
13
+ onOpenChange?: (open: boolean) => void;
14
+ /** Which month the calendar opens on when there is no value. */
15
+ defaultMonth?: Date;
16
+ /**
17
+ * The earliest moment that may be chosen. Unlike DatePicker's, this one is
18
+ * read at full precision: the day it falls on stays available and the clock
19
+ * columns block the hours before it.
20
+ */
21
+ minDate?: Date | null;
22
+ /** The latest moment that may be chosen, likewise at full precision. */
23
+ maxDate?: Date | null;
24
+ shouldDisableDate?: (date: Date) => boolean;
25
+ shouldDisableTime?: (value: Date, unit: TimeUnit) => boolean;
26
+ locale?: string;
27
+ weekStartsOn?: NebaWeekday;
28
+ /**
29
+ * How the trigger writes the chosen moment. Passed straight to `Intl`.
30
+ * @default { dateStyle: 'medium', timeStyle: 'short' }
31
+ */
32
+ format?: Intl.DateTimeFormatOptions;
33
+ /** A 12-hour dial with an AM/PM column. Defaults to whatever the locale does. */
34
+ hour12?: boolean;
35
+ showSeconds?: boolean;
36
+ hourStep?: number;
37
+ minuteStep?: number;
38
+ secondStep?: number;
39
+ placeholder?: React.ReactNode;
40
+ clearable?: boolean;
41
+ /** Offers the shortcut to this moment in the footer. @default true */
42
+ showNowButton?: boolean;
43
+ /**
44
+ * Closes the popup as soon as a day is chosen. `false` here and `true` on
45
+ * DatePicker, because a moment is a day *and* a time and closing on the first
46
+ * of the two would leave the second one unanswered.
47
+ * @default false
48
+ */
49
+ closeOnSelect?: boolean;
50
+ labels?: Partial<PickerLabels>;
51
+ /** Identifies the field when a form is submitted, as `YYYY-MM-DDTHH:MM`. */
52
+ name?: string;
53
+ }
54
+ /**
55
+ * A day and a time, in one popup.
56
+ *
57
+ * Not a DatePicker that grew a clock and not a TimePicker that grew a calendar:
58
+ * the two panels sit side by side at exactly the same height — seven rows of
59
+ * cells each, which is why the calendar's grid and the clock's columns share the
60
+ * `--n-cell` ladder — so the popup is one rectangle rather than two of different
61
+ * sizes pushed together.
62
+ *
63
+ * The bounds do more work here than anywhere else. `minDate` is read at full
64
+ * precision, so a minimum of 09:30 on the 27th leaves the 27th selectable in the
65
+ * calendar and greys out the morning in the clock. That is the behaviour a
66
+ * "not before now" rule needs, and it is the one a day-granular check cannot give.
67
+ */
68
+ export declare const DateTimePicker: React.ForwardRefExoticComponent<DateTimePickerProps & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Button as o}from"../button/Button";import{Calendar as n,TimeGrid as a,usePickerLabels as s}from"../../internal/calendar";import{CalendarIcon as i}from"../../internal/icons";import{PickerDivider as r,PickerFooter as c,PickerShell as d}from"../../internal/picker";import{displaySamples as m,formatDate as u,isDayOutside as h,isHour12 as p,isValidDate as f,localeWeekStart as S,mergeDateAndTime as b,startOfDay as y,startOfMonth as D,timeUnitSpan as g,toISODateTime as v,today as x,withPlaceholder as C,withTime as w}from"../../internal/date";import{cx as k,gapClasses as z}from"../../internal/styles";export const DateTimePicker=l.forwardRef(function({value:O,defaultValue:T,onValueChange:j,open:N,defaultOpen:V,onOpenChange:B,defaultMonth:I,minDate:M,maxDate:R,shouldDisableDate:E,shouldDisableTime:F,locale:P,weekStartsOn:q,format:A={dateStyle:"medium",timeStyle:"short"},hour12:G,showSeconds:H=!1,hourStep:J=1,minuteStep:K=1,secondStep:L=1,placeholder:Q,clearable:U=!1,showNowButton:W=!0,closeOnSelect:X=!1,labels:Y,name:Z,size:$="md",color:_="primary",density:ee="default",readOnly:te=!1,disabled:le=!1,startIcon:oe,...ne},ae){const se=s(Y),ie=q??S(P),re=G??p(P),[ce,de]=l.useState(T??null),me=void 0!==O?O:ce,[ue,he]=l.useState(V??!1),pe=N??ue,[fe,Se]=l.useState(()=>D(f(me)?me:I??x()));l.useEffect(()=>{pe&&Se(D(f(me)?me:I??x()))},[pe]);const be=e=>{e&&(te||le)||(void 0===N&&he(e),B?.(e))},ye=e=>{void 0===O&&de(e),j?.(e)},De=l.useCallback((e,t)=>{const[l,o]=g(t,e),n=y(e).getTime();return!!(f(M)&&n+1e3*o<M.getTime())||(!!(f(R)&&n+1e3*l>R.getTime())||(F?.(e,t)??!1))},[M,R,F]),ge=new Date,ve=w(ge,{seconds:H?ge.getSeconds():0}),xe=h(ve,M,R)||(E?.(ve)??!1)||De(ve,"second"),Ce=C(m(P,A),Q);return e(d,{...ne,size:$,color:_,density:ee,readOnly:te,disabled:le,triggerRef:ae,startIcon:oe??e(i,{}),display:f(me)?u(me,P,A):Q??"",samples:Ce,empty:!f(me),clearable:U,onClear:()=>ye(null),open:pe,onOpenChange:be,labels:se,hiddenValues:Z?[{name:Z,value:f(me)?v(me,H):""}]:void 0,children:t("div",{className:"flex flex-col gap-1.5",children:[t("div",{className:k("flex items-stretch",z[$]),children:[e(n,{size:$,color:_,locale:P,weekStartsOn:ie,month:fe,onMonthChange:Se,selected:[me],onSelect:e=>{const t=f(me)?b(e,me):y(e);ye(t),Se(D(t)),X&&be(!1)},minDate:M,maxDate:R,shouldDisableDate:E,labels:se,autoFocus:!0}),e(r,{}),e(a,{size:$,density:ee,locale:P,value:f(me)?me:null,referenceDate:f(me)?me:x(),onChange:ye,hour12:re,showSeconds:H,hourStep:J,minuteStep:K,secondStep:L,shouldDisableTime:De,labels:se})]}),t(c,{size:$,children:[U?e(o,{variant:"text",size:$,color:_,density:"compact",onClick:()=>{ye(null),be(!1)},children:se.clear}):null,W?e(o,{variant:"text",size:$,color:_,density:"compact",disabled:xe,onClick:()=>{ye(ve),Se(D(ve))},children:se.now}):null,e(o,{variant:"solid",size:$,color:_,density:"compact",onClick:()=>be(!1),children:se.done})]})]})})});
@@ -0,0 +1,2 @@
1
+ export { DateTimePicker } from './DateTimePicker';
2
+ export type { DateTimePickerProps } from './DateTimePicker';
@@ -0,0 +1 @@
1
+ export{DateTimePicker}from"./DateTimePicker";
@@ -1 +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]})})]})]})}
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:"",z?"":"py-1 -my-1"].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]})})]})]})}
@@ -19,6 +19,25 @@ export interface DividerProps extends Omit<React.ComponentPropsWithoutRef<'div'>
19
19
  color?: NebaColor;
20
20
  /** Type scale of the label. Nothing else on a divider has a size. */
21
21
  size?: NebaSize;
22
+ /**
23
+ * How far the rule runs — the width of a horizontal divider, the height of a
24
+ * vertical one. A number is pixels; a string is any CSS length, so `'50%'`
25
+ * and `'12rem'` both work.
26
+ *
27
+ * `length` rather than `width`, because a divider is the one component whose
28
+ * long axis turns with `orientation`: a `width` that meant height half the
29
+ * time would be a worse name than a longer one.
30
+ *
31
+ * Left out, a horizontal divider is the full width of its container and a
32
+ * vertical one stretches to the height of the flex row it is in — which is
33
+ * what a rule between two things should do by default.
34
+ */
35
+ length?: number | string;
36
+ /**
37
+ * How thick the rule is. A number is pixels; a string is any CSS length.
38
+ * @default 1
39
+ */
40
+ thickness?: number | string;
22
41
  /** A label set into the line — "OR" between two sign-in options. */
23
42
  children?: React.ReactNode;
24
43
  /**
@@ -1 +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}`})]})});
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{Separator as n}from"@base-ui/react/separator";import{metaTextClasses as l}from"../../internal/styles";const i="[border-color:var(--n-line)]";function a(e){return"number"==typeof e?`${e}px`:e}const o={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"]}},s={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:c="primary",size:d="md",length:f,thickness:h,textAlign:m="center",className:p,style:u,children:x,...w},b){const v="vertical"===t,g=null!=x&&!1!==x&&""!==x,$={"--n-line":`var(--neba-${c}-line)`,"--n-rule":a(h)??"1px"},y=a(f),j={...$,...void 0===y?null:v?{height:y}:{width:y},...u};if(!g)return e(n,{ref:b,orientation:t,className:[v?"w-0 border-l [border-left-width:var(--n-rule)] "+(void 0===y?"self-stretch":""):"h-0 w-full border-t [border-top-width:var(--n-rule)]",i,p??""].filter(Boolean).join(" "),style:j,...w});const[k,N]=o[t][m],z=v?"w-0 border-l [border-left-width:var(--n-rule)]":"h-0 border-t [border-top-width:var(--n-rule)]";return r(n,{ref:b,orientation:t,"aria-label":"string"==typeof x?x:void 0,className:["flex items-center",v?"w-auto flex-col "+(void 0===y?"self-stretch":""):"w-full",s[d],p??""].filter(Boolean).join(" "),style:j,...w,children:[e("span",{"aria-hidden":"true",className:`${z} ${k} ${i}`}),e("span",{className:["shrink-0 whitespace-nowrap text-(--neba-muted-fg)",l[d],v?"[writing-mode:vertical-rl]":""].filter(Boolean).join(" "),children:x}),e("span",{"aria-hidden":"true",className:`${z} ${N} ${i}`})]})});
@@ -0,0 +1,50 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaAlignSelf, NebaResponsive } from '../../types';
4
+ export interface GridProps extends React.ComponentPropsWithoutRef<'div'> {
5
+ /**
6
+ * How many of the container's columns the item takes. Read against the
7
+ * container's `columns`, so `span={6}` is a half of the default twelve and a
8
+ * quarter of `columns={24}`.
9
+ *
10
+ * Responsive: `span={{ xs: 12, md: 6, lg: 4 }}` is full width on a phone,
11
+ * half from 48rem and a third from 64rem. Every entry applies from its own
12
+ * breakpoint up, so two of them usually describe a whole layout.
13
+ *
14
+ * A span wider than the row is clamped to the row rather than overflowing.
15
+ * @default the container's full width
16
+ */
17
+ span?: NebaResponsive<number>;
18
+ /**
19
+ * Columns left empty *before* the item — space pushed in ahead of it, not an
20
+ * absolute position in the row. First in a twelve-column row, `offset={4}`
21
+ * with `span={4}` is the middle third; after an item that already took four
22
+ * columns, the same offset skips four more and lands on the last third.
23
+ *
24
+ * Responsive in the same way `span` is.
25
+ * @default 0
26
+ */
27
+ offset?: NebaResponsive<number>;
28
+ /** Overrides the row's `alignItems` for this item alone. */
29
+ alignSelf?: NebaAlignSelf;
30
+ /**
31
+ * Renders something other than a `<div>`: `render={<li />}`,
32
+ * `render={<article />}`. Base UI's own escape hatch.
33
+ */
34
+ render?: useRender.RenderProp;
35
+ children?: React.ReactNode;
36
+ }
37
+ /**
38
+ * One cell of a `GridContainer`.
39
+ *
40
+ * It is a width and nothing else — no surface, no padding, no typography. What
41
+ * goes inside brings its own, which is the whole reason a grid cell and a Box
42
+ * are two components: wrapping something in a layout should not change how it
43
+ * looks, and a cell that drew a sheet would make `span` a visual decision.
44
+ *
45
+ * The column count it divides by is inherited from the container as a custom
46
+ * property, so a `<Grid>` with no `<GridContainer>` above it falls back to
47
+ * twelve rather than breaking — but it will be a plain block in a plain parent,
48
+ * which is not a layout. Always wrap.
49
+ */
50
+ export declare const Grid: React.ForwardRefExoticComponent<GridProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{alignSelfClasses as n,offsetValue as o,responsiveSlots as t,spanValue as s}from"../../internal/grid";export const Grid=e.forwardRef(function({span:e,offset:a,alignSelf:i,render:f,className:l,style:c,children:d,...m},p){const u=["neba-grid-item",i?n[i]:"",l??""].filter(Boolean).join(" ");return r({render:f,ref:p,props:{className:u,style:{...t("span",e,s),...t("offset",a,o),...c},children:d,...m}})});
@@ -0,0 +1,2 @@
1
+ export { Grid } from './Grid';
2
+ export type { GridProps } from './Grid';
@@ -0,0 +1 @@
1
+ export{Grid}from"./Grid";
@@ -0,0 +1,79 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaAlignItems, NebaDensity, NebaJustifyContent, NebaResponsive, NebaSize } from '../../types';
4
+ export interface GridContainerProps extends React.ComponentPropsWithoutRef<'div'> {
5
+ /**
6
+ * How many columns a row is divided into. Every `span` and every `offset`
7
+ * inside is read against this number, so `columns={24}` makes `span={12}` a
8
+ * half and not a full width.
9
+ * @default 12
10
+ */
11
+ columns?: NebaResponsive<number>;
12
+ /**
13
+ * The gutter between items, on Tailwind's spacing scale — `spacing={4}` is
14
+ * `1rem`, the same length `gap-4` is. Fractions are allowed, so `1.5` is
15
+ * `0.375rem`.
16
+ * @default 2
17
+ */
18
+ spacing?: NebaResponsive<number>;
19
+ /** The gutter between rows only. Falls back to `spacing`. */
20
+ rowSpacing?: NebaResponsive<number>;
21
+ /** The gutter between columns only. Falls back to `spacing`. */
22
+ columnSpacing?: NebaResponsive<number>;
23
+ /** How a row distributes the space its items did not use. */
24
+ justifyContent?: NebaJustifyContent;
25
+ /** How items sit against each other across the row. @default 'stretch' */
26
+ alignItems?: NebaAlignItems;
27
+ /** Where the rows sit when the grid is shorter than the box holding it. */
28
+ alignContent?: NebaJustifyContent;
29
+ /**
30
+ * Whether a row that runs out of columns continues on the next one. Turning
31
+ * it off gives one row that overflows, which is what a horizontally
32
+ * scrolling strip wants.
33
+ * @default true
34
+ */
35
+ wrap?: boolean;
36
+ /**
37
+ * Inner padding, on the `size`/`density` scale. Turn it off when the grid is
38
+ * already inside something that pads — a Container, a Card, another grid.
39
+ * @default true
40
+ */
41
+ padded?: boolean;
42
+ /**
43
+ * The padding scale. As on Box, this is the size of the *sheet* — it never
44
+ * touches a height or the type scale, and it has nothing to do with the
45
+ * gutters, which are `spacing`.
46
+ * @default 'md'
47
+ */
48
+ size?: NebaSize;
49
+ /** @default 'default' */
50
+ density?: NebaDensity;
51
+ /**
52
+ * Renders something other than a `<div>`: `render={<section />}`,
53
+ * `render={<ul />}`. Base UI's own escape hatch.
54
+ */
55
+ render?: useRender.RenderProp;
56
+ children?: React.ReactNode;
57
+ }
58
+ /**
59
+ * The parent every `Grid` needs.
60
+ *
61
+ * It owns the three numbers an item cannot know on its own — how many columns
62
+ * there are and how wide the two gutters are — and hands them down as inherited
63
+ * custom properties rather than through a React context. That is not a
64
+ * shortcut: the values are responsive, and a media query can change an
65
+ * inherited custom property without React hearing about it, so the column count
66
+ * an item lays itself out against is always the one that is on screen. A
67
+ * context would have to re-render the tree at every breakpoint to say the same
68
+ * thing.
69
+ *
70
+ * It deliberately does not take `variant`, `color` or `elevation`. A grid is
71
+ * not a surface — it is the arrangement of the surfaces inside it, and the
72
+ * moment it draws its own sheet it stops being usable as the outermost thing on
73
+ * a page. Wrap it in a Box or a Card when the sheet is wanted.
74
+ *
75
+ * Nesting is a `GridContainer` inside a `Grid`, not a `Grid` that is also a
76
+ * container: the inner grid re-declares the column count for its own subtree
77
+ * while the item around it keeps the width the outer grid gave it.
78
+ */
79
+ export declare const GridContainer: React.ForwardRefExoticComponent<GridContainerProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{alignContentClasses as n,alignItemsClasses as a,columnCount as o,justifyContentClasses as t,responsiveSlots as i,spacingValue as p,withBaseline as s}from"../../internal/grid";import{boxPaddingClasses as l}from"../box/Box";export const GridContainer=e.forwardRef(function({columns:e,spacing:c,rowSpacing:d,columnSpacing:f,justifyContent:m,alignItems:g,alignContent:x,wrap:u=!0,padded:y=!0,size:w="md",density:b="default",render:C,className:h,style:j,children:B,...N},S){const z=["neba-grid flex",u?"flex-wrap":"flex-nowrap","gap-x-(--n-gap-x) gap-y-(--n-gap-y)",y?l[b][w]:"",m?t[m]:"",g?a[g]:"",x?n[x]:"",h??""].filter(Boolean).join(" ");return r({render:C,ref:S,props:{className:z,style:{...i("cols",s(e,12),o),...i("gap-x",s(f??c,2),p),...i("gap-y",s(d??c,2),p),...j},children:B,...N}})});
@@ -0,0 +1,2 @@
1
+ export { GridContainer } from './GridContainer';
2
+ export type { GridContainerProps } from './GridContainer';
@@ -0,0 +1 @@
1
+ export{GridContainer}from"./GridContainer";
@@ -0,0 +1,84 @@
1
+ import * as React from 'react';
2
+ import type { TypographyWeight } from '../typography/Typography';
3
+ import type { NebaColor, NebaVariant } from '../../types';
4
+ export interface HighlightProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
5
+ /**
6
+ * What to find.
7
+ *
8
+ * A string is one term, an array is several — the longest is tried first, so
9
+ * `['data', 'database']` marks the whole word rather than the first four
10
+ * letters of it. A `RegExp` is used as written, with the global flag forced
11
+ * on; `caseSensitive` and `wholeWord` are ignored for it, because a regular
12
+ * expression already says both of those things itself.
13
+ */
14
+ query: string | string[] | RegExp;
15
+ /**
16
+ * Weight of the mark.
17
+ *
18
+ * - `solid` — filled, the highlighter pen. The default.
19
+ * - `outline` — a hairline box around the word, for a page where a filled run
20
+ * would be too much.
21
+ * - `text` — the accent colour and nothing else, for marking a word inside a
22
+ * heading that is already loud.
23
+ * @default 'solid'
24
+ */
25
+ variant?: NebaVariant;
26
+ /**
27
+ * Semantic colour role. `warning` by default, and not arbitrarily: it is the
28
+ * one family whose fill is light with dark ink on it, so a solid `warning`
29
+ * mark is a yellow highlighter over black text rather than a white word on a
30
+ * block of colour.
31
+ * @default 'warning'
32
+ */
33
+ color?: NebaColor;
34
+ /**
35
+ * Whether `a` and `A` are different letters.
36
+ * @default false
37
+ */
38
+ caseSensitive?: boolean;
39
+ /**
40
+ * Whether a term has to be a word on its own — `cat` marking "cat" but not
41
+ * "concatenate".
42
+ *
43
+ * A word here is a run of letters, digits and underscores in any script, so it
44
+ * means what it should for `café` and `naïve`. It means very little for Korean
45
+ * or Japanese, where a phrase is not delimited by spaces at all; that is a
46
+ * property of the writing system rather than of this prop, and is the reason
47
+ * it is off by default.
48
+ * @default false
49
+ */
50
+ wholeWord?: boolean;
51
+ /** Underlines the mark as well. Combines with every variant. */
52
+ underline?: boolean;
53
+ /**
54
+ * Sets the mark's weight. Omit it and the mark is the weight of the text
55
+ * around it — the surface is already saying "this one", and a bolded word
56
+ * inside a sentence changes the rhythm of the whole line.
57
+ */
58
+ weight?: TypographyWeight;
59
+ /**
60
+ * The text to search. Elements are walked into and left otherwise untouched,
61
+ * so a match inside a `<strong>` is still marked and the `<strong>` survives.
62
+ */
63
+ children?: React.ReactNode;
64
+ }
65
+ /**
66
+ * Marks the words a reader is looking for, inside text they were already
67
+ * reading.
68
+ *
69
+ * The component is the search, not just the styling: `query` is what a search
70
+ * box holds, and everything about *how* the matching is done — case, whole
71
+ * words, a regular expression — is a prop rather than something a caller has to
72
+ * pre-compute into a list of offsets.
73
+ *
74
+ * The mark is a real `<mark>`, which is the element for "text of relevance to
75
+ * the reader" and is announced as such. That has one consequence worth knowing:
76
+ * marking eleven words in a paragraph tells a screen reader that eleven things
77
+ * are important, which is a way of saying nothing. A highlight is for a handful
78
+ * of matches.
79
+ *
80
+ * Nothing here is stateful and nothing measures — the whole component is a pure
81
+ * function of `children` and `query`, so it re-marks on its own the moment the
82
+ * search box changes.
83
+ */
84
+ export declare const Highlight: React.ForwardRefExoticComponent<HighlightProps & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as n}from"react/jsx-runtime";import*as e from"react";import{transitionClasses as t}from"../../internal/styles";const r={solid:"bg-(--n-fill) text-(--n-on-solid)",outline:"border bg-(--n-panel) text-(--n-accent) [border-color:var(--n-line)]",text:"bg-transparent text-(--n-accent)"},o={regular:"font-normal",medium:"font-medium",semibold:"font-semibold",bold:"font-bold"},l=/[\p{L}\p{N}_]/u;function i(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function a(n,e,t){const r=e>0?n[e-1]:"",o=t<n.length?n[t]:"";return!l.test(r)&&!l.test(o)}function s(n,e,t,r){e.lastIndex=0;const o=[];let l,i=0;for(;null!==(l=e.exec(n));){if(""===l[0]){e.lastIndex+=1;continue}const s=l.index,c=s+l[0].length;t&&!a(n,s,c)||(s>i&&o.push(n.slice(i,s)),o.push(r(l[0],`${s}`)),i=c)}return 0===o.length?n:(i<n.length&&o.push(n.slice(i)),o)}function c(n,t,r,o){if("string"==typeof n)return s(n,t,r,o);if("number"==typeof n)return s(String(n),t,r,o);if(Array.isArray(n))return e.Children.map(n,n=>c(n,t,r,o));if(e.isValidElement(n)){const l=n.props.children;return void 0===l||"function"==typeof l?n:e.cloneElement(n,void 0,c(l,t,r,o))}return n}export const Highlight=e.forwardRef(function({query:l,variant:a="solid",color:s="warning",caseSensitive:u=!1,wholeWord:f=!1,underline:d=!1,weight:m,className:p,style:g,children:h,...b},x){const y=e.useMemo(()=>function(n,e){if(n instanceof RegExp)return n.global?n:new RegExp(n.source,`${n.flags}g`);const t=(Array.isArray(n)?n:[n]).map(n=>n.trim()).filter(Boolean).sort((n,e)=>e.length-n.length);return 0===t.length?null:new RegExp(t.map(i).join("|"),e?"gu":"giu")}(l,u),[l,u]),v=["rounded-[0.25rem] px-0.5 -mx-0.5","box-decoration-clone",r[a],d?"underline decoration-2 underline-offset-2":"",m?o[m]:"",t].filter(Boolean).join(" "),$=y?c(h,y,f,(e,t)=>n("mark",{className:v,children:e},t)):h;return n("span",{ref:x,className:p,style:{"--n-fill":`var(--neba-${s}-fill)`,"--n-on-solid":`var(--neba-${s}-on-solid)`,"--n-accent":`var(--neba-${s}-accent)`,"--n-panel":`var(--neba-${s}-panel)`,"--n-line":`var(--neba-${s}-line)`,...g},...b,children:$})});
@@ -0,0 +1,2 @@
1
+ export { Highlight } from './Highlight';
2
+ export type { HighlightProps } from './Highlight';
@@ -0,0 +1 @@
1
+ export{Highlight}from"./Highlight";
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaSize } from '../../types';
3
+ export interface IconProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
4
+ /**
5
+ * The glyph. An `<svg>` element, an `<img>`, a component from an icon set, or
6
+ * a character — whatever is passed is laid into a box of the right size and
7
+ * given a colour to inherit.
8
+ *
9
+ * It is a prop rather than `children` on purpose. An icon set hands you an
10
+ * element you did not draw, and the two things you always want to change about
11
+ * it — how big it is and what colour it is — are the two things you cannot
12
+ * reach once it is a child of something. As a prop it is content the Icon
13
+ * *sizes*, not content the Icon merely wraps.
14
+ */
15
+ icon: React.ReactNode;
16
+ /**
17
+ * The box the glyph is drawn in: 14, 16, 20, 24 and 28px. Its own ladder
18
+ * rather than the control heights, because an icon is not a control.
19
+ * @default 'md'
20
+ */
21
+ size?: NebaSize;
22
+ /**
23
+ * Semantic colour role, or `inherit` — the default — to take the colour of
24
+ * whatever the icon sits in.
25
+ *
26
+ * `inherit` is the default and not `primary`, which is the one place this prop
27
+ * deviates from every other component in the library. An icon is content, and
28
+ * the overwhelmingly common case is an icon inside something that has already
29
+ * decided what colour its content is: a Button's label, a muted caption, an
30
+ * Alert's own family. An Icon that arrived pre-dyed blue would have to be
31
+ * turned off again at every one of those.
32
+ * @default 'inherit'
33
+ */
34
+ color?: NebaColor | 'inherit';
35
+ /**
36
+ * What the icon says, for a reader who cannot see it.
37
+ *
38
+ * Without it the icon is hidden from the accessibility tree entirely, which is
39
+ * the right default: the overwhelming majority of icons sit next to a word
40
+ * that already says the same thing, and reading both out loud is worse than
41
+ * reading one. Pass this only when the glyph is carrying meaning on its own.
42
+ */
43
+ label?: string;
44
+ }
45
+ /**
46
+ * A glyph at a known size, in a known colour.
47
+ *
48
+ * The library draws no icons of its own beyond the handful its components need —
49
+ * an icon set is a font-sized decision that belongs to the app, not to the
50
+ * component library it installs. What this does is give whatever icon the app
51
+ * chose the same two axes everything else here has.
52
+ *
53
+ * The box is `inline-flex` with the glyph told to fill it, and `font-size` is
54
+ * set to the same length — so an `<svg>` with its own `width`, an `<svg>` sized
55
+ * in `em`, and a bare character all come out the same size. That is the whole
56
+ * component: a box, a length written twice, and a colour.
57
+ */
58
+ export declare const Icon: React.ForwardRefExoticComponent<IconProps & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e}from"react/jsx-runtime";import*as t from"react";import{iconSizeClasses as i}from"../../internal/styles";const n={xs:"text-[0.875rem]",sm:"text-[1rem]",md:"text-[1.25rem]",lg:"text-[1.5rem]",xl:"text-[1.75rem]"};export const Icon=t.forwardRef(function({icon:t,size:r="md",color:l="inherit",label:s,className:a,style:o,...c},m){const f=["inline-flex shrink-0 items-center justify-center align-middle",i[r],"[&>svg]:block [&>svg]:size-full [&>img]:block [&>img]:size-full",`leading-none ${n[r]}`,"inherit"===l?"":"text-(--n-accent)",a??""].filter(Boolean).join(" ");return e("span",{ref:m,className:f,style:"inherit"===l?o:{"--n-accent":`var(--neba-${l}-accent)`,...o},role:s?"img":void 0,"aria-label":s,"aria-hidden":!s||void 0,...c,children:t})});
@@ -0,0 +1,2 @@
1
+ export { Icon } from './Icon';
2
+ export type { IconProps } from './Icon';
@@ -0,0 +1 @@
1
+ export{Icon}from"./Icon";
@@ -0,0 +1,39 @@
1
+ import * as React from 'react';
2
+ import { type ButtonProps } from '../button/Button';
3
+ export interface IconButtonProps extends Omit<ButtonProps, 'children' | 'startIcon' | 'endIcon'> {
4
+ /**
5
+ * The glyph. Wrap it in an `Icon` when it needs a size of its own; passed bare
6
+ * it is sized in `em` against the button, exactly as a `startIcon` is.
7
+ */
8
+ icon: React.ReactNode;
9
+ /**
10
+ * What the button does, in words.
11
+ *
12
+ * Required, and the one prop here that is. A button whose whole label is a
13
+ * drawing has no accessible name at all, and "an icon button with no
14
+ * `aria-label`" is the single most common accessibility defect a component
15
+ * library ships. Making it required is the only fix that survives review.
16
+ */
17
+ label: string;
18
+ }
19
+ /**
20
+ * A round button with a glyph in it and nothing else.
21
+ *
22
+ * A [Button] with an icon and no children already goes square — the same height,
23
+ * the same width, the acrylic corners cut off it. This is the other shape: a
24
+ * disc.
25
+ *
26
+ * That disc is a deliberate exception to the house radius rule, which holds
27
+ * every corner just short of the 50% that would make a control a pill, because
28
+ * the flat run along the top and bottom edge is what still reads as a sheet with
29
+ * its corners cut. The rule is about *labelled* controls: the flat run is there
30
+ * for the line of text to sit on, and a glyph has no line of text. A circle with
31
+ * a single mark centred in it is a punched token rather than a moulded key, so
32
+ * it says the thing the rule exists to protect by a different route.
33
+ *
34
+ * Everything else is Button's, unchanged and on purpose: the variants, the
35
+ * elevation ladder, the pointer light, `loading`, `readOnly`, and the values a
36
+ * surrounding ButtonGroup sets. Two components that draw the same surface from
37
+ * two copies of the same table are two components that will eventually disagree.
38
+ */
39
+ export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as t}from"react/jsx-runtime";import*as r from"react";import{Button as o}from"../button/Button";export const IconButton=r.forwardRef(function({icon:r,label:e,style:a,...n},s){return t(o,{ref:s,"aria-label":e,startIcon:r,style:{borderRadius:"9999px",...a},...n})});
@@ -0,0 +1,2 @@
1
+ export { IconButton } from './IconButton';
2
+ export type { IconButtonProps } from './IconButton';
@@ -0,0 +1 @@
1
+ export{IconButton}from"./IconButton";
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Button as n}from"../button/Button";import{ChevronIcon as i}from"../../internal/icons";import{controlTextClasses as r,gapClasses as l,srOnlyClasses as o}from"../../internal/styles";function s(e,t){return Array.from({length:Math.max(0,t-e+1)},(t,a)=>e+a)}function m(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const c={xs:"h-5.5 min-w-5.5",sm:"h-6.5 min-w-6.5",md:"h-8 min-w-8",lg:"h-10 min-w-10",xl:"h-12 min-w-12"};export const Pagination=a.forwardRef(function({variant:d="text",size:u="md",color:h="primary",density:f="compact",elevation:p=0,count:x,page:g,defaultPage:b=1,onPageChange:v,siblingCount:M=1,boundaryCount:w=1,showEdges:N=!1,showArrows:y=!0,disabled:L=!1,label:j="Pagination",pageLabel:$=e=>`Page ${e}`,previousLabel:k="Previous page",nextLabel:C="Next page",firstLabel:P="First page",lastLabel:z="Last page",className:B,children:A,...E},F){const[I,R]=a.useState(b),S=Math.min(Math.max(g??I,1),Math.max(x,1)),W=e=>{const t=Math.min(Math.max(e,1),x);t!==S&&(void 0===g&&R(t),v?.(t))};if(x<2)return null;const q=function(e,t,a,n){const i=s(1,Math.min(n,e)),r=s(Math.max(e-n+1,n+1),e),l=Math.max(Math.min(t-a,e-n-2*a-1),n+2),o=Math.min(Math.max(t+a,n+2*a+2),r.length>0?r[0]-2:e-1);return[...i,...l>n+2?["start-ellipsis"]:n+1<e-n?[n+1]:[],...s(l,o),...o<e-n-1?["end-ellipsis"]:e-n>n?[e-n]:[],...r]}(x,S,M,w),D=S<=1,G=S>=x,H=(t,a,i,r,l,o)=>e("li",{className:"flex",children:e(n,{variant:d,size:u,color:h,density:f,elevation:p,disabled:L||r,"aria-label":a,startIcon:e("span",{className:`flex items-center ${l}`,children:o}),onClick:()=>W(i)})},t);return t("nav",{ref:F,"aria-label":j,className:["flex items-center",B??""].filter(Boolean).join(" "),...E,children:[t("ul",{role:"list",className:`m-0 flex list-none items-center p-0 ${l[u]}`,children:[N?H("first",P,1,D,"rotate-180 rtl:rotate-0",e(m,{})):null,y?H("previous",k,S-1,D,"rotate-90 rtl:-rotate-90",e(i,{})):null,q.map((t,a)=>"number"==typeof t?e("li",{className:"flex",children:e(n,{variant:t===S?"solid":d,size:u,color:h,density:f,elevation:p,disabled:L,"aria-label":$(t),"aria-current":t===S?"page":void 0,className:"tabular-nums",onClick:()=>W(t),children:t})},t):e("li",{"aria-hidden":"true",className:["flex select-none items-center justify-center","text-(--neba-muted-fg)",r[u],c[u]].join(" "),children:"…"},`${t}-${a}`)),y?H("next",C,S+1,G,"-rotate-90 rtl:rotate-90",e(i,{})):null,N?H("last",z,x,G,"rtl:rotate-180",e(m,{})):null]}),e("span",{className:o,"aria-live":"polite",children:`${$(S)} of ${x}`}),A]})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Button as n}from"../button/Button";import{ChevronIcon as r}from"../../internal/icons";import{controlTextClasses as i,gapClasses as l,srOnlyClasses as o}from"../../internal/styles";function s(e,t){return Array.from({length:Math.max(0,t-e+1)},(t,a)=>e+a)}function m(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const c={xs:"h-5.5 min-w-5.5",sm:"h-6.5 min-w-6.5",md:"h-8 min-w-8",lg:"h-10 min-w-10",xl:"h-12 min-w-12"};export const Pagination=a.forwardRef(function({variant:d="text",size:u="md",color:h="primary",density:f="compact",elevation:p=0,count:x,page:g,defaultPage:b=1,onPageChange:v,siblingCount:M=1,boundaryCount:w=1,showEdges:N=!1,showArrows:y=!0,disabled:L=!1,label:j="Pagination",pageLabel:k=e=>`Page ${e}`,previousLabel:C="Previous page",nextLabel:P="Next page",firstLabel:$="First page",lastLabel:z="Last page",className:B,children:A,...E},F){const[I,R]=a.useState(b),S=Math.min(Math.max(g??I,1),Math.max(x,1)),W=e=>{const t=Math.min(Math.max(e,1),x);t!==S&&(void 0===g&&R(t),v?.(t))};if(x<2)return null;const q=function(e,t,a,n){const r=s(1,Math.min(n,e)),i=s(Math.max(e-n+1,n+1),e),l=Math.max(Math.min(t-a,e-n-2*a-1),n+2),o=Math.min(Math.max(t+a,n+2*a+2),i.length>0?i[0]-2:e-1);return[...r,...l>n+2?["start-ellipsis"]:n+1<e-n?[n+1]:[],...s(l,o),...o<e-n-1?["end-ellipsis"]:e-n>n?[e-n]:[],...i]}(x,S,M,w),D=S<=1,G=S>=x,H=(t,a,r,i,l,o)=>e("li",{className:"flex",children:e(n,{variant:d,size:u,color:h,density:f,elevation:p,disabled:L||i,"aria-label":a,startIcon:e("span",{className:`flex items-center ${l}`,children:o}),onClick:()=>W(r)})},t);return t("nav",{ref:F,"aria-label":j,className:["flex items-center",B??""].filter(Boolean).join(" "),...E,children:[t("ul",{role:"list",className:`m-0 flex list-none items-center p-0 ${l[u]}`,children:[N?H("first",$,1,D,"rotate-180 rtl:rotate-0",e(m,{})):null,y?H("previous",C,S-1,D,"rotate-90 rtl:-rotate-90",e(r,{})):null,q.map((t,a)=>e("li","number"==typeof t?{className:"flex",children:e(n,{variant:t===S?"solid":d,size:u,color:h,density:f,elevation:p,disabled:L,"aria-label":k(t),"aria-current":t===S?"page":void 0,className:"tabular-nums",onClick:()=>W(t),children:t})}:{"aria-hidden":"true",className:["flex select-none items-center justify-center","text-(--neba-muted-fg)",i[u],c[u]].join(" "),children:"…"},`slot-${a}`)),y?H("next",P,S+1,G,"-rotate-90 rtl:rotate-90",e(r,{})):null,N?H("last",z,x,G,"rtl:rotate-180",e(m,{})):null]}),e("span",{className:o,"aria-live":"polite",children:`${k(S)} of ${x}`}),A]})});
@@ -0,0 +1,80 @@
1
+ import * as React from 'react';
2
+ import type { NebaElevation, NebaPosition, NebaStyleProps } from '../../types';
3
+ export interface PillProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'onClick' | 'title'> {
4
+ /**
5
+ * Drop shadow depth. `2` here, against the `0` everything else defaults to.
6
+ *
7
+ * That is not an inconsistency: a Pill is defined by not being part of the
8
+ * page. Every other surface in the library rests on the page and earns its
9
+ * separation from the acrylic edge, so a shadow is opt-in. This one hovers
10
+ * over whatever is underneath it, and a lozenge floating flat on the content
11
+ * it is floating over reads as a mistake.
12
+ * @default 2
13
+ */
14
+ elevation?: NebaElevation;
15
+ /**
16
+ * The leading slot — a glyph, an avatar, a status dot, a photo.
17
+ *
18
+ * It is given a square box of its own and clipped to a circle, so an `<img>`
19
+ * lands in it as readily as an icon does: the image fills the box and is
20
+ * cropped rather than letterboxed, which is what a 20px avatar wants.
21
+ */
22
+ startIcon?: React.ReactNode;
23
+ /** The trailing slot. Outside the pressable area, so it can be a control. */
24
+ endIcon?: React.ReactNode;
25
+ /**
26
+ * The headline in the middle — what the pill is currently about.
27
+ *
28
+ * A prop rather than something to compose, for the reason Card's title is one:
29
+ * the arrangement is fixed and what a caller wants to decide is what goes in
30
+ * each slot. Almost every pill is a line of text and an optional second line
31
+ * under it, and spelling that as children means every caller inventing their
32
+ * own centring and type scale.
33
+ */
34
+ title?: React.ReactNode;
35
+ /** The second line, under the title. One step down and lighter. */
36
+ description?: React.ReactNode;
37
+ /**
38
+ * The second half, revealed when `expanded`.
39
+ *
40
+ * The pill grows downward into it rather than swapping to a different shape:
41
+ * one object saying more, which is the whole idea being borrowed here.
42
+ */
43
+ details?: React.ReactNode;
44
+ /** Whether `details` is showing. @default false */
45
+ expanded?: boolean;
46
+ /**
47
+ * How it sits in the page's scroll. `fixed` pins it against the viewport and
48
+ * centres it horizontally, which is the arrangement this shape exists for.
49
+ * @default 'static'
50
+ */
51
+ position?: NebaPosition;
52
+ /** Which edge it is held against when `position` is not `static`. @default 'top' */
53
+ side?: 'top' | 'bottom';
54
+ /** Passing it makes the row a real button. */
55
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
56
+ /**
57
+ * Anything the middle needs that `title` and `description` cannot say — a
58
+ * marquee, a pair of small readouts, a live counter. Rendered under them, in
59
+ * the same centred column.
60
+ */
61
+ children?: React.ReactNode;
62
+ }
63
+ /**
64
+ * A floating lozenge holding a small amount of live information.
65
+ *
66
+ * The shape is a stadium, which the house radius rule otherwise forbids: every
67
+ * control is held just short of the 50% that would make it a pill, because the
68
+ * flat run along its top and bottom edge is what still reads as a sheet with the
69
+ * corners cut off it. A Pill is the exception the rule is drawn against, and the
70
+ * exception works for the same reason the rule does — this is not a sheet lying
71
+ * on the page. It is an object hovering over it, and an object hovering over the
72
+ * page should not look like it was cut from the same material.
73
+ *
74
+ * `details` is revealed by animating a measured height, exactly as an Accordion
75
+ * panel is: nothing is transformed and no text is resampled, the pill is simply
76
+ * a window that opens. The measurement is a `ResizeObserver` rather than a
77
+ * hardcoded height, so a details area whose content changes — which is what live
78
+ * information does — grows with it.
79
+ */
80
+ export declare const Pill: React.ForwardRefExoticComponent<PillProps & React.RefAttributes<HTMLDivElement>>;