material-plus-ui 1.3.1 → 1.5.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/.fix.py +92 -0
- package/README.md +2 -2
- package/dist/components/alert/MPAlert.d.ts +26 -0
- package/dist/components/alert/MPAlert.js +1 -1
- package/dist/components/alert/index.d.ts +1 -1
- package/dist/components/animate-marquee/MPAnimateMarquee.js +1 -1
- package/dist/components/avatar/MPAvatar.js +1 -1
- package/dist/components/avatar-group/MPAvatarGroup.d.ts +74 -0
- package/dist/components/avatar-group/MPAvatarGroup.js +2 -0
- package/dist/components/avatar-group/index.d.ts +2 -0
- package/dist/components/avatar-group/index.js +1 -0
- package/dist/components/breadcrumb/MPBreadcrumb.d.ts +10 -4
- package/dist/components/breadcrumb/MPBreadcrumb.js +1 -1
- package/dist/components/button/MPButton.js +1 -1
- package/dist/components/button-group/MPButtonGroup.d.ts +9 -0
- package/dist/components/button-group/MPButtonGroup.js +1 -1
- package/dist/components/carousel/MPCarousel.d.ts +12 -7
- package/dist/components/carousel/MPCarousel.js +1 -1
- package/dist/components/chat-bubble/MPChatBubble.d.ts +15 -2
- package/dist/components/chat-bubble/MPChatBubble.js +1 -1
- package/dist/components/checkbox/MPCheckbox.d.ts +6 -0
- package/dist/components/checkbox/MPCheckbox.js +1 -1
- package/dist/components/color-picker/MPColorPicker.d.ts +20 -17
- package/dist/components/color-picker/MPColorPicker.js +1 -1
- package/dist/components/combobox/MPCombobox.d.ts +22 -4
- package/dist/components/combobox/MPCombobox.js +1 -1
- package/dist/components/command-palette/MPCommandPalette.d.ts +132 -0
- package/dist/components/command-palette/MPCommandPalette.js +2 -0
- package/dist/components/command-palette/index.d.ts +2 -0
- package/dist/components/command-palette/index.js +1 -0
- package/dist/components/container/MPContainer.js +1 -1
- package/dist/components/date-time-picker/MPDateTimePicker.d.ts +5 -0
- package/dist/components/dialog/MPDialog.js +1 -1
- package/dist/components/divider/MPDivider.js +1 -1
- package/dist/components/drawer/MPDrawer.js +1 -1
- package/dist/components/fieldset/MPFieldset.d.ts +52 -0
- package/dist/components/fieldset/MPFieldset.js +2 -0
- package/dist/components/fieldset/index.d.ts +2 -0
- package/dist/components/fieldset/index.js +1 -0
- package/dist/components/file-picker/MPFilePicker.d.ts +10 -3
- package/dist/components/file-picker/MPFilePicker.js +1 -1
- package/dist/components/floating-action-button/MPFloatingActionButton.js +1 -1
- package/dist/components/footer/MPFooter.d.ts +94 -0
- package/dist/components/footer/MPFooter.js +2 -0
- package/dist/components/footer/index.d.ts +2 -0
- package/dist/components/footer/index.js +1 -0
- package/dist/components/form/MPForm.d.ts +73 -0
- package/dist/components/form/MPForm.js +2 -0
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.js +1 -0
- package/dist/components/header/MPHeader.d.ts +122 -0
- package/dist/components/header/MPHeader.js +2 -0
- package/dist/components/header/index.d.ts +2 -0
- package/dist/components/header/index.js +1 -0
- package/dist/components/highlight/MPHighlight.d.ts +7 -0
- package/dist/components/menu/MPMenu.d.ts +4 -2
- package/dist/components/menu/MPMenu.js +1 -1
- package/dist/components/menubar/MPMenubar.d.ts +89 -0
- package/dist/components/menubar/MPMenubar.js +2 -0
- package/dist/components/menubar/index.d.ts +2 -0
- package/dist/components/menubar/index.js +1 -0
- package/dist/components/navigation-menu/MPNavigationMenu.d.ts +158 -0
- package/dist/components/navigation-menu/MPNavigationMenu.js +2 -0
- package/dist/components/navigation-menu/index.d.ts +2 -0
- package/dist/components/navigation-menu/index.js +1 -0
- package/dist/components/number-field/MPNumberField.d.ts +19 -4
- package/dist/components/number-field/MPNumberField.js +1 -1
- package/dist/components/overlay/MPOverlay.d.ts +8 -2
- package/dist/components/overlay/MPOverlay.js +1 -1
- package/dist/components/page-layout/MPPageLayout.d.ts +145 -0
- package/dist/components/page-layout/MPPageLayout.js +2 -0
- package/dist/components/page-layout/index.d.ts +2 -0
- package/dist/components/page-layout/index.js +1 -0
- package/dist/components/panes/MPPanes.js +1 -1
- package/dist/components/popover/MPPopover.js +1 -1
- package/dist/components/progress-box/MPProgressBox.js +1 -1
- package/dist/components/progress-circular/MPProgressCircular.js +1 -1
- package/dist/components/progress-linear/MPProgressLinear.js +1 -1
- package/dist/components/radio-group/MPRadioGroup.d.ts +12 -0
- package/dist/components/radio-group/MPRadioGroup.js +1 -1
- package/dist/components/segmented-button/MPSegmentedButton.d.ts +7 -0
- package/dist/components/segmented-button/MPSegmentedButton.js +1 -1
- package/dist/components/select/MPSelect.d.ts +19 -1
- package/dist/components/select/MPSelect.js +1 -1
- package/dist/components/shortcut/MPShortcut.js +1 -1
- package/dist/components/sidebar/MPSidebar.d.ts +160 -0
- package/dist/components/sidebar/MPSidebar.js +2 -0
- package/dist/components/sidebar/MPSidebarTrigger.d.ts +45 -0
- package/dist/components/sidebar/MPSidebarTrigger.js +2 -0
- package/dist/components/sidebar/index.d.ts +4 -0
- package/dist/components/sidebar/index.js +1 -0
- package/dist/components/skeleton/MPSkeleton.js +1 -1
- package/dist/components/slider/MPSlider.d.ts +6 -0
- package/dist/components/slider/MPSlider.js +1 -1
- package/dist/components/snackbar/MPSnackbar.js +1 -1
- package/dist/components/switch/MPSwitch.d.ts +6 -0
- package/dist/components/switch/MPSwitch.js +1 -1
- package/dist/components/table/MPTable.d.ts +27 -5
- package/dist/components/table/MPTable.js +1 -1
- package/dist/components/text-field/MPTextField.d.ts +21 -2
- package/dist/components/text-field/MPTextField.js +1 -1
- package/dist/components/text-link/MPTextLink.d.ts +7 -1
- package/dist/components/text-link/MPTextLink.js +1 -1
- package/dist/components/time-picker/MPTimePicker.d.ts +4 -0
- package/dist/components/toggle/MPToggle.d.ts +72 -0
- package/dist/components/toggle/MPToggle.js +2 -0
- package/dist/components/toggle/index.d.ts +2 -0
- package/dist/components/toggle/index.js +1 -0
- package/dist/components/toggle-group/MPToggleGroup.d.ts +74 -0
- package/dist/components/toggle-group/MPToggleGroup.js +2 -0
- package/dist/components/toggle-group/index.d.ts +2 -0
- package/dist/components/toggle-group/index.js +1 -0
- package/dist/components/tooltip/MPTooltip.js +1 -1
- package/dist/components/transfer/MPTransfer.d.ts +98 -0
- package/dist/components/transfer/MPTransfer.js +2 -0
- package/dist/components/transfer/index.d.ts +2 -0
- package/dist/components/transfer/index.js +1 -0
- package/dist/constants/glyphs.d.ts +10 -0
- package/dist/constants/glyphs.js +1 -1
- package/dist/constants/icons.d.ts +1 -0
- package/dist/constants/icons.js +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1 -1
- package/dist/internal/Calendar.js +1 -1
- package/dist/internal/FieldOutline.js +1 -1
- package/dist/internal/SupportingText.d.ts +1 -1
- package/dist/internal/SupportingText.js +1 -1
- package/dist/internal/animate.d.ts +0 -17
- package/dist/internal/animate.js +1 -1
- package/dist/internal/avatar-group.d.ts +22 -0
- package/dist/internal/avatar-group.js +2 -0
- package/dist/internal/button-group.d.ts +20 -1
- package/dist/internal/button-group.js +1 -1
- package/dist/internal/color.d.ts +0 -5
- package/dist/internal/color.js +1 -1
- package/dist/internal/date.js +1 -1
- package/dist/internal/i18n.d.ts +201 -4
- package/dist/internal/keys.d.ts +72 -0
- package/dist/internal/keys.js +2 -0
- package/dist/internal/length.d.ts +42 -0
- package/dist/internal/length.js +1 -0
- package/dist/internal/link.d.ts +44 -0
- package/dist/internal/link.js +1 -0
- package/dist/internal/locale.d.ts +20 -1
- package/dist/internal/locale.js +1 -1
- package/dist/internal/messages/breadcrumb.d.ts +3 -0
- package/dist/internal/messages/breadcrumb.js +1 -0
- package/dist/internal/messages/carousel.d.ts +3 -0
- package/dist/internal/messages/carousel.js +1 -0
- package/dist/internal/messages/color-picker.d.ts +3 -0
- package/dist/internal/messages/color-picker.js +1 -0
- package/dist/internal/messages/combobox.d.ts +3 -0
- package/dist/internal/messages/combobox.js +1 -0
- package/dist/internal/messages/command.d.ts +3 -0
- package/dist/internal/messages/command.js +1 -0
- package/dist/internal/messages/file-picker.d.ts +3 -0
- package/dist/internal/messages/file-picker.js +1 -0
- package/dist/internal/messages/layout.d.ts +3 -0
- package/dist/internal/messages/layout.js +1 -0
- package/dist/internal/messages/number-field.d.ts +3 -0
- package/dist/internal/messages/number-field.js +1 -0
- package/dist/internal/messages/overlay.d.ts +3 -0
- package/dist/internal/messages/overlay.js +1 -0
- package/dist/internal/messages/table.d.ts +3 -0
- package/dist/internal/messages/table.js +1 -0
- package/dist/internal/messages/text-link.d.ts +3 -0
- package/dist/internal/messages/text-link.js +1 -0
- package/dist/internal/messages/transfer.d.ts +3 -0
- package/dist/internal/messages/transfer.js +1 -0
- package/dist/internal/page-layout.d.ts +182 -0
- package/dist/internal/page-layout.js +2 -0
- package/dist/internal/scale.d.ts +17 -0
- package/dist/internal/scale.js +1 -1
- 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/alert.css +1 -1
- package/dist/styles/avatar-group.css +2 -0
- package/dist/styles/avatar.css +1 -1
- package/dist/styles/badge.css +1 -1
- package/dist/styles/blockquote.css +1 -1
- package/dist/styles/bottom-navigation.css +1 -1
- package/dist/styles/box.css +1 -1
- package/dist/styles/breadcrumb.css +1 -1
- package/dist/styles/button-group.css +1 -1
- package/dist/styles/button.css +1 -1
- package/dist/styles/card.css +1 -1
- package/dist/styles/carousel.css +1 -1
- package/dist/styles/chat-bubble.css +1 -1
- package/dist/styles/checkbox.css +1 -1
- package/dist/styles/chip.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/command-palette.css +2 -0
- 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/dialog.css +1 -1
- package/dist/styles/divider.css +1 -1
- package/dist/styles/drawer.css +1 -1
- package/dist/styles/empty.css +1 -1
- package/dist/styles/fieldset.css +2 -0
- package/dist/styles/file-picker.css +1 -1
- package/dist/styles/floating-action-button.css +1 -1
- package/dist/styles/footer.css +2 -0
- package/dist/styles/form.css +2 -0
- package/dist/styles/header.css +2 -0
- package/dist/styles/highlight.css +1 -1
- package/dist/styles/icon-button.css +1 -1
- package/dist/styles/list.css +1 -1
- package/dist/styles/locale.css +1 -1
- package/dist/styles/menu.css +1 -1
- package/dist/styles/menubar.css +2 -0
- package/dist/styles/navigation-menu.css +2 -0
- package/dist/styles/number-field.css +1 -1
- package/dist/styles/otp-field.css +1 -1
- package/dist/styles/overlay.css +1 -1
- package/dist/styles/page-layout.css +2 -0
- package/dist/styles/pagination.css +1 -1
- package/dist/styles/panes.css +1 -1
- package/dist/styles/pill.css +1 -1
- package/dist/styles/popover.css +1 -1
- package/dist/styles/progress-box.css +1 -1
- package/dist/styles/progress-circular.css +1 -1
- package/dist/styles/progress-linear.css +1 -1
- package/dist/styles/radio-group.css +1 -1
- package/dist/styles/segmented-button.css +1 -1
- package/dist/styles/select.css +1 -1
- package/dist/styles/sidebar.css +2 -0
- package/dist/styles/skeleton.css +1 -1
- package/dist/styles/slider.css +1 -1
- package/dist/styles/spoiler.css +1 -1
- package/dist/styles/switch.css +1 -1
- package/dist/styles/table.css +1 -1
- package/dist/styles/tabs.css +1 -1
- package/dist/styles/text-field.css +1 -1
- package/dist/styles/text-link.css +1 -1
- package/dist/styles/time-picker.css +1 -1
- package/dist/styles/timeline.css +1 -1
- package/dist/styles/toggle-group.css +2 -0
- package/dist/styles/toggle.css +2 -0
- package/dist/styles/transfer.css +2 -0
- package/dist/styles.css +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as t,jsxs as e}from"react/jsx-runtime";import*as a from"react";import{Button as
|
|
2
|
+
import{jsx as t,jsxs as e}from"react/jsx-runtime";import*as a from"react";import{Button as n}from"@base-ui/react/button";import{accentSlots as o}from"../../internal/accent.js";import{cssLength as i}from"../../internal/length.js";import{MPStateLayer as s}from"../../internal/StateLayer.js";import{hasContent as r}from"../../internal/scale.js";const m={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"bg-mp-surface-container-high text-(--_mp-accent)"},l={xs:"h-10",sm:"h-12",md:"h-14",lg:"h-18",xl:"h-24"},p={xs:"min-w-10 gap-0 px-0",sm:"min-w-12 gap-0 px-0",md:"min-w-14 gap-0 px-0",lg:"min-w-18 gap-0 px-0",xl:"min-w-24 gap-0 px-0"},d={xs:"rounded-mp-md",sm:"rounded-mp-lg",md:"rounded-mp-lg",lg:"rounded-mp-xl",xl:"rounded-mp-xl"},f={xs:24,sm:24,md:24,lg:30,xl:36},c={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"},x={xs:"min-w-16 gap-1.5 px-3",sm:"min-w-18 gap-2 px-4",md:"min-w-20 gap-2 px-4",lg:"min-w-24 gap-2.5 px-5",xl:"min-w-28 gap-3 px-6"},u={absolute:"absolute z-30",sticky:"sticky z-30",fixed:"fixed z-40"},b={"top-start":"top-(--_mp-fab-offset) start-(--_mp-fab-offset)","top-end":"top-(--_mp-fab-offset) end-(--_mp-fab-offset)","bottom-start":"bottom-(--_mp-fab-offset) start-(--_mp-fab-offset)","bottom-end":"bottom-(--_mp-fab-offset) end-(--_mp-fab-offset)"};export const MPFloatingActionButton=/*@__PURE__*/a.forwardRef(function({icon:a,label:g,extended:h=!1,variant:w="tonal",color:y="primary",size:_="md",position:j="fixed",corner:v="bottom-end",offset:k=16,disabled:z=!1,type:N="button",className:B,style:$,...A},F){return e(n,{ref:F,type:N,disabled:z,"aria-label":g,"data-mp-size":_,"data-mp-variant":w,className:["mp-fab group inline-flex shrink-0 items-center justify-center","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,box-shadow,color,min-width,padding,gap]","duration-(--mp-sys-motion-duration-short4) ease-mp-standard",d[_],l[_],c[_],h?x[_]:p[_],z?"bg-mp-on-surface/12 text-mp-on-surface/38 cursor-default shadow-none":`${m[w]} shadow-mp-3`,"static"===j?"relative":`${u[j]} ${b[v]}`,B??""].filter(Boolean).join(" "),style:{...o(y),"--_mp-fab-offset":i(k),...$},...A,children:[z?null:t(s,{}),r(a)?t("span",{className:"relative flex shrink-0 items-center justify-center",style:{width:f[_],height:f[_]},children:a}):null,t("span",{className:["relative grid transition-[grid-template-columns]","duration-(--mp-sys-motion-duration-short4) ease-mp-standard",h?"grid-cols-[1fr]":"grid-cols-[0fr]"].join(" "),children:t("span",{className:"min-w-0 truncate",children:g})})]})});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { MPPosition, MPSize, MPVariant } from '../../types.js';
|
|
4
|
+
export interface MPFooterProps extends Omit<React.ComponentPropsWithoutRef<'footer'>, 'title'> {
|
|
5
|
+
/**
|
|
6
|
+
* How the sheet sits in the page's scroll.
|
|
7
|
+
*
|
|
8
|
+
* `static` — the default, and the opposite of [MPHeader](./header)'s — is what
|
|
9
|
+
* a footer *is*: the thing at the end of the document, reached by scrolling to
|
|
10
|
+
* it. `sticky` and `fixed` are for the bar that has to stay in reach — a
|
|
11
|
+
* form's save row, a cookie notice — and an [MPPageLayout](./page-layout)
|
|
12
|
+
* reserves the height a `fixed` one takes out of the flow.
|
|
13
|
+
* @default 'static'
|
|
14
|
+
*/
|
|
15
|
+
position?: MPPosition;
|
|
16
|
+
/**
|
|
17
|
+
* How much surface the sheet paints, on the **container** ladder — a footer is
|
|
18
|
+
* never dyed, because what sits on it arrives with colours of its own.
|
|
19
|
+
*
|
|
20
|
+
* `outlined` is the default here and `tonal` is [MPHeader](./header)'s,
|
|
21
|
+
* because the two sit against different things. A header is over content that
|
|
22
|
+
* is passing underneath it and needs a tone of its own to stay legible; a
|
|
23
|
+
* footer has the end of the document above it and nothing below, so the
|
|
24
|
+
* hairline is the whole of what says the document ended.
|
|
25
|
+
* @default 'outlined'
|
|
26
|
+
*/
|
|
27
|
+
variant?: MPVariant;
|
|
28
|
+
/**
|
|
29
|
+
* The sheet's scale — its gutter and the air above and below its content. As
|
|
30
|
+
* on [MPBox](./box), `size` here is the size of the *sheet*: it sets no height
|
|
31
|
+
* and no type scale.
|
|
32
|
+
* @default 'md'
|
|
33
|
+
*/
|
|
34
|
+
size?: MPSize;
|
|
35
|
+
/**
|
|
36
|
+
* Holds the content to a measure and centres it while the sheet itself still
|
|
37
|
+
* spans the window. The same ladder [MPContainer](./container)'s `maxWidth`
|
|
38
|
+
* uses.
|
|
39
|
+
* @default 'none'
|
|
40
|
+
*/
|
|
41
|
+
maxWidth?: MPSize | 'none';
|
|
42
|
+
/**
|
|
43
|
+
* The gutter, and the air above and below.
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
padded?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The name the region is announced by. Worth writing when a page has more than
|
|
49
|
+
* one `<footer>` in it — an article's own and the site's.
|
|
50
|
+
*/
|
|
51
|
+
label?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Renders something other than a `<footer>`. Base UI's own escape hatch, and
|
|
54
|
+
* rarely what you want: at the top level of a document that tag is the
|
|
55
|
+
* `contentinfo` landmark, and it is what says "this is the site's own
|
|
56
|
+
* information" rather than "this is more of the article".
|
|
57
|
+
*/
|
|
58
|
+
render?: useRender.RenderProp;
|
|
59
|
+
/**
|
|
60
|
+
* Everything in it.
|
|
61
|
+
*
|
|
62
|
+
* A footer's content is four columns of links on one site and a single line on
|
|
63
|
+
* the next, all of it the caller's — which is why this component has slots for
|
|
64
|
+
* nothing and room for anything.
|
|
65
|
+
*/
|
|
66
|
+
children?: React.ReactNode;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The sheet at the end of a page.
|
|
70
|
+
*
|
|
71
|
+
* A real `<footer>`, which is the whole reason it is a component rather than a
|
|
72
|
+
* div: at the top level of a document that tag is the `contentinfo` landmark —
|
|
73
|
+
* the region a screen reader offers as "the site's own information", and the one
|
|
74
|
+
* a search engine reads the copyright, the address and the site map out of.
|
|
75
|
+
*
|
|
76
|
+
* ## Why it has no slots, and [MPHeader](./header) does
|
|
77
|
+
*
|
|
78
|
+
* Because a header's three regions are a fixed arrangement worth writing once,
|
|
79
|
+
* and a footer's content is not an arrangement at all. Four columns of links on
|
|
80
|
+
* one site, a copyright line on the next, a language picker and a row of logos
|
|
81
|
+
* on the third. A component that guessed would be a component every second site
|
|
82
|
+
* had to fight.
|
|
83
|
+
*
|
|
84
|
+
* What it decides instead is the **sheet**: the surface, the gutter, the measure,
|
|
85
|
+
* and whether it stays in reach. Everything above that is an
|
|
86
|
+
* [MPGrid](./grid) or an [MPContainer](./container) the caller puts inside it.
|
|
87
|
+
*
|
|
88
|
+
* ## Inside a layout, and outside one
|
|
89
|
+
*
|
|
90
|
+
* Inside an [MPPageLayout](./page-layout) it registers itself, so a `fixed`
|
|
91
|
+
* footer's height is reserved rather than sitting on top of the last paragraph.
|
|
92
|
+
* Outside one it is simply a sheet.
|
|
93
|
+
*/
|
|
94
|
+
export declare const MPFooter: React.ForwardRefExoticComponent<MPFooterProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{jsx as e}from"react/jsx-runtime";import*as t from"react";import{useRender as o}from"@base-ui/react/use-render";import{BAR_SURFACE as r,MPPageLayoutContext as a}from"../../internal/page-layout.js";import{MEASURE as i,SHEET_PAD_X as n,SHEET_PAD_Y as s}from"../../internal/scale.js";const l={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 MPFooter=/*@__PURE__*/t.forwardRef(function({position:m="static",variant:c="outlined",size:d="md",maxWidth:f="none",padded:u=!0,label:p,render:b,className:x,children:j,...z},h){const{register:v}=t.useContext(a),w=t.useCallback(e=>{v("footer",e),"function"==typeof h?h(e):h&&(h.current=e)},[v,h]);return o({render:b??e("footer",{}),ref:w,props:{"aria-label":p,"data-mp-size":d,"data-mp-variant":c,className:["mp-footer text-mp-on-surface box-border w-full min-w-0",r[c],"outlined"===c?"border-mp-outline-variant border-t":"",l[m],x??""].filter(Boolean).join(" "),children:e("div",{className:["mp-footer__inner w-full",u?`${n[d]} ${s[d]}`:"","none"===f?"":`${i[f]} mx-auto`].filter(Boolean).join(" "),children:j}),...z}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPFooter}from"./MPFooter.js";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { MPSize } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* When a field decides whether it is valid.
|
|
5
|
+
*
|
|
6
|
+
* Base UI's own three, under Base UI's own spelling. This is one of the few
|
|
7
|
+
* places the library does *not* invent a word of its own: `validationMode` is
|
|
8
|
+
* what a caller will read everywhere else, and a nicer synonym would only be a
|
|
9
|
+
* word they had to translate back.
|
|
10
|
+
*/
|
|
11
|
+
export type MPFormValidationMode = 'onSubmit' | 'onBlur' | 'onChange';
|
|
12
|
+
/** Errors that came from somewhere else, keyed by the field's `name`. */
|
|
13
|
+
export type MPFormErrors = Record<string, string | string[]>;
|
|
14
|
+
export interface MPFormProps extends Omit<React.ComponentPropsWithoutRef<'form'>, 'onSubmit'> {
|
|
15
|
+
/**
|
|
16
|
+
* When a field validates.
|
|
17
|
+
*
|
|
18
|
+
* - `onSubmit` — on submit, and on every change afterwards. The default, and
|
|
19
|
+
* the only one that does not tell somebody their email address is wrong
|
|
20
|
+
* while they are still typing it.
|
|
21
|
+
* - `onBlur` — when a field loses focus.
|
|
22
|
+
* - `onChange` — on every keystroke.
|
|
23
|
+
* @default 'onSubmit'
|
|
24
|
+
*/
|
|
25
|
+
validationMode?: MPFormValidationMode;
|
|
26
|
+
/**
|
|
27
|
+
* Errors from outside the browser's own validation — a server, a form action,
|
|
28
|
+
* a schema — keyed by the `name` of the field each belongs to.
|
|
29
|
+
*
|
|
30
|
+
* They are shown **on the field**, and cleared as soon as that field changes.
|
|
31
|
+
*/
|
|
32
|
+
errors?: MPFormErrors;
|
|
33
|
+
/**
|
|
34
|
+
* Called on a valid submit, with the form's values. The native submit event is
|
|
35
|
+
* prevented, so nothing navigates.
|
|
36
|
+
*/
|
|
37
|
+
onSubmit?: (values: Record<string, unknown>) => void;
|
|
38
|
+
/**
|
|
39
|
+
* The gap between the form's children. A form is a stack, and this is which
|
|
40
|
+
* rung of the [ladder](../../design/prop-conventions#size) it stacks on.
|
|
41
|
+
* @default 'md'
|
|
42
|
+
*/
|
|
43
|
+
size?: MPSize;
|
|
44
|
+
children?: React.ReactNode;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A `<form>` that knows which of its fields is wrong.
|
|
48
|
+
*
|
|
49
|
+
* On its own, a page of [MPTextField](./text-field)s validates one field at a
|
|
50
|
+
* time, and a failed submit leaves the reader to go and find the red one. What
|
|
51
|
+
* this adds is the part that has to be owned **above** the fields: a submit
|
|
52
|
+
* collects every field's validity at once, focus lands on the first one that
|
|
53
|
+
* failed, and `errors` puts a server's answer back on the field it belongs to
|
|
54
|
+
* rather than in a banner at the top of the page.
|
|
55
|
+
*
|
|
56
|
+
* ## It is not a form library
|
|
57
|
+
*
|
|
58
|
+
* There is no schema here, no resolver and no field array. A project that wants
|
|
59
|
+
* those keeps the one it already has and hands the result to `errors`, which is
|
|
60
|
+
* the seam this is built around — and it is a seam rather than an integration
|
|
61
|
+
* precisely because every one of those libraries can produce
|
|
62
|
+
* `{ [name]: message }`.
|
|
63
|
+
*
|
|
64
|
+
* ## Why it lays its children out at all
|
|
65
|
+
*
|
|
66
|
+
* Because a form is a **stack**, and a stack with no gap is a stack of fields
|
|
67
|
+
* touching. The gap is the only visual decision here: no surface, no padding, no
|
|
68
|
+
* measure. Those belong to an [MPCard](../layout/card) or an
|
|
69
|
+
* [MPContainer](../layout/container) around it, for the reason a container gives
|
|
70
|
+
* — the thing that decides the shape of a page should not also be the thing that
|
|
71
|
+
* submits it.
|
|
72
|
+
*/
|
|
73
|
+
export declare const MPForm: React.ForwardRefExoticComponent<MPFormProps & React.RefAttributes<HTMLFormElement>>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{jsx as r}from"react/jsx-runtime";import*as o from"react";import{Form as e}from"@base-ui/react/form";import{SHEET_GAP as i}from"../../internal/scale.js";export const MPForm=/*@__PURE__*/o.forwardRef(function({validationMode:o="onSubmit",errors:m,onSubmit:a,size:t="md",className:n,children:s,...f},l){return r(e,{ref:l,validationMode:o,errors:m,onFormSubmit:r=>a?.(r),"data-mp-size":t,className:["mp-form flex flex-col",i[t],n??""].filter(Boolean).join(" "),...f,children:s})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPForm}from"./MPForm.js";
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { MPAlign, MPPosition, MPSize, MPVariant } from '../../types.js';
|
|
4
|
+
export interface MPHeaderProps extends Omit<React.ComponentPropsWithoutRef<'header'>, 'title'> {
|
|
5
|
+
/**
|
|
6
|
+
* The leading slot: the mark, the product's name, the thing that is the same
|
|
7
|
+
* on every page — and, on a narrow window, the
|
|
8
|
+
* [MPSidebarTrigger](./sidebar#mpsidebartrigger) that goes ahead of it.
|
|
9
|
+
*
|
|
10
|
+
* A slot rather than the first of `children` because the three regions of a
|
|
11
|
+
* bar are laid out *against each other* — the middle can only be centred on
|
|
12
|
+
* the bar if the two ends are the component's to measure — and a caller
|
|
13
|
+
* writing three wrappers by hand is a caller whose header drifts from the next
|
|
14
|
+
* one.
|
|
15
|
+
*/
|
|
16
|
+
brand?: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* The trailing slot: the account menu, the theme switch, the call to action.
|
|
19
|
+
* Laid out end-aligned, so a row of icon buttons needs no wrapper of its own.
|
|
20
|
+
*/
|
|
21
|
+
actions?: React.ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* Where the middle slot sits.
|
|
24
|
+
*
|
|
25
|
+
* `center` is MD3's own **center-aligned top app bar**, and it is centred on
|
|
26
|
+
* the *bar* rather than in the space left over: both ends are given equal
|
|
27
|
+
* shares, so the middle stays on the bar's midline however long the brand is.
|
|
28
|
+
* @default 'start'
|
|
29
|
+
*/
|
|
30
|
+
align?: MPAlign;
|
|
31
|
+
/**
|
|
32
|
+
* How the bar sits in the page's scroll, spelled the way CSS spells it.
|
|
33
|
+
*
|
|
34
|
+
* `sticky` — the default — holds it against the top of the window once the
|
|
35
|
+
* page has scrolled to it, while leaving it in the flow so nothing has to be
|
|
36
|
+
* padded out of its way. `fixed` takes it out of the flow entirely, which an
|
|
37
|
+
* [MPPageLayout](./page-layout) answers by reserving its height. `static` lets
|
|
38
|
+
* it scroll away.
|
|
39
|
+
* @default 'sticky'
|
|
40
|
+
*/
|
|
41
|
+
position?: MPPosition;
|
|
42
|
+
/**
|
|
43
|
+
* How much surface the bar paints, on the **container** ladder — the bar is
|
|
44
|
+
* never dyed, because what sits on it arrives with colours of its own.
|
|
45
|
+
*
|
|
46
|
+
* `tonal` is the default and is MD3's own scrolled top app bar:
|
|
47
|
+
* `surface-container` against the page's `surface`. `outlined` is the flat one
|
|
48
|
+
* — the page's own surface with a hairline where it ends — and `text` paints
|
|
49
|
+
* nothing at all, which is what a bar over a hero image wants.
|
|
50
|
+
* @default 'tonal'
|
|
51
|
+
*/
|
|
52
|
+
variant?: MPVariant;
|
|
53
|
+
/**
|
|
54
|
+
* The bar's height floor, its gutter and the air between its slots.
|
|
55
|
+
*
|
|
56
|
+
* `md` is 64px, which is MD3's own small top app bar. It is a floor rather
|
|
57
|
+
* than a height: a bar whose middle slot wrapped onto a second line would
|
|
58
|
+
* otherwise clip it.
|
|
59
|
+
* @default 'md'
|
|
60
|
+
*/
|
|
61
|
+
size?: MPSize;
|
|
62
|
+
/**
|
|
63
|
+
* Holds the row of slots to a measure and centres it while the sheet itself
|
|
64
|
+
* still spans the window. The same ladder [MPContainer](./container)'s
|
|
65
|
+
* `maxWidth` uses, so a header and the container under it line up on one edge.
|
|
66
|
+
* @default 'none'
|
|
67
|
+
*/
|
|
68
|
+
maxWidth?: MPSize | 'none';
|
|
69
|
+
/**
|
|
70
|
+
* The gutter down each side of the row.
|
|
71
|
+
* @default true
|
|
72
|
+
*/
|
|
73
|
+
padded?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The name the bar is announced by. Worth writing when a page has more than
|
|
76
|
+
* one `<header>` in it — an article's own and the site's — because "banner"
|
|
77
|
+
* twice tells a reader which is which not at all.
|
|
78
|
+
*/
|
|
79
|
+
label?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Renders something other than a `<header>`. Base UI's own escape hatch, and
|
|
82
|
+
* rarely what you want: at the top level of a document that tag *is* the
|
|
83
|
+
* `banner` landmark, and it is what says so to a screen reader's landmark
|
|
84
|
+
* list, to a reader mode and to a crawler.
|
|
85
|
+
*/
|
|
86
|
+
render?: useRender.RenderProp;
|
|
87
|
+
/** The middle slot: a row of navigation links, a search field, a headline. */
|
|
88
|
+
children?: React.ReactNode;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The bar across the top of a page. **MD3's top app bar**, with the site's own
|
|
92
|
+
* three regions on it.
|
|
93
|
+
*
|
|
94
|
+
* A real `<header>`, which is the whole reason it is a component rather than a
|
|
95
|
+
* row of divs: at the top level of a document that tag is the `banner` landmark,
|
|
96
|
+
* and it is what a screen reader's landmark list, a reader mode and a search
|
|
97
|
+
* engine's understanding of the page are built out of.
|
|
98
|
+
*
|
|
99
|
+
* The slots are props rather than compound sub-components, for
|
|
100
|
+
* [MPCard](./card)'s reason: the arrangement is fixed — brand, middle, actions —
|
|
101
|
+
* and what a caller wants to decide is what goes in each. That the middle can be
|
|
102
|
+
* centred on the bar's own midline is only possible *because* the ends are the
|
|
103
|
+
* component's to measure.
|
|
104
|
+
*
|
|
105
|
+
* ## Why there is no `divider`
|
|
106
|
+
*
|
|
107
|
+
* [MPBottomNavigation](./bottom-navigation) has one and this does not, and the
|
|
108
|
+
* difference is that this takes a `variant`. MD3 separates a bar from the
|
|
109
|
+
* content by **tone** — `surface-container` against `surface` — and the case a
|
|
110
|
+
* hairline exists for is the bar that paints the page's own surface. That bar is
|
|
111
|
+
* `variant="outlined"`, and the rule is what `outlined` *means* here: a
|
|
112
|
+
* container's outline is a hairline all the way round, and a bar has exactly one
|
|
113
|
+
* edge with anything on the other side of it.
|
|
114
|
+
*
|
|
115
|
+
* ## Inside a layout, and outside one
|
|
116
|
+
*
|
|
117
|
+
* Inside an [MPPageLayout](./page-layout) the bar registers itself, so a column
|
|
118
|
+
* that holds its place knows how far down the window to start and a `fixed` bar
|
|
119
|
+
* has its height reserved. Outside one it is simply a bar, and everything above
|
|
120
|
+
* still holds.
|
|
121
|
+
*/
|
|
122
|
+
export declare const MPHeader: React.ForwardRefExoticComponent<MPHeaderProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{useRender as i}from"@base-ui/react/use-render";import{BAR_SURFACE as n,MPPageLayoutContext as r}from"../../internal/page-layout.js";import{hasContent as s,MEASURE as l,SHEET_PAD_X as m}from"../../internal/scale.js";const d={xs:"min-h-12",sm:"min-h-14",md:"min-h-16",lg:"min-h-20",xl:"min-h-24"},o={xs:"text-mp-title-small",sm:"text-mp-title-medium",md:"text-mp-title-large",lg:"text-mp-headline-small",xl:"text-mp-headline-medium"},c={xs:"gap-1.5",sm:"gap-2",md:"gap-3",lg:"gap-4",xl:"gap-5"},p={xs:"gap-3",sm:"gap-4",md:"gap-6",lg:"gap-8",xl:"gap-10"},x={static:"",absolute:"absolute inset-x-0 top-0 z-30",sticky:"sticky top-0 z-30",fixed:"fixed inset-x-0 top-0 z-40"},f={start:"shrink-0",center:"flex-1 basis-0",end:"shrink-0"},u={start:"flex min-w-0 flex-1 items-center justify-start",center:"flex min-w-0 shrink items-center justify-center",end:"flex min-w-0 flex-1 items-center justify-end"};export const MPHeader=/*@__PURE__*/a.forwardRef(function({brand:h,actions:g,align:b="start",position:j="sticky",variant:v="tonal",size:w="md",maxWidth:y="none",padded:N=!0,label:k,render:_,className:z,children:$,...B},C){const{register:H}=a.useContext(r),M=a.useCallback(e=>{H("header",e),"function"==typeof C?C(e):C&&(C.current=e)},[H,C]);return i({render:_??e("header",{}),ref:M,props:{"aria-label":k,"data-mp-size":w,"data-mp-variant":v,className:["mp-header text-mp-on-surface box-border w-full min-w-0",n[v],"outlined"===v?"border-mp-outline-variant border-b":"",x[j],z??""].filter(Boolean).join(" "),children:t("div",{className:["flex w-full items-center",d[w],p[w],N?m[w]:"","none"===y?"":`${l[y]} mx-auto`].filter(Boolean).join(" "),children:[s(h)?e("div",{className:["mp-header__brand flex min-w-0 items-center",f[b],c[w],o[w]].join(" "),children:h}):"center"===b?e("div",{"aria-hidden":"true",className:f[b]}):null,s($)?e("div",{className:`mp-header__middle ${u[b]} ${c[w]}`,children:$}):null,s(g)?e("div",{className:["mp-header__actions flex min-w-0 items-center justify-end",f[b],c[w]].join(" "),children:g}):"center"===b?e("div",{"aria-hidden":"true",className:f[b]}):null]}),...B}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPHeader}from"./MPHeader.js";
|
|
@@ -19,6 +19,13 @@ export interface MPHighlightProps extends Omit<React.ComponentPropsWithoutRef<'s
|
|
|
19
19
|
* letters of it. A `RegExp` is used as written, with the global flag forced on;
|
|
20
20
|
* `caseSensitive` and `wholeWord` are ignored for it, because a regular
|
|
21
21
|
* expression already says both of those things itself.
|
|
22
|
+
*
|
|
23
|
+
* Strings are escaped, so a search box's contents are safe to pass straight
|
|
24
|
+
* through however they are spelled. A `RegExp` is **not** — it is run as
|
|
25
|
+
* written, which is the point of accepting one. Building one out of text
|
|
26
|
+
* somebody else typed is a denial of service waiting for the input that
|
|
27
|
+
* backtracks; escape it into a string term instead, or keep the expression a
|
|
28
|
+
* literal in your own source.
|
|
22
29
|
*/
|
|
23
30
|
query: string | string[] | RegExp;
|
|
24
31
|
/**
|
|
@@ -133,6 +133,7 @@ export interface MPMenuGroupProps {
|
|
|
133
133
|
label?: React.ReactNode;
|
|
134
134
|
children?: React.ReactNode;
|
|
135
135
|
className?: string;
|
|
136
|
+
style?: React.CSSProperties;
|
|
136
137
|
}
|
|
137
138
|
export interface MPMenuCheckboxItemProps extends Omit<MPMenuItemProps, 'href' | 'target' | 'startIcon' | 'onClick'> {
|
|
138
139
|
checked?: boolean;
|
|
@@ -153,6 +154,7 @@ export interface MPMenuRadioGroupProps {
|
|
|
153
154
|
disabled?: boolean;
|
|
154
155
|
children?: React.ReactNode;
|
|
155
156
|
className?: string;
|
|
157
|
+
style?: React.CSSProperties;
|
|
156
158
|
}
|
|
157
159
|
export interface MPMenuRadioItemProps extends Omit<MPMenuItemProps, 'href' | 'target' | 'startIcon' | 'onClick'> {
|
|
158
160
|
/** What this row sets the group to. */
|
|
@@ -173,7 +175,7 @@ export declare function MPMenuItem({ onClick, href, target, rel, startIcon, endI
|
|
|
173
175
|
/** A row that ticks. The tick lands in the column a `startIcon` would. */
|
|
174
176
|
export declare function MPMenuCheckboxItem({ checked, defaultChecked, onCheckedChange, endIcon, shortcut, description, color, closeOnClick, disabled, label, children, className, style }: MPMenuCheckboxItemProps): React.JSX.Element;
|
|
175
177
|
/** One choice out of a set. Wraps the rows that make up the set. */
|
|
176
|
-
export declare function MPMenuRadioGroup({ value, defaultValue, onValueChange, disabled, children, className }: MPMenuRadioGroupProps): React.JSX.Element;
|
|
178
|
+
export declare function MPMenuRadioGroup({ value, defaultValue, onValueChange, disabled, children, className, style }: MPMenuRadioGroupProps): React.JSX.Element;
|
|
177
179
|
/**
|
|
178
180
|
* A row inside an `MPMenuRadioGroup`.
|
|
179
181
|
*
|
|
@@ -183,7 +185,7 @@ export declare function MPMenuRadioGroup({ value, defaultValue, onValueChange, d
|
|
|
183
185
|
*/
|
|
184
186
|
export declare function MPMenuRadioItem({ value, endIcon, shortcut, description, color, closeOnClick, disabled, label, children, className, style }: MPMenuRadioItemProps): React.JSX.Element;
|
|
185
187
|
/** A named run of rows. The label is a heading, not a row — it cannot be picked. */
|
|
186
|
-
export declare function MPMenuGroup({ label, children, className }: MPMenuGroupProps): React.JSX.Element;
|
|
188
|
+
export declare function MPMenuGroup({ label, children, className, style }: MPMenuGroupProps): React.JSX.Element;
|
|
187
189
|
/** The hairline between two runs of rows. `outline-variant`, as MD3 draws it. */
|
|
188
190
|
export declare function MPMenuSeparator({ className, ...props }: MPMenuSeparatorProps): React.JSX.Element;
|
|
189
191
|
/**
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as t from"react";import{Menu as a}from"@base-ui/react/menu";import{ContextMenu as l}from"@base-ui/react/context-menu";import{MPIcon as r}from"../icon/MPIcon.js";import{CheckIcon as
|
|
2
|
+
import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as t from"react";import{Menu as a}from"@base-ui/react/menu";import{ContextMenu as l}from"@base-ui/react/context-menu";import{MPIcon as r}from"../icon/MPIcon.js";import{CheckIcon as s,ChevronRightIcon as o}from"../../constants/icons.js";import{linkRel as i}from"../../internal/link.js";import{MPMenuContext as c}from"../../internal/menu.js";import{accentSlots as d}from"../../internal/accent.js";import{MPStateLayer as m}from"../../internal/StateLayer.js";import{CONTROL_ICON as u,META_TEXT as p,hasContent as h}from"../../internal/scale.js";import{FADE as f,PORTAL_LAYER as x}from"../../internal/surface.js";const b=/*@__PURE__*/["mp-menu__popup rounded-mp-xs shadow-mp-2 bg-mp-surface-container text-mp-on-surface","max-h-[min(24rem,var(--available-height))] min-w-[112px] max-w-[280px]","overflow-y-auto overscroll-contain py-2 outline-none",f].join(" "),g={xs:"min-h-8",sm:"min-h-10",md:"min-h-12",lg:"min-h-14",xl:"min-h-16"},N={xs:"px-2",sm:"px-2.5",md:"px-3",lg:"px-4",xl:"px-5"},v={xs:"gap-2",sm:"gap-2.5",md:"gap-3",lg:"gap-3",xl:"gap-4"},y={xs:"text-mp-label-medium",sm:"text-mp-label-large",md:"text-mp-label-large",lg:"text-mp-title-medium",xl:"text-mp-title-medium"};function C(e,n,t){return["group relative flex w-full cursor-pointer items-center select-none",n?"text-(--_mp-accent)":"text-mp-on-surface",g[e],N[e],v[e],y[e],"data-disabled:text-mp-on-surface/38 data-disabled:cursor-default","outline-none",t??""].filter(Boolean).join(" ")}function k(){return e(m,{layer:"inset-0 bg-current",className:"group-data-highlighted:opacity-8 group-data-popup-open:opacity-8 group-data-disabled:opacity-0"})}const M="relative flex shrink-0 items-center justify-center";function O({children:t,description:a}){return h(a)?n("span",{className:"relative flex min-w-0 flex-1 flex-col py-1.5 text-start",children:[e("span",{className:"truncate",children:t}),e("span",{className:`text-mp-on-surface-variant truncate ${p}`,children:a})]}):e("span",{className:"relative min-w-0 flex-1 truncate text-start",children:t})}function P({shortcut:n}){return h(n)?e("span",{className:`text-mp-on-surface-variant relative ms-2 shrink-0 ${p}`,children:n}):null}export function MPMenuItem({onClick:l,href:r,target:s,rel:o,startIcon:d,endIcon:m,shortcut:u,description:p,color:f,closeOnClick:x=!0,disabled:b=!1,label:g,children:N,className:v,style:y}){const{size:j}=t.useContext(c),I=n(t.Fragment,{children:[e(k,{}),h(d)?e("span",{className:`${M} text-mp-on-surface-variant`,children:d}):null,e(O,{description:p,children:N}),h(m)?e("span",{className:`${M} text-mp-on-surface-variant`,children:m}):null,e(P,{shortcut:u})]}),$=f?{"--_mp-accent":`var(--_mp-color-${f})`}:void 0,z=$||y?{...$,...y}:void 0;return void 0===r||b?e(a.Item,{disabled:b,label:g,closeOnClick:x,onClick:l,className:C(j,Boolean(f),v),style:z,children:I}):e(a.LinkItem,{href:r,target:s,rel:i(s,o),label:g,closeOnClick:x,onClick:l,className:C(j,Boolean(f),v),style:z,children:I})}export function MPMenuCheckboxItem({checked:l,defaultChecked:o,onCheckedChange:i,endIcon:d,shortcut:m,description:p,color:f,closeOnClick:x=!1,disabled:b=!1,label:g,children:N,className:v,style:y}){const{size:j}=t.useContext(c),I=f?{"--_mp-accent":`var(--_mp-color-${f})`}:void 0;return n(a.CheckboxItem,{checked:l,defaultChecked:o,onCheckedChange:e=>i?.(e),disabled:b,label:g,closeOnClick:x,className:C(j,Boolean(f),v),style:I||y?{...I,...y}:void 0,children:[e(k,{}),e("span",{className:`${M} text-(--_mp-accent)`,style:{width:u[j]},children:e(a.CheckboxItemIndicator,{className:"flex items-center justify-center",children:e(r,{icon:s,size:u[j]})})}),e(O,{description:p,children:N}),h(d)?e("span",{className:`${M} text-mp-on-surface-variant`,children:d}):null,e(P,{shortcut:m})]})}export function MPMenuRadioGroup({value:n,defaultValue:t,onValueChange:l,disabled:r=!1,children:s,className:o,style:i}){return e(a.RadioGroup,{value:n,defaultValue:t,onValueChange:e=>l?.(e),disabled:r,className:o,style:i,children:s})}export function MPMenuRadioItem({value:l,endIcon:r,shortcut:s,description:o,color:i,closeOnClick:d=!1,disabled:m=!1,label:p,children:f,className:x,style:b}){const{size:g}=t.useContext(c),N=i?{"--_mp-accent":`var(--_mp-color-${i})`}:void 0;return n(a.RadioItem,{value:l,disabled:m,label:p,closeOnClick:d,className:C(g,Boolean(i),x),style:N||b?{...N,...b}:void 0,children:[e(k,{}),e("span",{className:`${M} text-(--_mp-accent)`,style:{width:u[g]},children:e(a.RadioItemIndicator,{className:"flex items-center justify-center",children:e("span",{className:"block size-2.5 rounded-full bg-current"})})}),e(O,{description:o,children:f}),h(r)?e("span",{className:`${M} text-mp-on-surface-variant`,children:r}):null,e(P,{shortcut:s})]})}export function MPMenuGroup({label:l,children:r,className:s,style:o}){const{size:i}=t.useContext(c);return n(a.Group,{className:s,style:o,children:[h(l)?e(a.GroupLabel,{className:`text-mp-on-surface-variant pt-2 pb-1 ${N[i]} ${p}`,children:l}):null,r]})}export function MPMenuSeparator({className:n,...t}){return e(a.Separator,{className:["bg-mp-outline-variant my-2 h-px",n??""].filter(Boolean).join(" "),...t})}export function MPMenuSubmenu({label:l,startIcon:s,disabled:i=!1,side:m="right",sideOffset:p=0,children:f,className:g,style:N}){const{size:v,color:y}=t.useContext(c);return n(a.SubmenuRoot,{children:[n(a.SubmenuTrigger,{disabled:i,className:C(v,!1),children:[e(k,{}),h(s)?e("span",{className:`${M} text-mp-on-surface-variant`,children:s}):null,e("span",{className:"relative min-w-0 flex-1 truncate text-start",children:l}),e("span",{className:`${M} text-mp-on-surface-variant rtl:rotate-180`,children:e(r,{icon:o,size:u[v]})})]}),e(a.Portal,{children:e(a.Positioner,{className:x,side:m,sideOffset:p,align:"start",children:e(a.Popup,{className:[b,g??""].filter(Boolean).join(" "),style:{...d(y),...N},children:f})})})]})}export function MPMenu({size:l="md",color:r="primary",trigger:s,open:o,defaultOpen:i,onOpenChange:m,side:u="bottom",align:p="start",sideOffset:h=4,modal:f,openOnHover:g=!1,loopFocus:N=!0,disabled:v=!1,className:y,style:C,children:k}){const M=t.useMemo(()=>({size:l,color:r}),[l,r]);return e(c.Provider,{value:M,children:n(a.Root,{open:o,defaultOpen:i,onOpenChange:e=>m?.(e),modal:f,loopFocus:N,disabled:v,children:[s?e(a.Trigger,{render:s,openOnHover:g,disabled:v}):null,e(a.Portal,{children:e(a.Positioner,{className:x,side:u,align:p,sideOffset:h,children:e(a.Popup,{"data-mp-size":l,className:[b,y??""].filter(Boolean).join(" "),style:{...d(r),...C},children:k})})})]})})}export function MPContextMenu({size:a="md",color:r="primary",content:s,children:o,open:i,defaultOpen:m,onOpenChange:u,loopFocus:p=!0,disabled:h=!1,className:f,style:g}){const N=t.useMemo(()=>({size:a,color:r}),[a,r]);return e(c.Provider,{value:N,children:n(l.Root,{open:i,defaultOpen:m,onOpenChange:e=>u?.(e),loopFocus:p,disabled:h,children:[e(l.Trigger,{children:o}),e(l.Portal,{children:e(l.Positioner,{className:x,children:e(l.Popup,{"data-mp-size":a,className:[b,f??""].filter(Boolean).join(" "),style:{...d(r),...g},children:s})})})]})})}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { MPColor, MPOrientation, MPSize } from '../../types.js';
|
|
3
|
+
export interface MPMenubarProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
4
|
+
/**
|
|
5
|
+
* Which way the bar runs. `vertical` is the shape a side rail of menus takes;
|
|
6
|
+
* the arrow keys follow it either way.
|
|
7
|
+
* @default 'horizontal'
|
|
8
|
+
*/
|
|
9
|
+
orientation?: MPOrientation;
|
|
10
|
+
/**
|
|
11
|
+
* Whether an open menu takes the page away.
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
modal?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the arrow keys wrap around at the ends of the bar.
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
loopFocus?: boolean;
|
|
20
|
+
/** Disables every menu on the bar at once. */
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The row height and type scale, passed to every menu on the bar.
|
|
24
|
+
* @default 'md'
|
|
25
|
+
*/
|
|
26
|
+
size?: MPSize;
|
|
27
|
+
/**
|
|
28
|
+
* Which accent family an open menu's word reads, and which a chosen row inside
|
|
29
|
+
* it reads.
|
|
30
|
+
* @default 'primary'
|
|
31
|
+
*/
|
|
32
|
+
color?: MPColor;
|
|
33
|
+
/** The `MPMenubarMenu`s. */
|
|
34
|
+
children?: React.ReactNode;
|
|
35
|
+
}
|
|
36
|
+
export interface MPMenubarMenuProps {
|
|
37
|
+
/** The word on the bar. */
|
|
38
|
+
label: React.ReactNode;
|
|
39
|
+
/** A glyph before the label. */
|
|
40
|
+
startIcon?: React.ReactNode;
|
|
41
|
+
/** Unavailable. The word stays on the bar and opens nothing. */
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
/** The rows, written exactly as they are inside an [MPMenu](./menu). */
|
|
44
|
+
children?: React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* Added to the word on the bar — the button that opens the menu — rather than
|
|
47
|
+
* to the menu it opens. That one takes its own `className` on
|
|
48
|
+
* [MPMenu](./menu).
|
|
49
|
+
*/
|
|
50
|
+
className?: string;
|
|
51
|
+
style?: React.CSSProperties;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* One menu on the bar: the word, and the rows behind it.
|
|
55
|
+
*
|
|
56
|
+
* It has no `size` and no `color` of its own — both belong to the bar, which is
|
|
57
|
+
* the only place they can be set once and hold for every menu on it. The rows
|
|
58
|
+
* inside are the same [MPMenuItem](./menu), `MPMenuSeparator`, `MPMenuGroup` and
|
|
59
|
+
* `MPMenuSubmenu` an [MPMenu](./menu) takes, because it *is* the same menu.
|
|
60
|
+
*/
|
|
61
|
+
export declare function MPMenubarMenu({ label, startIcon, disabled, children, className, style }: MPMenubarMenuProps): React.JSX.Element;
|
|
62
|
+
/**
|
|
63
|
+
* The strip of words at the top of an application — File, Edit, View — each of
|
|
64
|
+
* which opens a menu.
|
|
65
|
+
*
|
|
66
|
+
* ## What makes it a bar rather than a row of menus
|
|
67
|
+
*
|
|
68
|
+
* What happens once one of them is **open**: moving along the strip walks
|
|
69
|
+
* through the others instead of closing the one you left, and the arrow keys
|
|
70
|
+
* move between the menus as well as inside them. Base UI owns all of that, along
|
|
71
|
+
* with the `menubar` role — which is what tells a screen reader that the strip
|
|
72
|
+
* is one widget with one tab stop rather than six unrelated buttons.
|
|
73
|
+
*
|
|
74
|
+
* ## Why it draws no surface
|
|
75
|
+
*
|
|
76
|
+
* A menu bar sits **on** something: an [MPHeader](../layout/header), a title
|
|
77
|
+
* bar, a toolbar. A sheet under a strip that is already on a sheet is two
|
|
78
|
+
* sheets, and the second one has nothing to say. It is the same refusal
|
|
79
|
+
* [MPContainer](../layout/container#why-it-draws-no-surface) makes, one level
|
|
80
|
+
* down.
|
|
81
|
+
*
|
|
82
|
+
* ## When this is the wrong component
|
|
83
|
+
*
|
|
84
|
+
* When there are more actions than a strip can hold. A menu bar's whole
|
|
85
|
+
* advantage is that every heading is visible before you go looking for one, and
|
|
86
|
+
* a bar of twelve words has already lost it — that is an
|
|
87
|
+
* [MPCommandPalette](./command-palette).
|
|
88
|
+
*/
|
|
89
|
+
export declare const MPMenubar: React.ForwardRefExoticComponent<MPMenubarProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Menubar as r}from"@base-ui/react/menubar";import{MPMenu as n}from"../menu/MPMenu.js";import{accentSlots as s}from"../../internal/accent.js";import{MPMenuContext as l}from"../../internal/menu.js";import{MPStateLayer as a}from"../../internal/StateLayer.js";import{CONTROL_GAP as i,hasContent as m}from"../../internal/scale.js";const c={xs:"h-6",sm:"h-7",md:"h-8",lg:"h-10",xl:"h-12"},p={xs:"px-1.5",sm:"px-2",md:"px-2.5",lg:"px-3",xl:"px-4"},u={xs:"text-mp-label-medium",sm:"text-mp-label-large",md:"text-mp-label-large",lg:"text-mp-title-medium",xl:"text-mp-title-medium"};export function MPMenubarMenu({label:r,startIcon:s,disabled:d=!1,children:f,className:x,style:b}){const{size:h,color:j}=o.useContext(l);return e(n,{size:h,color:j,disabled:d,openOnHover:!0,sideOffset:4,trigger:t("button",{type:"button",disabled:d,className:["mp-menubar__menu group text-mp-on-surface relative inline-flex shrink-0","rounded-mp-xs cursor-pointer items-center justify-center bg-transparent","appearance-none font-[inherit] whitespace-nowrap select-none","transition-colors duration-(--mp-sys-motion-duration-short4)","data-popup-open:text-(--_mp-accent)","disabled:text-mp-on-surface/38 disabled:cursor-default","outline-mp-secondary focus-visible:outline-2 focus-visible:-outline-offset-2","focus-visible:outline-solid outline-none",c[h],p[h],u[h],i[h],x??""].filter(Boolean).join(" "),style:b,children:[d?null:e(a,{className:"group-data-popup-open:opacity-8"}),m(s)?e("span",{className:"relative flex",children:s}):null,e("span",{className:"relative",children:r})]}),children:f})}export const MPMenubar=/*@__PURE__*/o.forwardRef(function({orientation:t="horizontal",modal:n=!0,loopFocus:a=!0,disabled:m=!1,size:c="md",color:p="primary",className:u,style:d,children:f,...x},b){const h=o.useMemo(()=>({size:c,color:p}),[c,p]);return e(l.Provider,{value:h,children:e(r,{ref:b,orientation:t,modal:n,loopFocus:a,disabled:m,"data-mp-size":c,"data-mp-orientation":t,className:["mp-menubar flex items-center","vertical"===t?"flex-col items-stretch":"flex-row",i[c],u??""].filter(Boolean).join(" "),style:{...s(p),...d},...x,children:f})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPMenubar,MPMenubarMenu}from"./MPMenubar.js";
|