material-plus-ui 1.10.0 → 1.12.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 (93) hide show
  1. package/README.md +17 -12
  2. package/dist/a2ui/catalog.d.ts +8 -5
  3. package/dist/a2ui/catalog.js +1 -1
  4. package/dist/a2ui/components/MPA2uiList.js +1 -1
  5. package/dist/a2ui/extended/api.d.ts +142 -810
  6. package/dist/a2ui/index.d.ts +8 -6
  7. package/dist/components/accordion/MPAccordion.js +1 -1
  8. package/dist/components/badge/MPBadge.d.ts +7 -6
  9. package/dist/components/button/MPButton.d.ts +5 -3
  10. package/dist/components/chip/MPChip.d.ts +1 -1
  11. package/dist/components/chip/MPChip.js +1 -1
  12. package/dist/components/collapsible/MPCollapsible.js +1 -1
  13. package/dist/components/color-picker/MPColorPicker.js +1 -1
  14. package/dist/components/combobox/MPCombobox.d.ts +11 -4
  15. package/dist/components/combobox/MPCombobox.js +1 -1
  16. package/dist/components/command-palette/MPCommandPalette.d.ts +3 -1
  17. package/dist/components/container/MPContainer.d.ts +1 -1
  18. package/dist/components/data-table/MPDataTable.d.ts +3 -2
  19. package/dist/components/data-table/MPDataTable.js +1 -1
  20. package/dist/components/date-picker/MPDatePicker.js +1 -1
  21. package/dist/components/date-range-picker/MPDateRangePicker.js +1 -1
  22. package/dist/components/date-time-picker/MPDateTimePicker.js +1 -1
  23. package/dist/components/dialog/MPDialog.d.ts +3 -2
  24. package/dist/components/floating-action-button/MPFloatingActionButton.d.ts +3 -1
  25. package/dist/components/floating-bottom-navigation/MPFloatingBottomNavigation.d.ts +10 -1
  26. package/dist/components/floating-bottom-navigation/MPFloatingBottomNavigation.js +1 -1
  27. package/dist/components/hover-card/MPHoverCard.d.ts +8 -7
  28. package/dist/components/icon-button/MPIconButton.js +1 -1
  29. package/dist/components/list/MPList.d.ts +3 -2
  30. package/dist/components/pagination/MPPagination.d.ts +4 -4
  31. package/dist/components/progress-box/MPProgressBox.js +1 -1
  32. package/dist/components/progress-linear/MPProgressLinear.d.ts +4 -3
  33. package/dist/components/segmented-button/MPSegmentedButton.js +1 -1
  34. package/dist/components/sidebar/MPSidebar.d.ts +4 -2
  35. package/dist/components/snackbar/MPSnackbar.d.ts +8 -6
  36. package/dist/components/stepper/MPStepper.d.ts +9 -7
  37. package/dist/components/stepper/MPStepper.js +1 -1
  38. package/dist/components/table/MPTable.d.ts +7 -3
  39. package/dist/components/text-field/MPTextField.d.ts +9 -0
  40. package/dist/components/text-field/MPTextField.js +1 -1
  41. package/dist/components/time-picker/MPTimePicker.js +1 -1
  42. package/dist/components/toolbar/MPToolbar.d.ts +3 -3
  43. package/dist/components/tooltip/MPTooltip.d.ts +6 -0
  44. package/dist/components/tree-select/MPTreeSelect.d.ts +12 -2
  45. package/dist/components/tree-select/MPTreeSelect.js +1 -1
  46. package/dist/internal/FieldOutline.d.ts +11 -1
  47. package/dist/internal/FieldOutline.js +1 -1
  48. package/dist/internal/FieldValue.d.ts +35 -0
  49. package/dist/internal/FieldValue.js +2 -0
  50. package/dist/internal/Picker.d.ts +24 -5
  51. package/dist/internal/Picker.js +1 -1
  52. package/dist/internal/fold.d.ts +45 -0
  53. package/dist/internal/fold.js +2 -0
  54. package/dist/internal/i18n.d.ts +6 -0
  55. package/dist/internal/messages/common.js +1 -1
  56. package/dist/internal/table.d.ts +4 -4
  57. package/dist/locales/ar.js +1 -1
  58. package/dist/locales/de.js +1 -1
  59. package/dist/locales/es.js +1 -1
  60. package/dist/locales/fr.js +1 -1
  61. package/dist/locales/hi.js +1 -1
  62. package/dist/locales/id.js +1 -1
  63. package/dist/locales/it.js +1 -1
  64. package/dist/locales/ja.js +1 -1
  65. package/dist/locales/ko.js +1 -1
  66. package/dist/locales/nl.js +1 -1
  67. package/dist/locales/pl.js +1 -1
  68. package/dist/locales/pt.js +1 -1
  69. package/dist/locales/ru.js +1 -1
  70. package/dist/locales/th.js +1 -1
  71. package/dist/locales/tr.js +1 -1
  72. package/dist/locales/vi.js +1 -1
  73. package/dist/locales/zh-hans.js +1 -1
  74. package/dist/locales/zh-hant.js +1 -1
  75. package/dist/styles/accordion.css +1 -1
  76. package/dist/styles/calendar.css +1 -1
  77. package/dist/styles/collapsible.css +1 -1
  78. package/dist/styles/color-picker.css +1 -1
  79. package/dist/styles/combobox.css +1 -1
  80. package/dist/styles/date-picker.css +1 -1
  81. package/dist/styles/date-range-picker.css +1 -1
  82. package/dist/styles/date-time-picker.css +1 -1
  83. package/dist/styles/number-field.css +1 -1
  84. package/dist/styles/progress-linear.css +1 -1
  85. package/dist/styles/segmented-button.css +1 -1
  86. package/dist/styles/select.css +1 -1
  87. package/dist/styles/stepper.css +1 -1
  88. package/dist/styles/text-field.css +1 -1
  89. package/dist/styles/time-picker.css +1 -1
  90. package/dist/styles/tree-select.css +1 -1
  91. package/dist/styles.css +1 -1
  92. package/dist/tailwind.css +62 -25
  93. package/package.json +24 -30
@@ -89,13 +89,14 @@ export interface MPHoverCardProps extends Omit<React.ComponentPropsWithoutRef<'d
89
89
  *
90
90
  * ## Because it is uninvited, it is never the only way to anything
91
91
  *
92
- * A keyboard with no hover, a touchscreen with no pointer, and a screen reader
93
- * all arrive by the trigger's own route instead. So whatever is in here has to
94
- * exist on the page the trigger leads to as well. Treat it as a shortcut for
95
- * the reader who has a pointer, never as the place a fact lives.
92
+ * A touchscreen with no pointer arrives by the trigger's own route instead, and
93
+ * a screen reader is not taken into the card when it opens. So whatever is in
94
+ * here has to exist on the page the trigger leads to as well. Treat it as a
95
+ * shortcut, never as the place a fact lives.
96
96
  *
97
- * That is also why there is no keyboard equivalent bolted on. A card that
98
- * opened on focus would interrupt every keyboard reader tabbing through a
99
- * paragraph of links, which is a worse answer than not opening at all.
97
+ * It does open on keyboard focus, after the same `delay` a pointer waits, which
98
+ * is Base UI's behaviour. That delay is also why tabbing through a paragraph of
99
+ * links does not open a card for each of them: only the link that focus rests
100
+ * on shows one.
100
101
  */
101
102
  export declare function MPHoverCard({ trigger, title, description, children, side, align, sideOffset, alignOffset, arrow, open, defaultOpen, onOpenChange, delay, closeDelay, width, size: sizeProp, density: densityProp, className, style, ...props }: MPHoverCardProps): React.JSX.Element;
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as t}from"react/jsx-runtime";import*as r from"react";import{MPButton as o}from"../button/MPButton.js";export const MPIconButton=/*@__PURE__*/r.forwardRef(function({icon:r,label:a,variant:n="text",...e},i){return t(o,{ref:i,"aria-label":a,variant:n,startIcon:r,...e})});
2
+ import{jsx as t}from"react/jsx-runtime";import*as r from"react";import{MPButton as o}from"../button/MPButton.js";import{MPButtonGroupContext as n}from"../../internal/button-group.js";export const MPIconButton=/*@__PURE__*/r.forwardRef(function({icon:a,label:e,variant:i,...s},m){const u=r.useContext(n);return t(o,{ref:m,"aria-label":e,variant:i??u?.variant??"text",startIcon:a,...s})});
@@ -25,8 +25,9 @@ export interface MPListProps extends Omit<React.ComponentPropsWithoutRef<'ul'>,
25
25
  */
26
26
  size?: MPSize;
27
27
  /**
28
- * Which accent family a selected or hovered row reads. The sheet itself stays
29
- * neutral whatever this is.
28
+ * Which accent family a selected row reads. The sheet stays neutral whatever
29
+ * this is, and so does the hover: the state layer is the row's own ink, as it
30
+ * is everywhere in the library.
30
31
  * @default 'primary'
31
32
  */
32
33
  color?: MPColor;
@@ -97,10 +97,10 @@ export interface MPPaginationProps extends MPStyleProps, Omit<React.ComponentPro
97
97
  *
98
98
  * A `<nav>` around a `<ul>`: a named landmark a screen reader can skip, holding
99
99
  * a list whose length says how far the pages go, with `aria-current="page"`
100
- * marking where the reader is. The ellipsis is a `<span>` rather than a disabled
101
- * button — it is not a control that happens to be unavailable, it is
102
- * punctuation — and it is `aria-hidden`, because "horizontal ellipsis" read out
103
- * between two numbers is noise.
100
+ * marking where the reader is. The ellipsis is a list item with no button in it
101
+ * rather than a disabled button — it is not a control that happens to be
102
+ * unavailable, it is punctuation — and it is `aria-hidden`, because "horizontal
103
+ * ellipsis" read out between two numbers is noise.
104
104
  *
105
105
  * ## Why it builds its own cells
106
106
  *
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Progress as n}from"@base-ui/react/progress";import{accentSlots as r}from"../../internal/accent.js";import{VISUALLY_HIDDEN as s}from"../../internal/visually-hidden.js";import{META_TEXT as t,STACK_GAP as o}from"../../internal/scale.js";import{SEGMENT_GAP as i,SEGMENT_RADIUS as m,SEGMENT_SIZE as c,progressAriaText as u,progressFraction as f,progressText as p}from"../../internal/progress.js";import{useMPColor as d,useMPSize as h}from"../../internal/config.js";import{useMPLocale as x}from"../../internal/locale.js";import{checkServerLocale as j,intlLocale as b}from"../../internal/intl.js";export const MPProgressBox=/*@__PURE__*/l.forwardRef(function({size:l,color:g,count:v=4,value:y=null,min:N=0,max:w=100,label:M,hideLabel:B=!1,showValue:L=!1,format:V,locale:_,className:k,style:z},A){const P=h(l),R=d(g),T=f(y,N,w),$=null===T,q=void 0!==V,C=x(_);q&&j(C);const D=B?null:M,E=Math.max(1,Math.floor(v));return a(n.Root,{ref:A,value:null===T?null:y??null,min:N,max:w,format:V,locale:b(C),getAriaValueText:u(T,q),"data-mp-size":P,className:["mp-progress-box inline-flex flex-col",o[P],k??""].filter(Boolean).join(" "),style:{...r(R),...z},children:[B&&M?e(n.Label,{className:s,children:M}):null,D||L?a("div",{className:["flex items-baseline gap-2",D?"justify-between":"justify-end",t].join(" "),children:[D?e(n.Label,{className:"text-mp-on-surface min-w-0 truncate",children:D}):null,L?e(n.Value,{className:"text-mp-on-surface-variant shrink-0 tabular-nums",children:e=>p(T,e,q)}):null]}):null,e(n.Track,{className:`flex ${i[P]}`,children:Array.from({length:E},(a,l)=>e("span",{className:["bg-mp-on-surface/12 relative overflow-hidden",c[P],m[P],$?"mp-progress-segment-wave bg-(--_mp-accent)":""].filter(Boolean).join(" "),style:$?{"--_mp-index":l}:void 0,children:$?null:e("span",{className:"absolute inset-y-0 start-0 bg-(--_mp-accent) transition-[width] duration-(--mp-sys-motion-duration-short4) ease-mp-standard",style:{width:`${Math.min(100,Math.max(0,100*(T*E-l)))}%`}})},l))})]})});
2
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Progress as n}from"@base-ui/react/progress";import{accentSlots as r}from"../../internal/accent.js";import{VISUALLY_HIDDEN as s}from"../../internal/visually-hidden.js";import{META_TEXT as t,STACK_GAP as o}from"../../internal/scale.js";import{SEGMENT_GAP as i,SEGMENT_RADIUS as m,SEGMENT_SIZE as c,progressAriaText as u,progressFraction as f,progressText as p}from"../../internal/progress.js";import{useMPColor as d,useMPSize as h}from"../../internal/config.js";import{useMPLocale as x}from"../../internal/locale.js";import{checkServerLocale as j,intlLocale as b}from"../../internal/intl.js";export const MPProgressBox=/*@__PURE__*/l.forwardRef(function({size:l,color:g,count:v=4,value:y=null,min:N=0,max:w=100,label:M,hideLabel:B=!1,showValue:L=!1,format:V,locale:_,className:k,style:z},A){const P=h(l),R=d(g),T=f(y,N,w),$=null===T,q=void 0!==V,C=x(_);q&&j(C);const D=B?null:M,E=Math.max(1,Math.floor(v));return a(n.Root,{ref:A,value:null===T?null:y??null,min:N,max:w,format:V,locale:b(C),getAriaValueText:u(T,q),"data-mp-size":P,className:["mp-progress-box inline-flex flex-col",o[P],k??""].filter(Boolean).join(" "),style:{...r(R),...z},children:[B&&M?e(n.Label,{className:s,children:M}):null,D||L?a("div",{className:["flex items-baseline gap-2",D?"justify-between":"justify-end",t].join(" "),children:[D?e(n.Label,{className:"text-mp-on-surface min-w-0 truncate",children:D}):null,L?e(n.Value,{className:"text-mp-on-surface-variant shrink-0 tabular-nums",children:e=>p(T,e,q)}):null]}):null,e(n.Track,{className:`flex ${i[P]}`,children:Array.from({length:E},(a,l)=>e("span",{className:["relative overflow-hidden",c[P],m[P],$?"mp-progress-segment-wave bg-(--_mp-accent)":"bg-mp-on-surface/12"].filter(Boolean).join(" "),style:$?{"--_mp-index":l}:void 0,children:$?null:e("span",{className:"absolute inset-y-0 start-0 bg-(--_mp-accent) transition-[width] duration-(--mp-sys-motion-duration-short4) ease-mp-standard",style:{width:`${Math.min(100,Math.max(0,100*(T*E-l)))}%`}})},l))})]})});
@@ -16,9 +16,10 @@ export interface MPProgressLinearProps extends MPProgressProps {
16
16
  *
17
17
  * It is the only one that can show *how much* is left at a glance, because length
18
18
  * is the one quantity a reader compares without counting. MD3 draws it as a 4dp
19
- * groove in `secondary-container` with the active indicator in `primary`; here
20
- * the two are the chosen family's own container and accent, so `color="error"` is
21
- * a red bar in a red groove rather than a red bar in a blue one.
19
+ * groove in `secondary-container` with the active indicator in `primary`. Here
20
+ * the indicator is the chosen family's accent and the groove is `on-surface` at
21
+ * 12%, so `color="error"` is a red bar in a neutral groove rather than a red bar
22
+ * in a blue one.
22
23
  *
23
24
  * Both ends are fully rounded, which is MD3's own shape for it: at four pixels
24
25
  * tall there is no flat run left to preserve, and a square-ended bar reads as a
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{Toggle as o}from"@base-ui/react/toggle";import{ToggleGroup as n}from"@base-ui/react/toggle-group";import{MPIcon as a}from"../icon/MPIcon.js";import{CheckIcon as s}from"../../constants/icons.js";import{MPStateLayer as i}from"../../internal/StateLayer.js";import{CONTROL_GAP as l,CONTROL_HEIGHT as d,CONTROL_ICON as c,CONTROL_PAD_X as m,CONTROL_TEXT as u}from"../../internal/scale.js";import{useMPSize as p}from"../../internal/config.js";export const MPSegmentedButton=/*@__PURE__*/r.forwardRef(function({items:r,value:f,defaultValue:b,onValueChange:h,multiple:g=!1,showCheck:y=!0,size:j,fullWidth:x=!1,disabled:v=!1,"aria-label":w,className:N,style:B},V){const k=p(j);return e(n,{ref:V,"aria-label":w,value:f,defaultValue:b,onValueChange:e=>h?.(e),multiple:g,disabled:v,"data-mp-size":k,className:["mp-segmented-button rounded-mp-full box-border items-center align-middle","overflow-hidden border",v?"border-mp-on-surface/12":"border-mp-outline",x?"flex w-full":"inline-flex w-fit",d[k],N??""].filter(Boolean).join(" "),style:B,children:r.map((r,n)=>{const d=v||r.disabled;return t(o,{value:r.value,disabled:r.disabled,className:["mp-segmented-button__segment group relative flex h-full items-center","box-border justify-center bg-transparent font-[inherit] whitespace-nowrap","select-none","appearance-none overflow-hidden outline-none","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",u[k],l[k],m[k],0===n?"border-0":"border-y-0 border-e-0 border-s",d?"border-mp-on-surface/12 text-mp-on-surface/38 cursor-default":["border-mp-outline cursor-pointer","text-mp-on-surface","data-pressed:bg-mp-secondary-container","data-pressed:text-mp-on-secondary-container"].join(" "),x?"flex-1":""].filter(Boolean).join(" "),children:[d?null:e(i,{}),y||r.icon?t("span",{className:"relative flex shrink-0 items-center justify-center",style:{width:c[k],height:c[k]},children:[y?e("span",{className:["absolute inset-0 flex items-center justify-center opacity-0","transition-opacity duration-(--mp-sys-motion-duration-short4)","ease-mp-standard group-data-pressed:opacity-100"].join(" "),children:e(a,{icon:s,size:c[k]})}):null,r.icon?e("span",{className:["absolute inset-0 flex items-center justify-center","transition-opacity duration-(--mp-sys-motion-duration-short4)","ease-mp-standard",y?"group-data-pressed:opacity-0":""].filter(Boolean).join(" "),children:r.icon}):null]}):null,e("span",{className:"truncate",children:r.label})]},`${n}:${r.value}`)})})});
2
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{Toggle as a}from"@base-ui/react/toggle";import{ToggleGroup as o}from"@base-ui/react/toggle-group";import{MPIcon as n}from"../icon/MPIcon.js";import{CheckIcon as s}from"../../constants/icons.js";import{MPStateLayer as l}from"../../internal/StateLayer.js";import{useMPSize as i}from"../../internal/config.js";const m={xs:"h-8",sm:"h-9",md:"h-10",lg:"h-12",xl:"h-14"},d={xs:"text-mp-label-large",sm:"text-mp-label-large",md:"text-mp-label-large",lg:"text-mp-title-medium",xl:"text-mp-title-medium"},p={xs:"px-3",sm:"px-3.5",md:"px-4",lg:"px-5",xl:"px-6"},c={xs:"gap-1.5",sm:"gap-1.5",md:"gap-2",lg:"gap-2",xl:"gap-2"},u={xs:16,sm:18,md:18,lg:20,xl:20};export const MPSegmentedButton=/*@__PURE__*/r.forwardRef(function({items:r,value:f,defaultValue:x,onValueChange:b,multiple:g=!1,showCheck:h=!0,size:y,fullWidth:j=!1,disabled:v=!1,"aria-label":w,className:N,style:B},V){const k=i(y);return e(o,{ref:V,"aria-label":w,value:f,defaultValue:x,onValueChange:e=>b?.(e),multiple:g,disabled:v,"data-mp-size":k,className:["mp-segmented-button rounded-mp-full box-border items-center align-middle","overflow-hidden border",v?"border-mp-on-surface/12":"border-mp-outline",j?"flex w-full":"inline-flex w-fit",m[k],N??""].filter(Boolean).join(" "),style:B,children:r.map((r,o)=>{const i=v||r.disabled;return t(a,{value:r.value,disabled:r.disabled,className:["mp-segmented-button__segment group relative flex h-full items-center","box-border justify-center bg-transparent font-[inherit] whitespace-nowrap","select-none","appearance-none overflow-hidden outline-none","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",d[k],c[k],p[k],0===o?"border-0":"border-y-0 border-e-0 border-s",i?"border-mp-on-surface/12 text-mp-on-surface/38 cursor-default":["border-mp-outline cursor-pointer","text-mp-on-surface","data-pressed:bg-mp-secondary-container","data-pressed:text-mp-on-secondary-container"].join(" "),j?"flex-1":""].filter(Boolean).join(" "),children:[i?null:e(l,{}),h||r.icon?t("span",{className:"relative flex shrink-0 items-center justify-center",style:{width:u[k],height:u[k]},children:[h?e("span",{className:["absolute inset-0 flex items-center justify-center opacity-0","transition-opacity duration-(--mp-sys-motion-duration-short4)","ease-mp-standard group-data-pressed:opacity-100"].join(" "),children:e(n,{icon:s,size:u[k]})}):null,r.icon?e("span",{className:["absolute inset-0 flex items-center justify-center","transition-opacity duration-(--mp-sys-motion-duration-short4)","ease-mp-standard",h?"group-data-pressed:opacity-0":""].filter(Boolean).join(" "),children:r.icon}):null]}):null,e("span",{className:"truncate",children:r.label})]},`${o}:${r.value}`)})})});
@@ -101,8 +101,10 @@ export interface MPSidebarProps extends Omit<React.ComponentPropsWithoutRef<'asi
101
101
  */
102
102
  title?: React.ReactNode;
103
103
  /**
104
- * How much surface the column paints, on the **container** ladder — a sidebar
105
- * is never dyed, because what sits on it arrives with colours of its own.
104
+ * How much surface the column paints, on the ladder `MPHeader` and `MPFooter`
105
+ * use: the container one, except that `elevated` lifts to a level-2 shadow and
106
+ * `outlined` keeps the page's surface. A sidebar is never dyed, because what
107
+ * sits on it arrives with colours of its own.
106
108
  *
107
109
  * `outlined` is the default: the page's own surface, with a hairline down the
108
110
  * edge that faces the content. That is the column *in the layout*. Once it has
@@ -28,10 +28,11 @@ export interface MPSnackbarData {
28
28
  * page whose bottom corner is a toolbar. Not for a preference: an application
29
29
  * whose snackbars all appear in the same wrong place should move the provider.
30
30
  *
31
- * All six stacks are on the page from the start whether or not anything is in
32
- * them, which is not a detail: a stack is its own `aria-live` region, and a
33
- * region added to the document at the same instant as the message inside it is
34
- * a region a screen reader has nothing to compare against and does not read.
31
+ * The six stacks share one `aria-live` region, which is on the page from the
32
+ * first render whether or not anything is in it, and that is not a detail: a
33
+ * region added to the document at the same instant as the message inside it
34
+ * is one a screen reader has nothing to compare against and does not read. A
35
+ * corner's stack is drawn inside it once that corner has a message.
35
36
  */
36
37
  position?: MPSnackbarPosition;
37
38
  /**
@@ -113,8 +114,9 @@ export interface MPSnackbarProviderProps {
113
114
  */
114
115
  limit?: number;
115
116
  /**
116
- * How wide a snackbar may get. Numbers are pixels. MD3's own maximum is 600dp
117
- * and its minimum is 344dp, which is what the two ends of the plate are set to.
117
+ * How wide a snackbar may get. Numbers are pixels. The default is MD3's own
118
+ * maximum, 600dp. There is no minimum on the plate; the message keeps at least
119
+ * 280px of the line, or the whole line on a window narrower than that.
118
120
  * @default 600
119
121
  */
120
122
  width?: number | string;
@@ -18,10 +18,12 @@ export interface MPStepperProps extends Omit<React.ComponentPropsWithoutRef<'div
18
18
  /**
19
19
  * Called with the step that was pressed.
20
20
  *
21
- * **Leaving it out is what makes the steps unpressable.** A stepper with no
22
- * handler is a progress indicator — it says where the reader is and offers no
23
- * way to move, which is the right shape for a sequence the application drives
24
- * with its own Next and Back buttons.
21
+ * **Leaving it out of a controlled stepper is what makes the steps
22
+ * unpressable.** A stepper given `active` and no handler is a progress
23
+ * indicator — it says where the reader is and offers no way to move, which is
24
+ * the right shape for a sequence the application drives with its own Next and
25
+ * Back buttons. An uncontrolled stepper moves itself when a step is pressed,
26
+ * handler or not.
25
27
  */
26
28
  onActiveChange?: (active: number) => void;
27
29
  /**
@@ -123,9 +125,9 @@ export interface MPStepProps extends Omit<React.ComponentPropsWithoutRef<'li'>,
123
125
  * | The content | is all on screen | is one panel |
124
126
  * | Default orientation | `vertical` | `horizontal` |
125
127
  *
126
- * A stepper with no `onActiveChange` is the overlap: unpressable, one panel, and
127
- * a progress indicator for a sequence the application's own Next and Back
128
- * buttons drive.
128
+ * A controlled stepper with no `onActiveChange` is the overlap: unpressable, one
129
+ * panel, and a progress indicator for a sequence the application's own Next and
130
+ * Back buttons drive.
129
131
  *
130
132
  * ## It ships no Next and Back
131
133
  *
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as t,Fragment as r}from"react/jsx-runtime";import*as n from"react";import{MPIcon as l}from"../icon/MPIcon.js";import{CheckIcon as o,ErrorIcon as a}from"../../constants/icons.js";import{accentSlots as i}from"../../internal/accent.js";import{hasContent as s,META_TEXT as c,SHEET_TITLE as p}from"../../internal/scale.js";import{BORDER_STYLE as m,BULLET as d,BULLET_GAP as u,BULLET_SIZE as f,CONNECTOR_COLOR as h,ITEM_GAP as v,ITEM_GAP_X as x,STEP_MOTION as b,TITLE_COLOR as _}from"../../internal/step.js";import{useMPColor as j,useMPSize as N}from"../../internal/config.js";function g(e,t){return`${e}-label-${t}`}function w(e){return`${e}-panel`}const y=/*@__PURE__*/n.createContext(null),z=/*@__PURE__*/n.createContext(0);export const MPStepper=/*@__PURE__*/n.forwardRef(function({active:r,defaultActive:l=0,onActiveChange:o,linear:a=!0,orientation:c="horizontal",size:p,color:m,className:d,style:u,children:h,...v},x){const b=N(p),_=j(m),[g,w]=n.useState(l),C=r??g,[P,S]=n.useState(C);C>P&&S(C);const $=n.Children.toArray(h).filter(n.isValidElement),k=$.length,M=n.useId(),A=s($[C]?.props.children),I=n.useCallback(e=>{void 0===r&&w(e),o?.(e)},[r,o]),R=n.useMemo(()=>({size:b,color:_,orientation:c,active:C,onSelect:o||void 0===r?I:null,linear:a,count:k,furthest:P,idBase:M,hasPanel:A}),[b,_,c,C,o,r,I,a,k,P,M,A]),E="horizontal"===c;return e(y.Provider,{value:R,children:t("div",{...v,ref:x,"data-mp-size":b,className:["mp-stepper flex flex-col",d??""].filter(Boolean).join(" "),style:{...i(_),...u},children:[e("ol",{className:["mp-stepper__rail m-0 flex list-none p-0",E?"flex-row items-start":"flex-col"].join(" "),style:{"--_mp-bullet":f[b]},children:$.map((t,r)=>e(z.Provider,{value:r,children:t},r))}),e(B,{steps:$,active:C,idBase:M})]})})});function B({steps:t,active:r,idBase:n}){const l=t[r],o=l?.props.children;if(!s(o))return null;const a=s(l?.props.label);return e("div",{id:w(n),role:"group","aria-labelledby":a?g(n,r):void 0,className:"mp-stepper__panel mt-4",children:o})}export const MPStep=/*@__PURE__*/n.forwardRef(function({label:f,description:j,bullet:N,error:B=!1,optional:C,disabled:P=!1,connector:S="solid",color:$,className:k,style:M,children:A,...I},R){const E=n.useContext(y),F=n.useContext(z),V=E?.size??"md",q=E?.orientation??"horizontal",D=E?.active??0,G=E?.count??1,H=E?.furthest??0,J=E?.linear??!0,K=F<D?"complete":F===D?"current":"upcoming",L=$??(B?"error":E?.color??"primary"),O="horizontal"===q,Q=F===G-1,T="none"!==S&&!Q,U=!P&&(!J||F<=H),W=null!=E?.onSelect&&U,X=N??("complete"!==K||B?B?e(l,{icon:a}):F+1:e(l,{icon:o})),Y=e("span",{"aria-hidden":"true",className:["mp-stepper__bullet rounded-mp-full relative z-10 flex shrink-0","items-center justify-center","size-(--_mp-bullet) text-[calc(var(--_mp-bullet)*0.5)] leading-none font-medium","tabular-nums [&>svg]:size-[0.6em]",d[K],"transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4) ease-mp-standard"].join(" "),children:X}),Z=T?e("span",{"aria-hidden":"true",className:["mp-stepper__connector pointer-events-none absolute",O?"start-(--_mp-bullet) top-[calc(var(--_mp-bullet)/2_-_1px)] end-0 border-t-2":"top-(--_mp-bullet) start-[calc(var(--_mp-bullet)/2_-_1px)] bottom-0 border-s-2",m[S],h[K],b].filter(Boolean).join(" ")}):null,ee=t("span",{className:"flex min-w-0 flex-col gap-0.5 text-start "+(O?"mt-2":""),children:[s(f)?e("span",{id:E?g(E.idBase,F):void 0,className:["mp-stepper__label",p[V],B?"text-mp-error":_[K],b].join(" "),children:f}):null,s(C)?e("span",{className:`text-mp-on-surface-variant ${c}`,children:C}):null,s(j)?e("span",{className:`text-mp-on-surface-variant ${c}`,children:j}):null]}),te=t(r,{children:[Z,t("span",{className:`flex min-w-0 ${O?"flex-col items-start":"flex-row"} ${O?"":u[V]}`,children:[Y,ee]})]});return e("li",{...I,ref:R,"aria-current":"current"===K?"step":void 0,className:["mp-stepper__step relative min-w-0",O?`flex-1 ${Q?"":x[V]}`:Q?"":v[V],k??""].filter(Boolean).join(" "),style:{...$||B?i(L):null,...M},children:W?e("button",{type:"button","aria-controls":E?.hasPanel?w(E.idBase):void 0,"aria-expanded":E?.hasPanel?"current"===K:void 0,className:["group relative flex w-full min-w-0 cursor-pointer appearance-none border-0 bg-transparent p-0 text-start","outline-mp-secondary rounded-mp-xs focus-visible:outline-2 focus-visible:outline-offset-2","outline-none"].join(" "),onClick:()=>E?.onSelect?.(F),children:te}):e("span",{className:"relative flex w-full min-w-0","aria-disabled":!(!E?.onSelect||U)||void 0,children:te})})});
2
+ import{jsx as e,jsxs as t,Fragment as r}from"react/jsx-runtime";import*as n from"react";import{MPIcon as l}from"../icon/MPIcon.js";import{CheckIcon as o,ErrorIcon as a}from"../../constants/icons.js";import{accentSlots as i}from"../../internal/accent.js";import{hasContent as s,META_TEXT as c,SHEET_TITLE as p}from"../../internal/scale.js";import{BORDER_STYLE as m,BULLET as d,BULLET_GAP as u,BULLET_SIZE as f,CONNECTOR_COLOR as h,ITEM_GAP as v,ITEM_GAP_X as x,STEP_MOTION as b,TITLE_COLOR as _}from"../../internal/step.js";import{useMPColor as j,useMPSize as N}from"../../internal/config.js";function g(e,t){return`${e}-label-${t}`}function w(e){return`${e}-panel`}const y=/*@__PURE__*/n.createContext(null),z=/*@__PURE__*/n.createContext(0);export const MPStepper=/*@__PURE__*/n.forwardRef(function({active:r,defaultActive:l=0,onActiveChange:o,linear:a=!0,orientation:c="horizontal",size:p,color:m,className:d,style:u,children:h,...v},x){const b=N(p),_=j(m),[g,w]=n.useState(l),C=r??g,[P,$]=n.useState(C);C>P&&$(C);const S=n.Children.toArray(h).filter(n.isValidElement),k=S.length,M=n.useId(),A=s(S[C]?.props.children),I=n.useCallback(e=>{void 0===r&&w(e),o?.(e)},[r,o]),R=n.useMemo(()=>({size:b,color:_,orientation:c,active:C,onSelect:o||void 0===r?I:null,linear:a,count:k,furthest:P,idBase:M,hasPanel:A}),[b,_,c,C,o,r,I,a,k,P,M,A]),E="horizontal"===c;return e(y.Provider,{value:R,children:t("div",{...v,ref:x,"data-mp-size":b,className:["mp-stepper flex flex-col",d??""].filter(Boolean).join(" "),style:{...i(_),...u},children:[e("ol",{className:["mp-stepper__rail m-0 flex list-none p-0",E?"flex-row items-start":"flex-col"].join(" "),style:{"--_mp-bullet":f[b]},children:S.map((t,r)=>e(z.Provider,{value:r,children:t},r))}),e(B,{steps:S,active:C,idBase:M})]})})});function B({steps:t,active:r,idBase:n}){const l=t[r],o=l?.props.children;if(!s(o))return null;const a=s(l?.props.label);return e("div",{id:w(n),role:"group","aria-labelledby":a?g(n,r):void 0,className:"mp-stepper__panel mt-4",children:o})}export const MPStep=/*@__PURE__*/n.forwardRef(function({label:f,description:j,bullet:N,error:B=!1,optional:C,disabled:P=!1,connector:$="solid",color:S,className:k,style:M,children:A,...I},R){const E=n.useContext(y),F=n.useContext(z),V=E?.size??"md",q=E?.orientation??"horizontal",D=E?.active??0,G=E?.count??1,H=E?.furthest??0,J=E?.linear??!0,K=F<D?"complete":F===D?"current":"upcoming",L=S??(B?"error":E?.color??"primary"),O="horizontal"===q,Q=F===G-1,T="none"!==$&&!Q,U=!P&&(!J||F<=H),W=null!=E?.onSelect,X=W&&U,Y=N??("complete"!==K||B?B?e(l,{icon:a}):F+1:e(l,{icon:o})),Z=e("span",{"aria-hidden":"true",className:["mp-stepper__bullet rounded-mp-full relative z-10 flex shrink-0","items-center justify-center","size-(--_mp-bullet) text-[calc(var(--_mp-bullet)*0.5)] leading-none font-medium","tabular-nums [&>svg]:size-[0.6em]",d[K],"transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4) ease-mp-standard"].join(" "),children:Y}),ee=T?e("span",{"aria-hidden":"true",className:["mp-stepper__connector pointer-events-none absolute",O?"start-(--_mp-bullet) top-[calc(var(--_mp-bullet)/2_-_1px)] end-0 border-t-2":"top-(--_mp-bullet) start-[calc(var(--_mp-bullet)/2_-_1px)] bottom-0 border-s-2",m[$],h[K],b].filter(Boolean).join(" ")}):null,te=t("span",{className:"flex min-w-0 flex-col gap-0.5 text-start "+(O?"mt-2":""),children:[s(f)?e("span",{id:E?g(E.idBase,F):void 0,className:["mp-stepper__label",p[V],B?"text-mp-error":_[K],b].join(" "),children:f}):null,s(C)?e("span",{className:`text-mp-on-surface-variant ${c}`,children:C}):null,s(j)?e("span",{className:`text-mp-on-surface-variant ${c}`,children:j}):null]}),re=t(r,{children:[ee,t("span",{className:`flex min-w-0 ${O?"flex-col items-start":"flex-row"} ${O?"":u[V]}`,children:[Z,te]})]});return e("li",{...I,ref:R,"aria-current":"current"===K?"step":void 0,className:["mp-stepper__step relative min-w-0",O?`flex-1 ${Q?"":x[V]}`:Q?"":v[V],k??""].filter(Boolean).join(" "),style:{...S||B?i(L):null,...M},children:W?e("button",{type:"button","aria-controls":E?.hasPanel?w(E.idBase):void 0,"aria-expanded":E?.hasPanel?"current"===K:void 0,"aria-disabled":!U||void 0,className:["group relative flex w-full min-w-0 appearance-none border-0 bg-transparent p-0 text-start",X?"cursor-pointer":"cursor-default","outline-mp-secondary rounded-mp-xs focus-visible:outline-2 focus-visible:outline-offset-2","outline-none"].join(" "),onClick:X?()=>E?.onSelect?.(F):void 0,children:re}):e("span",{className:"relative flex w-full min-w-0",children:re})})});
@@ -128,9 +128,13 @@ export interface MPTableProps<Row> extends Omit<React.ComponentPropsWithoutRef<'
128
128
  */
129
129
  size?: MPSize;
130
130
  /**
131
- * Which accent family a hovered or pressed row reads. The cells themselves
132
- * stay neutral.
133
- * @default 'primary'
131
+ * Has no visible effect, and is kept only so code that passes it still
132
+ * compiles.
133
+ *
134
+ * It promised the accent family a hovered row would read, and the rows were
135
+ * never tinted: a stripe and a hover are neutral surfaces one step apart, on
136
+ * purpose, because a table that tints its rows colours its data.
137
+ * @deprecated No effect. It is due to be removed in the next major version.
134
138
  */
135
139
  color?: MPColor;
136
140
  /**
@@ -43,6 +43,15 @@ export interface MPTextFieldProps extends MPStyleProps, MPControlEventProps<HTML
43
43
  * where a placeholder would be. See `floatingLabel`.
44
44
  */
45
45
  label?: string;
46
+ /**
47
+ * The accessible name, for a field with no visible `label` — a filter box
48
+ * whose purpose the panel around it already shows.
49
+ *
50
+ * A prop of its own because the field passes nothing on that it does not
51
+ * name, and a hyphenated attribute is one TypeScript never checks: written on
52
+ * the component, it used to be accepted without a word and dropped.
53
+ */
54
+ 'aria-label'?: string;
46
55
  /**
47
56
  * Whether the label rests on the field's line while there is nothing to make
48
57
  * room for, and rises into the notch on focus or on the first character.
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Field as n}from"@base-ui/react/field";import{MPIcon as r}from"../icon/MPIcon.js";import{MPFieldLabel as a,MPFieldOutline as i,useFloatingLabel as l}from"../../internal/FieldOutline.js";import{MPSupportingText as s}from"../../internal/SupportingText.js";import{VisibilityIcon as d,VisibilityOffIcon as p}from"../../constants/icons.js";import{useMPLocale as u,useMPMessages as c}from"../../internal/locale.js";import{TEXT_FIELD as m}from"../../internal/messages/text-field.js";import{useMPSize as f}from"../../internal/config.js";const x={xs:{padding:"px-2",control:"py-1.5",text:"text-mp-body-medium",icon:16},sm:{padding:"px-3",control:"py-2.5",text:"text-mp-body-medium",icon:18},md:{padding:"px-4",control:"py-4",text:"text-mp-body-large",icon:20},lg:{padding:"px-4",control:"py-5",text:"text-mp-body-large",icon:22},xl:{padding:"px-5",control:"py-6",text:"text-mp-body-large",icon:24}};export const MPTextField=/*@__PURE__*/o.forwardRef(function({value:b,name:g,type:y="text",placeholder:h,autoComplete:v,label:w,floatingLabel:C=!0,onChange:j,onFormReset:k,onSubmit:M,onKeyDown:z,onKeyUp:D,onFocus:N,onBlur:E,onClick:F,onDoubleClick:P,onContextMenu:S,errorMessage:B="",required:K=!1,fullWidth:q=!1,readOnly:L=!1,autoFocus:R=!1,size:U,disabled:I=!1,disableEnterKey:O=!1,rows:T,maxLength:$,startIcon:_,resizable:W=!1,id:A,locale:G,passwordLabels:H,className:J,style:Q},V){const X=f(U),Y=u(G),Z=c(m,Y,H),ee=o.useRef(null),[te,oe]=o.useState(!1),[ne,re]=o.useState(!1),[ae,ie]=o.useState(b),le=o.useId(),se=A??le,de=!!T,pe=B.length>0,ue=x[X],ce=ne?ae:b,{shrunk:me,focusProps:fe}=l({floating:C&&!!w,filled:ce.length>0,pinned:!!_}),xe=o.useCallback(e=>{ee.current=e,"function"==typeof V?V(e):V&&(V.current=e)},[V]),be=e=>{e.preventDefault()};return o.useEffect(()=>{ne||ie(b)},[b,ne]),o.useEffect(()=>{R&&!window.matchMedia("(max-width: 599.95px)").matches&&ee.current?.focus()},[]),t(n.Root,{className:["mp-text-field group relative",q?"w-full":"inline-block","align-top",J??""].filter(Boolean).join(" "),style:Q,disabled:I,invalid:pe,"data-mp-size":X,...fe,children:[t("div",{className:["relative flex w-full items-center gap-2",ue.padding,de?"py-2":""].filter(Boolean).join(" "),children:[e(i,{label:w,required:K,notched:me}),_?e("span",{className:"text-mp-on-surface-variant group-data-disabled:text-mp-on-surface/38 flex shrink-0 items-center",children:_}):null,e(n.Control,{render:de?e("textarea",{rows:T}):e("input",{}),id:se,name:g,type:de?void 0:te?"text":y,required:K,readOnly:L,disabled:I,autoComplete:v,placeholder:me?h:void 0,maxLength:$,value:ce,ref:xe,className:[`${ue.text} text-mp-on-surface w-full min-w-0 flex-1`,"font-[family-name:var(--mp-sys-typescale-body-large-font)]","appearance-none border-0 bg-transparent px-0 outline-none","caret-mp-primary",ue.control,de?"py-0":"",de&&W?"resize-y":"resize-none","search"===y?"[&::-webkit-search-cancel-button]:hidden":"","group-data-disabled:text-mp-on-surface/38","placeholder:text-mp-on-surface-variant group-data-disabled:placeholder:text-mp-on-surface/38"].filter(Boolean).join(" "),onChange:e=>{k?.();const t=e.target.value;ne&&ie(t),j?.(t)},onCompositionStart:()=>{re(!0),ie(b)},onCompositionUpdate:e=>{ie(e.target.value)},onCompositionEnd:e=>{re(!1);const t=e.target.value;k?.(),j?.(t),ie(t)},onKeyUp:D,onFocus:N,onBlur:E,onClick:F,onDoubleClick:P,onContextMenu:S,onKeyDown:e=>{if(z?.(e),!e.defaultPrevented&&"Enter"===e.key){if(function(e){const t=e.nativeEvent;return t.isComposing||229===t.keyCode}(e))return;M?.(),(O||M&&!de)&&e.preventDefault()}}}),"password"!==y||de?null:e("button",{type:"button","aria-label":te?Z.hidePassword:Z.showPassword,onClick:()=>oe(e=>!e),onMouseDown:be,onMouseUp:be,disabled:I,className:["text-mp-on-surface-variant -me-1 flex shrink-0 items-center justify-center","cursor-pointer appearance-none border-0 bg-transparent p-1 font-[inherit]","rounded-full","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none","hover:text-mp-on-surface focus-visible:text-mp-primary","disabled:text-mp-on-surface/38 disabled:cursor-default"].join(" "),children:e(r,{icon:te?d:p,size:ue.icon})}),w?e(a,{size:X,label:w,required:K,shrunk:me,multiline:de}):null]}),e(s,{errorMessage:B,className:`mp-text-field__support mt-1 ${ue.padding}`})]})});
2
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Field as n}from"@base-ui/react/field";import{MPIcon as a}from"../icon/MPIcon.js";import{MPFieldLabel as r,MPFieldOutline as i,useFloatingLabel as l}from"../../internal/FieldOutline.js";import{MPSupportingText as s}from"../../internal/SupportingText.js";import{VisibilityIcon as d,VisibilityOffIcon as p}from"../../constants/icons.js";import{useMPLocale as u,useMPMessages as c}from"../../internal/locale.js";import{TEXT_FIELD as m}from"../../internal/messages/text-field.js";import{useMPSize as f}from"../../internal/config.js";const x={xs:{padding:"px-2",control:"py-1.5",text:"text-mp-body-medium",icon:16},sm:{padding:"px-3",control:"py-2.5",text:"text-mp-body-medium",icon:18},md:{padding:"px-4",control:"py-4",text:"text-mp-body-large",icon:20},lg:{padding:"px-4",control:"py-5",text:"text-mp-body-large",icon:22},xl:{padding:"px-5",control:"py-6",text:"text-mp-body-large",icon:24}};export const MPTextField=/*@__PURE__*/o.forwardRef(function({value:b,name:g,type:y="text",placeholder:h,autoComplete:v,label:w,"aria-label":C,floatingLabel:j=!0,onChange:k,onFormReset:M,onSubmit:z,onKeyDown:D,onKeyUp:N,onFocus:E,onBlur:F,onClick:P,onDoubleClick:S,onContextMenu:B,errorMessage:K="",required:q=!1,fullWidth:L=!1,readOnly:R=!1,autoFocus:U=!1,size:I,disabled:O=!1,disableEnterKey:T=!1,rows:$,maxLength:_,startIcon:W,resizable:A=!1,id:G,locale:H,passwordLabels:J,className:Q,style:V},X){const Y=f(I),Z=u(H),ee=c(m,Z,J),te=o.useRef(null),[oe,ne]=o.useState(!1),[ae,re]=o.useState(!1),[ie,le]=o.useState(b),se=o.useId(),de=G??se,pe=!!$,ue=K.length>0,ce=x[Y],me=ae?ie:b,{shrunk:fe,focusProps:xe}=l({floating:j&&!!w,filled:me.length>0,pinned:!!W}),be=o.useCallback(e=>{te.current=e,"function"==typeof X?X(e):X&&(X.current=e)},[X]),ge=e=>{e.preventDefault()};return o.useEffect(()=>{ae||le(b)},[b,ae]),o.useEffect(()=>{U&&!window.matchMedia("(max-width: 599.95px)").matches&&te.current?.focus()},[]),t(n.Root,{className:["mp-text-field group relative",L?"w-full":"inline-block","align-top",Q??""].filter(Boolean).join(" "),style:V,disabled:O,invalid:ue,"data-mp-size":Y,...xe,children:[t("div",{className:["relative flex w-full items-center gap-2",ce.padding,pe?"py-2":""].filter(Boolean).join(" "),children:[e(i,{label:w,required:q,notched:fe}),W?e("span",{className:"text-mp-on-surface-variant group-data-disabled:text-mp-on-surface/38 flex shrink-0 items-center",children:W}):null,e(n.Control,{render:pe?e("textarea",{rows:$}):e("input",{}),id:de,name:g,"aria-label":C,type:pe?void 0:oe?"text":y,required:q,readOnly:R,disabled:O,autoComplete:v,placeholder:fe?h:void 0,maxLength:_,value:me,ref:be,className:[`${ce.text} text-mp-on-surface w-full min-w-0 flex-1`,"font-[family-name:var(--mp-sys-typescale-body-large-font)]","appearance-none border-0 bg-transparent px-0 outline-none","caret-mp-primary",ce.control,pe?"py-0":"",pe&&A?"resize-y":"resize-none","search"===y?"[&::-webkit-search-cancel-button]:hidden":"","group-data-disabled:text-mp-on-surface/38","placeholder:text-mp-on-surface-variant group-data-disabled:placeholder:text-mp-on-surface/38"].filter(Boolean).join(" "),onChange:e=>{M?.();const t=e.target.value;ae&&le(t),k?.(t)},onCompositionStart:()=>{re(!0),le(b)},onCompositionUpdate:e=>{le(e.target.value)},onCompositionEnd:e=>{re(!1);const t=e.target.value;M?.(),k?.(t),le(t)},onKeyUp:N,onFocus:E,onBlur:F,onClick:P,onDoubleClick:S,onContextMenu:B,onKeyDown:e=>{if(D?.(e),!e.defaultPrevented&&"Enter"===e.key){if(function(e){const t=e.nativeEvent;return t.isComposing||229===t.keyCode}(e))return;z?.(),(T||z&&!pe)&&e.preventDefault()}}}),"password"!==y||pe?null:e("button",{type:"button","aria-label":oe?ee.hidePassword:ee.showPassword,onClick:()=>ne(e=>!e),onMouseDown:ge,onMouseUp:ge,disabled:O,className:["text-mp-on-surface-variant -me-1 flex shrink-0 items-center justify-center","cursor-pointer appearance-none border-0 bg-transparent p-1 font-[inherit]","rounded-full","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none","hover:text-mp-on-surface focus-visible:text-mp-primary","disabled:text-mp-on-surface/38 disabled:cursor-default"].join(" "),children:e(a,{icon:oe?d:p,size:ce.icon})}),w?e(r,{size:Y,label:w,required:q,shrunk:fe,multiline:pe}):null]}),e(s,{errorMessage:K,className:`mp-text-field__support mt-1 ${ce.padding}`})]})});
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as n from"react";import{MPButton as l}from"../button/MPButton.js";import{MPIcon as r}from"../icon/MPIcon.js";import{ClockIcon as t}from"../../constants/icons.js";import{MPTimeGrid as i}from"../../internal/Calendar.js";import{FOOTER_SIZE as a,MPPickerFooter as s,MPPickerShell as c,useDisplaySamples as u}from"../../internal/Picker.js";import{useMPLocale as m,useMPMessages as d}from"../../internal/locale.js";import{PICKER as p}from"../../internal/messages/picker.js";import{CONTROL_ICON as f}from"../../internal/scale.js";import{formatDate as h,isHour12 as g,isValidDate as j,secondsOfDay as S,timeUnitSpan as b,toISOTime as v,withPlaceholder as C,withTime as x}from"../../internal/date.js";import{useMPColor as k,useMPSize as w}from"../../internal/config.js";export const MPTimePicker=/*@__PURE__*/n.forwardRef(function({value:z,defaultValue:D,onValueChange:O,open:P,defaultOpen:T,onOpenChange:y,referenceDate:M,minTime:I,maxTime:V,shouldDisableTime:B,hour12:N,showSeconds:R=!1,hourStep:F=1,minuteStep:H=1,secondStep:q=1,locale:A,format:E,placeholder:G,clearable:J=!1,showNowButton:K=!0,closeOnSelect:L=!1,labels:Q,name:U,size:W,color:X,readOnly:Y=!1,disabled:Z=!1,startIcon:$,..._},ee){const oe=w(W),ne=k(X),le=m(A),re=d(p,le,Q),te=N??g(le),[ie,ae]=n.useState(D??null),se=void 0!==z?z:ie,[ce,ue]=n.useState(T??!1),me=P??ce,[de]=n.useState(()=>M??new Date),pe=e=>{e&&(Y||Z)||(void 0===P&&ue(e),y?.(e))},fe=e=>{void 0===z&&ae(e),O?.(e)},he=n.useCallback((e,o)=>{const[n,l]=b(o,e);return!!(j(I)&&l<S(I))||(!!(j(V)&&n>S(V))||(B?.(e,o)??!1))},[I,V,B]),ge=E??{hour:"numeric",minute:"2-digit",hour12:te,...R?{second:"2-digit"}:{}},je=new Date,Se=x(M??de,{hours:je.getHours(),minutes:je.getMinutes(),seconds:R?je.getSeconds():0}),be=K||J||!L,ve=C(u(le,ge),G);return e(c,{..._,slug:"time-picker",size:oe,color:ne,readOnly:Y,disabled:Z,triggerRef:ee,startIcon:void 0===$?e(r,{icon:t,size:f[oe]}):$,display:j(se)?h(se,le,ge):G??"",samples:ve,empty:!j(se),clearable:J,onClear:()=>fe(null),open:me,onOpenChange:pe,labels:re,hiddenValues:U?[{name:U,value:j(se)?v(se,R):""}]:void 0,children:o("div",{className:"flex flex-col "+(be?"gap-1.5":""),children:[e(i,{size:oe,locale:le,value:j(se)?se:null,referenceDate:M??de,onChange:e=>{fe(e),L&&pe(!1)},hour12:te,showSeconds:R,hourStep:F,minuteStep:H,secondStep:q,shouldDisableTime:he,labels:re,autoFocus:!0}),be?o(s,{children:[J?e(l,{variant:"text",size:a[oe],color:ne,onClick:()=>{fe(null),pe(!1)},children:re.clear}):null,K?e(l,{variant:"text",size:a[oe],color:ne,disabled:he(Se,"second"),onClick:()=>{fe(Se),pe(!1)},children:re.now}):null,L?null:e(l,{variant:"filled",size:a[oe],color:ne,onClick:()=>pe(!1),children:re.done})]}):null]})})});
2
+ import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as n from"react";import{MPButton as l}from"../button/MPButton.js";import{MPIcon as r}from"../icon/MPIcon.js";import{ClockIcon as t}from"../../constants/icons.js";import{MPTimeGrid as a}from"../../internal/Calendar.js";import{FOOTER_SIZE as i,MPPickerFooter as s,MPPickerShell as c,useDisplaySamples as m}from"../../internal/Picker.js";import{useMPLocale as u,useMPMessages as d}from"../../internal/locale.js";import{PICKER as p}from"../../internal/messages/picker.js";import{CONTROL_ICON as f}from"../../internal/scale.js";import{formatDate as h,isHour12 as g,isValidDate as j,secondsOfDay as S,timeUnitSpan as b,toISOTime as v,withPlaceholder as C,withTime as x}from"../../internal/date.js";import{useMPColor as k,useMPSize as w}from"../../internal/config.js";export const MPTimePicker=/*@__PURE__*/n.forwardRef(function({value:z,defaultValue:D,onValueChange:O,open:P,defaultOpen:T,onOpenChange:y,referenceDate:M,minTime:V,maxTime:I,shouldDisableTime:B,hour12:N,showSeconds:R=!1,hourStep:F=1,minuteStep:H=1,secondStep:q=1,locale:A,format:E,placeholder:G,clearable:J=!1,showNowButton:K=!0,closeOnSelect:L=!1,labels:Q,name:U,size:W,color:X,readOnly:Y=!1,disabled:Z=!1,startIcon:$,..._},ee){const oe=w(W),ne=k(X),le=u(A),re=d(p,le,Q),te=N??g(le),[ae,ie]=n.useState(D??null),se=void 0!==z?z:ae,[ce,me]=n.useState(T??!1),ue=P??ce,[de]=n.useState(()=>M??new Date),pe=e=>{e&&(Y||Z)||(void 0===P&&me(e),y?.(e))},fe=e=>{void 0===z&&ie(e),O?.(e)},he=n.useCallback((e,o)=>{const[n,l]=b(o,e);return!!(j(V)&&l<S(V))||(!!(j(I)&&n>S(I))||(B?.(e,o)??!1))},[V,I,B]),ge=E??{hour:"numeric",minute:"2-digit",hour12:te,...R?{second:"2-digit"}:{}},je=new Date,Se=x(M??de,{hours:je.getHours(),minutes:je.getMinutes(),seconds:R?je.getSeconds():0}),be=K||J||!L,ve=C(m(le,ge),G),Ce=j(se)?v(se,R):"";return e(c,{..._,slug:"time-picker",size:oe,color:ne,name:U,locale:le,readOnly:Y,disabled:Z,triggerRef:ee,startIcon:void 0===$?e(r,{icon:t,size:f[oe]}):$,display:j(se)?h(se,le,ge):G??"",samples:ve,empty:!j(se),clearable:J,onClear:()=>fe(null),open:ue,onOpenChange:pe,labels:re,formValue:Ce,hiddenValues:U?[{name:U,value:Ce}]:void 0,children:o("div",{className:"flex flex-col "+(be?"gap-1.5":""),children:[e(a,{size:oe,locale:le,value:j(se)?se:null,referenceDate:M??de,onChange:e=>{fe(e),L&&pe(!1)},hour12:te,showSeconds:R,hourStep:F,minuteStep:H,secondStep:q,shouldDisableTime:he,labels:re,autoFocus:!0}),be?o(s,{children:[J?e(l,{variant:"text",size:i[oe],color:ne,onClick:()=>{fe(null),pe(!1)},children:re.clear}):null,K?e(l,{variant:"text",size:i[oe],color:ne,disabled:he(Se,"second"),onClick:()=>{fe(Se),pe(!1)},children:re.now}):null,L?null:e(l,{variant:"filled",size:i[oe],color:ne,onClick:()=>pe(!1),children:re.done})]}):null]})})});
@@ -99,8 +99,8 @@ export interface MPToolbarProps extends React.ComponentPropsWithoutRef<'div'> {
99
99
  *
100
100
  * ## What it is not
101
101
  *
102
- * Not `MPHeader`, which is `MPPageLayout`'s own slot and knows about the
103
- * sidebar, the skip link and the drawer. This is a bar you can put anywhere,
104
- * including inside a card.
102
+ * Not `MPHeader`, which is `MPPageLayout`'s header slot: the layout measures it
103
+ * and keeps the page clear of it. This is a bar you can put anywhere, including
104
+ * inside a card.
105
105
  */
106
106
  export declare const MPToolbar: React.ForwardRefExoticComponent<MPToolbarProps & React.RefAttributes<HTMLDivElement>>;
@@ -55,6 +55,12 @@ export interface MPTooltipProps {
55
55
  */
56
56
  disabled?: boolean;
57
57
  /**
58
+ * The plate's padding and type. `sm` and `md` both draw MD3's plain tooltip,
59
+ * 24dp tall with a `body-small` label, and differ only in the arrow.
60
+ *
61
+ * `sm` is this component's own answer, so it does not take the size
62
+ * `MPConfigProvider` sets for the rest of the application: a tooltip at a
63
+ * control's height is a slab. Set it here when a tooltip has to be larger.
58
64
  * @default 'sm'
59
65
  */
60
66
  size?: MPSize;
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { type MPTreeViewValue } from '../tree-view/MPTreeView.js';
3
3
  import { type MPPickerShellProps } from '../../internal/Picker.js';
4
4
  import type { MPPickerLabels } from '../../internal/Calendar.js';
5
- import type { MPSlots } from '../../types.js';
5
+ import type { MPColor, MPSlots } from '../../types.js';
6
6
  /** One node of the tree the reader is choosing from. */
7
7
  export interface MPTreeSelectItem {
8
8
  /** What is stored when this node is chosen. Unique across the whole tree. */
@@ -24,7 +24,17 @@ export interface MPTreeSelectItem {
24
24
  }
25
25
  /** The parts an `MPTreeSelect` draws that a `className` cannot reach. */
26
26
  export type MPTreeSelectSlot = 'popup' | 'tree' | 'item' | 'empty';
27
- export interface MPTreeSelectProps extends MPPickerShellProps {
27
+ export interface MPTreeSelectProps extends Omit<MPPickerShellProps, 'color'> {
28
+ /**
29
+ * Has no visible effect, and is kept only so code that passes it still
30
+ * compiles.
31
+ *
32
+ * The pickers share this prop for a calendar's chosen day and a range's band,
33
+ * and a tree has neither. A chosen row is `secondary-container`, as an
34
+ * `MPSelect`'s chosen option is.
35
+ * @deprecated No effect. It is due to be removed in the next major version.
36
+ */
37
+ color?: MPColor;
28
38
  /** The tree, as nested items. */
29
39
  items?: MPTreeSelectItem[];
30
40
  /** The chosen value, or values when `multiple`. */
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{MPTreeItem as n,MPTreeView as r}from"../tree-view/MPTreeView.js";import{MPPickerShell as t}from"../../internal/Picker.js";import{useMPLocale as o,useMPMessages as s}from"../../internal/locale.js";import{COMBOBOX as i}from"../../internal/messages/combobox.js";import{TRANSFER as c}from"../../internal/messages/transfer.js";import{PICKER as d}from"../../internal/messages/picker.js";import{META_TEXT as p}from"../../internal/scale.js";import{useMPColor as u,useMPSize as m}from"../../internal/config.js";function h(e,l=new Map){for(const a of e)l.set(a.value,a),a.children&&h(a.children,l);return l}const f=e=>e.trim().toLocaleLowerCase(),v=new WeakMap;function g(e){let l=v.get(e);return void 0===l&&(l=f(e.searchLabel??("string"==typeof e.label?e.label:String(e.value))),v.set(e,l)),l}function b(e,l){if(""===l)return e;const a=[];for(const n of e){const e=n.children?b(n.children,l):void 0,r=g(n).includes(l);(r||e&&e.length>0)&&a.push({...n,children:r?n.children:e})}return a}function x(e,l=[]){for(const a of e)a.children&&a.children.length>0&&(l.push(a.value),x(a.children,l));return l}export const MPTreeSelect=/*@__PURE__*/a.forwardRef(function({items:v=[],value:g,defaultValue:j,onValueChange:y,multiple:C=!1,selectableBranches:w=!1,defaultExpanded:S,expanded:M,onExpandedChange:N,open:O,defaultOpen:_,onOpenChange:k,placeholder:V,clearable:P=!1,closeOnSelect:z,searchable:B=!1,searchPlaceholder:E,locale:L,format:T,labels:A,name:D,size:I,color:R,readOnly:W=!1,disabled:q=!1,classNames:F,...G},H){const J=m(I),K=u(R),Q=o(L),U=s(i,Q),X=s(d,Q,A),Y=s(c,Q),Z=e=>null==e?[]:Array.isArray(e)?e:[e],[$,ee]=a.useState(()=>Z(j)),le=void 0!==g?Z(g):$,[ae,ne]=a.useState(_??!1),re=O??ae,[te,oe]=a.useState(""),se=a.useMemo(()=>h(v),[v]),ie=f(a.useDeferredValue(te)),ce=a.useMemo(()=>b(v,ie),[v,ie]),de=a.useMemo(()=>""===ie?void 0:x(ce),[ie,ce]),[pe,ue]=a.useState(()=>S??[]),me=de??M??pe,he=e=>{de||(void 0===M&&ue(e),N?.(e))},fe=e=>{e&&(W||q)||(void 0===O&&ne(e),e||oe(""),k?.(e))},ve=e=>{void 0===g&&ee(e),y?.(e)},ge=e=>e.selectable??(!(e.children&&e.children.length>0)||w),be=e=>l=>{l.preventDefault(),e.children&&e.children.length>0&&he(me.includes(e.value)?me.filter(l=>l!==e.value):[...me,e.value])},xe=le.map(e=>se.get(e)).filter(e=>void 0!==e),je=0===xe.length?V??"":T?T(xe):xe.map(e=>e.label).reduce((e,l,a)=>0===a?[l]:[...e,", ",l],[]),ye=l=>l.map(l=>e(n,{value:l.value,label:l.label,startIcon:l.startIcon,disabled:l.disabled,onClick:ge(l)?void 0:be(l),className:F?.item,children:l.children?ye(l.children):null},l.value));return e(t,{...G,slug:"tree-select",size:J,color:K,readOnly:W,disabled:q,triggerRef:H,display:je,empty:0===xe.length,clearable:P,onClear:()=>ve([]),open:re,onOpenChange:fe,labels:X,hiddenValues:D?le.map(e=>({name:D,value:String(e)})):void 0,children:l("div",{className:["mp-tree-select__popup flex max-h-80 w-64 flex-col gap-2",F?.popup??""].filter(Boolean).join(" "),children:[B?e("input",{type:"text",value:te,placeholder:E??Y.search,"aria-label":E??Y.search,onChange:e=>oe(e.currentTarget.value),className:["mp-tree-select__search text-mp-on-surface w-full shrink-0 bg-transparent","placeholder:text-mp-on-surface-variant px-1 py-1 [font:inherit] outline-none"].join(" ")}):null,e("div",{className:"min-h-0 flex-1 overflow-auto",children:0===ce.length?e("p",{className:["mp-tree-select__empty text-mp-on-surface-variant m-0 px-1 py-2",p,F?.empty??""].filter(Boolean).join(" "),children:U.empty}):e(r,{size:J,variant:"text",multiple:C,selected:le,onSelectedChange:e=>{const l=e.filter(e=>se.has(e));ve(C?l:l.slice(-1)),(z??!C)&&fe(!1)},expanded:me,onExpandedChange:he,className:F?.tree,children:ye(ce)})})]})})});
2
+ import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as n from"react";import{MPTreeItem as a,MPTreeView as r}from"../tree-view/MPTreeView.js";import{MPPickerShell as t}from"../../internal/Picker.js";import{useMPLocale as o,useMPMessages as i}from"../../internal/locale.js";import{COMBOBOX as s}from"../../internal/messages/combobox.js";import{TRANSFER as c}from"../../internal/messages/transfer.js";import{PICKER as u}from"../../internal/messages/picker.js";import{META_TEXT as d}from"../../internal/scale.js";import{useMPColor as p,useMPSize as m}from"../../internal/config.js";function h(e,l=new Map){for(const n of e)l.set(n.value,n),n.children&&h(n.children,l);return l}function f(e){return e.searchLabel??("string"==typeof e.label?e.label:String(e.value))}const g={usage:"search",sensitivity:"base",ignorePunctuation:!0},v=new Map;function b(e,l,n){for(let a=0;a+l.length<=e.length;a+=1)if(0===n.compare(e.slice(a,a+l.length),l))return!0;return!1}function x(e,l,n){if(""===l)return e;const a=[];for(const r of e){const e=r.children?x(r.children,l,n):void 0,t=b(f(r),l,n);(t||e&&e.length>0)&&a.push({...r,children:t?r.children:e})}return a}function j(e,l=[]){for(const n of e)n.children&&n.children.length>0&&(l.push(n.value),j(n.children,l));return l}export const MPTreeSelect=/*@__PURE__*/n.forwardRef(function({items:f=[],value:b,defaultValue:y,onValueChange:C,multiple:S=!1,selectableBranches:w=!1,defaultExpanded:M,expanded:N,onExpandedChange:O,open:V,defaultOpen:_,onOpenChange:P,placeholder:k,clearable:z=!1,closeOnSelect:B,searchable:E=!1,searchPlaceholder:I,locale:T,format:A,labels:D,name:R,size:L,color:q,readOnly:F=!1,disabled:G=!1,classNames:H,...J},K){const Q=m(L),U=p(q),W=o(T),X=i(s,W),Y=i(u,W,D),Z=i(c,W),$=e=>null==e?[]:Array.isArray(e)?e:[e],[ee,le]=n.useState(()=>$(y)),ne=void 0!==b?$(b):ee,[ae,re]=n.useState(_??!1),te=V??ae,[oe,ie]=n.useState(""),se=n.useMemo(()=>h(f),[f]),ce=n.useDeferredValue(oe).trim(),ue=function(e){const l=e??"";let n=v.get(l);return void 0===n&&(n=new Intl.Collator(e,g),v.set(l,n)),n}(W),de=n.useMemo(()=>x(f,ce,ue),[f,ce,ue]),pe=n.useMemo(()=>""===ce?void 0:j(de),[ce,de]),[me,he]=n.useState(()=>M??[]),fe=pe??N??me,ge=e=>{pe||(void 0===N&&he(e),O?.(e))},ve=e=>{e&&(F||G)||(void 0===V&&re(e),e||ie(""),P?.(e))},be=e=>{void 0===b&&le(e),C?.(e)},xe=e=>e.selectable??(!(e.children&&e.children.length>0)||w),je=e=>l=>{l.preventDefault(),e.children&&e.children.length>0&&ge(fe.includes(e.value)?fe.filter(l=>l!==e.value):[...fe,e.value])},ye=ne.map(e=>se.get(e)).filter(e=>void 0!==e),Ce=0===ye.length?k??"":A?A(ye):ye.map(e=>e.label).reduce((e,l,n)=>0===n?[l]:[...e,", ",l],[]),Se=l=>l.map(l=>e(a,{value:l.value,label:l.label,startIcon:l.startIcon,disabled:l.disabled,onClick:xe(l)?void 0:je(l),className:H?.item,children:l.children?Se(l.children):null},l.value));return e(t,{...J,slug:"tree-select",size:Q,color:U,name:R,locale:W,readOnly:F,disabled:G,triggerRef:K,display:Ce,empty:0===ye.length,clearable:z,onClear:()=>be([]),open:te,onOpenChange:ve,labels:Y,formValue:ne.map(String).join(","),hiddenValues:R?ne.map(e=>({name:R,value:String(e)})):void 0,children:l("div",{className:["mp-tree-select__popup flex max-h-80 w-64 flex-col gap-2",H?.popup??""].filter(Boolean).join(" "),children:[E?e("input",{type:"text",value:oe,placeholder:I??Z.search,"aria-label":I??Z.search,onChange:e=>ie(e.currentTarget.value),className:["mp-tree-select__search text-mp-on-surface w-full shrink-0 bg-transparent","placeholder:text-mp-on-surface-variant px-1 py-1 [font:inherit] outline-none"].join(" ")}):null,e("div",{className:"min-h-0 flex-1 overflow-auto",children:0===de.length?e("p",{className:["mp-tree-select__empty text-mp-on-surface-variant m-0 px-1 py-2",d,H?.empty??""].filter(Boolean).join(" "),children:X.empty}):e(r,{size:Q,variant:"text",multiple:S,selected:ne,onSelectedChange:e=>{const l=e.filter(e=>se.has(e));be(S?l:l.slice(-1)),(B??!S)&&ve(!1)},expanded:fe,onExpandedChange:ge,className:H?.tree,children:Se(de)})})]})})});
@@ -54,6 +54,16 @@ export interface MPFieldLabelProps extends MPFieldOutlineProps {
54
54
  * @default false
55
55
  */
56
56
  multiline?: boolean;
57
+ /**
58
+ * The word the asterisk is read out as, for a control that cannot say it is
59
+ * required itself.
60
+ *
61
+ * Left out wherever `required` is on the control, which is every field drawn
62
+ * on a native input. A picker's trigger is a `<button>`: it takes neither
63
+ * `required` nor `aria-required`, so without this the asterisk was the only
64
+ * sign, and it is `aria-hidden`.
65
+ */
66
+ requiredLabel?: string;
57
67
  }
58
68
  /**
59
69
  * The label a reader actually gets.
@@ -78,7 +88,7 @@ export interface MPFieldLabelProps extends MPFieldOutlineProps {
78
88
  * picker asked for without its glyph — `startIcon={null}`, which is the whole
79
89
  * point of `floatingLabel` on a picker — impossible to open with a mouse.
80
90
  */
81
- export declare function MPFieldLabel({ size, label, required, htmlFor, shrunk, multiline }: MPFieldLabelProps): React.JSX.Element;
91
+ export declare function MPFieldLabel({ size, label, required, htmlFor, shrunk, multiline, requiredLabel }: MPFieldLabelProps): React.JSX.Element;
82
92
  export interface MPFloatingLabel {
83
93
  /** Whether the label is up in the notch right now. */
84
94
  shrunk: boolean;
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as r,Fragment as t,jsxs as o}from"react/jsx-runtime";import*as e from"react";import{Field as a}from"@base-ui/react/field";import{PROSE_TEXT as n}from"./scale.js";const i={xs:"start-1",sm:"start-2",md:"start-3",lg:"start-3",xl:"start-4"},s={xs:"top-[18px]",sm:"top-[18px]",md:"top-5",lg:"top-5",xl:"top-5"};function d(e,a){return o(t,{children:[e,a?r("span",{"aria-hidden":"true",children:" *"}):null]})}export function MPFieldOutline({label:t,required:o=!1,notched:e=!0}){return r("fieldset",{"aria-hidden":"true",className:["pointer-events-none absolute inset-0 m-0 min-w-0 px-2 pt-0",t?"-top-[5px]":"","text-start","rounded-mp-xs border border-mp-outline","transition-[border-color] duration-(--mp-sys-motion-duration-short4)","group-hover:border-mp-on-surface","group-focus-within:border-2 group-focus-within:border-mp-primary","group-data-focused:border-2 group-data-focused:border-mp-primary","group-data-invalid:border-mp-error","group-data-disabled:border-mp-on-surface/12"].filter(Boolean).join(" "),children:t?r("legend",{className:["text-mp-body-small invisible float-none block h-[11px] w-auto overflow-hidden p-0","leading-none","ease-mp-standard transition-[max-width,padding]","duration-(--mp-sys-motion-duration-short4)",e?"max-w-full px-1":"max-w-0 px-0"].join(" "),children:d(t,o)}):null})}export function MPFieldLabel({size:t,label:o,required:e=!1,htmlFor:p,shrunk:l=!0,multiline:u=!1}){return r(a.Label,{...void 0===p?null:{htmlFor:p},"data-mp-shrunk":l?"":void 0,className:["text-mp-on-surface-variant","ease-mp-standard transition-[color,top,font-size,max-width]","duration-(--mp-sys-motion-duration-short4)","pointer-events-none absolute -translate-y-1/2 px-1 leading-none",i[t],l?"text-mp-body-small top-0 max-w-none":[n[t],"max-w-[calc(100%-2rem)] truncate",u?s[t]:"top-1/2"].join(" "),"group-focus-within:text-mp-primary","group-data-focused:text-mp-primary","group-data-invalid:text-mp-error","group-data-disabled:text-mp-on-surface/38"].join(" "),children:d(o,e)})}export function useFloatingLabel({floating:r,filled:t,pinned:o=!1}){const[a,n]=e.useState(!1);return{shrunk:!r||t||a||o,focusProps:{onFocusCapture:()=>n(!0),onBlurCapture:r=>{r.currentTarget.contains(r.relatedTarget)||n(!1)}}}}
2
+ import{jsx as r,Fragment as t,jsxs as e}from"react/jsx-runtime";import*as o from"react";import{Field as a}from"@base-ui/react/field";import{PROSE_TEXT as n}from"./scale.js";import{VISUALLY_HIDDEN as i}from"./visually-hidden.js";const s={xs:"start-1",sm:"start-2",md:"start-3",lg:"start-3",xl:"start-4"},d={xs:"top-[18px]",sm:"top-[18px]",md:"top-5",lg:"top-5",xl:"top-5"};function l(o,a){return e(t,{children:[o,a?r("span",{"aria-hidden":"true",children:" *"}):null]})}export function MPFieldOutline({label:t,required:e=!1,notched:o=!0}){return r("fieldset",{"aria-hidden":"true",className:["pointer-events-none absolute inset-0 m-0 min-w-0 px-2 pt-0",t?"-top-[5px]":"","text-start","rounded-mp-xs border border-mp-outline","transition-[border-color] duration-(--mp-sys-motion-duration-short4)","group-hover:border-mp-on-surface","group-focus-within:border-2 group-focus-within:border-mp-primary","group-data-focused:border-2 group-data-focused:border-mp-primary","group-data-invalid:border-mp-error","group-data-disabled:border-mp-on-surface/12"].filter(Boolean).join(" "),children:t?r("legend",{className:["text-mp-body-small invisible float-none block h-[11px] w-auto overflow-hidden p-0","leading-none","ease-mp-standard transition-[max-width,padding]","duration-(--mp-sys-motion-duration-short4)",o?"max-w-full px-1":"max-w-0 px-0"].join(" "),children:l(t,e)}):null})}export function MPFieldLabel({size:o,label:p,required:u=!1,htmlFor:m,shrunk:c=!0,multiline:x=!1,requiredLabel:f}){return e(a.Label,{...void 0===m?null:{htmlFor:m},"data-mp-shrunk":c?"":void 0,className:["text-mp-on-surface-variant","ease-mp-standard transition-[color,top,font-size,max-width]","duration-(--mp-sys-motion-duration-short4)","pointer-events-none absolute -translate-y-1/2 px-1 leading-none",s[o],c?"text-mp-body-small top-0 max-w-none":[n[o],"max-w-[calc(100%-2rem)] truncate",x?d[o]:"top-1/2"].join(" "),"group-focus-within:text-mp-primary","group-data-focused:text-mp-primary","group-data-invalid:text-mp-error","group-data-disabled:text-mp-on-surface/38"].join(" "),children:[l(p,u),u&&f?e(t,{children:[" ",r("span",{className:i,children:f})]}):null]})}export function useFloatingLabel({floating:r,filled:t,pinned:e=!1}){const[a,n]=o.useState(!1);return{shrunk:!r||t||a||e,focusProps:{onFocusCapture:()=>n(!0),onBlurCapture:r=>{r.currentTarget.contains(r.relatedTarget)||n(!1)}}}}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The value of a field whose control is a button.
3
+ *
4
+ * A picker opens from a popover trigger, and a trigger is a `<button>`: it has
5
+ * no value, takes no `required`, and registers nothing with the `Field` around
6
+ * it. So `required` decided nothing, and `MPForm` neither checked the picker on
7
+ * submit nor saw its value. This is the input that stands in for it.
8
+ *
9
+ * It is Base UI's own `Field.Control`, which is what makes the field count:
10
+ * `MPForm` checks it with every other field, puts its value under the field's
11
+ * name, shows the browser's message in the line under the field, and moves focus
12
+ * to it when it is the first field that failed. Outside an `MPForm` it is a
13
+ * required `<input>` in an ordinary form, which the browser checks before it
14
+ * submits.
15
+ *
16
+ * It has no `name` of its own. The picker's hidden rows are what a form submits,
17
+ * as they always were, and a name here would send the value twice. The name
18
+ * `MPForm` files the value under is the `Field.Root`'s.
19
+ *
20
+ * Its own file rather than a part of `Picker.tsx`, because `MPColorPicker`
21
+ * draws one too, and the split stylesheet is cut a file at a time along the
22
+ * import graph: importing the shell for this would hand the colour picker every
23
+ * class the shell spells out.
24
+ */
25
+ import * as React from 'react';
26
+ export interface MPFieldValueProps {
27
+ /** The value as one string, and `''` while nothing is chosen. */
28
+ value: string;
29
+ required: boolean;
30
+ /** A read-only field is not checked, as a read-only `<input>` is not. */
31
+ readOnly: boolean;
32
+ /** The id of the trigger, which is where focus belongs. */
33
+ targetId: string;
34
+ }
35
+ export declare function MPFieldValue({ value, required, readOnly, targetId }: MPFieldValueProps): React.JSX.Element;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsx as e}from"react/jsx-runtime";import{Field as r}from"@base-ui/react/field";import{VISUALLY_HIDDEN as t}from"./visually-hidden.js";export function MPFieldValue({value:a,required:o,readOnly:n,targetId:d}){return e(r.Control,{value:a,required:o,readOnly:n,tabIndex:-1,"aria-hidden":!0,onFocus:e=>{e.currentTarget.ownerDocument.getElementById(d)?.focus()},className:`${t} start-0 bottom-0 m-0 border-0 p-0`,render:r=>e("input",{...r,name:void 0})})}
@@ -81,7 +81,10 @@ export interface MPPickerShellProps extends MPStyleProps, MPControlEventProps<HT
81
81
  * `null` is how that glyph is asked for by name to go away.
82
82
  */
83
83
  startIcon?: React.ReactNode;
84
- /** Marks the picker required, both to assistive technology and to the label. */
84
+ /**
85
+ * Marks the picker required, both to assistive technology and to the label,
86
+ * and keeps a form from submitting while nothing is chosen.
87
+ */
85
88
  required?: boolean;
86
89
  /** Greys the picker out and stops it opening. */
87
90
  disabled?: boolean;
@@ -123,14 +126,30 @@ interface InternalShellProps extends MPPickerShellProps {
123
126
  /**
124
127
  * `<input type="hidden">` rows, so the control submits with a form.
125
128
  *
126
- * Each row carries its own name, which is why the shell takes no `name` of
127
- * its own: a range picker submits two of them under one name, and the id the
128
- * label points at is generated rather than derived from it.
129
+ * Each row carries its own name: a range picker submits two of them under one
130
+ * name, and the id the label points at is generated rather than derived from
131
+ * it.
129
132
  */
130
133
  hiddenValues?: Array<{
131
134
  name: string;
132
135
  value: string;
133
136
  }>;
137
+ /**
138
+ * The value as one string, `''` while nothing is chosen: what `required` is
139
+ * checked against, and what `MPForm` reports under the field's name. See
140
+ * `MPFieldValue`.
141
+ */
142
+ formValue: string;
143
+ /**
144
+ * The field's own name, which is what `MPForm`'s `errors` are matched by.
145
+ *
146
+ * Base UI finds a field's error by the name its control registers, and a
147
+ * popover trigger registers none, so the name goes on the `Field.Root`. It
148
+ * names no input; the rows above still carry their own.
149
+ */
150
+ name?: string;
151
+ /** The language the label's spoken "required" is written in. */
152
+ locale?: string;
134
153
  children: React.ReactNode;
135
154
  triggerRef?: React.Ref<HTMLButtonElement>;
136
155
  }
@@ -142,7 +161,7 @@ interface InternalShellProps extends MPPickerShellProps {
142
161
  * treatment, and the popup's `surface-container` at elevation 2 — which is the
143
162
  * same floating sheet a menu and a select's list are drawn on.
144
163
  */
145
- export declare function MPPickerShell({ slug, size, color, fullWidth, label, floatingLabel, description, errorMessage, startIcon, required, disabled, readOnly, id, className, style, onKeyDown, onKeyUp, onFocus, onBlur, onClick, onDoubleClick, onContextMenu, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, children, triggerRef }: InternalShellProps): React.JSX.Element;
164
+ export declare function MPPickerShell({ slug, size, color, fullWidth, label, floatingLabel, description, errorMessage, startIcon, required, disabled, readOnly, id, className, style, onKeyDown, onKeyUp, onFocus, onBlur, onClick, onDoubleClick, onContextMenu, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, formValue, name, locale, children, triggerRef }: InternalShellProps): React.JSX.Element;
146
165
  /**
147
166
  * The row of shortcuts under a picker's panel.
148
167
  *
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{Field as r}from"@base-ui/react/field";import{Popover as i}from"@base-ui/react/popover";import{MPIcon as t}from"../components/icon/MPIcon.js";import{CloseIcon as l}from"../constants/icons.js";import{accentSlots as s}from"./accent.js";import{MPFieldLabel as a,MPFieldOutline as p,useFloatingLabel as c}from"./FieldOutline.js";import{MPStateLayer as u}from"./StateLayer.js";import{MPSupportingText as m}from"./SupportingText.js";import{MPWidthSizer as d}from"./WidthSizer.js";import{displaySamples as f}from"./date.js";import{CONTROL_ICON as h,hasContent as x,PROSE_TEXT as g}from"./scale.js";import{FADE as b,PORTAL_LAYER as y}from"./surface.js";export function useDisplaySamples(e,n){const r=`${e??""} ${JSON.stringify(n)}`;return o.useMemo(()=>f(e,n),[r])}const j={xs:{padding:"px-2",height:"h-8"},sm:{padding:"px-3",height:"h-10"},md:{padding:"px-4",height:"h-14"},lg:{padding:"px-4",height:"h-16"},xl:{padding:"px-5",height:"h-18"}};export const POPUP_PAD={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function MPPickerShell({slug:f,size:v="md",color:P="primary",fullWidth:N=!1,label:k,floatingLabel:w=!0,description:C,errorMessage:O,startIcon:M,required:D=!1,disabled:F=!1,readOnly:S=!1,id:z,className:B,style:_,onKeyDown:I,onKeyUp:K,onFocus:R,onBlur:U,onClick:$,onDoubleClick:q,onContextMenu:T,display:A,samples:E,empty:L,clearable:W=!1,onClear:J,open:V,onOpenChange:Z,labels:G,hiddenValues:H,children:Q,triggerRef:X}){const Y=x(O),ee=j[v],ne=o.useId(),oe=z??ne,re=W&&!L&&!(F||S),{shrunk:ie,focusProps:te}=c({floating:w&&x(k),filled:!L,pinned:V||x(M)});return n(r.Root,{disabled:F,invalid:Y,"data-mp-size":v,className:[`mp-${f} group flex-col align-top`,N?"flex w-full":"inline-flex w-fit",B??""].filter(Boolean).join(" "),style:{...s(P),..._},...te,children:[n(i.Root,{open:V,onOpenChange:Z,children:[n("div",{className:"relative w-full",children:[n(i.Trigger,{id:oe,ref:X,disabled:F,nativeButton:!0,onKeyDown:I,onKeyUp:K,onFocus:R,onBlur:U,onClick:$,onDoubleClick:q,onContextMenu:T,className:["relative flex w-full items-center gap-2 select-none","appearance-none border-0 bg-transparent font-[inherit] outline-none",ee.padding,re?"pe-10":"",ee.height,g[v],F?"text-mp-on-surface/38 cursor-default":"text-mp-on-surface "+(S?"cursor-default":"cursor-pointer")].filter(Boolean).join(" "),children:[M?e("span",{className:["flex shrink-0 items-center",F?"text-mp-on-surface/38":"text-mp-on-surface-variant"].join(" "),children:M}):null,n("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:["w-full truncate text-start",L&&!F?"text-mp-on-surface-variant":""].filter(Boolean).join(" "),children:L&&!ie?null:A}),e(d,{samples:E??[]})]})]}),re?n("button",{type:"button","aria-label":G.clear,onClick:J,className:["group/clear rounded-mp-full text-mp-on-surface-variant absolute inset-y-0","end-1 my-auto flex size-8 cursor-pointer items-center justify-center","appearance-none border-0 bg-transparent p-0 font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "),children:[e(u,{className:"group-hover/clear:opacity-8 group-focus-visible/clear:opacity-10"}),e(t,{icon:l,size:h[v]})]}):null,e(p,{label:k,required:D,notched:ie}),x(k)?e(a,{size:v,label:k,required:D,htmlFor:oe,shrunk:ie}):null]}),e(i.Portal,{children:e(i.Positioner,{className:y,sideOffset:4,align:"start",children:e(i.Popup,{initialFocus:!1,style:s(P),className:[`mp-${f}__popup rounded-mp-md shadow-mp-2 bg-mp-surface-container`,"text-mp-on-surface outline-none",POPUP_PAD[v],g[v],b].join(" "),children:Q})})})]}),e(m,{description:C,errorMessage:O,className:ee.padding}),H?.map((n,o)=>e("input",{type:"hidden",name:n.name,value:n.value},o))]})}export function MPPickerFooter({children:n}){return e("div",{className:"border-mp-outline-variant flex items-center justify-end gap-1 border-t pt-1.5",children:n})}export function MPPickerDivider(){return e("div",{"aria-hidden":"true",className:"bg-mp-outline-variant w-px self-stretch"})}export const FOOTER_SIZE={xs:"xs",sm:"xs",md:"sm",lg:"sm",xl:"md"};
2
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as n from"react";import{Field as o}from"@base-ui/react/field";import{Popover as i}from"@base-ui/react/popover";import{MPIcon as t}from"../components/icon/MPIcon.js";import{CloseIcon as l}from"../constants/icons.js";import{accentSlots as a}from"./accent.js";import{MPFieldLabel as s,MPFieldOutline as p,useFloatingLabel as c}from"./FieldOutline.js";import{MPFieldValue as m}from"./FieldValue.js";import{MPStateLayer as u}from"./StateLayer.js";import{MPSupportingText as d}from"./SupportingText.js";import{MPWidthSizer as f}from"./WidthSizer.js";import{displaySamples as h}from"./date.js";import{useMPMessages as x}from"./locale.js";import{COMMON as g}from"./messages/common.js";import{CONTROL_ICON as b,hasContent as j,PROSE_TEXT as y}from"./scale.js";import{FADE as v,PORTAL_LAYER as P}from"./surface.js";export function useDisplaySamples(e,r){const o=`${e??""} ${JSON.stringify(r)}`;return n.useMemo(()=>h(e,r),[o])}const N={xs:{padding:"px-2",height:"h-8"},sm:{padding:"px-3",height:"h-10"},md:{padding:"px-4",height:"h-14"},lg:{padding:"px-4",height:"h-16"},xl:{padding:"px-5",height:"h-18"}};export const POPUP_PAD={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function MPPickerShell({slug:h,size:k="md",color:O="primary",fullWidth:w=!1,label:C,floatingLabel:M=!0,description:D,errorMessage:F,startIcon:S,required:q=!1,disabled:z=!1,readOnly:B=!1,id:I,className:_,style:K,onKeyDown:R,onKeyUp:U,onFocus:$,onBlur:L,onClick:T,onDoubleClick:V,onContextMenu:A,display:E,samples:W,empty:J,clearable:Z=!1,onClear:G,open:H,onOpenChange:Q,labels:X,hiddenValues:Y,formValue:ee,name:re,locale:ne,children:oe,triggerRef:ie}){const te=x(g,ne),le=j(F),ae=N[k],se=n.useId(),pe=I??se,ce=Z&&!J&&!(z||B),{shrunk:me,focusProps:ue}=c({floating:M&&j(C),filled:!J,pinned:H||j(S)});return r(o.Root,{name:re,disabled:z,invalid:le,"data-mp-size":k,className:[`mp-${h} group flex-col align-top`,w?"flex w-full":"inline-flex w-fit",_??""].filter(Boolean).join(" "),style:{...a(O),...K},...ue,children:[r(i.Root,{open:H,onOpenChange:Q,children:[r("div",{className:"relative w-full",children:[r(i.Trigger,{id:pe,ref:ie,disabled:z,nativeButton:!0,onKeyDown:R,onKeyUp:U,onFocus:$,onBlur:L,onClick:T,onDoubleClick:V,onContextMenu:A,className:["relative flex w-full items-center gap-2 select-none","appearance-none border-0 bg-transparent font-[inherit] outline-none",ae.padding,ce?"pe-10":"",ae.height,y[k],z?"text-mp-on-surface/38 cursor-default":"text-mp-on-surface "+(B?"cursor-default":"cursor-pointer")].filter(Boolean).join(" "),children:[S?e("span",{className:["flex shrink-0 items-center",z?"text-mp-on-surface/38":"text-mp-on-surface-variant"].join(" "),children:S}):null,r("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:["w-full truncate text-start",J&&!z?"text-mp-on-surface-variant":""].filter(Boolean).join(" "),children:J&&!me?null:E}),e(f,{samples:W??[]})]})]}),ce?r("button",{type:"button","aria-label":X.clear,onClick:G,className:["group/clear rounded-mp-full text-mp-on-surface-variant absolute inset-y-0","end-1 my-auto flex size-8 cursor-pointer items-center justify-center","appearance-none border-0 bg-transparent p-0 font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "),children:[e(u,{className:"group-hover/clear:opacity-8 group-focus-visible/clear:opacity-10"}),e(t,{icon:l,size:b[k]})]}):null,e(m,{value:ee,required:q,readOnly:B,targetId:pe}),e(p,{label:C,required:q,notched:me}),j(C)?e(s,{size:k,label:C,required:q,requiredLabel:te.required,htmlFor:pe,shrunk:me}):null]}),e(i.Portal,{children:e(i.Positioner,{className:P,sideOffset:4,align:"start",children:e(i.Popup,{initialFocus:!1,style:a(O),className:[`mp-${h}__popup rounded-mp-md shadow-mp-2 bg-mp-surface-container`,"text-mp-on-surface outline-none",POPUP_PAD[k],y[k],v].join(" "),children:oe})})})]}),e(d,{description:D,errorMessage:F,className:ae.padding}),Y?.map((r,n)=>e("input",{type:"hidden",name:r.name,value:r.value},n))]})}export function MPPickerFooter({children:r}){return e("div",{className:"border-mp-outline-variant flex items-center justify-end gap-1 border-t pt-1.5",children:r})}export function MPPickerDivider(){return e("div",{"aria-hidden":"true",className:"bg-mp-outline-variant w-px self-stretch"})}export const FOOTER_SIZE={xs:"xs",sm:"xs",md:"sm",lg:"sm",xl:"md"};