neba 1.2.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 (91) hide show
  1. package/README.md +7 -5
  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 +7 -1
  53. package/dist/components/avatar/Avatar.js +1 -1
  54. package/dist/components/blockquote/Blockquote.d.ts +7 -1
  55. package/dist/components/blockquote/Blockquote.js +1 -1
  56. package/dist/components/box/Box.d.ts +7 -1
  57. package/dist/components/box/Box.js +1 -1
  58. package/dist/components/chip/Chip.d.ts +7 -1
  59. package/dist/components/chip/Chip.js +1 -1
  60. package/dist/components/color-picker/ColorPicker.d.ts +102 -0
  61. package/dist/components/color-picker/ColorPicker.js +1 -0
  62. package/dist/components/color-picker/index.d.ts +2 -0
  63. package/dist/components/color-picker/index.js +1 -0
  64. package/dist/components/drawer/Drawer.d.ts +145 -0
  65. package/dist/components/drawer/Drawer.js +1 -0
  66. package/dist/components/drawer/index.d.ts +2 -0
  67. package/dist/components/drawer/index.js +1 -0
  68. package/dist/components/icon/Icon.d.ts +8 -1
  69. package/dist/components/icon/Icon.js +1 -1
  70. package/dist/components/popover/Popover.d.ts +109 -0
  71. package/dist/components/popover/Popover.js +1 -0
  72. package/dist/components/popover/index.d.ts +2 -0
  73. package/dist/components/popover/index.js +1 -0
  74. package/dist/components/skeleton/Skeleton.d.ts +76 -0
  75. package/dist/components/skeleton/Skeleton.js +1 -0
  76. package/dist/components/skeleton/index.d.ts +2 -0
  77. package/dist/components/skeleton/index.js +1 -0
  78. package/dist/components/typography/Typography.d.ts +7 -1
  79. package/dist/components/typography/Typography.js +1 -1
  80. package/dist/index.d.ts +16 -0
  81. package/dist/index.js +1 -1
  82. package/dist/internal/animate.d.ts +175 -0
  83. package/dist/internal/animate.js +1 -0
  84. package/dist/internal/color.d.ts +108 -0
  85. package/dist/internal/color.js +1 -0
  86. package/dist/internal/i18n.d.ts +25 -0
  87. package/dist/internal/i18n.js +1 -1
  88. package/dist/styles.css +1 -1
  89. package/dist/tailwind.css +379 -0
  90. package/dist/types.d.ts +112 -0
  91. package/package.json +8 -8
@@ -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";
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { NebaColor, NebaElevation, NebaSize, NebaVariant } from '../../types';
2
+ import type { NebaColor, NebaElevation, NebaSize, NebaTransition, NebaVariant } from '../../types';
3
3
  /** What Base UI reports about the picture as it loads. */
4
4
  export type AvatarLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';
5
5
  /**
@@ -66,6 +66,12 @@ export interface AvatarProps extends Omit<React.ComponentPropsWithoutRef<'span'>
66
66
  * @default 0
67
67
  */
68
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;
69
75
  /**
70
76
  * How long to wait before drawing the fallback, in milliseconds. Set it to
71
77
  * roughly the time a cached image takes and the initials stop flashing up in
@@ -1 +1 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{Avatar as n}from"@base-ui/react/avatar";import{controlHeightClasses as a,controlSlots as o,controlSquareClasses as l,hasContent as s,srOnlyClasses as i,surfaceClasses as d,transitionClasses as c}from"../../internal/styles";const m={xs:"text-[0.5625rem]",sm:"text-[0.6875rem]",md:"text-[0.8125rem]",lg:"text-[1rem]",xl:"text-[1.1875rem]"},f={xs:"rounded-[0.375rem]",sm:"rounded-[0.4375rem]",md:"rounded-[0.5625rem]",lg:"rounded-[0.6875rem]",xl:"rounded-[0.875rem]"},u={solid:[d,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev)]"].join(" "),outline:[d,"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)]"},x="after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit]",h={solid:`${x} after:[box-shadow:var(--neba-plate-solid)]`,outline:`${x} after:[box-shadow:var(--neba-plate-glass)]`,text:""},v=["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%]",c].join(" ");function p(){return r("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=t.forwardRef(function({src:t,srcSet:d,alt:c,name:x,initials:g,shape:b="circle",variant:w="text",size:j="md",color:y="primary",elevation:N=0,delay:z,imageProps:C,onLoadingStatusChange:A,className:B,style:S,children:k,...L},F){const M=x?function(e){const r=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===r.length?"":((Array.from(r[0])[0]??"")+(r.length>1?Array.from(r[r.length-1])[0]??"":"")).toLocaleUpperCase()}(x):"",R=c??x,Z=s(k)?k:(g??M)||e(p,{}),$=s(k)||Boolean(g??M),_=[v,a[j],l[j],m[j],"circle"===b?"rounded-full":f[j],u[w],h[w],B??""].filter(Boolean).join(" ");return r(n.Root,{ref:F,className:_,style:{...o(y,N,w),...S},...L,children:[t?e(n.Image,{src:t,srcSet:d,alt:R??"",className:"size-full object-cover",onLoadingStatusChange:A,...C}):null,r(n.Fallback,{delay:t?z:void 0,className:"flex size-full items-center justify-center",children:[R&&$?e("span",{className:i,children:R}):null,e("span",{"aria-hidden":!(!R||!$)||void 0,className:"contents",children:Z})]})]})});
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})]})]})});
@@ -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}})});
@@ -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
  export interface ChipProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
4
4
  /**
5
5
  * Drop shadow depth. `0` (the default) is flat. A chip is a token sitting on
@@ -7,6 +7,12 @@ export interface ChipProps extends NebaStyleProps, Omit<React.ComponentPropsWith
7
7
  * @default 0
8
8
  */
9
9
  elevation?: NebaElevation;
10
+ /**
11
+ * An entrance animation, run once on mount: `transition="fade"`, or an object
12
+ * for the details. For a trigger, a replay or anything under your own
13
+ * control, wrap it in an `Animate*` component instead.
14
+ */
15
+ transition?: NebaTransition;
10
16
  /** Content placed before the label — an icon, a status dot, an avatar. */
11
17
  startIcon?: React.ReactNode;
12
18
  /** Content placed after the label, before any `count`. */
@@ -1 +1 @@
1
- import{jsx as e,Fragment as n,jsxs as l}from"react/jsx-runtime";import*as t from"react";import{CloseIcon as o}from"../../internal/icons";import{chipRemoveClasses as i,controlHeightClasses as r,controlSlots as s,controlTextClasses as a,disabledClasses as c,focusRingClasses as d,gapClasses as m,iconClasses as p,paddingXClasses as b,pressTransitionClasses as f,radiusClasses as u,surfaceClasses as h,transitionClasses as v}from"../../internal/styles";const x={xs:"xs",sm:"xs",md:"sm",lg:"md",xl:"lg"},g={solid:[h,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[h,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft)"},j={solid:"bg-(--n-fill-active)",outline:"bg-(--n-panel-press) [border-color:var(--n-line-hover)]",text:"bg-(--n-soft-press)"},w={solid:"hover:bg-(--n-fill-hover) active:bg-(--n-fill-active)",outline:"hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)] active:bg-(--n-panel-press)",text:"hover:bg-(--n-soft-hover) active:bg-(--n-soft-press)"},y=["relative inline-flex max-w-full shrink-0 select-none items-center","align-middle font-medium leading-none whitespace-nowrap","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",v,f,p].join(" "),k=["flex min-w-0 flex-1 cursor-pointer items-center justify-center self-stretch rounded-[inherit]",d].join(" ");export const Chip=t.forwardRef(function({variant:t="outline",size:d="md",color:p="primary",density:f="default",elevation:h=0,startIcon:v,endIcon:N,count:C,onDelete:$,deleteLabel:B="Remove",selected:I=!1,disabled:R=!1,className:z,style:D,children:F,onClick:L,...q},A){const E=Boolean(L)&&!R,G=x[d],H=b[f][G],J=[y,r[G],a[G],m[G],u[G],R?c[t]:g[t],!R&&I?j[t]:"",E?w[t]:"",E?"ps-0":H,$?"pe-1":E?"pe-0":"",z??""].filter(Boolean).join(" "),K=l(n,{children:[v,null!=F&&!1!==F?e("span",{className:"min-w-0 truncate",children:F}):null,N,null!=C&&!1!==C?e("span",{className:["ms-0.5 inline-flex shrink-0 items-center justify-center rounded-full px-1.5 py-px","text-[0.85em] leading-none font-semibold tabular-nums","solid"===t?"bg-(--neba-glow-on-fill) text-(--n-on-solid)":"bg-(--n-soft-press) text-(--n-accent)"].join(" "),children:C}):null]});return l("span",{ref:A,className:J,style:{...s(p,h,t),...D},"aria-disabled":!(!R||E)||void 0,...q,children:[E?e("button",{type:"button","aria-pressed":I,className:`${k} ${m[G]} ${H}`,onClick:L,children:K}):K,$?e("button",{type:"button","aria-label":B,disabled:R,className:i,onClick:$,children:e(o,{})}):null]})});
1
+ import{jsx as e,Fragment as n,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{CloseIcon as o}from"../../internal/icons";import{transitionProps as i}from"../../internal/animate";import{chipRemoveClasses as r,controlHeightClasses as a,controlSlots as s,controlTextClasses as c,disabledClasses as d,focusRingClasses as m,gapClasses as p,iconClasses as b,paddingXClasses as f,pressTransitionClasses as u,radiusClasses as h,surfaceClasses as v,transitionClasses as x}from"../../internal/styles";const g={xs:"xs",sm:"xs",md:"sm",lg:"md",xl:"lg"},j={solid:[v,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[v,"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)"},y={solid:"bg-(--n-fill-active)",outline:"bg-(--n-panel-press) [border-color:var(--n-line-hover)]",text:"bg-(--n-soft-press)"},w={solid:"hover:bg-(--n-fill-hover) active:bg-(--n-fill-active)",outline:"hover:bg-(--n-panel-hover) hover:[border-color:var(--n-line-hover)] active:bg-(--n-panel-press)",text:"hover:bg-(--n-soft-hover) active:bg-(--n-soft-press)"},N=["relative inline-flex max-w-full shrink-0 select-none items-center","align-middle font-medium leading-none whitespace-nowrap","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",x,u,b].join(" "),k=["flex min-w-0 flex-1 cursor-pointer items-center justify-center self-stretch rounded-[inherit]",m].join(" ");export const Chip=l.forwardRef(function({variant:l="outline",size:m="md",color:b="primary",density:u="default",elevation:v=0,startIcon:x,endIcon:C,count:$,onDelete:B,deleteLabel:I="Remove",transition:R,selected:z=!1,disabled:D=!1,className:F,style:L,children:q,onClick:A,...E},G){const H=Boolean(A)&&!D,J=g[m],K=i(R),M=f[u][J],O=[N,a[J],c[J],p[J],h[J],D?d[l]:j[l],!D&&z?y[l]:"",H?w[l]:"",H?"ps-0":M,B?"pe-1":H?"pe-0":"",K.className,F??""].filter(Boolean).join(" "),P=t(n,{children:[x,null!=q&&!1!==q?e("span",{className:"min-w-0 truncate",children:q}):null,C,null!=$&&!1!==$?e("span",{className:["ms-0.5 inline-flex shrink-0 items-center justify-center rounded-full px-1.5 py-px","text-[0.85em] leading-none font-semibold tabular-nums","solid"===l?"bg-(--neba-glow-on-fill) text-(--n-on-solid)":"bg-(--n-soft-press) text-(--n-accent)"].join(" "),children:$}):null]});return t("span",{ref:G,className:O,style:{...s(b,v,l),...K.style,...L},"aria-disabled":!(!D||H)||void 0,...E,children:[H?e("button",{type:"button","aria-pressed":z,className:`${k} ${p[J]} ${M}`,onClick:A,children:P}):P,B?e("button",{type:"button","aria-label":I,disabled:D,className:r,onClick:B,children:e(o,{})}):null]})});
@@ -0,0 +1,102 @@
1
+ import * as React from 'react';
2
+ import type { ColorFormat } from '../../internal/color';
3
+ import type { NebaElevation, NebaStyleProps } from '../../types';
4
+ /** The names for the parts of the picker that have no text on them. */
5
+ export interface ColorPickerLabels {
6
+ /** The saturation/brightness square. */
7
+ area: string;
8
+ /** The hue rail beside it. */
9
+ hue: string;
10
+ /** The opacity rail, when `alpha` is on. */
11
+ alpha: string;
12
+ /** The field the value can be typed into. */
13
+ value: string;
14
+ /** The grid of ready-made colours. */
15
+ swatches: string;
16
+ /** The × that empties the control. */
17
+ clear: string;
18
+ /** What the trigger reads before anything has been chosen. */
19
+ empty: string;
20
+ }
21
+ export interface ColorPickerProps extends NebaStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
22
+ /** The colour, as a CSS string. Pass it to drive the picker yourself. */
23
+ value?: string;
24
+ /** Where an uncontrolled picker starts. @default '#1a58d1' */
25
+ defaultValue?: string;
26
+ /** Called with the new colour, written in `format`. */
27
+ onValueChange?: (value: string) => void;
28
+ /**
29
+ * Which notation the value is written in on the way out.
30
+ * @default 'hex'
31
+ */
32
+ format?: ColorFormat;
33
+ /**
34
+ * Offers an opacity rail, and lets the value carry a fourth channel.
35
+ * @default false
36
+ */
37
+ alpha?: boolean;
38
+ /**
39
+ * The ready-made colours under the panel. `false` draws none; an array of CSS
40
+ * colour strings replaces the built-in set.
41
+ */
42
+ swatches?: readonly string[] | false;
43
+ /**
44
+ * Draws the panel in the page instead of in a popup, with no trigger.
45
+ * @default false
46
+ */
47
+ inline?: boolean;
48
+ /**
49
+ * The field under the panel that the value can be typed into.
50
+ * @default true
51
+ */
52
+ editable?: boolean;
53
+ /** Label above the control. */
54
+ label?: React.ReactNode;
55
+ /** Helper text below it. */
56
+ description?: React.ReactNode;
57
+ /** Error message below. Its presence also turns the control invalid. */
58
+ error?: React.ReactNode;
59
+ invalid?: boolean;
60
+ required?: boolean;
61
+ disabled?: boolean;
62
+ /** Shows the colour and forbids changing it. @default false */
63
+ readOnly?: boolean;
64
+ /** Stretches the trigger to its container. @default false */
65
+ fullWidth?: boolean;
66
+ /** Offers the × that empties the control. @default false */
67
+ clearable?: boolean;
68
+ /** Submits with a form under this name. */
69
+ name?: string;
70
+ /** Whether the popup is open. Pass it to drive the popup yourself. */
71
+ open?: boolean;
72
+ /** Where an uncontrolled popup starts. @default false */
73
+ defaultOpen?: boolean;
74
+ onOpenChange?: (open: boolean) => void;
75
+ /**
76
+ * Which language the accessible names are written in — a BCP 47 tag such as
77
+ * `ko`, `pt-BR` or `zh-Hant`. Unsupported tags fall back to English.
78
+ */
79
+ locale?: string;
80
+ /** Overrides for those names, one at a time. */
81
+ labels?: Partial<ColorPickerLabels>;
82
+ /** Drop shadow depth on the trigger. `0` (the default) is flat. @default 0 */
83
+ elevation?: NebaElevation;
84
+ }
85
+ /**
86
+ * A colour, chosen by eye.
87
+ *
88
+ * A saturation square with a hue rail beside it — the arrangement every design
89
+ * tool has settled on, because it is the one that puts every colour of a hue
90
+ * within a single movement of the pointer. `alpha` adds a third rail, `format`
91
+ * decides which notation comes back out, and `swatches` puts the handful of
92
+ * colours a product actually uses one click away.
93
+ *
94
+ * The panel's state is HSV and it never leaves that model, which is what keeps
95
+ * the hue rail still while the pointer is in the black corner: through RGB,
96
+ * every shade of black is the same colour and the rail would snap to red.
97
+ *
98
+ * There is no colour library under this. The conversions are in
99
+ * `internal/color.ts`, which is a hundred lines of arithmetic — the whole
100
+ * reason the package still has one runtime dependency.
101
+ */
102
+ export declare const ColorPicker: React.ForwardRefExoticComponent<ColorPickerProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{defaultPickerLabels as l}from"../../internal/calendar";import{PickerShell as n}from"../../internal/picker";import{CheckIcon as t}from"../../internal/icons";import{useMessages as o}from"../../internal/i18n";import{checkerBackground as s,clamp as i,cssColor as d,defaultSwatches as h,formatColor as c,parseColor as u,readableInk as f}from"../../internal/color";import{controlTextClasses as p,cx as b,focusRingClasses as m,metaTextClasses as g,radiusClasses as v,stackGapClasses as x,surfaceSlots as y}from"../../internal/styles";const w={xs:"w-40",sm:"w-44",md:"w-52",lg:"w-60",xl:"w-72"},N={xs:"h-24",sm:"h-28",md:"h-32",lg:"h-40",xl:"h-48"},k={xs:"h-2.5",sm:"h-3",md:"h-3.5",lg:"h-4",xl:"h-5"},C={xs:"gap-1.5",sm:"gap-2",md:"gap-2.5",lg:"gap-3",xl:"gap-3.5"},_={xs:10,sm:12,md:14,lg:16,xl:18},z=["relative overflow-hidden border","[border-color:var(--neba-border)]","[box-shadow:var(--neba-plate-glass)]"].join(" "),I=["pointer-events-none absolute rounded-full border-2 border-white","[box-shadow:0_0_0_1px_rgba(0,0,0,0.35),0_1px_3px_rgba(0,0,0,0.4)]"].join(" ");function T(e){const a=e.currentTarget.getBoundingClientRect();return{x:0===a.width?0:i((e.clientX-a.left)/a.width,0,1),y:0===a.height?0:i((e.clientY-a.top)/a.height,0,1)}}function j(e){const a=e.shiftKey?10:1;switch(e.key){case"ArrowLeft":return{x:-a,y:0};case"ArrowRight":return{x:a,y:0};case"ArrowUp":return{x:0,y:a};case"ArrowDown":return{x:0,y:-a};default:return null}}function A({hsv:r,alphaValue:l,onChange:n,text:o,onTextChange:h,withAlpha:p,swatches:x,editable:y,size:A,inert:D,labels:M}){const O=_[A],P=-O/2,V=d({h:r.h,s:100,v:100}),$=d(r),L=e=>({onPointerDown:a=>{D||(a.currentTarget.setPointerCapture(a.pointerId),e(a))},onPointerMove:a=>{!D&&a.currentTarget.hasPointerCapture(a.pointerId)&&e(a)}}),S=(e,a,r,l)=>({role:"slider",tabIndex:D?-1:0,"aria-label":e,"aria-valuemin":0,"aria-valuemax":r,"aria-valuenow":Math.round(a),"aria-orientation":"horizontal","aria-disabled":D||void 0,onKeyDown:e=>{const a=j(e);!D&&a&&0!==a.x&&(e.preventDefault(),l(a.x))}});return a("div",{className:b("flex flex-col",w[A],C[A]),children:[e("div",{...L(e=>{const{x:a,y:t}=T(e);n({hsv:{h:r.h,s:100*a,v:100*(1-t)},alpha:l})}),role:"slider",tabIndex:D?-1:0,"aria-label":M.area,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(r.s),"aria-valuetext":`${Math.round(r.s)}%, ${Math.round(r.v)}%`,"aria-disabled":D||void 0,onKeyDown:e=>{const a=j(e);!D&&a&&(e.preventDefault(),n({hsv:{h:r.h,s:i(r.s+a.x,0,100),v:i(r.v+a.y,0,100)},alpha:l}))},className:b(z,N[A],v[A],m,D?"cursor-default":"cursor-crosshair touch-none"),style:{backgroundColor:V,backgroundImage:"linear-gradient(to top, #000000, rgba(0, 0, 0, 0)), linear-gradient(to right, #ffffff, rgba(255, 255, 255, 0))"},children:e("span",{className:I,style:{width:O,height:O,left:`${r.s}%`,top:100-r.v+"%",marginLeft:P,marginTop:P,backgroundColor:$}})}),e("div",{...L(e=>n({hsv:{...r,h:360*T(e).x},alpha:l})),...S(M.hue,r.h,360,e=>n({hsv:{...r,h:(r.h+2*e+360)%360},alpha:l})),className:b(z,k[A],"rounded-full",m,D?"cursor-default":"cursor-pointer touch-none"),style:{backgroundImage:"linear-gradient(to right, #ff0000 0%, #ffff00 16.66%, #00ff00 33.33%, #00ffff 50%, #0000ff 66.66%, #ff00ff 83.33%, #ff0000 100%)"},children:e("span",{className:I,style:{width:O,height:O,left:r.h/360*100+"%",top:"50%",marginLeft:P,marginTop:P,backgroundColor:V}})}),p?a("div",{...L(e=>n({hsv:r,alpha:T(e).x})),...S(M.alpha,100*l,100,e=>n({hsv:r,alpha:i(l+e/100,0,1)})),className:b(z,k[A],"rounded-full",m,D?"cursor-default":"cursor-pointer touch-none"),style:s,children:[e("span",{"aria-hidden":"true",className:"absolute inset-0",style:{backgroundImage:`linear-gradient(to right, ${d(r,0)}, ${$})`}}),e("span",{className:I,style:{width:O,height:O,left:100*l+"%",top:"50%",marginLeft:P,marginTop:P,backgroundColor:d(r,l)}})]}):null,y?a("div",{className:b("flex items-center",C[A]),children:[e("span",{"aria-hidden":"true",className:b("shrink-0 rounded-full border","[border-color:var(--neba-border)]"),style:{width:O+6,height:O+6,...s},children:e("span",{className:"block size-full rounded-full",style:{backgroundColor:d(r,l)}})}),e("input",{type:"text",value:o,readOnly:D,spellCheck:!1,autoComplete:"off","aria-label":M.value,onChange:e=>h(e.target.value),className:b("min-w-0 flex-1 border bg-transparent px-1.5 py-1 font-mono lowercase","[border-color:var(--neba-border)]",v.xs,g[A],"text-(--neba-fg)","[outline:none] focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1")})]}):null,x&&x.length>0?e("div",{role:"group","aria-label":M.swatches,className:"grid grid-cols-8 gap-1",children:x.map(a=>{const o=u(a),s=null!==o&&c(o.hsv,o.alpha,"hex")===c(r,l,"hex");return e("button",{type:"button",disabled:D,"aria-label":a,"aria-pressed":s,onClick:()=>{o&&n(o)},className:b("flex aspect-square items-center justify-center rounded-full border","[border-color:color-mix(in_oklab,var(--neba-fg)_18%,transparent)]","[transition:box-shadow_var(--neba-duration)_var(--neba-ease)]",m,"[outline:none]",D?"cursor-default":"cursor-pointer hover:[box-shadow:var(--neba-shadow-1)]","[&_svg]:size-3"),style:{backgroundColor:a},children:s&&o?e("span",{style:{color:f(o.hsv)},children:e(t,{})}):null},a)})}):null]})}function D(e,a){return"hex"===e?[a?"#ffffffff":"#ffffff"]:"rgb"===e?[a?"rgba(255, 255, 255, 0.55)":"rgb(255, 255, 255)"]:[a?"hsla(360, 100%, 100%, 0.55)":"hsl(360, 100%, 100%)"]}const M={h:217,s:87,v:82};export const ColorPicker=r.forwardRef(function({value:t,defaultValue:i="#1a58d1",onValueChange:f,format:m="hex",alpha:v=!1,swatches:w=h,inline:N=!1,editable:k=!0,label:C,description:_,error:z,invalid:I,required:T=!1,disabled:j=!1,readOnly:O=!1,fullWidth:P=!1,clearable:V=!1,name:$,open:L,defaultOpen:S=!1,onOpenChange:q,locale:K,labels:R,variant:B="outline",size:W="md",color:E="primary",density:U="default",elevation:X=0,className:Y,style:F,...G},H){const J=o(K),Q=r.useMemo(()=>({...J.color,...R}),[J,R]),[Z,ee]=r.useState(i),ae=t??Z,[re,le]=r.useState(S),ne=L??re,[te,oe]=r.useState(()=>u(ae)??{hsv:M,alpha:1}),[se,ie]=r.useState(()=>ae||""),de=c(te.hsv,v?te.alpha:1,m),he=""===ae;r.useEffect(()=>{const e=u(ae);e?c(e.hsv,v?e.alpha:1,m)!==de&&(ie(ae),oe(e)):ie(ae)},[ae,de,v,m]);const ce=(e,a)=>{oe(e);const r=c(e.hsv,v?e.alpha:1,m);ie(a??r),void 0===t&&ee(r),f?.(r)},ue=j||O,fe=e(A,{hsv:te.hsv,alphaValue:te.alpha,onChange:ce,text:se,onTextChange:e=>{ie(e);const a=u(e);a&&ce(a,e)},withAlpha:v,swatches:w,editable:k,size:W,inert:ue,labels:Q}),pe=$?e("input",{type:"hidden",name:$,value:he?"":de}):null;if(N){const r=I??Boolean(z)?"danger":E;return a("div",{ref:H,className:b("flex flex-col",x[W],Y),style:{...y(r,X),...F},...G,children:[C?e("span",{className:b(g[W],"font-medium",j?"text-(--neba-disabled-fg)":"text-(--neba-fg)"),children:C}):null,fe,_?e("span",{className:b(g[W],"text-(--neba-muted-fg)"),children:_}):null,z?e("span",{className:b(g[W],"text-(--n-accent)"),children:z}):null,pe]})}return e("div",{ref:H,className:P?"w-full":"inline-block",...G,children:e(n,{variant:B,size:W,color:E,density:U,elevation:X,style:F,label:C,description:_,error:z,invalid:I,required:T,disabled:j,readOnly:O,fullWidth:P,className:Y,startIcon:e("span",{"aria-hidden":"true",className:b("block size-[1.15em] shrink-0 rounded-full border","[border-color:color-mix(in_oklab,var(--neba-fg)_18%,transparent)]"),style:s,children:e("span",{className:"block size-full rounded-full",style:{backgroundColor:he?"transparent":d(te.hsv,v?te.alpha:1)}})}),display:he?Q.empty:de,samples:D(m,v),empty:he,clearable:V,onClear:()=>{void 0===t&&ee(""),ie(""),f?.("")},open:ne,onOpenChange:e=>{void 0===L&&le(e),q?.(e)},labels:{...l,clear:Q.clear},hiddenValues:$?[{name:$,value:he?"":de}]:void 0,children:e("div",{className:p[W],children:fe})})})});
@@ -0,0 +1,2 @@
1
+ export { ColorPicker } from './ColorPicker';
2
+ export type { ColorPickerLabels, ColorPickerProps } from './ColorPicker';
@@ -0,0 +1 @@
1
+ export{ColorPicker}from"./ColorPicker";