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.
Files changed (265) hide show
  1. package/README.md +39 -28
  2. package/dist/components/accordion/MPAccordion.d.ts +115 -0
  3. package/dist/components/accordion/MPAccordion.js +1 -0
  4. package/dist/components/accordion/index.d.ts +2 -0
  5. package/dist/components/accordion/index.js +1 -0
  6. package/dist/components/alert/MPAlert.d.ts +91 -0
  7. package/dist/components/alert/MPAlert.js +1 -0
  8. package/dist/components/alert/index.d.ts +2 -0
  9. package/dist/components/alert/index.js +1 -0
  10. package/dist/components/aspect-ratio/MPAspectRatio.d.ts +69 -0
  11. package/dist/components/aspect-ratio/MPAspectRatio.js +1 -0
  12. package/dist/components/aspect-ratio/index.d.ts +2 -0
  13. package/dist/components/aspect-ratio/index.js +1 -0
  14. package/dist/components/avatar/MPAvatar.d.ts +97 -0
  15. package/dist/components/avatar/MPAvatar.js +1 -0
  16. package/dist/components/avatar/index.d.ts +2 -0
  17. package/dist/components/avatar/index.js +1 -0
  18. package/dist/components/badge/MPBadge.d.ts +104 -0
  19. package/dist/components/badge/MPBadge.js +1 -0
  20. package/dist/components/badge/index.d.ts +2 -0
  21. package/dist/components/badge/index.js +1 -0
  22. package/dist/components/blockquote/MPBlockquote.d.ts +73 -0
  23. package/dist/components/blockquote/MPBlockquote.js +1 -0
  24. package/dist/components/blockquote/index.d.ts +2 -0
  25. package/dist/components/blockquote/index.js +1 -0
  26. package/dist/components/box/MPBox.d.ts +78 -0
  27. package/dist/components/box/MPBox.js +1 -0
  28. package/dist/components/box/index.d.ts +2 -0
  29. package/dist/components/box/index.js +1 -0
  30. package/dist/components/breadcrumb/MPBreadcrumb.d.ts +105 -0
  31. package/dist/components/breadcrumb/MPBreadcrumb.js +1 -0
  32. package/dist/components/breadcrumb/index.d.ts +2 -0
  33. package/dist/components/breadcrumb/index.js +1 -0
  34. package/dist/components/button/MPButton.d.ts +70 -0
  35. package/dist/components/button/MPButton.js +1 -0
  36. package/dist/components/button/index.d.ts +2 -0
  37. package/dist/components/button/index.js +1 -0
  38. package/dist/components/button-group/MPButtonGroup.d.ts +31 -0
  39. package/dist/components/button-group/MPButtonGroup.js +1 -0
  40. package/dist/components/button-group/index.d.ts +2 -0
  41. package/dist/components/button-group/index.js +1 -0
  42. package/dist/components/card/MPCard.d.ts +73 -0
  43. package/dist/components/card/MPCard.js +1 -0
  44. package/dist/components/card/index.d.ts +2 -0
  45. package/dist/components/card/index.js +1 -0
  46. package/dist/components/carousel/MPCarousel.d.ts +116 -0
  47. package/dist/components/carousel/MPCarousel.js +1 -0
  48. package/dist/components/carousel/index.d.ts +2 -0
  49. package/dist/components/carousel/index.js +1 -0
  50. package/dist/components/chat-bubble/MPChatBubble.d.ts +132 -0
  51. package/dist/components/chat-bubble/MPChatBubble.js +1 -0
  52. package/dist/components/chat-bubble/index.d.ts +2 -0
  53. package/dist/components/chat-bubble/index.js +1 -0
  54. package/dist/components/checkbox/MPCheckbox.d.ts +76 -0
  55. package/dist/components/checkbox/MPCheckbox.js +1 -0
  56. package/dist/components/checkbox/index.d.ts +2 -0
  57. package/dist/components/checkbox/index.js +1 -0
  58. package/dist/components/chip/MPChip.d.ts +64 -0
  59. package/dist/components/chip/MPChip.js +1 -0
  60. package/dist/components/chip/index.d.ts +2 -0
  61. package/dist/components/chip/index.js +1 -0
  62. package/dist/components/collapsible/MPCollapsible.d.ts +97 -0
  63. package/dist/components/collapsible/MPCollapsible.js +1 -0
  64. package/dist/components/collapsible/index.d.ts +2 -0
  65. package/dist/components/collapsible/index.js +1 -0
  66. package/dist/components/color-picker/MPColorPicker.d.ts +113 -0
  67. package/dist/components/color-picker/MPColorPicker.js +1 -0
  68. package/dist/components/color-picker/index.d.ts +2 -0
  69. package/dist/components/color-picker/index.js +1 -0
  70. package/dist/components/combobox/MPCombobox.d.ts +147 -0
  71. package/dist/components/combobox/MPCombobox.js +1 -0
  72. package/dist/components/combobox/index.d.ts +2 -0
  73. package/dist/components/combobox/index.js +1 -0
  74. package/dist/components/date-picker/MPDatePicker.d.ts +95 -0
  75. package/dist/components/date-picker/MPDatePicker.js +1 -0
  76. package/dist/components/date-picker/index.d.ts +2 -0
  77. package/dist/components/date-picker/index.js +1 -0
  78. package/dist/components/date-range-picker/MPDateRangePicker.d.ts +98 -0
  79. package/dist/components/date-range-picker/MPDateRangePicker.js +1 -0
  80. package/dist/components/date-range-picker/index.d.ts +2 -0
  81. package/dist/components/date-range-picker/index.js +1 -0
  82. package/dist/components/date-time-picker/MPDateTimePicker.d.ts +78 -0
  83. package/dist/components/date-time-picker/MPDateTimePicker.js +1 -0
  84. package/dist/components/date-time-picker/index.d.ts +2 -0
  85. package/dist/components/date-time-picker/index.js +1 -0
  86. package/dist/components/dialog/MPDialog.d.ts +145 -0
  87. package/dist/components/dialog/MPDialog.js +1 -0
  88. package/dist/components/dialog/index.d.ts +2 -0
  89. package/dist/components/dialog/index.js +1 -0
  90. package/dist/components/divider/MPDivider.d.ts +80 -0
  91. package/dist/components/divider/MPDivider.js +1 -0
  92. package/dist/components/divider/index.d.ts +2 -0
  93. package/dist/components/divider/index.js +1 -0
  94. package/dist/components/drawer/MPDrawer.d.ts +163 -0
  95. package/dist/components/drawer/MPDrawer.js +1 -0
  96. package/dist/components/drawer/index.d.ts +2 -0
  97. package/dist/components/drawer/index.js +1 -0
  98. package/dist/components/empty/MPEmpty.d.ts +64 -0
  99. package/dist/components/empty/MPEmpty.js +1 -0
  100. package/dist/components/empty/index.d.ts +2 -0
  101. package/dist/components/empty/index.js +1 -0
  102. package/dist/components/file-picker/MPFilePicker.d.ts +103 -0
  103. package/dist/components/file-picker/MPFilePicker.js +1 -0
  104. package/dist/components/file-picker/index.d.ts +2 -0
  105. package/dist/components/file-picker/index.js +1 -0
  106. package/dist/components/highlight/MPHighlight.d.ts +95 -0
  107. package/dist/components/highlight/MPHighlight.js +1 -0
  108. package/dist/components/highlight/index.d.ts +2 -0
  109. package/dist/components/highlight/index.js +1 -0
  110. package/dist/components/icon-button/MPIconButton.d.ts +59 -0
  111. package/dist/components/icon-button/MPIconButton.js +1 -0
  112. package/dist/components/icon-button/index.d.ts +2 -0
  113. package/dist/components/icon-button/index.js +1 -0
  114. package/dist/components/list/MPList.d.ts +96 -0
  115. package/dist/components/list/MPList.js +1 -0
  116. package/dist/components/list/index.d.ts +2 -0
  117. package/dist/components/list/index.js +1 -0
  118. package/dist/components/locale/MPLocaleProvider.d.ts +63 -0
  119. package/dist/components/locale/MPLocaleProvider.js +1 -0
  120. package/dist/components/locale/index.d.ts +2 -0
  121. package/dist/components/locale/index.js +1 -0
  122. package/dist/components/menu/MPMenu.d.ts +223 -0
  123. package/dist/components/menu/MPMenu.js +1 -0
  124. package/dist/components/menu/index.d.ts +2 -0
  125. package/dist/components/menu/index.js +1 -0
  126. package/dist/components/number-field/MPNumberField.d.ts +99 -0
  127. package/dist/components/number-field/MPNumberField.js +1 -0
  128. package/dist/components/number-field/index.d.ts +2 -0
  129. package/dist/components/number-field/index.js +1 -0
  130. package/dist/components/otp-field/MPOtpField.d.ts +89 -0
  131. package/dist/components/otp-field/MPOtpField.js +1 -0
  132. package/dist/components/otp-field/index.d.ts +2 -0
  133. package/dist/components/otp-field/index.js +1 -0
  134. package/dist/components/overlay/MPOverlay.d.ts +96 -0
  135. package/dist/components/overlay/MPOverlay.js +1 -0
  136. package/dist/components/overlay/index.d.ts +2 -0
  137. package/dist/components/overlay/index.js +1 -0
  138. package/dist/components/panes/MPPanes.d.ts +100 -0
  139. package/dist/components/panes/MPPanes.js +1 -0
  140. package/dist/components/panes/index.d.ts +2 -0
  141. package/dist/components/panes/index.js +1 -0
  142. package/dist/components/pill/MPPill.d.ts +117 -0
  143. package/dist/components/pill/MPPill.js +1 -0
  144. package/dist/components/pill/index.d.ts +2 -0
  145. package/dist/components/pill/index.js +1 -0
  146. package/dist/components/popover/MPPopover.d.ts +138 -0
  147. package/dist/components/popover/MPPopover.js +1 -0
  148. package/dist/components/popover/index.d.ts +2 -0
  149. package/dist/components/popover/index.js +1 -0
  150. package/dist/components/progress-box/MPProgressBox.d.ts +40 -0
  151. package/dist/components/progress-box/MPProgressBox.js +1 -0
  152. package/dist/components/progress-box/index.d.ts +2 -0
  153. package/dist/components/progress-box/index.js +1 -0
  154. package/dist/components/progress-circular/MPProgressCircular.d.ts +32 -0
  155. package/dist/components/progress-circular/MPProgressCircular.js +1 -0
  156. package/dist/components/progress-circular/index.d.ts +2 -0
  157. package/dist/components/progress-circular/index.js +1 -0
  158. package/dist/components/progress-linear/MPProgressLinear.d.ts +32 -0
  159. package/dist/components/progress-linear/MPProgressLinear.js +1 -0
  160. package/dist/components/progress-linear/index.d.ts +2 -0
  161. package/dist/components/progress-linear/index.js +1 -0
  162. package/dist/components/radio-group/MPRadioGroup.d.ts +81 -0
  163. package/dist/components/radio-group/MPRadioGroup.js +1 -0
  164. package/dist/components/radio-group/index.d.ts +2 -0
  165. package/dist/components/radio-group/index.js +1 -0
  166. package/dist/components/segmented-button/MPSegmentedButton.d.ts +75 -0
  167. package/dist/components/segmented-button/MPSegmentedButton.js +1 -0
  168. package/dist/components/segmented-button/index.d.ts +2 -0
  169. package/dist/components/segmented-button/index.js +1 -0
  170. package/dist/components/select/MPSelect.d.ts +86 -0
  171. package/dist/components/select/MPSelect.js +1 -0
  172. package/dist/components/select/index.d.ts +2 -0
  173. package/dist/components/select/index.js +1 -0
  174. package/dist/components/shortcut/MPShortcut.d.ts +67 -0
  175. package/dist/components/shortcut/MPShortcut.js +1 -0
  176. package/dist/components/shortcut/index.d.ts +2 -0
  177. package/dist/components/shortcut/index.js +1 -0
  178. package/dist/components/skeleton/MPSkeleton.d.ts +76 -0
  179. package/dist/components/skeleton/MPSkeleton.js +1 -0
  180. package/dist/components/skeleton/index.d.ts +2 -0
  181. package/dist/components/skeleton/index.js +1 -0
  182. package/dist/components/slider/MPSlider.d.ts +77 -0
  183. package/dist/components/slider/MPSlider.js +1 -0
  184. package/dist/components/slider/index.d.ts +2 -0
  185. package/dist/components/slider/index.js +1 -0
  186. package/dist/components/snackbar/MPSnackbar.d.ts +170 -0
  187. package/dist/components/snackbar/MPSnackbar.js +1 -0
  188. package/dist/components/snackbar/index.d.ts +2 -0
  189. package/dist/components/snackbar/index.js +1 -0
  190. package/dist/components/spoiler/MPSpoiler.d.ts +106 -0
  191. package/dist/components/spoiler/MPSpoiler.js +1 -0
  192. package/dist/components/spoiler/index.d.ts +2 -0
  193. package/dist/components/spoiler/index.js +1 -0
  194. package/dist/components/switch/MPSwitch.d.ts +75 -0
  195. package/dist/components/switch/MPSwitch.js +1 -0
  196. package/dist/components/switch/index.d.ts +2 -0
  197. package/dist/components/switch/index.js +1 -0
  198. package/dist/components/table/MPTable.d.ts +107 -0
  199. package/dist/components/table/MPTable.js +1 -0
  200. package/dist/components/table/index.d.ts +2 -0
  201. package/dist/components/table/index.js +1 -0
  202. package/dist/components/text-field/MPTextField.d.ts +17 -18
  203. package/dist/components/text-field/MPTextField.js +1 -1
  204. package/dist/components/text-link/MPTextLink.d.ts +88 -0
  205. package/dist/components/text-link/MPTextLink.js +1 -0
  206. package/dist/components/text-link/index.d.ts +2 -0
  207. package/dist/components/text-link/index.js +1 -0
  208. package/dist/components/time-picker/MPTimePicker.d.ts +108 -0
  209. package/dist/components/time-picker/MPTimePicker.js +1 -0
  210. package/dist/components/time-picker/index.d.ts +2 -0
  211. package/dist/components/time-picker/index.js +1 -0
  212. package/dist/components/timeline/MPTimeline.d.ts +96 -0
  213. package/dist/components/timeline/MPTimeline.js +1 -0
  214. package/dist/components/timeline/index.d.ts +2 -0
  215. package/dist/components/timeline/index.js +1 -0
  216. package/dist/components/tooltip/MPTooltip.d.ts +117 -0
  217. package/dist/components/tooltip/MPTooltip.js +1 -0
  218. package/dist/components/tooltip/index.d.ts +2 -0
  219. package/dist/components/tooltip/index.js +1 -0
  220. package/dist/components/typography/MPTypography.d.ts +94 -0
  221. package/dist/components/typography/MPTypography.js +1 -0
  222. package/dist/components/typography/index.d.ts +2 -0
  223. package/dist/components/typography/index.js +1 -0
  224. package/dist/constants/icons.d.ts +36 -0
  225. package/dist/constants/icons.js +1 -1
  226. package/dist/index.d.ts +55 -0
  227. package/dist/index.js +1 -1
  228. package/dist/internal/Calendar.d.ts +118 -0
  229. package/dist/internal/Calendar.js +1 -0
  230. package/dist/internal/FieldOutline.d.ts +38 -0
  231. package/dist/internal/FieldOutline.js +1 -0
  232. package/dist/internal/Picker.d.ts +110 -0
  233. package/dist/internal/Picker.js +1 -0
  234. package/dist/internal/StateLayer.d.ts +45 -0
  235. package/dist/internal/StateLayer.js +1 -0
  236. package/dist/internal/SupportingText.d.ts +23 -0
  237. package/dist/internal/SupportingText.js +1 -0
  238. package/dist/internal/WidthSizer.d.ts +31 -0
  239. package/dist/internal/WidthSizer.js +1 -0
  240. package/dist/internal/accent.d.ts +39 -0
  241. package/dist/internal/accent.js +1 -0
  242. package/dist/internal/button-group.d.ts +21 -0
  243. package/dist/internal/button-group.js +1 -0
  244. package/dist/internal/color.d.ts +125 -0
  245. package/dist/internal/color.js +1 -0
  246. package/dist/internal/date.d.ts +179 -0
  247. package/dist/internal/date.js +1 -0
  248. package/dist/internal/i18n.d.ts +131 -0
  249. package/dist/internal/i18n.js +1 -0
  250. package/dist/internal/locale.d.ts +43 -0
  251. package/dist/internal/locale.js +1 -0
  252. package/dist/internal/menu.d.ts +23 -0
  253. package/dist/internal/menu.js +1 -0
  254. package/dist/internal/progress.d.ts +126 -0
  255. package/dist/internal/progress.js +1 -0
  256. package/dist/internal/scale.d.ts +127 -0
  257. package/dist/internal/scale.js +1 -0
  258. package/dist/internal/surface.d.ts +76 -0
  259. package/dist/internal/surface.js +1 -0
  260. package/dist/internal/visually-hidden.d.ts +23 -0
  261. package/dist/internal/visually-hidden.js +1 -0
  262. package/dist/styles.css +1 -1
  263. package/dist/tailwind.css +1285 -20
  264. package/dist/types.d.ts +107 -16
  265. package/package.json +16 -21
@@ -0,0 +1,145 @@
1
+ import * as React from 'react';
2
+ import { Dialog } from '@base-ui/react/dialog';
3
+ import type { MPColor, MPSize } from '../../types';
4
+ /**
5
+ * A dialog takes `size` and `color` and stops there.
6
+ *
7
+ * There is no `variant`: the five weights answer "how much of a surface does this
8
+ * paint against the page around it", and a modal has already taken the page.
9
+ * There is no `elevation` prop either — see the note on the sheet below.
10
+ */
11
+ export interface MPDialogProps {
12
+ /** The dialog is shown. Use with `onOpenChange` for a controlled dialog. */
13
+ open?: boolean;
14
+ /** Whether the dialog starts open, for an uncontrolled one. */
15
+ defaultOpen?: boolean;
16
+ onOpenChange?: (open: boolean) => void;
17
+ /**
18
+ * The element that opens the dialog, wired up by Base UI. Optional — a
19
+ * controlled dialog opened from elsewhere in the application needs no trigger
20
+ * at all, and passing one here is a convenience for the common case.
21
+ */
22
+ trigger?: React.ReactElement;
23
+ /**
24
+ * A glyph above the headline.
25
+ *
26
+ * MD3's own hero icon, and passing one is what centres the header: a dialog
27
+ * with an icon is announcing something, and a dialog without one is asking
28
+ * something. Both are correct; they are two different dialogs.
29
+ */
30
+ icon?: React.ReactNode;
31
+ /** The headline. Rendered as the `<h2>` that names the dialog. */
32
+ title?: React.ReactNode;
33
+ /** The supporting text under it, and the dialog's accessible description. */
34
+ description?: React.ReactNode;
35
+ /**
36
+ * The bottom row. Laid out end-aligned, so a pair of buttons needs no wrapper
37
+ * of its own — and `MPDialogClose` is what makes one of them dismiss.
38
+ */
39
+ actions?: React.ReactNode;
40
+ /**
41
+ * Draws a hairline between the header, the body and the actions instead of
42
+ * separating them with space. Worth turning on the moment the body scrolls: the
43
+ * lines are what say the header stayed put.
44
+ * @default false
45
+ */
46
+ dividers?: boolean;
47
+ /**
48
+ * Shows the × in the corner.
49
+ *
50
+ * Defaults to whatever `fullScreen` is, which is MD3's own split: a basic
51
+ * dialog is answered by its actions and has no ×, while a full-screen dialog
52
+ * carries one at the start of its top bar because there is no scrim left to
53
+ * click. Set it explicitly to disagree with either.
54
+ */
55
+ showClose?: boolean;
56
+ /**
57
+ * Accessible name of the × button.
58
+ * @default 'Close'
59
+ */
60
+ closeLabel?: string;
61
+ /**
62
+ * A hard cap on the sheet's width, overriding the one `size` implies. Numbers
63
+ * are pixels. For the dialog whose *content* decides its width — a wide table,
64
+ * a narrow confirmation — rather than for tuning the scale, which is `size`.
65
+ */
66
+ width?: number | string;
67
+ /**
68
+ * The sheet takes the full width its `size` allows.
69
+ *
70
+ * On by default, which is the other way round from every other component in the
71
+ * library. Elsewhere `fullWidth` means "fill the container"; a dialog's
72
+ * container is the viewport, and a dialog that shrank to fit two words would be
73
+ * a tooltip.
74
+ * @default true
75
+ */
76
+ fullWidth?: boolean;
77
+ /** Fills the viewport edge to edge. For a phone-sized screen, or an editor. */
78
+ fullScreen?: boolean;
79
+ /**
80
+ * Whether the page behind is taken away. `'trap-focus'` keeps the page
81
+ * scrollable and clickable while still holding focus inside.
82
+ * @default true
83
+ */
84
+ modal?: boolean | 'trap-focus';
85
+ /**
86
+ * Whether Escape or a click outside closes the dialog. Turn it off for the
87
+ * dialog that has to be answered — and then give it actions that answer it,
88
+ * because there will be no other way out.
89
+ * @default true
90
+ */
91
+ dismissible?: boolean;
92
+ /**
93
+ * The type scale the sheet is drawn at, and how wide it is allowed to get.
94
+ * @default 'md'
95
+ */
96
+ size?: MPSize;
97
+ /**
98
+ * Which accent family the hero icon reads.
99
+ *
100
+ * The sheet itself stays neutral, exactly as MD3's does — a dialog is already
101
+ * the only thing on the screen, and painting it in an accent would be shouting
102
+ * at a reader who is not looking anywhere else. The icon is the one part that
103
+ * carries a family, and `secondary` is the spec's own choice for it.
104
+ * @default 'secondary'
105
+ */
106
+ color?: MPColor;
107
+ /** The body. */
108
+ children?: React.ReactNode;
109
+ className?: string;
110
+ style?: React.CSSProperties;
111
+ }
112
+ export type MPDialogCloseProps = React.ComponentProps<typeof Dialog.Close>;
113
+ /**
114
+ * Closes the dialog it is inside.
115
+ *
116
+ * Exported because an uncontrolled dialog has no `setOpen` for its Cancel button
117
+ * to call, and the alternative — making every dialog controlled — is a piece of
118
+ * state per dialog that exists only to answer a button.
119
+ *
120
+ * `render` is Base UI's own escape hatch, so a real Material Plus button
121
+ * dismisses: `<MPDialogClose render={<MPButton variant="text">Cancel</MPButton>} />`.
122
+ */
123
+ export declare const MPDialogClose: React.ForwardRefExoticComponent<Omit<import("@base-ui/react").AlertDialogCloseProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
124
+ /**
125
+ * A sheet that takes the page away until it is answered.
126
+ *
127
+ * The sections are props rather than compound sub-components: the arrangement of
128
+ * a dialog is fixed — icon, headline, supporting text, body, actions — and what a
129
+ * caller wants to decide is what goes in each slot, not what order they come in.
130
+ *
131
+ * Base UI owns everything hard about it: the focus trap, the scroll lock, the
132
+ * `aria-labelledby` / `aria-describedby` wiring, restoring focus to the trigger,
133
+ * and the inert page behind. What is left here is the surface, the width ladder
134
+ * and the scroll behaviour — the header and the actions stay put while only the
135
+ * body scrolls, which is why `dividers` matters more here than on a list.
136
+ *
137
+ * ## The sheet
138
+ *
139
+ * `surface-container-high` at `corner-extra-large`, elevation 3 — MD3's own three
140
+ * choices for a dialog, and the only surface in this library that carries the
141
+ * third elevation level. There is no `elevation` prop for the same reason there
142
+ * is no `variant`: a dialog that could be told to sit flat on the page would be a
143
+ * dialog that could be told to stop being a dialog.
144
+ */
145
+ export declare function MPDialog({ open, defaultOpen, onOpenChange, trigger, icon, title, description, actions, dividers, showClose, closeLabel, width, fullWidth, fullScreen, modal, dismissible, size, color, className, style, children }: MPDialogProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as l}from"react/jsx-runtime";import{Dialog as i}from"@base-ui/react/dialog";import{MPIcon as t}from"../icon/MPIcon";import{CloseIcon as n}from"../../constants/icons";import{accentSlots as o}from"../../internal/accent";import{MPStateLayer as s}from"../../internal/StateLayer";import{SHEET_GAP as r,hasContent as a}from"../../internal/scale";import{FADE as m,PORTAL_LAYER as c,SCRIM as p}from"../../internal/surface";const d={xs:"max-w-[320px]",sm:"max-w-[400px]",md:"max-w-[560px]",lg:"max-w-[720px]",xl:"max-w-[960px]"},x={xs:"p-3",sm:"p-4",md:"p-6",lg:"p-7",xl:"p-8"},f={xs:"px-3",sm:"px-4",md:"px-6",lg:"px-7",xl:"px-8"},u={xs:"py-3",sm:"py-4",md:"py-6",lg:"py-7",xl:"py-8"},h={xs:"text-mp-title-medium",sm:"text-mp-title-large",md:"text-mp-headline-small",lg:"text-mp-headline-medium",xl:"text-mp-headline-large"},g={xs:"text-mp-body-small",sm:"text-mp-body-small",md:"text-mp-body-medium",lg:"text-mp-body-large",xl:"text-mp-body-large"},y={xs:20,sm:22,md:24,lg:28,xl:32};export const MPDialogClose=i.Close;export function MPDialog({open:v,defaultOpen:b,onOpenChange:w,trigger:j,icon:N,title:$,description:C,actions:k,dividers:P=!1,showClose:B,closeLabel:z="Close",width:D,fullWidth:O=!0,fullScreen:M=!1,modal:L=!0,dismissible:S=!0,size:T="md",color:W="secondary",className:I,style:R,children:V}){const _=B??M,q=a(N),A=a($)||a(C)||q,E=a(k),F=P?x[T]:f[T],G="border-mp-outline-variant border-t";return l(i.Root,{open:v,defaultOpen:b,modal:L,disablePointerDismissal:!S,onOpenChange:(e,l)=>{S||e||"escape-key"!==l.reason?w?.(e):l.cancel()},children:[j?e(i.Trigger,{render:j}):null,l(i.Portal,{children:[e(i.Backdrop,{className:`${c} fixed inset-0 ${m} ${p}`}),e(i.Viewport,{className:[c,"fixed inset-0 flex justify-center",M?"items-stretch":"items-center p-4"].join(" "),children:l(i.Popup,{"data-mp-size":T,className:["mp-dialog relative flex w-full flex-col overflow-hidden","bg-mp-surface-container-high text-mp-on-surface shadow-mp-3 outline-none",M?"h-full max-w-none rounded-none":`rounded-mp-xl max-h-full ${void 0===D?d[T]:""}`,M||O?"":"w-auto",P?"":`${u[T]} ${r[T]}`,m,I??""].filter(Boolean).join(" "),style:{...o(W),...void 0===D||M?null:{maxWidth:"number"==typeof D?`${D}px`:D},...R},children:[A||_?l("div",{className:["flex shrink-0 items-start gap-3",F,q&&!_?"flex-col items-center text-center":""].filter(Boolean).join(" "),children:[q?e("span",{className:"flex shrink-0 items-center justify-center text-(--_mp-accent)",children:N}):null,l("div",{className:`flex min-w-0 flex-1 flex-col ${r[T]}`,children:[a($)?e(i.Title,{className:`m-0 ${h[T]}`,children:$}):null,a(C)?e(i.Description,{className:`text-mp-on-surface-variant m-0 ${g[T]}`,children:C}):null]}),_?l(i.Close,{"aria-label":z,className:["group text-mp-on-surface-variant relative flex size-10 shrink-0","rounded-mp-full cursor-pointer items-center justify-center","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),children:[e(s,{}),e(t,{icon:n,size:y[T]})]}):null]}):null,a(V)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",g[T],F,P&&(A||_)?G:""].filter(Boolean).join(" "),children:V}):null,E?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",F,P?G:""].filter(Boolean).join(" "),children:k}):null]})})]})]})}
@@ -0,0 +1,2 @@
1
+ export { MPDialog, MPDialogClose } from './MPDialog';
2
+ export type { MPDialogCloseProps, MPDialogProps } from './MPDialog';
@@ -0,0 +1 @@
1
+ export{MPDialog,MPDialogClose}from"./MPDialog";
@@ -0,0 +1,80 @@
1
+ import * as React from 'react';
2
+ import type { MPAlign, MPColor, MPOrientation, MPSize } from '../../types';
3
+ /** Where the label sits along a labelled divider. Ignored without a label. */
4
+ export type MPDividerTextAlign = MPAlign;
5
+ export interface MPDividerProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'children'> {
6
+ /**
7
+ * Which way the line runs. A vertical divider has no height of its own — it
8
+ * stretches to its flex parent, the way a rule between two toolbar groups
9
+ * should.
10
+ * @default 'horizontal'
11
+ */
12
+ orientation?: MPOrientation;
13
+ /**
14
+ * Which accent family the rule is drawn in.
15
+ *
16
+ * **This is the one component in the library whose `color` has no default**,
17
+ * and the reason is the specification: MD3 gives a divider exactly one colour,
18
+ * `outline-variant`, and it is not an accent at all. It is the quietest line
19
+ * in the token sheet — quieter than `outline`, which is the edge of a control
20
+ * — because a divider's job is to separate two things without becoming a
21
+ * third.
22
+ *
23
+ * So left unset the rule is `outline-variant`, which is the Material divider.
24
+ * Setting it tints the rule with an accent, for the case a divider is carrying
25
+ * meaning rather than structure — the line under a failed section.
26
+ */
27
+ color?: MPColor;
28
+ /** Type scale of the label. Nothing else on a divider has a size. */
29
+ size?: MPSize;
30
+ /**
31
+ * How far the rule runs — the width of a horizontal divider, the height of a
32
+ * vertical one. A number is pixels; a string is any CSS length, so `'50%'`
33
+ * and `'12rem'` both work.
34
+ *
35
+ * `length` rather than `width`, because a divider is the one component whose
36
+ * long axis turns with `orientation`: a `width` that meant height half the
37
+ * time would be a worse name than a longer one.
38
+ *
39
+ * Left out, a horizontal divider is the full width of its container and a
40
+ * vertical one stretches to the height of the flex row it is in — which is
41
+ * what a rule between two things should do by default.
42
+ */
43
+ length?: number | string;
44
+ /**
45
+ * How thick the rule is. A number is pixels; a string is any CSS length.
46
+ *
47
+ * MD3's divider is 1dp and there is no second thickness in the specification.
48
+ * This exists for the hairline that has to survive a display where 1px is
49
+ * half a device pixel, not as a weight to design with.
50
+ * @default 1
51
+ */
52
+ thickness?: number | string;
53
+ /** A label set into the line — "OR" between two sign-in options. */
54
+ children?: React.ReactNode;
55
+ /**
56
+ * Where the label sits. `center` splits the line in half; `start` and `end`
57
+ * leave a short stub on the near side so the label still reads as set *into*
58
+ * the rule rather than floating above it.
59
+ * @default 'center'
60
+ */
61
+ textAlign?: MPDividerTextAlign;
62
+ }
63
+ /**
64
+ * A rule between two things.
65
+ *
66
+ * With no children it is Base UI's `Separator` and nothing else — a real
67
+ * `role="separator"` with the right `aria-orientation`. With children the line
68
+ * breaks around the label.
69
+ *
70
+ * `separator` is not a name-from-content role, so the visible label does *not*
71
+ * become the accessible name on its own: a screen reader would announce a bare
72
+ * "separator" and the word "OR" would be read as loose text somewhere nearby. A
73
+ * string label is therefore copied into `aria-label`. Anything richer is left
74
+ * alone — only the caller knows which part of it is the name.
75
+ *
76
+ * There is no `variant` and no elevation. A divider is not a surface: it has no
77
+ * container to paint, so four of the five variants would have nothing to say and
78
+ * the fifth would be the line it already is.
79
+ */
80
+ export declare const MPDivider: React.ForwardRefExoticComponent<MPDividerProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{Separator as l}from"@base-ui/react/separator";import{hasContent as a}from"../../internal/scale";const i="[border-color:var(--_mp-line)]";function o(e){return"number"==typeof e?`${e}px`:e}const n={horizontal:{start:["w-4 shrink-0","flex-1"],center:["flex-1","flex-1"],end:["flex-1","w-4 shrink-0"]},vertical:{start:["h-4 shrink-0","flex-1"],center:["flex-1","flex-1"],end:["flex-1","h-4 shrink-0"]}},s={xs:"text-mp-label-small",sm:"text-mp-label-small",md:"text-mp-label-medium",lg:"text-mp-label-large",xl:"text-mp-label-large"},m={xs:"gap-1.5",sm:"gap-2",md:"gap-3",lg:"gap-3.5",xl:"gap-4"};export const MPDivider=t.forwardRef(function({orientation:t="horizontal",color:p,size:d="md",length:c,thickness:f,textAlign:h="center",className:x,style:u,children:v,...b},w){const g="vertical"===t,_=a(v),$={"--_mp-line":p?`var(--_mp-color-${p})`:"var(--_mp-color-outline-variant)","--_mp-rule":o(f)??"1px"},j=o(c),k={...$,...void 0===j?null:g?{height:j}:{width:j},...u};if(!_)return e(l,{ref:w,orientation:t,"data-mp-size":d,className:["mp-divider",g?"w-0 border-l [border-left-width:var(--_mp-rule)] "+(void 0===j?"self-stretch":""):"h-0 w-full border-t [border-top-width:var(--_mp-rule)]",i,x??""].filter(Boolean).join(" "),style:k,...b});const[N,y]=n[t][h],z=g?"w-0 border-l [border-left-width:var(--_mp-rule)]":"h-0 border-t [border-top-width:var(--_mp-rule)]";return r(l,{ref:w,orientation:t,"aria-label":"string"==typeof v?v:void 0,"data-mp-size":d,className:["mp-divider flex items-center",g?"w-auto flex-col "+(void 0===j?"self-stretch":""):"w-full",m[d],x??""].filter(Boolean).join(" "),style:k,...b,children:[e("span",{"aria-hidden":"true",className:`${z} ${N} ${i}`}),e("span",{className:["text-mp-on-surface-variant shrink-0 whitespace-nowrap",s[d],g?"[writing-mode:vertical-rl]":""].filter(Boolean).join(" "),children:v}),e("span",{"aria-hidden":"true",className:`${z} ${y} ${i}`})]})});
@@ -0,0 +1,2 @@
1
+ export { MPDivider } from './MPDivider';
2
+ export type { MPDividerProps, MPDividerTextAlign } from './MPDivider';
@@ -0,0 +1 @@
1
+ export{MPDivider}from"./MPDivider";
@@ -0,0 +1,163 @@
1
+ import * as React from 'react';
2
+ import { Dialog } from '@base-ui/react/dialog';
3
+ import type { MPSide, MPSize } from '../../types';
4
+ /**
5
+ * How the panel relates to the page, in MD3's own two words for it.
6
+ *
7
+ * - `modal` — it is opened, it floats over the page on a scrim, it holds the
8
+ * focus, and it is dismissed. The navigation drawer behind a hamburger, the
9
+ * filter panel beside a table, the bottom sheet a phone raises.
10
+ * - `standard` — it is part of the layout and the page is laid out around it.
11
+ * No scrim, no portal, no focus trap, nothing to dismiss. The sidebar that is
12
+ * simply there.
13
+ *
14
+ * A separate axis from `variant`, which is why this component has no `variant`:
15
+ * the five weights answer "how much does this surface assert itself against the
16
+ * page", and a panel that has taken an edge of the window has answered it.
17
+ */
18
+ export type MPDrawerMode = 'modal' | 'standard';
19
+ /**
20
+ * A drawer takes `side`, `mode` and `size`, and stops there.
21
+ *
22
+ * There is no `variant`, for [MPDialog](../feedback/dialog)'s reason. There is
23
+ * no `color` either: MD3's navigation drawer is `surface-container-low` under
24
+ * neutral ink, and what carries an accent inside one is the *selected row*,
25
+ * which belongs to whatever list the caller puts in it.
26
+ */
27
+ export interface MPDrawerProps {
28
+ /**
29
+ * Which edge the panel is attached to.
30
+ *
31
+ * Physical rather than logical, the way `MPSide` is everywhere in this
32
+ * library: a drawer along the top of the window is along the top in every
33
+ * writing direction.
34
+ * @default 'left'
35
+ */
36
+ side?: MPSide;
37
+ /** @default 'modal' */
38
+ mode?: MPDrawerMode;
39
+ /** The drawer is shown. Use with `onOpenChange` for a controlled drawer. */
40
+ open?: boolean;
41
+ /**
42
+ * Whether the drawer starts open, for an uncontrolled one.
43
+ *
44
+ * Defaults to `false` in `modal` mode and `true` in `standard` mode, because a
45
+ * fixed sidebar that had to be opened before it appeared would not be a fixed
46
+ * sidebar.
47
+ */
48
+ defaultOpen?: boolean;
49
+ onOpenChange?: (open: boolean) => void;
50
+ /**
51
+ * The element that opens the drawer, wired up by Base UI.
52
+ *
53
+ * `modal` only. A `standard` drawer is not opened — it is in the layout — so a
54
+ * trigger there would have nothing to do and is not rendered.
55
+ */
56
+ trigger?: React.ReactElement;
57
+ /** The heading. Rendered as the element that names the drawer. */
58
+ title?: React.ReactNode;
59
+ /** A line under it, and the drawer's accessible description. */
60
+ description?: React.ReactNode;
61
+ /**
62
+ * The bottom row, held against the foot of the panel while the body scrolls.
63
+ * Laid out end-aligned, so a pair of buttons needs no wrapper of its own — and
64
+ * `MPDrawerClose` is what makes one of them dismiss.
65
+ */
66
+ actions?: React.ReactNode;
67
+ /**
68
+ * Draws a hairline between the header, the body and the actions instead of
69
+ * separating them with space. Worth turning on the moment the body scrolls:
70
+ * the lines are what say the header stayed put.
71
+ * @default false
72
+ */
73
+ dividers?: boolean;
74
+ /**
75
+ * Shows the × in the corner.
76
+ *
77
+ * On in `modal` mode, where the panel has taken the page and the way out
78
+ * should not have to be remembered; off in `standard` mode, where a × that
79
+ * closes a fixed sidebar with nothing to reopen it is a one-way door.
80
+ */
81
+ showClose?: boolean;
82
+ /**
83
+ * Accessible name of the × button.
84
+ * @default 'Close'
85
+ */
86
+ closeLabel?: string;
87
+ /**
88
+ * How far the panel reaches in from its edge: a **width** for `left` and
89
+ * `right`, a **height** for `top` and `bottom`. Numbers are pixels.
90
+ *
91
+ * Left alone, a side panel takes the width its `size` implies and a top or
92
+ * bottom panel is as tall as what is in it, up to 85% of the window.
93
+ */
94
+ extent?: number | string;
95
+ /**
96
+ * Rounds the corners on the edge that faces the page — the top and bottom of a
97
+ * side panel, the inner pair of a top or bottom one.
98
+ *
99
+ * The corners against the window edge are always square, because a corner cut
100
+ * off something that has no visible end is a corner cut off nothing.
101
+ * @default true
102
+ */
103
+ rounded?: boolean;
104
+ /**
105
+ * Whether pressing Escape or clicking the scrim closes the drawer. Turn it off
106
+ * for the drawer that has to be answered — and then give it actions that
107
+ * answer it, because there will be no other way out. `modal` only.
108
+ * @default true
109
+ */
110
+ dismissible?: boolean;
111
+ /**
112
+ * How far the panel reaches in by default, and the type scale inside it.
113
+ * `md` is MD3's own 360dp navigation drawer.
114
+ * @default 'md'
115
+ */
116
+ size?: MPSize;
117
+ /** The body. */
118
+ children?: React.ReactNode;
119
+ className?: string;
120
+ style?: React.CSSProperties;
121
+ }
122
+ export type MPDrawerCloseProps = React.ComponentProps<typeof Dialog.Close>;
123
+ /**
124
+ * Closes the drawer it is inside.
125
+ *
126
+ * Exported for `MPDialogClose`'s reason: an uncontrolled drawer has no `setOpen`
127
+ * for its Cancel button to call, and making every drawer controlled is a piece
128
+ * of state per drawer that exists only to answer a button.
129
+ *
130
+ * It is a `modal` drawer's button — a `standard` one is not a Base UI dialog and
131
+ * has nothing for this to talk to. `render` is Base UI's own escape hatch, so a
132
+ * real Material Plus button dismisses:
133
+ * `<MPDrawerClose render={<MPButton variant="text">Cancel</MPButton>} />`.
134
+ */
135
+ export declare const MPDrawerClose: React.ForwardRefExoticComponent<Omit<import("@base-ui/react").AlertDialogCloseProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
136
+ /**
137
+ * A panel attached to one edge of the window.
138
+ *
139
+ * Two things in one component, because they are the same panel: `modal` is the
140
+ * drawer you open — a scrim, a focus trap, Escape — and `standard` is the drawer
141
+ * that is simply part of the page. MD3 names both of them, and the reason they
142
+ * are not two components is that a sidebar becoming a hamburger at a breakpoint
143
+ * is one line rather than a swap.
144
+ *
145
+ * The sections are props rather than compound sub-components, as on
146
+ * [MPCard](../layout/card) and [MPDialog](../feedback/dialog): the arrangement
147
+ * is fixed — heading, description, body, actions — and the body is the only part
148
+ * that scrolls, so the heading and the actions stay put.
149
+ *
150
+ * In `modal` mode Base UI owns everything hard about it: the focus trap, the
151
+ * scroll lock, the `aria-labelledby` / `aria-describedby` wiring, restoring
152
+ * focus to the trigger, and the inert page behind.
153
+ *
154
+ * ## The surface, and why it does not slide
155
+ *
156
+ * `surface-container-low` at elevation 1 for the modal panel and `surface` flat
157
+ * for the standard one — MD3's own two answers. The transition is opacity only,
158
+ * exactly as on the dialog: a drawer is nothing but text and controls, and a
159
+ * panel that slid would drag its own sentences across the screen for the length
160
+ * of the animation. What says the panel came from an edge is that it is
161
+ * *attached* to one: square against the window, cut on the free side.
162
+ */
163
+ export declare function MPDrawer({ side, mode, open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers, showClose, closeLabel, extent, rounded, dismissible, size, className, style, children }: MPDrawerProps): React.JSX.Element | null;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as l,Fragment as o}from"react/jsx-runtime";import{Dialog as r}from"@base-ui/react/dialog";import{MPIcon as i}from"../icon/MPIcon";import{CloseIcon as t}from"../../constants/icons";import{MPStateLayer as n}from"../../internal/StateLayer";import{hasContent as a,META_TEXT as s,PROSE_TEXT as d,SHEET_GAP as m,SHEET_PAD_X as c,SHEET_PAD_Y as f,SHEET_TITLE as p}from"../../internal/scale";import{FADE as u,PORTAL_LAYER as h,SCRIM as x}from"../../internal/surface";const b={xs:"w-60",sm:"w-72",md:"w-90",lg:"w-104",xl:"w-120"},g={left:"rounded-r-mp-lg",right:"rounded-l-mp-lg",top:"rounded-b-mp-xl",bottom:"rounded-t-mp-xl"},v={left:"border-r",right:"border-l",top:"border-b",bottom:"border-t"},w={left:"flex-row justify-start",right:"flex-row justify-end",top:"flex-col justify-start",bottom:"flex-col justify-end"},y="border-mp-outline-variant border-t";export const MPDrawerClose=r.Close;export function MPDrawer({side:$="left",mode:j="modal",open:N,defaultOpen:C,onOpenChange:k,trigger:z,title:P,description:B,actions:D,dividers:O=!1,showClose:M,closeLabel:L="Close",extent:T,rounded:F=!0,dismissible:I=!0,size:R="md",className:S,style:V,children:q}){const A="modal"===j,E="left"===$||"right"===$,G=M??A,H=c[R],J=f[R],K=O?`${H} ${J}`:H,Q=a(P)||a(B),U=a(D),W=void 0===T?null:{[E?"width":"height"]:"number"==typeof T?`${T}px`:T},X=["mp-drawer relative flex flex-col overflow-hidden box-border","border-mp-outline-variant outline-none",A?"bg-mp-surface-container-low shadow-mp-1":"bg-mp-surface","text-mp-on-surface",d[R],v[$],F?g[$]:"",A?u:"",E?`h-full max-w-full ${void 0===T?b[R]:""}`:"w-full "+(void 0===T?"max-h-[85%]":""),O?"":`${J} ${m[R]}`,S??""].filter(Boolean).join(" "),Y=A?r.Title:"h2",Z=A?r.Description:"p",_=["group text-mp-on-surface-variant relative flex size-10 shrink-0","rounded-mp-full cursor-pointer items-center justify-center","appearance-none border-0 bg-transparent","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),ee=l(o,{children:[Q||G?l("div",{className:`flex shrink-0 items-start gap-3 ${K}`,children:[l("div",{className:"flex min-w-0 flex-1 flex-col",children:[a(P)?e(Y,{className:`m-0 ${p[R]}`,children:P}):null,a(B)?e(Z,{className:`text-mp-on-surface-variant m-0 ${s}`,children:B}):null]}),G?A?l(r.Close,{"aria-label":L,className:_,children:[e(n,{}),e(i,{icon:t,size:20})]}):l("button",{type:"button","aria-label":L,className:_,onClick:()=>k?.(!1),children:[e(n,{}),e(i,{icon:t,size:20})]}):null]}):null,a(q)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",K,O&&(Q||G)?y:"",O?"":"-my-1 py-1"].filter(Boolean).join(" "),children:q}):null,U?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",K,O?y:""].filter(Boolean).join(" "),children:D}):null]});return A?l(r.Root,{open:N,defaultOpen:C,disablePointerDismissal:!I,onOpenChange:(e,l)=>{I||e||"escape-key"!==l.reason?k?.(e):l.cancel()},children:[z?e(r.Trigger,{render:z}):null,l(r.Portal,{children:[e(r.Backdrop,{className:`${h} fixed inset-0 ${u} ${x}`}),e(r.Viewport,{className:`${h} fixed inset-0 flex ${w[$]}`,children:e(r.Popup,{"data-mp-size":R,"data-mp-side":$,"data-mp-mode":j,className:X,style:{...W,...V},children:ee})})]})]}):N??C??1?e("div",{"data-mp-size":R,"data-mp-side":$,"data-mp-mode":j,className:X,style:{...W,...V},children:ee}):null}
@@ -0,0 +1,2 @@
1
+ export { MPDrawer, MPDrawerClose } from './MPDrawer';
2
+ export type { MPDrawerCloseProps, MPDrawerMode, MPDrawerProps } from './MPDrawer';
@@ -0,0 +1 @@
1
+ export{MPDrawer,MPDrawerClose}from"./MPDrawer";
@@ -0,0 +1,64 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { MPSize, MPVariant } from '../../types';
4
+ export interface MPEmptyProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title'> {
5
+ /**
6
+ * The headline. Defaults to `Nothing here`; pass `false` for a state that is a
7
+ * glyph and a sentence with no heading over them.
8
+ */
9
+ title?: React.ReactNode | false;
10
+ /**
11
+ * The glyph above the headline. Defaults to the empty tray; pass `false` to
12
+ * drop it, or a node — an illustration, a brand mark, an icon from any set —
13
+ * to replace it.
14
+ */
15
+ icon?: React.ReactNode | false;
16
+ /**
17
+ * What to do about it, under the text: a "Create the first one" button, a
18
+ * "Clear filters" link. Several of them sit in a row and wrap together.
19
+ */
20
+ action?: React.ReactNode;
21
+ /**
22
+ * How much surface the state paints.
23
+ *
24
+ * `text` is the default here and on nothing else in the library. An empty
25
+ * state is nearly always already inside something — a card's body, a table
26
+ * below its header, a panel — and a second rectangle drawn inside the first is
27
+ * one rectangle too many. The other four are for the case where it is not.
28
+ * @default 'text'
29
+ */
30
+ variant?: MPVariant;
31
+ /**
32
+ * @default 'md'
33
+ */
34
+ size?: MPSize;
35
+ /** Renders something other than a `<div>`: `render={<td colSpan={5} />}`. */
36
+ render?: useRender.RenderProp;
37
+ /** The sentence under the headline: why it is empty, or what to do next. */
38
+ children?: React.ReactNode;
39
+ }
40
+ /**
41
+ * What stands where content would have been: a glyph, a headline, a sentence and
42
+ * a way out.
43
+ *
44
+ * It is the other half of `MPSkeleton`. A skeleton is the shape of something on
45
+ * its way; this is the shape of something that is not coming — a search with no
46
+ * matches, an inbox nobody has written to, a folder before the first file. The
47
+ * two are never both right at once, and a list that shows neither has a blank
48
+ * rectangle where its answer should be.
49
+ *
50
+ * The headline is the only text in the library a component invents at full size,
51
+ * and it is defaulted rather than required for one reason: the version that says
52
+ * nothing useful is the version that gets shipped. `Nothing here` is a floor, and
53
+ * every slot above it — the glyph, the sentence, the action — is there to be
54
+ * filled with what is actually missing.
55
+ *
56
+ * ## No `color`
57
+ *
58
+ * Deliberately absent, where nearly every other component here has one. An empty
59
+ * state in the accent colour is making a claim about content that does not
60
+ * exist; the surface roles it reads are the neutral ones, and the way to say
61
+ * "this is a problem" is a `color="error"` button in `action` — which is the
62
+ * thing that can actually be pressed about it.
63
+ */
64
+ export declare const MPEmpty: React.ForwardRefExoticComponent<MPEmptyProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t,Fragment as r}from"react/jsx-runtime";import*as n from"react";import{useRender as s}from"@base-ui/react/use-render";import{hasContent as a,PROSE_TEXT as l,SHEET_GAP as i,SHEET_PAD_X as o,SHEET_TITLE as m}from"../../internal/scale";import{CONTAINER_SURFACE as c}from"../../internal/surface";const d={xs:"py-5",sm:"py-6",md:"py-8",lg:"py-10",xl:"py-12"},p={xs:"text-[1.5rem]",sm:"text-[1.75rem]",md:"text-[2.25rem]",lg:"text-[2.75rem]",xl:"text-[3.25rem]"};function x(){return t("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",className:"size-[1em]",children:[e("path",{d:"M1.75 9.75h3l.9 1.6h4.7l.9-1.6h3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"m1.75 9.75 2.1-6a1.5 1.5 0 0 1 1.42-1h5.46a1.5 1.5 0 0 1 1.42 1l2.1 6v2a1.5 1.5 0 0 1-1.5 1.5h-9.5a1.5 1.5 0 0 1-1.5-1.5Z",stroke:"currentColor",strokeWidth:"1.5",strokeLinejoin:"round"})]})}export const MPEmpty=n.forwardRef(function({variant:n="text",size:u="md",title:f,icon:h,action:v,render:y,className:N,style:j,children:g,...k},w){const z=void 0===f?"Nothing here":f,$=void 0===h?e(x,{}):h,L=a(z),B=["mp-empty flex w-full flex-col items-center justify-center text-center",o[u],d[u],"text"===n?"":"rounded-mp-md",i[u],c[n],"text-mp-on-surface",N??""].filter(Boolean).join(" ");return s({render:y,ref:w,props:{role:"status","data-mp-size":u,"data-mp-variant":n,className:B,style:j,children:t(r,{children:[a($)?e("span",{className:`text-mp-on-surface-variant flex items-center ${p[u]} [&>svg]:size-[1em]`,children:$}):null,L||a(g)?t("div",{className:`flex max-w-prose flex-col items-center ${i[u]}`,children:[L?e("div",{className:m[u],children:z}):null,a(g)?e("div",{className:`${l[u]} ${L?"text-mp-on-surface-variant":""}`,children:g}):null]}):null,a(v)?e("div",{className:"flex flex-wrap items-center justify-center gap-2",children:v}):null]}),...k}})});
@@ -0,0 +1,2 @@
1
+ export { MPEmpty } from './MPEmpty';
2
+ export type { MPEmptyProps } from './MPEmpty';
@@ -0,0 +1 @@
1
+ export{MPEmpty}from"./MPEmpty";
@@ -0,0 +1,103 @@
1
+ import * as React from 'react';
2
+ import type { MPStyleProps } from '../../types';
3
+ /** Why a file was turned away. One reason per file, in the order they are checked. */
4
+ export type MPFileRejectionReason = 'type' | 'size' | 'count';
5
+ export interface MPFileRejection {
6
+ file: File;
7
+ reason: MPFileRejectionReason;
8
+ }
9
+ /**
10
+ * `1.4 MB`, in the units the reader's own file browser uses.
11
+ *
12
+ * Base 1000 and `MB` rather than base 1024 and `MiB`: it is the number every
13
+ * desktop file manager shows, and a picker that disagrees with the Finder about
14
+ * how big a file is has picked a fight it cannot win.
15
+ *
16
+ * Exported because a caller writing their own `hint` — "up to 5 MB" — needs the
17
+ * same spelling the list underneath will use, and two spellings of one number in
18
+ * one component is the version of this that looks like a bug.
19
+ */
20
+ export declare function formatFileSize(bytes: number): string;
21
+ export interface MPFilePickerProps extends MPStyleProps {
22
+ /**
23
+ * Which files the browser's own dialog offers, in the `accept` grammar —
24
+ * `'image/*,.pdf'`. Dropped files are checked against it too, which the
25
+ * attribute alone does not do.
26
+ */
27
+ accept?: string;
28
+ /** Whether more than one file may be chosen. @default false */
29
+ multiple?: boolean;
30
+ /** The largest a single file may be, in bytes. */
31
+ maxSize?: number;
32
+ /**
33
+ * How many files may be held at once. Checked against what is already chosen
34
+ * rather than against one drop, which is the difference between "you may drop
35
+ * five files" and "you may end up with five files" — only the second is what
36
+ * this means.
37
+ */
38
+ maxFiles?: number;
39
+ /** The chosen files. Use with `onFilesChange` for a controlled picker. */
40
+ value?: readonly File[];
41
+ /** The files chosen at the start, for an uncontrolled picker. */
42
+ defaultValue?: readonly File[];
43
+ onFilesChange?: (files: File[]) => void;
44
+ /**
45
+ * Called with everything that was turned away, and why. Without it a rejected
46
+ * file disappears in silence, which is the single worst thing a dropzone does.
47
+ */
48
+ onReject?: (rejections: MPFileRejection[]) => void;
49
+ /** Label above the box. */
50
+ label?: React.ReactNode;
51
+ /** The line under the box. Replaced by `errorMessage` when there is one. */
52
+ description?: React.ReactNode;
53
+ /** The message under the box, which also turns the picker over. */
54
+ errorMessage?: React.ReactNode;
55
+ /** The line inside the box. @default 'Drop files here, or click to browse' */
56
+ title?: React.ReactNode;
57
+ /** The line under it — what is accepted, how big, how many. */
58
+ hint?: React.ReactNode;
59
+ /** The glyph above the title. Pass `null` for a box with no picture in it. */
60
+ icon?: React.ReactNode;
61
+ /** Lists the chosen files under the box, each with a way to remove it. @default true */
62
+ showList?: boolean;
63
+ /** The accessible name of a file's remove button. Receives the file's name. */
64
+ removeLabel?: (name: string) => string;
65
+ /** Marks the field required. */
66
+ required?: boolean;
67
+ /** Greys the picker out and stops it taking files. */
68
+ disabled?: boolean;
69
+ /** Shows what was chosen without allowing it to be added to or removed from. */
70
+ readOnly?: boolean;
71
+ /** Name of the form control. */
72
+ name?: string;
73
+ /** The id put on the browse button. */
74
+ id?: string;
75
+ }
76
+ /**
77
+ * A box you drop files on, or click to open the file dialog.
78
+ *
79
+ * There is no Material component for this and no Base UI primitive under it, and
80
+ * both absences are fine: a dropzone is a `<div>` listening for four drag events
81
+ * plus an `<input type="file">` it clicks for you. There is no popup to position,
82
+ * no focus to trap, no roving anything. What it borrows from Material is the part
83
+ * that is a *surface* — the corner size, the `outline-variant` edge, the state
84
+ * layers, the supporting text — so it sits in a form with the rest of these
85
+ * components rather than beside them.
86
+ *
87
+ * The edge is dashed, which is the one place this library draws a line that is
88
+ * not solid. It is not decoration: a dashed rectangle is the established sign for
89
+ * "this area takes a drop", and a dropzone that looks like a card is a card
90
+ * nobody tries to drop on.
91
+ *
92
+ * ## The two things a hand-rolled dropzone gets wrong
93
+ *
94
+ * **The drag counter.** `dragenter` and `dragleave` both fire as the pointer
95
+ * crosses a *child* of the zone, so a zone that toggles a boolean flickers the
96
+ * entire time a file is being dragged across its own contents. Counting the
97
+ * events instead is the only version that survives having anything inside the
98
+ * box.
99
+ *
100
+ * **`accept`.** The browser enforces it on its own dialog and never on a drop.
101
+ * See `matchesAccept` above.
102
+ */
103
+ export declare const MPFilePicker: React.ForwardRefExoticComponent<MPFilePickerProps & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as n from"react";import{MPIcon as t}from"../icon/MPIcon";import{CloseIcon as a,UploadIcon as i}from"../../constants/icons";import{MPStateLayer as o}from"../../internal/StateLayer";import{CONTROL_ICON as l,META_TEXT as s,PROSE_TEXT as c,STACK_GAP as p,hasContent as u}from"../../internal/scale";const m={xs:"p-4",sm:"p-5",md:"p-6",lg:"p-8",xl:"p-10"};export function formatFileSize(e){if(e<1e3)return`${e} B`;const r=["kB","MB","GB","TB"];let n=e/1e3,t=0;for(;n>=1e3&&t<r.length-1;)n/=1e3,t+=1;return`${n<10?n.toFixed(1):Math.round(n)} ${r[t]}`}function d(e,r){const n=e.name.toLowerCase(),t=e.type.toLowerCase();return r.split(",").map(e=>e.trim().toLowerCase()).filter(Boolean).some(e=>e.startsWith(".")?n.endsWith(e):e.endsWith("/*")?t.startsWith(e.slice(0,-1)):t===e)}export const MPFilePicker=n.forwardRef(function({accept:f,multiple:h=!1,maxSize:x,maxFiles:b,value:v,defaultValue:g,onFilesChange:y,onReject:j,label:N,description:k,errorMessage:w,title:z,hint:C,icon:I,showList:B=!0,removeLabel:D=e=>`Remove ${e}`,size:$="md",fullWidth:F=!0,required:L=!1,disabled:M=!1,readOnly:S=!1,name:R,id:T},W){const _=n.useRef(null);n.useImperativeHandle(W,()=>_.current);const[P,E]=n.useState(()=>[...g??[]]),O=v?[...v]:P,q=n.useRef(0),[A,V]=n.useState(!1),G=u(w),H=M||S,Y=n.useId(),J=n.useCallback(e=>{v||E(e),y?.(e)},[y,v]),K=n.useCallback(e=>{const r=[],n=[],t=h?b??Number.POSITIVE_INFINITY:1,a=h?O.length:0;for(const i of e)f&&!d(i,f)?n.push({file:i,reason:"type"}):void 0!==x&&i.size>x?n.push({file:i,reason:"size"}):a+r.length>=t?n.push({file:i,reason:"count"}):r.push(i);return{kept:r,rejections:n}},[f,O.length,b,x,h]),Q=n.useCallback(e=>{const{kept:r,rejections:n}=K(e);n.length>0&&j?.(n),r.length>0&&J(h?[...O,...r]:r)},[K,J,O,h,j]);return r("div",{className:["mp-file-picker flex-col align-top",p[$],F?"flex w-full":"inline-flex"].join(" "),"data-mp-size":$,"data-disabled":M||void 0,"data-invalid":G||void 0,children:[u(N)?r("span",{className:[s,M?"text-mp-on-surface/38":G?"text-mp-error":"text-mp-on-surface-variant"].join(" "),children:[N,L?e("span",{"aria-hidden":"true",children:" *"}):null]}):null,r("div",{className:"flex w-full flex-col",onDragEnter:e=>{H||(e.preventDefault(),q.current+=1,V(!0))},onDragOver:e=>{H||(e.preventDefault(),e.dataTransfer.dropEffect="copy")},onDragLeave:()=>{H||(q.current=Math.max(0,q.current-1),0===q.current&&V(!1))},onDrop:e=>{H||(e.preventDefault(),q.current=0,V(!1),Q(Array.from(e.dataTransfer.files)))},children:[r("button",{type:"button",id:T,disabled:M,"aria-describedby":u(k)||G?Y:void 0,"aria-invalid":G||void 0,className:["mp-file-picker__zone group relative flex w-full flex-col items-center","justify-center gap-2 text-center","rounded-mp-md box-border border-2 border-dashed","appearance-none bg-transparent font-[inherit] outline-none","transition-[border-color,background-color] duration-(--mp-sys-motion-duration-short4)",m[$],c[$],M?"border-mp-on-surface/12 text-mp-on-surface/38 cursor-default":[S?"cursor-default":"cursor-pointer",G?"border-mp-error":"border-mp-outline-variant","text-mp-on-surface",A?"border-mp-primary bg-mp-primary/8":""].filter(Boolean).join(" ")].filter(Boolean).join(" "),onClick:()=>{!H&&_.current&&(_.current.value="",_.current.click())},children:[H?null:e(o,{layer:"inset-0 rounded-[inherit] bg-mp-primary"}),void 0===I?e(t,{icon:i,size:1.6*l[$],className:M?"":"text-mp-primary"}):u(I)?e("span",{className:M?"":"text-mp-primary",children:I}):null,e("span",{className:"font-medium",children:z??"Drop files here, or click to browse"}),u(C)?e("span",{className:[s,M?"text-mp-on-surface/38":"text-mp-on-surface-variant"].join(" "),children:C}):null]}),e("input",{ref:_,type:"file",name:R,accept:f,multiple:h,required:L&&0===O.length,disabled:H,tabIndex:-1,"aria-hidden":"true",className:"absolute size-px overflow-hidden opacity-0 [clip-path:inset(50%)]",onChange:e=>Q(Array.from(e.target.files??[]))})]}),B&&O.length>0?e("ul",{className:["mp-file-picker__list m-0 flex w-full list-none flex-col p-0",p[$]].join(" "),children:O.map((n,i)=>r("li",{className:["rounded-mp-xs bg-mp-surface-container-low flex w-full items-center gap-3","px-3 py-2",c[$],M?"text-mp-on-surface/38":"text-mp-on-surface"].join(" "),children:[e("span",{className:"min-w-0 flex-1 truncate",children:n.name}),e("span",{className:[s,"shrink-0 tabular-nums",M?"text-mp-on-surface/38":"text-mp-on-surface-variant"].join(" "),children:formatFileSize(n.size)}),H?null:r("button",{type:"button","aria-label":D(n.name),className:["group text-mp-on-surface-variant relative flex size-8 shrink-0","cursor-pointer appearance-none items-center justify-center rounded-full","bg-transparent p-0 font-[inherit] outline-none"].join(" "),onClick:()=>J(O.filter((e,r)=>r!==i)),children:[e(o,{}),e(t,{icon:a,size:18})]})]},`${n.name}-${n.size}-${n.lastModified}-${i}`))}):null,G?e("span",{id:Y,className:[s,"text-mp-error"].join(" "),children:w}):u(k)?e("span",{id:Y,className:[s,M?"text-mp-on-surface/38":"text-mp-on-surface-variant"].join(" "),children:k}):null]})});
@@ -0,0 +1,2 @@
1
+ export { MPFilePicker, formatFileSize } from './MPFilePicker';
2
+ export type { MPFilePickerProps, MPFileRejection, MPFileRejectionReason } from './MPFilePicker';
@@ -0,0 +1 @@
1
+ export{MPFilePicker,formatFileSize}from"./MPFilePicker";