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 @@
1
+ import{jsx as e,jsxs as n,Fragment as t}from"react/jsx-runtime";import*as o from"react";import{controlSlots as l,controlTextClasses as r,focusRingClasses as i,gapClasses as s,hasContent as a,iconClasses as c,iconSizeClasses as d,metaTextClasses as m,paddingXClasses as x,pressTransitionClasses as f,sheetBodyClasses as p,surfaceClasses as u,transitionClasses as h}from"../../internal/styles";const v={solid:[u,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[u,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:`${u} text-(--n-accent) bg-(--n-soft)`},b={solid:"hover:bg-(--n-fill-hover) active:bg-(--n-fill-active)",outline:"hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)] active:bg-(--n-panel-press)",text:"hover:bg-(--n-soft-hover) active:bg-(--n-soft-press)"},g={xs:"min-h-5.5",sm:"min-h-6.5",md:"min-h-8",lg:"min-h-10",xl:"min-h-12"},w={xs:"rounded-[0.6875rem]",sm:"rounded-[0.8125rem]",md:"rounded-[1rem]",lg:"rounded-[1.25rem]",xl:"rounded-[1.5rem]"},j={default:{xs:"px-3",sm:"px-4",md:"px-5",lg:"px-6",xl:"px-8"},compact:{xs:"px-1.5",sm:"px-2",md:"px-2.5",lg:"px-3",xl:"px-4"}},y={static:{top:"",bottom:""},sticky:{top:"sticky top-3 z-20",bottom:"sticky bottom-3 z-20"},fixed:{top:"fixed inset-x-0 top-3 z-30 mx-auto w-fit",bottom:"fixed inset-x-0 bottom-3 z-30 mx-auto w-fit"}};export const Pill=o.forwardRef(function({variant:u="solid",size:N="md",color:k="secondary",density:z="default",elevation:$=2,startIcon:_,endIcon:C,title:R,description:B,details:H,expanded:I=!1,position:E="static",side:F="top",className:O,style:P,children:S,onClick:q,...A},D){const G=o.useRef(null),[J,K]=o.useState(0);o.useEffect(()=>{const e=G.current;if(!e)return;const n=new ResizeObserver(()=>{K(e.scrollHeight)});return n.observe(e),K(e.scrollHeight),()=>n.disconnect()},[H]);const L=Boolean(q),M=x[z][N],Q=n(t,{children:[a(_)?e("span",{className:`flex shrink-0 items-center justify-center overflow-hidden rounded-full [&_img]:size-full [&_img]:object-cover ${d[N]}`,children:_}):null,a(R)||a(B)||a(S)?n("span",{className:["flex min-w-0 flex-1 flex-col items-center justify-center text-center",j[z][N]].join(" "),children:[a(R)?e("span",{className:"max-w-full truncate",children:R}):null,a(B)?e("span",{className:`max-w-full truncate font-normal ${m[N]} [color:color-mix(in_oklab,currentColor_72%,transparent)]`,children:B}):null,S]}):null]});return n("div",{ref:D,className:["inline-flex max-w-full flex-col overflow-hidden align-middle",w[N],"font-medium whitespace-nowrap select-none",r[N],v[u],h,f,c,L?`neba-glow ${b[u]}`:"",y[E][F],O??""].filter(Boolean).join(" "),style:{...l(k,$,u),...P},...A,children:[n("div",{className:["flex shrink-0 items-center py-1",g[N],s[N],L?"ps-0":M,a(C)?"pe-1":L?"pe-0":""].join(" "),children:[L?e("button",{type:"button",className:["flex min-w-0 flex-1 cursor-pointer items-center justify-center self-stretch","rounded-[inherit]",s[N],M,i].join(" "),onClick:q,children:Q}):Q,a(C)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:C}):null]}),a(H)?e("div",{className:["overflow-hidden","[transition:height_var(--neba-duration)_var(--neba-ease)]","motion-reduce:[transition-duration:0ms]"].join(" "),style:{height:I?J:0},inert:!I,children:e("div",{ref:G,className:`whitespace-normal ${M} pb-2 ${p[N]}`,children:H})}):null]})});
@@ -0,0 +1,2 @@
1
+ export { Pill } from './Pill';
2
+ export type { PillProps } from './Pill';
@@ -0,0 +1 @@
1
+ export{Pill}from"./Pill";
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Radio as n}from"@base-ui/react/radio";import{RadioGroup as l}from"@base-ui/react/radio-group";import{Field as o}from"@base-ui/react/field";import{controlTextClasses as i,metaTextClasses as t,surfaceClasses as s,tickSizeClasses as d,transitionClasses as c}from"../../internal/styles";const b=r.createContext({size:"md",color:"primary",readOnly:!1}),f=["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",c,"active:[transition-duration:0ms]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),h=[s,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)]","hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]","data-[checked]:[box-shadow:var(--neba-plate-solid)]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),p=[s,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)] [filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),m=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)] shadow-none","data-[checked]:bg-(--neba-disabled-bg)"].join(" ");export const Radio=r.forwardRef(function({label:l,description:s,disabled:c=!1,className:u,style:v,...x},g){const y=r.useContext(b),N=x.readOnly??y.readOnly;return e(o.Root,{disabled:c,className:["flex flex-col",u??""].filter(Boolean).join(" "),style:v,children:a("div",{className:`flex items-start gap-2 ${i[y.size]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(n.Root,{ref:g,className:[f,d[y.size],c?m:N?p:h].join(" "),disabled:c,...x,children:e(n.Indicator,{className:"size-[38%] rounded-full bg-current"})})}),l||s?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[l?e(o.Label,{className:["leading-[1.4]",c?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:l}):null,s?e(o.Description,{className:`${t[y.size]} text-(--neba-muted-fg)`,children:s}):null]}):null]})})});export const RadioGroup=r.forwardRef(function({size:n="md",color:i="primary",orientation:s="vertical",label:d,description:c,error:f,invalid:h,disabled:p=!1,readOnly:m=!1,className:u,style:v,children:x,...g},y){const N=null!=f&&!1!==f&&""!==f,j=h??N,k=j?"danger":i,w={"--n-fill":`var(--neba-${k}-fill)`,"--n-fill-hover":`var(--neba-${k}-fill-hover)`,"--n-on-solid":`var(--neba-${k}-on-solid)`,"--n-accent":`var(--neba-${k}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${k}-line)`,"--n-line-hover":`var(--neba-${k}-line-hover)`,"--n-ring":`var(--neba-${k}-ring)`},$=r.useMemo(()=>({size:n,color:k,readOnly:m}),[n,k,m]);return e(b.Provider,{value:$,children:a(o.Root,{disabled:p,invalid:j,className:["flex flex-col gap-1.5",u??""].filter(Boolean).join(" "),style:{...w,...v},children:[d?e(o.Label,{className:[t[n],"font-medium",p?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:d}):null,c?e(o.Description,{className:`${t[n]} text-(--neba-muted-fg)`,children:c}):null,e(l,{ref:y,disabled:p,readOnly:m,className:["flex","horizontal"===s?"flex-row flex-wrap gap-x-5 gap-y-2":"flex-col gap-2"].join(" "),...g,children:x}),N?e(o.Error,{match:!0,className:`${t[n]} text-(--n-accent)`,children:f}):null]})})});
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Radio as n}from"@base-ui/react/radio";import{RadioGroup as l}from"@base-ui/react/radio-group";import{Field as o}from"@base-ui/react/field";import{controlTextClasses as i,metaTextClasses as t,surfaceClasses as s,tickDotClasses as d,tickRowLeadingClasses as c,tickSizeClasses as b,transitionClasses as f}from"../../internal/styles";const h=r.createContext({size:"md",color:"primary",readOnly:!1}),m=["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",f,"active:[transition-duration:0ms]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),u=[s,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),p=[s,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:text-(--n-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),v=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)] shadow-none","data-[checked]:bg-(--neba-disabled-bg)"].join(" ");export const Radio=r.forwardRef(function({label:l,description:s,disabled:f=!1,className:x,style:g,...y},N){const j=r.useContext(h),$=y.readOnly??j.readOnly;return e(o.Root,{disabled:f,className:["flex flex-col",x??""].filter(Boolean).join(" "),style:g,children:a("div",{className:`flex items-start gap-2 ${i[j.size]} ${c}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(n.Root,{ref:N,className:[m,b[j.size],f?v:$?p:u].join(" "),disabled:f,...y,children:e(n.Indicator,{className:`rounded-full bg-current ${d[j.size]}`})})}),l||s?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[l?e(o.Label,{className:["leading-[1.4]",f?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:l}):null,s?e(o.Description,{className:`${t[j.size]} text-(--neba-muted-fg)`,children:s}):null]}):null]})})});export const RadioGroup=r.forwardRef(function({size:n="md",color:i="primary",orientation:s="vertical",label:d,description:c,error:b,invalid:f,disabled:m=!1,readOnly:u=!1,className:p,style:v,children:x,...g},y){const N=null!=b&&!1!==b&&""!==b,j=f??N,$=j?"danger":i,k={"--n-fill":`var(--neba-${$}-fill)`,"--n-fill-hover":`var(--neba-${$}-fill-hover)`,"--n-on-solid":`var(--neba-${$}-on-solid)`,"--n-accent":`var(--neba-${$}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${$}-line)`,"--n-line-hover":`var(--neba-${$}-line-hover)`,"--n-ring":`var(--neba-${$}-ring)`},R=r.useMemo(()=>({size:n,color:$,readOnly:u}),[n,$,u]);return e(h.Provider,{value:R,children:a(o.Root,{disabled:m,invalid:j,className:["flex flex-col gap-1.5",p??""].filter(Boolean).join(" "),style:{...k,...v},children:[d?e(o.Label,{className:[t[n],"font-medium",m?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:d}):null,c?e(o.Description,{className:`${t[n]} text-(--neba-muted-fg)`,children:c}):null,e(l,{ref:y,disabled:m,readOnly:u,className:["flex","horizontal"===s?"flex-row flex-wrap gap-x-5 gap-y-2":"flex-col gap-2"].join(" "),...g,children:x}),N?e(o.Error,{match:!0,className:`${t[n]} text-(--n-accent)`,children:b}):null]})})});
@@ -0,0 +1,77 @@
1
+ import * as React from 'react';
2
+ import type { NebaElevation, NebaStyleProps, NebaVariant } from '../../types';
3
+ /** A segment's value. The same restraint Tabs and Select put on theirs. */
4
+ export type SegmentValue = string | number;
5
+ export interface SegmentedButtonProps extends Omit<NebaStyleProps, 'variant'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
6
+ /**
7
+ * Weight of the trough the segments sit in.
8
+ *
9
+ * - `solid` — a frosted trough with a filled tile riding in it. The loudest,
10
+ * and the one for a control a screen is about to be steered by.
11
+ * - `outline` — the same trough with a hairline around it and a lit tile
12
+ * rather than a filled one. The default.
13
+ * - `text` — no trough at all: the segments sit straight on the page and only
14
+ * the chosen one has a surface.
15
+ * @default 'outline'
16
+ */
17
+ variant?: NebaVariant;
18
+ /** The chosen segment. Use with `onValueChange` for a controlled set. */
19
+ value?: SegmentValue | null;
20
+ /** Which starts chosen, for an uncontrolled set. */
21
+ defaultValue?: SegmentValue | null;
22
+ onValueChange?: (value: SegmentValue | null) => void;
23
+ /**
24
+ * Drop shadow depth of the trough. `0` (the default) is flat.
25
+ * @default 0
26
+ */
27
+ elevation?: NebaElevation;
28
+ /** Disables every segment at once. */
29
+ disabled?: boolean;
30
+ /** Shows which one is chosen but does not let it be changed. */
31
+ readOnly?: boolean;
32
+ /** Identifies the value when a form is submitted. */
33
+ name?: string;
34
+ /** The segments share the full width, each taking an equal part of it. */
35
+ fullWidth?: boolean;
36
+ children?: React.ReactNode;
37
+ }
38
+ export interface SegmentProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'value' | 'color'> {
39
+ /** Identifies the segment. What `onValueChange` reports. */
40
+ value: SegmentValue;
41
+ /** Content before the label. Sized in `em`, so it tracks the label. */
42
+ startIcon?: React.ReactNode;
43
+ /** Content after the label — a count, a status dot. */
44
+ endIcon?: React.ReactNode;
45
+ /** Unavailable, but still part of the set. */
46
+ disabled?: boolean;
47
+ children?: React.ReactNode;
48
+ }
49
+ /**
50
+ * One choice in a segmented button.
51
+ *
52
+ * It has no `size`, no `color` and no `variant` of its own: all three belong to
53
+ * the set, which is the only place they can be set once and mean the same thing
54
+ * for every segment.
55
+ */
56
+ export declare const Segment: React.ForwardRefExoticComponent<SegmentProps & React.RefAttributes<HTMLElement>>;
57
+ /**
58
+ * Two or more choices in one pill, exactly one of them taken.
59
+ *
60
+ * Underneath it is a radio group, and that is the whole accessibility argument:
61
+ * a segmented button *is* "exactly one of these", so it gets `role="radiogroup"`,
62
+ * one tab stop for the set, arrow keys within it, and `aria-checked` on the one
63
+ * that is taken. Building it out of `aria-pressed` toggles — which is what a row
64
+ * of buttons would give — would announce four independent switches, three of
65
+ * which happen to be off.
66
+ *
67
+ * The tile slides because its `left`, `top`, `width` and `height` are measured
68
+ * off the chosen segment and animated. Nothing is transformed: the tile is an
69
+ * empty box, and no label is resampled while it travels. That is the same
70
+ * distinction Tabs' indicator draws, and the reason the house no-transform rule
71
+ * survives a component whose entire point is that something moves.
72
+ *
73
+ * `left`, not `inset-inline-start`, for the reason Tabs gives: `offsetLeft` is a
74
+ * distance from the left edge and stays one under RTL. Pairing a physical
75
+ * measurement with a logical property is what would break the direction.
76
+ */
77
+ export declare const SegmentedButton: React.ForwardRefExoticComponent<SegmentedButtonProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{Radio as n}from"@base-ui/react/radio";import{RadioGroup as r}from"@base-ui/react/radio-group";import{controlHeightClasses as s,controlSlots as l,controlTextClasses as o,gapClasses as i,hasContent as d,iconClasses as u,paddingXClasses as c,surfaceClasses as f,transitionClasses as h}from"../../internal/styles";const p=a.createContext({variant:"outline",size:"md",density:"default",fullWidth:!1}),b={solid:`${f} bg-(--n-panel) p-1 [box-shadow:var(--n-elev),var(--neba-plate-glass)]`,outline:`${f} border bg-(--n-panel) p-1 [border-color:var(--n-line)] [box-shadow:var(--n-elev),var(--neba-plate-glass)]`,text:""},m={solid:`${f} bg-(--n-fill) [box-shadow:var(--neba-shadow-1),var(--neba-plate-solid)]`,outline:`${f} bg-(--n-panel-press) [box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]`,text:`${f} bg-(--n-panel-press) [box-shadow:var(--neba-shadow-1),var(--neba-plate-glass)]`},v={solid:"data-[checked]:text-(--n-on-solid)",outline:"data-[checked]:text-(--n-accent)",text:"data-[checked]:text-(--n-accent)"};export const Segment=a.forwardRef(function({value:r,startIcon:l,endIcon:f,disabled:b=!1,className:m,children:x,...g},y){const{variant:w,size:k,density:$,fullWidth:R}=a.useContext(p);return t(n.Root,{ref:y,value:r,disabled:b,"data-segment":"",className:["relative z-10 inline-flex shrink-0 cursor-pointer items-center justify-center select-none","whitespace-nowrap font-medium","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",s[k],o[k],i[k],c[$][k],"rounded-full",h,u,"text-(--neba-muted-fg) hover:text-(--neba-fg)",v[w],"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","data-[readonly]:cursor-default",R?"flex-1":"",m??""].filter(Boolean).join(" "),...g,children:[d(l)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:l}):null,x,d(f)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:f}):null]})});export const SegmentedButton=a.forwardRef(function({variant:n="outline",size:s="md",color:o="primary",density:i="default",elevation:d=0,value:u,defaultValue:c=null,onValueChange:f,disabled:v=!1,readOnly:x=!1,name:g,fullWidth:y=!1,className:w,style:k,children:$,...R},j){const[N,z]=a.useState(c),W=void 0!==u,C=W?u:N,P=a.useRef(null),S=a.useRef(null),A=a.useCallback(e=>{const t=P.current,a=S.current;if(!t||!a)return;const n=t.querySelector("[data-segment][data-checked]");if(!n)return;const r=!e||!a.hasAttribute("data-ready");r&&a.removeAttribute("data-ready"),a.style.setProperty("--n-seg-x",`${n.offsetLeft}px`),a.style.setProperty("--n-seg-y",`${n.offsetTop}px`),a.style.setProperty("--n-seg-w",`${n.offsetWidth}px`),a.style.setProperty("--n-seg-h",`${n.offsetHeight}px`),r&&a.offsetWidth,a.setAttribute("data-ready","")},[]);a.useLayoutEffect(()=>{A(!0)},[A,C,n,s,i,y,$]),a.useEffect(()=>{const e=P.current;if(!e)return;const t=new ResizeObserver(()=>A(!1));return t.observe(e),()=>t.disconnect()},[A]);const B=a.useMemo(()=>({variant:n,size:s,density:i,fullWidth:y}),[n,s,i,y]);return e(p.Provider,{value:B,children:t(r,{ref:e=>{P.current=e,"function"==typeof j?j(e):j&&(j.current=e)},value:C,onValueChange:e=>{const t=e??null;W||z(t),f?.(t)},disabled:v,readOnly:x,name:g,className:["relative inline-flex items-center rounded-full",b[n],h,x?"[filter:saturate(0.55)]":"",y?"flex w-full":"",w??""].filter(Boolean).join(" "),style:{...l(o,d,n),...k},...R,children:[null!=C?e("span",{ref:S,"aria-hidden":"true",className:["pointer-events-none absolute rounded-full","left-(--n-seg-x) top-(--n-seg-y) h-(--n-seg-h) w-(--n-seg-w)",m[n],"[transition-property:left,top,width,height]","[transition-timing-function:var(--neba-ease)]","[transition-duration:0ms] data-[ready]:[transition-duration:var(--neba-duration)]"].join(" ")}):null,$]})})});
@@ -0,0 +1,2 @@
1
+ export { Segment, SegmentedButton } from './SegmentedButton';
2
+ export type { SegmentedButtonProps, SegmentProps, SegmentValue } from './SegmentedButton';
@@ -0,0 +1 @@
1
+ export{Segment,SegmentedButton}from"./SegmentedButton";
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Select as l}from"@base-ui/react/select";import{Field as n}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons";import{controlHeightClasses as o,controlTextLeadingClasses as s,disabledClasses as d,fieldReadOnlyClasses as c,fieldRestClasses as u,focusWithinRingClasses as m,gapClasses as h,iconClasses as f,metaTextClasses as p,paddingXClasses as b,radiusClasses as g,stackGapClasses as x,surfaceClasses as v,surfaceSlots as N,transitionClasses as j}from"../../internal/styles";const w=["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",j,"focus-within:[transition-duration:0ms]",m,f].join(" "),y=[v,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--n-panel-press) p-1","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]"].join(" "),I=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",j,"data-[highlighted]:bg-(--n-soft-hover)","data-[selected]:text-(--n-accent) data-[selected]:font-medium","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","[outline:none]"].join(" ");export const Select=t.forwardRef(function({variant:m="outline",size:f="md",color:v="primary",density:j="default",elevation:$=0,items:S,value:V,defaultValue:k,onValueChange:z,placeholder:O,label:P,description:R,error:T,invalid:q,startIcon:C,fullWidth:W=!1,disabled:_=!1,readOnly:B=!1,required:D=!1,name:E,id:L,className:M,style:A},F){const G=null!=T&&!1!==T&&""!==T,H=q??G,J=H?"danger":v,K=t.useMemo(()=>S.map(e=>({label:e.label??String(e.value),value:e.value})),[S]);return a(n.Root,{disabled:_,invalid:H,className:["flex-col align-top",x[f],W?"flex w-full":"inline-flex",M??""].filter(Boolean).join(" "),style:{...N(J,$),...A},children:[P?e(n.Label,{className:[p[f],"font-medium",_?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:P}):null,a(l.Root,{id:L,name:E,items:K,value:V,defaultValue:k,onValueChange:e=>z?.(e),disabled:_,readOnly:B,required:D,children:[a(l.Trigger,{ref:F,className:[w,o[f],s[f],g[f],h[f],b[j][f],_?d[m]:B?`${c[m]} cursor-default`:u[m]].join(" "),children:[C?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:C}):null,e(l.Value,{className:["min-w-0 flex-1 truncate text-start","data-[placeholder]:text-(--neba-muted-fg)"].join(" "),placeholder:O}),e(l.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)","[transition:rotate_var(--neba-duration)_var(--neba-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(l.Portal,{children:e(l.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(l.Popup,{className:`${y} ${g[f]} ${s[f]}`,children:S.map(t=>a(l.Item,{value:t.value,disabled:t.disabled,className:I,children:[e(l.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(l.ItemText,{className:"truncate",children:t.label??String(t.value)})]},String(t.value)))})})})]}),R?e(n.Description,{className:`${p[f]} text-(--neba-muted-fg)`,children:R}):null,G?e(n.Error,{match:!0,className:`${p[f]} text-(--n-accent)`,children:T}):null]})});
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Select as l}from"@base-ui/react/select";import{Field as n}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons";import{WidthSizer as s}from"../../internal/sizer";import{controlHeightClasses as o,controlTextLeadingClasses as d,disabledClasses as c,fieldReadOnlyClasses as m,fieldRestClasses as u,focusWithinRingClasses as h,gapClasses as f,hasContent as p,iconClasses as b,metaTextClasses as g,paddingXClasses as x,radiusClasses as v,stackGapClasses as N,surfaceClasses as w,surfaceSlots as j,transitionClasses as y}from"../../internal/styles";const I=["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",y,"focus-within:[transition-duration:0ms]",h,b].join(" "),S=[w,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--n-panel-press) p-1","[border-color:var(--n-line)]","[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]","[outline:none]"].join(" "),$=["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--neba-radius-xs) py-1.5 pe-2 ps-7",y,"data-[highlighted]:bg-(--n-soft-hover) data-[highlighted]:text-(--n-accent)","data-[selected]:text-(--n-accent) data-[selected]:font-medium","data-[disabled]:cursor-not-allowed data-[disabled]:text-(--neba-disabled-fg)","[outline:none]"].join(" ");export const Select=t.forwardRef(function({variant:h="outline",size:b="md",color:w="primary",density:y="default",elevation:V=0,items:z,value:k,defaultValue:O,onValueChange:P,placeholder:R,label:T,description:q,error:C,invalid:M,startIcon:W,fullWidth:_=!1,disabled:B=!1,readOnly:D=!1,required:E=!1,name:L,id:A,className:F,style:G},H){const J=null!=C&&!1!==C&&""!==C,K=M??J,Q=K?"danger":w,U=t.useMemo(()=>z.map(e=>({label:e.label??String(e.value),value:e.value})),[z]),X=t.useMemo(()=>[...z.map(e=>e.label??String(e.value)),...p(R)?[R]:[]],[z,R]);return a(n.Root,{disabled:B,invalid:K,className:["flex-col align-top",N[b],_?"flex w-full":"inline-flex",F??""].filter(Boolean).join(" "),style:{...j(Q,V),...G},children:[T?e(n.Label,{className:[g[b],"font-medium",B?"text-(--neba-disabled-fg)":"text-(--neba-fg)"].join(" "),children:T}):null,a(l.Root,{id:A,name:L,items:U,value:k,defaultValue:O,onValueChange:e=>P?.(e),disabled:B,readOnly:D,required:E,children:[a(l.Trigger,{ref:H,className:[I,o[b],d[b],v[b],f[b],x[y][b],B?c[h]:D?`${m[h]} cursor-default`:u[h]].join(" "),children:[W?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)",children:W}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e(l.Value,{className:["w-full truncate text-start","data-[placeholder]:text-(--neba-muted-fg)"].join(" "),placeholder:R}),e(s,{samples:X})]}),e(l.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--neba-muted-fg)","[transition:rotate_var(--neba-duration)_var(--neba-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(l.Portal,{children:e(l.Positioner,{className:"neba-portal z-50 [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(l.Popup,{className:`${S} ${v[b]} ${d[b]}`,style:j(Q,3),children:z.map(t=>a(l.Item,{value:t.value,disabled:t.disabled,className:$,children:[e(l.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(l.ItemText,{className:"truncate",children:t.label??String(t.value)})]},String(t.value)))})})})]}),q?e(n.Description,{className:`${g[b]} text-(--neba-muted-fg)`,children:q}):null,J?e(n.Error,{match:!0,className:`${g[b]} text-(--n-accent)`,children:C}):null]})});
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ import type { NebaElevation, NebaStyleProps } from '../../types';
3
+ /**
4
+ * Which keyboard the shortcut is being read on.
5
+ *
6
+ * `auto` asks the browser, which is right for a shortcut a reader is about to
7
+ * press. The three explicit values are for documentation that has to name a
8
+ * platform rather than the reader's own — a support page describing the Windows
9
+ * build, a table comparing the two.
10
+ */
11
+ export type ShortcutOS = 'auto' | 'mac' | 'windows' | 'linux';
12
+ export interface ShortcutProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'span'>, 'color' | 'children'> {
13
+ /**
14
+ * The keys, innermost punctuation and all.
15
+ *
16
+ * A string is split on `+` — `'Mod+Shift+P'` — which covers everything except
17
+ * a shortcut whose key *is* a plus. For that one, pass the array form:
18
+ * `keys={['Ctrl', '+']}`.
19
+ */
20
+ keys: string | string[];
21
+ /**
22
+ * Which keyboard to name the modifiers for.
23
+ * @default 'auto'
24
+ */
25
+ os?: ShortcutOS;
26
+ /**
27
+ * What goes between two keys. Omit it for the platform's own convention: a `+`
28
+ * on Windows and Linux, and nothing at all on macOS, where a shortcut is
29
+ * written as a run of symbols — `⇧⌘P`, never `⇧+⌘+P`.
30
+ */
31
+ separator?: React.ReactNode;
32
+ /**
33
+ * Drop shadow depth. `0` (the default) is flat. A key cap is the one place a
34
+ * raised surface is tempting and wrong: this is a picture of a key, not a key.
35
+ * @default 0
36
+ */
37
+ elevation?: NebaElevation;
38
+ }
39
+ /**
40
+ * A keyboard key, or a combination of them.
41
+ *
42
+ * Two things make this more than a styled `<kbd>`, and both are about the label
43
+ * rather than the box around it.
44
+ *
45
+ * The first is `Mod`. A shortcut written as `Ctrl+K` is wrong for every Mac
46
+ * reader and one written as `⌘K` is wrong for everybody else, so the token that
47
+ * means "the modifier shortcuts are built on" resolves per platform — and `os`
48
+ * is there for the pages that have to name a platform rather than the reader's.
49
+ *
50
+ * The second is that `⌘` is not a word. A screen reader reads it as "place of
51
+ * interest sign", so every key drawn as a glyph carries its name beside it, in
52
+ * the clipped box `srOnlyClasses` describes. What is announced is "Command K",
53
+ * which is what the shortcut is called.
54
+ *
55
+ * The keys are real `<kbd>` elements; the wrapper around them is a `<span>`.
56
+ * Nesting `<kbd>` inside `<kbd>` is allowed and would also be defensible, but a
57
+ * `kbd` wrapper is a second box for a host stylesheet to reach into for no gain
58
+ * — the semantics are carried by the keys themselves either way.
59
+ */
60
+ export declare const Shortcut: React.ForwardRefExoticComponent<ShortcutProps & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as n,Fragment as e,jsxs as a}from"react/jsx-runtime";import*as o from"react";import{controlHeightClasses as t,controlSlots as r,controlTextClasses as l,paddingXClasses as s,radiusClasses as m,srOnlyClasses as i,surfaceClasses as c,transitionClasses as d}from"../../internal/styles";const w=n=>({symbol:n,name:n}),u={mod:{mac:{symbol:"⌘",name:"Command"},windows:w("Ctrl"),linux:w("Ctrl")},meta:{mac:{symbol:"⌘",name:"Command"},windows:w("Win"),linux:w("Super")},ctrl:{mac:{symbol:"⌃",name:"Control"},windows:w("Ctrl"),linux:w("Ctrl")},alt:{mac:{symbol:"⌥",name:"Option"},windows:w("Alt"),linux:w("Alt")},shift:{mac:{symbol:"⇧",name:"Shift"},windows:w("Shift"),linux:w("Shift")},enter:{mac:{symbol:"↩",name:"Enter"},windows:w("Enter"),linux:w("Enter")},tab:{mac:{symbol:"⇥",name:"Tab"},windows:w("Tab"),linux:w("Tab")},escape:{mac:{symbol:"⎋",name:"Escape"},windows:w("Esc"),linux:w("Esc")},backspace:{mac:{symbol:"⌫",name:"Backspace"},windows:w("Backspace"),linux:w("Backspace")},delete:{mac:{symbol:"⌦",name:"Delete"},windows:w("Del"),linux:w("Del")},capslock:{mac:{symbol:"⇪",name:"Caps Lock"},windows:w("Caps Lock"),linux:w("Caps Lock")}},p={cmdorctrl:"mod",commandorcontrol:"mod",cmd:"meta",command:"meta",super:"meta",win:"meta",windows:"meta",control:"ctrl",option:"alt",opt:"alt",return:"enter",esc:"escape",del:"delete",caps:"capslock"},b={up:{symbol:"↑",name:"Arrow up"},down:{symbol:"↓",name:"Arrow down"},left:{symbol:"←",name:"Arrow left"},right:{symbol:"→",name:"Arrow right"},arrowup:{symbol:"↑",name:"Arrow up"},arrowdown:{symbol:"↓",name:"Arrow down"},arrowleft:{symbol:"←",name:"Arrow left"},arrowright:{symbol:"→",name:"Arrow right"}};function f(){if("undefined"==typeof navigator)return"windows";const n=navigator.userAgentData,e=`${n?.platform??""} ${navigator.platform??""} ${navigator.userAgent??""}`;return/mac|iphone|ipad|ipod/i.test(e)?"mac":/win/i.test(e)?"windows":"linux"}function y(){return()=>{}}function x(){return"windows"}const g={xs:"xs",sm:"xs",md:"sm",lg:"md",xl:"lg"},h={solid:[c,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[c,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft)"},v={xs:"min-w-5.5",sm:"min-w-6.5",md:"min-w-8",lg:"min-w-10",xl:"min-w-12"};export const Shortcut=o.forwardRef(function({variant:c="outline",size:A="md",color:k="secondary",density:C="compact",elevation:j=0,keys:E,os:S="auto",separator:B,className:N,style:D,...L},T){const $=o.useSyncExternalStore(y,f,x),F="auto"===S?$:S,z=g[A],O=function(n){return Array.isArray(n)?n.map(n=>n.trim()).filter(Boolean):n.split("+").map(n=>n.trim()).filter(Boolean)}(E),R=O.map(n=>function(n,e){const a=n.toLowerCase().replace(/[\s_-]/g,""),o=p[a]??a,t=b[o];if(t)return t;const r=u[o];return r?r[e]:w(1===n.length?n.toUpperCase():n)}(n,F)),U=void 0===B?"mac"===F?null:"+":B,W=["inline-flex shrink-0 items-center justify-center","font-mono font-medium leading-none whitespace-nowrap tabular-nums",t[z],l[z],v[z],s[C][z],m[z],h[c],d].join(" ");return n("span",{ref:T,className:["inline-flex max-w-full items-center gap-1 align-middle",N??""].filter(Boolean).join(" "),style:{...r(k,j,c),...D},...L,children:R.map((t,r)=>a(o.Fragment,{children:[r>0&&null!==U?n("span",{"aria-hidden":"true",className:"text-(--neba-muted-fg)",children:U}):null,n("kbd",{className:W,children:t.symbol===t.name?t.symbol:a(e,{children:[n("span",{"aria-hidden":"true",children:t.symbol}),n("span",{className:i,children:t.name})]})})]},r))})});
@@ -0,0 +1,2 @@
1
+ export { Shortcut } from './Shortcut';
2
+ export type { ShortcutOS, ShortcutProps } from './Shortcut';
@@ -0,0 +1 @@
1
+ export{Shortcut}from"./Shortcut";
@@ -0,0 +1,91 @@
1
+ import * as React from 'react';
2
+ import { type BoxProps } from '../box/Box';
3
+ import type { NebaAlign } from '../../types';
4
+ export interface StatisticProps extends Omit<BoxProps, 'title' | 'prefix'> {
5
+ /**
6
+ * What the number is. The name of the measure, not a sentence about it —
7
+ * "Active users", "MRR", "이탈률".
8
+ *
9
+ * `label` rather than `title`, which is what Card calls the same slot: this is
10
+ * the name of a *value*, which is the thing the library already spells `label`
11
+ * on every field it has.
12
+ */
13
+ label?: React.ReactNode;
14
+ /**
15
+ * The figure. A number is formatted; a string is printed exactly as given, for
16
+ * the values that are not numbers at all — "3h 42m", "A+", "—".
17
+ */
18
+ value: number | string;
19
+ /**
20
+ * How to write a numeric `value` — `Intl.NumberFormat` options, the same prop
21
+ * the progress indicators take. Without it a number is grouped by the reader's
22
+ * own locale and otherwise left alone.
23
+ */
24
+ format?: Intl.NumberFormatOptions;
25
+ /** Set before the figure and never wrapped away from it — a currency sign. */
26
+ prefix?: React.ReactNode;
27
+ /**
28
+ * Set after the figure: `%`, `MB`, `명`.
29
+ *
30
+ * A second slot rather than one `adornment` with a side, because the two are
31
+ * typographically different things and always have been — a currency symbol
32
+ * leads its number and a unit follows it, in every locale that has both.
33
+ */
34
+ unit?: React.ReactNode;
35
+ /** A glyph before the label. An `Icon`, or anything else that draws. */
36
+ icon?: React.ReactNode;
37
+ /**
38
+ * The figure this one is being compared against — last month's, last quarter's,
39
+ * the target. Passing it is what makes the delta appear.
40
+ *
41
+ * Only meaningful for a numeric `value`; with a string there is nothing to
42
+ * subtract and the delta is left out.
43
+ */
44
+ previousValue?: number;
45
+ /**
46
+ * How the difference is written.
47
+ *
48
+ * - `percent` — the change relative to `previousValue`. The default, because a
49
+ * report is nearly always asking "how much has this moved", not "by how many".
50
+ * - `absolute` — the difference itself, in the figure's own units.
51
+ * - `both` — the percentage with the difference after it.
52
+ * - `none` — no delta, even with a `previousValue` given.
53
+ * @default 'percent'
54
+ */
55
+ delta?: 'percent' | 'absolute' | 'both' | 'none';
56
+ /**
57
+ * Which direction counts as good, and so which way the delta is coloured.
58
+ *
59
+ * `up` for revenue, `down` for churn and error rate and page weight. This is
60
+ * not decoration: green-for-larger on a bounce rate says the opposite of what
61
+ * the report means, and it says it to exactly the reader who is skimming.
62
+ * @default 'up'
63
+ */
64
+ betterWhen?: 'up' | 'down';
65
+ /** A line under the figure — "vs. last month", "as of 3 July". */
66
+ caption?: React.ReactNode;
67
+ /**
68
+ * Where the block sits in the card. `center` for a row of tiles that read as
69
+ * one band; `start` — the default — for a card with anything else in it.
70
+ * @default 'start'
71
+ */
72
+ align?: NebaAlign;
73
+ /** Anything below the caption: a sparkline, a ProgressLinear against a target. */
74
+ children?: React.ReactNode;
75
+ }
76
+ /**
77
+ * A number with its name on it, and — when there is something to compare it
78
+ * against — how far it has moved.
79
+ *
80
+ * A Box with a fixed arrangement laid on it, exactly as Card is. The slots are
81
+ * props and not compound sub-components for the reason Card gives: the order
82
+ * never varies, so what a caller wants to decide is what goes in each slot.
83
+ *
84
+ * The delta is a Chip rather than a coloured span, and that is the whole reason
85
+ * it looks right next to everything else — it is the same token the rest of the
86
+ * library uses, at the same step down the control ladder, with the same acrylic
87
+ * on it. It also carries a shape and not only a colour: a report whose "down" is
88
+ * red and nothing else is a report that says nothing to a reader who cannot
89
+ * separate red from green.
90
+ */
91
+ export declare const Statistic: React.ForwardRefExoticComponent<StatisticProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Box as n}from"../box/Box";import{Chip as a}from"../chip/Chip";import{MinusIcon as r,TrendDownIcon as s,TrendUpIcon as m}from"../../internal/icons";import{hasContent as i,metaTextClasses as o,sheetSectionGapClasses as c}from"../../internal/styles";const u={xs:"text-[1.125rem]/[1.375rem]",sm:"text-[1.375rem]/[1.625rem]",md:"text-[1.75rem]/[2rem]",lg:"text-[2.25rem]/[2.5rem]",xl:"text-[2.875rem]/[3.25rem]"},d={xs:"text-[0.75rem]",sm:"text-[0.875rem]",md:"text-[1rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},x={xs:"gap-y-0.5",sm:"gap-y-0.5",md:"gap-y-1",lg:"gap-y-1",xl:"gap-y-1.5"},f={start:"items-start text-start",center:"items-center text-center",end:"items-end text-end"},p={up:e(m,{}),down:e(s,{}),flat:e(r,{})};export const Statistic=l.forwardRef(function({size:r="md",color:s="primary",density:m="default",label:b,value:h,format:g,prefix:w,unit:N,icon:y,previousValue:v,delta:$="percent",betterWhen:j="up",caption:M,align:z="start",className:B,children:k,...F},I){const C=l.useMemo(()=>new Intl.NumberFormat(void 0,g),[g]),R="number"==typeof h?h:null,S=null===R?h:C.format(R),V=null!==R&&void 0!==v?R-v:null,W=null!==V&&0!==v&&void 0!==v?V/Math.abs(v):null,q=null===V?null:V>0?"up":V<0?"down":"flat";let A=null;if(null!==V&&null!==q&&"none"!==$){const e=V>0?"+":V<0?"-":"",t=`${e}${C.format(Math.abs(V))}`,l=null===W?null:`${e}${(100*Math.abs(W)).toFixed(1).replace(/\.0$/,"")}%`;A="absolute"===$?t:"both"===$?[l,t].filter(Boolean).join(" · "):l??t}const D=null===q||"flat"===q?"secondary":q===j?"success":"danger",E=null!==A||i(M);return t(n,{ref:I,size:r,color:s,density:m,className:["flex flex-col",c[r],f[z],B??""].filter(Boolean).join(" "),...F,children:[i(b)||i(y)?t("div",{className:["flex min-w-0 items-center gap-1.5 font-medium text-(--neba-muted-fg)",o[r]].join(" "),children:[i(y)?e("span",{className:"flex shrink-0 items-center",children:y}):null,i(b)?e("span",{className:"min-w-0 truncate",children:b}):null]}):null,t("div",{className:["flex min-w-0 flex-wrap items-baseline gap-1 font-semibold text-(--neba-fg) tabular-nums",u[r]].join(" "),children:[i(w)?e("span",{className:`font-medium text-(--neba-muted-fg) ${d[r]}`,children:w}):null,e("span",{className:"min-w-0 break-words",children:S}),i(N)?e("span",{className:`font-medium text-(--neba-muted-fg) ${d[r]}`,children:N}):null]}),E?t("div",{className:`flex min-w-0 flex-wrap items-center gap-x-2 ${x[r]}`,children:[null!==A&&null!==q?e(a,{size:r,variant:"text",color:D,startIcon:p[q],className:"tabular-nums",children:A}):null,i(M)?e("span",{className:`min-w-0 text-(--neba-muted-fg) ${o[r]}`,children:M}):null]}):null,k]})});
@@ -0,0 +1,2 @@
1
+ export { Statistic } from './Statistic';
2
+ export type { StatisticProps } from './Statistic';
@@ -0,0 +1 @@
1
+ export{Statistic}from"./Statistic";
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a,Fragment as r}from"react/jsx-runtime";import*as n from"react";import{Switch as l}from"@base-ui/react/switch";import{Field as o}from"@base-ui/react/field";import{controlTextClasses as t,metaTextClasses as i,surfaceClasses as c}from"../../internal/styles";const s={xs:"h-3.5 w-6",sm:"h-4 w-7",md:"h-5 w-9",lg:"h-6 w-11",xl:"h-7 w-13"},d={xs:"data-[checked]:left-[calc(100%-0.75rem)]",sm:"data-[checked]:left-[calc(100%-0.875rem)]",md:"data-[checked]:left-[calc(100%-1.125rem)]",lg:"data-[checked]:left-[calc(100%-1.375rem)]",xl:"data-[checked]:left-[calc(100%-1.625rem)]"},b=["relative inline-flex shrink-0 border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","rounded-full","[transition-property:background-color,border-color,box-shadow]","[transition-duration:var(--neba-duration-fill),var(--neba-duration),var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),h=[c,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)]","hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","data-[checked]:bg-(--n-fill) data-[checked]:[border-color:transparent]","data-[checked]:[box-shadow:var(--neba-plate-solid)]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),f=[c,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[box-shadow:var(--neba-plate-glass)] [filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:[border-color:transparent]"].join(" "),m=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)] shadow-none","data-[checked]:bg-(--neba-disabled-bg)"].join(" "),v=["absolute inset-y-0.5 left-0.5 aspect-square rounded-full bg-(--neba-surface)","[box-shadow:var(--neba-shadow-1)]","[transition:left_var(--neba-duration)_var(--neba-ease)]"].join(" ");export const Switch=n.forwardRef(function({size:n="md",color:c="primary",label:u,description:p,error:g,invalid:x,labelPlacement:w="end",disabled:k=!1,readOnly:j=!1,className:$,style:N,...y},_){const R=null!=g&&!1!==g&&""!==g,B=x??R,O=B?"danger":c,S={"--n-fill":`var(--neba-${O}-fill)`,"--n-fill-hover":`var(--neba-${O}-fill-hover)`,"--n-accent":`var(--neba-${O}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${O}-line)`,"--n-line-hover":`var(--neba-${O}-line-hover)`,"--n-ring":`var(--neba-${O}-ring)`},q=e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:_,className:[b,s[n],k?m:j?f:h].join(" "),disabled:k,readOnly:j,...y,children:e(l.Thumb,{className:`${v} ${d[n]}`})})}),z=u||p?a("span",{className:["flex min-w-0 flex-col gap-0.5","start"===w?"flex-1":""].filter(Boolean).join(" "),children:[u?e(o.Label,{className:["leading-[1.4]",k?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:u}):null,p?e(o.Description,{className:`${i[n]} text-(--neba-muted-fg)`,children:p}):null]}):null;return a(o.Root,{disabled:k,invalid:B,className:["inline-flex flex-col gap-1 align-top",$??""].filter(Boolean).join(" "),style:{...S,...N},children:[e("div",{className:`flex items-start gap-2.5 ${t[n]}`,children:a(r,"start"===w?{children:[z,q]}:{children:[q,z]})}),R?e(o.Error,{match:!0,className:`${i[n]} text-(--n-accent)`,children:g}):null]})});
1
+ import{jsx as e,jsxs as a,Fragment as r}from"react/jsx-runtime";import*as n from"react";import{Switch as l}from"@base-ui/react/switch";import{Field as o}from"@base-ui/react/field";import{controlTextClasses as t,metaTextClasses as i,surfaceClasses as c,tickRowLeadingClasses as s}from"../../internal/styles";const d={xs:"h-3.5 w-6",sm:"h-4 w-7",md:"h-5 w-9",lg:"h-6 w-11",xl:"h-7 w-13"},b={xs:"data-[checked]:left-[calc(100%-0.75rem)]",sm:"data-[checked]:left-[calc(100%-0.875rem)]",md:"data-[checked]:left-[calc(100%-1.125rem)]",lg:"data-[checked]:left-[calc(100%-1.375rem)]",xl:"data-[checked]:left-[calc(100%-1.625rem)]"},h=["relative inline-flex shrink-0 border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","rounded-full","[transition-property:background-color,border-color,box-shadow]","[transition-duration:var(--neba-duration-fill),var(--neba-duration),var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" "),f=[c,"cursor-pointer bg-(--n-panel) [border-color:var(--n-line)]","hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)]","data-[checked]:bg-(--n-fill) data-[checked]:[border-color:transparent]","data-[checked]:hover:bg-(--n-fill-hover)"].join(" "),m=[c,"cursor-default bg-(--n-panel) [border-color:var(--n-line)]","[filter:saturate(0.55)]","data-[checked]:bg-(--n-fill) data-[checked]:[border-color:transparent]"].join(" "),u=["cursor-not-allowed bg-transparent [border-color:var(--neba-disabled-border)] shadow-none","data-[checked]:bg-(--neba-disabled-bg)"].join(" "),v=["absolute inset-y-0.5 left-0.5 aspect-square rounded-full bg-(--neba-surface)","[box-shadow:var(--neba-shadow-1)]","[transition:left_var(--neba-duration)_var(--neba-ease)]"].join(" ");export const Switch=n.forwardRef(function({size:n="md",color:c="primary",label:p,description:g,error:x,invalid:w,labelPlacement:k="end",disabled:j=!1,readOnly:$=!1,className:N,style:y,..._},R){const B=null!=x&&!1!==x&&""!==x,O=w??B,S=O?"danger":c,q={"--n-fill":`var(--neba-${S}-fill)`,"--n-fill-hover":`var(--neba-${S}-fill-hover)`,"--n-accent":`var(--neba-${S}-accent)`,"--n-panel":"var(--neba-panel)","--n-panel-hover":"var(--neba-panel-hover)","--n-line":`var(--neba-${S}-line)`,"--n-line-hover":`var(--neba-${S}-line-hover)`,"--n-ring":`var(--neba-${S}-ring)`},z=e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:R,className:[h,d[n],j?u:$?m:f].join(" "),disabled:j,readOnly:$,..._,children:e(l.Thumb,{className:`${v} ${b[n]}`})})}),D=p||g?a("span",{className:["flex min-w-0 flex-col gap-0.5","start"===k?"flex-1":""].filter(Boolean).join(" "),children:[p?e(o.Label,{className:["leading-[1.4]",j?"text-(--neba-disabled-fg)":"cursor-pointer text-(--neba-fg)"].join(" "),children:p}):null,g?e(o.Description,{className:`${i[n]} text-(--neba-muted-fg)`,children:g}):null]}):null;return a(o.Root,{disabled:j,invalid:O,className:["inline-flex flex-col gap-1 align-top",N??""].filter(Boolean).join(" "),style:{...q,...y},children:[e("div",{className:`flex items-start gap-2.5 ${t[n]} ${s}`,children:a(r,"start"===k?{children:[D,z]}:{children:[z,D]})}),B?e(o.Error,{match:!0,className:`${i[n]} text-(--n-accent)`,children:x}):null]})});
@@ -0,0 +1,76 @@
1
+ import * as React from 'react';
2
+ import { type PickerLabels, type TimeUnit } from '../../internal/calendar';
3
+ import { type PickerShellProps } from '../../internal/picker';
4
+ /**
5
+ * Which column of the clock a row belongs to. Re-exported so a caller writing a
6
+ * `shouldDisableTime` rule can name the argument it is handed.
7
+ */
8
+ export type { TimeUnit };
9
+ export interface TimePickerProps extends PickerShellProps {
10
+ /** The chosen time. A `Date`, so it carries a day as well — see `referenceDate`. */
11
+ value?: Date | null;
12
+ defaultValue?: Date | null;
13
+ onValueChange?: (value: Date | null) => void;
14
+ open?: boolean;
15
+ defaultOpen?: boolean;
16
+ onOpenChange?: (open: boolean) => void;
17
+ /**
18
+ * The day a chosen time is written onto while there is no value yet.
19
+ * @default today
20
+ */
21
+ referenceDate?: Date;
22
+ /** The earliest time of day that may be chosen. Only the clock is read. */
23
+ minTime?: Date | null;
24
+ /** The latest time of day that may be chosen. */
25
+ maxTime?: Date | null;
26
+ /**
27
+ * Blocks individual rows. Called once per row per column with the instant that
28
+ * row would produce and the column it is in, so a rule may be as coarse as
29
+ * "no afternoons" or as fine as one minute.
30
+ */
31
+ shouldDisableTime?: (value: Date, unit: TimeUnit) => boolean;
32
+ /** A 12-hour dial with an AM/PM column. Defaults to whatever the locale does. */
33
+ hour12?: boolean;
34
+ /** Adds the seconds column. @default false */
35
+ showSeconds?: boolean;
36
+ /** How far apart the rows of each column are. @default 1 */
37
+ hourStep?: number;
38
+ minuteStep?: number;
39
+ secondStep?: number;
40
+ locale?: string;
41
+ /**
42
+ * How the trigger writes the chosen time. Passed straight to `Intl`.
43
+ * @default { hour: 'numeric', minute: '2-digit' }, plus seconds when shown
44
+ */
45
+ format?: Intl.DateTimeFormatOptions;
46
+ placeholder?: React.ReactNode;
47
+ clearable?: boolean;
48
+ /** Offers the shortcut to the current time in the footer. @default true */
49
+ showNowButton?: boolean;
50
+ /**
51
+ * Closes the popup as soon as any column is touched. `false` by default and
52
+ * unlike DatePicker, because a time is two answers and closing after the first
53
+ * one would make choosing 9:30 a matter of opening the popup twice.
54
+ * @default false
55
+ */
56
+ closeOnSelect?: boolean;
57
+ labels?: Partial<PickerLabels>;
58
+ /** Identifies the field when a form is submitted, as `HH:MM` (`HH:MM:SS`). */
59
+ name?: string;
60
+ }
61
+ /**
62
+ * A time of day, chosen from columns.
63
+ *
64
+ * The bounds are checked at the granularity of the column being drawn, which is
65
+ * the detail that separates a working time picker from a frustrating one. With a
66
+ * `minTime` of 09:30, the hour `9` stays available — the hour *contains* allowed
67
+ * minutes — and it is the minute column that greys out `00` through `25`. The
68
+ * naive check compares the whole candidate instant and hides the 9 entirely,
69
+ * which makes half past nine unreachable.
70
+ *
71
+ * The value is a `Date` rather than a string or a number of minutes, because
72
+ * everything else in this library that carries a moment is one, and because a
73
+ * time on its own has nowhere to record that it crossed a DST boundary.
74
+ * `referenceDate` is the day a bare time is written onto.
75
+ */
76
+ export declare const TimePicker: React.ForwardRefExoticComponent<TimePickerProps & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{Button as t}from"../button/Button";import{TimeGrid as l,usePickerLabels as a}from"../../internal/calendar";import{ClockIcon as i}from"../../internal/icons";import{PickerFooter as r,PickerShell as s}from"../../internal/picker";import{displaySamples as c,formatDate as d,isHour12 as u,isValidDate as m,secondsOfDay as p,timeUnitSpan as h,toISOTime as f,withPlaceholder as S,withTime as b}from"../../internal/date";import{cx as g}from"../../internal/styles";export const TimePicker=o.forwardRef(function({value:y,defaultValue:v,onValueChange:x,open:C,defaultOpen:w,onOpenChange:z,referenceDate:k,minTime:D,maxTime:O,shouldDisableTime:T,hour12:j,showSeconds:V=!1,hourStep:B=1,minuteStep:I=1,secondStep:M=1,locale:N,format:R,placeholder:F,clearable:H=!1,showNowButton:P=!0,closeOnSelect:q=!1,labels:A,name:E,size:G="md",color:J="primary",density:K="default",readOnly:L=!1,disabled:Q=!1,startIcon:U,...W},X){const Y=a(A),Z=j??u(N),[$,_]=o.useState(v??null),ee=void 0!==y?y:$,[ne,oe]=o.useState(w??!1),te=C??ne,[le]=o.useState(()=>k??new Date),ae=e=>{e&&(L||Q)||(void 0===C&&oe(e),z?.(e))},ie=e=>{void 0===y&&_(e),x?.(e)},re=o.useCallback((e,n)=>{const[o,t]=h(n,e);return!!(m(D)&&t<p(D))||(!!(m(O)&&o>p(O))||(T?.(e,n)??!1))},[D,O,T]),se=R??{hour:"numeric",minute:"2-digit",...V?{second:"2-digit"}:{}},ce=new Date,de=b(k??le,{hours:ce.getHours(),minutes:ce.getMinutes(),seconds:V?ce.getSeconds():0}),ue=P||H||!q,me=o.useMemo(()=>S(c(N,se),F),[N,se,F]);return e(s,{...W,size:G,color:J,density:K,readOnly:L,disabled:Q,triggerRef:X,startIcon:U??e(i,{}),display:m(ee)?d(ee,N,se):F??"",samples:me,empty:!m(ee),clearable:H,onClear:()=>ie(null),open:te,onOpenChange:ae,labels:Y,hiddenValues:E?[{name:E,value:m(ee)?f(ee,V):""}]:void 0,children:n("div",{className:g("flex flex-col",ue&&"gap-1.5"),children:[e(l,{size:G,density:K,locale:N,value:m(ee)?ee:null,referenceDate:k??le,onChange:e=>{ie(e),q&&ae(!1)},hour12:Z,showSeconds:V,hourStep:B,minuteStep:I,secondStep:M,shouldDisableTime:re,labels:Y,autoFocus:!0}),ue?n(r,{size:G,children:[H?e(t,{variant:"text",size:G,color:J,density:"compact",onClick:()=>{ie(null),ae(!1)},children:Y.clear}):null,P?e(t,{variant:"text",size:G,color:J,density:"compact",disabled:re(de,"second"),onClick:()=>{ie(de),ae(!1)},children:Y.now}):null,q?null:e(t,{variant:"solid",size:G,color:J,density:"compact",onClick:()=>ae(!1),children:Y.done})]}):null]})})});
@@ -0,0 +1,2 @@
1
+ export { TimePicker } from './TimePicker';
2
+ export type { TimePickerProps, TimeUnit } from './TimePicker';
@@ -0,0 +1 @@
1
+ export{TimePicker}from"./TimePicker";
@@ -0,0 +1,98 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaColor, NebaDensity, NebaOrientation, NebaSize } from '../../types';
4
+ /**
5
+ * How far along one item is.
6
+ *
7
+ * Three states rather than two, because "the one you are on" is not the same
8
+ * claim as "done" and a sequence that cannot say which step is current is a
9
+ * list. Each gets its own axis — a filled bullet, a filled bullet with a halo
10
+ * around it, an empty one — rather than three shades of the same thing.
11
+ */
12
+ export type TimelineStatus = 'complete' | 'current' | 'upcoming';
13
+ /** How the line between two items is drawn. `none` leaves the gap open. */
14
+ export type TimelineConnector = 'solid' | 'dashed' | 'dotted' | 'none';
15
+ export interface TimelineProps extends Omit<React.ComponentPropsWithoutRef<'ol'>, 'color'> {
16
+ /**
17
+ * How far the sequence has got: the index of the item being worked on now.
18
+ * Everything before it is complete, everything after it is still to come.
19
+ *
20
+ * An index rather than a value, because a timeline has no selection — nothing
21
+ * here is chosen, and the only question is how far down the list reality has
22
+ * reached. Omit it and every item is `upcoming` unless it says otherwise; pass
23
+ * the item count to mark the whole sequence done.
24
+ */
25
+ active?: number;
26
+ /** @default 'md' */
27
+ size?: NebaSize;
28
+ /** @default 'primary' */
29
+ color?: NebaColor;
30
+ /** Spacing between items. Never the type scale, never the bullet. */
31
+ density?: NebaDensity;
32
+ /**
33
+ * Which way the sequence runs. `vertical` is the default and the one that
34
+ * takes an arbitrary number of steps with an arbitrary amount to say about
35
+ * each; `horizontal` is the stepper across the top of a checkout, and it is
36
+ * only honest while every label is short.
37
+ * @default 'vertical'
38
+ */
39
+ orientation?: NebaOrientation;
40
+ /** Renders something other than an `<ol>` — Base UI's own escape hatch. */
41
+ render?: useRender.RenderProp;
42
+ children?: React.ReactNode;
43
+ }
44
+ export interface TimelineItemProps extends Omit<React.ComponentPropsWithoutRef<'li'>, 'color' | 'title'> {
45
+ /** The heading of this step. */
46
+ title?: React.ReactNode;
47
+ /**
48
+ * When it happened — a date, a duration, a name. Set beside the title on a
49
+ * wide item and under it on a narrow one.
50
+ */
51
+ meta?: React.ReactNode;
52
+ /**
53
+ * What goes inside the bullet: a number, an icon, an avatar. Omit it and the
54
+ * bullet is a plain disc, which is what a step with nothing to say about
55
+ * itself should be.
56
+ */
57
+ bullet?: React.ReactNode;
58
+ /**
59
+ * Overrides what the timeline's `active` would have computed for this item —
60
+ * a step that failed and stopped the sequence, a step that was skipped.
61
+ */
62
+ status?: TimelineStatus;
63
+ /** Overrides the timeline's colour family for this item alone. */
64
+ color?: NebaColor;
65
+ /**
66
+ * How the line to the next item is drawn.
67
+ * @default 'solid'
68
+ */
69
+ connector?: TimelineConnector;
70
+ /** The body of the step. */
71
+ children?: React.ReactNode;
72
+ }
73
+ /**
74
+ * One step.
75
+ *
76
+ * Its index is not a prop and cannot be: an item that had to be told where it
77
+ * was in the list would be an item every caller could put in the wrong place,
78
+ * and `active={2}` would stop meaning anything. The Timeline numbers its
79
+ * children as it walks them, and hands each one its index through a context.
80
+ */
81
+ export declare const TimelineItem: React.ForwardRefExoticComponent<TimelineItemProps & React.RefAttributes<HTMLLIElement>>;
82
+ /**
83
+ * A sequence of steps, in the order they happen in.
84
+ *
85
+ * There is no Base UI primitive under this and there should not be: a timeline
86
+ * has no selection, no roving focus and no keyboard contract — it is a list, and
87
+ * reaching for a composite primitive to draw one would hand every consumer's
88
+ * record of events the semantics of a widget.
89
+ *
90
+ * It is an `<ol>` for the reason it exists at all: the order *is* the content. A
91
+ * screen reader announcing "list of 5 items" over an unordered list would be
92
+ * describing something else.
93
+ *
94
+ * The children are numbered here rather than by a prop on each item, so `active`
95
+ * has something to count against and inserting a step in the middle does not
96
+ * mean renumbering the ones after it.
97
+ */
98
+ export declare const Timeline: React.ForwardRefExoticComponent<TimelineProps & React.RefAttributes<HTMLOListElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as r from"react";import{useRender as t}from"@base-ui/react/use-render";import{cx as n,hasContent as a,iconClasses as o,metaTextClasses as s,sheetBodyClasses as i,sheetTitleClasses as d,surfaceClasses as c,surfaceSlots as m,transitionClasses as p}from"../../internal/styles";const u=r.createContext(null),b=r.createContext({index:0,last:!1}),x={xs:"0.875rem",sm:"1rem",md:"1.25rem",lg:"1.5rem",xl:"1.875rem"},f={xs:"gap-2",sm:"gap-2.5",md:"gap-3",lg:"gap-3.5",xl:"gap-4"},v={default:{xs:"pb-5",sm:"pb-6",md:"pb-7",lg:"pb-8",xl:"pb-10"},compact:{xs:"pb-3",sm:"pb-3.5",md:"pb-4",lg:"pb-5",xl:"pb-6"}},g={default:{xs:"pe-5",sm:"pe-6",md:"pe-7",lg:"pe-8",xl:"pe-10"},compact:{xs:"pe-3",sm:"pe-3.5",md:"pe-4",lg:"pe-5",xl:"pe-6"}},h={solid:"border-solid",dashed:"border-dashed",dotted:"border-dotted",none:""},y={complete:`${c} bg-(--n-fill) text-(--n-on-solid) [box-shadow:var(--neba-plate-solid)]`,current:`${c} bg-(--n-fill) text-(--n-on-solid) [box-shadow:0_0_0_0.25rem_var(--n-soft),var(--neba-plate-solid)]`,upcoming:`${c} border-2 bg-(--n-panel) text-(--neba-muted-fg) [border-color:var(--n-line)]`},N={complete:"[border-color:var(--n-line-hover)]",current:"[border-color:var(--neba-border)]",upcoming:"[border-color:var(--neba-border)]"},w={complete:"text-(--neba-fg)",current:"text-(--n-accent)",upcoming:"text-(--neba-muted-fg)"};export const TimelineItem=r.forwardRef(function({title:t,meta:c,bullet:_,status:z,color:C,connector:$="solid",className:j,children:P,...R},T){const k=r.useContext(u),{index:A,last:I}=r.useContext(b),M=k?.size??"md",q=k?.density??"default",B=k?.orientation??"vertical",D=C??k?.color??"primary",E=k?.active??null,F=z??(null===E?"upcoming":A<E?"complete":A===E?"current":"upcoming"),G="horizontal"===B,H="none"!==$&&!I,J=e("span",{"aria-hidden":"true",className:n("relative z-10 flex shrink-0 items-center justify-center rounded-full","size-(--n-bullet) text-[calc(var(--n-bullet)*0.5)] leading-none font-semibold tabular-nums",y[F],p,o),children:_}),K=H?e("span",{"aria-hidden":"true",className:n("pointer-events-none absolute",G?"top-[calc(var(--n-bullet)/2_-_1px)] start-(--n-bullet) end-0 border-t-2":"start-[calc(var(--n-bullet)/2_-_1px)] top-(--n-bullet) bottom-0 border-s-2",h[$],N[F],p)}):null,L=l("div",{className:n("flex min-w-0 flex-col gap-0.5",G?"mt-2":""),children:[a(t)||a(c)?l("div",{className:"flex flex-wrap items-baseline gap-x-2",children:[a(t)?e("span",{className:n("font-semibold",d[M],w[F],p),children:t}):null,a(c)?e("span",{className:n("text-(--neba-muted-fg)",s[M]),children:c}):null]}):null,a(P)?e("div",{className:n("text-(--neba-muted-fg)",i[M]),children:P}):null]});return l("li",{ref:T,"aria-current":"current"===F?"step":void 0,"data-status":F,className:n("relative",G?n("flex min-w-0 flex-1 flex-col",I?"":g[q][M]):n("flex",f[M],I?"":v[q][M]),j),style:{"--n-bullet":x[M],...m(D,0),"--n-fill":`var(--neba-${D}-fill)`,"--n-on-solid":`var(--neba-${D}-on-solid)`},...R,children:[K,J,L]})});export const Timeline=r.forwardRef(function({active:l,size:a="md",color:o="primary",density:s="default",orientation:i="vertical",render:d,className:c,style:p,children:x,...f},v){const g=r.Children.toArray(x),h=g.length,y=r.useMemo(()=>({size:a,density:s,orientation:i,color:o,active:l??null}),[a,s,i,o,l]),N=t({render:d??e("ol",{}),ref:v,props:{role:"list",className:n("flex","horizontal"===i?"flex-row":"flex-col",c),style:{...m(o,0),...p},children:g.map((l,r)=>e(b.Provider,{value:{index:r,last:r===h-1},children:l},r)),...f}});return e(u.Provider,{value:y,children:N})});
@@ -0,0 +1,2 @@
1
+ export { Timeline, TimelineItem } from './Timeline';
2
+ export type { TimelineConnector, TimelineItemProps, TimelineProps, TimelineStatus } from './Timeline';
@@ -0,0 +1 @@
1
+ export{Timeline,TimelineItem}from"./Timeline";