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,110 @@
1
+ import * as React from 'react';
2
+ import type { MPPickerLabels } from './Calendar';
3
+ import type { MPColor, MPSize, MPStyleProps } from '../types';
4
+ /**
5
+ * The props a picker takes from its shell rather than inventing.
6
+ *
7
+ * Written out here rather than left to `MPStyleProps` alone because these are
8
+ * the rows a reader of the docs is actually looking at — every one of the four
9
+ * pickers lists them, and they mean the same thing on all four.
10
+ */
11
+ export interface MPPickerShellProps extends MPStyleProps {
12
+ /**
13
+ * Which accent family the popup reads: the chosen day's fill, the band across
14
+ * a range, today's outline, the footer's confirm button.
15
+ * @default 'primary'
16
+ */
17
+ color?: MPColor;
18
+ /**
19
+ * Label in the outline's notch. Always drawn there rather than floating over
20
+ * the value, so a picker with a label and one without sit at the same height
21
+ * in a form.
22
+ */
23
+ label?: React.ReactNode;
24
+ /** The line under the control. Replaced by `errorMessage` when there is one. */
25
+ description?: React.ReactNode;
26
+ /**
27
+ * The message under the control. Its presence is also what puts the picker
28
+ * into its error state — there is no separate `error` boolean, so there is no
29
+ * way to render a control that is visibly wrong with no explanation of why.
30
+ */
31
+ errorMessage?: React.ReactNode;
32
+ /** Content placed before the value. Defaults to the picker's own glyph. */
33
+ startIcon?: React.ReactNode;
34
+ /** Marks the picker required, both to assistive technology and to the label. */
35
+ required?: boolean;
36
+ /** Greys the picker out and stops it opening. */
37
+ disabled?: boolean;
38
+ /**
39
+ * Shows the value without allowing it to be changed, and stays focusable.
40
+ *
41
+ * The popup does not open either. What a read-only picker holds is something
42
+ * to read, and a calendar whose every cell was inert would be a menu of
43
+ * nothing.
44
+ */
45
+ readOnly?: boolean;
46
+ /**
47
+ * The id put on the trigger and pointed at by the label. Derived from `name`
48
+ * when omitted, and generated when there is no name either.
49
+ */
50
+ id?: string;
51
+ className?: string;
52
+ style?: React.CSSProperties;
53
+ }
54
+ interface InternalShellProps extends MPPickerShellProps {
55
+ /** Which component this is, for the class hook and the generated id. */
56
+ slug: string;
57
+ /** What the trigger reads. A placeholder when `empty`. */
58
+ display: React.ReactNode;
59
+ /**
60
+ * Every string the display could hold, so the trigger stops changing width
61
+ * with its value. `displaySamples` in `internal/date` produces them and
62
+ * `MPWidthSizer` is what lays them out.
63
+ */
64
+ samples?: string[];
65
+ /** Nothing has been chosen yet, so the display is muted. */
66
+ empty: boolean;
67
+ /** Offers the × that empties the control. */
68
+ clearable?: boolean;
69
+ onClear: () => void;
70
+ open: boolean;
71
+ onOpenChange: (open: boolean) => void;
72
+ labels: MPPickerLabels;
73
+ /** `<input type="hidden">` rows, so the control submits with a form. */
74
+ hiddenValues?: Array<{
75
+ name: string;
76
+ value: string;
77
+ }>;
78
+ name?: string;
79
+ children: React.ReactNode;
80
+ triggerRef?: React.Ref<HTMLButtonElement>;
81
+ }
82
+ /**
83
+ * A trigger, a label, the line of text under it, and a popup.
84
+ *
85
+ * Everything about it that is visible is a decision already made elsewhere: the
86
+ * notched outline, the label in the notch, the supporting text, the disabled
87
+ * treatment, and the popup's `surface-container` at elevation 2 — which is the
88
+ * same floating sheet a menu and a select's list are drawn on.
89
+ */
90
+ export declare function MPPickerShell({ slug, size, color, fullWidth, label, description, errorMessage, startIcon, required, disabled, readOnly, id, className, style, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, name, children, triggerRef }: InternalShellProps): React.JSX.Element;
91
+ /**
92
+ * The row of shortcuts under a picker's panel.
93
+ *
94
+ * A hairline above it rather than a gap, because the actions act on the panel
95
+ * and a gap would read as a second popup stacked under the first.
96
+ */
97
+ export declare function MPPickerFooter({ children }: {
98
+ children: React.ReactNode;
99
+ }): React.JSX.Element;
100
+ /** The vertical hairline between a calendar and the clock beside it. */
101
+ export declare function MPPickerDivider(): React.JSX.Element;
102
+ /**
103
+ * What a picker's footer buttons are drawn at.
104
+ *
105
+ * The same rung the calendar's header uses, for the same reason: a `md` picker's
106
+ * footer sitting at the control ladder's 56px would be taller than two rows of
107
+ * the calendar above it.
108
+ */
109
+ export declare const FOOTER_SIZE: Record<MPSize, MPSize>;
110
+ export {};
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as i from"react";import{Field as t}from"@base-ui/react/field";import{Popover as n}from"@base-ui/react/popover";import{MPIcon as a}from"../components/icon/MPIcon";import{CloseIcon as o}from"../constants/icons";import{accentSlots as l}from"./accent";import{MPFieldLabel as s,MPFieldOutline as p}from"./FieldOutline";import{MPStateLayer as c}from"./StateLayer";import{MPSupportingText as m}from"./SupportingText";import{MPWidthSizer as d}from"./WidthSizer";import{CONTROL_ICON as u,hasContent as f,PROSE_TEXT as h}from"./scale";import{FADE as x,PORTAL_LAYER as g}from"./surface";const b={xs:{padding:"px-2",height:"h-8"},sm:{padding:"px-3",height:"h-10"},md:{padding:"px-4",height:"h-14"},lg:{padding:"px-4",height:"h-16"},xl:{padding:"px-5",height:"h-18"}},v={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function MPPickerShell({slug:y,size:N="md",color:j="primary",fullWidth:P=!1,label:w,description:O,errorMessage:z,startIcon:M,required:k=!1,disabled:F=!1,readOnly:S=!1,id:B,className:C,style:I,display:R,samples:$,empty:q,clearable:T=!1,onClear:_,open:E,onOpenChange:W,labels:D,hiddenValues:L,name:V,children:Z,triggerRef:A}){const G=f(z),H=b[N],J=i.useId(),K=B??`mp-${y}-${V??J}`,Q=T&&!q&&!(F||S);return r(t.Root,{disabled:F,invalid:G,"data-mp-size":N,className:[`mp-${y} group flex-col align-top`,P?"flex w-full":"inline-flex w-fit",C??""].filter(Boolean).join(" "),style:{...l(j),...I},children:[r(n.Root,{open:E,onOpenChange:W,children:[r("div",{className:"relative w-full",children:[r(n.Trigger,{id:K,ref:A,disabled:F,nativeButton:!0,className:["relative flex w-full items-center gap-2 select-none","appearance-none bg-transparent font-[inherit] outline-none",H.padding,Q?"pe-10":"",H.height,h[N],F?"text-mp-on-surface/38 cursor-default":"text-mp-on-surface "+(S?"cursor-default":"cursor-pointer")].filter(Boolean).join(" "),children:[M?e("span",{className:["flex shrink-0 items-center",F?"text-mp-on-surface/38":"text-mp-on-surface-variant"].join(" "),children:M}):null,r("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:["w-full truncate text-start",q&&!F?"text-mp-on-surface-variant":""].filter(Boolean).join(" "),children:R}),e(d,{samples:$??[]})]})]}),Q?r("button",{type:"button","aria-label":D.clear,onClick:_,className:["group/clear rounded-mp-full text-mp-on-surface-variant absolute inset-y-0","end-1 my-auto flex size-8 cursor-pointer items-center justify-center","appearance-none border-0 bg-transparent font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "),children:[e(c,{className:"group-hover/clear:opacity-8 group-focus-visible/clear:opacity-10"}),e(a,{icon:o,size:u[N]})]}):null,e(p,{label:w,required:k}),f(w)?e(s,{size:N,label:w,required:k,htmlFor:K}):null]}),e(n.Portal,{children:e(n.Positioner,{className:g,sideOffset:4,align:"start",children:e(n.Popup,{initialFocus:!1,className:[`mp-${y}__popup rounded-mp-md shadow-mp-2 bg-mp-surface-container`,"text-mp-on-surface outline-none",v[N],h[N],x].join(" "),children:Z})})})]}),e(m,{description:O,errorMessage:z,className:H.padding}),L?.map((r,i)=>e("input",{type:"hidden",name:r.name,value:r.value},i))]})}export function MPPickerFooter({children:r}){return e("div",{className:"border-mp-outline-variant flex items-center justify-end gap-1 border-t pt-1.5",children:r})}export function MPPickerDivider(){return e("div",{"aria-hidden":"true",className:"bg-mp-outline-variant w-px self-stretch"})}export const FOOTER_SIZE={xs:"xs",sm:"xs",md:"sm",lg:"sm",xl:"md"};
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Material's state layer.
4
+ *
5
+ * MD3 does not express hover, focus and press as three more colours. It puts a
6
+ * translucent wash of the *content* colour over the container — 8% hovered, 10%
7
+ * focused or pressed — so one rule covers a filled button, an outlined one and a
8
+ * bare text one without any of them naming a second background.
9
+ *
10
+ * That is the whole reason this is an element rather than a `hover:bg-…` on the
11
+ * control itself. A background can only be replaced, and replacing it is what
12
+ * makes a text button's hover state opaque and an outlined button's hover state
13
+ * cover its own border. A layer composites instead, so whatever was underneath —
14
+ * a fill, a hairline, nothing at all — is still there under the wash.
15
+ *
16
+ * `bg-current` is what makes it one rule: the layer takes the colour of the
17
+ * label it sits behind, which is already the right ink for the surface. A caller
18
+ * that needs a different one sets `text-…` on the layer.
19
+ *
20
+ * ## How it is wired
21
+ *
22
+ * The control carries `group` and `relative`; this carries `group-hover:` and
23
+ * friends. It cannot key off its own `:hover` because it covers the control and
24
+ * has to be `pointer-events-none` for clicks to reach it — and an element that
25
+ * takes no pointer events is never hovered.
26
+ *
27
+ * `rounded-[inherit]` rather than a radius of its own: the layer is the control's
28
+ * shape, and a pill with a square wash in it is worse than no wash.
29
+ *
30
+ * ## `layer` replaces the appearance rather than adding to it
31
+ *
32
+ * The shape and the colour arrive as one string because a tick's layer is
33
+ * neither. MD3 draws it as a 40dp circle *around* an 18dp box, in `on-surface`
34
+ * rather than in the ink — which for a ticked checkbox is white, and a white
35
+ * halo is not a state. Appending those classes to the defaults would leave two
36
+ * `background-color` declarations of equal specificity fighting, and which one
37
+ * wins is decided by their order in the generated stylesheet. So the caller
38
+ * replaces the set rather than adding to it, and only the opacity ladder — the
39
+ * part that is genuinely the same everywhere — is fixed here.
40
+ */
41
+ export declare function MPStateLayer({ layer, className }: {
42
+ /** Shape, position and colour. Replaces the defaults; it does not extend them. */
43
+ layer?: string;
44
+ className?: string;
45
+ }): React.JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as o}from"react/jsx-runtime";export function MPStateLayer({layer:t="inset-0 rounded-[inherit] bg-current",className:a}){return o("span",{"aria-hidden":"true",className:["pointer-events-none absolute opacity-0",t,"transition-opacity duration-(--mp-sys-motion-duration-short4)","group-hover:opacity-8","group-active:opacity-10","group-focus-visible:opacity-10","group-disabled:opacity-0 group-data-disabled:opacity-0",a??""].filter(Boolean).join(" ")})}
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * The line under a control.
4
+ *
5
+ * Material calls it supporting text and gives it one slot, not two — which is
6
+ * why this renders *either* the description or the error rather than stacking
7
+ * them. An error is not additional information about a field, it is the field's
8
+ * current problem, and pushing the description down a line to make room leaves
9
+ * the reader reading a sentence that has just stopped applying.
10
+ *
11
+ * Both parts come from Base UI's `Field`, so whichever one is showing is wired
12
+ * to the control by `aria-describedby` without anybody generating an id.
13
+ * `Field.Error` needs `match` because it normally waits for the browser's own
14
+ * validity state; here the message's presence *is* the state, which is the same
15
+ * bargain `MPTextField.errorMessage` makes — there is no way to render a control
16
+ * that is visibly wrong with no explanation of why.
17
+ */
18
+ export declare function MPSupportingText({ description, errorMessage, className }: {
19
+ description?: React.ReactNode;
20
+ errorMessage?: React.ReactNode;
21
+ /** Whatever inset lines the text up with the control it belongs to. */
22
+ className?: string;
23
+ }): React.JSX.Element | null;
@@ -0,0 +1 @@
1
+ import{jsx as r}from"react/jsx-runtime";import{Field as e}from"@base-ui/react/field";import{META_TEXT as t,hasContent as o}from"./scale";export function MPSupportingText({description:a,errorMessage:s,className:i}){const n=["mp-supporting-text block",t,"data-disabled:text-mp-on-surface/38",i??""].filter(Boolean).join(" ");return o(s)?r(e.Error,{match:!0,className:`${n} text-mp-error`,children:s}):o(a)?r(e.Description,{className:`${n} text-mp-on-surface-variant`,children:a}):null}
@@ -0,0 +1,31 @@
1
+ import type * as React from 'react';
2
+ /**
3
+ * Holds a control open at the width of the widest thing it could ever say.
4
+ *
5
+ * A control that is not `fullWidth` is sized by what it is *currently* saying,
6
+ * which for anything whose value changes means the box changes with it. A date
7
+ * picker on the 1st is a dozen pixels narrower than the same picker on the 28th,
8
+ * and `Sep` is wider than `May`. Either way the field moves under the pointer
9
+ * that just used it, and the whole row of controls beside it shuffles along.
10
+ *
11
+ * So the alternatives are laid out too, stacked in a box clipped to no height.
12
+ * The control's intrinsic width becomes the widest of them and stops depending
13
+ * on the value.
14
+ *
15
+ * Three things it deliberately is not:
16
+ *
17
+ * - **Not `hidden`, and not `display: none`.** Both take the box out of layout,
18
+ * and a box that is not laid out reserves nothing.
19
+ * - **Not read out.** `aria-hidden`, or a screen reader would announce every
20
+ * date the control might hold before the one it does.
21
+ * - **Not text.** A sample is drawn as generated content off a data attribute
22
+ * rather than as a text node. `content: attr(…)` lays out exactly like text,
23
+ * so it reserves the same width — but it leaves nothing for `getByText` or a
24
+ * browser's find-in-page to trip over, so a caller's test asking for the date
25
+ * they chose keeps finding one element rather than two.
26
+ */
27
+ export declare function MPWidthSizer({ samples }: {
28
+ samples: readonly string[];
29
+ }): React.JSX.Element | null;
30
+ /** The props a component hands over when it wants one of these. */
31
+ export type MPWidthSizerProps = React.ComponentProps<typeof MPWidthSizer>;
@@ -0,0 +1 @@
1
+ import{jsx as e}from"react/jsx-runtime";export function MPWidthSizer({samples:a}){return 0===a.length?null:e("span",{"aria-hidden":"true",className:"invisible h-0 min-h-0 overflow-hidden",children:a.map((a,n)=>e("span",{"data-sample":a,className:"block whitespace-nowrap before:content-[attr(data-sample)]"},`${n}:${a}`))})}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The `color` prop, made available to a stylesheet.
3
+ *
4
+ * `color="tertiary"` has to reach a `background-color`, and there is no way for
5
+ * it to do that through a class name: Tailwind finds classes by scanning source
6
+ * text, so `bg-mp-${color}` generates nothing at all. The alternative — a table
7
+ * of every variant crossed with every colour, written out — is twenty literal
8
+ * strings per component that all say the same thing.
9
+ *
10
+ * So the family is a *value* rather than a name. Four custom properties are set
11
+ * on the component's root and the classes read those, which means one set of
12
+ * classes covers all four families and the ladder of roles inside each of them
13
+ * stays intact: `filled` is always the accent under its own ink, whichever accent
14
+ * that turns out to be.
15
+ *
16
+ * The names are `--_mp-*` because they are private, in the same sense the derived
17
+ * colours in `styles.css` are: read by components, not a name to set. What a
18
+ * consumer sets is the *role* — `--mp-sys-color-tertiary` — and it arrives here
19
+ * on its own, because these are indirections through the role rather than copies
20
+ * of its value.
21
+ *
22
+ * ## Why an inline style rather than a class
23
+ *
24
+ * A custom property's `var()` references are substituted at the element the
25
+ * property is declared on. Declaring these on the component's own root is what
26
+ * makes the substitution happen *there* — so a family set on a wrapper, or a
27
+ * source colour scoped to a section, is what the component resolves against.
28
+ */
29
+ import type * as React from 'react';
30
+ import type { MPColor } from '../types';
31
+ /**
32
+ * The four roles an accent family has, pointed at one of the four families.
33
+ *
34
+ * `error` is a family like any other here. That is deliberate: a destructive
35
+ * button and a primary one differ only in which palette they read, and a
36
+ * component that special-cased the error colour would need a second code path
37
+ * for the one case that most needs to look like all the others.
38
+ */
39
+ export declare function accentSlots(color: MPColor): React.CSSProperties;
@@ -0,0 +1 @@
1
+ export function accentSlots(n){return{"--_mp-accent":`var(--_mp-color-${n})`,"--_mp-on-accent":`var(--_mp-color-on-${n})`,"--_mp-accent-container":`var(--_mp-color-${n}-container)`,"--_mp-on-accent-container":`var(--_mp-color-on-${n}-container)`}}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * What a button inherits from the group around it.
3
+ *
4
+ * Its own module rather than a file `MPButtonGroup` exports, because both sides
5
+ * import it: the group provides the context and the button reads it. Putting it
6
+ * in either component would make one of them import the other, and a `<Button>`
7
+ * that pulls in a `<ButtonGroup>` nobody used is dead weight in every bundle.
8
+ *
9
+ * Every field is optional and every one of them may legitimately be `undefined`.
10
+ * A button reads the group as a *fallback*, so "not set on the group" has to keep
11
+ * meaning "use the button's own default" rather than turning into one.
12
+ */
13
+ import * as React from 'react';
14
+ import type { MPColor, MPSize, MPVariant } from '../types';
15
+ export interface MPButtonGroupContextValue {
16
+ variant?: MPVariant;
17
+ size?: MPSize;
18
+ color?: MPColor;
19
+ disabled?: boolean;
20
+ }
21
+ export declare const MPButtonGroupContext: React.Context<MPButtonGroupContextValue | null>;
@@ -0,0 +1 @@
1
+ import*as t from"react";export const MPButtonGroupContext=t.createContext(null);
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Colour arithmetic, written out rather than installed.
3
+ *
4
+ * `MPColorPicker` is the only component in the library that has to *compute* a
5
+ * colour rather than name one, and the whole of what it needs is here: three
6
+ * representations, the conversions between them, one parser and one formatter.
7
+ * It is a hundred lines of arithmetic, which is the entire reason the package
8
+ * still has one runtime dependency.
9
+ *
10
+ * Two decisions worth knowing before reading:
11
+ *
12
+ * - **HSV is the model the panel is drawn in, and it never leaves.** A
13
+ * saturation/value square with a hue rail beside it *is* HSV, so the picker
14
+ * keeps its state that way and converts on the way out. Round-tripping through
15
+ * RGB instead would lose the hue of every greyscale colour — black is `#000` at
16
+ * every hue — and the rail would jump to red the moment the pointer reached a
17
+ * corner.
18
+ * - **`alpha` is 0–1, everything else is what CSS says it is.** `h` is degrees,
19
+ * `s`/`v`/`l` are percentages, `r`/`g`/`b` are 0–255. Nothing here invents a
20
+ * normalised unit, because every one of these numbers is eventually written
21
+ * into a string a human reads.
22
+ *
23
+ * ## Why this is not OKLCh, when the token sheet is
24
+ *
25
+ * `styles.css` derives the scheme in OKLCh because it is generating *related*
26
+ * colours, and a perceptual space is what makes "the same lightness" mean the
27
+ * same thing across hues. A picker is not generating anything. It is showing a
28
+ * reader a square and asking them to point at a colour, and the square every
29
+ * design tool draws — saturation across, brightness down — is HSV. Drawing it in
30
+ * a perceptual space would give a square with unreachable corners.
31
+ *
32
+ * Nothing here is exported from `src/index.ts`. It is the library talking to
33
+ * itself, in the sense `internal/` always means.
34
+ */
35
+ /** 0–255 per channel, the way a hex triplet and `rgb()` both spell it. */
36
+ export interface MPRgb {
37
+ r: number;
38
+ g: number;
39
+ b: number;
40
+ }
41
+ /** `h` in degrees, `s` and `v` as percentages. The panel's own model. */
42
+ export interface MPHsv {
43
+ h: number;
44
+ s: number;
45
+ v: number;
46
+ }
47
+ /** `h` in degrees, `s` and `l` as percentages. Only ever an output format. */
48
+ export interface MPHsl {
49
+ h: number;
50
+ s: number;
51
+ l: number;
52
+ }
53
+ /** A colour and how much of it there is. `alpha` is 0–1. */
54
+ export interface MPColorValue {
55
+ hsv: MPHsv;
56
+ alpha: number;
57
+ }
58
+ /** The three ways the picker will write a colour back out. */
59
+ export type MPColorFormat = 'hex' | 'rgb' | 'hsl';
60
+ export declare function clamp(value: number, min: number, max: number): number;
61
+ export declare function hsvToRgb({ h, s, v }: MPHsv): MPRgb;
62
+ export declare function rgbToHsv({ r, g, b }: MPRgb): MPHsv;
63
+ export declare function rgbToHsl({ r, g, b }: MPRgb): MPHsl;
64
+ export declare function hslToRgb({ h, s, l }: MPHsl): MPRgb;
65
+ /**
66
+ * A CSS colour string, or `null` if it is not one this understands.
67
+ *
68
+ * Hex in all four lengths, `rgb()`/`rgba()` and `hsl()`/`hsla()` in both the
69
+ * comma and the space syntax. Named colours and `color()` are deliberately out:
70
+ * a picker has to be able to write every value it can read, and there is no
71
+ * honest way back from `rebeccapurple` to a point on the panel.
72
+ */
73
+ export declare function parseColor(input: string): MPColorValue | null;
74
+ export declare function rgbToHex({ r, g, b }: MPRgb, alpha?: number): string;
75
+ /**
76
+ * The value the component hands back, in whichever notation was asked for.
77
+ *
78
+ * `hex` drops the alpha pair when the colour is opaque, and the two functional
79
+ * forms drop the fourth argument for the same reason — a caller who never turned
80
+ * `alpha` on should never see `rgba(…, 1)` come out of a control they only used
81
+ * three channels of.
82
+ */
83
+ export declare function formatColor(hsv: MPHsv, alpha: number, format: MPColorFormat): string;
84
+ /** A plain `rgb()` for the swatches and rails, where alpha is drawn separately. */
85
+ export declare function cssColor(hsv: MPHsv, alpha?: number): string;
86
+ /**
87
+ * Black or white, whichever can be read on top of this colour.
88
+ *
89
+ * The tick on a chosen swatch is the only thing the picker draws *on* an
90
+ * arbitrary colour, and a fixed white tick disappears on yellow. The threshold
91
+ * is relative luminance rather than plain lightness, because the eye weighs green
92
+ * about six times as heavily as blue and a colour model that pretends otherwise
93
+ * puts the tick the wrong way round on both.
94
+ */
95
+ export declare function readableInk(hsv: MPHsv): string;
96
+ /**
97
+ * The swatches a picker shows when it was given none.
98
+ *
99
+ * Deliberately not the library's own four accent families: those are *roles* —
100
+ * `primary` means "the most important thing on this screen" — and a picker is
101
+ * being asked for a colour, not for a meaning. Offering the scheme here would
102
+ * also be offering four colours that change under the reader when somebody edits
103
+ * `--mp-source-color`, which is not what a tag colour should do.
104
+ *
105
+ * So this is a plain spectrum plus the greys: the row somebody reaches for when
106
+ * they are labelling a calendar, a tag or a project, which is what a colour
107
+ * picker in an application is nearly always for.
108
+ */
109
+ export declare const DEFAULT_SWATCHES: readonly string[];
110
+ /**
111
+ * The chequerboard behind a translucent colour, as a background shorthand.
112
+ *
113
+ * Two conic gradients would be one declaration fewer, but a chequer drawn with
114
+ * conic gradients has a seam down the middle of every tile at a fractional device
115
+ * pixel ratio. Four linear stops at 45° do not.
116
+ *
117
+ * It reads `--mp-sys-color-outline-variant`'s computed value through the same
118
+ * `--_mp-*` indirection everything else does, so the chequer follows the scheme
119
+ * rather than being a fixed grey that vanishes in dark mode.
120
+ */
121
+ export declare const CHECKER_BACKGROUND: {
122
+ readonly backgroundImage: "linear-gradient(45deg, var(--_mp-color-outline-variant) 25%, transparent 25%), linear-gradient(-45deg, var(--_mp-color-outline-variant) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--_mp-color-outline-variant) 75%), linear-gradient(-45deg, transparent 75%, var(--_mp-color-outline-variant) 75%)";
123
+ readonly backgroundSize: "8px 8px";
124
+ readonly backgroundPosition: "0 0, 0 4px, 4px -4px, -4px 0";
125
+ };
@@ -0,0 +1 @@
1
+ export function clamp(r,t,n){return r<t?t:r>n?n:r}function r(r){const t=r%360;return t<0?t+360:t}export function hsvToRgb({h:t,s:n,v:o}){const e=r(t)/60,a=clamp(n,0,100)/100,s=clamp(o,0,100)/100,c=s*a,l=c*(1-Math.abs(e%2-1)),u=s-c,i=Math.floor(e)%6,[g,h,f]=[[c,l,0],[l,c,0],[0,c,l],[0,l,c],[l,0,c],[c,0,l]][i];return{r:Math.round(255*(g+u)),g:Math.round(255*(h+u)),b:Math.round(255*(f+u))}}export function rgbToHsv({r:t,g:n,b:o}){const e=clamp(t,0,255)/255,a=clamp(n,0,255)/255,s=clamp(o,0,255)/255,c=Math.max(e,a,s),l=c-Math.min(e,a,s);let u=0;return 0!==l&&(u=c===e?(a-s)/l%6:c===a?(s-e)/l+2:(e-a)/l+4),{h:r(60*u),s:0===c?0:l/c*100,v:100*c}}export function rgbToHsl({r:r,g:t,b:n}){const{h:o,s:e,v:a}=rgbToHsv({r:r,g:t,b:n}),s=a/100,c=s*(1-e/100/2),l=Math.min(c,1-c);return{h:o,s:0===l?0:(s-c)/l*100,l:100*c}}export function hslToRgb({h:r,s:t,l:n}){const o=clamp(n,0,100)/100,e=o+clamp(t,0,100)/100*Math.min(o,1-o);return hsvToRgb({h:r,s:0===e?0:2*(1-o/e)*100,v:100*e})}const t=/^#?([0-9a-f]{3,8})$/i;export function parseColor(r){const n=r.trim().toLowerCase();if(!n)return null;if(n.startsWith("#")||t.test(n))return function(r){const n=t.exec(r.trim());if(!n)return null;const o=n[1],e=3===o.length||4===o.length?[...o].map(r=>r+r).join(""):o;if(6!==e.length&&8!==e.length)return null;const a=r=>parseInt(e.slice(2*r,2*r+2),16);return{hsv:rgbToHsv({r:a(0),g:a(1),b:a(2)}),alpha:8===e.length?a(3)/255:1}}(n);const o=/^(rgba?|hsla?)\((.*)\)$/.exec(n);if(!o)return null;const[,e,a]=o,s=function(r){return r.match(/-?[\d.]+%?/g)??[]}(a),c=s.map(r=>parseFloat(r));if(c.length<3||c.some(Number.isNaN))return null;const l=function(r,t){return t.length<=3?1:clamp(r[3]?.endsWith("%")?t[3]/100:t[3],0,1)}(s,c);return e.startsWith("rgb")?{hsv:rgbToHsv({r:c[0],g:c[1],b:c[2]}),alpha:l}:{hsv:rgbToHsv(hslToRgb({h:c[0],s:c[1],l:c[2]})),alpha:l}}function n(r){return clamp(Math.round(r),0,255).toString(16).padStart(2,"0")}export function rgbToHex({r:r,g:t,b:o},e=1){const a=`#${n(r)}${n(t)}${n(o)}`;return e>=1?a:`${a}${n(255*e)}`}function o(r){return String(Math.round(100*clamp(r,0,1))/100)}export function formatColor(r,t,n){const e=hsvToRgb(r);if("hex"===n)return rgbToHex(e,t);if("rgb"===n){const r=`${e.r}, ${e.g}, ${e.b}`;return t>=1?`rgb(${r})`:`rgba(${r}, ${o(t)})`}const{h:a,s:s,l:c}=rgbToHsl(e),l=`${Math.round(a)}, ${Math.round(s)}%, ${Math.round(c)}%`;return t>=1?`hsl(${l})`:`hsla(${l}, ${o(t)})`}export function cssColor(r,t=1){const{r:n,g:e,b:a}=hsvToRgb(r);return t>=1?`rgb(${n}, ${e}, ${a})`:`rgba(${n}, ${e}, ${a}, ${o(t)})`}export function readableInk(r){const{r:t,g:n,b:o}=hsvToRgb(r),e=r=>{const t=r/255;return t<=.03928?t/12.92:((t+.055)/1.055)**2.4};return.2126*e(t)+.7152*e(n)+.0722*e(o)>.42?"#000000":"#ffffff"}export const DEFAULT_SWATCHES=["#000000","#4b5563","#9ca3af","#ffffff","#ef4444","#f97316","#f59e0b","#84cc16","#22c55e","#14b8a6","#06b6d4","#3b82f6","#6366f1","#8b5cf6","#d946ef","#ec4899"];export const CHECKER_BACKGROUND={backgroundImage:"linear-gradient(45deg, var(--_mp-color-outline-variant) 25%, transparent 25%), linear-gradient(-45deg, var(--_mp-color-outline-variant) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--_mp-color-outline-variant) 75%), linear-gradient(-45deg, transparent 75%, var(--_mp-color-outline-variant) 75%)",backgroundSize:"8px 8px",backgroundPosition:"0 0, 0 4px, 4px -4px, -4px 0"};
@@ -0,0 +1,179 @@
1
+ /**
2
+ * The arithmetic and the naming the four pickers share.
3
+ *
4
+ * No date library under it, deliberately. This package has one runtime
5
+ * dependency and it is an icon set; a component library that quietly adds
6
+ * `date-fns` — or worse, picks a side in the dayjs/luxon/Temporal argument on
7
+ * its consumer's behalf — has made a decision that was not its to make.
8
+ * Everything here is either `Date` arithmetic, which is a dozen lines, or
9
+ * `Intl`, which the platform already ships and which knows more about month
10
+ * names in more languages than any bundled table ever will.
11
+ *
12
+ * Two rules hold everywhere below:
13
+ *
14
+ * - **Local time, always.** A calendar day is a thing a person is looking at on
15
+ * a wall, not an instant on a line. `new Date(2026, 6, 27)` is midnight local
16
+ * and every comparison here is made on the local Y/M/D triple, so a picker in
17
+ * Seoul and a picker in São Paulo both light up the cell that says 27.
18
+ * - **Nothing is mutated.** `Date` is mutable and every method on it that sounds
19
+ * like a question is actually a command. Each function here copies first, so a
20
+ * `value` handed in by a caller is never the object that comes back out.
21
+ *
22
+ * Nothing here is exported from `src/index.ts`. It is the library talking to
23
+ * itself, in the sense `internal/` always means.
24
+ */
25
+ import type { MPWeekday } from '../types';
26
+ /** Which unit the calendar is currently letting you pick. */
27
+ export type MPCalendarView = 'day' | 'month' | 'year';
28
+ /** How many years one page of the year grid holds. Four columns of three. */
29
+ export declare const YEAR_PAGE_SIZE = 12;
30
+ /**
31
+ * A local midnight on the given Y/M/D, with out-of-range parts normalised —
32
+ * month `12` rolls into January, day `0` into the last day of the month before.
33
+ *
34
+ * Built through `setFullYear` rather than `new Date(year, month, day)` because
35
+ * the two-argument constructor maps years 0–99 onto 1900–1999. Nobody is going
36
+ * to pick a date in the year 47, but a component that silently rewrites the year
37
+ * it was handed is a component that will eventually be blamed for something
38
+ * else.
39
+ */
40
+ export declare function makeDate(year: number, month: number, day: number): Date;
41
+ /** Is this a `Date` that stands for a real instant? `new Date('nope')` is not. */
42
+ export declare function isValidDate(value: unknown): value is Date;
43
+ /** The same day with the clock wound back to midnight. */
44
+ export declare function startOfDay(date: Date): Date;
45
+ /** The first day of the month this date is in, at midnight. */
46
+ export declare function startOfMonth(date: Date): Date;
47
+ /** How many days a month has, leap years included. */
48
+ export declare function daysInMonth(year: number, month: number): number;
49
+ /** Today, at midnight. The one place the pickers read the clock for a *date*. */
50
+ export declare function today(): Date;
51
+ export declare function addDays(date: Date, amount: number): Date;
52
+ /**
53
+ * Months, with the day of the month clamped rather than allowed to overflow.
54
+ *
55
+ * 31 January plus one month is 28 February, not 3 March. The naive
56
+ * `setMonth(getMonth() + 1)` gives the second answer, which is why stepping a
57
+ * calendar forward from a 31st with it skips February entirely.
58
+ */
59
+ export declare function addMonths(date: Date, amount: number): Date;
60
+ export declare function addYears(date: Date, amount: number): Date;
61
+ /** Negative, zero or positive, the way a sort comparator wants it. */
62
+ export declare function compareDay(a: Date, b: Date): number;
63
+ export declare function isSameDay(a: Date | null | undefined, b: Date | null | undefined): boolean;
64
+ export declare function isSameMonth(a: Date | null | undefined, b: Date | null | undefined): boolean;
65
+ /**
66
+ * Is this calendar *day* outside the allowed span?
67
+ *
68
+ * Day-granular on purpose. A `maxDate` of 27 July at 09:00 still leaves the 27th
69
+ * pickable — the bound is about which days exist, and the time of day is the
70
+ * clock's problem. `MPDateTimePicker` re-checks at full precision once an hour
71
+ * has been chosen.
72
+ */
73
+ export declare function isDayOutside(date: Date, min?: Date | null, max?: Date | null): boolean;
74
+ /** Seconds since local midnight — what `minTime`/`maxTime` are compared on. */
75
+ export declare function secondsOfDay(date: Date): number;
76
+ /** Which column of a clock a candidate time is being offered for. */
77
+ export type MPTimeUnit = 'hour' | 'minute' | 'second' | 'meridiem';
78
+ /**
79
+ * The span of the day one row of one column covers, in seconds since midnight.
80
+ *
81
+ * This is the detail that separates a working time picker from a frustrating
82
+ * one. A bound has to be checked against the *span* a row stands for, not
83
+ * against one instant inside it: with a `minTime` of 09:30, the hour `9` covers
84
+ * 09:00:00–09:59:59, which overlaps what is allowed, so it stays available and
85
+ * the minute column is where `00` through `25` grey out. Comparing the whole
86
+ * candidate instead hides the 9 and makes half past nine unreachable.
87
+ */
88
+ export declare function timeUnitSpan(unit: MPTimeUnit, at: Date): [number, number];
89
+ /** The same instant with one or more clock fields replaced. */
90
+ export declare function withTime(date: Date, parts: {
91
+ hours?: number;
92
+ minutes?: number;
93
+ seconds?: number;
94
+ }): Date;
95
+ /** `date`'s calendar day wearing `time`'s clock. */
96
+ export declare function mergeDateAndTime(date: Date, time: Date): Date;
97
+ /**
98
+ * Six weeks of seven days, always — including the leading and trailing days that
99
+ * belong to the neighbouring months.
100
+ *
101
+ * Six rows whatever the month, and that is the whole point. A February that
102
+ * starts on a Sunday needs four rows and a 31-day month starting on a Saturday
103
+ * needs six; a grid that renders only the rows it needs is a grid that changes
104
+ * height when you step a month forward, moving every cell out from under the
105
+ * pointer that just pressed one.
106
+ */
107
+ export declare function calendarWeeks(month: Date, weekStartsOn: MPWeekday): Date[][];
108
+ /** The first year on the page a given year falls on. 2026 → 2016 at 12 a page. */
109
+ export declare function yearPageStart(year: number): number;
110
+ /** A memoised `Intl.DateTimeFormat`. `undefined` locale means the runtime's own. */
111
+ export declare function dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat;
112
+ /** Formats a date, tolerating the `null` a cleared picker holds. */
113
+ export declare function formatDate(date: Date | null | undefined, locale: string | undefined, options: Intl.DateTimeFormatOptions): string;
114
+ /**
115
+ * Every distinct string those instants format to. Deduplicated, because a
116
+ * date-only format collapses twenty-four of them into a handful.
117
+ */
118
+ export declare function displaySamples(locale: string | undefined, options: Intl.DateTimeFormatOptions): string[];
119
+ /**
120
+ * The samples plus the placeholder, when the placeholder is a string.
121
+ *
122
+ * An empty picker shows the placeholder, which can easily be longer than any
123
+ * date — "Pick a departure date" against "3 Aug 2026" — and a trigger that
124
+ * shrinks the moment the first date is chosen is the same jump from the other
125
+ * direction. A `ReactNode` placeholder is left out: there is nothing to measure
126
+ * without rendering it twice.
127
+ */
128
+ export declare function withPlaceholder(samples: string[], placeholder: unknown): string[];
129
+ /**
130
+ * The three machine-readable spellings, for the hidden input that makes a picker
131
+ * submit with a form.
132
+ *
133
+ * Local, not UTC, and that is the whole point: `toISOString()` on a `Date`
134
+ * standing for 27 July in Seoul gives `2026-07-26T15:00:00Z`, and a form field
135
+ * that quietly reports the day before the one on screen is the single most
136
+ * expensive bug a date picker can ship. The shapes are the ones the native
137
+ * `<input type="date">`, `type="time"` and `type="datetime-local"` submit, so a
138
+ * server that already parses those needs no new code.
139
+ */
140
+ export declare function toISODate(date: Date): string;
141
+ export declare function toISOTime(date: Date, withSeconds?: boolean): string;
142
+ export declare function toISODateTime(date: Date, withSeconds?: boolean): string;
143
+ /**
144
+ * The seven column headers, rotated so the first one is `weekStartsOn`.
145
+ *
146
+ * `narrow` is what MD3's own calendar draws — one character per column, which is
147
+ * what keeps a 40dp cell a cell rather than a word. English narrow names collide
148
+ * (`S`, `M`, `T`, `W`, `T`, `F`, `S`), so the full name goes on the header's
149
+ * `aria-label` and a screen reader hears "Monday" rather than "M".
150
+ */
151
+ export declare function weekdayLabels(locale: string | undefined, weekStartsOn: MPWeekday, weekday?: 'narrow' | 'short' | 'long'): string[];
152
+ /** The twelve month names, January first, in the locale's own words. */
153
+ export declare function monthLabels(locale: string | undefined, month?: 'short' | 'long'): string[];
154
+ /**
155
+ * Does this locale write the month before the year?
156
+ *
157
+ * The calendar's header is two separate buttons — one that opens the month grid
158
+ * and one that opens the year grid — so it cannot just print what `Intl` gives
159
+ * it. Asking `formatToParts` which part came first is how the two buttons end up
160
+ * in the order the reader expects: `July 2026` in English, `2026년 7월` in
161
+ * Korean. Getting this wrong is subtle and reads as broken to exactly the people
162
+ * it is wrong for.
163
+ */
164
+ export declare function isMonthBeforeYear(locale: string | undefined): boolean;
165
+ /** Does this locale put a clock on a 12-hour dial? */
166
+ export declare function isHour12(locale: string | undefined): boolean;
167
+ /** What this locale calls AM and PM. */
168
+ export declare function meridiemLabels(locale: string | undefined): [string, string];
169
+ /**
170
+ * Which day the week starts on here — Sunday in the US and Korea, Monday across
171
+ * most of Europe, Saturday in much of the Middle East.
172
+ *
173
+ * `Intl.Locale`'s week info is the right source and is also the least evenly
174
+ * implemented corner of `Intl`: it is a getter in some engines, a method in
175
+ * others, and absent in the rest. All three are handled, and the fallback is
176
+ * Sunday rather than a throw — a calendar that renders starting on the wrong day
177
+ * is a small annoyance, and a calendar that renders nothing is not.
178
+ */
179
+ export declare function localeWeekStart(locale: string | undefined): MPWeekday;
@@ -0,0 +1 @@
1
+ export const YEAR_PAGE_SIZE=12;export function makeDate(t,e,r){const n=new Date(0);return n.setFullYear(t,e,r),n.setHours(0,0,0,0),n}export function isValidDate(t){return t instanceof Date&&!Number.isNaN(t.getTime())}export function startOfDay(t){const e=new Date(t.getTime());return e.setHours(0,0,0,0),e}export function startOfMonth(t){return makeDate(t.getFullYear(),t.getMonth(),1)}export function daysInMonth(t,e){return makeDate(t,e+1,0).getDate()}export function today(){return startOfDay(new Date)}export function addDays(t,e){const r=new Date(t.getTime());return r.setDate(r.getDate()+e),r}export function addMonths(t,e){const r=new Date(t.getTime()),n=makeDate(t.getFullYear(),t.getMonth()+e,1);return r.setFullYear(n.getFullYear(),n.getMonth(),Math.min(t.getDate(),daysInMonth(n.getFullYear(),n.getMonth()))),r}export function addYears(t,e){return addMonths(t,12*e)}export function compareDay(t,e){return startOfDay(t).getTime()-startOfDay(e).getTime()}export function isSameDay(t,e){return isValidDate(t)&&isValidDate(e)&&0===compareDay(t,e)}export function isSameMonth(t,e){return isValidDate(t)&&isValidDate(e)&&t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()}export function isDayOutside(t,e,r){return!!(isValidDate(e)&&compareDay(t,e)<0)||isValidDate(r)&&compareDay(t,r)>0}export function secondsOfDay(t){return 3600*t.getHours()+60*t.getMinutes()+t.getSeconds()}export function timeUnitSpan(t,e){const r=secondsOfDay(e);if("hour"===t){const t=3600*Math.floor(r/3600);return[t,t+3599]}if("minute"===t){const t=60*Math.floor(r/60);return[t,t+59]}if("second"===t)return[r,r];const n=e.getHours()<12?0:43200;return[n,n+43200-1]}export function withTime(t,e){const r=new Date(t.getTime());return r.setHours(e.hours??r.getHours(),e.minutes??r.getMinutes(),e.seconds??r.getSeconds(),0),r}export function mergeDateAndTime(t,e){return withTime(startOfDay(t),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()})}export function calendarWeeks(t,e){const r=startOfMonth(t),n=(r.getDay()-e+7)%7,o=addDays(r,-n);return Array.from({length:6},(t,e)=>Array.from({length:7},(t,r)=>addDays(o,7*e+r)))}export function yearPageStart(t){return t-(t%12+12)%12}const t=new Map;export function dateFormatter(e,r){const n=`${e??""}\0${JSON.stringify(r)}`;let o=t.get(n);return o||(o=new Intl.DateTimeFormat(e,r),t.set(n,o)),o}export function formatDate(t,e,r){return isValidDate(t)?dateFormatter(e,r).format(t):""}const e=Array.from({length:24},(t,e)=>new Date(2027,e%12,21+e%7,e,58,58));export function displaySamples(t,r){const n=dateFormatter(t,r);return[...new Set(e.map(t=>n.format(t)))]}export function withPlaceholder(t,e){return"string"==typeof e&&""!==e?[...t,e]:t}export function toISODate(t){const e=t=>String(t).padStart(2,"0");return`${String(t.getFullYear()).padStart(4,"0")}-${e(t.getMonth()+1)}-${e(t.getDate())}`}export function toISOTime(t,e=!1){const r=t=>String(t).padStart(2,"0"),n=`${r(t.getHours())}:${r(t.getMinutes())}`;return e?`${n}:${r(t.getSeconds())}`:n}export function toISODateTime(t,e=!1){return`${toISODate(t)}T${toISOTime(t,e)}`}const r=makeDate(2021,7,1);export function weekdayLabels(t,e,n="narrow"){const o=dateFormatter(t,{weekday:n});return Array.from({length:7},(t,n)=>o.format(addDays(r,(e+n)%7)))}export function monthLabels(t,e="short"){const r=dateFormatter(t,{month:e});return Array.from({length:12},(t,e)=>r.format(makeDate(2021,e,1)))}export function isMonthBeforeYear(t){const e=dateFormatter(t,{year:"numeric",month:"long"}).formatToParts(r);return e.findIndex(t=>"month"===t.type)<e.findIndex(t=>"year"===t.type)}export function isHour12(t){const e=dateFormatter(t,{hour:"numeric"}).resolvedOptions();return e.hourCycle?"h11"===e.hourCycle||"h12"===e.hourCycle:!0===e.hour12}export function meridiemLabels(t){const e=dateFormatter(t,{hour:"numeric",hour12:!0}),n=t=>{const n=e.formatToParts(withTime(r,{hours:t})).find(t=>"dayPeriod"===t.type);return n?.value??(t<12?"AM":"PM")};return[n(9),n(21)]}export function localeWeekStart(t){try{const e=t??(new Intl.DateTimeFormat).resolvedOptions().locale,r=new Intl.Locale(e),n="function"==typeof r.getWeekInfo?r.getWeekInfo():r.weekInfo;if("number"==typeof n?.firstDay)return n.firstDay%7}catch{}return 0}