material-plus-ui 1.10.0 → 1.11.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.
- package/README.md +2 -2
- package/dist/components/accordion/MPAccordion.js +1 -1
- package/dist/components/badge/MPBadge.d.ts +7 -6
- package/dist/components/button/MPButton.d.ts +5 -3
- package/dist/components/chip/MPChip.d.ts +1 -1
- package/dist/components/chip/MPChip.js +1 -1
- package/dist/components/collapsible/MPCollapsible.js +1 -1
- package/dist/components/color-picker/MPColorPicker.js +1 -1
- package/dist/components/combobox/MPCombobox.d.ts +3 -2
- package/dist/components/combobox/MPCombobox.js +1 -1
- package/dist/components/command-palette/MPCommandPalette.d.ts +3 -1
- package/dist/components/data-table/MPDataTable.d.ts +3 -2
- package/dist/components/data-table/MPDataTable.js +1 -1
- package/dist/components/date-picker/MPDatePicker.js +1 -1
- package/dist/components/date-range-picker/MPDateRangePicker.js +1 -1
- package/dist/components/date-time-picker/MPDateTimePicker.js +1 -1
- package/dist/components/dialog/MPDialog.d.ts +3 -2
- package/dist/components/floating-action-button/MPFloatingActionButton.d.ts +3 -1
- package/dist/components/floating-bottom-navigation/MPFloatingBottomNavigation.d.ts +10 -1
- package/dist/components/floating-bottom-navigation/MPFloatingBottomNavigation.js +1 -1
- package/dist/components/hover-card/MPHoverCard.d.ts +8 -7
- package/dist/components/icon-button/MPIconButton.js +1 -1
- package/dist/components/list/MPList.d.ts +3 -2
- package/dist/components/pagination/MPPagination.d.ts +4 -4
- package/dist/components/progress-box/MPProgressBox.js +1 -1
- package/dist/components/progress-linear/MPProgressLinear.d.ts +4 -3
- package/dist/components/segmented-button/MPSegmentedButton.js +1 -1
- package/dist/components/sidebar/MPSidebar.d.ts +4 -2
- package/dist/components/snackbar/MPSnackbar.d.ts +8 -6
- package/dist/components/stepper/MPStepper.d.ts +9 -7
- package/dist/components/stepper/MPStepper.js +1 -1
- package/dist/components/table/MPTable.d.ts +7 -3
- package/dist/components/text-field/MPTextField.d.ts +9 -0
- package/dist/components/text-field/MPTextField.js +1 -1
- package/dist/components/time-picker/MPTimePicker.js +1 -1
- package/dist/components/toolbar/MPToolbar.d.ts +3 -3
- package/dist/components/tooltip/MPTooltip.d.ts +6 -0
- package/dist/components/tree-select/MPTreeSelect.d.ts +12 -2
- package/dist/components/tree-select/MPTreeSelect.js +1 -1
- package/dist/internal/FieldOutline.d.ts +11 -1
- package/dist/internal/FieldOutline.js +1 -1
- package/dist/internal/FieldValue.d.ts +35 -0
- package/dist/internal/FieldValue.js +2 -0
- package/dist/internal/Picker.d.ts +24 -5
- package/dist/internal/Picker.js +1 -1
- package/dist/internal/fold.d.ts +45 -0
- package/dist/internal/fold.js +2 -0
- package/dist/internal/i18n.d.ts +6 -0
- package/dist/internal/messages/common.js +1 -1
- package/dist/internal/table.d.ts +4 -4
- package/dist/locales/ar.js +1 -1
- package/dist/locales/de.js +1 -1
- package/dist/locales/es.js +1 -1
- package/dist/locales/fr.js +1 -1
- package/dist/locales/hi.js +1 -1
- package/dist/locales/id.js +1 -1
- package/dist/locales/it.js +1 -1
- package/dist/locales/ja.js +1 -1
- package/dist/locales/ko.js +1 -1
- package/dist/locales/nl.js +1 -1
- package/dist/locales/pl.js +1 -1
- package/dist/locales/pt.js +1 -1
- package/dist/locales/ru.js +1 -1
- package/dist/locales/th.js +1 -1
- package/dist/locales/tr.js +1 -1
- package/dist/locales/vi.js +1 -1
- package/dist/locales/zh-hans.js +1 -1
- package/dist/locales/zh-hant.js +1 -1
- package/dist/styles/accordion.css +1 -1
- package/dist/styles/calendar.css +1 -1
- package/dist/styles/collapsible.css +1 -1
- package/dist/styles/color-picker.css +1 -1
- package/dist/styles/combobox.css +1 -1
- package/dist/styles/date-picker.css +1 -1
- package/dist/styles/date-range-picker.css +1 -1
- package/dist/styles/date-time-picker.css +1 -1
- package/dist/styles/number-field.css +1 -1
- package/dist/styles/progress-linear.css +1 -1
- package/dist/styles/segmented-button.css +1 -1
- package/dist/styles/select.css +1 -1
- package/dist/styles/stepper.css +1 -1
- package/dist/styles/text-field.css +1 -1
- package/dist/styles/time-picker.css +1 -1
- package/dist/styles/tree-select.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +62 -25
- package/package.json +1 -1
|
@@ -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:["
|
|
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
|
|
20
|
-
* the
|
|
21
|
-
* a red bar in a
|
|
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
|
|
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
|
|
105
|
-
*
|
|
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
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* region added to the document at the same instant as the message inside it
|
|
34
|
-
*
|
|
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
|
|
117
|
-
*
|
|
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
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* with its own Next and
|
|
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
|
|
127
|
-
* a progress indicator for a sequence the application's own Next and
|
|
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
|
|
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
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
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
|
|
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
|
|
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
|
|
103
|
-
*
|
|
104
|
-
*
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
127
|
-
*
|
|
128
|
-
*
|
|
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
|
*
|
package/dist/internal/Picker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as e,jsxs as
|
|
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"};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When a folding panel may stop clipping what is inside it.
|
|
3
|
+
*
|
|
4
|
+
* `MPAccordion` and `MPCollapsible` animate a panel's height, and both clip the
|
|
5
|
+
* panel while it moves so the body is a window rather than a squashed copy of
|
|
6
|
+
* itself. That clip is the animation's, not the panel's, and it has no business
|
|
7
|
+
* surviving the animation: a settled panel that goes on clipping cuts the top
|
|
8
|
+
* off the first thing in it that draws outside its own box. A text field's
|
|
9
|
+
* floating label is exactly that — it sits *on* the field's top edge, which is
|
|
10
|
+
* the panel's top edge — so a form in a fold arrived with its first label
|
|
11
|
+
* sliced in half, and nothing in the console said so. A select's popup, a
|
|
12
|
+
* tooltip and a focus ring are the same bug with different pixels.
|
|
13
|
+
*
|
|
14
|
+
* It cannot be a `data-open:` variant on its own: `data-open` is set for the
|
|
15
|
+
* whole of the opening animation, which is the part that has to clip. The state
|
|
16
|
+
* this needs is "open **and** no longer moving", and nothing in the DOM says
|
|
17
|
+
* that, so `useSettledPanel` works it out from the transition itself.
|
|
18
|
+
*
|
|
19
|
+
* Its own file because the two components share it, and two copies of one rule
|
|
20
|
+
* are two copies that will eventually disagree. It was the accordion's alone
|
|
21
|
+
* until the collapsible turned out to clip the same label.
|
|
22
|
+
*/
|
|
23
|
+
import * as React from 'react';
|
|
24
|
+
/** Added to a panel once it has finished opening. */
|
|
25
|
+
export declare const PANEL_SETTLED = "data-open:overflow-visible";
|
|
26
|
+
/**
|
|
27
|
+
* Whether the panel has finished opening, and the two hooks into it that say so.
|
|
28
|
+
*
|
|
29
|
+
* - The height's `transitionend` decides it, either way. Base UI's
|
|
30
|
+
* `transitionStatus` cannot: it marks the first frame and the last, and what
|
|
31
|
+
* is needed here is the stretch between them.
|
|
32
|
+
* - The callback ref covers the two panels that never transition at all — one
|
|
33
|
+
* that started open, and any panel under reduced motion — both of which would
|
|
34
|
+
* otherwise wait for an end that is not coming. It runs during the commit,
|
|
35
|
+
* before the browser paints, so a panel opening the ordinary way is clipped by
|
|
36
|
+
* the time there is anything to see.
|
|
37
|
+
*
|
|
38
|
+
* Closing needs nothing: `data-open` goes the moment a fold is asked to close,
|
|
39
|
+
* which puts the clip back for the whole of the way down.
|
|
40
|
+
*/
|
|
41
|
+
export declare function useSettledPanel(): {
|
|
42
|
+
attach: (node: HTMLDivElement | null) => void;
|
|
43
|
+
settled: boolean;
|
|
44
|
+
onTransitionEnd: (event: React.TransitionEvent<HTMLDivElement>) => void;
|
|
45
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import*as t from"react";export const PANEL_SETTLED="data-open:overflow-visible";export function useSettledPanel(){const e=t.useRef(null),[a,r]=t.useState(!1);return{attach:t.useCallback(t=>{var a;e.current=t,t&&r(t.hasAttribute("data-open")&&!((a=t).hasAttribute("data-starting-style")&&parseFloat(getComputedStyle(a).transitionDuration)>0))},[]),settled:a,onTransitionEnd:t.useCallback(t=>{t.target===e.current&&"height"===t.propertyName&&r(e.current.hasAttribute("data-open"))},[])}}
|
package/dist/internal/i18n.d.ts
CHANGED
|
@@ -42,6 +42,12 @@ export interface MPMessages {
|
|
|
42
42
|
removeNamed: string;
|
|
43
43
|
/** The spinner that replaces a button's leading glyph while it waits. */
|
|
44
44
|
loading: string;
|
|
45
|
+
/**
|
|
46
|
+
* The asterisk after a field's label, read out where the control cannot
|
|
47
|
+
* say it itself. A picker's trigger is a `<button>`, which takes neither
|
|
48
|
+
* `required` nor `aria-required`, so its label carries the word instead.
|
|
49
|
+
*/
|
|
50
|
+
required: string;
|
|
45
51
|
};
|
|
46
52
|
/**
|
|
47
53
|
* MPTextField.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const COMMON={name:"common",en:{close:"Close",clear:"Clear",open:"Open",remove:"Remove",removeNamed:"Remove {label}",loading:"Loading"}};
|
|
1
|
+
export const COMMON={name:"common",en:{close:"Close",clear:"Clear",open:"Open",remove:"Remove",removeNamed:"Remove {label}",loading:"Loading",required:"Required"}};
|
package/dist/internal/table.d.ts
CHANGED
|
@@ -13,10 +13,10 @@ import type { MPDensity, MPSize } from '../types.js';
|
|
|
13
13
|
export declare function cellPadX(size: MPSize, density: MPDensity): string;
|
|
14
14
|
export declare function cellPadY(size: MPSize, density: MPDensity): string;
|
|
15
15
|
/**
|
|
16
|
-
* What a cell is set in.
|
|
17
|
-
*
|
|
18
|
-
* size one weight up, so a heading
|
|
19
|
-
* column's measure.
|
|
16
|
+
* What a cell is set in. Material's data table puts its cells in Body 2 and its
|
|
17
|
+
* column headings in Subtitle 2, which MD3's scale calls `body-medium` and
|
|
18
|
+
* `title-small` — 14px at weight 500, the same size one weight up, so a heading
|
|
19
|
+
* reads as a heading without changing the column's measure.
|
|
20
20
|
*/
|
|
21
21
|
export declare const CELL_TEXT: Record<MPSize, string>;
|
|
22
22
|
export declare const HEAD_TEXT: Record<MPSize, string>;
|