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