material-plus-ui 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -28
- package/dist/components/accordion/MPAccordion.d.ts +115 -0
- package/dist/components/accordion/MPAccordion.js +1 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +1 -0
- package/dist/components/alert/MPAlert.d.ts +91 -0
- package/dist/components/alert/MPAlert.js +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/aspect-ratio/MPAspectRatio.d.ts +69 -0
- package/dist/components/aspect-ratio/MPAspectRatio.js +1 -0
- package/dist/components/aspect-ratio/index.d.ts +2 -0
- package/dist/components/aspect-ratio/index.js +1 -0
- package/dist/components/avatar/MPAvatar.d.ts +97 -0
- package/dist/components/avatar/MPAvatar.js +1 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +1 -0
- package/dist/components/badge/MPBadge.d.ts +104 -0
- package/dist/components/badge/MPBadge.js +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/blockquote/MPBlockquote.d.ts +73 -0
- package/dist/components/blockquote/MPBlockquote.js +1 -0
- package/dist/components/blockquote/index.d.ts +2 -0
- package/dist/components/blockquote/index.js +1 -0
- package/dist/components/box/MPBox.d.ts +78 -0
- package/dist/components/box/MPBox.js +1 -0
- package/dist/components/box/index.d.ts +2 -0
- package/dist/components/box/index.js +1 -0
- package/dist/components/breadcrumb/MPBreadcrumb.d.ts +105 -0
- package/dist/components/breadcrumb/MPBreadcrumb.js +1 -0
- package/dist/components/breadcrumb/index.d.ts +2 -0
- package/dist/components/breadcrumb/index.js +1 -0
- package/dist/components/button/MPButton.d.ts +70 -0
- package/dist/components/button/MPButton.js +1 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/button-group/MPButtonGroup.d.ts +31 -0
- package/dist/components/button-group/MPButtonGroup.js +1 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.js +1 -0
- package/dist/components/card/MPCard.d.ts +73 -0
- package/dist/components/card/MPCard.js +1 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/carousel/MPCarousel.d.ts +116 -0
- package/dist/components/carousel/MPCarousel.js +1 -0
- package/dist/components/carousel/index.d.ts +2 -0
- package/dist/components/carousel/index.js +1 -0
- package/dist/components/chat-bubble/MPChatBubble.d.ts +132 -0
- package/dist/components/chat-bubble/MPChatBubble.js +1 -0
- package/dist/components/chat-bubble/index.d.ts +2 -0
- package/dist/components/chat-bubble/index.js +1 -0
- package/dist/components/checkbox/MPCheckbox.d.ts +76 -0
- package/dist/components/checkbox/MPCheckbox.js +1 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/chip/MPChip.d.ts +64 -0
- package/dist/components/chip/MPChip.js +1 -0
- package/dist/components/chip/index.d.ts +2 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/collapsible/MPCollapsible.d.ts +97 -0
- package/dist/components/collapsible/MPCollapsible.js +1 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/color-picker/MPColorPicker.d.ts +113 -0
- package/dist/components/color-picker/MPColorPicker.js +1 -0
- package/dist/components/color-picker/index.d.ts +2 -0
- package/dist/components/color-picker/index.js +1 -0
- package/dist/components/combobox/MPCombobox.d.ts +147 -0
- package/dist/components/combobox/MPCombobox.js +1 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/date-picker/MPDatePicker.d.ts +95 -0
- package/dist/components/date-picker/MPDatePicker.js +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-range-picker/MPDateRangePicker.d.ts +98 -0
- package/dist/components/date-range-picker/MPDateRangePicker.js +1 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/date-time-picker/MPDateTimePicker.d.ts +78 -0
- package/dist/components/date-time-picker/MPDateTimePicker.js +1 -0
- package/dist/components/date-time-picker/index.d.ts +2 -0
- package/dist/components/date-time-picker/index.js +1 -0
- package/dist/components/dialog/MPDialog.d.ts +145 -0
- package/dist/components/dialog/MPDialog.js +1 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/divider/MPDivider.d.ts +80 -0
- package/dist/components/divider/MPDivider.js +1 -0
- package/dist/components/divider/index.d.ts +2 -0
- package/dist/components/divider/index.js +1 -0
- package/dist/components/drawer/MPDrawer.d.ts +163 -0
- package/dist/components/drawer/MPDrawer.js +1 -0
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/drawer/index.js +1 -0
- package/dist/components/empty/MPEmpty.d.ts +64 -0
- package/dist/components/empty/MPEmpty.js +1 -0
- package/dist/components/empty/index.d.ts +2 -0
- package/dist/components/empty/index.js +1 -0
- package/dist/components/file-picker/MPFilePicker.d.ts +103 -0
- package/dist/components/file-picker/MPFilePicker.js +1 -0
- package/dist/components/file-picker/index.d.ts +2 -0
- package/dist/components/file-picker/index.js +1 -0
- package/dist/components/highlight/MPHighlight.d.ts +95 -0
- package/dist/components/highlight/MPHighlight.js +1 -0
- package/dist/components/highlight/index.d.ts +2 -0
- package/dist/components/highlight/index.js +1 -0
- package/dist/components/icon-button/MPIconButton.d.ts +59 -0
- package/dist/components/icon-button/MPIconButton.js +1 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/icon-button/index.js +1 -0
- package/dist/components/list/MPList.d.ts +96 -0
- package/dist/components/list/MPList.js +1 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.js +1 -0
- package/dist/components/locale/MPLocaleProvider.d.ts +63 -0
- package/dist/components/locale/MPLocaleProvider.js +1 -0
- package/dist/components/locale/index.d.ts +2 -0
- package/dist/components/locale/index.js +1 -0
- package/dist/components/menu/MPMenu.d.ts +223 -0
- package/dist/components/menu/MPMenu.js +1 -0
- package/dist/components/menu/index.d.ts +2 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/number-field/MPNumberField.d.ts +99 -0
- package/dist/components/number-field/MPNumberField.js +1 -0
- package/dist/components/number-field/index.d.ts +2 -0
- package/dist/components/number-field/index.js +1 -0
- package/dist/components/otp-field/MPOtpField.d.ts +89 -0
- package/dist/components/otp-field/MPOtpField.js +1 -0
- package/dist/components/otp-field/index.d.ts +2 -0
- package/dist/components/otp-field/index.js +1 -0
- package/dist/components/overlay/MPOverlay.d.ts +96 -0
- package/dist/components/overlay/MPOverlay.js +1 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.js +1 -0
- package/dist/components/panes/MPPanes.d.ts +100 -0
- package/dist/components/panes/MPPanes.js +1 -0
- package/dist/components/panes/index.d.ts +2 -0
- package/dist/components/panes/index.js +1 -0
- package/dist/components/pill/MPPill.d.ts +117 -0
- package/dist/components/pill/MPPill.js +1 -0
- package/dist/components/pill/index.d.ts +2 -0
- package/dist/components/pill/index.js +1 -0
- package/dist/components/popover/MPPopover.d.ts +138 -0
- package/dist/components/popover/MPPopover.js +1 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +1 -0
- package/dist/components/progress-box/MPProgressBox.d.ts +40 -0
- package/dist/components/progress-box/MPProgressBox.js +1 -0
- package/dist/components/progress-box/index.d.ts +2 -0
- package/dist/components/progress-box/index.js +1 -0
- package/dist/components/progress-circular/MPProgressCircular.d.ts +32 -0
- package/dist/components/progress-circular/MPProgressCircular.js +1 -0
- package/dist/components/progress-circular/index.d.ts +2 -0
- package/dist/components/progress-circular/index.js +1 -0
- package/dist/components/progress-linear/MPProgressLinear.d.ts +32 -0
- package/dist/components/progress-linear/MPProgressLinear.js +1 -0
- package/dist/components/progress-linear/index.d.ts +2 -0
- package/dist/components/progress-linear/index.js +1 -0
- package/dist/components/radio-group/MPRadioGroup.d.ts +81 -0
- package/dist/components/radio-group/MPRadioGroup.js +1 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +1 -0
- package/dist/components/segmented-button/MPSegmentedButton.d.ts +75 -0
- package/dist/components/segmented-button/MPSegmentedButton.js +1 -0
- package/dist/components/segmented-button/index.d.ts +2 -0
- package/dist/components/segmented-button/index.js +1 -0
- package/dist/components/select/MPSelect.d.ts +86 -0
- package/dist/components/select/MPSelect.js +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/shortcut/MPShortcut.d.ts +67 -0
- package/dist/components/shortcut/MPShortcut.js +1 -0
- package/dist/components/shortcut/index.d.ts +2 -0
- package/dist/components/shortcut/index.js +1 -0
- package/dist/components/skeleton/MPSkeleton.d.ts +76 -0
- package/dist/components/skeleton/MPSkeleton.js +1 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/slider/MPSlider.d.ts +77 -0
- package/dist/components/slider/MPSlider.js +1 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +1 -0
- package/dist/components/snackbar/MPSnackbar.d.ts +170 -0
- package/dist/components/snackbar/MPSnackbar.js +1 -0
- package/dist/components/snackbar/index.d.ts +2 -0
- package/dist/components/snackbar/index.js +1 -0
- package/dist/components/spoiler/MPSpoiler.d.ts +106 -0
- package/dist/components/spoiler/MPSpoiler.js +1 -0
- package/dist/components/spoiler/index.d.ts +2 -0
- package/dist/components/spoiler/index.js +1 -0
- package/dist/components/switch/MPSwitch.d.ts +75 -0
- package/dist/components/switch/MPSwitch.js +1 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/MPTable.d.ts +107 -0
- package/dist/components/table/MPTable.js +1 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/text-field/MPTextField.d.ts +17 -18
- package/dist/components/text-field/MPTextField.js +1 -1
- package/dist/components/text-link/MPTextLink.d.ts +88 -0
- package/dist/components/text-link/MPTextLink.js +1 -0
- package/dist/components/text-link/index.d.ts +2 -0
- package/dist/components/text-link/index.js +1 -0
- package/dist/components/time-picker/MPTimePicker.d.ts +108 -0
- package/dist/components/time-picker/MPTimePicker.js +1 -0
- package/dist/components/time-picker/index.d.ts +2 -0
- package/dist/components/time-picker/index.js +1 -0
- package/dist/components/timeline/MPTimeline.d.ts +96 -0
- package/dist/components/timeline/MPTimeline.js +1 -0
- package/dist/components/timeline/index.d.ts +2 -0
- package/dist/components/timeline/index.js +1 -0
- package/dist/components/tooltip/MPTooltip.d.ts +117 -0
- package/dist/components/tooltip/MPTooltip.js +1 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/typography/MPTypography.d.ts +94 -0
- package/dist/components/typography/MPTypography.js +1 -0
- package/dist/components/typography/index.d.ts +2 -0
- package/dist/components/typography/index.js +1 -0
- package/dist/constants/icons.d.ts +36 -0
- package/dist/constants/icons.js +1 -1
- package/dist/index.d.ts +55 -0
- package/dist/index.js +1 -1
- package/dist/internal/Calendar.d.ts +118 -0
- package/dist/internal/Calendar.js +1 -0
- package/dist/internal/FieldOutline.d.ts +38 -0
- package/dist/internal/FieldOutline.js +1 -0
- package/dist/internal/Picker.d.ts +110 -0
- package/dist/internal/Picker.js +1 -0
- package/dist/internal/StateLayer.d.ts +45 -0
- package/dist/internal/StateLayer.js +1 -0
- package/dist/internal/SupportingText.d.ts +23 -0
- package/dist/internal/SupportingText.js +1 -0
- package/dist/internal/WidthSizer.d.ts +31 -0
- package/dist/internal/WidthSizer.js +1 -0
- package/dist/internal/accent.d.ts +39 -0
- package/dist/internal/accent.js +1 -0
- package/dist/internal/button-group.d.ts +21 -0
- package/dist/internal/button-group.js +1 -0
- package/dist/internal/color.d.ts +125 -0
- package/dist/internal/color.js +1 -0
- package/dist/internal/date.d.ts +179 -0
- package/dist/internal/date.js +1 -0
- package/dist/internal/i18n.d.ts +131 -0
- package/dist/internal/i18n.js +1 -0
- package/dist/internal/locale.d.ts +43 -0
- package/dist/internal/locale.js +1 -0
- package/dist/internal/menu.d.ts +23 -0
- package/dist/internal/menu.js +1 -0
- package/dist/internal/progress.d.ts +126 -0
- package/dist/internal/progress.js +1 -0
- package/dist/internal/scale.d.ts +127 -0
- package/dist/internal/scale.js +1 -0
- package/dist/internal/surface.d.ts +76 -0
- package/dist/internal/surface.js +1 -0
- package/dist/internal/visually-hidden.d.ts +23 -0
- package/dist/internal/visually-hidden.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +1285 -20
- package/dist/types.d.ts +107 -16
- package/package.json +16 -21
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { MPColor, MPSize } from '../../types';
|
|
3
|
+
/** Which side of the track the label sits on. */
|
|
4
|
+
export type MPSwitchLabelPlacement = 'start' | 'end';
|
|
5
|
+
export interface MPSwitchProps {
|
|
6
|
+
/** Whether the switch is on. Use with `onCheckedChange` for a controlled one. */
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
/** Whether it starts on, for an uncontrolled one. */
|
|
9
|
+
defaultChecked?: boolean;
|
|
10
|
+
/** Called with the new state — a boolean, not an event. */
|
|
11
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
12
|
+
/** The text beside the track, wired to it by Base UI's Field. */
|
|
13
|
+
label?: React.ReactNode;
|
|
14
|
+
/** The line under the label. Replaced by `errorMessage` when there is one. */
|
|
15
|
+
description?: React.ReactNode;
|
|
16
|
+
/** The message under the label, which also turns the switch over. */
|
|
17
|
+
errorMessage?: React.ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Draws a tick in the thumb when it is on and a cross when it is off.
|
|
20
|
+
*
|
|
21
|
+
* Off by default, and worth turning on wherever the two states are not
|
|
22
|
+
* obviously different in context: the thumb's position and the track's colour
|
|
23
|
+
* are otherwise the only signals, and one of those is a hue.
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
icons?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Which side the label sits on. `end` reads as a caption for the control;
|
|
29
|
+
* `start` is for a settings list, where the labels form a column and every
|
|
30
|
+
* switch lines up on the right.
|
|
31
|
+
* @default 'end'
|
|
32
|
+
*/
|
|
33
|
+
labelPlacement?: MPSwitchLabelPlacement;
|
|
34
|
+
/**
|
|
35
|
+
* The track's size and the label's type scale.
|
|
36
|
+
* @default 'md'
|
|
37
|
+
*/
|
|
38
|
+
size?: MPSize;
|
|
39
|
+
/**
|
|
40
|
+
* Which accent family the track takes when it is on.
|
|
41
|
+
* @default 'primary'
|
|
42
|
+
*/
|
|
43
|
+
color?: MPColor;
|
|
44
|
+
/** Marks the switch required. */
|
|
45
|
+
required?: boolean;
|
|
46
|
+
/** Greys the switch out and stops it taking input. */
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
/** Shows the state without allowing it to be changed. */
|
|
49
|
+
readOnly?: boolean;
|
|
50
|
+
/** Name of the form control. */
|
|
51
|
+
name?: string;
|
|
52
|
+
/**
|
|
53
|
+
* The id put on the control and pointed at by the label. Derived from `name`
|
|
54
|
+
* when omitted, and generated when there is no name either.
|
|
55
|
+
*/
|
|
56
|
+
id?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Stretches the row, so a `start` label takes the slack and the track sits
|
|
59
|
+
* against the far edge. This is what makes a column of settings line up.
|
|
60
|
+
*/
|
|
61
|
+
fullWidth?: boolean;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A Material Design switch.
|
|
65
|
+
*
|
|
66
|
+
* The difference from a checkbox is not visual, it is temporal: a checkbox is a
|
|
67
|
+
* value that gets submitted with a form, a switch takes effect the moment it
|
|
68
|
+
* moves. If there is a Save button underneath, it should have been a checkbox.
|
|
69
|
+
*
|
|
70
|
+
* The thumb is the one thing in this library that actually travels, so this is
|
|
71
|
+
* also the only place the spec's `standard` easing is read — quick to leave, slow
|
|
72
|
+
* to arrive, which is what makes a 200ms move read as something being pushed
|
|
73
|
+
* rather than as something being teleported and then apologised for.
|
|
74
|
+
*/
|
|
75
|
+
export declare const MPSwitch: React.ForwardRefExoticComponent<MPSwitchProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,Fragment as t,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Switch as n}from"@base-ui/react/switch";import{Field as i}from"@base-ui/react/field";import{MPIcon as c}from"../icon/MPIcon";import{CheckIcon as s,CloseIcon as o}from"../../constants/icons";import{accentSlots as l}from"../../internal/accent";import{MPStateLayer as d}from"../../internal/StateLayer";import{MPSupportingText as h}from"../../internal/SupportingText";import{PROSE_TEXT as m,hasContent as p}from"../../internal/scale";const u={xs:{track:"h-5 w-8",thumb:"left-[5px] size-2.5 data-checked:left-[15px] data-checked:size-3.5",halo:"size-8",glyph:8},sm:{track:"h-6 w-10",thumb:"left-1.5 size-3 data-checked:left-[19px] data-checked:size-[18px]",halo:"size-9",glyph:10},md:{track:"h-8 w-13",thumb:"left-2 size-4 data-checked:left-6 data-checked:size-6",halo:"size-10",glyph:14},lg:{track:"h-9 w-15",thumb:"left-[9px] size-[18px] data-checked:left-7 data-checked:size-7",halo:"size-11",glyph:16},xl:{track:"h-10 w-17",thumb:"left-2.5 size-5 data-checked:left-[33px] data-checked:size-[30px]",halo:"size-12",glyph:18}};export const MPSwitch=r.forwardRef(function({checked:f,defaultChecked:g,onCheckedChange:k,label:x,description:b,errorMessage:z,icons:y=!1,labelPlacement:w="end",size:j="md",color:N="primary",required:_=!1,disabled:C=!1,readOnly:M=!1,name:v,id:P,fullWidth:R=!1},S){const W=p(z),q=W?"error":N,F=u[j],I=r.useId(),L=P??`mp-switch-${v??I}`,O=e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(n.Root,{ref:S,id:L,name:v,checked:f,defaultChecked:g,required:_,disabled:C,readOnly:M,onCheckedChange:e=>k?.(e),className:["mp-switch__track group relative box-border inline-flex shrink-0 p-0","rounded-mp-full appearance-none font-[inherit] outline-none","transition-[background-color,box-shadow]","duration-(--mp-sys-motion-duration-short4) ease-mp-standard",F.track,C?["bg-mp-surface-container-highest inset-ring-2 inset-ring-mp-on-surface/12","cursor-default","data-checked:bg-mp-on-surface/12 data-checked:inset-ring-0"].join(" "):[M?"cursor-default":"cursor-pointer","bg-mp-surface-container-highest inset-ring-2",W?"inset-ring-mp-error":"inset-ring-mp-outline","data-checked:inset-ring-0 data-checked:bg-(--_mp-accent)"].join(" ")].join(" "),children:a(n.Thumb,{className:["mp-switch__thumb absolute top-1/2 flex -translate-y-1/2 items-center justify-center","rounded-full","transition-[left,width,height,background-color]","duration-(--mp-sys-motion-duration-short4) ease-mp-standard",F.thumb,C?"bg-mp-on-surface/38 data-checked:bg-mp-surface-container-highest":[W?"bg-mp-error":"bg-mp-outline","data-checked:bg-(--_mp-on-accent)"].join(" ")].join(" "),children:[C?null:e(d,{layer:["top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full",F.halo,"bg-mp-on-surface group-data-checked:bg-(--_mp-accent)"].join(" ")}),y?a(t,{children:[e("span",{className:["hidden items-center group-data-checked:flex",C?"text-mp-surface-container-highest":"text-(--_mp-accent)"].join(" "),children:e(c,{icon:s,size:F.glyph,strokeWidth:3})}),e("span",{className:"text-mp-surface-container-highest flex items-center group-data-checked:hidden",children:e(c,{icon:o,size:F.glyph,strokeWidth:3})})]}):null]})})}),T=p(x)||p(b)||W?a("span",{className:["flex min-w-0 flex-col gap-0.5","start"===w?"flex-1":""].filter(Boolean).join(" "),children:[p(x)?a(i.Label,{htmlFor:L,className:["leading-[1.4]",C?"text-mp-on-surface/38 cursor-default":M?"text-mp-on-surface":"text-mp-on-surface cursor-pointer"].join(" "),children:[x,_?e("span",{"aria-hidden":"true",children:" *"}):null]}):null,e(h,{description:b,errorMessage:z})]}):null;return e(i.Root,{className:["mp-switch align-top",R?"flex w-full":"inline-flex"].join(" "),disabled:C,invalid:W,"data-mp-size":j,style:l(q),children:e("div",{className:["flex w-full items-start gap-3",m[j]].join(" "),children:a(t,"start"===w?{children:[T,O]}:{children:[O,T]})})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPSwitch}from"./MPSwitch";
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { MPAlign, MPColor, MPSize, MPVariant } from '../../types';
|
|
3
|
+
/** Which edge the text in a column lines up against. */
|
|
4
|
+
export type MPTableAlign = MPAlign;
|
|
5
|
+
/**
|
|
6
|
+
* A column: its heading, its default width, and how to get a cell out of a row.
|
|
7
|
+
*
|
|
8
|
+
* This is the whole reason the component takes data rather than markup. A `<td>`
|
|
9
|
+
* written out per row can silently disagree with the `<th>` above it about how
|
|
10
|
+
* many there are or what order they come in; a column list cannot.
|
|
11
|
+
*/
|
|
12
|
+
export interface MPTableColumn<Row> {
|
|
13
|
+
/**
|
|
14
|
+
* Identifies the column, and — unless `render` says otherwise — names the
|
|
15
|
+
* property to read off each row.
|
|
16
|
+
*/
|
|
17
|
+
key: string;
|
|
18
|
+
/** The heading. Defaults to the `key`, which is usually not what you want. */
|
|
19
|
+
label?: React.ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* The column's default width. A number is pixels; a string is any CSS length.
|
|
22
|
+
*
|
|
23
|
+
* "Default" is meant: the table still balances the columns to fill its width,
|
|
24
|
+
* so this is a starting proportion rather than a guarantee.
|
|
25
|
+
*/
|
|
26
|
+
width?: number | string;
|
|
27
|
+
/**
|
|
28
|
+
* Text alignment. Numbers usually want `end` so their digits line up in a
|
|
29
|
+
* column; everything else wants `start`.
|
|
30
|
+
* @default 'start'
|
|
31
|
+
*/
|
|
32
|
+
align?: MPTableAlign;
|
|
33
|
+
/**
|
|
34
|
+
* Renders the cell. Without it the cell is `row[key]` rendered as-is, which
|
|
35
|
+
* covers strings and numbers and nothing else.
|
|
36
|
+
*/
|
|
37
|
+
render?: (row: Row, index: number) => React.ReactNode;
|
|
38
|
+
}
|
|
39
|
+
export interface MPTableProps<Row> extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'children'> {
|
|
40
|
+
/** The columns, in the order they appear. */
|
|
41
|
+
headers: readonly MPTableColumn<Row>[];
|
|
42
|
+
/** The rows. */
|
|
43
|
+
items: readonly Row[];
|
|
44
|
+
/**
|
|
45
|
+
* A stable key per row. Defaults to the row's index, which is fine for a
|
|
46
|
+
* static table and wrong for one that sorts or filters.
|
|
47
|
+
*/
|
|
48
|
+
getRowKey?: (row: Row, index: number) => React.Key;
|
|
49
|
+
/** Shown above the table, and read out as its accessible name. */
|
|
50
|
+
caption?: React.ReactNode;
|
|
51
|
+
/**
|
|
52
|
+
* What to show instead of rows when `items` is empty.
|
|
53
|
+
* @default 'No data'
|
|
54
|
+
*/
|
|
55
|
+
empty?: React.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* Tints every other row. Useful for a wide table where the eye has to track
|
|
58
|
+
* across; noise on a narrow one.
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
striped?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Lights the row under the pointer.
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
hoverable?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Pins the header while the body scrolls. Only does anything if something
|
|
69
|
+
* around the table actually constrains its height.
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
stickyHeader?: boolean;
|
|
73
|
+
/** Makes rows activatable. Also turns on the hover treatment. */
|
|
74
|
+
onRowClick?: (row: Row, index: number) => void;
|
|
75
|
+
/**
|
|
76
|
+
* How much surface the sheet around the table paints.
|
|
77
|
+
* @default 'outlined'
|
|
78
|
+
*/
|
|
79
|
+
variant?: MPVariant;
|
|
80
|
+
/**
|
|
81
|
+
* @default 'md'
|
|
82
|
+
*/
|
|
83
|
+
size?: MPSize;
|
|
84
|
+
/**
|
|
85
|
+
* Which accent family a hovered or pressed row reads. The cells themselves
|
|
86
|
+
* stay neutral.
|
|
87
|
+
* @default 'primary'
|
|
88
|
+
*/
|
|
89
|
+
color?: MPColor;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A grid of data.
|
|
93
|
+
*
|
|
94
|
+
* The sheet takes the same `variant`, `size` and `color` as everything it might
|
|
95
|
+
* sit next to. What the table adds is the part that is genuinely tabular: the
|
|
96
|
+
* columns, the rows, and the fact that the two cannot drift apart.
|
|
97
|
+
*
|
|
98
|
+
* ## Why it is not `React.forwardRef`
|
|
99
|
+
*
|
|
100
|
+
* It is generic in `Row`, and a `forwardRef` component's type erases that: the
|
|
101
|
+
* wrapper is typed as one component rather than as a function with a type
|
|
102
|
+
* parameter, so `headers` and `items` would stop checking against each other and
|
|
103
|
+
* `column.render` would hand back `unknown`. Losing that check would cost more
|
|
104
|
+
* than a ref on the scroll container is worth — and a caller who needs one can
|
|
105
|
+
* put it on a `<div>` of their own around this.
|
|
106
|
+
*/
|
|
107
|
+
export declare function MPTable<Row>({ headers, items, getRowKey, caption, empty, striped, hoverable, stickyHeader, onRowClick, variant, size, color, className, style, ...props }: MPTableProps<Row>): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{accentSlots as r}from"../../internal/accent";import{META_TEXT as a}from"../../internal/scale";import{CONTAINER_SURFACE as l}from"../../internal/surface";const o={xs:"0.625rem",sm:"0.75rem",md:"1rem",lg:"1.25rem",xl:"1.5rem"},m={xs:"0.375rem",sm:"0.625rem",md:"1rem",lg:"1.25rem",xl:"1.5rem"},n={xs:"text-mp-body-small",sm:"text-mp-body-small",md:"text-mp-body-medium",lg:"text-mp-body-medium",xl:"text-mp-body-large"},i={xs:"text-mp-label-medium",sm:"text-mp-label-medium",md:"text-mp-title-small",lg:"text-mp-title-small",xl:"text-mp-title-medium"},s=["[--_mp-row:transparent]","transition-[background-color] duration-(--mp-sys-motion-duration-short4)"].join(" ");export function MPTable({headers:c,items:d,getRowKey:p,caption:x,empty:u="No data",striped:y=!1,hoverable:h=!1,stickyHeader:g=!1,onRowClick:b,variant:f="outlined",size:v="md",color:w="primary",className:k,style:N,..._}){const j=o[v],$=m[v],C=Boolean(b),A=h||C,B={padding:`${$} ${j}`},z={...B,backgroundColor:"var(--_mp-color-surface-container)"},R={borderTop:"1px solid var(--_mp-color-outline-variant)",backgroundColor:"var(--_mp-row)"};return e("div",{"data-mp-size":v,"data-mp-variant":f,className:["mp-table rounded-mp-md overflow-x-auto",l[f],k??""].filter(Boolean).join(" "),style:{...r(w),...N},..._,children:t("table",{className:`text-mp-on-surface w-full text-start ${n[v]}`,style:{borderCollapse:"collapse"},children:[x?e("caption",{className:`text-mp-on-surface-variant ${a}`,style:{...B,textAlign:"start"},children:x}):null,e("colgroup",{children:c.map(t=>{return e("col",{style:void 0===t.width?void 0:{width:(r=t.width,"number"==typeof r?`${r}px`:r)}},t.key);var r})}),e("thead",{children:e("tr",{children:c.map(t=>e("th",{scope:"col",className:["text-mp-on-surface-variant whitespace-nowrap",i[v],g?"sticky top-0 z-10":""].filter(Boolean).join(" "),style:{...z,textAlign:t.align??"start"},children:t.label??t.key},t.key))})}),e("tbody",{children:0===d.length?e("tr",{className:s,style:R,children:e("td",{colSpan:c.length,className:"text-mp-on-surface-variant",style:{padding:`2rem ${j}`,textAlign:"center"},children:u})}):d.map((t,r)=>e("tr",{className:[s,y&&r%2==1?"[--_mp-row:var(--_mp-color-surface-container-low)]":"",A?"hover:[--_mp-row:var(--_mp-color-surface-container)]":"",C?"cursor-pointer":""].filter(Boolean).join(" "),style:R,onClick:b?()=>b(t,r):void 0,children:c.map(a=>e("td",{style:{...B,textAlign:a.align??"start"},children:a.render?a.render(t,r):t[a.key]},a.key))},p?p(t,r):r))})]})})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPTable}from"./MPTable";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import type { MPStyleProps } from '../../types';
|
|
2
3
|
/** The input modes this field is built for. */
|
|
3
4
|
export type MPTextFieldType = 'email' | 'password' | 'text';
|
|
4
|
-
export interface MPTextFieldProps {
|
|
5
|
+
export interface MPTextFieldProps extends MPStyleProps {
|
|
5
6
|
/**
|
|
6
7
|
* The field's text. This is a controlled component: what is shown is what is
|
|
7
8
|
* passed, except during composition — see `onChange`.
|
|
@@ -20,28 +21,21 @@ export interface MPTextFieldProps {
|
|
|
20
21
|
/** Native `autocomplete` token — `'email'`, `'current-password'`, `'off'`. */
|
|
21
22
|
autoComplete?: string;
|
|
22
23
|
/**
|
|
23
|
-
* Label above the field. Always drawn
|
|
24
|
-
* over the placeholder, so a field with a label and a field without
|
|
25
|
-
* at the same height in a form.
|
|
24
|
+
* Label above the field. Always drawn in the outline's notch rather than
|
|
25
|
+
* floating over the placeholder, so a field with a label and a field without
|
|
26
|
+
* one sit at the same height in a form.
|
|
26
27
|
*/
|
|
27
28
|
label?: string;
|
|
28
29
|
/** Marks the field required, both to assistive technology and to the label. */
|
|
29
30
|
required?: boolean;
|
|
30
31
|
/** Greys the field out and stops it taking input. */
|
|
31
32
|
disabled?: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Draws the field at MUI's `medium` size instead of `small`.
|
|
34
|
-
* @default false
|
|
35
|
-
*/
|
|
36
|
-
large?: boolean;
|
|
37
33
|
/**
|
|
38
34
|
* Focuses the field on mount — except on a small screen, where it would
|
|
39
35
|
* summon the on-screen keyboard over the page the reader has just arrived at.
|
|
40
36
|
* @default false
|
|
41
37
|
*/
|
|
42
38
|
autoFocus?: boolean;
|
|
43
|
-
/** Stretches the field to the width of its container. */
|
|
44
|
-
fullWidth?: boolean;
|
|
45
39
|
/**
|
|
46
40
|
* Shows the value without allowing edits. Unlike `disabled` the text stays
|
|
47
41
|
* selectable and the field stays in the tab order, which is what you want for
|
|
@@ -97,14 +91,19 @@ export interface MPTextFieldProps {
|
|
|
97
91
|
onFormReset?: () => void;
|
|
98
92
|
}
|
|
99
93
|
/**
|
|
100
|
-
* A Material
|
|
94
|
+
* A Material Design text field that survives an IME.
|
|
95
|
+
*
|
|
96
|
+
* The control is an outlined text field, drawn from Material Design 3's own
|
|
97
|
+
* component tokens: `outline` at rest, `primary` and a 2px stroke on focus,
|
|
98
|
+
* `error` when there is a message, and the spec's disabled opacities. Behaviour
|
|
99
|
+
* that a field needs but has nothing to do with looks — the label association,
|
|
100
|
+
* the validity plumbing, the `aria-describedby` onto the supporting text —
|
|
101
|
+
* comes from Base UI's `Field`.
|
|
101
102
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* exposes, plus the parts of a field that are always assembled by hand
|
|
107
|
-
* anyway: the label, the helper text, the adornments and the password toggle.
|
|
103
|
+
* What this component adds is the handling around a controlled input that a
|
|
104
|
+
* language with an input method exposes, plus the parts of a field that are
|
|
105
|
+
* always assembled by hand anyway: the notch, the adornments and the password
|
|
106
|
+
* toggle.
|
|
108
107
|
*
|
|
109
108
|
* ## The composition problem
|
|
110
109
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as o from"react";import{Field as a}from"@base-ui/react/field";import{MPIcon as n}from"../icon/MPIcon";import{MPFieldLabel as r,MPFieldOutline as l}from"../../internal/FieldOutline";import{VisibilityIcon as i,VisibilityOffIcon as s}from"../../constants/icons";const d={xs:{padding:"px-2",control:"py-1.5",text:"text-mp-body-medium",icon:16},sm:{padding:"px-3",control:"py-2.5",text:"text-mp-body-medium",icon:18},md:{padding:"px-4",control:"py-4",text:"text-mp-body-large",icon:20},lg:{padding:"px-4",control:"py-5",text:"text-mp-body-large",icon:22},xl:{padding:"px-5",control:"py-6",text:"text-mp-body-large",icon:24}};export const MPTextField=o.forwardRef(function({value:p,name:c,type:m="text",placeholder:u,autoComplete:f,label:x,onChange:b,onFormReset:y,onSubmit:g,errorMessage:h="",required:v=!1,fullWidth:w=!1,readOnly:C=!1,autoFocus:j=!1,size:k="md",disabled:z=!1,disableEnterKey:E=!1,rows:M,maxLength:N,startIcon:F,resizable:S=!1,id:q},D){const R=o.useRef(null),[I,O]=o.useState(!1),[B,K]=o.useState(!1),[L,P]=o.useState(p),U=o.useId(),$=q??`mp-text-field-${c??U}`,_=!!M,T=h.length>0,W=d[k],A=o.useCallback(e=>{R.current=e,"function"==typeof D?D(e):D&&(D.current=e)},[D]),G=e=>{e.preventDefault()};return o.useEffect(()=>{B||P(p)},[p,B]),o.useEffect(()=>{j&&!window.matchMedia("(max-width: 599.95px)").matches&&R.current?.focus()},[]),t(a.Root,{className:["mp-text-field group relative",w?"w-full":"inline-block","align-top"].join(" "),disabled:z,invalid:T,"data-mp-size":k,children:[t("div",{className:["relative flex w-full items-center gap-2",W.padding,_?"py-2":""].filter(Boolean).join(" "),children:[e(l,{label:x,required:v}),F?e("span",{className:"text-mp-on-surface-variant group-data-disabled:text-mp-on-surface/38 flex shrink-0 items-center",children:F}):null,e(a.Control,{render:_?e("textarea",{rows:M}):e("input",{}),id:$,name:c,type:_?void 0:I?"text":m,required:v,readOnly:C,disabled:z,autoComplete:f,placeholder:u,maxLength:N,value:B?L:p,ref:A,className:[`${W.text} text-mp-on-surface w-full min-w-0 flex-1`,"font-[family-name:var(--mp-sys-typescale-body-large-font)]","appearance-none border-0 bg-transparent px-0 outline-none","caret-mp-primary",W.control,_?"py-0":"",_&&S?"resize-y":"resize-none","group-data-disabled:text-mp-on-surface/38","placeholder:text-mp-on-surface-variant group-data-disabled:placeholder:text-mp-on-surface/38"].filter(Boolean).join(" "),onChange:e=>{y?.();const t=e.target.value;B&&P(t),b?.(t)},onCompositionStart:()=>{K(!0),P(p)},onCompositionUpdate:e=>{P(e.target.value)},onCompositionEnd:e=>{K(!1);const t=e.target.value;y?.(),b?.(t),P(t)},onKeyDown:e=>{"Enter"===e.key&&(g?.(),_&&!E||e.preventDefault())}}),"password"!==m||_?null:e("button",{type:"button","aria-label":I?"hide the password":"display the password",onClick:()=>O(e=>!e),onMouseDown:G,onMouseUp:G,disabled:z,className:["text-mp-on-surface-variant -mr-1 flex shrink-0 items-center justify-center","cursor-pointer appearance-none border-0 bg-transparent p-1 font-[inherit]","rounded-full outline-none","hover:text-mp-on-surface focus-visible:text-mp-primary","disabled:text-mp-on-surface/38 disabled:cursor-default"].join(" "),children:e(n,{icon:I?i:s,size:W.icon})})]}),x?e(r,{size:k,label:x,required:v,htmlFor:$}):null,T?e(a.Error,{match:!0,className:["mp-text-field__support text-mp-body-small text-mp-error mt-1 block",W.padding,"group-data-disabled:text-mp-on-surface/38"].join(" "),children:h}):null]})});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { MPColor, MPSize } from '../../types';
|
|
4
|
+
/**
|
|
5
|
+
* When the line under a link is drawn.
|
|
6
|
+
*
|
|
7
|
+
* `always` is the default, and the reason is `color`: an `MPTextLink` takes no
|
|
8
|
+
* accent family unless one is asked for, so with the line off there would be
|
|
9
|
+
* nothing at all distinguishing a link from the sentence it sits in. That is
|
|
10
|
+
* also why this is not a boolean — "no underline" is a real choice for a link in
|
|
11
|
+
* a nav bar or a footer, where position already says what it is, and it should
|
|
12
|
+
* have to be spelled out rather than fallen into.
|
|
13
|
+
*/
|
|
14
|
+
export type MPTextLinkUnderline = 'always' | 'hover' | 'none';
|
|
15
|
+
export interface MPTextLinkProps extends Omit<React.ComponentPropsWithoutRef<'a'>, 'color'> {
|
|
16
|
+
/** Where the link goes. */
|
|
17
|
+
href: string;
|
|
18
|
+
/**
|
|
19
|
+
* When the underline is drawn.
|
|
20
|
+
* @default 'always'
|
|
21
|
+
*/
|
|
22
|
+
underline?: MPTextLinkUnderline;
|
|
23
|
+
/**
|
|
24
|
+
* Which accent family the link reads. Like `MPTypography` and unlike every
|
|
25
|
+
* control in the library this has **no default** — a link in a paragraph is
|
|
26
|
+
* usually the paragraph's own colour with a line under it, and a component
|
|
27
|
+
* that arrived pre-dyed is one a page has to undo.
|
|
28
|
+
*/
|
|
29
|
+
color?: MPColor;
|
|
30
|
+
/**
|
|
31
|
+
* The type scale. Also no default: a link inside a sentence is the size of the
|
|
32
|
+
* sentence. Set it for a link that stands on its own.
|
|
33
|
+
*/
|
|
34
|
+
size?: MPSize;
|
|
35
|
+
/**
|
|
36
|
+
* Opens the link in a new tab, with the `rel` that keeps the new page from
|
|
37
|
+
* reaching back into this one.
|
|
38
|
+
*
|
|
39
|
+
* A window changing under the reader is the one thing about a link that cannot
|
|
40
|
+
* be seen before it happens, so this also turns `icon` on by default and adds
|
|
41
|
+
* a line for a screen reader — see `newTabLabel`.
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
newTab?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The mark after the label. `true` draws the arrow leaving its box when
|
|
47
|
+
* `newTab` is on and the chain otherwise, `false` draws nothing, and a node of
|
|
48
|
+
* your own replaces the glyph.
|
|
49
|
+
*
|
|
50
|
+
* Left out, it follows `newTab`.
|
|
51
|
+
*/
|
|
52
|
+
icon?: React.ReactNode | boolean;
|
|
53
|
+
/**
|
|
54
|
+
* What a screen reader hears after the label when `newTab` is on. A link
|
|
55
|
+
* without it says nothing of its own, so this changes nothing there.
|
|
56
|
+
* @default 'Opens in a new tab'
|
|
57
|
+
*/
|
|
58
|
+
newTabLabel?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Renders something other than an `<a>` — the `Link` a router brings, most of
|
|
61
|
+
* the time. `href` still goes through, so `render={<NextLink href="…" />}`
|
|
62
|
+
* needs it written once, on the `MPTextLink`.
|
|
63
|
+
*/
|
|
64
|
+
render?: useRender.RenderProp;
|
|
65
|
+
/** The label. */
|
|
66
|
+
children?: React.ReactNode;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A link, in a sentence or on its own.
|
|
70
|
+
*
|
|
71
|
+
* Everything about it is deliberately smaller than a button. It has no surface,
|
|
72
|
+
* no height of its own and no colour unless asked — what it has is a line under
|
|
73
|
+
* it, which is the one mark a reader already knows means "this goes somewhere".
|
|
74
|
+
*
|
|
75
|
+
* The three things it does that a bare `<a>` does not: it draws that line on a
|
|
76
|
+
* schedule (`always`, or only under the pointer), it marks a link that opens a
|
|
77
|
+
* new tab both visibly and for a screen reader, and it takes `render`, so the
|
|
78
|
+
* `Link` a router brings can wear all of it.
|
|
79
|
+
*
|
|
80
|
+
* ## Why this is not a button with an `href`
|
|
81
|
+
*
|
|
82
|
+
* `MPButton` deliberately has no `href`, and this is the other half of that
|
|
83
|
+
* decision. A link is announced as a link, opens in a new tab on the middle
|
|
84
|
+
* mouse button, and shows its destination in the status bar; a button does none
|
|
85
|
+
* of those and should not pretend to. Two components, because they are two
|
|
86
|
+
* things.
|
|
87
|
+
*/
|
|
88
|
+
export declare const MPTextLink: React.ForwardRefExoticComponent<MPTextLinkProps & React.RefAttributes<HTMLAnchorElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,Fragment as n,jsxs as o}from"react/jsx-runtime";import*as r from"react";import{useRender as i}from"@base-ui/react/use-render";import{MPIcon as t}from"../icon/MPIcon";import{ExternalLinkIcon as l,LinkIcon as s}from"../../constants/icons";import{accentSlots as a}from"../../internal/accent";import{PROSE_TEXT as c}from"../../internal/scale";import{VISUALLY_HIDDEN as m}from"../../internal/visually-hidden";const p={always:"[&.mp-link]:underline",hover:"[&.mp-link]:no-underline [&.mp-link]:hover:underline",none:"[&.mp-link]:no-underline"},d=["[&.mp-link]:[text-underline-offset:0.2em]","[&.mp-link]:[text-decoration-thickness:0.08em]","[&.mp-link]:[text-decoration-color:color-mix(in_oklab,currentColor_45%,transparent)]","[&.mp-link]:hover:[text-decoration-color:currentColor]"].join(" ");export const MPTextLink=r.forwardRef(function({href:r,underline:u="always",color:f,size:h,newTab:k=!1,icon:x,newTabLabel:b="Opens in a new tab",render:v,className:y,style:w,children:j,...N},_){const g=x??k,T=!0===g?e(t,{icon:k?l:s,size:"0.95em"}):g,z=["mp-link cursor-pointer","transition-[color,text-decoration-color]","duration-(--mp-sys-motion-duration-short4)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid focus-visible:rounded-mp-xs outline-none",h?c[h]:"",p[u],d,f?"[&.mp-link]:text-(--_mp-accent)":"[&.mp-link]:text-inherit",y??""].filter(Boolean).join(" ");return i({render:v??e("a",{}),ref:_,props:{href:r,target:k?"_blank":void 0,rel:k?"noopener noreferrer":void 0,className:z,style:f?{...a(f),...w}:w,children:o(n,{children:[j,T?e("span",{className:"ms-[0.25em] inline-flex align-baseline",children:T}):null,k?o(n,{children:[" ",e("span",{className:m,children:b})]}):null]}),...N}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPTextLink}from"./MPTextLink";
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MPPickerLabels } from '../../internal/Calendar';
|
|
3
|
+
import { type MPPickerShellProps } from '../../internal/Picker';
|
|
4
|
+
import { type MPTimeUnit } from '../../internal/date';
|
|
5
|
+
/**
|
|
6
|
+
* Which column of the clock a row belongs to.
|
|
7
|
+
*
|
|
8
|
+
* Re-exported so a caller writing a `shouldDisableTime` rule can name the
|
|
9
|
+
* argument it is handed.
|
|
10
|
+
*/
|
|
11
|
+
export type { MPTimeUnit };
|
|
12
|
+
export interface MPTimePickerProps extends MPPickerShellProps {
|
|
13
|
+
/**
|
|
14
|
+
* The chosen time. A `Date`, so it carries a day as well — see
|
|
15
|
+
* `referenceDate`.
|
|
16
|
+
*/
|
|
17
|
+
value?: Date | null;
|
|
18
|
+
defaultValue?: Date | null;
|
|
19
|
+
onValueChange?: (value: Date | null) => void;
|
|
20
|
+
open?: boolean;
|
|
21
|
+
defaultOpen?: boolean;
|
|
22
|
+
onOpenChange?: (open: boolean) => void;
|
|
23
|
+
/**
|
|
24
|
+
* The day a chosen time is written onto while there is no value yet.
|
|
25
|
+
* @default today
|
|
26
|
+
*/
|
|
27
|
+
referenceDate?: Date;
|
|
28
|
+
/** The earliest time of day that may be chosen. Only the clock is read. */
|
|
29
|
+
minTime?: Date | null;
|
|
30
|
+
/** The latest time of day that may be chosen. */
|
|
31
|
+
maxTime?: Date | null;
|
|
32
|
+
/**
|
|
33
|
+
* Blocks individual rows. Called once per row per column with the instant that
|
|
34
|
+
* row would produce and the column it is in, so a rule may be as coarse as
|
|
35
|
+
* "no afternoons" or as fine as one minute.
|
|
36
|
+
*/
|
|
37
|
+
shouldDisableTime?: (value: Date, unit: MPTimeUnit) => boolean;
|
|
38
|
+
/** A 12-hour dial with an AM/PM column. Defaults to whatever the locale does. */
|
|
39
|
+
hour12?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Adds the seconds column.
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
showSeconds?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* How far apart the rows of each column are.
|
|
47
|
+
* @default 1
|
|
48
|
+
*/
|
|
49
|
+
hourStep?: number;
|
|
50
|
+
minuteStep?: number;
|
|
51
|
+
secondStep?: number;
|
|
52
|
+
/**
|
|
53
|
+
* A BCP 47 tag deciding whether the clock is 12- or 24-hour, what AM and PM
|
|
54
|
+
* are called, and how the trigger writes the time. Falls back to the nearest
|
|
55
|
+
* `MPLocaleProvider`, then to the platform's own.
|
|
56
|
+
*/
|
|
57
|
+
locale?: string;
|
|
58
|
+
/**
|
|
59
|
+
* How the trigger writes the chosen time. Passed straight to `Intl`.
|
|
60
|
+
* @default { hour: 'numeric', minute: '2-digit' }, plus seconds when shown
|
|
61
|
+
*/
|
|
62
|
+
format?: Intl.DateTimeFormatOptions;
|
|
63
|
+
placeholder?: React.ReactNode;
|
|
64
|
+
clearable?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Offers the shortcut to the current time in the footer.
|
|
67
|
+
* @default true
|
|
68
|
+
*/
|
|
69
|
+
showNowButton?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Closes the popup as soon as any column is touched.
|
|
72
|
+
*
|
|
73
|
+
* `false` by default, and unlike `MPDatePicker`: a time is two answers, and
|
|
74
|
+
* closing after the first one would make choosing 9:30 a matter of opening the
|
|
75
|
+
* popup twice.
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
closeOnSelect?: boolean;
|
|
79
|
+
labels?: Partial<MPPickerLabels>;
|
|
80
|
+
/** Identifies the field when a form is submitted, as `HH:MM` (`HH:MM:SS`). */
|
|
81
|
+
name?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A time of day, chosen from columns.
|
|
85
|
+
*
|
|
86
|
+
* The bounds are checked at the granularity of the column being drawn, which is
|
|
87
|
+
* the detail that separates a working time picker from a frustrating one. With a
|
|
88
|
+
* `minTime` of 09:30, the hour `9` stays available — the hour *contains* allowed
|
|
89
|
+
* minutes — and it is the minute column that greys out `00` through `25`. The
|
|
90
|
+
* naive check compares the whole candidate instant, hides the 9 entirely, and
|
|
91
|
+
* makes half past nine unreachable.
|
|
92
|
+
*
|
|
93
|
+
* The value is a `Date` rather than a string or a number of minutes, because
|
|
94
|
+
* everything else in this library that carries a moment is one, and because a
|
|
95
|
+
* time on its own has nowhere to record which day it is on — which is what
|
|
96
|
+
* decides whether it crossed a daylight-saving boundary. `referenceDate` is the
|
|
97
|
+
* day a bare time is written onto.
|
|
98
|
+
*
|
|
99
|
+
* ## Columns, not MD3's dial
|
|
100
|
+
*
|
|
101
|
+
* This is the one place the library knowingly draws something the specification
|
|
102
|
+
* draws differently, and the reason is in `internal/Calendar.tsx` next to the
|
|
103
|
+
* grid itself: a dial is a pointer control, MD3 ships a second "time input" mode
|
|
104
|
+
* precisely because a dial cannot serve a keyboard, and a component with two
|
|
105
|
+
* implementations of one question has the accessible one hidden behind a toggle.
|
|
106
|
+
* Columns answer both readers at once, in the library's own shapes.
|
|
107
|
+
*/
|
|
108
|
+
export declare const MPTimePicker: React.ForwardRefExoticComponent<MPTimePickerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as n from"react";import{MPButton as l}from"../button/MPButton";import{MPIcon as r}from"../icon/MPIcon";import{ClockIcon as t}from"../../constants/icons";import{MPTimeGrid as a}from"../../internal/Calendar";import{FOOTER_SIZE as i,MPPickerFooter as s,MPPickerShell as c}from"../../internal/Picker";import{useMPLocale as u,useMPMessages as m}from"../../internal/locale";import{CONTROL_ICON as d}from"../../internal/scale";import{displaySamples as p,formatDate as h,isHour12 as f,isValidDate as g,secondsOfDay as S,timeUnitSpan as b,toISOTime as v,withPlaceholder as C,withTime as x}from"../../internal/date";export const MPTimePicker=n.forwardRef(function({value:k,defaultValue:w,onValueChange:z,open:D,defaultOpen:O,onOpenChange:y,referenceDate:M,minTime:P,maxTime:T,shouldDisableTime:j,hour12:I,showSeconds:V=!1,hourStep:B=1,minuteStep:N=1,secondStep:R=1,locale:F,format:H,placeholder:q,clearable:A=!1,showNowButton:E=!0,closeOnSelect:G=!1,labels:J,name:K,size:L="md",color:Q="primary",readOnly:U=!1,disabled:W=!1,startIcon:X,...Y},Z){const $=u(F),_=m("picker",$,J),ee=I??f($),[oe,ne]=n.useState(w??null),le=void 0!==k?k:oe,[re,te]=n.useState(O??!1),ae=D??re,[ie]=n.useState(()=>M??new Date),se=e=>{e&&(U||W)||(void 0===D&&te(e),y?.(e))},ce=e=>{void 0===k&&ne(e),z?.(e)},ue=n.useCallback((e,o)=>{const[n,l]=b(o,e);return!!(g(P)&&l<S(P))||(!!(g(T)&&n>S(T))||(j?.(e,o)??!1))},[P,T,j]),me=H??{hour:"numeric",minute:"2-digit",hour12:ee,...V?{second:"2-digit"}:{}},de=new Date,pe=x(M??ie,{hours:de.getHours(),minutes:de.getMinutes(),seconds:V?de.getSeconds():0}),he=E||A||!G,fe=n.useMemo(()=>C(p($,me),q),[$,me,q]);return e(c,{...Y,slug:"time-picker",size:L,color:Q,readOnly:U,disabled:W,name:K,triggerRef:Z,startIcon:X??e(r,{icon:t,size:d[L]}),display:g(le)?h(le,$,me):q??"",samples:fe,empty:!g(le),clearable:A,onClear:()=>ce(null),open:ae,onOpenChange:se,labels:_,hiddenValues:K?[{name:K,value:g(le)?v(le,V):""}]:void 0,children:o("div",{className:"flex flex-col "+(he?"gap-1.5":""),children:[e(a,{size:L,locale:$,value:g(le)?le:null,referenceDate:M??ie,onChange:e=>{ce(e),G&&se(!1)},hour12:ee,showSeconds:V,hourStep:B,minuteStep:N,secondStep:R,shouldDisableTime:ue,labels:_,autoFocus:!0}),he?o(s,{children:[A?e(l,{variant:"text",size:i[L],color:Q,onClick:()=>{ce(null),se(!1)},children:_.clear}):null,E?e(l,{variant:"text",size:i[L],color:Q,disabled:ue(pe,"second"),onClick:()=>{ce(pe),se(!1)},children:_.now}):null,G?null:e(l,{variant:"filled",size:i[L],color:Q,onClick:()=>se(!1),children:_.done})]}):null]})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MPTimePicker}from"./MPTimePicker";
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { MPColor, MPOrientation, MPSize } from '../../types';
|
|
4
|
+
/**
|
|
5
|
+
* How far along one item is.
|
|
6
|
+
*
|
|
7
|
+
* Three states rather than two, because "the one you are on" is not the same
|
|
8
|
+
* claim as "done", and a sequence that cannot say which step is current is a
|
|
9
|
+
* list. Each gets its own axis — a filled bullet, a filled bullet with a halo
|
|
10
|
+
* around it, an empty one — rather than three shades of the same thing.
|
|
11
|
+
*/
|
|
12
|
+
export type MPTimelineStatus = 'complete' | 'current' | 'upcoming';
|
|
13
|
+
/** How the line between two items is drawn. `none` leaves the gap open. */
|
|
14
|
+
export type MPTimelineConnector = 'solid' | 'dashed' | 'dotted' | 'none';
|
|
15
|
+
export interface MPTimelineProps extends Omit<React.ComponentPropsWithoutRef<'ol'>, 'color'> {
|
|
16
|
+
/**
|
|
17
|
+
* How far the sequence has got: the index of the item being worked on now.
|
|
18
|
+
* Everything before it is complete, everything after it is still to come.
|
|
19
|
+
*
|
|
20
|
+
* An index rather than a value, because a timeline has no selection — nothing
|
|
21
|
+
* here is chosen, and the only question is how far down the list reality has
|
|
22
|
+
* reached. Omit it and every item is `upcoming` unless it says otherwise; pass
|
|
23
|
+
* the item count to mark the whole sequence done.
|
|
24
|
+
*/
|
|
25
|
+
active?: number;
|
|
26
|
+
/** @default 'md' */
|
|
27
|
+
size?: MPSize;
|
|
28
|
+
/** @default 'primary' */
|
|
29
|
+
color?: MPColor;
|
|
30
|
+
/**
|
|
31
|
+
* Which way the sequence runs. `vertical` is the default and the one that
|
|
32
|
+
* takes an arbitrary number of steps with an arbitrary amount to say about
|
|
33
|
+
* each; `horizontal` is the stepper across the top of a checkout, and it is
|
|
34
|
+
* only honest while every label is short.
|
|
35
|
+
* @default 'vertical'
|
|
36
|
+
*/
|
|
37
|
+
orientation?: MPOrientation;
|
|
38
|
+
/** Renders something other than an `<ol>` — Base UI's own escape hatch. */
|
|
39
|
+
render?: useRender.RenderProp;
|
|
40
|
+
children?: React.ReactNode;
|
|
41
|
+
}
|
|
42
|
+
export interface MPTimelineItemProps extends Omit<React.ComponentPropsWithoutRef<'li'>, 'color' | 'title'> {
|
|
43
|
+
/** The heading of this step. */
|
|
44
|
+
title?: React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* When it happened — a date, a duration, a name. Set beside the title on a
|
|
47
|
+
* wide item and under it on a narrow one.
|
|
48
|
+
*/
|
|
49
|
+
meta?: React.ReactNode;
|
|
50
|
+
/**
|
|
51
|
+
* What goes inside the bullet: a number, an icon, an avatar. Omit it and the
|
|
52
|
+
* bullet is a plain disc, which is what a step with nothing to say about
|
|
53
|
+
* itself should be.
|
|
54
|
+
*/
|
|
55
|
+
bullet?: React.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* Overrides what the timeline's `active` would have computed for this item — a
|
|
58
|
+
* step that failed and stopped the sequence, a step that was skipped.
|
|
59
|
+
*/
|
|
60
|
+
status?: MPTimelineStatus;
|
|
61
|
+
/** Overrides the timeline's accent family for this item alone. */
|
|
62
|
+
color?: MPColor;
|
|
63
|
+
/**
|
|
64
|
+
* How the line to the next item is drawn.
|
|
65
|
+
* @default 'solid'
|
|
66
|
+
*/
|
|
67
|
+
connector?: MPTimelineConnector;
|
|
68
|
+
/** The body of the step. */
|
|
69
|
+
children?: React.ReactNode;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* One step.
|
|
73
|
+
*
|
|
74
|
+
* Its index is not a prop and cannot be: an item that had to be told where it
|
|
75
|
+
* was in the list would be an item every caller could put in the wrong place,
|
|
76
|
+
* and `active={2}` would stop meaning anything. The timeline numbers its
|
|
77
|
+
* children as it walks them and hands each one its index through a context.
|
|
78
|
+
*/
|
|
79
|
+
export declare const MPTimelineItem: React.ForwardRefExoticComponent<MPTimelineItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
80
|
+
/**
|
|
81
|
+
* A sequence of steps, in the order they happen in.
|
|
82
|
+
*
|
|
83
|
+
* There is no Base UI primitive under this and there should not be: a timeline
|
|
84
|
+
* has no selection, no roving focus and no keyboard contract — it is a list, and
|
|
85
|
+
* reaching for a composite primitive to draw one would hand every consumer's
|
|
86
|
+
* record of events the semantics of a widget.
|
|
87
|
+
*
|
|
88
|
+
* It is an `<ol>` for the reason it exists at all: the order *is* the content. A
|
|
89
|
+
* screen reader announcing "list of 5 items" over an unordered list would be
|
|
90
|
+
* describing something else.
|
|
91
|
+
*
|
|
92
|
+
* The children are numbered here rather than by a prop on each item, so `active`
|
|
93
|
+
* has something to count against and inserting a step in the middle does not
|
|
94
|
+
* mean renumbering the ones after it.
|
|
95
|
+
*/
|
|
96
|
+
export declare const MPTimeline: React.ForwardRefExoticComponent<MPTimelineProps & React.RefAttributes<HTMLOListElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{useRender as n}from"@base-ui/react/use-render";import{accentSlots as l}from"../../internal/accent";import{hasContent as a,META_TEXT as o,PROSE_TEXT as i,SHEET_TITLE as s}from"../../internal/scale";const c=r.createContext(null),m=r.createContext({index:0,last:!1}),p={xs:"0.875rem",sm:"1rem",md:"1.25rem",lg:"1.5rem",xl:"1.875rem"},d={xs:"gap-2",sm:"gap-2.5",md:"gap-3",lg:"gap-3.5",xl:"gap-4"},u={xs:"pb-5",sm:"pb-6",md:"pb-7",lg:"pb-8",xl:"pb-10"},x={xs:"pe-5",sm:"pe-6",md:"pe-7",lg:"pe-8",xl:"pe-10"},f={solid:"border-solid",dashed:"border-dashed",dotted:"border-dotted",none:""},b={complete:"bg-(--_mp-accent) text-(--_mp-on-accent)",current:"bg-(--_mp-accent) text-(--_mp-on-accent) shadow-[0_0_0_0.25rem_var(--_mp-accent-container)]",upcoming:"border-mp-outline text-mp-on-surface-variant border-2 bg-transparent"},v={complete:"border-(--_mp-accent)",current:"border-mp-outline-variant",upcoming:"border-mp-outline-variant"},h={complete:"text-mp-on-surface",current:"text-(--_mp-accent)",upcoming:"text-mp-on-surface-variant"};export const MPTimelineItem=r.forwardRef(function({title:n,meta:g,bullet:_,status:N,color:y,connector:z="solid",className:j,style:w,children:$,...C},P){const B=r.useContext(c),{index:M,last:k}=r.useContext(m),R=B?.size??"md",T=B?.orientation??"vertical",A=y??B?.color??"primary",I=B?.active??null,q=N??(null===I?"upcoming":M<I?"complete":M===I?"current":"upcoming"),D="horizontal"===T,E="none"!==z&&!k,F=e("span",{"aria-hidden":"true",className:["rounded-mp-full relative z-10 flex shrink-0 items-center justify-center","size-(--_mp-bullet) text-[calc(var(--_mp-bullet)*0.5)] leading-none font-medium","tabular-nums [&>svg]:size-[0.6em]",b[q],"transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)"].join(" "),children:_}),G=E?e("span",{"aria-hidden":"true",className:["pointer-events-none absolute",D?"start-(--_mp-bullet) top-[calc(var(--_mp-bullet)/2_-_1px)] end-0 border-t-2":"top-(--_mp-bullet) start-[calc(var(--_mp-bullet)/2_-_1px)] bottom-0 border-s-2",f[z],v[q]].filter(Boolean).join(" ")}):null,H=t("div",{className:"flex min-w-0 flex-col gap-0.5 "+(D?"mt-2":""),children:[a(n)||a(g)?t("div",{className:"flex flex-wrap items-baseline gap-x-2",children:[a(n)?e("span",{className:`${s[R]} ${h[q]}`,children:n}):null,a(g)?e("span",{className:`text-mp-on-surface-variant ${o}`,children:g}):null]}):null,a($)?e("div",{className:`text-mp-on-surface-variant ${i[R]}`,children:$}):null]});return t("li",{ref:P,"aria-current":"current"===q?"step":void 0,"data-status":q,className:["relative",D?`flex min-w-0 flex-1 flex-col ${k?"":x[R]}`:`flex ${d[R]} ${k?"":u[R]}`,j??""].filter(Boolean).join(" "),style:{"--_mp-bullet":p[R],...l(A),...w},...C,children:[G,F,H]})});export const MPTimeline=r.forwardRef(function({active:t,size:l="md",color:a="primary",orientation:o="vertical",render:i,className:s,style:p,children:d,...u},x){const f=r.Children.toArray(d),b=f.length,v=r.useMemo(()=>({size:l,orientation:o,color:a,active:t??null}),[l,o,a,t]),h=n({render:i??e("ol",{}),ref:x,props:{role:"list","data-mp-size":l,className:["mp-timeline flex","horizontal"===o?"flex-row":"flex-col",s??""].filter(Boolean).join(" "),style:p,children:f.map((t,r)=>e(m.Provider,{value:{index:r,last:r===b-1},children:t},r)),...u}});return e(c.Provider,{value:v,children:h})});
|