neba 0.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +177 -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/blockquote/Blockquote.d.ts +65 -0
  15. package/dist/components/blockquote/Blockquote.js +1 -0
  16. package/dist/components/blockquote/index.d.ts +2 -0
  17. package/dist/components/blockquote/index.js +1 -0
  18. package/dist/components/box/Box.d.ts +50 -0
  19. package/dist/components/box/Box.js +1 -0
  20. package/dist/components/box/index.d.ts +2 -0
  21. package/dist/components/box/index.js +1 -0
  22. package/dist/components/button/Button.d.ts +25 -3
  23. package/dist/components/button/Button.js +1 -1
  24. package/dist/components/button/index.d.ts +1 -0
  25. package/dist/components/button-group/ButtonGroup.d.ts +31 -0
  26. package/dist/components/button-group/ButtonGroup.js +1 -0
  27. package/dist/components/button-group/index.d.ts +2 -0
  28. package/dist/components/button-group/index.js +1 -0
  29. package/dist/components/card/Card.d.ts +45 -0
  30. package/dist/components/card/Card.js +1 -0
  31. package/dist/components/card/index.d.ts +2 -0
  32. package/dist/components/card/index.js +1 -0
  33. package/dist/components/carousel/Carousel.d.ts +74 -0
  34. package/dist/components/carousel/Carousel.js +1 -0
  35. package/dist/components/carousel/index.d.ts +2 -0
  36. package/dist/components/carousel/index.js +1 -0
  37. package/dist/components/checkbox/Checkbox.d.ts +39 -0
  38. package/dist/components/checkbox/Checkbox.js +1 -0
  39. package/dist/components/checkbox/index.d.ts +2 -0
  40. package/dist/components/checkbox/index.js +1 -0
  41. package/dist/components/chip/Chip.d.ts +50 -0
  42. package/dist/components/chip/Chip.js +1 -0
  43. package/dist/components/chip/index.d.ts +2 -0
  44. package/dist/components/chip/index.js +1 -0
  45. package/dist/components/combobox/Combobox.d.ts +131 -0
  46. package/dist/components/combobox/Combobox.js +1 -0
  47. package/dist/components/combobox/index.d.ts +2 -0
  48. package/dist/components/combobox/index.js +1 -0
  49. package/dist/components/container/Container.d.ts +55 -0
  50. package/dist/components/container/Container.js +1 -0
  51. package/dist/components/container/index.d.ts +2 -0
  52. package/dist/components/container/index.js +1 -0
  53. package/dist/components/date-picker/DatePicker.d.ts +75 -0
  54. package/dist/components/date-picker/DatePicker.js +1 -0
  55. package/dist/components/date-picker/index.d.ts +2 -0
  56. package/dist/components/date-picker/index.js +1 -0
  57. package/dist/components/date-range-picker/DateRangePicker.d.ts +81 -0
  58. package/dist/components/date-range-picker/DateRangePicker.js +1 -0
  59. package/dist/components/date-range-picker/index.d.ts +2 -0
  60. package/dist/components/date-range-picker/index.js +1 -0
  61. package/dist/components/date-time-picker/DateTimePicker.d.ts +68 -0
  62. package/dist/components/date-time-picker/DateTimePicker.js +1 -0
  63. package/dist/components/date-time-picker/index.d.ts +2 -0
  64. package/dist/components/date-time-picker/index.js +1 -0
  65. package/dist/components/dialog/Dialog.d.ts +111 -0
  66. package/dist/components/dialog/Dialog.js +1 -0
  67. package/dist/components/dialog/index.d.ts +2 -0
  68. package/dist/components/dialog/index.js +1 -0
  69. package/dist/components/divider/Divider.d.ts +67 -0
  70. package/dist/components/divider/Divider.js +1 -0
  71. package/dist/components/divider/index.d.ts +2 -0
  72. package/dist/components/divider/index.js +1 -0
  73. package/dist/components/file-picker/FilePicker.d.ts +103 -0
  74. package/dist/components/file-picker/FilePicker.js +1 -0
  75. package/dist/components/file-picker/index.d.ts +2 -0
  76. package/dist/components/file-picker/index.js +1 -0
  77. package/dist/components/grid/Grid.d.ts +50 -0
  78. package/dist/components/grid/Grid.js +1 -0
  79. package/dist/components/grid/index.d.ts +2 -0
  80. package/dist/components/grid/index.js +1 -0
  81. package/dist/components/grid-container/GridContainer.d.ts +79 -0
  82. package/dist/components/grid-container/GridContainer.js +1 -0
  83. package/dist/components/grid-container/index.d.ts +2 -0
  84. package/dist/components/grid-container/index.js +1 -0
  85. package/dist/components/highlight/Highlight.d.ts +84 -0
  86. package/dist/components/highlight/Highlight.js +1 -0
  87. package/dist/components/highlight/index.d.ts +2 -0
  88. package/dist/components/highlight/index.js +1 -0
  89. package/dist/components/icon/Icon.d.ts +58 -0
  90. package/dist/components/icon/Icon.js +1 -0
  91. package/dist/components/icon/index.d.ts +2 -0
  92. package/dist/components/icon/index.js +1 -0
  93. package/dist/components/icon-button/IconButton.d.ts +39 -0
  94. package/dist/components/icon-button/IconButton.js +1 -0
  95. package/dist/components/icon-button/index.d.ts +2 -0
  96. package/dist/components/icon-button/index.js +1 -0
  97. package/dist/components/list/List.d.ts +81 -0
  98. package/dist/components/list/List.js +1 -0
  99. package/dist/components/list/index.d.ts +2 -0
  100. package/dist/components/list/index.js +1 -0
  101. package/dist/components/menu/Menu.d.ts +216 -0
  102. package/dist/components/menu/Menu.js +1 -0
  103. package/dist/components/menu/index.d.ts +2 -0
  104. package/dist/components/menu/index.js +1 -0
  105. package/dist/components/number-field/NumberField.d.ts +113 -0
  106. package/dist/components/number-field/NumberField.js +1 -0
  107. package/dist/components/number-field/index.d.ts +2 -0
  108. package/dist/components/number-field/index.js +1 -0
  109. package/dist/components/overlay/Overlay.d.ts +85 -0
  110. package/dist/components/overlay/Overlay.js +1 -0
  111. package/dist/components/overlay/index.d.ts +2 -0
  112. package/dist/components/overlay/index.js +1 -0
  113. package/dist/components/pagination/Pagination.d.ts +65 -0
  114. package/dist/components/pagination/Pagination.js +1 -0
  115. package/dist/components/pagination/index.d.ts +2 -0
  116. package/dist/components/pagination/index.js +1 -0
  117. package/dist/components/pill/Pill.d.ts +80 -0
  118. package/dist/components/pill/Pill.js +1 -0
  119. package/dist/components/pill/index.d.ts +2 -0
  120. package/dist/components/pill/index.js +1 -0
  121. package/dist/components/progress-box/ProgressBox.d.ts +33 -0
  122. package/dist/components/progress-box/ProgressBox.js +1 -0
  123. package/dist/components/progress-box/index.d.ts +2 -0
  124. package/dist/components/progress-box/index.js +1 -0
  125. package/dist/components/progress-circular/ProgressCircular.d.ts +19 -0
  126. package/dist/components/progress-circular/ProgressCircular.js +1 -0
  127. package/dist/components/progress-circular/index.d.ts +2 -0
  128. package/dist/components/progress-circular/index.js +1 -0
  129. package/dist/components/progress-linear/ProgressLinear.d.ts +20 -0
  130. package/dist/components/progress-linear/ProgressLinear.js +1 -0
  131. package/dist/components/progress-linear/index.d.ts +2 -0
  132. package/dist/components/progress-linear/index.js +1 -0
  133. package/dist/components/radio-group/RadioGroup.d.ts +51 -0
  134. package/dist/components/radio-group/RadioGroup.js +1 -0
  135. package/dist/components/radio-group/index.d.ts +2 -0
  136. package/dist/components/radio-group/index.js +1 -0
  137. package/dist/components/segmented-button/SegmentedButton.d.ts +77 -0
  138. package/dist/components/segmented-button/SegmentedButton.js +1 -0
  139. package/dist/components/segmented-button/index.d.ts +2 -0
  140. package/dist/components/segmented-button/index.js +1 -0
  141. package/dist/components/select/Select.d.ts +76 -0
  142. package/dist/components/select/Select.js +1 -0
  143. package/dist/components/select/index.d.ts +2 -0
  144. package/dist/components/select/index.js +1 -0
  145. package/dist/components/shortcut/Shortcut.d.ts +60 -0
  146. package/dist/components/shortcut/Shortcut.js +1 -0
  147. package/dist/components/shortcut/index.d.ts +2 -0
  148. package/dist/components/shortcut/index.js +1 -0
  149. package/dist/components/slider/Slider.d.ts +38 -0
  150. package/dist/components/slider/Slider.js +1 -0
  151. package/dist/components/slider/index.d.ts +2 -0
  152. package/dist/components/slider/index.js +1 -0
  153. package/dist/components/statistic/Statistic.d.ts +91 -0
  154. package/dist/components/statistic/Statistic.js +1 -0
  155. package/dist/components/statistic/index.d.ts +2 -0
  156. package/dist/components/statistic/index.js +1 -0
  157. package/dist/components/switch/Switch.d.ts +39 -0
  158. package/dist/components/switch/Switch.js +1 -0
  159. package/dist/components/switch/index.d.ts +2 -0
  160. package/dist/components/switch/index.js +1 -0
  161. package/dist/components/table/Table.d.ts +80 -0
  162. package/dist/components/table/Table.js +1 -0
  163. package/dist/components/table/index.d.ts +2 -0
  164. package/dist/components/table/index.js +1 -0
  165. package/dist/components/tabs/Tabs.d.ts +92 -0
  166. package/dist/components/tabs/Tabs.js +1 -0
  167. package/dist/components/tabs/index.d.ts +2 -0
  168. package/dist/components/tabs/index.js +1 -0
  169. package/dist/components/text-field/TextField.d.ts +63 -0
  170. package/dist/components/text-field/TextField.js +1 -0
  171. package/dist/components/text-field/index.d.ts +2 -0
  172. package/dist/components/text-field/index.js +1 -0
  173. package/dist/components/time-picker/TimePicker.d.ts +76 -0
  174. package/dist/components/time-picker/TimePicker.js +1 -0
  175. package/dist/components/time-picker/index.d.ts +2 -0
  176. package/dist/components/time-picker/index.js +1 -0
  177. package/dist/components/timeline/Timeline.d.ts +98 -0
  178. package/dist/components/timeline/Timeline.js +1 -0
  179. package/dist/components/timeline/index.d.ts +2 -0
  180. package/dist/components/timeline/index.js +1 -0
  181. package/dist/components/toast/Toast.d.ts +116 -0
  182. package/dist/components/toast/Toast.js +1 -0
  183. package/dist/components/toast/index.d.ts +2 -0
  184. package/dist/components/toast/index.js +1 -0
  185. package/dist/components/toolbar/Toolbar.d.ts +67 -0
  186. package/dist/components/toolbar/Toolbar.js +1 -0
  187. package/dist/components/toolbar/index.d.ts +2 -0
  188. package/dist/components/toolbar/index.js +1 -0
  189. package/dist/components/tooltip/Tooltip.d.ts +81 -0
  190. package/dist/components/tooltip/Tooltip.js +1 -0
  191. package/dist/components/tooltip/index.d.ts +2 -0
  192. package/dist/components/tooltip/index.js +1 -0
  193. package/dist/components/typography/Typography.d.ts +62 -0
  194. package/dist/components/typography/Typography.js +1 -0
  195. package/dist/components/typography/index.d.ts +2 -0
  196. package/dist/components/typography/index.js +1 -0
  197. package/dist/index.d.ts +50 -1
  198. package/dist/index.js +1 -1
  199. package/dist/internal/button-group.d.ts +25 -0
  200. package/dist/internal/button-group.js +1 -0
  201. package/dist/internal/calendar.d.ts +149 -0
  202. package/dist/internal/calendar.js +1 -0
  203. package/dist/internal/date.d.ts +170 -0
  204. package/dist/internal/date.js +1 -0
  205. package/dist/internal/grid.d.ts +69 -0
  206. package/dist/internal/grid.js +1 -0
  207. package/dist/internal/icons.d.ts +79 -0
  208. package/dist/internal/icons.js +1 -0
  209. package/dist/internal/menu.d.ts +20 -0
  210. package/dist/internal/menu.js +1 -0
  211. package/dist/internal/picker.d.ts +111 -0
  212. package/dist/internal/picker.js +1 -0
  213. package/dist/internal/progress.d.ts +122 -0
  214. package/dist/internal/progress.js +1 -0
  215. package/dist/internal/sizer.d.ts +33 -0
  216. package/dist/internal/sizer.js +1 -0
  217. package/dist/internal/styles.d.ts +257 -0
  218. package/dist/internal/styles.js +1 -0
  219. package/dist/styles.css +2 -0
  220. package/dist/tailwind.css +892 -0
  221. package/dist/types.d.ts +142 -0
  222. package/dist/types.js +8 -0
  223. package/package.json +90 -21
  224. package/pnpm-workspace.yaml +0 -2
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import*as o from"react";import{Button as r}from"../components/button/Button";import{ChevronIcon as a}from"./icons";import{controlHeightClasses as l,controlTextClasses as s,cx as i,gapClasses as c,metaTextClasses as u,pressTransitionClasses as d,srOnlyClasses as m,transitionClasses as h}from"./styles";import{addDays as g,addMonths as f,addYears as b,calendarWeeks as p,compareDay as v,dateFormatter as x,daysInMonth as w,isDayOutside as y,isMonthBeforeYear as D,isSameDay as N,isSameMonth as S,isValidDate as M,makeDate as P,meridiemLabels as C,monthLabels as k,startOfDay as Y,startOfMonth as z,today as A,weekdayLabels as F,withTime as E,YEAR_PAGE_SIZE as T,yearPageStart as j}from"./date";export const defaultPickerLabels={previousMonth:"Previous month",nextMonth:"Next month",previousYear:"Previous year",nextYear:"Next year",previousYears:"Previous years",nextYears:"Next years",chooseMonth:"Choose a month",chooseYear:"Choose a year",today:"Today",now:"Now",clear:"Clear",done:"Done",hour:"Hour",minute:"Minute",second:"Second",meridiem:"AM/PM",start:"Start",end:"End"};export function usePickerLabels(e){return o.useMemo(()=>e?{...defaultPickerLabels,...e}:defaultPickerLabels,[e])}const R={xs:"1.375rem",sm:"1.625rem",md:"2rem",lg:"2.5rem",xl:"3rem"},B={xs:"rounded-(--neba-radius-xs)",sm:"rounded-(--neba-radius-xs)",md:"rounded-(--neba-radius-sm)",lg:"rounded-(--neba-radius-md)",xl:"rounded-(--neba-radius-lg)"},H={xs:"rounded-s-(--neba-radius-xs)",sm:"rounded-s-(--neba-radius-xs)",md:"rounded-s-(--neba-radius-sm)",lg:"rounded-s-(--neba-radius-md)",xl:"rounded-s-(--neba-radius-lg)"},L={xs:"rounded-e-(--neba-radius-xs)",sm:"rounded-e-(--neba-radius-xs)",md:"rounded-e-(--neba-radius-sm)",lg:"rounded-e-(--neba-radius-md)",xl:"rounded-e-(--neba-radius-lg)"},K=["relative flex select-none items-center justify-center tabular-nums","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",h,d,"focus-visible:z-10 focus-visible:[outline:2px_solid_var(--n-ring)]","focus-visible:[outline-offset:-2px]"].join(" ");function O({children:n,label:o,selected:r,inRange:a=!1,rangeEdge:l=null,current:s=!1,muted:c=!1,disabled:u=!1,focused:d=!1,size:m,className:h,onClick:g,onPointerEnter:f,onKeyDown:b}){return t("button",{type:"button",role:"gridcell","aria-label":o,"aria-selected":r,"aria-current":s?"date":void 0,"aria-disabled":u||void 0,tabIndex:d?0:-1,"data-focus-target":d?"true":void 0,className:i(K,"start"===l?H[m]:"end"===l?L[m]:"middle"===l?"rounded-none":B[m],u?"cursor-not-allowed text-(--neba-disabled-fg)":r?"cursor-pointer bg-(--n-fill) font-semibold text-(--n-on-solid) hover:bg-(--n-fill-hover) active:bg-(--n-fill-active)":a?"cursor-pointer bg-(--n-soft) text-(--neba-fg) hover:bg-(--n-soft-hover) active:bg-(--n-soft-press)":s?"cursor-pointer font-semibold text-(--n-accent) hover:bg-(--n-soft) active:bg-(--n-soft-press)":c?"cursor-pointer text-(--neba-muted-fg) hover:bg-(--n-soft) active:bg-(--n-soft-press)":"cursor-pointer text-(--neba-fg) hover:bg-(--n-soft) active:bg-(--n-soft-press)",h),onClick:()=>{u||g()},onPointerEnter:f,onKeyDown:b,children:[n,s?e("span",{"aria-hidden":"true",className:"absolute bottom-[0.18em] size-[0.22em] rounded-full bg-current"}):null]})}function U({size:o,color:u,view:d,month:m,locale:h,labels:g,showPreviousButton:f,showNextButton:b,onStep:p,onViewChange:v}){const x=k(h,"long")[m.getMonth()],w=String(m.getFullYear()),y=D(h),N="day"===d?[g.previousMonth,g.nextMonth]:"month"===d?[g.previousYear,g.nextYear]:[g.previousYears,g.nextYears],S=(t,n)=>n?e(r,{variant:"text",size:o,color:u,density:"compact","aria-label":N[-1===t?0:1],onClick:()=>p(t),startIcon:e("span",{className:i("flex items-center",-1===t?"rotate-90 rtl:-rotate-90":"-rotate-90 rtl:rotate-90"),children:e(a,{})})}):e("span",{"aria-hidden":"true",className:i(l[o],"w-(--n-cell)")}),M=t=>e("span",{className:i("flex items-center text-(--neba-muted-fg)","[transition:rotate_var(--neba-duration)_var(--neba-ease)]",t&&"rotate-180"),children:e(a,{})}),P=e(r,{variant:"text",size:o,color:u,density:"compact","aria-label":g.chooseMonth,"aria-expanded":"month"===d,onClick:()=>v("month"===d?"day":"month"),endIcon:M("month"===d),children:x},"month"),C=e(r,{variant:"text",size:o,color:u,density:"compact",className:"tabular-nums","aria-label":g.chooseYear,"aria-expanded":"year"===d,onClick:()=>v("year"===d?"day":"year"),endIcon:M("year"===d),children:w},"year"),Y=j(m.getFullYear());return t("div",{className:"flex items-center justify-between gap-1",children:[S(-1,f),e("div",{className:i("flex min-w-0 flex-1 items-center justify-center",c[o]),children:"year"===d?e("span",{className:i("flex items-center font-medium tabular-nums text-(--neba-fg)",l[o],s[o]),children:`${Y}–${Y+T-1}`}):"month"===d?C:t(n,y?{children:[P,C]}:{children:[C,P]})}),S(1,b)]})}export function Calendar({size:n,color:r,locale:a,weekStartsOn:l,month:s,onMonthChange:u,selected:d,rangeStart:m=null,rangeEnd:h=null,onSelect:g,onPreviewChange:p,minDate:v,maxDate:x,shouldDisableDate:w,showOutsideDays:D=!0,autoFocus:N=!1,showPreviousButton:C=!0,showNextButton:k=!0,labels:F,className:E}){const[j,B]=o.useState("day"),H=o.useMemo(()=>d.filter(M),[d]),[L,K]=o.useState(()=>{const e=H.find(e=>S(e,s));return e?Y(e):S(A(),s)?A():z(s)}),O=o.useRef(N),_=o.useRef(null);o.useEffect(()=>{K(e=>S(e,s)?e:z(s))},[s]),o.useLayoutEffect(()=>{O.current&&(O.current=!1,_.current?.querySelector('[data-focus-target="true"]')?.focus({preventScroll:!0}))});const V=o.useCallback(e=>y(e,v,x)||(w?.(e)??!1),[v,x,w]),G=e=>{O.current=!0,B(e)},J=e=>{O.current=!0,u(e)};return t("div",{ref:_,className:i("flex flex-col",c[n],E),style:{"--n-cell":R[n]},onPointerLeave:()=>p?.(null),children:[e(U,{size:n,color:r,view:j,month:s,locale:a,labels:F,showPreviousButton:C,showNextButton:k,onStep:e=>{u("day"===j?f(s,e):b(s,"month"===j?e:e*T))},onViewChange:G}),e("div",{className:"h-[calc(var(--n-cell)*7)] w-[calc(var(--n-cell)*7)]",children:"day"===j?e(q,{size:n,locale:a,weekStartsOn:l,month:s,chosen:H,rangeStart:m,rangeEnd:h,focusedDate:L,showOutsideDays:D,isDisabled:V,onSelect:e=>{K(e),g(e)},onPreviewChange:p,onMoveFocus:e=>{O.current=!0,K(e),S(e,s)||u(z(e))}}):"month"===j?e(I,{size:n,locale:a,month:s,chosen:H,minDate:v,maxDate:x,onMoveCursor:J,onPick:e=>{u(P(s.getFullYear(),e,1)),G("day")}}):e($,{size:n,month:s,chosen:H,minDate:v,maxDate:x,onMoveCursor:J,onPick:e=>{u(P(e,s.getMonth(),1)),G("month")}})})]})}function q({size:n,locale:o,weekStartsOn:r,month:a,chosen:l,rangeStart:c,rangeEnd:d,focusedDate:m,showOutsideDays:h,isDisabled:b,onSelect:w,onPreviewChange:y,onMoveFocus:D}){const P=p(a,r),C=F(o,r,"short"),k=F(o,r,"long"),Y=x(o,{dateStyle:"full"}),z=(T=d,M(E=c)&&M(T)?v(E,T)<=0?[E,T]:[T,E]:null);var E,T;const j=A();return t("div",{role:"grid",className:"flex h-full flex-col",children:[e("div",{role:"row",className:"grid grid-cols-7",children:C.map((t,o)=>e("span",{role:"columnheader","aria-label":k[o],className:i("flex h-(--n-cell) items-center justify-center font-medium text-(--neba-muted-fg) select-none",u[n]),children:t},o))}),P.map((t,o)=>e("div",{role:"row",className:"grid grid-cols-7",children:t.map(t=>{const o=!S(t,a);if(o&&!h)return e("span",{role:"gridcell","aria-hidden":"true",className:"size-(--n-cell)"},t.getTime());const c=l.some(e=>N(e,t)),u=null!==z&&v(t,z[0])>=0&&v(t,z[1])<=0,d=null!==z&&u&&N(t,z[0]),p=null!==z&&u&&N(t,z[1]);return e(O,{size:n,label:Y.format(t),selected:c,inRange:u&&!c,rangeEdge:u?d&&p?"both":d?"start":p?"end":"middle":null,current:N(t,j)&&!c,muted:o,disabled:b(t),focused:N(t,m),className:i("size-(--n-cell)",s[n]),onClick:()=>w(t),onPointerEnter:()=>y?.(t),onKeyDown:e=>((e,t)=>{const n=(t.getDay()-r+7)%7,o={ArrowLeft:()=>g(t,-1),ArrowRight:()=>g(t,1),ArrowUp:()=>g(t,-7),ArrowDown:()=>g(t,7),Home:()=>g(t,-n),End:()=>g(t,6-n),PageUp:()=>f(t,e.shiftKey?-12:-1),PageDown:()=>f(t,e.shiftKey?12:1)}[e.key];o&&(e.preventDefault(),D(o()))})(e,t),children:t.getDate()},t.getTime())})},o))]})}function I({size:t,locale:n,month:o,chosen:r,minDate:a,maxDate:l,onMoveCursor:c,onPick:u}){const d=k(n,"short"),m=k(n,"long"),h=o.getFullYear(),g=new Date,b=e=>{const t={ArrowLeft:-1,ArrowRight:1,ArrowUp:-3,ArrowDown:3,PageUp:-12,PageDown:12}[e.key];void 0!==t&&(e.preventDefault(),c(f(z(o),t)))};return e("div",{role:"grid",className:"flex h-full flex-col justify-evenly",children:[0,1,2,3].map(n=>e("div",{role:"row",className:"grid grid-cols-3 gap-1",children:[0,1,2].map(c=>{const f=3*n+c,p=P(h,f,1),x=P(h,f,w(h,f));return e(O,{size:t,label:`${m[f]} ${h}`,selected:r.some(e=>e.getFullYear()===h&&e.getMonth()===f),current:g.getFullYear()===h&&g.getMonth()===f,disabled:M(a)&&v(x,a)<0||M(l)&&v(p,l)>0,focused:f===o.getMonth(),className:i("h-(--n-cell) w-full",s[t]),onClick:()=>u(f),onKeyDown:b,children:d[f]},f)})},n))})}function $({size:t,month:n,chosen:o,minDate:r,maxDate:a,onMoveCursor:l,onPick:c}){const u=j(n.getFullYear()),d=(new Date).getFullYear(),m=e=>{const t={ArrowLeft:-1,ArrowRight:1,ArrowUp:-4,ArrowDown:4,PageUp:-T,PageDown:T}[e.key];void 0!==t&&(e.preventDefault(),l(b(z(n),t)))};return e("div",{role:"grid",className:"flex h-full flex-col justify-evenly",children:[0,1,2].map(l=>e("div",{role:"row",className:"grid grid-cols-4 gap-1",children:[0,1,2,3].map(h=>{const g=u+4*l+h;return e(O,{size:t,label:String(g),selected:o.some(e=>e.getFullYear()===g),current:g===d,disabled:M(r)&&g<r.getFullYear()||M(a)&&g>a.getFullYear(),focused:g===n.getFullYear(),className:i("h-(--n-cell) w-full",s[t]),onClick:()=>c(g),onKeyDown:m,children:g},g)})},l))})}function _(e){const t=e.parentElement;if(!t)return;const n=e.getBoundingClientRect(),o=t.getBoundingClientRect(),r=n.top-o.top-t.clientTop+t.scrollTop,a=r+n.height;r<t.scrollTop?t.scrollTop=r:a>t.scrollTop+t.clientHeight&&(t.scrollTop=a-t.clientHeight)}export function TimeGrid({size:n,density:r,locale:a,value:c,referenceDate:u,onChange:d,hour12:h,showSeconds:g,hourStep:f,minuteStep:b,secondStep:p,shouldDisableTime:v,autoFocus:w=!1,labels:y,className:D}){const N=c??u,S=o.useRef(null),[M,P]=o.useMemo(()=>C(a),[a]);o.useEffect(()=>{const e=S.current;if(e?.querySelectorAll('[data-chosen="true"]').forEach(_),w){const t=e?.querySelector('[role="listbox"]');(t?.querySelector('[data-chosen="true"]')??t?.querySelector('[role="option"]'))?.focus({preventScroll:!0})}},[w]);const k=o.useMemo(()=>{const e=Math.ceil((h?12:24)/f),t=Array.from({length:e},(e,t)=>t*f);return h?t.map(e=>0===e?12:e):t},[h,f]),Y=o.useMemo(()=>Array.from({length:Math.ceil(60/b)},(e,t)=>t*b),[b]),z=o.useMemo(()=>Array.from({length:Math.ceil(60/p)},(e,t)=>t*p),[p]),A=e=>String(e).padStart(2,"0"),F=h?N.getHours()%12||12:N.getHours(),T=(t,o,r,a,u)=>e("div",{role:"listbox","aria-label":o,className:i("flex flex-col gap-0.5 overflow-y-auto overscroll-contain","h-[calc(var(--n-cell)*7)] w-[calc(var(--n-cell)*2)]","scroll-py-0.5 [scrollbar-width:thin]"),children:r.map(o=>{const r=((e,t)=>E(N,"hour"===e?{hours:h?t%12+(N.getHours()>=12?12:0):t}:"minute"===e?{minutes:t}:"second"===e?{seconds:t}:{hours:N.getHours()%12+12*t}))(t,o),m=null!==c&&a(o),g=v?.(r,t)??!1;return e("button",{type:"button",role:"option","aria-selected":m,"aria-disabled":g||void 0,"data-chosen":m?"true":void 0,className:i(K,B[n],l[n],s[n],"w-full shrink-0",g?"cursor-not-allowed text-(--neba-disabled-fg)":m?"cursor-pointer bg-(--n-fill) font-semibold text-(--n-on-solid) hover:bg-(--n-fill-hover) active:bg-(--n-fill-active)":"cursor-pointer text-(--neba-fg) hover:bg-(--n-soft) active:bg-(--n-soft-press)"),onClick:()=>{g||d(r)},children:u(o)},o)})},t);return t("div",{ref:S,className:i("flex","compact"===r?"gap-0.5":"gap-1",D),style:{"--n-cell":R[n]},children:[T("hour",y.hour,k,e=>e===F,e=>h?String(e):A(e)),T("minute",y.minute,Y,e=>e===N.getMinutes(),A),g?T("second",y.second,z,e=>e===N.getSeconds(),A):null,h?T("meridiem",y.meridiem,[0,1],e=>(N.getHours()>=12?1:0)===e,e=>0===e?M:P):null,e("span",{className:m,"aria-live":"polite",children:null===c?"":x(a,{hour:"numeric",minute:"2-digit",...g?{second:"2-digit"}:{}}).format(c)})]})}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * The arithmetic and the naming the four pickers share.
3
+ *
4
+ * No date library under it, deliberately. Neba's one runtime dependency is Base
5
+ * UI, and a component library that quietly adds `date-fns` — or worse, picks a
6
+ * side in the dayjs/luxon/Temporal argument on its consumer's behalf — has made
7
+ * a decision that was not its to make. Everything here is either `Date`
8
+ * arithmetic, which is a dozen lines, or `Intl`, which the platform already
9
+ * ships and which knows more about month names in more languages than any
10
+ * bundled table ever will.
11
+ *
12
+ * Two rules hold everywhere below:
13
+ *
14
+ * - **Local time, always.** A calendar day is a thing a person is looking at on
15
+ * a wall, not an instant on a line. `new Date(2026, 6, 27)` is midnight local
16
+ * and every comparison here is made on the local Y/M/D triple, so a picker in
17
+ * Seoul and a picker in São Paulo both light up the cell that says 27.
18
+ * - **Nothing is mutated.** `Date` is mutable and every method on it that sounds
19
+ * like a question is actually a command. Each function here copies first, so a
20
+ * `value` handed in by a caller is never the object that comes back out.
21
+ */
22
+ import type { NebaWeekday } from '../types';
23
+ /** Which unit the calendar is currently letting you pick. */
24
+ export type CalendarView = 'day' | 'month' | 'year';
25
+ /** How many years one page of the year grid holds. Four columns of three. */
26
+ export declare const YEAR_PAGE_SIZE = 12;
27
+ /**
28
+ * A local midnight on the given Y/M/D, with out-of-range parts normalised —
29
+ * month `12` rolls into January, day `0` into the last day of the month before.
30
+ *
31
+ * Built through `setFullYear` rather than `new Date(year, month, day)` because
32
+ * the two-argument constructor maps years 0–99 onto 1900–1999. Nobody is going
33
+ * to pick a date in the year 47, but a component that silently rewrites the year
34
+ * it was handed is a component that will eventually be blamed for something else.
35
+ */
36
+ export declare function makeDate(year: number, month: number, day: number): Date;
37
+ /** Is this a `Date` that stands for a real instant? `new Date('nope')` is not. */
38
+ export declare function isValidDate(value: unknown): value is Date;
39
+ /** The same day with the clock wound back to midnight. */
40
+ export declare function startOfDay(date: Date): Date;
41
+ /** The first day of the month this date is in, at midnight. */
42
+ export declare function startOfMonth(date: Date): Date;
43
+ /** How many days a month has, leap years included. */
44
+ export declare function daysInMonth(year: number, month: number): number;
45
+ /** Today, at midnight. The one place the pickers read the clock for a *date*. */
46
+ export declare function today(): Date;
47
+ export declare function addDays(date: Date, amount: number): Date;
48
+ /**
49
+ * Months, with the day of the month clamped rather than allowed to overflow.
50
+ *
51
+ * 31 January plus one month is 28 February, not 3 March. The naive
52
+ * `setMonth(getMonth() + 1)` gives the second answer, which is why stepping a
53
+ * calendar forward from a 31st with it skips February entirely.
54
+ */
55
+ export declare function addMonths(date: Date, amount: number): Date;
56
+ export declare function addYears(date: Date, amount: number): Date;
57
+ /** Negative, zero or positive, the way a sort comparator wants it. */
58
+ export declare function compareDay(a: Date, b: Date): number;
59
+ export declare function isSameDay(a: Date | null | undefined, b: Date | null | undefined): boolean;
60
+ export declare function isSameMonth(a: Date | null | undefined, b: Date | null | undefined): boolean;
61
+ /** Strictly between the two ends, both of which are optional. */
62
+ export declare function isDayInRange(date: Date, start: Date | null, end: Date | null): boolean;
63
+ /** Holds a date inside `[min, max]`, at whatever precision the bounds carry. */
64
+ export declare function clampDate(date: Date, min?: Date | null, max?: Date | null): Date;
65
+ /**
66
+ * Is this calendar *day* outside the allowed span?
67
+ *
68
+ * Day-granular on purpose. A `maxDate` of 27 July at 09:00 still leaves the 27th
69
+ * pickable — the bound is about which days exist, and the time of day is the
70
+ * time picker's problem. `DateTimePicker` re-checks at full precision once an
71
+ * hour has been chosen.
72
+ */
73
+ export declare function isDayOutside(date: Date, min?: Date | null, max?: Date | null): boolean;
74
+ /** Minutes since local midnight — what `minTime`/`maxTime` are compared on. */
75
+ export declare function minutesOfDay(date: Date): number;
76
+ /** Seconds since local midnight, for the pickers that show a seconds column. */
77
+ export declare function secondsOfDay(date: Date): number;
78
+ /** Which column of a clock a candidate time is being offered for. */
79
+ export type TimeUnit = 'hour' | 'minute' | 'second' | 'meridiem';
80
+ /**
81
+ * The span of the day one row of one column covers, in seconds since midnight.
82
+ *
83
+ * This is the detail that separates a working time picker from a frustrating
84
+ * one. A bound has to be checked against the *span* a row stands for, not
85
+ * against one instant inside it: with a `minTime` of 09:30, the hour `9` covers
86
+ * 09:00:00–09:59:59, which overlaps what is allowed, so it stays available and
87
+ * the minute column is where `00` through `25` grey out. Comparing the whole
88
+ * candidate instead hides the 9 and makes half past nine unreachable.
89
+ */
90
+ export declare function timeUnitSpan(unit: TimeUnit, at: Date): [number, number];
91
+ /** The same instant with one or more clock fields replaced. */
92
+ export declare function withTime(date: Date, parts: {
93
+ hours?: number;
94
+ minutes?: number;
95
+ seconds?: number;
96
+ }): Date;
97
+ /** `date`'s calendar day wearing `time`'s clock. */
98
+ export declare function mergeDateAndTime(date: Date, time: Date): Date;
99
+ /**
100
+ * Six weeks of seven days, always — including the leading and trailing days that
101
+ * belong to the neighbouring months.
102
+ *
103
+ * Six rows whatever the month, and that is the whole point. A February that
104
+ * starts on a Sunday needs four rows and a 31-day month starting on a Saturday
105
+ * needs six; a grid that renders only the rows it needs is a grid that changes
106
+ * height when you step a month forward, moving every cell out from under the
107
+ * pointer that just pressed one. The same reason Pagination pins its slot count.
108
+ */
109
+ export declare function calendarWeeks(month: Date, weekStartsOn: NebaWeekday): Date[][];
110
+ /** The first year on the page a given year falls on. 2026 → 2016 at 12 a page. */
111
+ export declare function yearPageStart(year: number): number;
112
+ /** A memoised `Intl.DateTimeFormat`. `undefined` locale means the runtime's own. */
113
+ export declare function dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat;
114
+ /** Formats a date, tolerating the `null` a cleared picker holds. */
115
+ export declare function formatDate(date: Date | null | undefined, locale: string | undefined, options: Intl.DateTimeFormatOptions): string;
116
+ /**
117
+ * Every distinct string those instants format to. Deduplicated, because a
118
+ * date-only format collapses twenty-four of them into a handful.
119
+ */
120
+ export declare function displaySamples(locale: string | undefined, options: Intl.DateTimeFormatOptions): string[];
121
+ /**
122
+ * The samples plus the placeholder, when the placeholder is a string.
123
+ *
124
+ * An empty picker shows the placeholder, which can easily be longer than any
125
+ * date — "Pick a departure date" against "3 Aug 2026" — and a trigger that
126
+ * shrinks the moment the first date is chosen is the same jump from the other
127
+ * direction. A `ReactNode` placeholder is left out: there is nothing to measure
128
+ * without rendering it twice.
129
+ */
130
+ export declare function withPlaceholder(samples: string[], placeholder: unknown): string[];
131
+ /**
132
+ * The three machine-readable spellings, for the hidden input that makes a picker
133
+ * submit with a form.
134
+ *
135
+ * Local, not UTC, and that is the whole point: `toISOString()` on a `Date`
136
+ * standing for 27 July in Seoul gives `2026-07-26T15:00:00Z`, and a form field
137
+ * that quietly reports the day before the one on screen is the single most
138
+ * expensive bug a date picker can ship. The shapes are the ones the native
139
+ * `<input type="date">`, `type="time"` and `type="datetime-local"` submit, so a
140
+ * server that already parses those needs no new code.
141
+ */
142
+ export declare function toISODate(date: Date): string;
143
+ export declare function toISOTime(date: Date, withSeconds?: boolean): string;
144
+ export declare function toISODateTime(date: Date, withSeconds?: boolean): string;
145
+ /**
146
+ * The seven column headers, rotated so the first one is `weekStartsOn`.
147
+ *
148
+ * `short` rather than `narrow`: narrow gives `S`, `M`, `T`, `W`, `T`, `F`, `S`
149
+ * in English, where two pairs are indistinguishable. The full name goes on the
150
+ * header's `aria-label` so a screen reader hears "Monday" rather than "Mon".
151
+ */
152
+ export declare function weekdayLabels(locale: string | undefined, weekStartsOn: NebaWeekday, weekday?: 'narrow' | 'short' | 'long'): string[];
153
+ /** The twelve month names, January first, in the locale's own words. */
154
+ export declare function monthLabels(locale: string | undefined, month?: 'short' | 'long'): string[];
155
+ /**
156
+ * Does this locale write the month before the year?
157
+ *
158
+ * The calendar's header is two separate buttons — one that opens the month grid
159
+ * and one that opens the year grid — so it cannot just print what `Intl` gives
160
+ * it. Asking `formatToParts` which part came first is how the two buttons end up
161
+ * in the order the reader expects: `July 2026` in English, `2026년 7월` in
162
+ * Korean. Getting this wrong is subtle and reads as broken to exactly the people
163
+ * it is wrong for.
164
+ */
165
+ export declare function isMonthBeforeYear(locale: string | undefined): boolean;
166
+ /** Does this locale put a clock on a 12-hour dial? */
167
+ export declare function isHour12(locale: string | undefined): boolean;
168
+ /** What this locale calls AM and PM. */
169
+ export declare function meridiemLabels(locale: string | undefined): [string, string];
170
+ export declare function localeWeekStart(locale: string | undefined): NebaWeekday;
@@ -0,0 +1 @@
1
+ export const YEAR_PAGE_SIZE=12;export function makeDate(t,e,r){const n=new Date(0);return n.setFullYear(t,e,r),n.setHours(0,0,0,0),n}export function isValidDate(t){return t instanceof Date&&!Number.isNaN(t.getTime())}export function startOfDay(t){const e=new Date(t.getTime());return e.setHours(0,0,0,0),e}export function startOfMonth(t){return makeDate(t.getFullYear(),t.getMonth(),1)}export function daysInMonth(t,e){return makeDate(t,e+1,0).getDate()}export function today(){return startOfDay(new Date)}export function addDays(t,e){const r=new Date(t.getTime());return r.setDate(r.getDate()+e),r}export function addMonths(t,e){const r=t.getFullYear(),n=t.getMonth()+e,o=new Date(t.getTime()),a=makeDate(r,n,1);return o.setFullYear(a.getFullYear(),a.getMonth(),Math.min(t.getDate(),daysInMonth(a.getFullYear(),a.getMonth()))),o}export function addYears(t,e){return addMonths(t,12*e)}export function compareDay(t,e){return startOfDay(t).getTime()-startOfDay(e).getTime()}export function isSameDay(t,e){return isValidDate(t)&&isValidDate(e)&&0===compareDay(t,e)}export function isSameMonth(t,e){return isValidDate(t)&&isValidDate(e)&&t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()}export function isDayInRange(t,e,r){return!(!isValidDate(e)||!isValidDate(r))&&(compareDay(t,e)>0&&compareDay(t,r)<0)}export function clampDate(t,e,r){return isValidDate(e)&&t.getTime()<e.getTime()?new Date(e.getTime()):isValidDate(r)&&t.getTime()>r.getTime()?new Date(r.getTime()):t}export function isDayOutside(t,e,r){return!!(isValidDate(e)&&compareDay(t,e)<0)||isValidDate(r)&&compareDay(t,r)>0}export function minutesOfDay(t){return 60*t.getHours()+t.getMinutes()}export function secondsOfDay(t){return 3600*t.getHours()+60*t.getMinutes()+t.getSeconds()}export function timeUnitSpan(t,e){const r=secondsOfDay(e);if("hour"===t){const t=3600*Math.floor(r/3600);return[t,t+3599]}if("minute"===t){const t=60*Math.floor(r/60);return[t,t+59]}if("second"===t)return[r,r];const n=e.getHours()<12?0:43200;return[n,n+43200-1]}export function withTime(t,e){const r=new Date(t.getTime());return r.setHours(e.hours??r.getHours(),e.minutes??r.getMinutes(),e.seconds??r.getSeconds(),0),r}export function mergeDateAndTime(t,e){return withTime(startOfDay(t),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()})}export function calendarWeeks(t,e){const r=startOfMonth(t),n=(r.getDay()-e+7)%7,o=addDays(r,-n);return Array.from({length:6},(t,e)=>Array.from({length:7},(t,r)=>addDays(o,7*e+r)))}export function yearPageStart(t){return t-(t%12+12)%12}const t=new Map;export function dateFormatter(e,r){const n=`${e??""}\0${JSON.stringify(r)}`;let o=t.get(n);return o||(o=new Intl.DateTimeFormat(e,r),t.set(n,o)),o}export function formatDate(t,e,r){return isValidDate(t)?dateFormatter(e,r).format(t):""}const e=Array.from({length:24},(t,e)=>new Date(2027,e%12,21+e%7,e,58,58));export function displaySamples(t,r){const n=dateFormatter(t,r);return[...new Set(e.map(t=>n.format(t)))]}export function withPlaceholder(t,e){return"string"==typeof e&&""!==e?[...t,e]:t}export function toISODate(t){const e=t=>String(t).padStart(2,"0");return`${String(t.getFullYear()).padStart(4,"0")}-${e(t.getMonth()+1)}-${e(t.getDate())}`}export function toISOTime(t,e=!1){const r=t=>String(t).padStart(2,"0"),n=`${r(t.getHours())}:${r(t.getMinutes())}`;return e?`${n}:${r(t.getSeconds())}`:n}export function toISODateTime(t,e=!1){return`${toISODate(t)}T${toISOTime(t,e)}`}const r=makeDate(2021,7,1);export function weekdayLabels(t,e,n="short"){const o=dateFormatter(t,{weekday:n});return Array.from({length:7},(t,n)=>o.format(addDays(r,(e+n)%7)))}export function monthLabels(t,e="short"){const r=dateFormatter(t,{month:e});return Array.from({length:12},(t,e)=>r.format(makeDate(2021,e,1)))}export function isMonthBeforeYear(t){const e=dateFormatter(t,{year:"numeric",month:"long"}).formatToParts(r);return e.findIndex(t=>"month"===t.type)<e.findIndex(t=>"year"===t.type)}export function isHour12(t){const e=dateFormatter(t,{hour:"numeric"}).resolvedOptions();return e.hourCycle?"h11"===e.hourCycle||"h12"===e.hourCycle:!0===e.hour12}export function meridiemLabels(t){const e=dateFormatter(t,{hour:"numeric",hour12:!0}),n=t=>{const n=e.formatToParts(withTime(r,{hours:t})).find(t=>"dayPeriod"===t.type);return n?.value??(t<12?"AM":"PM")};return[n(9),n(21)]}export function localeWeekStart(t){try{const e=t??(new Intl.DateTimeFormat).resolvedOptions().locale,r=new Intl.Locale(e),n="function"==typeof r.getWeekInfo?r.getWeekInfo():r.weekInfo;if("number"==typeof n?.firstDay)return n.firstDay%7}catch{}return 0}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The arithmetic and the vocabulary the three layout components share.
3
+ *
4
+ * Like `internal/styles.ts` this is the library talking to itself, and it lives
5
+ * here rather than in either component's folder for the same reason
6
+ * `internal/button-group.ts` does: `GridContainer` and `Grid` are one system in
7
+ * two elements, and neither should have to import the other.
8
+ *
9
+ * What is *not* here is the layout itself. A column width is
10
+ * `(100% + gap) * span / columns - gap`, it has to change at four breakpoints,
11
+ * and it is the width of an element whose column count is declared on its
12
+ * parent — none of which Tailwind can spell, because Tailwind only ever sees
13
+ * class names written out literally and `columns` is a number a caller picks.
14
+ * So the widths are real CSS in `styles.css`, driven by the `--n-*` slots this
15
+ * file generates. That is the same split the rest of the library makes: per-
16
+ * instance values go in inline custom properties, never in class names.
17
+ */
18
+ import type * as React from 'react';
19
+ import type { NebaAlignItems, NebaAlignSelf, NebaBreakpoint, NebaJustifyContent, NebaResponsive } from '../types';
20
+ /** Smallest first, which is also the order the media queries have to be in. */
21
+ export declare const breakpoints: readonly NebaBreakpoint[];
22
+ /**
23
+ * Turns a responsive value into the `--n-{name}-{breakpoint}` slots the CSS
24
+ * reads, emitting only the breakpoints the caller actually named.
25
+ *
26
+ * The gaps are filled in by CSS rather than here: each breakpoint's rule falls
27
+ * back through the ones below it, so `{ md: 6 }` needs one slot and not five.
28
+ * That keeps the inline style on a grid item down to what was asked for.
29
+ */
30
+ export declare function responsiveSlots<T>(name: string, value: NebaResponsive<T> | undefined, toCss: (value: T) => string): React.CSSProperties;
31
+ /**
32
+ * Fills in the `xs` entry of a partial map with the prop's own default.
33
+ *
34
+ * Without this, `spacing={{ md: 4 }}` would be a grid with no gutter at all
35
+ * below 48rem — the CSS fallback rather than the documented default of 2 — and
36
+ * a caller who narrowed one breakpoint would silently lose every other one. A
37
+ * map says "from here up, use this instead"; it does not say "and nothing
38
+ * below".
39
+ */
40
+ export declare function withBaseline<T>(value: NebaResponsive<T> | undefined, baseline: T): NebaResponsive<T>;
41
+ /**
42
+ * A count of columns, as a plain number for `calc()` to divide by.
43
+ *
44
+ * Rounded and floored at 1 because the value ends up as a divisor: a grid of
45
+ * 2.5 columns is not a thing anyone meant, and a grid of 0 is a division by
46
+ * zero that would take the width declaration down with it.
47
+ */
48
+ export declare function columnCount(value: number): string;
49
+ /** A span or an offset. Same rounding; an offset of 0 is meaningful. */
50
+ export declare function columnUnits(value: number, min: number): string;
51
+ export declare const spanValue: (value: number) => string;
52
+ export declare const offsetValue: (value: number) => string;
53
+ /**
54
+ * A gutter, as a length.
55
+ *
56
+ * Fractions are the point — `spacing={1.5}` is `0.375rem`, the same step
57
+ * `gap-1.5` is — so the multiplication is rounded to five places rather than
58
+ * left to print `0.30000000000000004rem` into the DOM.
59
+ */
60
+ export declare function spacingValue(units: number): string;
61
+ export declare const justifyContentClasses: Record<NebaJustifyContent, string>;
62
+ export declare const alignItemsClasses: Record<NebaAlignItems, string>;
63
+ /**
64
+ * Where the *rows* sit when the grid is shorter than the box holding it. Only
65
+ * ever visible on a container with a height of its own, which is why it takes
66
+ * the full distribution vocabulary and `alignItems` does not.
67
+ */
68
+ export declare const alignContentClasses: Record<NebaJustifyContent, string>;
69
+ export declare const alignSelfClasses: Record<NebaAlignSelf, string>;
@@ -0,0 +1 @@
1
+ export const breakpoints=["xs","sm","md","lg","xl"];export function responsiveSlots(t,e,n){const s=function(t){return null==t?{}:"object"==typeof t?t:{xs:t}}(e),o={};for(const e of breakpoints){const r=s[e];void 0!==r&&(o[`--n-${t}-${e}`]=n(r))}return o}export function withBaseline(t,e){return null==t?e:"object"==typeof t?{xs:e,...t}:t}export function columnCount(t){return String(Math.max(1,Math.round(t)))}export function columnUnits(t,e){return String(Math.max(e,Math.round(t)))}export const spanValue=t=>columnUnits(t,1);export const offsetValue=t=>columnUnits(t,0);export function spacingValue(t){const e=.25*Math.max(0,t);return`${Number(e.toFixed(5))}rem`}export const justifyContentClasses={start:"justify-start",center:"justify-center",end:"justify-end","space-between":"justify-between","space-around":"justify-around","space-evenly":"justify-evenly",stretch:"justify-stretch"};export const alignItemsClasses={start:"items-start",center:"items-center",end:"items-end",stretch:"items-stretch",baseline:"items-baseline"};export const alignContentClasses={start:"content-start",center:"content-center",end:"content-end","space-between":"content-between","space-around":"content-around","space-evenly":"content-evenly",stretch:"content-stretch"};export const alignSelfClasses={auto:"self-auto",start:"self-start",center:"self-center",end:"self-end",stretch:"self-stretch",baseline:"self-baseline"};
@@ -0,0 +1,79 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor } from '../types';
3
+ /**
4
+ * The glyphs more than one component draws.
5
+ *
6
+ * All of them are 16×16 with a 1.5px stroke and no fill except where a dot is
7
+ * meant to read as solid, and none of them carries a size: `iconClasses` in
8
+ * `styles.ts` sizes every icon in `em`, so one drawing serves every step of the
9
+ * scale.
10
+ *
11
+ * They live here rather than in the components for the ordinary reason — the ×
12
+ * on a Chip, an Alert, a Dialog and a Toast is one × — and for one that matters
13
+ * more: the severity set is a piece of the design language. An alert that says
14
+ * "this went wrong" only in red says it only to some readers, so the shape has
15
+ * to carry the meaning too, and that only holds if every component uses the
16
+ * same shape for the same family.
17
+ */
18
+ export declare function CloseIcon(): React.JSX.Element;
19
+ /**
20
+ * The disclosure chevron, drawn pointing **down**.
21
+ *
22
+ * One drawing for every direction: a Select's trigger, an Accordion's header, a
23
+ * submenu's arrow and a Pagination's steppers all want the same wedge turned a
24
+ * different way, and turning it is the one allowance the no-transform rule
25
+ * makes — a glyph has no text in it to resample.
26
+ */
27
+ export declare function ChevronIcon(): React.JSX.Element;
28
+ /** The tick: a chosen option, a ticked menu item. */
29
+ export declare function CheckIcon(): React.JSX.Element;
30
+ /**
31
+ * The two steppers, and the `+` that offers a value the list does not have.
32
+ *
33
+ * They are a pair and stay one: a minus drawn to a different weight from the
34
+ * plus beside it reads as two toolkits in one control. NumberField draws both;
35
+ * Combobox draws the plus on its "add this" row.
36
+ */
37
+ export declare function MinusIcon(): React.JSX.Element;
38
+ export declare function PlusIcon(): React.JSX.Element;
39
+ /**
40
+ * The two trend arrows a comparison draws.
41
+ *
42
+ * A pair, and they stay one: an arrow that rises at a different angle from the
43
+ * one that falls beside it reads as two toolkits in one report. Statistic draws
44
+ * both, and reaches for `MinusIcon` above when a figure has not moved — the
45
+ * third state of a comparison is genuinely the absence of an arrow.
46
+ *
47
+ * The shape carries the meaning for the same reason the severity set does: a
48
+ * delta that says "down" only in red says it only to some readers.
49
+ */
50
+ export declare function TrendUpIcon(): React.JSX.Element;
51
+ export declare function TrendDownIcon(): React.JSX.Element;
52
+ /**
53
+ * The two glyphs a picker's trigger wears.
54
+ *
55
+ * They are a pair in the same sense the steppers are: a DateTimePicker draws
56
+ * only the calendar, because a control cannot say two things at once and the
57
+ * date is the part you scan for. Drawn on the same 16×16 grid at the same
58
+ * weight, so a row of a DatePicker and a TimePicker does not look like two
59
+ * icon sets pushed together.
60
+ */
61
+ export declare function CalendarIcon(): React.JSX.Element;
62
+ export declare function ClockIcon(): React.JSX.Element;
63
+ /**
64
+ * The arrow between the two ends of a range.
65
+ *
66
+ * Drawn pointing right and turned under RTL by the component, for the same
67
+ * reason the chevron is: it is a glyph, and there is no text in it to resample.
68
+ */
69
+ export declare function ArrowRightIcon(): React.JSX.Element;
70
+ /** The filled dot: the chosen one of a set, where a tick would say "and". */
71
+ export declare function DotIcon(): React.JSX.Element;
72
+ /**
73
+ * One drawing per colour family.
74
+ *
75
+ * `primary` and `secondary` have no severity to draw, so they take the note the
76
+ * informational one uses — three shapes for six families, because the three
77
+ * that mean something are the three worth telling apart.
78
+ */
79
+ export declare const severityIcons: Record<NebaColor, React.ReactNode>;
@@ -0,0 +1 @@
1
+ import{jsx as r,jsxs as e}from"react/jsx-runtime";export function CloseIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("path",{d:"m4.5 4.5 7 7m0-7-7 7",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round"})})}export function ChevronIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("path",{d:"m4.5 6.5 3.5 3.5 3.5-3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}export function CheckIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("path",{d:"m3.5 8.5 3 3 6-6",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"})})}export function MinusIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("path",{d:"M3.5 8h9",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round"})})}export function PlusIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("path",{d:"M8 3.5v9M3.5 8h9",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round"})})}export function TrendUpIcon(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("path",{d:"M3 11 6.5 7.5 9 10l4-4",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"}),r("path",{d:"M9.5 6h3.5v3.5",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"})]})}export function TrendDownIcon(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("path",{d:"M3 5 6.5 8.5 9 6l4 4",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"}),r("path",{d:"M9.5 10h3.5V6.5",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"})]})}export function CalendarIcon(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("rect",{x:"2",y:"3.25",width:"12",height:"10.75",rx:"2",stroke:"currentColor",strokeWidth:"1.5"}),r("path",{d:"M2 6.75h12",stroke:"currentColor",strokeWidth:"1.5"}),r("path",{d:"M5.25 1.75v2.5M10.75 1.75v2.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]})}export function ClockIcon(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("circle",{cx:"8",cy:"8",r:"6.25",stroke:"currentColor",strokeWidth:"1.5"}),r("path",{d:"M8 4.5V8l2.4 1.6",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]})}export function ArrowRightIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("path",{d:"M3 8h10m-3.5-3.5L13 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}export function DotIcon(){return r("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:r("circle",{cx:"8",cy:"8",r:"3.25",fill:"currentColor"})})}function o(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("circle",{cx:"8",cy:"8",r:"6.25",stroke:"currentColor",strokeWidth:"1.5"}),r("path",{d:"M8 7.25v4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),r("circle",{cx:"8",cy:"4.9",r:"0.85",fill:"currentColor"})]})}export const severityIcons={primary:r(o,{}),secondary:r(o,{}),info:r(o,{}),success:e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("circle",{cx:"8",cy:"8",r:"6.25",stroke:"currentColor",strokeWidth:"1.5"}),r("path",{d:"m5.25 8.25 1.9 1.9 3.6-3.9",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]}),warning:e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("path",{d:"M7.13 2.6 1.9 11.7a1 1 0 0 0 .87 1.5h10.46a1 1 0 0 0 .87-1.5L8.87 2.6a1 1 0 0 0-1.74 0Z",stroke:"currentColor",strokeWidth:"1.5",strokeLinejoin:"round"}),r("path",{d:"M8 6.1v3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),r("circle",{cx:"8",cy:"11.2",r:"0.85",fill:"currentColor"})]}),danger:e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[r("circle",{cx:"8",cy:"8",r:"6.25",stroke:"currentColor",strokeWidth:"1.5"}),r("path",{d:"m5.9 5.9 4.2 4.2m0-4.2-4.2 4.2",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]})};
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaDensity, NebaSize } from '../types';
3
+ /**
4
+ * What a menu item inherits from the menu around it.
5
+ *
6
+ * The same arrangement `ButtonGroup` uses, and for the same reason: `size`,
7
+ * `color` and `density` are properties of the *menu*, not of any one row in it,
8
+ * and passing them per item would be three chances per row to get one wrong —
9
+ * with a silent failure, a menu where the fourth item is a size bigger.
10
+ *
11
+ * It lives in `internal/` rather than in `Menu.tsx` because a submenu is a menu
12
+ * inside a menu and a context menu is the same rows hung off a right-click, so
13
+ * three components read this and none of them should have to import the others.
14
+ */
15
+ export interface MenuContextValue {
16
+ size: NebaSize;
17
+ color: NebaColor;
18
+ density: NebaDensity;
19
+ }
20
+ export declare const MenuContext: React.Context<MenuContextValue>;
@@ -0,0 +1 @@
1
+ import*as t from"react";export const MenuContext=t.createContext({size:"md",color:"primary",density:"default"});
@@ -0,0 +1,111 @@
1
+ import * as React from 'react';
2
+ import type { PickerLabels } from './calendar';
3
+ import type { NebaColor, NebaElevation, NebaSize, NebaStyleProps } from '../types';
4
+ /**
5
+ * The shell all four pickers wear: a field-shaped trigger with a popup hanging
6
+ * off it.
7
+ *
8
+ * It is here rather than in one of the components for the reason the calendar
9
+ * is: four components need it, and none of them should have to import another.
10
+ * What it draws is deliberately not new — the trigger is `fieldRestClasses`,
11
+ * which is the same box a TextField and a Select's trigger are drawn on, to the
12
+ * pixel. A form where the date field is a different height, radius or colour
13
+ * from the text field beside it is a form that looks assembled rather than
14
+ * designed.
15
+ *
16
+ * The one thing the pickers do *not* offer is typing a date into the trigger.
17
+ * Parsing a date out of free text is locale-dependent in a way that cannot be
18
+ * done honestly without a date library, and a field that understands `27/7/26`
19
+ * in one browser and not the next is worse than one that never claimed to. So
20
+ * the trigger is a button, exactly as a Select's is, and the calendar is where
21
+ * the answer comes from.
22
+ */
23
+ /**
24
+ * The popup's slots: a container's undyed sheet with the *control* fill added
25
+ * back on top.
26
+ *
27
+ * Neither generator in `internal/styles` says this on its own, and the reason is
28
+ * that a picker's popup is both things at once. It is a container — it holds a
29
+ * grid of forty-two days, and dyeing the sheet under them would put every one of
30
+ * them on a background it was not chosen against — and it also holds the one
31
+ * filled token in the library that has to be legible without being read, which
32
+ * is the day you picked. So the sheet stays white and the family arrives in the
33
+ * four fill slots the chosen cell reads.
34
+ */
35
+ export declare function popupSlots(color: NebaColor, elevation: NebaElevation): React.CSSProperties;
36
+ /**
37
+ * The popup. Like every floating surface in the library it carries a shadow by
38
+ * default, at level 3 — as far as the scale goes without hovering — because it
39
+ * is genuinely off the page rather than merely on top of it.
40
+ */
41
+ export declare const pickerPopupClasses: string;
42
+ /** The popup's own padding, one track tighter than a control's. */
43
+ export declare const popupPaddingClasses: Record<NebaSize, string>;
44
+ export interface PickerShellProps extends NebaStyleProps {
45
+ elevation?: NebaElevation;
46
+ /** Label above the trigger. */
47
+ label?: React.ReactNode;
48
+ /** Helper text below it. */
49
+ description?: React.ReactNode;
50
+ /** Error message below. Its presence also turns the control invalid. */
51
+ error?: React.ReactNode;
52
+ invalid?: boolean;
53
+ /** The glyph before the value — a calendar or a clock. */
54
+ startIcon?: React.ReactNode;
55
+ fullWidth?: boolean;
56
+ disabled?: boolean;
57
+ readOnly?: boolean;
58
+ required?: boolean;
59
+ id?: string;
60
+ className?: string;
61
+ style?: React.CSSProperties;
62
+ }
63
+ interface InternalShellProps extends PickerShellProps {
64
+ /** What the trigger reads. A placeholder when `empty`. */
65
+ display: React.ReactNode;
66
+ /**
67
+ * Every string the display could hold, so the trigger stops changing width
68
+ * with its value. `displaySamples` in `internal/date` produces them and
69
+ * `WidthSizer` is what lays them out.
70
+ */
71
+ samples?: string[];
72
+ /** Nothing has been chosen yet, so the display is muted. */
73
+ empty: boolean;
74
+ /** Offers the × that empties the control. */
75
+ clearable?: boolean;
76
+ onClear: () => void;
77
+ open: boolean;
78
+ onOpenChange: (open: boolean) => void;
79
+ labels: PickerLabels;
80
+ /** `<input type="hidden">` rows, so the control submits with a form. */
81
+ hiddenValues?: Array<{
82
+ name: string;
83
+ value: string;
84
+ }>;
85
+ /** How far off the trigger the popup sits. */
86
+ sideOffset?: number;
87
+ children: React.ReactNode;
88
+ triggerRef?: React.Ref<HTMLButtonElement>;
89
+ }
90
+ /**
91
+ * A trigger, a label, the two lines of text under it, and a popup.
92
+ *
93
+ * Everything about it that is visible is a decision already made elsewhere: the
94
+ * shell classes, the read-only and disabled treatments, the label's type scale
95
+ * and the way `invalid` re-points the whole colour family at `danger` so the
96
+ * edge, the ring and the message turn over together.
97
+ */
98
+ export declare function PickerShell({ variant, size, color, density, elevation, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, id, className, style, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, sideOffset, children, triggerRef }: InternalShellProps): React.JSX.Element;
99
+ /**
100
+ * The row of shortcuts under a picker's panel.
101
+ *
102
+ * A hairline above it rather than a gap, because the actions act on the panel
103
+ * and a gap would read as a second popup stacked under the first.
104
+ */
105
+ export declare function PickerFooter({ size, children }: {
106
+ size: NebaSize;
107
+ children: React.ReactNode;
108
+ }): React.JSX.Element;
109
+ /** The vertical hairline between a calendar and the clock beside it. */
110
+ export declare function PickerDivider(): React.JSX.Element;
111
+ export {};
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as a from"react";import{Field as i}from"@base-ui/react/field";import{Popover as t}from"@base-ui/react/popover";import{CloseIcon as l}from"./icons";import{WidthSizer as r}from"./sizer";import{chipRemoveClasses as o,controlHeightClasses as s,controlTextLeadingClasses as d,cx as c,disabledClasses as p,fieldReadOnlyClasses as u,fieldRestClasses as m,focusWithinRingClasses as f,gapClasses as b,iconClasses as h,metaTextClasses as x,paddingXClasses as g,radiusClasses as v,stackGapClasses as y,surfaceClasses as N,surfaceSlots as w,transitionClasses as P}from"./styles";export function popupSlots(e,n){return{...w(e,n),"--n-fill":`var(--neba-${e}-fill)`,"--n-fill-hover":`var(--neba-${e}-fill-hover)`,"--n-fill-active":`var(--neba-${e}-fill-active)`,"--n-on-solid":`var(--neba-${e}-on-solid)`}}const k=["group relative flex w-full items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",P,"focus-within:[transition-duration:0ms]",f,h].join(" ");export const pickerPopupClasses=[N,"border 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(" ");export const popupPaddingClasses={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function PickerShell({variant:f="outline",size:h="md",color:N="primary",density:P="default",elevation:C=0,label:$,description:j,error:O,invalid:z,startIcon:F,fullWidth:R=!1,disabled:S=!1,readOnly:q=!1,required:D=!1,id:I,className:_,style:B,display:E,samples:L,empty:T,clearable:V=!1,onClear:W,open:A,onOpenChange:G,labels:H,hiddenValues:J,sideOffset:K=6,children:M,triggerRef:Q}){const U=a.useId(),X=I??`${U}-trigger`,Y=`${U}-label`,Z=`${U}-description`,ee=`${U}-error`,ne=null!=O&&!1!==O&&""!==O,ae=z??ne,ie=ae?"danger":N,te=S||q,le=[j?Z:null,ne?ee:null].filter(Boolean).join(" ")||void 0;return n(i.Root,{disabled:S,invalid:ae,className:c("flex-col align-top",y[h],R?"flex w-full":"inline-flex",_),style:{...w(ie,C),...B},children:[$?e(i.Label,{id:Y,htmlFor:X,className:c(x[h],"font-medium",S?"text-(--neba-disabled-fg)":"text-(--neba-fg)"),children:$}):null,n(t.Root,{open:A,onOpenChange:e=>G(e),children:[n("span",{className:c(k,s[h],d[h],v[h],b[h],g[P][h],S?p[f]:q?u[f]:m[f]),children:[n(t.Trigger,{id:X,ref:Q,disabled:S,"aria-labelledby":$?Y:void 0,"aria-describedby":le,"aria-required":D||void 0,"aria-invalid":ae||void 0,className:c("flex min-w-0 flex-1 items-center bg-transparent text-start [font:inherit] text-inherit",b[h],"[outline:none]",te?"cursor-default":"cursor-pointer"),children:[F?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg) transition-[color] duration-(--neba-duration) group-focus-within:text-(--n-accent)",children:F}):null,n("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:c("w-full truncate",T?"text-(--neba-muted-fg)":"text-(--neba-fg)"),children:E}),e(r,{samples:L??[]})]})]}),!V||T||te?null:e("button",{type:"button","aria-label":H.clear,className:c(o,"text-(--neba-muted-fg)"),onClick:e=>{e.stopPropagation(),W()},children:e(l,{})})]}),e(t.Portal,{children:e(t.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:K,align:"start",children:e(t.Popup,{initialFocus:!1,className:c(pickerPopupClasses,v[h],popupPaddingClasses[h],d[h]),style:popupSlots(ie,3),children:M})})})]}),j?e(i.Description,{id:Z,className:c(x[h],"text-(--neba-muted-fg)"),children:j}):null,ne?e(i.Error,{id:ee,match:!0,className:c(x[h],"text-(--n-accent)"),children:O}):null,J?.map((n,a)=>e("input",{type:"hidden",name:n.name,value:n.value},a))]})}export function PickerFooter({size:n,children:a}){return e("div",{className:c("flex items-center justify-end border-t pt-1.5","[border-color:var(--n-line)]",b[n]),children:a})}export function PickerDivider(){return e("div",{"aria-hidden":"true",className:"w-px self-stretch bg-(--n-line)"})}