material-plus-ui 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/components/animate-appear/MPAnimateAppear.d.ts +56 -0
  2. package/dist/components/animate-appear/MPAnimateAppear.js +1 -0
  3. package/dist/components/animate-appear/index.d.ts +2 -0
  4. package/dist/components/animate-appear/index.js +1 -0
  5. package/dist/components/animate-blink/MPAnimateBlink.d.ts +41 -0
  6. package/dist/components/animate-blink/MPAnimateBlink.js +1 -0
  7. package/dist/components/animate-blink/index.d.ts +2 -0
  8. package/dist/components/animate-blink/index.js +1 -0
  9. package/dist/components/animate-fade/MPAnimateFade.d.ts +38 -0
  10. package/dist/components/animate-fade/MPAnimateFade.js +1 -0
  11. package/dist/components/animate-fade/index.d.ts +2 -0
  12. package/dist/components/animate-fade/index.js +1 -0
  13. package/dist/components/animate-grow/MPAnimateGrow.d.ts +52 -0
  14. package/dist/components/animate-grow/MPAnimateGrow.js +1 -0
  15. package/dist/components/animate-grow/index.d.ts +2 -0
  16. package/dist/components/animate-grow/index.js +1 -0
  17. package/dist/components/animate-headline/MPAnimateHeadline.d.ts +63 -0
  18. package/dist/components/animate-headline/MPAnimateHeadline.js +1 -0
  19. package/dist/components/animate-headline/index.d.ts +2 -0
  20. package/dist/components/animate-headline/index.js +1 -0
  21. package/dist/components/animate-lighting/MPAnimateLighting.d.ts +68 -0
  22. package/dist/components/animate-lighting/MPAnimateLighting.js +1 -0
  23. package/dist/components/animate-lighting/index.d.ts +2 -0
  24. package/dist/components/animate-lighting/index.js +1 -0
  25. package/dist/components/animate-marquee/MPAnimateMarquee.d.ts +66 -0
  26. package/dist/components/animate-marquee/MPAnimateMarquee.js +1 -0
  27. package/dist/components/animate-marquee/index.d.ts +2 -0
  28. package/dist/components/animate-marquee/index.js +1 -0
  29. package/dist/components/animate-rotate/MPAnimateRotate.d.ts +56 -0
  30. package/dist/components/animate-rotate/MPAnimateRotate.js +1 -0
  31. package/dist/components/animate-rotate/index.d.ts +2 -0
  32. package/dist/components/animate-rotate/index.js +1 -0
  33. package/dist/components/animate-slide/MPAnimateSlide.d.ts +53 -0
  34. package/dist/components/animate-slide/MPAnimateSlide.js +1 -0
  35. package/dist/components/animate-slide/index.d.ts +2 -0
  36. package/dist/components/animate-slide/index.js +1 -0
  37. package/dist/components/animate-typing/MPAnimateTyping.d.ts +59 -0
  38. package/dist/components/animate-typing/MPAnimateTyping.js +1 -0
  39. package/dist/components/animate-typing/index.d.ts +2 -0
  40. package/dist/components/animate-typing/index.js +1 -0
  41. package/dist/components/animate-zoom/MPAnimateZoom.d.ts +44 -0
  42. package/dist/components/animate-zoom/MPAnimateZoom.js +1 -0
  43. package/dist/components/animate-zoom/index.d.ts +2 -0
  44. package/dist/components/animate-zoom/index.js +1 -0
  45. package/dist/components/avatar/MPAvatar.d.ts +9 -2
  46. package/dist/components/avatar/MPAvatar.js +1 -1
  47. package/dist/components/bottom-navigation/MPBottomNavigation.d.ts +144 -0
  48. package/dist/components/bottom-navigation/MPBottomNavigation.js +1 -0
  49. package/dist/components/bottom-navigation/index.d.ts +2 -0
  50. package/dist/components/bottom-navigation/index.js +1 -0
  51. package/dist/components/breadcrumb/MPBreadcrumb.d.ts +22 -0
  52. package/dist/components/breadcrumb/MPBreadcrumb.js +1 -1
  53. package/dist/components/button/MPButton.d.ts +7 -2
  54. package/dist/components/button/MPButton.js +1 -1
  55. package/dist/components/carousel/MPCarousel.js +1 -1
  56. package/dist/components/checkbox/MPCheckbox.d.ts +2 -2
  57. package/dist/components/checkbox/MPCheckbox.js +1 -1
  58. package/dist/components/chip/MPChip.d.ts +13 -3
  59. package/dist/components/chip/MPChip.js +1 -1
  60. package/dist/components/color-picker/MPColorPicker.d.ts +21 -3
  61. package/dist/components/color-picker/MPColorPicker.js +1 -1
  62. package/dist/components/combobox/MPCombobox.d.ts +38 -10
  63. package/dist/components/combobox/MPCombobox.js +1 -1
  64. package/dist/components/container/MPContainer.d.ts +75 -0
  65. package/dist/components/container/MPContainer.js +1 -0
  66. package/dist/components/container/index.d.ts +2 -0
  67. package/dist/components/container/index.js +1 -0
  68. package/dist/components/date-picker/MPDatePicker.d.ts +3 -0
  69. package/dist/components/date-picker/MPDatePicker.js +1 -1
  70. package/dist/components/date-range-picker/MPDateRangePicker.js +1 -1
  71. package/dist/components/date-time-picker/MPDateTimePicker.js +1 -1
  72. package/dist/components/dialog/MPDialog.d.ts +8 -3
  73. package/dist/components/dialog/MPDialog.js +1 -1
  74. package/dist/components/drawer/MPDrawer.d.ts +8 -3
  75. package/dist/components/drawer/MPDrawer.js +1 -1
  76. package/dist/components/empty/MPEmpty.d.ts +12 -2
  77. package/dist/components/empty/MPEmpty.js +1 -1
  78. package/dist/components/file-picker/MPFilePicker.d.ts +11 -1
  79. package/dist/components/file-picker/MPFilePicker.js +1 -1
  80. package/dist/components/floating-action-button/MPFloatingActionButton.d.ts +126 -0
  81. package/dist/components/floating-action-button/MPFloatingActionButton.js +1 -0
  82. package/dist/components/floating-action-button/index.d.ts +2 -0
  83. package/dist/components/floating-action-button/index.js +1 -0
  84. package/dist/components/grid/MPGrid.d.ts +155 -0
  85. package/dist/components/grid/MPGrid.js +1 -0
  86. package/dist/components/grid/index.d.ts +2 -0
  87. package/dist/components/grid/index.js +1 -0
  88. package/dist/components/highlight/MPHighlight.js +1 -1
  89. package/dist/components/list/MPList.js +1 -1
  90. package/dist/components/menu/MPMenu.d.ts +10 -1
  91. package/dist/components/menu/MPMenu.js +1 -1
  92. package/dist/components/number-field/MPNumberField.d.ts +21 -3
  93. package/dist/components/number-field/MPNumberField.js +1 -1
  94. package/dist/components/pagination/MPPagination.d.ts +106 -0
  95. package/dist/components/pagination/MPPagination.js +1 -0
  96. package/dist/components/pagination/index.d.ts +2 -0
  97. package/dist/components/pagination/index.js +1 -0
  98. package/dist/components/panes/MPPanes.js +1 -1
  99. package/dist/components/pill/MPPill.js +1 -1
  100. package/dist/components/popover/MPPopover.d.ts +8 -3
  101. package/dist/components/popover/MPPopover.js +1 -1
  102. package/dist/components/rating/MPRating.d.ts +135 -0
  103. package/dist/components/rating/MPRating.js +1 -0
  104. package/dist/components/rating/index.d.ts +2 -0
  105. package/dist/components/rating/index.js +1 -0
  106. package/dist/components/select/MPSelect.d.ts +23 -6
  107. package/dist/components/select/MPSelect.js +1 -1
  108. package/dist/components/skeleton/MPSkeleton.js +1 -1
  109. package/dist/components/snackbar/MPSnackbar.d.ts +8 -3
  110. package/dist/components/snackbar/MPSnackbar.js +1 -1
  111. package/dist/components/spoiler/MPSpoiler.js +1 -1
  112. package/dist/components/switch/MPSwitch.d.ts +2 -2
  113. package/dist/components/switch/MPSwitch.js +1 -1
  114. package/dist/components/table/MPTable.d.ts +14 -1
  115. package/dist/components/table/MPTable.js +1 -1
  116. package/dist/components/tabs/MPTabs.d.ts +145 -0
  117. package/dist/components/tabs/MPTabs.js +1 -0
  118. package/dist/components/tabs/index.d.ts +2 -0
  119. package/dist/components/tabs/index.js +1 -0
  120. package/dist/components/text-field/MPTextField.d.ts +37 -7
  121. package/dist/components/text-field/MPTextField.js +1 -1
  122. package/dist/components/text-link/MPTextLink.js +1 -1
  123. package/dist/components/time-picker/MPTimePicker.js +1 -1
  124. package/dist/components/timeline/MPTimeline.js +1 -1
  125. package/dist/constants/icons.d.ts +13 -0
  126. package/dist/constants/icons.js +1 -1
  127. package/dist/index.d.ts +18 -0
  128. package/dist/index.js +1 -1
  129. package/dist/internal/Calendar.js +1 -1
  130. package/dist/internal/FieldOutline.d.ts +75 -4
  131. package/dist/internal/FieldOutline.js +1 -1
  132. package/dist/internal/Picker.d.ts +52 -9
  133. package/dist/internal/Picker.js +1 -1
  134. package/dist/internal/animate.d.ts +179 -0
  135. package/dist/internal/animate.js +1 -0
  136. package/dist/internal/date.d.ts +2 -2
  137. package/dist/internal/date.js +1 -1
  138. package/dist/internal/i18n.d.ts +110 -0
  139. package/dist/internal/i18n.js +1 -1
  140. package/dist/internal/inert.d.ts +11 -0
  141. package/dist/internal/inert.js +1 -0
  142. package/dist/styles.css +1 -1
  143. package/dist/tailwind.css +590 -4
  144. package/dist/types.d.ts +155 -0
  145. package/package.json +1 -1
@@ -0,0 +1,59 @@
1
+ import * as React from 'react';
2
+ import type { MPAnimateProps } from '../../types';
3
+ export interface MPAnimateTypingProps extends Omit<MPAnimateProps, 'alternate' | 'easing'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {
4
+ /** The text, when it is easier to pass than to nest. Overrides `children`. */
5
+ text?: string;
6
+ /**
7
+ * How fast it is typed, in characters per second.
8
+ * @default 24
9
+ */
10
+ speed?: number;
11
+ /**
12
+ * How long the finished text is held before it repeats, in milliseconds.
13
+ * @default 1400
14
+ */
15
+ hold?: number;
16
+ /**
17
+ * Deletes the text again before repeating, rather than clearing it in one
18
+ * frame. Only means anything when `repeat` is more than once.
19
+ * @default false
20
+ */
21
+ erase?: boolean;
22
+ /**
23
+ * How fast it is deleted, in characters per second. Deleting is usually about
24
+ * twice as fast as typing, which is what a person actually does.
25
+ * @default twice `speed`
26
+ */
27
+ eraseSpeed?: number;
28
+ /**
29
+ * The block after the text.
30
+ * @default true
31
+ */
32
+ caret?: boolean;
33
+ /**
34
+ * What the caret is drawn as.
35
+ * @default '|'
36
+ */
37
+ caretChar?: React.ReactNode;
38
+ /** The text to type. Only text is typed — see below. */
39
+ children?: React.ReactNode;
40
+ }
41
+ /**
42
+ * Text appearing one character at a time.
43
+ *
44
+ * The whole string is in the document from the first frame — in a clipped box
45
+ * for a screen reader, which reads it once and is not made to sit through the
46
+ * performance — and what animates is a visible copy that is `aria-hidden`. So
47
+ * the effect costs a reader who cannot see it nothing, and costs a reader who
48
+ * can nothing either: the box is not laid out from the characters that have
49
+ * arrived, so the text around it does not reflow on every frame.
50
+ *
51
+ * `repeat`, `hold` and `erase` are what make it a loop: type, hold, delete,
52
+ * type again. Without `erase` a repeat clears in one frame, which is right for
53
+ * a line that is being replaced rather than rewritten.
54
+ *
55
+ * Only **text** is typed. Pass a string, or strings; an element among the
56
+ * children contributes its text and nothing about its markup, because there is
57
+ * no honest way to reveal half of a link.
58
+ */
59
+ export declare const MPAnimateTyping: React.ForwardRefExoticComponent<MPAnimateTypingProps & 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{VISUALLY_HIDDEN as s}from"../../internal/visually-hidden";function u(e){return"string"==typeof e||"number"==typeof e?String(e):Array.isArray(e)?e.map(u).join(""):""}export const MPAnimateTyping=r.forwardRef(function({text:o,speed:m=24,hold:c=1400,erase:f=!1,eraseSpeed:l,caret:d=!0,caretChar:p="|",duration:h,delay:g=0,repeat:y=1,paused:x,trigger:T="mount",play:v,once:j=!0,threshold:M=.2,className:N,style:S,children:w,...A},I){const E=a({trigger:T,play:v,once:j,threshold:M,paused:x,infinite:n(y)}),R=i(),b=o??u(w),C=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]}(b),[b]),P=C.length,[k,q]=r.useState(0),z=r.useRef(0),B=h&&P>0?h/P:1e3/Math.max(m,1),D=1e3/Math.max(l??2*m,1);return r.useEffect(()=>{z.current=0},[P]),r.useEffect(()=>{if(R||0===P)return void q(P);if(!E.started)return z.current=0,void q(0);if(x)return;let e,t=!1,r=z.current,n=1,a=!1;const i="infinite"===y?1/0:Math.max(1,y);if(r>=P&&1===i)return;const s=()=>{if(!t){if(a)return r-=1,z.current=r,q(r),r<=0&&(a=!1,n+=1),void(e=setTimeout(s,a?D:B));if(r+=1,z.current=r,q(r),r<P)e=setTimeout(s,B);else if(!(n>=i)){if(f)return a=!0,void(e=setTimeout(s,c));n+=1,e=setTimeout(()=>{t||(r=0,z.current=0,q(0),e=setTimeout(s,B))},c)}}};return q(r),e=setTimeout(s,0===r?g:B),()=>{t=!0,clearTimeout(e)}},[E.started,x,R,P,B,D,g,c,f,y]),t("div",{ref:e=>{E.ref(e),"function"==typeof I?I(e):I&&(I.current=e)},className:N,style:S,"data-mp-animation":"typing","data-mp-state":E.state,...E.handlers,...A,children:[e("span",{className:s,children:b}),t("span",{"aria-hidden":"true",className:"whitespace-pre-wrap",children:[C.slice(0,k).join(""),d?e("span",{className:"mp-typing-caret",children:p}):null]})]})});
@@ -0,0 +1,2 @@
1
+ export { MPAnimateTyping } from './MPAnimateTyping';
2
+ export type { MPAnimateTypingProps } from './MPAnimateTyping';
@@ -0,0 +1 @@
1
+ export{MPAnimateTyping}from"./MPAnimateTyping";
@@ -0,0 +1,44 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { MPAnimateMode, MPAnimateProps } from '../../types';
4
+ export interface MPAnimateZoomProps extends MPAnimateProps, React.ComponentPropsWithoutRef<'div'> {
5
+ /**
6
+ * Whether the content comes forward or falls away. An exit is quicker than an
7
+ * entrance — MD3's `short4` against `medium4` — unless `duration` says
8
+ * otherwise.
9
+ * @default 'in'
10
+ */
11
+ mode?: MPAnimateMode;
12
+ /**
13
+ * The scale it starts from, as a multiple of its final size. Above `1` it
14
+ * arrives oversized and settles back, which reads as coming *towards* the
15
+ * reader rather than up out of the page.
16
+ * @default 0.4
17
+ */
18
+ from?: number;
19
+ /**
20
+ * Fades in as it zooms.
21
+ * @default true
22
+ */
23
+ fade?: boolean;
24
+ /** Renders something other than a `<div>`. Base UI's own escape hatch. */
25
+ render?: useRender.RenderProp;
26
+ children?: React.ReactNode;
27
+ }
28
+ /**
29
+ * Content arriving from the middle of where it will end up.
30
+ *
31
+ * The same arithmetic as [MPAnimateGrow](../motion/animate-grow) at more than
32
+ * twice the distance, and always about the centre — which is the whole
33
+ * difference. A grow unfolds *from* somewhere; a zoom comes at the reader.
34
+ *
35
+ * Use it for the one thing on a screen that is meant to interrupt: a
36
+ * confirmation, a result, a number that has just landed. Use it once. An
37
+ * interruption that happens three times on one screen is a layout, and the
38
+ * effect that belongs to a set of things rather than to one is
39
+ * [MPAnimateAppear](../motion/animate-appear).
40
+ *
41
+ * There is no `origin`, on purpose. A zoom anchored to a corner is a grow, and
42
+ * the library does not offer two spellings of one idea.
43
+ */
44
+ export declare const MPAnimateZoom: React.ForwardRefExoticComponent<MPAnimateZoomProps & 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 a,useAnimateElement as t}from"../../internal/animate";export const MPAnimateZoom=e.forwardRef(function({duration:e,delay:o=0,easing:n,repeat:i=1,alternate:s,paused:l,trigger:m="mount",play:d,once:c=!0,threshold:f=.2,mode:p="in",from:u=.4,fade:y=!0,render:g,className:h,style:N,children:b,...j},w){const x=t({effect:"zoom",duration:e,delay:o,easing:n,repeat:i,alternate:s,mode:p,scale:u,opacity:y?0:1,trigger:m,play:d,once:c,threshold:f,paused:l,infinite:a(i)});return r({render:g,ref:[w,x.ref],props:{...j,className:[x.className,h].filter(Boolean).join(" "),style:{transformOrigin:"center",...x.style,...N},...x.props,children:b}})});
@@ -0,0 +1,2 @@
1
+ export { MPAnimateZoom } from './MPAnimateZoom';
2
+ export type { MPAnimateZoomProps } from './MPAnimateZoom';
@@ -0,0 +1 @@
1
+ export{MPAnimateZoom}from"./MPAnimateZoom";
@@ -69,8 +69,15 @@ export interface MPAvatarProps extends Omit<React.ComponentPropsWithoutRef<'span
69
69
  * front of a picture that was about to arrive anyway.
70
70
  */
71
71
  delay?: number;
72
- /** Anything else the `<img>` needs — `loading`, `crossOrigin`, `referrerPolicy`. */
73
- imageProps?: Omit<React.ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'alt'>;
72
+ /**
73
+ * Anything else the `<img>` needs — `loading`, `crossOrigin`, `referrerPolicy`.
74
+ *
75
+ * `className` is not among them, and deliberately: the picture is sized and
76
+ * cropped by the avatar's own box, and a class replacing that would be a
77
+ * picture that no longer fits the circle it is in. Style the avatar instead —
78
+ * `className` on the component reaches the box the picture fills.
79
+ */
80
+ imageProps?: Omit<React.ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'alt' | 'className'>;
74
81
  /** Called as the picture moves between `idle`, `loading`, `loaded` and `error`. */
75
82
  onLoadingStatusChange?: (status: MPAvatarLoadingStatus) => void;
76
83
  /**
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Avatar as n}from"@base-ui/react/avatar";import{accentSlots as r}from"../../internal/accent";import{CONTROL_SQUARE as l,hasContent as i}from"../../internal/scale";import{VISUALLY_HIDDEN as o}from"../../internal/visually-hidden";const m={xs:"text-mp-label-medium",sm:"text-mp-label-large",md:"text-mp-title-large",lg:"text-mp-headline-small",xl:"text-mp-headline-medium"},s={xs:"rounded-mp-xs",sm:"rounded-mp-sm",md:"rounded-mp-md",lg:"rounded-mp-md",xl:"rounded-mp-md"},c={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"text-mp-on-surface-variant bg-transparent"};function d(){return a("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",className:"size-[60%]",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 MPAvatar=t.forwardRef(function({src:t,srcSet:p,alt:u,name:f,initials:h,shape:x="circle",variant:g="tonal",size:v="md",color:b="primary",delay:y,imageProps:N,onLoadingStatusChange:j,className:w,style:z,children:_,...C},A){const B=f?function(e){const a=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===a.length?"":((Array.from(a[0])[0]??"")+(a.length>1?Array.from(a[a.length-1])[0]??"":"")).toLocaleUpperCase()}(f):"",S=u??f,L=i(_)?_:(h??B)||e(d,{}),M=i(_)||Boolean(h??B),k=["mp-avatar relative inline-flex shrink-0 items-center justify-center overflow-hidden","align-middle leading-none font-medium whitespace-nowrap select-none",l[v],m[v],"circle"===x?"rounded-mp-full":s[v],c[g],w??""].filter(Boolean).join(" ");return a(n.Root,{ref:A,"data-mp-size":v,"data-mp-variant":g,className:k,style:{...r(b),...z},...C,children:[t?e(n.Image,{src:t,srcSet:p,alt:S??"",className:"size-full object-cover",onLoadingStatusChange:j,...N}):null,a(n.Fallback,{delay:t?y:void 0,className:"flex size-full items-center justify-center",children:[S&&M?e("span",{className:o,children:S}):null,e("span",{"aria-hidden":!(!S||!M)||void 0,className:"contents",children:L})]})]})});
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Avatar as n}from"@base-ui/react/avatar";import{accentSlots as r}from"../../internal/accent";import{CONTROL_SQUARE as l,hasContent as i}from"../../internal/scale";import{VISUALLY_HIDDEN as o}from"../../internal/visually-hidden";const m={xs:"text-mp-label-medium",sm:"text-mp-label-large",md:"text-mp-title-large",lg:"text-mp-headline-small",xl:"text-mp-headline-medium"},s={xs:"rounded-mp-xs",sm:"rounded-mp-sm",md:"rounded-mp-md",lg:"rounded-mp-md",xl:"rounded-mp-md"},c={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"text-mp-on-surface-variant bg-transparent"};function d(){return a("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",className:"size-[60%]",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 MPAvatar=t.forwardRef(function({src:t,srcSet:p,alt:u,name:f,initials:h,shape:x="circle",variant:g="tonal",size:v="md",color:b="primary",delay:y,imageProps:N,onLoadingStatusChange:j,className:w,style:z,children:_,...C},A){const B=f?function(e){const a=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===a.length?"":((Array.from(a[0])[0]??"")+(a.length>1?Array.from(a[a.length-1])[0]??"":"")).toLocaleUpperCase()}(f):"",S=u??f,L=i(_)?_:(h??B)||e(d,{}),M=i(_)||Boolean(h??B),k=["mp-avatar relative inline-flex shrink-0 items-center justify-center overflow-hidden","align-middle leading-none font-medium whitespace-nowrap select-none",l[v],m[v],"circle"===x?"rounded-mp-full":s[v],c[g],w??""].filter(Boolean).join(" ");return a(n.Root,{ref:A,"data-mp-size":v,"data-mp-variant":g,className:k,style:{...r(b),...z},...C,children:[t?e(n.Image,{src:t,srcSet:p,alt:S??"",onLoadingStatusChange:j,...N,className:"size-full object-cover"}):null,a(n.Fallback,{delay:t?y:void 0,className:"flex size-full items-center justify-center",children:[S&&M?e("span",{className:o,children:S}):null,e("span",{"aria-hidden":!(!S||!M)||void 0,className:"contents",children:L})]})]})});
@@ -0,0 +1,144 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { MPPosition, MPSize } from '../../types';
4
+ /** A destination's value. The same restraint `MPTabs` puts on a tab's. */
5
+ export type MPBottomNavigationValue = string | number;
6
+ /**
7
+ * Which names are drawn.
8
+ *
9
+ * MD3's three label behaviours, and the order they lose information in:
10
+ *
11
+ * - `all` — every destination is named. The default, and the only one that works
12
+ * for a reader who has not used the application before.
13
+ * - `selected` — only the destination the reader is on. The bar keeps its height
14
+ * either way.
15
+ * - `none` — glyphs only.
16
+ *
17
+ * Undrawn is never unsaid: in both of the last two the names stay in the
18
+ * document for a screen reader, because a glyph on its own has no accessible
19
+ * name at all.
20
+ */
21
+ export type MPBottomNavigationLabels = 'all' | 'selected' | 'none';
22
+ export interface MPBottomNavigationProps extends Omit<React.ComponentPropsWithoutRef<'nav'>, 'defaultValue' | 'onChange'> {
23
+ /** The destination the reader is on. Use with `onValueChange` for a controlled bar. */
24
+ value?: MPBottomNavigationValue | null;
25
+ /** Which starts current, for an uncontrolled bar. */
26
+ defaultValue?: MPBottomNavigationValue | null;
27
+ /** Called with the value of the destination that was pressed. */
28
+ onValueChange?: (value: MPBottomNavigationValue) => void;
29
+ /**
30
+ * How the bar sits in the page's scroll. `fixed` — the default, against the
31
+ * `static` everything else in this library defaults to — is what a bottom
32
+ * navigation bar is: held against the bottom edge of the window whatever the
33
+ * page under it does.
34
+ * @default 'fixed'
35
+ */
36
+ position?: MPPosition;
37
+ /**
38
+ * Which names are drawn.
39
+ * @default 'all'
40
+ */
41
+ labels?: MPBottomNavigationLabels;
42
+ /**
43
+ * The bar's height and type scale. `md` is MD3's own 80dp.
44
+ * @default 'md'
45
+ */
46
+ size?: MPSize;
47
+ /**
48
+ * A hairline along the top edge.
49
+ *
50
+ * Off by default, because MD3 separates the bar from the page by *tone* — the
51
+ * container is `surface-container` against the page's `surface` — rather than
52
+ * by a rule. Turn it on when the page behind it is the same tone, which is
53
+ * where the tonal difference stops being visible.
54
+ * @default false
55
+ */
56
+ divider?: boolean;
57
+ /**
58
+ * Keeps the destinations clear of a phone's home indicator by adding
59
+ * `env(safe-area-inset-bottom)` under them. The container still reaches the
60
+ * bottom of the screen — only the row moves up, so the surface runs under the
61
+ * indicator rather than stopping in a stripe above it.
62
+ * @default true
63
+ */
64
+ safeArea?: boolean;
65
+ /** Every destination stops answering. */
66
+ disabled?: boolean;
67
+ /**
68
+ * The name the bar is announced by — "Main", "Sections". A landmark with no
69
+ * name is a landmark a screen reader lists as "navigation".
70
+ */
71
+ label?: string;
72
+ /**
73
+ * Renders something other than a `<nav>`. Base UI's own escape hatch, and
74
+ * rarely what you want here: a row of destinations is navigation.
75
+ */
76
+ render?: useRender.RenderProp;
77
+ /** The `MPBottomNavigationItem`s — three to five of them. */
78
+ children?: React.ReactNode;
79
+ }
80
+ export interface MPBottomNavigationItemProps extends Omit<React.ComponentPropsWithoutRef<'button'>, 'value'> {
81
+ /** Identifies the destination. What `onValueChange` reports. */
82
+ value: MPBottomNavigationValue;
83
+ /** The glyph, drawn inside the active indicator. */
84
+ icon?: React.ReactNode;
85
+ /**
86
+ * A second glyph for while this is the destination the reader is on — MD3
87
+ * fills the selected icon and outlines the rest, which is a signal that
88
+ * survives being seen out of the corner of an eye. Falls back to `icon`.
89
+ */
90
+ activeIcon?: React.ReactNode;
91
+ /**
92
+ * Renders the destination as a real link.
93
+ *
94
+ * Worth reaching for: a long press then offers "open in a new tab", the
95
+ * address shows in the status bar, and a crawler can follow it — none of which
96
+ * a `<button>` that calls `router.push` can do. `onValueChange` still fires.
97
+ */
98
+ href?: string;
99
+ /** Unavailable, but still part of the set. */
100
+ disabled?: boolean;
101
+ /** The destination's name. Read out even when `labels` keeps it undrawn. */
102
+ children?: React.ReactNode;
103
+ }
104
+ /**
105
+ * A row of destinations held against the bottom edge of the window.
106
+ *
107
+ * **MD3 calls this the navigation bar**; the name here is the one the pattern is
108
+ * still known by, and the two are the same component. What is drawn is the
109
+ * specification's: a `surface-container` bar 80dp tall, with the destination the
110
+ * reader is on marked by a 64×32dp `secondary-container` pill behind its glyph.
111
+ *
112
+ * ## Why it is a `<nav>` and not a tab list
113
+ *
114
+ * It is a deliberate choice about what is being promised. A tab list owes a
115
+ * keyboard reader one tab stop for the whole set and arrow keys within it, and
116
+ * owes a screen reader a panel per tab; a navigation bar switches what the
117
+ * *page* is, not which panel of one is showing. Claiming the role without the
118
+ * behaviour is worse for a keyboard reader than never claiming it.
119
+ *
120
+ * What is claimed instead is `aria-current="page"`, which is the honest
121
+ * statement: this is the destination you are on. Every item is an ordinary
122
+ * button or link, in the tab order, doing what buttons and links do.
123
+ *
124
+ * For dividing one screen into panels, that genuinely is [MPTabs](./tabs).
125
+ *
126
+ * ## Why it takes no `color`
127
+ *
128
+ * The active indicator is `secondary-container` because MD3 says it is, and for
129
+ * the reason [MPSegmentedButton](../inputs/segmented-button) gives: a mark
130
+ * saying *where you are* is not an accent statement. `primary` is what a screen
131
+ * reserves for the action it is about, and a navigation bar does nothing.
132
+ */
133
+ export declare const MPBottomNavigation: React.ForwardRefExoticComponent<MPBottomNavigationProps & React.RefAttributes<HTMLElement>>;
134
+ /**
135
+ * One destination.
136
+ *
137
+ * It has no `size` and no colour of its own: both belong to the bar, which is
138
+ * the only place they can be set once and mean the same thing for every item. A
139
+ * bar whose third destination is a rung out is not a bar.
140
+ *
141
+ * With an `href` it is a real `<a>`; without one it is a `<button>`, because a
142
+ * `<div>` carrying a click handler is invisible to a keyboard.
143
+ */
144
+ export declare const MPBottomNavigationItem: React.ForwardRefExoticComponent<MPBottomNavigationItemProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as a,Fragment as l}from"react/jsx-runtime";import*as t from"react";import{useRender as n}from"@base-ui/react/use-render";import{MPStateLayer as i}from"../../internal/StateLayer";import{hasContent as o}from"../../internal/scale";import{VISUALLY_HIDDEN as r}from"../../internal/visually-hidden";const s=t.createContext({value:null,change:()=>{},size:"md",labels:"all",disabled:!1}),c={xs:"h-14",sm:"h-16",md:"h-20",lg:"h-22",xl:"h-24"},m={xs:"h-6 w-12",sm:"h-7 w-14",md:"h-8 w-16",lg:"h-9 w-18",xl:"h-10 w-20"},d={xs:20,sm:22,md:24,lg:26,xl:28},u={xs:"text-mp-label-small",sm:"text-mp-label-small",md:"text-mp-label-medium",lg:"text-mp-label-medium",xl:"text-mp-label-large"},f={xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"},p={static:"",absolute:"absolute inset-x-0 bottom-0 z-30",sticky:"sticky bottom-0 z-30",fixed:"fixed inset-x-0 bottom-0 z-40"};export const MPBottomNavigation=t.forwardRef(function({value:a,defaultValue:l=null,onValueChange:i,position:o="fixed",labels:r="all",size:m="md",divider:d=!1,safeArea:u=!0,disabled:f=!1,label:b,render:x,className:h,children:v,...g},w){const[y,z]=t.useState(l),N=void 0!==a,j=N?a:y,k=t.useCallback(e=>{N||z(e),i?.(e)},[N,i]),C=t.useMemo(()=>({value:j??null,change:k,size:m,labels:r,disabled:f}),[j,k,m,r,f]);return n({render:x??e("nav",{}),ref:w,props:{"aria-label":b,"data-mp-size":m,className:["mp-bottom-navigation bg-mp-surface-container text-mp-on-surface box-border w-full",d?"border-mp-outline-variant border-t":"",p[o],u?"pb-[env(safe-area-inset-bottom)]":"",h??""].filter(Boolean).join(" "),children:e(s.Provider,{value:C,children:e("div",{className:`flex w-full items-stretch ${c[m]}`,children:v})}),...g}})});export const MPBottomNavigationItem=t.forwardRef(function({value:n,icon:c,activeIcon:p,href:b,disabled:x=!1,className:h,children:v,onClick:g,...w},y){const z=t.useContext(s),N=x||z.disabled,j=null!==z.value&&z.value===n,k="all"===z.labels||"selected"===z.labels&&j,C=["mp-bottom-navigation__item group flex min-w-0 flex-1 flex-col items-center justify-center","box-border appearance-none bg-transparent px-1 font-[inherit] no-underline select-none",f[z.size],"outline-mp-secondary focus-visible:outline-2 focus-visible:-outline-offset-2","focus-visible:outline-solid outline-none",N?"text-mp-on-surface/38 cursor-default":j?"text-mp-on-surface cursor-pointer":"text-mp-on-surface-variant cursor-pointer",h??""].filter(Boolean).join(" "),B=a(l,{children:[o(c)||o(p)?a("span",{className:["relative flex shrink-0 items-center justify-center overflow-hidden","rounded-mp-full","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",m[z.size],j&&!N?"bg-mp-secondary-container text-mp-on-secondary-container":""].filter(Boolean).join(" "),children:[N?null:e(i,{}),e("span",{className:"relative flex items-center justify-center",style:{width:d[z.size],height:d[z.size]},children:j?p??c:c})]}):null,o(v)?e("span",{className:k?`max-w-full truncate ${u[z.size]}`:r,children:v}):null]}),M=e=>{N?e.preventDefault():(z.change(n),g?.(e))};return b?e("a",{ref:y,href:N?void 0:b,"aria-current":j?"page":void 0,"aria-disabled":N||void 0,className:C,onClick:M,...w,children:B}):e("button",{ref:y,type:"button",disabled:N,"aria-current":j?"page":void 0,className:C,onClick:M,...w,children:B})});
@@ -0,0 +1,2 @@
1
+ export { MPBottomNavigation, MPBottomNavigationItem } from './MPBottomNavigation';
2
+ export type { MPBottomNavigationItemProps, MPBottomNavigationLabels, MPBottomNavigationProps, MPBottomNavigationValue } from './MPBottomNavigation';
@@ -0,0 +1 @@
1
+ export{MPBottomNavigation,MPBottomNavigationItem}from"./MPBottomNavigation";
@@ -54,6 +54,28 @@ export interface MPBreadcrumbProps extends Omit<React.ComponentPropsWithoutRef<'
54
54
  * @default 'Show hidden steps'
55
55
  */
56
56
  expandLabel?: string;
57
+ /**
58
+ * Publishes the trail as schema.org `BreadcrumbList` microdata, which is what
59
+ * a search engine reads to draw the trail under a result instead of the bare
60
+ * URL.
61
+ *
62
+ * Off by default, and that is not timidity: a page may only claim one
63
+ * breadcrumb trail, so a component that emitted this unasked would collide
64
+ * with the JSON-LD a site already has in its `<head>` — and two trails is
65
+ * worse than none. Turn it on when this component *is* the page's trail.
66
+ *
67
+ * What it adds is attributes and `<meta>`; nothing about the drawing, the
68
+ * layout or the accessibility tree changes.
69
+ *
70
+ * ## It does not survive a fold
71
+ *
72
+ * `BreadcrumbList` positions have to run 1, 2, 3 with nothing missing, and a
73
+ * folded trail does not render the steps behind its `…` — so publishing one
74
+ * would describe a trail that skips from 2 to 6. Turning this on therefore
75
+ * turns `maxItems` off. A trail worth publishing is a trail worth showing.
76
+ * @default false
77
+ */
78
+ structuredData?: boolean;
57
79
  /** The `MPBreadcrumbItem`s. */
58
80
  children?: React.ReactNode;
59
81
  }
@@ -1 +1 @@
1
- import{jsx as e,jsxs as n,Fragment as r}from"react/jsx-runtime";import*as t from"react";import{MPIcon as a}from"../icon/MPIcon";import{ArrowRightIcon as o,ChevronRightIcon as i,MoreIcon as s}from"../../constants/icons";import{accentSlots as l}from"../../internal/accent";import{CONTROL_GAP as c,hasContent as m,PROSE_TEXT as d}from"../../internal/scale";const u=t.createContext({size:"md",last:!1}),p={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2.5",xl:"gap-3"},f={xs:"rounded-mp-xs",sm:"rounded-mp-xs",md:"rounded-mp-xs",lg:"rounded-mp-sm",xl:"rounded-mp-sm"};const h=["chevron","arrow","slash","dot"];export const MPBreadcrumb=t.forwardRef(function({size:r="md",color:c="primary",separator:m="chevron",maxItems:f,itemsBeforeCollapse:x=1,itemsAfterCollapse:b=1,expandable:v=!0,label:g="Breadcrumb",expandLabel:N="Show hidden steps",className:y,style:k,children:j,...w},z){const[B,C]=t.useState(!1),M=t.Children.toArray(j).filter(t.isValidElement),I=M.length,P=M.some(e=>!0===e.props.current),_=!B&&void 0!==f&&I>Math.max(f,1)&&I-x-b>1?[...M.slice(0,Math.max(0,x)),null,...M.slice(I-Math.max(0,b))]:M,A="string"==typeof(F=m)&&h.includes(F)?function(n){switch(n){case"chevron":return e(a,{icon:i,size:"1.1em",className:"rtl:rotate-180"});case"arrow":return e(a,{icon:o,size:"1em",className:"rtl:rotate-180"});case"slash":return e("span",{"aria-hidden":"true",children:"/"});case"dot":return e("span",{"aria-hidden":"true",children:"·"});default:return null}}(m):m;var F;const R=["rounded-mp-xs text-mp-on-surface-variant inline-flex items-center px-0.5","appearance-none border-0 bg-transparent font-[inherit]","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",v?["cursor-pointer hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):""].filter(Boolean).join(" ");return e("nav",{ref:z,"aria-label":g,"data-mp-size":r,className:["mp-breadcrumb flex",d[r],y??""].filter(Boolean).join(" "),style:{...l(c),...k},...w,children:e("ol",{role:"list",className:`flex list-none flex-wrap items-center p-0 ${p[r]}`,children:_.map((o,i)=>n(t.Fragment,{children:[i>0?e("li",{"aria-hidden":"true",className:"text-mp-on-surface-variant flex shrink-0 items-center select-none",children:A}):null,o?e(u.Provider,{value:{size:r,last:!P&&i===_.length-1},children:o}):e("li",{className:"flex shrink-0 items-center",children:v?e("button",{type:"button",className:R,"aria-label":N,onClick:()=>C(!0),children:e(a,{icon:s,size:"1.1em"})}):e("span",{className:R,"aria-hidden":"true",children:e(a,{icon:s,size:"1.1em"})})})]},o?o.key??i:"fold"))})})});export const MPBreadcrumbItem=t.forwardRef(function({href:a,onClick:o,startIcon:i,endIcon:s,current:l,disabled:d=!1,className:p,children:h,...x},b){const{size:v,last:g}=t.useContext(u),N=l??g,y=Boolean(a||o)&&!N&&!d,k=["inline-flex min-w-0 items-center px-1 no-underline","appearance-none border-0 bg-transparent font-[inherit] text-[inherit]",c[v],f[v],"transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",d?"text-mp-on-surface/38 cursor-default":N?"text-mp-on-surface font-medium":y?["text-mp-on-surface-variant cursor-pointer","hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):"text-mp-on-surface-variant"].filter(Boolean).join(" "),j=n(r,{children:[m(i)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:i}):null,e("span",{className:"truncate",children:h}),m(s)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:s}):null]});return e("li",{ref:b,className:["flex min-w-0 items-center",p??""].filter(Boolean).join(" "),...x,children:y&&a?e("a",{href:a,className:k,onClick:o,children:j}):y?e("button",{type:"button",className:k,onClick:o,children:j}):e("span",{className:k,"aria-current":N?"page":void 0,"aria-disabled":d||void 0,children:j})})});
1
+ import{jsx as e,jsxs as n,Fragment as t}from"react/jsx-runtime";import*as r from"react";import{MPIcon as o}from"../icon/MPIcon";import{ArrowRightIcon as i,ChevronRightIcon as a,MoreIcon as s}from"../../constants/icons";import{accentSlots as l}from"../../internal/accent";import{CONTROL_GAP as c,hasContent as m,PROSE_TEXT as d}from"../../internal/scale";const u=r.createContext({size:"md",last:!1,position:null}),p={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2.5",xl:"gap-3"},h={xs:"rounded-mp-xs",sm:"rounded-mp-xs",md:"rounded-mp-xs",lg:"rounded-mp-sm",xl:"rounded-mp-sm"};const f=["chevron","arrow","slash","dot"];export const MPBreadcrumb=r.forwardRef(function({size:t="md",color:c="primary",separator:m="chevron",maxItems:h,itemsBeforeCollapse:x=1,itemsAfterCollapse:b=1,expandable:v=!0,label:g="Breadcrumb",expandLabel:N="Show hidden steps",structuredData:y=!1,className:k,style:B,children:j,...w},z){const[C,P]=r.useState(!1),M=r.Children.toArray(j).filter(r.isValidElement),I=M.length,S=M.some(e=>!0===e.props.current),L=!C&&!y&&void 0!==h&&I>Math.max(h,1)&&I-x-b>1?[...M.slice(0,Math.max(0,x)),null,...M.slice(I-Math.max(0,b))]:M,_="string"==typeof(A=m)&&f.includes(A)?function(n){switch(n){case"chevron":return e(o,{icon:a,size:"1.1em",className:"rtl:rotate-180"});case"arrow":return e(o,{icon:i,size:"1em",className:"rtl:rotate-180"});case"slash":return e("span",{"aria-hidden":"true",children:"/"});case"dot":return e("span",{"aria-hidden":"true",children:"·"});default:return null}}(m):m;var A;const E=r.useMemo(()=>Array.from({length:L.length},(e,n)=>({size:t,last:!S&&n===L.length-1,position:y?n+1:null})),[t,S,L.length,y]),F=["rounded-mp-xs text-mp-on-surface-variant inline-flex items-center px-0.5","appearance-none border-0 bg-transparent font-[inherit]","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",v?["cursor-pointer hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):""].filter(Boolean).join(" ");return e("nav",{ref:z,"aria-label":g,"data-mp-size":t,className:["mp-breadcrumb flex",d[t],k??""].filter(Boolean).join(" "),style:{...l(c),...B},...w,children:e("ol",{role:"list",itemScope:y||void 0,itemType:y?"https://schema.org/BreadcrumbList":void 0,className:`flex list-none flex-wrap items-center p-0 ${p[t]}`,children:L.map((t,i)=>n(r.Fragment,{children:[i>0?e("li",{"aria-hidden":"true",className:"text-mp-on-surface-variant flex shrink-0 items-center select-none",children:_}):null,t?e(u.Provider,{value:E[i],children:t}):e("li",{className:"flex shrink-0 items-center",children:v?e("button",{type:"button",className:F,"aria-label":N,onClick:()=>P(!0),children:e(o,{icon:s,size:"1.1em"})}):e("span",{className:F,"aria-hidden":"true",children:e(o,{icon:s,size:"1.1em"})})})]},t?t.key??i:"fold"))})})});export const MPBreadcrumbItem=r.forwardRef(function({href:o,onClick:i,startIcon:a,endIcon:s,current:l,disabled:d=!1,className:p,children:f,...x},b){const{size:v,last:g,position:N}=r.useContext(u),y=l??g,k=Boolean(o||i)&&!y&&!d,B=null!==N,j=["inline-flex min-w-0 items-center px-1 no-underline","appearance-none border-0 bg-transparent font-[inherit] text-[inherit]",c[v],h[v],"transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",d?"text-mp-on-surface/38 cursor-default":y?"text-mp-on-surface font-medium":k?["text-mp-on-surface-variant cursor-pointer","hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):"text-mp-on-surface-variant"].filter(Boolean).join(" "),w=n(t,{children:[m(a)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:a}):null,e("span",{className:"truncate",itemProp:B?"name":void 0,children:f}),m(s)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:s}):null]});return n("li",{ref:b,itemProp:B?"itemListElement":void 0,itemScope:B||void 0,itemType:B?"https://schema.org/ListItem":void 0,className:["flex min-w-0 items-center",p??""].filter(Boolean).join(" "),...x,children:[B?e("meta",{itemProp:"position",content:String(N)}):null,k&&o?e("a",{href:o,itemProp:B?"item":void 0,className:j,onClick:i,children:w}):k?e("button",{type:"button",className:j,onClick:i,children:w}):e("span",{className:j,"aria-current":y?"page":void 0,"aria-disabled":d||void 0,children:w})]})});
@@ -28,10 +28,15 @@ export interface MPButtonProps extends MPStyleProps, Omit<React.ComponentPropsWi
28
28
  */
29
29
  loading?: boolean;
30
30
  /**
31
- * The accessible name of the spinner, announced while `loading`.
32
- * @default 'Loading'
31
+ * The accessible name of the spinner, announced while `loading`. Defaults to
32
+ * the word for "loading" in `locale`.
33
33
  */
34
34
  loadingLabel?: string;
35
+ /**
36
+ * Which language the spinner's default name is written in. Falls back to the
37
+ * nearest `MPLocaleProvider`, then to English.
38
+ */
39
+ locale?: string;
35
40
  /**
36
41
  * `button`, not `submit`. A native button defaults to submitting the form
37
42
  * around it, which turns every unrelated button inside a form into one that
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Button as n}from"@base-ui/react/button";import{MPIcon as r}from"../icon/MPIcon";import{SpinnerIcon as a}from"../../constants/icons";import{accentSlots as i}from"../../internal/accent";import{MPButtonGroupContext as s}from"../../internal/button-group";import{MPStateLayer as l}from"../../internal/StateLayer";import{CONTROL_GAP as c,CONTROL_HEIGHT as p,CONTROL_ICON as d,CONTROL_PAD_X as m,CONTROL_SQUARE as u,CONTROL_TEXT as f,hasContent as b}from"../../internal/scale";const x={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 hover:shadow-mp-2 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"bg-transparent text-(--_mp-accent)"},g={filled:"bg-mp-on-surface/12 text-mp-on-surface/38",tonal:"bg-mp-on-surface/12 text-mp-on-surface/38",elevated:"bg-mp-on-surface/12 text-mp-on-surface/38 shadow-none",outlined:"border-mp-on-surface/12 border bg-transparent text-mp-on-surface/38",text:"bg-transparent text-mp-on-surface/38"};export const MPButton=o.forwardRef(function({variant:v,size:h,color:w,disabled:y,startIcon:_,endIcon:j,loading:k=!1,loadingLabel:z="Loading",fullWidth:B=!1,type:C="button",className:I,style:L,children:N,onClick:P,...M},D){const R=o.useContext(s),S=v??R?.variant??"filled",W=h??R?.size??"md",$=w??R?.color??"primary",q=y??R?.disabled??!1,A=!b(N);return t(n,{ref:D,type:C,disabled:q,"aria-busy":k||void 0,"aria-disabled":k||void 0,"data-mp-size":W,"data-mp-variant":S,"data-loading":k||void 0,className:["mp-button group relative inline-flex shrink-0 items-center justify-center","rounded-mp-full box-border overflow-hidden align-middle whitespace-nowrap select-none","cursor-pointer appearance-none font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none","transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)",p[W],f[W],c[W],A?`${u[W]} px-0`:m[W],q?g[S]:x[S],q?"cursor-default":"",k?"cursor-progress":"",B?"w-full":"",I??""].filter(Boolean).join(" "),style:{...i($),...L},onClick:e=>{if(k)return e.preventDefault(),void e.stopPropagation();P?.(e)},...M,children:[q?null:e(l,{}),k?e(r,{icon:a,size:d[W],label:z,className:"animate-spin"}):_,N,j]})});
1
+ import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as t from"react";import{Button as n}from"@base-ui/react/button";import{MPIcon as r}from"../icon/MPIcon";import{SpinnerIcon as a}from"../../constants/icons";import{accentSlots as i}from"../../internal/accent";import{MPButtonGroupContext as s}from"../../internal/button-group";import{useMPLocale as l,useMPMessages as c}from"../../internal/locale";import{MPStateLayer as m}from"../../internal/StateLayer";import{CONTROL_GAP as p,CONTROL_HEIGHT as d,CONTROL_ICON as u,CONTROL_PAD_X as f,CONTROL_SQUARE as b,CONTROL_TEXT as x,hasContent as g}from"../../internal/scale";const v={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 hover:shadow-mp-2 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"bg-transparent text-(--_mp-accent)"},h={filled:"bg-mp-on-surface/12 text-mp-on-surface/38",tonal:"bg-mp-on-surface/12 text-mp-on-surface/38",elevated:"bg-mp-on-surface/12 text-mp-on-surface/38 shadow-none",outlined:"border-mp-on-surface/12 border bg-transparent text-mp-on-surface/38",text:"bg-transparent text-mp-on-surface/38"};export const MPButton=t.forwardRef(function({variant:w,size:y,color:_,disabled:j,startIcon:k,endIcon:z,loading:B=!1,loadingLabel:C,locale:I,fullWidth:N=!1,type:P="button",className:L,style:M,children:D,onClick:R,...S},W){const $=l(I),q=c("common",$),A=t.useContext(s),E=w??A?.variant??"filled",F=y??A?.size??"md",G=_??A?.color??"primary",H=j??A?.disabled??!1,J=!g(D);return o(n,{ref:W,type:P,disabled:H,"aria-busy":B||void 0,"aria-disabled":B||void 0,"data-mp-size":F,"data-mp-variant":E,"data-loading":B||void 0,className:["mp-button group relative inline-flex shrink-0 items-center justify-center","rounded-mp-full box-border overflow-hidden align-middle whitespace-nowrap select-none","cursor-pointer appearance-none font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none","transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)",d[F],x[F],p[F],J?`${b[F]} px-0`:f[F],H?h[E]:v[E],H?"cursor-default":"",B?"cursor-progress":"",N?"w-full":"",L??""].filter(Boolean).join(" "),style:{...i(G),...M},onClick:e=>{if(B)return e.preventDefault(),void e.stopPropagation();R?.(e)},...S,children:[H?null:e(m,{}),B?e(r,{icon:a,size:u[F],label:C??q.loading,className:"animate-spin"}):k,D,z]})});
@@ -1 +1 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{MPIconButton as n}from"../icon-button/MPIconButton";import{MPIcon as o}from"../icon/MPIcon";import{ChevronLeftIcon as a,ChevronRightIcon as i}from"../../constants/icons";import{accentSlots as l}from"../../internal/accent";import{CONTROL_ICON as s}from"../../internal/scale";import{CONTAINER_SURFACE as c}from"../../internal/surface";import{VISUALLY_HIDDEN as u}from"../../internal/visually-hidden";const d={xs:"start-1 end-1",sm:"start-1.5 end-1.5",md:"start-2 end-2",lg:"start-3 end-3",xl:"start-4 end-4"},m={xs:{rest:"h-1 w-1",current:"h-1 w-3",gap:"gap-1"},sm:{rest:"h-1 w-1",current:"h-1 w-3.5",gap:"gap-1"},md:{rest:"h-1.5 w-1.5",current:"h-1.5 w-4",gap:"gap-1.5"},lg:{rest:"h-1.5 w-1.5",current:"h-1.5 w-5",gap:"gap-2"},xl:{rest:"h-2 w-2",current:"h-2 w-6",gap:"gap-2"}},f=(e,r)=>`Slide ${e} of ${r}`;export const MPCarousel=t.forwardRef(function({value:p,defaultValue:h=0,onValueChange:b,loop:v=!0,autoPlay:w=!1,interval:x=5e3,arrows:g=!0,indicators:N=!0,variant:y="outlined",size:M="md",color:k="primary",label:j="Carousel",previousLabel:C="Previous slide",nextLabel:P="Next slide",slideLabel:z=f,className:I,style:R,children:$,...L},S){const B=t.Children.toArray($),E=B.length,[V,T]=t.useState(h),W=Math.min(Math.max(p??V,0),Math.max(E-1,0)),A=t.useRef(null),F=t.useRef([]),_=t.useRef(!1),q=t.useRef(!1),D=t.useRef(!1),[G,H]=t.useState(!1),J=t.useCallback((e,r=!1)=>{if(0===E)return;const t=v?(e%E+E)%E:Math.min(Math.max(e,0),E-1);_.current=r,void 0===p&&T(t),t!==W&&b?.(t)},[E,v,p,W,b]);t.useEffect(()=>{if(_.current)return void(_.current=!1);if(!q.current)return void(q.current=!0);F.current[W]?.scrollIntoView({block:"nearest",inline:"start"}),D.current=!0;const e=window.setTimeout(()=>{D.current=!1},700);return()=>window.clearTimeout(e)},[W]),t.useEffect(()=>{if(!w||G||E<2)return;if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;const e=window.setInterval(()=>{document.hidden||J(W+1)},x);return()=>window.clearInterval(e)},[w,G,E,x,W,J]);const K=W<=0,O=W>=E-1;return r("div",{ref:S,role:"region","aria-roledescription":"carousel","aria-label":j,"data-mp-size":M,"data-mp-variant":y,className:["mp-carousel flex w-full flex-col",I??""].filter(Boolean).join(" "),style:{...l(k),...R},onPointerEnter:()=>H(!0),onPointerLeave:()=>H(!1),onFocus:()=>H(!0),onBlur:()=>H(!1),...L,children:[r("div",{className:["relative min-w-0 overflow-hidden","rounded-mp-md box-border",c[y],"text-mp-on-surface"].join(" "),children:[e("div",{ref:A,tabIndex:0,role:"group","aria-label":j,className:["flex min-w-0 snap-x snap-mandatory overflow-x-auto scroll-smooth","motion-reduce:scroll-auto","[scrollbar-width:none] [&::-webkit-scrollbar]:hidden","outline-mp-secondary focus-visible:outline-2 focus-visible:-outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),onScroll:()=>{const e=A.current;if(!e||0===e.clientWidth||D.current)return;const r=Math.round(Math.abs(e.scrollLeft)/e.clientWidth);r!==W&&r>=0&&r<E&&J(r,!0)},children:B.map((r,t)=>e("div",{ref:e=>{F.current[t]=e},role:"group","aria-roledescription":"slide","aria-label":z(t+1,E),className:"w-full shrink-0 grow-0 basis-full snap-start",children:r},t))}),g&&E>1?r("div",{className:`pointer-events-none absolute inset-y-0 flex items-center ${d[M]}`,children:[e(n,{variant:"filled",size:M,color:k,label:C,disabled:!v&&K,className:"pointer-events-auto",icon:e(o,{icon:a,size:s[M],className:"rtl:rotate-180"}),onClick:()=>J(W-1)}),e("span",{className:"flex-1"}),e(n,{variant:"filled",size:M,color:k,label:P,disabled:!v&&O,className:"pointer-events-auto",icon:e(o,{icon:i,size:s[M],className:"rtl:rotate-180"}),onClick:()=>J(W+1)})]}):null]}),N&&E>1?e("div",{className:`flex shrink-0 items-center justify-center pt-2 ${m[M].gap}`,children:B.map((r,t)=>e("button",{type:"button","aria-label":z(t+1,E),"aria-current":t===W?"true":void 0,className:["rounded-mp-full cursor-pointer appearance-none border-0 p-0","transition-[width,background-color] duration-(--mp-sys-motion-duration-short4)","ease-mp-standard motion-reduce:transition-none","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none",t===W?`${m[M].current} bg-(--_mp-accent)`:`${m[M].rest} bg-mp-outline-variant hover:bg-mp-outline`].join(" "),onClick:()=>J(t)},t))}):null,e("span",{className:u,"aria-live":w?"off":"polite",children:E>0?z(W+1,E):""})]})});
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{MPIconButton as n}from"../icon-button/MPIconButton";import{MPIcon as o}from"../icon/MPIcon";import{ChevronLeftIcon as a,ChevronRightIcon as i}from"../../constants/icons";import{accentSlots as l}from"../../internal/accent";import{CONTROL_ICON as s}from"../../internal/scale";import{CONTAINER_SURFACE as c}from"../../internal/surface";import{VISUALLY_HIDDEN as u}from"../../internal/visually-hidden";const d={xs:"start-1 end-1",sm:"start-1.5 end-1.5",md:"start-2 end-2",lg:"start-3 end-3",xl:"start-4 end-4"},m={xs:{rest:"h-1 w-1",current:"h-1 w-3",gap:"gap-1"},sm:{rest:"h-1 w-1",current:"h-1 w-3.5",gap:"gap-1"},md:{rest:"h-1.5 w-1.5",current:"h-1.5 w-4",gap:"gap-1.5"},lg:{rest:"h-1.5 w-1.5",current:"h-1.5 w-5",gap:"gap-2"},xl:{rest:"h-2 w-2",current:"h-2 w-6",gap:"gap-2"}},f=(e,r)=>`Slide ${e} of ${r}`;export const MPCarousel=t.forwardRef(function({value:p,defaultValue:h=0,onValueChange:b,loop:v=!0,autoPlay:w=!1,interval:g=5e3,arrows:x=!0,indicators:N=!0,variant:y="outlined",size:M="md",color:k="primary",label:R="Carousel",previousLabel:j="Previous slide",nextLabel:C="Next slide",slideLabel:P=f,className:z,style:I,children:$,...L},E){const S=t.Children.toArray($),T=S.length,[A,B]=t.useState(h),F=Math.min(Math.max(p??A,0),Math.max(T-1,0)),V=t.useRef(null),W=t.useRef([]),q=t.useRef(!1),_=t.useRef(!1),D=t.useRef(!1),[G,H]=t.useState(!1),J=t.useRef(F),K=t.useRef(b);J.current=F,K.current=b;const O=t.useCallback((e,r=!1)=>{if(0===T)return;const t=v?(e%T+T)%T:Math.min(Math.max(e,0),T-1);q.current=r,void 0===p&&B(t),t!==J.current&&K.current?.(t)},[T,v,p]);t.useEffect(()=>{if(q.current)return void(q.current=!1);if(!_.current)return void(_.current=!0);W.current[F]?.scrollIntoView({block:"nearest",inline:"start"}),D.current=!0;const e=window.setTimeout(()=>{D.current=!1},700);return()=>window.clearTimeout(e)},[F]),t.useEffect(()=>{if(!w||G||T<2)return;if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;const e=window.setInterval(()=>{document.hidden||O(J.current+1)},g);return()=>window.clearInterval(e)},[w,G,T,g,O]);const Q=t.useRef(0);t.useEffect(()=>()=>cancelAnimationFrame(Q.current),[]);const U=F<=0,X=F>=T-1;return r("div",{ref:E,role:"region","aria-roledescription":"carousel","aria-label":R,"data-mp-size":M,"data-mp-variant":y,className:["mp-carousel flex w-full flex-col",z??""].filter(Boolean).join(" "),style:{...l(k),...I},onPointerEnter:()=>H(!0),onPointerLeave:()=>H(!1),onFocus:()=>H(!0),onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||H(!1)},...L,children:[r("div",{className:["relative min-w-0 overflow-hidden","rounded-mp-md box-border",c[y],"text-mp-on-surface"].join(" "),children:[e("div",{ref:V,tabIndex:0,role:"group","aria-label":R,className:["flex min-w-0 snap-x snap-mandatory overflow-x-auto scroll-smooth","motion-reduce:scroll-auto","[scrollbar-width:none] [&::-webkit-scrollbar]:hidden","outline-mp-secondary focus-visible:outline-2 focus-visible:-outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),onScroll:()=>{Q.current||(Q.current=requestAnimationFrame(()=>{Q.current=0;const e=V.current;if(!e||0===e.clientWidth||D.current)return;const r=Math.round(Math.abs(e.scrollLeft)/e.clientWidth);r!==J.current&&r>=0&&r<T&&O(r,!0)}))},children:S.map((r,t)=>e("div",{ref:e=>{W.current[t]=e,W.current.length=T},role:"group","aria-roledescription":"slide","aria-label":P(t+1,T),className:"w-full shrink-0 grow-0 basis-full snap-start",children:r},t))}),x&&T>1?r("div",{className:`pointer-events-none absolute inset-y-0 flex items-center ${d[M]}`,children:[e(n,{variant:"filled",size:M,color:k,label:j,disabled:!v&&U,className:"pointer-events-auto",icon:e(o,{icon:a,size:s[M],className:"rtl:rotate-180"}),onClick:()=>O(F-1)}),e("span",{className:"flex-1"}),e(n,{variant:"filled",size:M,color:k,label:C,disabled:!v&&X,className:"pointer-events-auto",icon:e(o,{icon:i,size:s[M],className:"rtl:rotate-180"}),onClick:()=>O(F+1)})]}):null]}),N&&T>1?e("div",{className:`flex shrink-0 items-center justify-center pt-2 ${m[M].gap}`,children:S.map((r,t)=>e("button",{type:"button","aria-label":P(t+1,T),"aria-current":t===F?"true":void 0,className:["rounded-mp-full cursor-pointer appearance-none border-0 p-0","transition-[width,background-color] duration-(--mp-sys-motion-duration-short4)","ease-mp-standard motion-reduce:transition-none","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none",t===F?`${m[M].current} bg-(--_mp-accent)`:`${m[M].rest} bg-mp-outline-variant hover:bg-mp-outline`].join(" "),onClick:()=>O(t)},t))}):null,e("span",{className:u,"aria-live":w?"off":"polite",children:T>0?P(F+1,T):""})]})});
@@ -52,8 +52,8 @@ export interface MPCheckboxProps {
52
52
  /** The value submitted when the box is ticked. */
53
53
  value?: string;
54
54
  /**
55
- * The id put on the control and pointed at by the label. Derived from `name`
56
- * when omitted, and generated when there is no name either.
55
+ * The id put on the control and pointed at by the label. Generated when it is
56
+ * left out.
57
57
  */
58
58
  id?: string;
59
59
  }
@@ -1 +1 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{Checkbox as t}from"@base-ui/react/checkbox";import{Field as n}from"@base-ui/react/field";import{MPIcon as o}from"../icon/MPIcon";import{CheckIcon as i,RemoveIcon as c}from"../../constants/icons";import{accentSlots as s}from"../../internal/accent";import{MPStateLayer as d}from"../../internal/StateLayer";import{MPSupportingText as l}from"../../internal/SupportingText";import{PROSE_TEXT as m,hasContent as p}from"../../internal/scale";const h={xs:{box:"size-3.5",halo:"size-8",glyph:12},sm:{box:"size-4",halo:"size-9",glyph:14},md:{box:"size-[18px]",halo:"size-10",glyph:16},lg:{box:"size-5",halo:"size-11",glyph:18},xl:{box:"size-[22px]",halo:"size-12",glyph:20}};export const MPCheckbox=a.forwardRef(function({checked:u,defaultChecked:b,onCheckedChange:f,indeterminate:x=!1,label:g,description:k,errorMessage:y,size:z="md",color:j="primary",required:_=!1,disabled:v=!1,readOnly:C=!1,name:N,value:M,id:I},R){const q=p(y),w=q?"error":j,L=h[z],O=a.useId(),P=I??`mp-checkbox-${N??O}`;return e(n.Root,{className:"mp-checkbox inline-block align-top",disabled:v,invalid:q,"data-mp-size":z,style:s(w),children:r("div",{className:["flex items-start gap-3",m[z]].join(" "),children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:r(t.Root,{ref:R,id:P,name:N,value:M,checked:u,defaultChecked:b,indeterminate:x,required:_,disabled:v,readOnly:C,onCheckedChange:e=>f?.(e),className:["mp-checkbox__tick group relative inline-flex shrink-0 items-center","box-border justify-center border-2 p-0","rounded-[calc(var(--mp-sys-shape-corner-extra-small)/2)]","appearance-none bg-transparent font-[inherit] outline-none","transition-[background-color,border-color]","duration-(--mp-sys-motion-duration-short4)",L.box,v?["border-mp-on-surface/38 cursor-default","data-checked:bg-mp-on-surface/38 data-checked:border-transparent","data-indeterminate:bg-mp-on-surface/38 data-indeterminate:border-transparent"].join(" "):[C?"cursor-default":"cursor-pointer",q?"border-mp-error":"border-mp-on-surface-variant","data-checked:border-transparent data-checked:bg-(--_mp-accent)","data-checked:text-(--_mp-on-accent)","data-indeterminate:border-transparent data-indeterminate:bg-(--_mp-accent)","data-indeterminate:text-(--_mp-on-accent)"].join(" ")].join(" "),children:[v?null:e(d,{layer:["top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full",L.halo,"bg-mp-on-surface","group-data-checked:bg-(--_mp-accent)","group-data-indeterminate:bg-(--_mp-accent)"].join(" ")}),e(t.Indicator,{className:"flex items-center justify-center",children:e(o,{icon:x?c:i,size:L.glyph,strokeWidth:3})})]})}),p(g)||p(k)||q?r("span",{className:"flex min-w-0 flex-col gap-0.5",children:[p(g)?r(n.Label,{htmlFor:P,className:["leading-[1.4]",v?"text-mp-on-surface/38 cursor-default":C?"text-mp-on-surface":"text-mp-on-surface cursor-pointer"].join(" "),children:[g,_?e("span",{"aria-hidden":"true",children:" *"}):null]}):null,e(l,{description:k,errorMessage:y})]}):null]})})});
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{Checkbox as t}from"@base-ui/react/checkbox";import{Field as n}from"@base-ui/react/field";import{MPIcon as o}from"../icon/MPIcon";import{CheckIcon as i,RemoveIcon as c}from"../../constants/icons";import{accentSlots as s}from"../../internal/accent";import{MPStateLayer as d}from"../../internal/StateLayer";import{MPSupportingText as l}from"../../internal/SupportingText";import{PROSE_TEXT as m,hasContent as p}from"../../internal/scale";const h={xs:{box:"size-3.5",halo:"size-8",glyph:12},sm:{box:"size-4",halo:"size-9",glyph:14},md:{box:"size-[18px]",halo:"size-10",glyph:16},lg:{box:"size-5",halo:"size-11",glyph:18},xl:{box:"size-[22px]",halo:"size-12",glyph:20}};export const MPCheckbox=a.forwardRef(function({checked:u,defaultChecked:f,onCheckedChange:b,indeterminate:x=!1,label:g,description:k,errorMessage:y,size:z="md",color:j="primary",required:_=!1,disabled:v=!1,readOnly:C=!1,name:N,value:M,id:I},R){const q=p(y),w=q?"error":j,L=h[z],O=a.useId(),P=I??O;return e(n.Root,{className:"mp-checkbox inline-block align-top",disabled:v,invalid:q,"data-mp-size":z,style:s(w),children:r("div",{className:["flex items-start gap-3",m[z]].join(" "),children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:r(t.Root,{ref:R,id:P,name:N,value:M,checked:u,defaultChecked:f,indeterminate:x,required:_,disabled:v,readOnly:C,onCheckedChange:e=>b?.(e),className:["mp-checkbox__tick group relative inline-flex shrink-0 items-center","box-border justify-center border-2 p-0","rounded-[calc(var(--mp-sys-shape-corner-extra-small)/2)]","appearance-none bg-transparent font-[inherit] outline-none","transition-[background-color,border-color]","duration-(--mp-sys-motion-duration-short4)",L.box,v?["border-mp-on-surface/38 cursor-default","data-checked:bg-mp-on-surface/38 data-checked:border-transparent","data-indeterminate:bg-mp-on-surface/38 data-indeterminate:border-transparent"].join(" "):[C?"cursor-default":"cursor-pointer",q?"border-mp-error":"border-mp-on-surface-variant","data-checked:border-transparent data-checked:bg-(--_mp-accent)","data-checked:text-(--_mp-on-accent)","data-indeterminate:border-transparent data-indeterminate:bg-(--_mp-accent)","data-indeterminate:text-(--_mp-on-accent)"].join(" ")].join(" "),children:[v?null:e(d,{layer:["top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full",L.halo,"bg-mp-on-surface","group-data-checked:bg-(--_mp-accent)","group-data-indeterminate:bg-(--_mp-accent)"].join(" ")}),e(t.Indicator,{className:"flex items-center justify-center",children:e(o,{icon:x?c:i,size:L.glyph,strokeWidth:3})})]})}),p(g)||p(k)||q?r("span",{className:"flex min-w-0 flex-col gap-0.5",children:[p(g)?r(n.Label,{htmlFor:P,className:["leading-[1.4]",v?"text-mp-on-surface/38 cursor-default":C?"text-mp-on-surface":"text-mp-on-surface cursor-pointer"].join(" "),children:[g,_?e("span",{"aria-hidden":"true",children:" *"}):null]}):null,e(l,{description:k,errorMessage:y})]}):null]})})});
@@ -31,17 +31,27 @@ export interface MPChipProps extends Omit<React.ComponentPropsWithoutRef<'span'>
31
31
  */
32
32
  onDelete?: (event: React.MouseEvent<HTMLButtonElement>) => void;
33
33
  /**
34
- * Accessible name of the delete button.
35
- * @default 'Remove'
34
+ * Accessible name of the delete button. Defaults to the word for "remove" in
35
+ * `locale`.
36
36
  */
37
37
  deleteLabel?: string;
38
+ /**
39
+ * Which language the delete button's default name is written in. Falls back
40
+ * to the nearest `MPLocaleProvider`, then to English.
41
+ */
42
+ locale?: string;
38
43
  /**
39
44
  * Marks the chip as chosen — a filter that is on.
40
45
  *
41
46
  * MD3's selected filter chip fills with the container tone of its own family
42
47
  * rather than changing family, which is what this does: a filter that is on is
43
48
  * still the same filter.
44
- * @default false
49
+ *
50
+ * Deliberately **without a default**, which is the one thing about it worth
51
+ * knowing. Passing it — either way round — is what says this chip is a toggle,
52
+ * and only then is it announced as one. A chip that merely has an `onClick`
53
+ * is an action, and an action announced as "not pressed" is a screen reader
54
+ * describing a state the chip does not have.
45
55
  */
46
56
  selected?: boolean;
47
57
  /** Unavailable. Drops the accent family, as everywhere else in the library. */
@@ -1 +1 @@
1
- import{jsx as e,Fragment as t,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{MPIcon as a}from"../icon/MPIcon";import{CloseIcon as r}from"../../constants/icons";import{accentSlots as i}from"../../internal/accent";import{hasContent as l}from"../../internal/scale";import{MPStateLayer as c}from"../../internal/StateLayer";const s={xs:"h-6",sm:"h-7",md:"h-8",lg:"h-10",xl:"h-12"},m={xs:"text-mp-label-medium",sm:"text-mp-label-medium",md:"text-mp-label-large",lg:"text-mp-label-large",xl:"text-mp-title-medium"},p={xs:"px-2",sm:"px-3",md:"px-4",lg:"px-5",xl:"px-6"},d={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2",xl:"gap-2.5"},u={xs:"rounded-mp-xs",sm:"rounded-mp-sm",md:"rounded-mp-sm",lg:"rounded-mp-sm",xl:"rounded-mp-md"},x={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-mp-on-surface-variant",outlined:"border-mp-outline text-mp-on-surface-variant border bg-transparent",text:"text-mp-on-surface-variant bg-transparent"},f={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",outlined:"border-mp-outline bg-(--_mp-accent-container) text-(--_mp-on-accent-container) border",text:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)"},b={filled:"bg-mp-on-surface/12 text-mp-on-surface/38",tonal:"bg-mp-on-surface/12 text-mp-on-surface/38",elevated:"bg-mp-on-surface/12 text-mp-on-surface/38 shadow-none",outlined:"border-mp-on-surface/12 text-mp-on-surface/38 border bg-transparent",text:"bg-transparent text-mp-on-surface/38"},g=["ms-0.5 -me-1 inline-flex shrink-0 cursor-pointer items-center justify-center","rounded-mp-full size-[1.35em] opacity-70","transition-opacity duration-(--mp-sys-motion-duration-short4)","hover:opacity-100 focus-visible:opacity-100","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none","disabled:cursor-default disabled:opacity-38"].join(" "),h=["group relative flex min-w-0 flex-1 cursor-pointer items-center justify-center","self-stretch rounded-[inherit] font-[inherit] text-[inherit]","appearance-none border-0 bg-transparent","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" ");export const MPChip=o.forwardRef(function({variant:o="outlined",size:v="md",color:y="primary",startIcon:_,endIcon:w,count:j,onDelete:k,deleteLabel:N="Remove",selected:z=!1,disabled:C=!1,className:I,style:$,children:B,onClick:L,...M},P){const R=Boolean(L)&&!C,D=["mp-chip relative inline-flex max-w-full shrink-0 items-center","box-border overflow-hidden align-middle leading-none whitespace-nowrap select-none","transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)",s[v],m[v],d[v],u[v],C?b[o]:z?f[o]:x[o],R?"ps-0":p[v],k?"pe-2":R?"pe-0":"",I??""].filter(Boolean).join(" "),F=n(t,{children:[_,l(B)?e("span",{className:"min-w-0 truncate",children:B}):null,w,l(j)?e("span",{className:["rounded-mp-full ms-0.5 inline-flex shrink-0 items-center justify-center px-1.5 py-px","text-[0.85em] leading-none font-medium tabular-nums","filled"===o?"bg-(--_mp-on-accent)/20 text-(--_mp-on-accent)":"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)"].join(" "),children:j}):null]});return n("span",{ref:P,"data-mp-size":v,"data-mp-variant":o,"data-selected":z||void 0,className:D,style:{...i(y),...$},"aria-disabled":!(!C||R)||void 0,...M,children:[R?n("button",{type:"button","aria-pressed":z,className:`${h} ${d[v]} ${p[v]}`,onClick:L,children:[e(c,{}),F]}):F,k?e("button",{type:"button","aria-label":N,disabled:C,className:g,onClick:k,children:e(a,{icon:r,size:"1em"})}):null]})});
1
+ import{jsx as e,Fragment as t,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{MPIcon as a}from"../icon/MPIcon";import{CloseIcon as r}from"../../constants/icons";import{accentSlots as i}from"../../internal/accent";import{useMPLocale as l,useMPMessages as c}from"../../internal/locale";import{hasContent as s}from"../../internal/scale";import{MPStateLayer as m}from"../../internal/StateLayer";const p={xs:"h-6",sm:"h-7",md:"h-8",lg:"h-10",xl:"h-12"},d={xs:"text-mp-label-medium",sm:"text-mp-label-medium",md:"text-mp-label-large",lg:"text-mp-label-large",xl:"text-mp-title-medium"},u={xs:"px-2",sm:"px-3",md:"px-4",lg:"px-5",xl:"px-6"},f={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2",xl:"gap-2.5"},x={xs:"rounded-mp-xs",sm:"rounded-mp-sm",md:"rounded-mp-sm",lg:"rounded-mp-sm",xl:"rounded-mp-md"},b={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-mp-on-surface-variant",outlined:"border-mp-outline text-mp-on-surface-variant border bg-transparent",text:"text-mp-on-surface-variant bg-transparent"},g={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",outlined:"border-mp-outline bg-(--_mp-accent-container) text-(--_mp-on-accent-container) border",text:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)"},h={filled:"bg-mp-on-surface/12 text-mp-on-surface/38",tonal:"bg-mp-on-surface/12 text-mp-on-surface/38",elevated:"bg-mp-on-surface/12 text-mp-on-surface/38 shadow-none",outlined:"border-mp-on-surface/12 text-mp-on-surface/38 border bg-transparent",text:"bg-transparent text-mp-on-surface/38"},v=["ms-0.5 -me-1 inline-flex shrink-0 cursor-pointer items-center justify-center","rounded-mp-full size-[1.35em] opacity-70","transition-opacity duration-(--mp-sys-motion-duration-short4)","hover:opacity-100 focus-visible:opacity-100","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none","disabled:cursor-default disabled:opacity-38"].join(" "),y=["group relative flex min-w-0 flex-1 cursor-pointer items-center justify-center","self-stretch rounded-[inherit] font-[inherit] text-[inherit]","appearance-none border-0 bg-transparent","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" ");export const MPChip=o.forwardRef(function({variant:o="outlined",size:_="md",color:w="primary",startIcon:j,endIcon:k,count:N,onDelete:z,deleteLabel:C,locale:I,selected:$,disabled:B=!1,className:L,style:M,children:P,onClick:D,...F},R){const S=l(I),q=c("common",S),A=Boolean(D)&&!B,E=["mp-chip relative inline-flex max-w-full shrink-0 items-center","box-border overflow-hidden align-middle leading-none whitespace-nowrap select-none","transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)",p[_],d[_],f[_],x[_],B?h[o]:$?g[o]:b[o],A?"ps-0":u[_],z?"pe-2":A?"pe-0":"",L??""].filter(Boolean).join(" "),G=n(t,{children:[j,s(P)?e("span",{className:"min-w-0 truncate",children:P}):null,k,s(N)?e("span",{className:["rounded-mp-full ms-0.5 inline-flex shrink-0 items-center justify-center px-1.5 py-px","text-[0.85em] leading-none font-medium tabular-nums","filled"===o?"bg-(--_mp-on-accent)/20 text-(--_mp-on-accent)":"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)"].join(" "),children:N}):null]});return n("span",{ref:R,"data-mp-size":_,"data-mp-variant":o,"data-selected":$||void 0,className:E,style:{...i(w),...M},"aria-disabled":!(!B||A)||void 0,...F,children:[A?n("button",{type:"button","aria-pressed":$,className:`${y} ${f[_]} ${u[_]}`,onClick:D,children:[e(m,{}),G]}):G,z?e("button",{type:"button","aria-label":C??q.remove,disabled:B,className:v,onClick:z,children:e(a,{icon:r,size:"1em"})}):null]})});
@@ -50,8 +50,26 @@ export interface MPColorPickerProps extends MPStyleProps {
50
50
  * @default true
51
51
  */
52
52
  editable?: boolean;
53
- /** Label in the outline's notch, or above the panel when `inline`. */
53
+ /**
54
+ * Label for the picker, drawn in the outline's notch — or above the panel when
55
+ * `inline`, which has no notch to draw it in. While nothing is chosen and the
56
+ * trigger is unfocused it rests on the trigger's own line instead. See
57
+ * `floatingLabel`.
58
+ */
54
59
  label?: React.ReactNode;
60
+ /**
61
+ * Whether the label rests on the trigger's line while there is nothing to make
62
+ * room for, and rises into the notch on focus or on the first colour.
63
+ *
64
+ * The swatch comes down with it. The swatch is the value drawn rather than an
65
+ * affordance — with no colour in the picker it is an empty ring — so it is the
66
+ * one leading mark in the library that gives its place up to a resting label
67
+ * rather than holding the label out of it.
68
+ *
69
+ * Ignored when `inline`, which has no trigger for a label to rest on.
70
+ * @default true
71
+ */
72
+ floatingLabel?: boolean;
55
73
  /** The line under the control. Replaced by `errorMessage` when there is one. */
56
74
  description?: React.ReactNode;
57
75
  /**
@@ -77,8 +95,8 @@ export interface MPColorPickerProps extends MPStyleProps {
77
95
  /** Overrides for the accessible names, one at a time. */
78
96
  labels?: Partial<MPColorPickerLabels>;
79
97
  /**
80
- * The id put on the trigger and pointed at by the label. Derived from `name`
81
- * when omitted, and generated when there is no name either.
98
+ * The id put on the trigger and pointed at by the label. Generated when it is
99
+ * left out.
82
100
  */
83
101
  id?: string;
84
102
  className?: string;