neba 1.1.0 → 1.3.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 (123) hide show
  1. package/README.md +12 -7
  2. package/dist/components/alert/Alert.d.ts +7 -1
  3. package/dist/components/alert/Alert.js +1 -1
  4. package/dist/components/animate-appear/AnimateAppear.d.ts +55 -0
  5. package/dist/components/animate-appear/AnimateAppear.js +1 -0
  6. package/dist/components/animate-appear/index.d.ts +2 -0
  7. package/dist/components/animate-appear/index.js +1 -0
  8. package/dist/components/animate-blink/AnimateBlink.d.ts +31 -0
  9. package/dist/components/animate-blink/AnimateBlink.js +1 -0
  10. package/dist/components/animate-blink/index.d.ts +2 -0
  11. package/dist/components/animate-blink/index.js +1 -0
  12. package/dist/components/animate-fade/AnimateFade.d.ts +31 -0
  13. package/dist/components/animate-fade/AnimateFade.js +1 -0
  14. package/dist/components/animate-fade/index.d.ts +2 -0
  15. package/dist/components/animate-fade/index.js +1 -0
  16. package/dist/components/animate-grow/AnimateGrow.d.ts +41 -0
  17. package/dist/components/animate-grow/AnimateGrow.js +1 -0
  18. package/dist/components/animate-grow/index.d.ts +2 -0
  19. package/dist/components/animate-grow/index.js +1 -0
  20. package/dist/components/animate-headline/AnimateHeadline.d.ts +55 -0
  21. package/dist/components/animate-headline/AnimateHeadline.js +1 -0
  22. package/dist/components/animate-headline/index.d.ts +2 -0
  23. package/dist/components/animate-headline/index.js +1 -0
  24. package/dist/components/animate-lighting/AnimateLighting.d.ts +62 -0
  25. package/dist/components/animate-lighting/AnimateLighting.js +1 -0
  26. package/dist/components/animate-lighting/index.d.ts +2 -0
  27. package/dist/components/animate-lighting/index.js +1 -0
  28. package/dist/components/animate-marquee/AnimateMarquee.d.ts +65 -0
  29. package/dist/components/animate-marquee/AnimateMarquee.js +1 -0
  30. package/dist/components/animate-marquee/index.d.ts +2 -0
  31. package/dist/components/animate-marquee/index.js +1 -0
  32. package/dist/components/animate-rotate/AnimateRotate.d.ts +48 -0
  33. package/dist/components/animate-rotate/AnimateRotate.js +1 -0
  34. package/dist/components/animate-rotate/index.d.ts +2 -0
  35. package/dist/components/animate-rotate/index.js +1 -0
  36. package/dist/components/animate-slide/AnimateSlide.d.ts +46 -0
  37. package/dist/components/animate-slide/AnimateSlide.js +1 -0
  38. package/dist/components/animate-slide/index.d.ts +2 -0
  39. package/dist/components/animate-slide/index.js +1 -0
  40. package/dist/components/animate-typing/AnimateTyping.d.ts +58 -0
  41. package/dist/components/animate-typing/AnimateTyping.js +1 -0
  42. package/dist/components/animate-typing/index.d.ts +2 -0
  43. package/dist/components/animate-typing/index.js +1 -0
  44. package/dist/components/animate-zoom/AnimateZoom.d.ts +37 -0
  45. package/dist/components/animate-zoom/AnimateZoom.js +1 -0
  46. package/dist/components/animate-zoom/index.d.ts +2 -0
  47. package/dist/components/animate-zoom/index.js +1 -0
  48. package/dist/components/aspect-ratio/AspectRatio.d.ts +63 -0
  49. package/dist/components/aspect-ratio/AspectRatio.js +1 -0
  50. package/dist/components/aspect-ratio/index.d.ts +2 -0
  51. package/dist/components/aspect-ratio/index.js +1 -0
  52. package/dist/components/avatar/Avatar.d.ts +106 -0
  53. package/dist/components/avatar/Avatar.js +1 -0
  54. package/dist/components/avatar/index.d.ts +2 -0
  55. package/dist/components/avatar/index.js +1 -0
  56. package/dist/components/blockquote/Blockquote.d.ts +7 -1
  57. package/dist/components/blockquote/Blockquote.js +1 -1
  58. package/dist/components/box/Box.d.ts +7 -1
  59. package/dist/components/box/Box.js +1 -1
  60. package/dist/components/breadcrumb/Breadcrumb.d.ts +92 -0
  61. package/dist/components/breadcrumb/Breadcrumb.js +1 -0
  62. package/dist/components/breadcrumb/index.d.ts +2 -0
  63. package/dist/components/breadcrumb/index.js +1 -0
  64. package/dist/components/chat-bubble/ChatBubble.d.ts +114 -0
  65. package/dist/components/chat-bubble/ChatBubble.js +1 -0
  66. package/dist/components/chat-bubble/index.d.ts +2 -0
  67. package/dist/components/chat-bubble/index.js +1 -0
  68. package/dist/components/chip/Chip.d.ts +7 -1
  69. package/dist/components/chip/Chip.js +1 -1
  70. package/dist/components/color-picker/ColorPicker.d.ts +102 -0
  71. package/dist/components/color-picker/ColorPicker.js +1 -0
  72. package/dist/components/color-picker/index.d.ts +2 -0
  73. package/dist/components/color-picker/index.js +1 -0
  74. package/dist/components/drawer/Drawer.d.ts +145 -0
  75. package/dist/components/drawer/Drawer.js +1 -0
  76. package/dist/components/drawer/index.d.ts +2 -0
  77. package/dist/components/drawer/index.js +1 -0
  78. package/dist/components/icon/Icon.d.ts +8 -1
  79. package/dist/components/icon/Icon.js +1 -1
  80. package/dist/components/otp-field/OtpField.d.ts +85 -0
  81. package/dist/components/otp-field/OtpField.js +1 -0
  82. package/dist/components/otp-field/index.d.ts +2 -0
  83. package/dist/components/otp-field/index.js +1 -0
  84. package/dist/components/panes/Panes.d.ts +78 -0
  85. package/dist/components/panes/Panes.js +1 -0
  86. package/dist/components/panes/index.d.ts +2 -0
  87. package/dist/components/panes/index.js +1 -0
  88. package/dist/components/popover/Popover.d.ts +109 -0
  89. package/dist/components/popover/Popover.js +1 -0
  90. package/dist/components/popover/index.d.ts +2 -0
  91. package/dist/components/popover/index.js +1 -0
  92. package/dist/components/skeleton/Skeleton.d.ts +76 -0
  93. package/dist/components/skeleton/Skeleton.js +1 -0
  94. package/dist/components/skeleton/index.d.ts +2 -0
  95. package/dist/components/skeleton/index.js +1 -0
  96. package/dist/components/spoiler/Spoiler.d.ts +95 -0
  97. package/dist/components/spoiler/Spoiler.js +1 -0
  98. package/dist/components/spoiler/index.d.ts +2 -0
  99. package/dist/components/spoiler/index.js +1 -0
  100. package/dist/components/text-link/TextLink.d.ts +82 -0
  101. package/dist/components/text-link/TextLink.js +1 -0
  102. package/dist/components/text-link/index.d.ts +2 -0
  103. package/dist/components/text-link/index.js +1 -0
  104. package/dist/components/tree-view/TreeView.d.ts +115 -0
  105. package/dist/components/tree-view/TreeView.js +1 -0
  106. package/dist/components/tree-view/index.d.ts +2 -0
  107. package/dist/components/tree-view/index.js +1 -0
  108. package/dist/components/typography/Typography.d.ts +7 -1
  109. package/dist/components/typography/Typography.js +1 -1
  110. package/dist/index.d.ts +24 -0
  111. package/dist/index.js +1 -1
  112. package/dist/internal/animate.d.ts +175 -0
  113. package/dist/internal/animate.js +1 -0
  114. package/dist/internal/color.d.ts +108 -0
  115. package/dist/internal/color.js +1 -0
  116. package/dist/internal/i18n.d.ts +103 -0
  117. package/dist/internal/i18n.js +1 -0
  118. package/dist/internal/icons.d.ts +23 -0
  119. package/dist/internal/icons.js +1 -1
  120. package/dist/styles.css +1 -1
  121. package/dist/tailwind.css +504 -0
  122. package/dist/types.d.ts +112 -0
  123. package/package.json +14 -14
@@ -0,0 +1,46 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaAnimateMode, NebaAnimateProps, NebaSide } from '../../types';
4
+ export interface AnimateSlideProps extends NebaAnimateProps, React.ComponentPropsWithoutRef<'div'> {
5
+ /**
6
+ * Whether the content slides in or slides away. `out` leaves by the same edge
7
+ * it would have come from.
8
+ * @default 'in'
9
+ */
10
+ mode?: NebaAnimateMode;
11
+ /**
12
+ * Which edge it travels from. Physical, as `NebaSide` is everywhere — a panel
13
+ * sliding down from the top comes from the top in every writing direction.
14
+ * @default 'bottom'
15
+ */
16
+ from?: NebaSide;
17
+ /**
18
+ * How far it travels — a CSS length, or a number in pixels. `'100%'` is the
19
+ * element's own width or height, which is what makes it appear from behind
20
+ * its own edge.
21
+ * @default '100%'
22
+ */
23
+ distance?: number | string;
24
+ /**
25
+ * Fades in as it slides.
26
+ * @default true
27
+ */
28
+ fade?: boolean;
29
+ /** Renders something other than a `<div>`. Base UI's own escape hatch. */
30
+ render?: useRender.RenderProp;
31
+ children?: React.ReactNode;
32
+ }
33
+ /**
34
+ * Content travelling in from one edge.
35
+ *
36
+ * The default distance is the element's own size, so it starts exactly out of
37
+ * frame and arrives without ever having been half drawn somewhere it does not
38
+ * belong. Put it in a box with `overflow: hidden` and the effect is a panel
39
+ * appearing from behind that box's edge.
40
+ *
41
+ * A slide moves the element, so what is *around* it does not move: this is a
42
+ * `translate`, not a change of layout, and nothing on the page reflows while it
43
+ * runs. For a much shorter travel over a list of things, one after another, use
44
+ * AnimateAppear.
45
+ */
46
+ export declare const AnimateSlide: React.ForwardRefExoticComponent<AnimateSlideProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,slideOffsets as a,useAnimateElement as n}from"../../internal/animate";import{cx as o}from"../../internal/styles";export const AnimateSlide=e.forwardRef(function({duration:e=380,delay:i=0,easing:s,repeat:l=1,alternate:d,paused:m,trigger:p="mount",play:c,once:f=!0,threshold:y=.2,mode:u="in",from:g="bottom",distance:h="100%",fade:x=!0,render:N,className:b,style:w,children:A,...R},S){const{x:j,y:k}=a(g,h),q=n({effect:"slide",duration:e,delay:i,easing:s,repeat:l,alternate:d,mode:u,x:j,y:k,opacity:x?0:1,trigger:p,play:c,once:f,threshold:y,paused:m,infinite:t(l)});return r({render:N,ref:[S,q.ref],props:{...R,className:o(q.className,b),style:{...q.style,...w},...q.props,children:A}})});
@@ -0,0 +1,2 @@
1
+ export { AnimateSlide } from './AnimateSlide';
2
+ export type { AnimateSlideProps } from './AnimateSlide';
@@ -0,0 +1 @@
1
+ export{AnimateSlide}from"./AnimateSlide";
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+ import type { NebaAnimateProps } from '../../types';
3
+ export interface AnimateTypingProps extends Omit<NebaAnimateProps, 'alternate' | 'easing'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {
4
+ /**
5
+ * The text, when it is easier to pass than to nest. Overrides `children`.
6
+ */
7
+ text?: string;
8
+ /**
9
+ * How fast it is typed, in characters per second.
10
+ * @default 24
11
+ */
12
+ speed?: number;
13
+ /**
14
+ * How long the finished text is held before it repeats, in milliseconds.
15
+ * @default 1400
16
+ */
17
+ hold?: number;
18
+ /**
19
+ * Deletes the text again before repeating, rather than clearing it in one
20
+ * frame. Only means anything when `repeat` is more than once.
21
+ * @default false
22
+ */
23
+ erase?: boolean;
24
+ /**
25
+ * How fast it is deleted, in characters per second. Deleting is usually about
26
+ * twice as fast as typing, which is what a person actually does.
27
+ * @default twice `speed`
28
+ */
29
+ eraseSpeed?: number;
30
+ /**
31
+ * The block after the text.
32
+ * @default true
33
+ */
34
+ caret?: boolean;
35
+ /** What the caret is drawn as. @default '|' */
36
+ caretChar?: React.ReactNode;
37
+ /** The text to type. Only text is typed — see below. */
38
+ children?: React.ReactNode;
39
+ }
40
+ /**
41
+ * Text appearing one character at a time.
42
+ *
43
+ * The whole string is in the document from the first frame — in a clipped box
44
+ * for a screen reader, which reads it once and is not made to sit through the
45
+ * performance — and what animates is a visible copy that is `aria-hidden`. So
46
+ * the effect costs a reader who cannot see it nothing, and costs a reader who
47
+ * can nothing either: the box is not laid out from the characters that have
48
+ * arrived, so the text around it does not reflow on every frame.
49
+ *
50
+ * `repeat`, `hold` and `erase` are what make it a loop: type, hold, delete,
51
+ * type again. Without `erase` a repeat clears in one frame, which is right for
52
+ * a line that is being replaced rather than rewritten.
53
+ *
54
+ * Only text is typed. Pass a string, or strings; an element among the children
55
+ * contributes its text and nothing about its markup, because there is no honest
56
+ * way to reveal half of a link.
57
+ */
58
+ export declare const AnimateTyping: React.ForwardRefExoticComponent<AnimateTypingProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{isInfinite as n,useAnimationRun as a,usePrefersReducedMotion as i}from"../../internal/animate";import{cx as s,srOnlyClasses as o}from"../../internal/styles";function u(e){return"string"==typeof e||"number"==typeof e?String(e):Array.isArray(e)?e.map(u).join(""):""}export const AnimateTyping=r.forwardRef(function({text:c,speed:m=24,hold:f=1400,erase:l=!1,eraseSpeed:d,caret:p=!0,caretChar:h="|",duration:g,delay:y=0,repeat:x=1,paused:T,trigger:j="mount",play:v,once:N=!0,threshold:S=.2,className:w,style:M,children:b,...A},I){const E=a({trigger:j,play:v,once:N,threshold:S,paused:T,infinite:n(x)}),R=i(),C=c??u(b),k=r.useMemo(()=>function(e,t){if("undefined"!=typeof Intl&&"Segmenter"in Intl)return[...new Intl.Segmenter(t,{granularity:"grapheme"}).segment(e)].map(e=>e.segment);return[...e]}(C),[C]),q=k.length,[z,B]=r.useState(0),D=r.useRef(0),F=g&&q>0?g/q:1e3/Math.max(m,1),G=1e3/Math.max(d??2*m,1);return r.useEffect(()=>{D.current=0},[q]),r.useEffect(()=>{if(R||0===q)return void B(q);if(!E.started)return D.current=0,void B(0);if(T)return;let e,t=!1,r=D.current,n=1,a=!1;const i="infinite"===x?1/0:Math.max(1,x);if(r>=q&&1===i)return;const s=()=>{if(!t){if(a)return r-=1,D.current=r,B(r),r<=0&&(a=!1,n+=1),void(e=setTimeout(s,a?G:F));if(r+=1,D.current=r,B(r),r<q)e=setTimeout(s,F);else if(!(n>=i)){if(l)return a=!0,void(e=setTimeout(s,f));n+=1,e=setTimeout(()=>{t||(r=0,D.current=0,B(0),e=setTimeout(s,F))},f)}}};return B(r),e=setTimeout(s,0===r?y:F),()=>{t=!0,clearTimeout(e)}},[E.started,T,R,q,F,G,y,f,l,x]),t("div",{ref:e=>{E.ref(e),"function"==typeof I?I(e):I&&(I.current=e)},className:w,style:M,"data-neba-animation":"typing","data-state":E.state,...E.handlers,...A,children:[e("span",{className:o,children:C}),t("span",{"aria-hidden":"true",className:"whitespace-pre-wrap",children:[k.slice(0,z).join(""),p?e("span",{className:s("neba-typing-caret"),children:h}):null]})]})});
@@ -0,0 +1,2 @@
1
+ export { AnimateTyping } from './AnimateTyping';
2
+ export type { AnimateTypingProps } from './AnimateTyping';
@@ -0,0 +1 @@
1
+ export{AnimateTyping}from"./AnimateTyping";
@@ -0,0 +1,37 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaAnimateMode, NebaAnimateProps } from '../../types';
4
+ export interface AnimateZoomProps extends NebaAnimateProps, React.ComponentPropsWithoutRef<'div'> {
5
+ /**
6
+ * Whether the content comes forward or falls away.
7
+ * @default 'in'
8
+ */
9
+ mode?: NebaAnimateMode;
10
+ /**
11
+ * The scale it starts from, as a multiple of its final size. Above `1` it
12
+ * arrives oversized and settles back, which reads as coming *towards* the
13
+ * reader rather than up out of the page.
14
+ * @default 0.4
15
+ */
16
+ from?: number;
17
+ /**
18
+ * Fades in as it zooms.
19
+ * @default true
20
+ */
21
+ fade?: boolean;
22
+ /** Renders something other than a `<div>`. Base UI's own escape hatch. */
23
+ render?: useRender.RenderProp;
24
+ children?: React.ReactNode;
25
+ }
26
+ /**
27
+ * Content arriving from the middle of where it will end up.
28
+ *
29
+ * The same arithmetic as Grow at more than twice the distance, and always about
30
+ * the centre — which is the whole difference. A Grow unfolds from somewhere; a
31
+ * Zoom comes at you. Use it for the one thing on a screen that is meant to
32
+ * interrupt: a confirmation, a result, a number that just landed.
33
+ *
34
+ * There is no `origin`, on purpose. A zoom anchored to a corner is a grow, and
35
+ * the library does not offer two spellings of one idea.
36
+ */
37
+ export declare const AnimateZoom: React.ForwardRefExoticComponent<AnimateZoomProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as a}from"../../internal/animate";import{cx as n}from"../../internal/styles";export const AnimateZoom=e.forwardRef(function({duration:e=340,delay:o=0,easing:s,repeat:i=1,alternate:l,paused:m,trigger:d="mount",play:c,once:p=!0,threshold:f=.2,mode:u="in",from:y=.4,fade:g=!0,render:h,className:N,style:b,children:w,...x},z){const A=a({effect:"zoom",duration:e,delay:o,easing:s,repeat:i,alternate:l,mode:u,scale:y,opacity:g?0:1,trigger:d,play:c,once:p,threshold:f,paused:m,infinite:t(i)});return r({render:h,ref:[z,A.ref],props:{...x,className:n(A.className,N),style:{transformOrigin:"center",...A.style,...b},...A.props,children:w}})});
@@ -0,0 +1,2 @@
1
+ export { AnimateZoom } from './AnimateZoom';
2
+ export type { AnimateZoomProps } from './AnimateZoom';
@@ -0,0 +1 @@
1
+ export{AnimateZoom}from"./AnimateZoom";
@@ -0,0 +1,63 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaSize } from '../../types';
4
+ /**
5
+ * How the media inside is fitted to the box, spelled the way CSS spells it.
6
+ *
7
+ * These are `object-fit`'s own values rather than a nicer set of words, for the
8
+ * same reason `NebaPosition` keeps `static`/`sticky`/`fixed`: inventing
9
+ * `fill-the-box` would only make a reader look up which CSS it maps to.
10
+ */
11
+ export type NebaAspectFit = 'cover' | 'contain' | 'fill' | 'none';
12
+ export interface AspectRatioProps extends React.ComponentPropsWithoutRef<'div'> {
13
+ /**
14
+ * The proportion the box holds, written the way CSS writes it — a number
15
+ * (`1.5`) or a ratio (`'16 / 9'`). Both reach `aspect-ratio` untouched.
16
+ * @default 1
17
+ */
18
+ ratio?: number | string;
19
+ /**
20
+ * How a single piece of media inside is fitted. Applies to an `img`, a
21
+ * `video`, a `canvas`, an `svg` or an `iframe` that is a direct child; those
22
+ * are stretched to the full box and then fitted. Anything else is laid out
23
+ * normally and this prop does not reach it.
24
+ * @default 'cover'
25
+ */
26
+ fit?: NebaAspectFit;
27
+ /**
28
+ * Rounds the corners to the `size` step of the house radius ladder.
29
+ *
30
+ * Off by default. A layout component draws nothing, and a photograph with its
31
+ * corners cut is a decision about the photograph — but it is such a common one
32
+ * that making the caller reach for a `className` would be perverse.
33
+ * @default false
34
+ */
35
+ rounded?: boolean;
36
+ /**
37
+ * Which step of the radius ladder `rounded` uses. As on Box, `size` here is
38
+ * the size of the *sheet* — there is no height and no type scale on a box
39
+ * whose whole job is a proportion.
40
+ * @default 'md'
41
+ */
42
+ size?: NebaSize;
43
+ /**
44
+ * Renders something other than a `<div>`: `render={<figure />}`,
45
+ * `render={<a href="…" />}`. Base UI's own escape hatch.
46
+ */
47
+ render?: useRender.RenderProp;
48
+ children?: React.ReactNode;
49
+ }
50
+ /**
51
+ * A box that keeps a proportion whatever width it is given.
52
+ *
53
+ * It draws nothing — no surface, no border, no shadow — which is what puts it in
54
+ * `layout` beside Container and Grid rather than in `surfaces`. What it does is
55
+ * reserve the space: a card whose image arrives late does not reflow the page
56
+ * around it, and a row of thumbnails is a row of one shape.
57
+ *
58
+ * The proportion is CSS's own `aspect-ratio`, so a caller who already knows
59
+ * `16 / 9` has nothing to translate. `fit` is the one convenience on top: the
60
+ * media inside is stretched to the box and then fitted, which is the pair of
61
+ * declarations every use of this component would otherwise start with.
62
+ */
63
+ export declare const AspectRatio: React.ForwardRefExoticComponent<AspectRatioProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import*as e from"react";import{useRender as i}from"@base-ui/react/use-render";import{radiusClasses as o}from"../../internal/styles";const t=["[&>img]:size-full","[&>video]:size-full","[&>canvas]:size-full","[&>svg]:size-full","[&>iframe]:size-full","[&>picture]:size-full","[&>picture>img]:size-full"].join(" "),c={cover:"[&>img]:object-cover [&>video]:object-cover [&>picture>img]:object-cover",contain:"[&>img]:object-contain [&>video]:object-contain [&>picture>img]:object-contain",fill:"[&>img]:object-fill [&>video]:object-fill [&>picture>img]:object-fill",none:"[&>img]:object-none [&>video]:object-none [&>picture>img]:object-none"};export const AspectRatio=e.forwardRef(function({ratio:e=1,fit:r="cover",rounded:l=!1,size:n="md",render:s,className:a,style:f,children:m,...u},d){const b=["relative block w-full overflow-hidden",t,c[r],l?o[n]:"",a??""].filter(Boolean).join(" ");return i({render:s,ref:d,props:{className:b,style:{aspectRatio:e,...f},children:m,...u}})});
@@ -0,0 +1,2 @@
1
+ export { AspectRatio } from './AspectRatio';
2
+ export type { AspectRatioProps, NebaAspectFit } from './AspectRatio';
@@ -0,0 +1 @@
1
+ export{AspectRatio}from"./AspectRatio";
@@ -0,0 +1,106 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaElevation, NebaSize, NebaTransition, NebaVariant } from '../../types';
3
+ /** What Base UI reports about the picture as it loads. */
4
+ export type AvatarLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';
5
+ /**
6
+ * The crop, not the sheet.
7
+ *
8
+ * `circle` is the default, and it is the one place besides Badge where the
9
+ * library draws something without a flat run along its edge. The reasoning is
10
+ * Badge's: the cut acrylic edge is what says "this is a surface", and an avatar
11
+ * is not a surface — it is a portrait laid on one. A round crop is what a
12
+ * portrait has been for as long as there have been portraits.
13
+ *
14
+ * `square` cuts the corners off instead, which is what a logo or a repository
15
+ * icon wants: those are drawn to the edges of a rectangle and a round crop eats
16
+ * them.
17
+ */
18
+ export type AvatarShape = 'circle' | 'square';
19
+ export interface AvatarProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
20
+ /**
21
+ * The picture. Until it loads — and forever, if it fails — the fallback is
22
+ * what is drawn, so an avatar is never an empty box.
23
+ */
24
+ src?: string;
25
+ /** Candidate images at other resolutions, as on any `<img>`. */
26
+ srcSet?: string;
27
+ /**
28
+ * What the picture says, for a reader who cannot see it. Defaults to `name`,
29
+ * and to nothing at all when there is no name — an avatar next to the person's
30
+ * own name in the row is decoration, and reading it out says the name twice.
31
+ */
32
+ alt?: string;
33
+ /**
34
+ * Who or what this is. One prop doing three jobs: it names the picture, the
35
+ * initials are derived from it, and it is the sentence a screen reader hears
36
+ * instead of those initials.
37
+ *
38
+ * The initials are the first character of the first word plus the first
39
+ * character of the last — "Jane Doe" is `JD`, "홍길동" is `홍`. That rule is
40
+ * wrong for some names, which is what `initials` is for.
41
+ */
42
+ name?: string;
43
+ /** The initials, written out, for when the rule derived the wrong ones. */
44
+ initials?: string;
45
+ /**
46
+ * The crop.
47
+ * @default 'circle'
48
+ */
49
+ shape?: AvatarShape;
50
+ /**
51
+ * Weight of the surface behind the fallback. Invisible once a picture has
52
+ * loaded, apart from the edge it keeps.
53
+ * @default 'text'
54
+ */
55
+ variant?: NebaVariant;
56
+ /**
57
+ * The box the picture is drawn in — the control heights, so an avatar and the
58
+ * button beside it in a toolbar are the same height.
59
+ * @default 'md'
60
+ */
61
+ size?: NebaSize;
62
+ /** @default 'primary' */
63
+ color?: NebaColor;
64
+ /**
65
+ * Drop shadow depth. `0` (the default) is flat.
66
+ * @default 0
67
+ */
68
+ elevation?: NebaElevation;
69
+ /**
70
+ * An entrance animation, run once on mount: `transition="fade"`, or an object
71
+ * for the details. For a trigger, a replay or anything under your own
72
+ * control, wrap it in an `Animate*` component instead.
73
+ */
74
+ transition?: NebaTransition;
75
+ /**
76
+ * How long to wait before drawing the fallback, in milliseconds. Set it to
77
+ * roughly the time a cached image takes and the initials stop flashing up in
78
+ * front of a picture that was about to arrive anyway.
79
+ */
80
+ delay?: number;
81
+ /** Anything else the `<img>` needs — `loading`, `crossOrigin`, `referrerPolicy`. */
82
+ imageProps?: Omit<React.ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'alt'>;
83
+ /** Called as the picture moves between `idle`, `loading`, `loaded` and `error`. */
84
+ onLoadingStatusChange?: (status: AvatarLoadingStatus) => void;
85
+ /**
86
+ * The fallback, drawn instead of the initials. An icon, a logo, a single
87
+ * emoji — whatever stands in for this particular thing when there is no
88
+ * picture of it.
89
+ */
90
+ children?: React.ReactNode;
91
+ }
92
+ /**
93
+ * A picture of a person or a thing, at a known size, that is never an empty box.
94
+ *
95
+ * Three things can be drawn in it and exactly one of them is at a time: the
96
+ * picture, if `src` is given and loads; otherwise whatever stands in for it —
97
+ * `children`, or `initials`, or the initials derived from `name`; and failing
98
+ * all of those, a silhouette. Which one is showing is Base UI's `Avatar` to
99
+ * decide, because "has the image loaded" is a question with four answers and a
100
+ * race in the middle of it.
101
+ *
102
+ * It carries no status dot of its own. An avatar with a green mark on it is a
103
+ * [Badge](./badge) with an avatar in it, and inventing a second spelling for
104
+ * that would give the library two of them.
105
+ */
106
+ export declare const Avatar: React.ForwardRefExoticComponent<AvatarProps & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{Avatar as n}from"@base-ui/react/avatar";import{transitionProps as a}from"../../internal/animate";import{controlHeightClasses as o,controlSlots as l,controlSquareClasses as s,hasContent as i,srOnlyClasses as d,surfaceClasses as c,transitionClasses as m}from"../../internal/styles";const f={xs:"text-[0.5625rem]",sm:"text-[0.6875rem]",md:"text-[0.8125rem]",lg:"text-[1rem]",xl:"text-[1.1875rem]"},u={xs:"rounded-[0.375rem]",sm:"rounded-[0.4375rem]",md:"rounded-[0.5625rem]",lg:"rounded-[0.6875rem]",xl:"rounded-[0.875rem]"},x={solid:[c,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev)]"].join(" "),outline:[c,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft-press) [box-shadow:var(--n-elev)]"},h="after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit]",v={solid:`${h} after:[box-shadow:var(--neba-plate-solid)]`,outline:`${h} after:[box-shadow:var(--neba-plate-glass)]`,text:""},p=["relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden","align-middle font-semibold tracking-wide whitespace-nowrap leading-none","[&_svg]:pointer-events-none [&_svg]:size-[55%]",m].join(" ");function g(){return t("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",children:[e("path",{d:"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z"}),e("path",{d:"M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z"})]})}export const Avatar=r.forwardRef(function({src:r,srcSet:c,alt:m,name:h,initials:b,shape:w="circle",variant:y="text",size:j="md",color:N="primary",elevation:z=0,delay:C,imageProps:A,onLoadingStatusChange:B,transition:S,className:k,style:L,children:F,...M},R){const Z=h?function(e){const t=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===t.length?"":((Array.from(t[0])[0]??"")+(t.length>1?Array.from(t[t.length-1])[0]??"":"")).toLocaleUpperCase()}(h):"",$=a(S),_=m??h,I=i(F)?F:(b??Z)||e(g,{}),P=i(F)||Boolean(b??Z),U=[p,o[j],s[j],f[j],"circle"===w?"rounded-full":u[j],x[y],v[y],$.className,k??""].filter(Boolean).join(" ");return t(n.Root,{ref:R,className:U,style:{...l(N,z,y),...$.style,...L},...M,children:[r?e(n.Image,{src:r,srcSet:c,alt:_??"",className:"size-full object-cover",onLoadingStatusChange:B,...A}):null,t(n.Fallback,{delay:r?C:void 0,className:"flex size-full items-center justify-center",children:[_&&P?e("span",{className:d,children:_}):null,e("span",{"aria-hidden":!(!_||!P)||void 0,className:"contents",children:I})]})]})});
@@ -0,0 +1,2 @@
1
+ export { Avatar } from './Avatar';
2
+ export type { AvatarLoadingStatus, AvatarProps, AvatarShape } from './Avatar';
@@ -0,0 +1 @@
1
+ export{Avatar}from"./Avatar";
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { NebaElevation, NebaStyleProps } from '../../types';
2
+ import type { NebaElevation, NebaStyleProps, NebaTransition } from '../../types';
3
3
  /**
4
4
  * The props are a `<figure>`'s rather than a `<blockquote>`'s, which is a
5
5
  * consequence of where the drawing happens: everything a caller passes lands on
@@ -14,6 +14,12 @@ export interface BlockquoteProps extends NebaStyleProps, Omit<React.ComponentPro
14
14
  * @default 0
15
15
  */
16
16
  elevation?: NebaElevation;
17
+ /**
18
+ * An entrance animation, run once on mount: `transition="fade"`, or an object
19
+ * for the details. For a trigger, a replay or anything under your own
20
+ * control, wrap it in an `Animate*` component instead.
21
+ */
22
+ transition?: NebaTransition;
17
23
  /**
18
24
  * Who said it. Its presence is what turns the quote into a `<figure>` with a
19
25
  * `<figcaption>`, which is the markup the HTML spec asks for: an attribution
@@ -1 +1 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{boxPaddingClasses as n}from"../box/Box";import{hasContent as l,metaTextClasses as a,radiusClasses as o,surfaceClasses as i,surfaceSlots as s,transitionClasses as c}from"../../internal/styles";const m={xs:"text-[0.75rem]/[1.25rem]",sm:"text-[0.8125rem]/[1.375rem]",md:"text-[0.9375rem]/[1.625rem]",lg:"text-[1.0625rem]/[1.875rem]",xl:"text-[1.25rem]/[2.125rem]"},d="border-s-2 [border-inline-start-color:var(--n-accent)]",x={solid:[i,"bg-(--n-panel-hover)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[i,"border border-s-2 bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"bg-transparent"};function f(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"M6.4 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6ZM13.3 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6Z",fill:"currentColor"})})}export const Blockquote=t.forwardRef(function({variant:t="text",size:i="md",color:u="primary",density:b="default",elevation:p=0,author:h,source:v,cite:g,icon:N,className:j,style:y,children:w,...B},k){const z=l(h)||l(v),q=void 0===N?e(f,{}):N,M=["flex flex-col text-(--neba-fg)",d,"text"===t?"":`${o[i]} rounded-s-none`,x[t],n[b][i],c,j??""].filter(Boolean).join(" "),Z=r("blockquote",{cite:g,className:m[i],children:[l(q)?e("span",{"aria-hidden":"true",className:"mb-1 block size-[2em] text-(--n-soft-press) [&>svg]:size-full",children:q}):null,w]}),C={...s(u,p),...y};return z?r("figure",{ref:k,className:M,style:C,...B,children:[Z,r("figcaption",{className:["mt-2 flex flex-wrap items-baseline gap-x-1.5 text-(--neba-muted-fg)",a[i]].join(" "),children:[l(h)?r("span",{className:"font-medium text-(--neba-fg)",children:[e("span",{"aria-hidden":"true",children:"— "}),h]}):null,l(v)?e("cite",{className:"not-italic",children:v}):null]})]}):e("div",{ref:k,className:M,style:C,...B,children:Z})});
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{boxPaddingClasses as n}from"../box/Box";import{transitionProps as a}from"../../internal/animate";import{hasContent as l,metaTextClasses as o,radiusClasses as i,surfaceClasses as s,surfaceSlots as c,transitionClasses as m}from"../../internal/styles";const d={xs:"text-[0.75rem]/[1.25rem]",sm:"text-[0.8125rem]/[1.375rem]",md:"text-[0.9375rem]/[1.625rem]",lg:"text-[1.0625rem]/[1.875rem]",xl:"text-[1.25rem]/[2.125rem]"},x="border-s-2 [border-inline-start-color:var(--n-accent)]",f={solid:[s,"bg-(--n-panel-hover)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[s,"border border-s-2 bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"bg-transparent"};function u(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"M6.4 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6ZM13.3 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6Z",fill:"currentColor"})})}export const Blockquote=t.forwardRef(function({variant:t="text",size:s="md",color:b="primary",density:p="default",elevation:h=0,author:v,source:g,cite:N,icon:j,transition:y,className:w,style:B,children:k,...z},q){const M=a(y),Z=l(v)||l(g),C=void 0===j?e(u,{}):j,R=["flex flex-col text-(--neba-fg)",x,"text"===t?"":`${i[s]} rounded-s-none`,f[t],n[p][s],m,M.className,w??""].filter(Boolean).join(" "),$=r("blockquote",{cite:N,className:d[s],children:[l(C)?e("span",{"aria-hidden":"true",className:"mb-1 block size-[2em] text-(--n-soft-press) [&>svg]:size-full",children:C}):null,k]}),A={...c(b,h),...M.style,...B};return Z?r("figure",{ref:q,className:R,style:A,...z,children:[$,r("figcaption",{className:["mt-2 flex flex-wrap items-baseline gap-x-1.5 text-(--neba-muted-fg)",o[s]].join(" "),children:[l(v)?r("span",{className:"font-medium text-(--neba-fg)",children:[e("span",{"aria-hidden":"true",children:"— "}),v]}):null,l(g)?e("cite",{className:"not-italic",children:g}):null]})]}):e("div",{ref:q,className:R,style:A,...z,children:$})});
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { useRender } from '@base-ui/react/use-render';
3
- import type { NebaDensity, NebaElevation, NebaSize, NebaStyleProps } from '../../types';
3
+ import type { NebaDensity, NebaElevation, NebaSize, NebaStyleProps, NebaTransition } from '../../types';
4
4
  export interface BoxProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
5
5
  /**
6
6
  * Drop shadow depth. `0` (the default) is flat — the acrylic edge is what
@@ -15,6 +15,12 @@ export interface BoxProps extends NebaStyleProps, Omit<React.ComponentPropsWitho
15
15
  * @default true
16
16
  */
17
17
  padded?: boolean;
18
+ /**
19
+ * An entrance animation, run once on mount: `transition="fade"`, or an object
20
+ * for the details. For a trigger, a replay or anything under your own
21
+ * control, wrap the Box in an `Animate*` component instead.
22
+ */
23
+ transition?: NebaTransition;
18
24
  /**
19
25
  * Renders something other than a `<div>`: `render={<section />}`,
20
26
  * `render={<li />}`, or a function for full control. Base UI's own escape
@@ -1 +1 @@
1
- import*as e from"react";import{useRender as s}from"@base-ui/react/use-render";import{radiusClasses as o,surfaceClasses as a,surfaceSlots as p,transitionClasses as t}from"../../internal/styles";const l=o;export const boxPaddingClasses={default:{xs:"p-2",sm:"p-3",md:"p-4",lg:"p-5",xl:"p-6"},compact:{xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-4"}};export const boxPaddingXClasses={default:{xs:"px-2",sm:"px-3",md:"px-4",lg:"px-5",xl:"px-6"},compact:{xs:"px-1.5",sm:"px-2",md:"px-2.5",lg:"px-3",xl:"px-4"}};export const boxPaddingYClasses={default:{xs:"py-2",sm:"py-3",md:"py-4",lg:"py-5",xl:"py-6"},compact:{xs:"py-1.5",sm:"py-2",md:"py-2.5",lg:"py-3",xl:"py-4"}};const n=["block",t].join(" "),r={solid:[a,"text-(--neba-fg) bg-(--n-panel-hover)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[a,"border text-(--neba-fg) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"};export const Box=e.forwardRef(function({variant:e="outline",size:o="md",color:a="primary",density:t="default",elevation:x=0,padded:d=!0,render:i,className:m,style:c,children:b,...g},f){const y=[n,l[o],d?boxPaddingClasses[t][o]:"",r[e],m??""].filter(Boolean).join(" ");return s({render:i,ref:f,props:{className:y,style:{...p(a,x),...c},children:b,...g}})});
1
+ import*as e from"react";import{useRender as a}from"@base-ui/react/use-render";import{transitionProps as s}from"../../internal/animate";import{radiusClasses as o,surfaceClasses as t,surfaceSlots as n,transitionClasses as p}from"../../internal/styles";const l=o;export const boxPaddingClasses={default:{xs:"p-2",sm:"p-3",md:"p-4",lg:"p-5",xl:"p-6"},compact:{xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-4"}};export const boxPaddingXClasses={default:{xs:"px-2",sm:"px-3",md:"px-4",lg:"px-5",xl:"px-6"},compact:{xs:"px-1.5",sm:"px-2",md:"px-2.5",lg:"px-3",xl:"px-4"}};export const boxPaddingYClasses={default:{xs:"py-2",sm:"py-3",md:"py-4",lg:"py-5",xl:"py-6"},compact:{xs:"py-1.5",sm:"py-2",md:"py-2.5",lg:"py-3",xl:"py-4"}};const r=["block",p].join(" "),x={solid:[t,"text-(--neba-fg) bg-(--n-panel-hover)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[t,"border text-(--neba-fg) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"};export const Box=e.forwardRef(function({variant:e="outline",size:o="md",color:t="primary",density:p="default",elevation:d=0,padded:i=!0,transition:m,render:c,className:b,style:g,children:f,...y},u){const v=s(m),h=[r,l[o],i?boxPaddingClasses[p][o]:"",x[e],v.className,b??""].filter(Boolean).join(" ");return a({render:c,ref:u,props:{className:h,style:{...n(t,d),...v.style,...g},children:f,...y}})});
@@ -0,0 +1,92 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaDensity, NebaSize } from '../../types';
3
+ /**
4
+ * What is drawn between two steps of the trail.
5
+ *
6
+ * Four named marks rather than a free-for-all, because a separator is read
7
+ * hundreds of times a day and the difference between them is meaning, not
8
+ * decoration: a `chevron` and an `arrow` say "and then", a `slash` says "path",
9
+ * a `dot` says "these are peers of one thing". Anything else can still be passed
10
+ * as a node.
11
+ */
12
+ export type BreadcrumbSeparator = 'chevron' | 'arrow' | 'slash' | 'dot';
13
+ export interface BreadcrumbProps extends Omit<React.ComponentPropsWithoutRef<'nav'>, 'color'> {
14
+ /** @default 'md' */
15
+ size?: NebaSize;
16
+ /** The colour family a link picks up when it is hovered. @default 'primary' */
17
+ color?: NebaColor;
18
+ /** How tightly the steps pack. Spacing only. @default 'default' */
19
+ density?: NebaDensity;
20
+ /**
21
+ * The mark between two steps. One of the four names, or any node.
22
+ * @default 'chevron'
23
+ */
24
+ separator?: BreadcrumbSeparator | React.ReactNode;
25
+ /**
26
+ * How many steps to show before the middle is folded away behind a `…`.
27
+ * Left out, the whole trail is shown however long it gets.
28
+ */
29
+ maxItems?: number;
30
+ /** How many steps stay at the front of a folded trail. @default 1 */
31
+ itemsBeforeCollapse?: number;
32
+ /** How many stay at the end. @default 1 */
33
+ itemsAfterCollapse?: number;
34
+ /**
35
+ * Whether pressing the `…` unfolds the trail in place. Turn it off to leave
36
+ * the fold as a plain mark.
37
+ * @default true
38
+ */
39
+ expandable?: boolean;
40
+ /** The name the trail is announced by. @default 'Breadcrumb' */
41
+ label?: string;
42
+ /** What the `…` is announced as. @default 'Show hidden steps' */
43
+ expandLabel?: string;
44
+ /** The BreadcrumbItems. */
45
+ children?: React.ReactNode;
46
+ }
47
+ export interface BreadcrumbItemProps extends Omit<React.ComponentPropsWithoutRef<'li'>, 'color' | 'onClick'> {
48
+ /** Renders the step as a link. */
49
+ href?: string;
50
+ /** Fires when the step is pressed. Renders it as a button when there is no `href`. */
51
+ onClick?: React.MouseEventHandler<HTMLElement>;
52
+ /** Content before the label — a home glyph, a repository avatar. */
53
+ startIcon?: React.ReactNode;
54
+ /** Content after the label. */
55
+ endIcon?: React.ReactNode;
56
+ /**
57
+ * Marks this step as the page you are on, which stops it being a link.
58
+ *
59
+ * The last step is the current one on its own, so this is only needed for a
60
+ * trail that ends somewhere the reader is not — and setting it anywhere takes
61
+ * the mark off the last step, because only one step in a trail can be it.
62
+ */
63
+ current?: boolean;
64
+ /** Unavailable. Stops answering, keeps its place in the trail. */
65
+ disabled?: boolean;
66
+ /** The step's label. */
67
+ children?: React.ReactNode;
68
+ }
69
+ /**
70
+ * The trail of pages above the one being read.
71
+ *
72
+ * Two things make this more than a row of links. The first is that the last step
73
+ * is where the reader already is, so it is not a link at all — it carries
74
+ * `aria-current="page"` and stops being pressable, and the component works that
75
+ * out rather than asking every caller to remember it. The second is the fold: a
76
+ * trail seven levels deep is a trail nobody reads, so the middle collapses to a
77
+ * `…` that puts it back when pressed.
78
+ *
79
+ * The separators are drawn by the trail rather than by the steps. A step does
80
+ * not know whether anything follows it, and a mark that belonged to a step would
81
+ * have to be taken off the last one by hand.
82
+ */
83
+ export declare const Breadcrumb: React.ForwardRefExoticComponent<BreadcrumbProps & React.RefAttributes<HTMLElement>>;
84
+ /**
85
+ * One step of the trail.
86
+ *
87
+ * It renders three different things and the caller picks by what they pass: an
88
+ * `<a>` with an `href`, a `<button>` with an `onClick`, and a plain `<span>` with
89
+ * neither — which is what the last step is, because the page you are already on
90
+ * is not somewhere to go.
91
+ */
92
+ export declare const BreadcrumbItem: React.ForwardRefExoticComponent<BreadcrumbItemProps & React.RefAttributes<HTMLLIElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as a,Fragment as n}from"react/jsx-runtime";import*as t from"react";import{ArrowRightIcon as s,ChevronIcon as r,EllipsisIcon as l}from"../../internal/icons";import{controlTextClasses as i,cx as c,gapClasses as o,hasContent as m,iconClasses as d,radiusClasses as f,transitionClasses as u}from"../../internal/styles";const h=t.createContext({size:"md",last:!1}),p={default:{xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2.5",xl:"gap-3"},compact:{xs:"gap-0.5",sm:"gap-1",md:"gap-1",lg:"gap-1.5",xl:"gap-2"}},x={xs:f.xs,sm:f.xs,md:f.xs,lg:f.sm,xl:f.sm};const b=["chevron","arrow","slash","dot"];export const Breadcrumb=t.forwardRef(function({size:n="md",color:o="primary",density:m="default",separator:f="chevron",maxItems:x,itemsBeforeCollapse:g=1,itemsAfterCollapse:v=1,expandable:N=!0,label:y="Breadcrumb",expandLabel:w="Show hidden steps",className:k,style:C,children:B,...z},I){const[_,j]=t.useState(!1),M=t.Children.toArray(B).filter(t.isValidElement),$=M.length,A=M.some(e=>!0===e.props.current),F=!_&&void 0!==x&&$>Math.max(x,1)&&$-g-v>1?[...M.slice(0,Math.max(0,g)),null,...M.slice($-Math.max(0,v))]:M,R="string"==typeof(S=f)&&b.includes(S)?function(a){switch(a){case"chevron":return e("span",{className:"flex -rotate-90 items-center rtl:rotate-90",children:e(r,{})});case"arrow":return e("span",{className:"flex items-center rtl:rotate-180",children:e(s,{})});case"slash":return e("span",{className:"opacity-70",children:"/"});case"dot":return e("span",{className:"opacity-70",children:"·"});default:return null}}(f):f;var S;const E=c("inline-flex items-center rounded-(--neba-radius-xs) px-0.5","text-(--neba-muted-fg)",u,d,N?c("cursor-pointer hover:bg-(--n-soft) hover:text-(--n-accent)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1"):"");return e("nav",{ref:I,"aria-label":y,className:c("flex",i[n],d,k),style:{"--n-accent":`var(--neba-${o}-accent)`,"--n-soft":`var(--neba-${o}-soft)`,"--n-ring":`var(--neba-${o}-ring)`,...C},...z,children:e("ol",{role:"list",className:c("flex list-none flex-wrap items-center p-0",p[m][n]),children:F.map((s,r)=>a(t.Fragment,{children:[r>0?e("li",{"aria-hidden":"true",className:"flex shrink-0 items-center text-(--neba-muted-fg) select-none",children:R}):null,s?e(h.Provider,{value:{size:n,last:!A&&r===F.length-1},children:s}):e("li",{className:"flex shrink-0 items-center",children:N?e("button",{type:"button",className:E,"aria-label":w,onClick:()=>j(!0),children:e(l,{})}):e("span",{className:E,"aria-hidden":"true",children:e(l,{})})})]},s?s.key??r:"fold"))})})});export const BreadcrumbItem=t.forwardRef(function({href:s,onClick:r,startIcon:l,endIcon:i,current:d,disabled:f=!1,className:p,children:b,...g},v){const{size:N,last:y}=t.useContext(h),w=d??y,k=Boolean(s||r)&&!w&&!f,C=c("inline-flex min-w-0 items-center px-1",o[N],x[N],u,f?"cursor-not-allowed text-(--neba-disabled-fg)":w?"font-medium text-(--neba-fg)":k?c("cursor-pointer text-(--neba-muted-fg)","hover:bg-(--n-soft) hover:text-(--n-accent)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1"):"text-(--neba-muted-fg)"),B=a(n,{children:[m(l)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:l}):null,e("span",{className:"truncate",children:b}),m(i)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:i}):null]});return e("li",{ref:v,className:c("flex min-w-0 items-center",p),...g,children:k&&s?e("a",{href:s,className:C,onClick:r,children:B}):k?e("button",{type:"button",className:C,onClick:r,children:B}):e("span",{className:C,"aria-current":w?"page":void 0,"aria-disabled":f||void 0,children:B})})});
@@ -0,0 +1,2 @@
1
+ export { Breadcrumb, BreadcrumbItem } from './Breadcrumb';
2
+ export type { BreadcrumbItemProps, BreadcrumbProps, BreadcrumbSeparator } from './Breadcrumb';
@@ -0,0 +1 @@
1
+ export{Breadcrumb,BreadcrumbItem}from"./Breadcrumb";