material-plus-ui 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.fix.py +92 -0
- package/README.md +1 -1
- package/dist/components/accordion/MPAccordion.js +1 -1
- package/dist/components/alert/MPAlert.js +1 -1
- package/dist/components/animate-lighting/MPAnimateLighting.js +1 -1
- package/dist/components/aspect-ratio/MPAspectRatio.js +1 -1
- package/dist/components/avatar/MPAvatar.js +1 -1
- package/dist/components/avatar-group/MPAvatarGroup.js +1 -1
- package/dist/components/badge/MPBadge.js +1 -1
- package/dist/components/blockquote/MPBlockquote.js +1 -1
- package/dist/components/bottom-navigation/MPBottomNavigation.d.ts +17 -0
- package/dist/components/bottom-navigation/MPBottomNavigation.js +1 -1
- package/dist/components/breadcrumb/MPBreadcrumb.js +1 -1
- package/dist/components/button/MPButton.d.ts +49 -3
- package/dist/components/button/MPButton.js +1 -1
- package/dist/components/calendar/MPCalendar.d.ts +160 -0
- package/dist/components/calendar/MPCalendar.js +2 -0
- package/dist/components/calendar/index.d.ts +2 -0
- package/dist/components/calendar/index.js +1 -0
- package/dist/components/card/MPCard.js +1 -1
- package/dist/components/carousel/MPCarousel.js +1 -1
- package/dist/components/chat-bubble/MPChatBubble.js +1 -1
- package/dist/components/checkbox/MPCheckbox.d.ts +6 -0
- package/dist/components/checkbox/MPCheckbox.js +1 -1
- package/dist/components/chip/MPChip.d.ts +21 -6
- package/dist/components/chip/MPChip.js +1 -1
- package/dist/components/collapsible/MPCollapsible.js +1 -1
- package/dist/components/color-picker/MPColorPicker.js +1 -1
- package/dist/components/combobox/MPCombobox.d.ts +52 -3
- package/dist/components/combobox/MPCombobox.js +1 -1
- package/dist/components/command-palette/MPCommandPalette.d.ts +1 -1
- package/dist/components/command-palette/MPCommandPalette.js +1 -1
- package/dist/components/config/MPConfigProvider.d.ts +124 -0
- package/dist/components/config/MPConfigProvider.js +2 -0
- package/dist/components/config/index.d.ts +2 -0
- package/dist/components/config/index.js +1 -0
- package/dist/components/confirm/MPConfirmProvider.d.ts +143 -0
- package/dist/components/confirm/MPConfirmProvider.js +2 -0
- package/dist/components/confirm/index.d.ts +2 -0
- package/dist/components/confirm/index.js +1 -0
- package/dist/components/container/MPContainer.js +1 -1
- package/dist/components/date-picker/MPDatePicker.d.ts +53 -2
- package/dist/components/date-picker/MPDatePicker.js +1 -1
- package/dist/components/date-picker/index.d.ts +1 -1
- package/dist/components/date-range-picker/MPDateRangePicker.js +1 -1
- package/dist/components/date-time-picker/MPDateTimePicker.js +1 -1
- package/dist/components/dialog/MPDialog.d.ts +16 -3
- package/dist/components/dialog/MPDialog.js +1 -1
- package/dist/components/divider/MPDivider.js +1 -1
- package/dist/components/drawer/MPDrawer.d.ts +1 -1
- package/dist/components/drawer/MPDrawer.js +1 -1
- package/dist/components/empty/MPEmpty.js +1 -1
- package/dist/components/file-picker/MPFilePicker.d.ts +6 -0
- package/dist/components/file-picker/MPFilePicker.js +1 -1
- package/dist/components/floating-action-button/MPFloatingActionButton.js +1 -1
- package/dist/components/footer/MPFooter.js +1 -1
- package/dist/components/grid/MPGrid.d.ts +23 -1
- package/dist/components/grid/MPGrid.js +1 -1
- package/dist/components/header/MPHeader.js +1 -1
- package/dist/components/image/MPImage.d.ts +112 -0
- package/dist/components/image/MPImage.js +2 -0
- package/dist/components/image/index.d.ts +2 -0
- package/dist/components/image/index.js +1 -0
- package/dist/components/list/MPList.d.ts +28 -0
- package/dist/components/list/MPList.js +1 -1
- package/dist/components/menu/MPMenu.d.ts +25 -4
- package/dist/components/menu/MPMenu.js +1 -1
- package/dist/components/menubar/MPMenubar.d.ts +8 -1
- package/dist/components/menubar/MPMenubar.js +1 -1
- package/dist/components/navigation-menu/MPNavigationMenu.d.ts +8 -1
- package/dist/components/navigation-menu/MPNavigationMenu.js +1 -1
- package/dist/components/number-field/MPNumberField.d.ts +9 -3
- package/dist/components/number-field/MPNumberField.js +1 -1
- package/dist/components/otp-field/MPOtpField.js +1 -1
- package/dist/components/overlay/MPOverlay.d.ts +1 -1
- package/dist/components/overlay/MPOverlay.js +1 -1
- package/dist/components/pagination/MPPagination.js +1 -1
- package/dist/components/panes/MPPanes.js +1 -1
- package/dist/components/pill/MPPill.js +1 -1
- package/dist/components/popconfirm/MPPopconfirm.d.ts +92 -0
- package/dist/components/popconfirm/MPPopconfirm.js +2 -0
- package/dist/components/popconfirm/index.d.ts +2 -0
- package/dist/components/popconfirm/index.js +1 -0
- package/dist/components/popover/MPPopover.d.ts +1 -1
- package/dist/components/popover/MPPopover.js +1 -1
- package/dist/components/progress-box/MPProgressBox.js +1 -1
- package/dist/components/progress-circular/MPProgressCircular.js +1 -1
- package/dist/components/progress-linear/MPProgressLinear.js +1 -1
- package/dist/components/radio-group/MPRadioGroup.d.ts +12 -0
- package/dist/components/radio-group/MPRadioGroup.js +1 -1
- package/dist/components/rating/MPRating.js +1 -1
- package/dist/components/segmented-button/MPSegmentedButton.d.ts +7 -0
- package/dist/components/segmented-button/MPSegmentedButton.js +1 -1
- package/dist/components/select/MPSelect.d.ts +9 -2
- package/dist/components/select/MPSelect.js +1 -1
- package/dist/components/shortcut/MPShortcut.js +1 -1
- package/dist/components/sidebar/MPSidebar.js +1 -1
- package/dist/components/skeleton/MPSkeleton.js +1 -1
- package/dist/components/slider/MPSlider.d.ts +33 -0
- package/dist/components/slider/MPSlider.js +1 -1
- package/dist/components/snackbar/MPSnackbar.d.ts +20 -1
- package/dist/components/snackbar/MPSnackbar.js +1 -1
- package/dist/components/spoiler/MPSpoiler.js +1 -1
- package/dist/components/stepper/MPStepper.d.ts +153 -0
- package/dist/components/stepper/MPStepper.js +2 -0
- package/dist/components/stepper/index.d.ts +2 -0
- package/dist/components/stepper/index.js +1 -0
- package/dist/components/switch/MPSwitch.d.ts +6 -0
- package/dist/components/switch/MPSwitch.js +1 -1
- package/dist/components/table/MPTable.d.ts +1 -1
- package/dist/components/table/MPTable.js +1 -1
- package/dist/components/tabs/MPTabs.js +1 -1
- package/dist/components/text-field/MPTextField.d.ts +46 -14
- package/dist/components/text-field/MPTextField.js +1 -1
- package/dist/components/time-picker/MPTimePicker.js +1 -1
- package/dist/components/timeline/MPTimeline.d.ts +10 -2
- package/dist/components/timeline/MPTimeline.js +1 -1
- package/dist/components/toggle/MPToggle.js +1 -1
- package/dist/components/transfer/MPTransfer.js +1 -1
- package/dist/components/typography/MPTypography.d.ts +7 -0
- package/dist/components/typography/MPTypography.js +1 -2
- package/dist/components/visually-hidden/MPVisuallyHidden.d.ts +60 -0
- package/dist/components/visually-hidden/MPVisuallyHidden.js +2 -0
- package/dist/components/visually-hidden/index.d.ts +2 -0
- package/dist/components/visually-hidden/index.js +1 -0
- package/dist/constants/glyphs.d.ts +2 -0
- package/dist/constants/glyphs.js +1 -1
- package/dist/constants/icons.d.ts +1 -0
- package/dist/constants/icons.js +1 -1
- package/dist/hooks/index.d.ts +23 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useMPColorScheme.d.ts +135 -0
- package/dist/hooks/useMPColorScheme.js +1 -0
- package/dist/hooks/useMPReducedMotion.d.ts +32 -0
- package/dist/hooks/useMPReducedMotion.js +1 -0
- package/dist/hooks/useMPShortcut.d.ts +105 -0
- package/dist/hooks/useMPShortcut.js +2 -0
- package/dist/hooks/useMPWindowClass.d.ts +48 -0
- package/dist/hooks/useMPWindowClass.js +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/dist/internal/Calendar.d.ts +19 -4
- package/dist/internal/Calendar.js +1 -1
- package/dist/internal/Picker.d.ts +15 -3
- package/dist/internal/Picker.js +1 -1
- package/dist/internal/color-scheme.d.ts +28 -0
- package/dist/internal/color-scheme.js +2 -0
- package/dist/internal/config.d.ts +43 -0
- package/dist/internal/config.js +2 -0
- package/dist/internal/date.d.ts +50 -3
- package/dist/internal/date.js +1 -1
- package/dist/internal/i18n.d.ts +26 -1
- package/dist/internal/messages/confirm.d.ts +3 -0
- package/dist/internal/messages/confirm.js +1 -0
- package/dist/internal/messages/picker.js +1 -1
- package/dist/internal/progress.d.ts +14 -0
- package/dist/internal/step.d.ts +71 -0
- package/dist/internal/step.js +1 -0
- package/dist/internal/window-class.d.ts +21 -0
- package/dist/internal/window-class.js +2 -0
- package/dist/locales/ar.js +1 -1
- package/dist/locales/de.js +1 -1
- package/dist/locales/es.js +1 -1
- package/dist/locales/fr.js +1 -1
- package/dist/locales/hi.js +1 -1
- package/dist/locales/id.js +1 -1
- package/dist/locales/it.js +1 -1
- package/dist/locales/ja.js +1 -1
- package/dist/locales/ko.js +1 -1
- package/dist/locales/nl.js +1 -1
- package/dist/locales/pl.js +1 -1
- package/dist/locales/pt.js +1 -1
- package/dist/locales/ru.js +1 -1
- package/dist/locales/th.js +1 -1
- package/dist/locales/tr.js +1 -1
- package/dist/locales/vi.js +1 -1
- package/dist/locales/zh-hans.js +1 -1
- package/dist/locales/zh-hant.js +1 -1
- package/dist/styles/accordion.css +1 -1
- package/dist/styles/animate-lighting.css +1 -1
- package/dist/styles/aspect-ratio.css +1 -1
- package/dist/styles/bottom-navigation.css +1 -1
- package/dist/styles/calendar.css +2 -0
- package/dist/styles/chip.css +1 -1
- package/dist/styles/combobox.css +1 -1
- package/dist/styles/config.css +2 -0
- package/dist/styles/confirm.css +2 -0
- package/dist/styles/grid.css +1 -1
- package/dist/styles/highlight.css +1 -1
- package/dist/styles/image.css +2 -0
- package/dist/styles/list.css +1 -1
- package/dist/styles/panes.css +1 -1
- package/dist/styles/popconfirm.css +2 -0
- package/dist/styles/progress-box.css +1 -1
- package/dist/styles/progress-circular.css +1 -1
- package/dist/styles/progress-linear.css +1 -1
- package/dist/styles/rating.css +1 -1
- package/dist/styles/shortcut.css +1 -1
- package/dist/styles/slider.css +1 -1
- package/dist/styles/snackbar.css +1 -1
- package/dist/styles/stepper.css +2 -0
- package/dist/styles/text-field.css +1 -1
- package/dist/styles/timeline.css +1 -1
- package/dist/styles/tokens.css +1 -1
- package/dist/styles/transfer.css +1 -1
- package/dist/styles/typography.css +1 -1
- package/dist/styles/visually-hidden.css +2 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +91 -5
- package/dist/types.d.ts +64 -0
- package/package.json +6 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { type MPResolvedOS } from '../internal/keys.js';
|
|
2
|
+
/** The three platforms a shortcut is spelled for. */
|
|
3
|
+
export type { MPResolvedOS };
|
|
4
|
+
/** Where the keystroke is listened for, and what happens to it. */
|
|
5
|
+
export interface MPShortcutOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Turns the binding off without unmounting whatever holds it. A shortcut
|
|
8
|
+
* behind a feature flag, or one that belongs to a panel that is closed.
|
|
9
|
+
* @default true
|
|
10
|
+
*/
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Calls `preventDefault()` on the matching keystroke.
|
|
14
|
+
*
|
|
15
|
+
* On by default, and it is the honest default: some browsers put their own
|
|
16
|
+
* search bar on `Mod+K`, and a page binding that combination has said the key
|
|
17
|
+
* is theirs. Switch it off for a shortcut that means to run *alongside* the
|
|
18
|
+
* browser's, which is rare enough to be worth writing down.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
preventDefault?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Ignores the keystroke while the focus is in a text input, a textarea or
|
|
24
|
+
* anything `contenteditable`.
|
|
25
|
+
*
|
|
26
|
+
* Off by default, because the shortcut most pages bind has a modifier and
|
|
27
|
+
* `Mod+K` typed into a search field still means "open the palette". Switch it
|
|
28
|
+
* on for a **bare** key — `/` to focus search, `?` for help — which would
|
|
29
|
+
* otherwise be swallowed out of the middle of somebody's sentence.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
ignoreInputs?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* What the listener is attached to.
|
|
35
|
+
* @default the window
|
|
36
|
+
*/
|
|
37
|
+
target?: EventTarget | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Runs something when a keystroke arrives, spelled the way this library spells
|
|
41
|
+
* shortcuts everywhere else.
|
|
42
|
+
*
|
|
43
|
+
* `MPShortcut` **writes** a shortcut down, `MPCommandPalette` **reads** one off
|
|
44
|
+
* a real keyboard, and both have always gone through one matcher so that a label
|
|
45
|
+
* on the screen and the binding under it cannot disagree — see `internal/keys.ts`
|
|
46
|
+
* for the day they did. This is that matcher, for the shortcuts an application
|
|
47
|
+
* binds itself.
|
|
48
|
+
*
|
|
49
|
+
* ```tsx
|
|
50
|
+
* useMPShortcut('Mod+K', () => setOpen(true));
|
|
51
|
+
* useMPShortcut('/', focusSearch, { ignoreInputs: true });
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* ## `Mod` is the whole point
|
|
55
|
+
*
|
|
56
|
+
* It resolves to Command on a Mac and Control everywhere else, which is what
|
|
57
|
+
* lets one string be both the binding and the label:
|
|
58
|
+
*
|
|
59
|
+
* ```tsx
|
|
60
|
+
* <MPShortcut keys="Mod+K" />;
|
|
61
|
+
* useMPShortcut('Mod+K', open);
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* Two lines, one spelling, and no way for the page to draw `⌘K` while listening
|
|
65
|
+
* for `Ctrl+K`.
|
|
66
|
+
*
|
|
67
|
+
* Modifiers are matched in **both** directions: `Mod+K` does not fire when Shift
|
|
68
|
+
* is also held, because that combination may belong to something else. A
|
|
69
|
+
* shortcut that ignored extra modifiers would be quietly taking keystrokes it
|
|
70
|
+
* was not given.
|
|
71
|
+
*
|
|
72
|
+
* ## The handler is not a dependency
|
|
73
|
+
*
|
|
74
|
+
* It is kept in a ref and read at the moment the key arrives, so an inline arrow
|
|
75
|
+
* function is fine and does not rebind the listener on every render. What *does*
|
|
76
|
+
* rebind is the shortcut itself, `enabled`, and `target` — the things that change
|
|
77
|
+
* what is being listened for.
|
|
78
|
+
*
|
|
79
|
+
* ## Sharp edges
|
|
80
|
+
*
|
|
81
|
+
* - **It listens on the window**, so it fires wherever the focus is unless
|
|
82
|
+
* `ignoreInputs` says otherwise. That is what a page-wide shortcut wants and
|
|
83
|
+
* not what a shortcut belonging to one panel wants — pass that panel's element
|
|
84
|
+
* as `target`.
|
|
85
|
+
* - **It does not stop propagation.** A page with two hooks bound to one
|
|
86
|
+
* combination runs both, which is a collision the page has to resolve rather
|
|
87
|
+
* than something the hook can guess at.
|
|
88
|
+
* - **The platform is detected once.** It cannot change under a running page.
|
|
89
|
+
*/
|
|
90
|
+
export declare function useMPShortcut(keys: string | string[], handler: (event: KeyboardEvent) => void, options?: MPShortcutOptions): void;
|
|
91
|
+
/**
|
|
92
|
+
* Which keyboard the reader is on — `'mac'`, `'windows'` or `'linux'`.
|
|
93
|
+
*
|
|
94
|
+
* The same detection `MPShortcut` prints its key caps from, exported so an
|
|
95
|
+
* application writing a key cap of its own cannot end up on a different answer
|
|
96
|
+
* from the component beside it. Three sources are matched at once —
|
|
97
|
+
* `userAgentData.platform`, `navigator.platform` and the user agent string —
|
|
98
|
+
* because the question is coarse and browsers freeze or lie about each of them
|
|
99
|
+
* separately.
|
|
100
|
+
*
|
|
101
|
+
* `'windows'` on a server, and corrected on hydration through
|
|
102
|
+
* `useSyncExternalStore` — which is the one API that tells React the two renders
|
|
103
|
+
* are *meant* to differ, and is exactly the sequence a Mac reader sees.
|
|
104
|
+
*/
|
|
105
|
+
export declare function useMPPlatform(): MPResolvedOS;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import*as e from"react";import{matchesShortcut as t,useDetectedOS as n}from"../internal/keys.js";const r=/^(input|textarea|select)$/i;export function useMPShortcut(o,i,s={}){const{enabled:u=!0,preventDefault:a=!0,ignoreInputs:c=!1,target:f}=s,d=n(),l=e.useRef(i);l.current=i;const p=Array.isArray(o)?o.join("+"):o;e.useEffect(()=>{if(!u)return;const e=void 0===f?"undefined"==typeof window?null:window:f;if(!e)return;const n=e=>{const n=e;c&&function(e){return e instanceof HTMLElement&&(r.test(e.tagName)||e.isContentEditable)}(n.target)||t(n,p,d)&&(a&&n.preventDefault(),l.current(n))};return e.addEventListener("keydown",n),()=>e.removeEventListener("keydown",n)},[p,d,u,a,c,f])}export function useMPPlatform(){return n()}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { MPWindowClass } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Which of Material's five window size classes the window is in.
|
|
4
|
+
*
|
|
5
|
+
* The library has always had this axis — `MPGrid` reflows along it, `MPResponsive`
|
|
6
|
+
* is written in terms of it, `MPSidebar` collapses at it — and a consumer could
|
|
7
|
+
* name the classes in a prop without ever being able to *ask* which one they
|
|
8
|
+
* were in. So a page that wanted one more decision than a prop covers had to
|
|
9
|
+
* write the four breakpoints out again, in numbers that had to match the
|
|
10
|
+
* library's or the layout would disagree with itself at one width.
|
|
11
|
+
*
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const size = useMPWindowClass();
|
|
14
|
+
*
|
|
15
|
+
* return size === 'compact' ? <MPDrawer>{nav}</MPDrawer> : <MPSidebar>{nav}</MPSidebar>;
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* ## It reads the media queries, not the width
|
|
19
|
+
*
|
|
20
|
+
* Which is what keeps it agreeing with the stylesheet. `innerWidth` counts a
|
|
21
|
+
* classic scrollbar and a media query does not, so a 615px window with a 15px
|
|
22
|
+
* scrollbar is `medium` to CSS and `compact` to arithmetic — a layout whose
|
|
23
|
+
* JavaScript and whose CSS part company at exactly one width, which is the
|
|
24
|
+
* hardest kind of bug to be shown.
|
|
25
|
+
*
|
|
26
|
+
* It also subscribes to the four boundaries rather than to `resize`. A window
|
|
27
|
+
* dragged from 500 to 1900 wakes this four times; a `resize` listener wakes
|
|
28
|
+
* several hundred, for the same four answers.
|
|
29
|
+
*
|
|
30
|
+
* ## On a server
|
|
31
|
+
*
|
|
32
|
+
* There is no window, so there is no true answer — and this returns `onServer`,
|
|
33
|
+
* which is `'expanded'` unless you say otherwise. That is a **guess**, and the
|
|
34
|
+
* argument is there because an application usually knows better than the library
|
|
35
|
+
* does: a marketing site's first paint is mostly phones and `'compact'` is the
|
|
36
|
+
* closer bet, an internal dashboard's is not.
|
|
37
|
+
*
|
|
38
|
+
* The client corrects it on hydration. `useSyncExternalStore` is what makes that
|
|
39
|
+
* correction legitimate rather than a mismatch React warns about — but the
|
|
40
|
+
* correction is a second render, so a component that swaps a whole navigation
|
|
41
|
+
* pattern on this will do so visibly on a first load. Where that matters, the
|
|
42
|
+
* CSS answer is the one that has no first render to be wrong: `MPGrid`'s
|
|
43
|
+
* responsive props and Tailwind's own variants are resolved by the browser
|
|
44
|
+
* before anything paints.
|
|
45
|
+
*
|
|
46
|
+
* @param onServer what to answer where there is no window. @default 'expanded'
|
|
47
|
+
*/
|
|
48
|
+
export declare function useMPWindowClass(onServer?: MPWindowClass): MPWindowClass;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useWindowClass as n}from"../internal/window-class.js";export function useMPWindowClass(e="expanded"){return n(e)}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export { registerMPMessages, type MPLocale, type MPMessages, type MPPartialMessages } from './internal/i18n.js';
|
|
3
3
|
export * from './constants/icons.js';
|
|
4
|
+
export * from './hooks/index.js';
|
|
4
5
|
export * from './components/accordion/index.js';
|
|
5
6
|
export * from './components/alert/index.js';
|
|
6
7
|
export * from './components/animate-appear/index.js';
|
|
@@ -24,12 +25,15 @@ export * from './components/box/index.js';
|
|
|
24
25
|
export * from './components/breadcrumb/index.js';
|
|
25
26
|
export * from './components/button/index.js';
|
|
26
27
|
export * from './components/button-group/index.js';
|
|
28
|
+
export * from './components/calendar/index.js';
|
|
27
29
|
export * from './components/card/index.js';
|
|
28
30
|
export * from './components/carousel/index.js';
|
|
29
31
|
export * from './components/chat-bubble/index.js';
|
|
30
32
|
export * from './components/checkbox/index.js';
|
|
31
33
|
export * from './components/chip/index.js';
|
|
32
34
|
export * from './components/collapsible/index.js';
|
|
35
|
+
export * from './components/config/index.js';
|
|
36
|
+
export * from './components/confirm/index.js';
|
|
33
37
|
export * from './components/color-picker/index.js';
|
|
34
38
|
export * from './components/combobox/index.js';
|
|
35
39
|
export * from './components/command-palette/index.js';
|
|
@@ -51,6 +55,7 @@ export * from './components/header/index.js';
|
|
|
51
55
|
export * from './components/highlight/index.js';
|
|
52
56
|
export * from './components/icon/index.js';
|
|
53
57
|
export * from './components/icon-button/index.js';
|
|
58
|
+
export * from './components/image/index.js';
|
|
54
59
|
export * from './components/list/index.js';
|
|
55
60
|
export * from './components/locale/index.js';
|
|
56
61
|
export * from './components/menu/index.js';
|
|
@@ -63,6 +68,7 @@ export * from './components/page-layout/index.js';
|
|
|
63
68
|
export * from './components/pagination/index.js';
|
|
64
69
|
export * from './components/panes/index.js';
|
|
65
70
|
export * from './components/pill/index.js';
|
|
71
|
+
export * from './components/popconfirm/index.js';
|
|
66
72
|
export * from './components/popover/index.js';
|
|
67
73
|
export * from './components/progress-box/index.js';
|
|
68
74
|
export * from './components/progress-circular/index.js';
|
|
@@ -77,6 +83,7 @@ export * from './components/skeleton/index.js';
|
|
|
77
83
|
export * from './components/slider/index.js';
|
|
78
84
|
export * from './components/snackbar/index.js';
|
|
79
85
|
export * from './components/spoiler/index.js';
|
|
86
|
+
export * from './components/stepper/index.js';
|
|
80
87
|
export * from './components/switch/index.js';
|
|
81
88
|
export * from './components/table/index.js';
|
|
82
89
|
export * from './components/tabs/index.js';
|
|
@@ -89,3 +96,4 @@ export * from './components/toggle-group/index.js';
|
|
|
89
96
|
export * from './components/tooltip/index.js';
|
|
90
97
|
export * from './components/transfer/index.js';
|
|
91
98
|
export * from './components/typography/index.js';
|
|
99
|
+
export * from './components/visually-hidden/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./types.js";export{registerMPMessages}from"./internal/i18n.js";export*from"./constants/icons.js";export*from"./components/accordion/index.js";export*from"./components/alert/index.js";export*from"./components/animate-appear/index.js";export*from"./components/animate-blink/index.js";export*from"./components/animate-fade/index.js";export*from"./components/animate-grow/index.js";export*from"./components/animate-headline/index.js";export*from"./components/animate-lighting/index.js";export*from"./components/animate-marquee/index.js";export*from"./components/animate-rotate/index.js";export*from"./components/animate-slide/index.js";export*from"./components/animate-typing/index.js";export*from"./components/animate-zoom/index.js";export*from"./components/aspect-ratio/index.js";export*from"./components/avatar/index.js";export*from"./components/avatar-group/index.js";export*from"./components/badge/index.js";export*from"./components/blockquote/index.js";export*from"./components/bottom-navigation/index.js";export*from"./components/box/index.js";export*from"./components/breadcrumb/index.js";export*from"./components/button/index.js";export*from"./components/button-group/index.js";export*from"./components/card/index.js";export*from"./components/carousel/index.js";export*from"./components/chat-bubble/index.js";export*from"./components/checkbox/index.js";export*from"./components/chip/index.js";export*from"./components/collapsible/index.js";export*from"./components/color-picker/index.js";export*from"./components/combobox/index.js";export*from"./components/command-palette/index.js";export*from"./components/container/index.js";export*from"./components/date-picker/index.js";export*from"./components/date-range-picker/index.js";export*from"./components/date-time-picker/index.js";export*from"./components/dialog/index.js";export*from"./components/divider/index.js";export*from"./components/drawer/index.js";export*from"./components/empty/index.js";export*from"./components/fieldset/index.js";export*from"./components/file-picker/index.js";export*from"./components/floating-action-button/index.js";export*from"./components/footer/index.js";export*from"./components/form/index.js";export*from"./components/grid/index.js";export*from"./components/header/index.js";export*from"./components/highlight/index.js";export*from"./components/icon/index.js";export*from"./components/icon-button/index.js";export*from"./components/list/index.js";export*from"./components/locale/index.js";export*from"./components/menu/index.js";export*from"./components/menubar/index.js";export*from"./components/navigation-menu/index.js";export*from"./components/number-field/index.js";export*from"./components/otp-field/index.js";export*from"./components/overlay/index.js";export*from"./components/page-layout/index.js";export*from"./components/pagination/index.js";export*from"./components/panes/index.js";export*from"./components/pill/index.js";export*from"./components/popover/index.js";export*from"./components/progress-box/index.js";export*from"./components/progress-circular/index.js";export*from"./components/progress-linear/index.js";export*from"./components/radio-group/index.js";export*from"./components/rating/index.js";export*from"./components/segmented-button/index.js";export*from"./components/select/index.js";export*from"./components/shortcut/index.js";export*from"./components/sidebar/index.js";export*from"./components/skeleton/index.js";export*from"./components/slider/index.js";export*from"./components/snackbar/index.js";export*from"./components/spoiler/index.js";export*from"./components/switch/index.js";export*from"./components/table/index.js";export*from"./components/tabs/index.js";export*from"./components/text-field/index.js";export*from"./components/text-link/index.js";export*from"./components/time-picker/index.js";export*from"./components/timeline/index.js";export*from"./components/toggle/index.js";export*from"./components/toggle-group/index.js";export*from"./components/tooltip/index.js";export*from"./components/transfer/index.js";export*from"./components/typography/index.js";
|
|
1
|
+
export*from"./types.js";export{registerMPMessages}from"./internal/i18n.js";export*from"./constants/icons.js";export*from"./hooks/index.js";export*from"./components/accordion/index.js";export*from"./components/alert/index.js";export*from"./components/animate-appear/index.js";export*from"./components/animate-blink/index.js";export*from"./components/animate-fade/index.js";export*from"./components/animate-grow/index.js";export*from"./components/animate-headline/index.js";export*from"./components/animate-lighting/index.js";export*from"./components/animate-marquee/index.js";export*from"./components/animate-rotate/index.js";export*from"./components/animate-slide/index.js";export*from"./components/animate-typing/index.js";export*from"./components/animate-zoom/index.js";export*from"./components/aspect-ratio/index.js";export*from"./components/avatar/index.js";export*from"./components/avatar-group/index.js";export*from"./components/badge/index.js";export*from"./components/blockquote/index.js";export*from"./components/bottom-navigation/index.js";export*from"./components/box/index.js";export*from"./components/breadcrumb/index.js";export*from"./components/button/index.js";export*from"./components/button-group/index.js";export*from"./components/calendar/index.js";export*from"./components/card/index.js";export*from"./components/carousel/index.js";export*from"./components/chat-bubble/index.js";export*from"./components/checkbox/index.js";export*from"./components/chip/index.js";export*from"./components/collapsible/index.js";export*from"./components/config/index.js";export*from"./components/confirm/index.js";export*from"./components/color-picker/index.js";export*from"./components/combobox/index.js";export*from"./components/command-palette/index.js";export*from"./components/container/index.js";export*from"./components/date-picker/index.js";export*from"./components/date-range-picker/index.js";export*from"./components/date-time-picker/index.js";export*from"./components/dialog/index.js";export*from"./components/divider/index.js";export*from"./components/drawer/index.js";export*from"./components/empty/index.js";export*from"./components/fieldset/index.js";export*from"./components/file-picker/index.js";export*from"./components/floating-action-button/index.js";export*from"./components/footer/index.js";export*from"./components/form/index.js";export*from"./components/grid/index.js";export*from"./components/header/index.js";export*from"./components/highlight/index.js";export*from"./components/icon/index.js";export*from"./components/icon-button/index.js";export*from"./components/image/index.js";export*from"./components/list/index.js";export*from"./components/locale/index.js";export*from"./components/menu/index.js";export*from"./components/menubar/index.js";export*from"./components/navigation-menu/index.js";export*from"./components/number-field/index.js";export*from"./components/otp-field/index.js";export*from"./components/overlay/index.js";export*from"./components/page-layout/index.js";export*from"./components/pagination/index.js";export*from"./components/panes/index.js";export*from"./components/pill/index.js";export*from"./components/popconfirm/index.js";export*from"./components/popover/index.js";export*from"./components/progress-box/index.js";export*from"./components/progress-circular/index.js";export*from"./components/progress-linear/index.js";export*from"./components/radio-group/index.js";export*from"./components/rating/index.js";export*from"./components/segmented-button/index.js";export*from"./components/select/index.js";export*from"./components/shortcut/index.js";export*from"./components/sidebar/index.js";export*from"./components/skeleton/index.js";export*from"./components/slider/index.js";export*from"./components/snackbar/index.js";export*from"./components/spoiler/index.js";export*from"./components/stepper/index.js";export*from"./components/switch/index.js";export*from"./components/table/index.js";export*from"./components/tabs/index.js";export*from"./components/text-field/index.js";export*from"./components/text-link/index.js";export*from"./components/time-picker/index.js";export*from"./components/timeline/index.js";export*from"./components/toggle/index.js";export*from"./components/toggle-group/index.js";export*from"./components/tooltip/index.js";export*from"./components/transfer/index.js";export*from"./components/typography/index.js";export*from"./components/visually-hidden/index.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { type MPTimeUnit } from './date.js';
|
|
2
|
+
import { type MPCalendarView, type MPTimeUnit } from './date.js';
|
|
3
3
|
import type { MPMessages } from './i18n.js';
|
|
4
4
|
import type { MPColor, MPSize, MPWeekday } from '../types.js';
|
|
5
5
|
/**
|
|
@@ -10,7 +10,15 @@ import type { MPColor, MPSize, MPWeekday } from '../types.js';
|
|
|
10
10
|
* calendars, so three components need this and none of them should have to
|
|
11
11
|
* import another. The two things it reaches *up* for are `MPButton` and
|
|
12
12
|
* `MPIconButton` — the header's steppers are buttons, they are not a new kind of
|
|
13
|
-
* control.
|
|
13
|
+
* control.
|
|
14
|
+
*
|
|
15
|
+
* Nothing here is exported from `src/index.ts` under its own name. `Calendar` is
|
|
16
|
+
* reachable from outside through `MPCalendar`, which is a wrapper rather than a
|
|
17
|
+
* re-export: everything below is fully controlled and takes its `labels` already
|
|
18
|
+
* resolved, because four callers had already decided those things. A consumer
|
|
19
|
+
* has not, so the public component is where the state and the translation are
|
|
20
|
+
* put back. That is also why the name went the other way round — the `MP` prefix
|
|
21
|
+
* belongs to what a consumer can import.
|
|
14
22
|
*
|
|
15
23
|
* The day cells are deliberately *not* buttons in that sense. A cell has states
|
|
16
24
|
* a button has no vocabulary for — inside a range, at the end of a range, today,
|
|
@@ -19,7 +27,7 @@ import type { MPColor, MPSize, MPWeekday } from '../types.js';
|
|
|
19
27
|
*/
|
|
20
28
|
/** The strings a picker says that `Intl` has no opinion about. */
|
|
21
29
|
export type MPPickerLabels = MPMessages['picker'];
|
|
22
|
-
export interface
|
|
30
|
+
export interface CalendarProps {
|
|
23
31
|
size: MPSize;
|
|
24
32
|
color: MPColor;
|
|
25
33
|
locale?: string;
|
|
@@ -54,6 +62,13 @@ export interface MPCalendarProps {
|
|
|
54
62
|
autoFocus?: boolean;
|
|
55
63
|
showPreviousButton?: boolean;
|
|
56
64
|
showNextButton?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* The finest view the calendar offers, and therefore what a press answers
|
|
67
|
+
* with. `'month'` never draws a day grid and `'year'` never draws either of
|
|
68
|
+
* the other two.
|
|
69
|
+
* @default 'day'
|
|
70
|
+
*/
|
|
71
|
+
precision?: MPCalendarView;
|
|
57
72
|
labels: MPPickerLabels;
|
|
58
73
|
}
|
|
59
74
|
/**
|
|
@@ -71,7 +86,7 @@ export interface MPCalendarProps {
|
|
|
71
86
|
* grid instead of walking forty-two cells — the pattern the ARIA date-picker
|
|
72
87
|
* practice describes, and the reason none of the cells is a `disabled` button.
|
|
73
88
|
*/
|
|
74
|
-
export declare function
|
|
89
|
+
export declare function Calendar({ size, color, locale, weekStartsOn, month, onMonthChange, selected, rangeStart, rangeEnd, onSelect, onPreviewChange, minDate, maxDate, shouldDisableDate, showOutsideDays, autoFocus, showPreviousButton, showNextButton, precision, labels }: CalendarProps): React.JSX.Element;
|
|
75
90
|
export interface MPTimeGridProps {
|
|
76
91
|
size: MPSize;
|
|
77
92
|
locale?: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import*as o from"react";import{MPButton as r}from"../components/button/MPButton.js";import{MPIcon as l}from"../components/icon/MPIcon.js";import{MPIconButton as a}from"../components/icon-button/MPIconButton.js";import{ChevronDownIcon as s,ChevronLeftIcon as c,ChevronRightIcon as i}from"../constants/icons.js";import{MPStateLayer as u}from"./StateLayer.js";import{CONTROL_ICON as m,META_TEXT as d,PROSE_TEXT as h}from"./scale.js";import{VISUALLY_HIDDEN as f}from"./visually-hidden.js";import{addDays as p,addMonths as g,addYears as v,calendarWeeks as y,compareDay as w,dateFormatter as x,daysInMonth as b,isDayOutside as D,isMonthBeforeYear as S,isSameDay as M,isSameMonth as N,isValidDate as P,makeDate as _,meridiemLabels as C,monthLabels as k,startOfDay as j,startOfMonth as z,today as F,weekdayLabels as A,withTime as E,YEAR_PAGE_SIZE as T,yearPageStart as Y}from"./date.js";const B={xs:"1.75rem",sm:"2rem",md:"2.5rem",lg:"2.75rem",xl:"3rem"},R={xs:"xs",sm:"xs",md:"sm",lg:"sm",xl:"md"},H=/*@__PURE__*/["group relative flex cursor-pointer items-center justify-center overflow-hidden","box-border appearance-none bg-transparent font-[inherit] tabular-nums select-none","transition-[background-color,border-color,color]","duration-(--mp-sys-motion-duration-short4)","outline-mp-secondary focus-visible:z-10 focus-visible:outline-2","focus-visible:outline-offset-[-2px] focus-visible:outline-solid outline-none"].join(" ");function $({children:n,label:o,selected:r,inRange:l=!1,rangeEdge:a=null,current:s=!1,muted:c=!1,disabled:i=!1,focused:m=!1,className:d,onClick:h,onPointerEnter:f,onKeyDown:p}){return t("button",{type:"button",role:"gridcell","aria-label":o,"aria-selected":r,"aria-current":s?"date":void 0,"aria-disabled":i||void 0,tabIndex:m?0:-1,"data-focus-target":m?"true":void 0,className:[H,"start"===a?"rounded-s-mp-full":"end"===a?"rounded-e-mp-full":"middle"===a?"rounded-none":"rounded-mp-full",i?"cursor-default text-mp-on-surface/38":r?"bg-(--_mp-accent) text-(--_mp-on-accent)":l?"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)":s?"border border-(--_mp-accent) text-(--_mp-accent)":c?"text-mp-on-surface-variant":"text-mp-on-surface",d??""].filter(Boolean).join(" "),onClick:()=>{i||h()},onPointerEnter:f,onKeyDown:p,children:[i?null:e(u,{}),n]})}function K({size:o,color:u,view:d,month:f,locale:p,labels:g,showPreviousButton:v,showNextButton:y,onStep:w,onViewChange:x}){const b=k(p,"long")[f.getMonth()],D=String(f.getFullYear()),M=S(p),N=R[o],P="day"===d?[g.previousMonth,g.nextMonth]:"month"===d?[g.previousYear,g.nextYear]:[g.previousYears,g.nextYears],_=(t,n)=>n?e(a,{size:N,color:u,label:P[-1===t?0:1],icon:e(l,{icon:-1===t?c:i,size:m[N],className:"rtl:rotate-180"}),onClick:()=>w(t)}):e("span",{"aria-hidden":"true",className:"size-(--_mp-cell)"}),C=t=>e(l,{icon:s,size:m[N],className:["transition-transform duration-(--mp-sys-motion-duration-short4)",t?"rotate-180":""].filter(Boolean).join(" ")}),j=e(r,{variant:"text",size:N,color:u,"aria-label":g.chooseMonth,"aria-expanded":"month"===d,endIcon:C("month"===d),onClick:()=>x("month"===d?"day":"month"),children:b},"month"),z=e(r,{variant:"text",size:N,color:u,className:"tabular-nums","aria-label":g.chooseYear,"aria-expanded":"year"===d,endIcon:C("year"===d),onClick:()=>x("year"===d?"day":"year"),children:D},"year"),F=Y(f.getFullYear());return t("div",{className:"flex items-center justify-between gap-1",children:[_(-1,v),e("div",{className:"flex min-w-0 flex-1 items-center justify-center gap-1",children:"year"===d?e("span",{className:`text-mp-on-surface flex h-(--_mp-cell) items-center tabular-nums ${h[o]}`,children:`${F}–${F+T-1}`}):"month"===d?z:t(n,M?{children:[j,z]}:{children:[z,j]})}),_(1,y)]})}export function MPCalendar({size:n,color:r,locale:l,weekStartsOn:a,month:s,onMonthChange:c,selected:i,rangeStart:u=null,rangeEnd:m=null,onSelect:d,onPreviewChange:h,minDate:f,maxDate:p,shouldDisableDate:y,showOutsideDays:w=!0,autoFocus:x=!1,showPreviousButton:b=!0,showNextButton:S=!0,labels:M}){const[C,k]=o.useState("day"),A=o.useMemo(()=>i.filter(P),[i]),[E,Y]=o.useState(()=>{const e=A.find(e=>N(e,s));return e?j(e):N(F(),s)?F():z(s)}),R=o.useRef(x),H=o.useRef(null);o.useEffect(()=>{Y(e=>N(e,s)?e:z(s))},[s]),o.useLayoutEffect(()=>{R.current&&(R.current=!1,H.current?.querySelector('[data-focus-target="true"]')?.focus({preventScroll:!0}))});const $=o.useCallback(e=>D(e,f,p)||(y?.(e)??!1),[f,p,y]),L=e=>{R.current=!0,k(e)},q=e=>{R.current=!0,c(e)};return t("div",{ref:H,className:"mp-calendar flex flex-col gap-1",style:{"--_mp-cell":B[n]},onPointerLeave:()=>h?.(null),children:[e(K,{size:n,color:r,view:C,month:s,locale:l,labels:M,showPreviousButton:b,showNextButton:S,onStep:e=>{c("day"===C?g(s,e):v(s,"month"===C?e:e*T))},onViewChange:L}),e("div",{className:"h-[calc(var(--_mp-cell)*7)] w-[calc(var(--_mp-cell)*7)]",children:"day"===C?e(U,{size:n,locale:l,weekStartsOn:a,month:s,chosen:A,rangeStart:u,rangeEnd:m,focusedDate:E,showOutsideDays:w,isDisabled:$,onSelect:e=>{Y(e),d(e)},onPreviewChange:h,onMoveFocus:e=>{R.current=!0,Y(e),N(e,s)||c(z(e))}}):"month"===C?e(I,{size:n,locale:l,month:s,chosen:A,minDate:f,maxDate:p,onMoveCursor:q,onPick:e=>{c(_(s.getFullYear(),e,1)),L("day")}}):e(O,{size:n,month:s,chosen:A,minDate:f,maxDate:p,onMoveCursor:q,onPick:e=>{c(_(e,s.getMonth(),1)),L("month")}})})]})}function L(e){return"rtl"===getComputedStyle(e).direction?-1:1}function U({size:n,locale:r,weekStartsOn:l,month:a,chosen:s,rangeStart:c,rangeEnd:i,focusedDate:u,showOutsideDays:m,isDisabled:f,onSelect:v,onPreviewChange:b,onMoveFocus:D}){const S=A(r,l,"narrow"),_=A(r,l,"long"),C=(j=i,P(k=c)&&P(j)?w(k,j)<=0?[k,j]:[j,k]:null);var k,j;const z=F(),E=o.useMemo(()=>{const e=x(r,{dateStyle:"full"});return y(a,l).map(t=>t.map(t=>({date:t,label:e.format(t)})))},[a,l,r]),T=o.useRef(null),Y=o.useRef(a);o.useLayoutEffect(()=>{const e=T.current,t=Y.current;if(Y.current=a,!e||N(t,a))return;const n=t.getTime()<a.getTime(),o="rtl"===getComputedStyle(e).direction;e.style.setProperty("--_mp-calendar-from",String(n===o?-1:1)),e.dataset.mpPaged="true",e.style.animationName="none",e.offsetWidth,e.style.animationName=""},[a]);return t("div",{role:"grid","aria-label":x(r,{year:"numeric",month:"long"}).format(a),className:"flex h-full flex-col",children:[e("div",{role:"rowgroup",children:e("div",{role:"row",className:"grid grid-cols-7",children:S.map((t,n)=>e("span",{role:"columnheader","aria-label":_[n],className:`text-mp-on-surface-variant flex h-(--_mp-cell) items-center justify-center select-none ${d}`,children:t},n))})}),e("div",{ref:T,role:"rowgroup",className:"mp-calendar__page flex flex-1 flex-col",children:E.map((t,o)=>e("div",{role:"row",className:"grid grid-cols-7",children:t.map(({date:t,label:o})=>{const r=!N(t,a);if(r&&!m)return e("span",{role:"gridcell","aria-hidden":"true",className:"size-(--_mp-cell)"},t.getTime());const c=s.some(e=>M(e,t)),i=null!==C&&w(t,C[0])>=0&&w(t,C[1])<=0,d=null!==C&&i&&M(t,C[0]),y=null!==C&&i&&M(t,C[1]);return e($,{label:o,selected:c,inRange:i&&!c,rangeEdge:i?d&&y?"both":d?"start":y?"end":"middle":null,current:M(t,z)&&!c,muted:r,disabled:f(t),focused:M(t,u),className:`size-(--_mp-cell) ${h[n]}`,onClick:()=>v(t),onPointerEnter:()=>b?.(t),onKeyDown:e=>((e,t)=>{const n=(t.getDay()-l+7)%7,o=L(e.currentTarget),r={ArrowLeft:()=>p(t,-o),ArrowRight:()=>p(t,o),ArrowUp:()=>p(t,-7),ArrowDown:()=>p(t,7),Home:()=>p(t,-n),End:()=>p(t,6-n),PageUp:()=>g(t,e.shiftKey?-12:-1),PageDown:()=>g(t,e.shiftKey?12:1)}[e.key];r&&(e.preventDefault(),D(r()))})(e,t),children:t.getDate()},t.getTime())})},o))})]})}function I({size:t,locale:n,month:o,chosen:r,minDate:l,maxDate:a,onMoveCursor:s,onPick:c}){const i=k(n,"short"),u=k(n,"long"),m=o.getFullYear(),d=new Date,f=e=>{const t=L(e.currentTarget),n={ArrowLeft:-t,ArrowRight:t,ArrowUp:-3,ArrowDown:3,PageUp:-12,PageDown:12}[e.key];void 0!==n&&(e.preventDefault(),s(g(z(o),n)))};return e("div",{role:"grid",className:"flex h-full flex-col justify-evenly",children:[0,1,2,3].map(n=>e("div",{role:"row",className:"grid grid-cols-3 gap-1",children:[0,1,2].map(s=>{const p=3*n+s,g=_(m,p,1),v=_(m,p,b(m,p));return e($,{label:`${u[p]} ${m}`,selected:r.some(e=>e.getFullYear()===m&&e.getMonth()===p),current:d.getFullYear()===m&&d.getMonth()===p,disabled:P(l)&&w(v,l)<0||P(a)&&w(g,a)>0,focused:p===o.getMonth(),className:`h-(--_mp-cell) w-full ${h[t]}`,onClick:()=>c(p),onKeyDown:f,children:i[p]},p)})},n))})}function O({size:t,month:n,chosen:o,minDate:r,maxDate:l,onMoveCursor:a,onPick:s}){const c=Y(n.getFullYear()),i=(new Date).getFullYear(),u=e=>{const t=L(e.currentTarget),o={ArrowLeft:-t,ArrowRight:t,ArrowUp:-4,ArrowDown:4,PageUp:-T,PageDown:T}[e.key];void 0!==o&&(e.preventDefault(),a(v(z(n),o)))};return e("div",{role:"grid",className:"flex h-full flex-col justify-evenly",children:[0,1,2].map(a=>e("div",{role:"row",className:"grid grid-cols-4 gap-1",children:[0,1,2,3].map(m=>{const d=c+4*a+m;return e($,{label:String(d),selected:o.some(e=>e.getFullYear()===d),current:d===i,disabled:P(r)&&d<r.getFullYear()||P(l)&&d>l.getFullYear(),focused:d===n.getFullYear(),className:`h-(--_mp-cell) w-full ${h[t]}`,onClick:()=>s(d),onKeyDown:u,children:d},d)})},a))})}function q(e,t){return Number.isFinite(e)?Math.min(t,Math.max(1,Math.round(e))):1}function V(e){const t=e.parentElement;if(!t)return;const n=e.getBoundingClientRect(),o=t.getBoundingClientRect(),r=n.top-o.top-t.clientTop+t.scrollTop,l=r+n.height;r<t.scrollTop?t.scrollTop=r:l>t.scrollTop+t.clientHeight&&(t.scrollTop=l-t.clientHeight)}export function MPTimeGrid({size:n,locale:r,value:l,referenceDate:a,onChange:s,hour12:c,showSeconds:i,hourStep:m,minuteStep:d,secondStep:p,shouldDisableTime:g,autoFocus:v=!1,labels:y}){const w=l??a,b=o.useRef(null),[D,S]=o.useMemo(()=>C(r),[r]);o.useEffect(()=>{const e=b.current;if(e?.querySelectorAll('[data-chosen="true"]').forEach(V),v){const t=e?.querySelector('[role="listbox"]');(t?.querySelector('[data-chosen="true"]')??t?.querySelector('[role="option"]'))?.focus({preventScroll:!0})}},[v]);const M=o.useMemo(()=>{const e=c?12:24,t=q(m,e),n=Array.from({length:Math.ceil(e/t)},(e,n)=>n*t);return c?n.map(e=>0===e?12:e):n},[c,m]),N=o.useMemo(()=>{const e=q(d,60);return Array.from({length:Math.ceil(60/e)},(t,n)=>n*e)},[d]),P=o.useMemo(()=>{const e=q(p,60);return Array.from({length:Math.ceil(60/e)},(t,n)=>n*e)},[p]),_=e=>String(e).padStart(2,"0"),k=c?w.getHours()%12||12:w.getHours(),[j,z]=o.useState({}),F=(o,r,a,i,m)=>{const d=null===l?-1:a.findIndex(e=>i(e)),f=j[o]??(d>=0?d:0);return e("div",{role:"listbox","aria-label":r,className:["mp-time-grid__column flex flex-col gap-0.5 overflow-y-auto overscroll-contain","h-[calc(var(--_mp-cell)*7)] w-[calc(var(--_mp-cell)*1.75)]","scroll-py-0.5 [scrollbar-width:thin]"].join(" "),onKeyDown:e=>{const t={ArrowDown:1,ArrowUp:-1,PageDown:5,PageUp:-5}[e.key],n=void 0!==t?(e=>{const t=[...e.children].indexOf(document.activeElement);return t>=0?t:f})(e.currentTarget)+t:"Home"===e.key?0:"End"===e.key?a.length-1:null;null!==n&&(e.preventDefault(),((e,t)=>{const n=Math.min(a.length-1,Math.max(0,e)),r=t.children[n];z(e=>({...e,[o]:n})),r instanceof HTMLElement&&(r.focus({preventScroll:!0}),V(r))})(n,e.currentTarget))},children:a.map((r,a)=>{const d=((e,t)=>E(w,"hour"===e?{hours:c?t%12+(w.getHours()>=12?12:0):t}:"minute"===e?{minutes:t}:"second"===e?{seconds:t}:{hours:w.getHours()%12+12*t}))(o,r),p=null!==l&&i(r),v=g?.(d,o)??!1;return t("button",{type:"button",role:"option","aria-selected":p,"aria-disabled":v||void 0,"data-chosen":p?"true":void 0,tabIndex:a===f?0:-1,className:[H,"rounded-mp-full h-(--_mp-cell) w-full shrink-0",h[n],v?"cursor-default text-mp-on-surface/38":p?"bg-(--_mp-accent) text-(--_mp-on-accent)":"text-mp-on-surface"].join(" "),onFocus:()=>z(e=>({...e,[o]:a})),onClick:()=>{v||s(d)},children:[v?null:e(u,{}),m(r)]},r)})},o)};return t("div",{ref:b,className:"mp-time-grid flex gap-1",style:{"--_mp-cell":B[n]},children:[F("hour",y.hour,M,e=>e===k,e=>c?String(e):_(e)),F("minute",y.minute,N,e=>e===w.getMinutes(),_),i?F("second",y.second,P,e=>e===w.getSeconds(),_):null,c?F("meridiem",y.meridiem,[0,1],e=>(w.getHours()>=12?1:0)===e,e=>0===e?D:S):null,e("span",{className:f,"aria-live":"polite",children:null===l?"":x(r,{hour:"numeric",minute:"2-digit",...i?{second:"2-digit"}:{}}).format(l)})]})}
|
|
2
|
+
import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import*as o from"react";import{MPButton as r}from"../components/button/MPButton.js";import{MPIcon as l}from"../components/icon/MPIcon.js";import{MPIconButton as a}from"../components/icon-button/MPIconButton.js";import{ChevronDownIcon as s,ChevronLeftIcon as c,ChevronRightIcon as i}from"../constants/icons.js";import{MPStateLayer as u}from"./StateLayer.js";import{CONTROL_ICON as m,META_TEXT as d,PROSE_TEXT as h}from"./scale.js";import{VISUALLY_HIDDEN as p}from"./visually-hidden.js";import{addDays as f,addMonths as g,addYears as y,calendarWeeks as v,compareDay as w,dateFormatter as x,isDayOutside as b,isMonthBeforeYear as D,isSameDay as S,isSameMonth as M,isUnitOutside as N,isValidDate as P,makeDate as _,meridiemLabels as C,monthLabels as k,startOfDay as j,startOfMonth as z,today as A,weekdayLabels as E,withTime as T,YEAR_PAGE_SIZE as F,yearPageStart as Y}from"./date.js";const B={xs:"1.75rem",sm:"2rem",md:"2.5rem",lg:"2.75rem",xl:"3rem"},R={xs:"xs",sm:"xs",md:"sm",lg:"sm",xl:"md"},H=/*@__PURE__*/["group relative flex cursor-pointer items-center justify-center overflow-hidden","box-border appearance-none font-[inherit] tabular-nums select-none","transition-[background-color,border-color,color]","duration-(--mp-sys-motion-duration-short4)","outline-mp-secondary focus-visible:z-10 focus-visible:outline-2","focus-visible:outline-offset-[-2px] focus-visible:outline-solid outline-none"].join(" "),$={day:0,month:1,year:2};function K({children:n,label:o,selected:r,inRange:l=!1,rangeEdge:a=null,current:s=!1,muted:c=!1,disabled:i=!1,focused:m=!1,className:d,onClick:h,onPointerEnter:p,onKeyDown:f}){return t("button",{type:"button",role:"gridcell","aria-label":o,"aria-selected":r,"aria-current":s?"date":void 0,"aria-disabled":i||void 0,tabIndex:m?0:-1,"data-focus-target":m?"true":void 0,className:[H,"start"===a?"rounded-s-mp-full":"end"===a?"rounded-e-mp-full":"middle"===a?"rounded-none":"rounded-mp-full",i?"bg-transparent cursor-default text-mp-on-surface/38":r?"bg-(--_mp-accent) text-(--_mp-on-accent)":l?"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)":s?"bg-transparent border border-(--_mp-accent) text-(--_mp-accent)":c?"bg-transparent text-mp-on-surface-variant":"bg-transparent text-mp-on-surface",d??""].filter(Boolean).join(" "),onClick:()=>{i||h()},onPointerEnter:p,onKeyDown:f,children:[i?null:e(u,{}),n]})}function L({size:o,color:u,view:d,month:p,locale:f,labels:g,showPreviousButton:y,showNextButton:v,onStep:w,onViewChange:x}){const b=k(f,"long")[p.getMonth()],S=String(p.getFullYear()),M=D(f),N=R[o],P="day"===d?[g.previousMonth,g.nextMonth]:"month"===d?[g.previousYear,g.nextYear]:[g.previousYears,g.nextYears],_=(t,n)=>n?e(a,{size:N,color:u,label:P[-1===t?0:1],icon:e(l,{icon:-1===t?c:i,size:m[N],className:"rtl:rotate-180"}),onClick:()=>w(t)}):e("span",{"aria-hidden":"true",className:"size-(--_mp-cell)"}),C=t=>e(l,{icon:s,size:m[N],className:["transition-transform duration-(--mp-sys-motion-duration-short4)",t?"rotate-180":""].filter(Boolean).join(" ")}),j=e(r,{variant:"text",size:N,color:u,"aria-label":g.chooseMonth,"aria-expanded":"month"===d,endIcon:C("month"===d),onClick:()=>x("month"===d?"day":"month"),children:b},"month"),z=e(r,{variant:"text",size:N,color:u,className:"tabular-nums","aria-label":g.chooseYear,"aria-expanded":"year"===d,endIcon:C("year"===d),onClick:()=>x("year"===d?"day":"year"),children:S},"year"),A=Y(p.getFullYear());return t("div",{className:"flex items-center justify-between gap-1",children:[_(-1,y),e("div",{className:"flex min-w-0 flex-1 items-center justify-center gap-1",children:"year"===d?e("span",{className:`text-mp-on-surface flex h-(--_mp-cell) items-center tabular-nums ${h[o]}`,children:`${A}–${A+F-1}`}):"month"===d?z:t(n,M?{children:[j,z]}:{children:[z,j]})}),_(1,v)]})}export function Calendar({size:n,color:r,locale:l,weekStartsOn:a,month:s,onMonthChange:c,selected:i,rangeStart:u=null,rangeEnd:m=null,onSelect:d,onPreviewChange:h,minDate:p,maxDate:f,shouldDisableDate:v,showOutsideDays:w=!0,autoFocus:x=!1,showPreviousButton:D=!0,showNextButton:S=!0,precision:N="day",labels:C}){const[k,E]=o.useState(N),T=$[k]<$[N]?N:k,Y=o.useMemo(()=>i.filter(P),[i]),[R,H]=o.useState(()=>{const e=Y.find(e=>M(e,s));return e?j(e):M(A(),s)?A():z(s)}),K=o.useRef(x),U=o.useRef(null);o.useEffect(()=>{H(e=>M(e,s)?e:z(s))},[s]),o.useLayoutEffect(()=>{K.current&&(K.current=!1,U.current?.querySelector('[data-focus-target="true"]')?.focus({preventScroll:!0}))});const V=o.useCallback(e=>b(e,p,f)||(v?.(e)??!1),[p,f,v]),G=e=>{K.current=!0,E(e)},W=e=>{K.current=!0,c(e)};return t("div",{ref:U,className:"mp-calendar flex flex-col gap-1",style:{"--_mp-cell":B[n]},onPointerLeave:()=>h?.(null),children:[e(L,{size:n,color:r,view:T,month:s,locale:l,labels:C,showPreviousButton:D,showNextButton:S,onStep:e=>{c("day"===T?g(s,e):y(s,"month"===T?e:e*F))},onViewChange:G}),e("div",{className:"h-[calc(var(--_mp-cell)*7)] w-[calc(var(--_mp-cell)*7)]",children:"day"===T?e(I,{size:n,locale:l,weekStartsOn:a,month:s,chosen:Y,rangeStart:u,rangeEnd:m,focusedDate:R,showOutsideDays:w,isDisabled:V,onSelect:e=>{H(e),d(e)},onPreviewChange:h,onMoveFocus:e=>{K.current=!0,H(e),M(e,s)||c(z(e))}}):"month"===T?e(O,{size:n,locale:l,month:s,chosen:Y,minDate:p,maxDate:f,onMoveCursor:W,onPick:e=>{const t=_(s.getFullYear(),e,1);"month"!==N?(c(t),G("day")):d(t)}}):e(q,{size:n,month:s,chosen:Y,minDate:p,maxDate:f,onMoveCursor:W,onPick:e=>{"year"!==N?(c(_(e,s.getMonth(),1)),G("month")):d(_(e,0,1))}})})]})}function U(e){return"rtl"===getComputedStyle(e).direction?-1:1}function I({size:n,locale:r,weekStartsOn:l,month:a,chosen:s,rangeStart:c,rangeEnd:i,focusedDate:u,showOutsideDays:m,isDisabled:p,onSelect:y,onPreviewChange:b,onMoveFocus:D}){const N=E(r,l,"narrow"),_=E(r,l,"long"),C=(j=i,P(k=c)&&P(j)?w(k,j)<=0?[k,j]:[j,k]:null);var k,j;const z=A(),T=o.useMemo(()=>{const e=x(r,{dateStyle:"full"});return v(a,l).map(t=>t.map(t=>({date:t,label:e.format(t)})))},[a,l,r]),F=o.useRef(null),Y=o.useRef(a);o.useLayoutEffect(()=>{const e=F.current,t=Y.current;if(Y.current=a,!e||M(t,a))return;const n=t.getTime()<a.getTime(),o="rtl"===getComputedStyle(e).direction;e.style.setProperty("--_mp-calendar-from",String(n===o?-1:1)),e.dataset.mpPaged="true",e.style.animationName="none",e.offsetWidth,e.style.animationName=""},[a]);return t("div",{role:"grid","aria-label":x(r,{year:"numeric",month:"long"}).format(a),className:"flex h-full flex-col",children:[e("div",{role:"rowgroup",children:e("div",{role:"row",className:"grid grid-cols-7",children:N.map((t,n)=>e("span",{role:"columnheader","aria-label":_[n],className:`text-mp-on-surface-variant flex h-(--_mp-cell) items-center justify-center select-none ${d}`,children:t},n))})}),e("div",{ref:F,role:"rowgroup",className:"mp-calendar__page flex flex-1 flex-col",children:T.map((t,o)=>e("div",{role:"row",className:"grid grid-cols-7",children:t.map(({date:t,label:o})=>{const r=!M(t,a);if(r&&!m)return e("span",{role:"gridcell","aria-hidden":"true",className:"size-(--_mp-cell)"},t.getTime());const c=s.some(e=>S(e,t)),i=null!==C&&w(t,C[0])>=0&&w(t,C[1])<=0,d=null!==C&&i&&S(t,C[0]),v=null!==C&&i&&S(t,C[1]);return e(K,{label:o,selected:c,inRange:i&&!c,rangeEdge:i?d&&v?"both":d?"start":v?"end":"middle":null,current:S(t,z)&&!c,muted:r,disabled:p(t),focused:S(t,u),className:`size-(--_mp-cell) ${h[n]}`,onClick:()=>y(t),onPointerEnter:()=>b?.(t),onKeyDown:e=>((e,t)=>{const n=(t.getDay()-l+7)%7,o=U(e.currentTarget),r={ArrowLeft:()=>f(t,-o),ArrowRight:()=>f(t,o),ArrowUp:()=>f(t,-7),ArrowDown:()=>f(t,7),Home:()=>f(t,-n),End:()=>f(t,6-n),PageUp:()=>g(t,e.shiftKey?-12:-1),PageDown:()=>g(t,e.shiftKey?12:1)}[e.key];r&&(e.preventDefault(),D(r()))})(e,t),children:t.getDate()},t.getTime())})},o))})]})}function O({size:t,locale:n,month:r,chosen:l,minDate:a,maxDate:s,onMoveCursor:c,onPick:i}){const u=k(n,"short"),m=r.getFullYear(),d=new Date,p=o.useMemo(()=>{const e=x(n,{year:"numeric",month:"long"});return Array.from({length:12},(t,n)=>e.format(_(m,n,1)))},[n,m]),f=e=>{const t=U(e.currentTarget),n={ArrowLeft:-t,ArrowRight:t,ArrowUp:-3,ArrowDown:3,PageUp:-12,PageDown:12}[e.key];void 0!==n&&(e.preventDefault(),c(g(z(r),n)))};return e("div",{role:"grid","aria-label":String(m),className:"flex h-full flex-col justify-evenly",children:[0,1,2,3].map(n=>e("div",{role:"row",className:"grid grid-cols-3 gap-1",children:[0,1,2].map(o=>{const c=3*n+o;return e(K,{label:p[c],selected:l.some(e=>e.getFullYear()===m&&e.getMonth()===c),current:d.getFullYear()===m&&d.getMonth()===c,disabled:N(_(m,c,1),"month",a,s),focused:c===r.getMonth(),className:`h-(--_mp-cell) w-full ${h[t]}`,onClick:()=>i(c),onKeyDown:f,children:u[c]},c)})},n))})}function q({size:t,month:n,chosen:o,minDate:r,maxDate:l,onMoveCursor:a,onPick:s}){const c=Y(n.getFullYear()),i=(new Date).getFullYear(),u=e=>{const t=U(e.currentTarget),o={ArrowLeft:-t,ArrowRight:t,ArrowUp:-4,ArrowDown:4,PageUp:-F,PageDown:F}[e.key];void 0!==o&&(e.preventDefault(),a(y(z(n),o)))};return e("div",{role:"grid","aria-label":`${c}–${c+F-1}`,className:"flex h-full flex-col justify-evenly",children:[0,1,2].map(a=>e("div",{role:"row",className:"grid grid-cols-4 gap-1",children:[0,1,2,3].map(m=>{const d=c+4*a+m;return e(K,{label:String(d),selected:o.some(e=>e.getFullYear()===d),current:d===i,disabled:N(_(d,0,1),"year",r,l),focused:d===n.getFullYear(),className:`h-(--_mp-cell) w-full ${h[t]}`,onClick:()=>s(d),onKeyDown:u,children:d},d)})},a))})}function V(e,t){return Number.isFinite(e)?Math.min(t,Math.max(1,Math.round(e))):1}function G(e){const t=e.parentElement;if(!t)return;const n=e.getBoundingClientRect(),o=t.getBoundingClientRect(),r=n.top-o.top-t.clientTop+t.scrollTop,l=r+n.height;r<t.scrollTop?t.scrollTop=r:l>t.scrollTop+t.clientHeight&&(t.scrollTop=l-t.clientHeight)}export function MPTimeGrid({size:n,locale:r,value:l,referenceDate:a,onChange:s,hour12:c,showSeconds:i,hourStep:m,minuteStep:d,secondStep:f,shouldDisableTime:g,autoFocus:y=!1,labels:v}){const w=l??a,b=o.useRef(null),[D,S]=o.useMemo(()=>C(r),[r]);o.useEffect(()=>{const e=b.current;if(e?.querySelectorAll('[data-chosen="true"]').forEach(G),y){const t=e?.querySelector('[role="listbox"]');(t?.querySelector('[data-chosen="true"]')??t?.querySelector('[role="option"]'))?.focus({preventScroll:!0})}},[y]);const M=o.useMemo(()=>{const e=c?12:24,t=V(m,e),n=Array.from({length:Math.ceil(e/t)},(e,n)=>n*t);return c?n.map(e=>0===e?12:e):n},[c,m]),N=o.useMemo(()=>{const e=V(d,60);return Array.from({length:Math.ceil(60/e)},(t,n)=>n*e)},[d]),P=o.useMemo(()=>{const e=V(f,60);return Array.from({length:Math.ceil(60/e)},(t,n)=>n*e)},[f]),_=e=>String(e).padStart(2,"0"),k=c?w.getHours()%12||12:w.getHours(),[j,z]=o.useState({}),A=(o,r,a,i,m)=>{const d=null===l?-1:a.findIndex(e=>i(e)),p=j[o]??(d>=0?d:0);return e("div",{role:"listbox","aria-label":r,className:["mp-time-grid__column flex flex-col gap-0.5 overflow-y-auto overscroll-contain","h-[calc(var(--_mp-cell)*7)] w-[calc(var(--_mp-cell)*1.75)]","scroll-py-0.5 [scrollbar-width:thin]"].join(" "),onKeyDown:e=>{const t={ArrowDown:1,ArrowUp:-1,PageDown:5,PageUp:-5}[e.key],n=void 0!==t?(e=>{const t=[...e.children].indexOf(document.activeElement);return t>=0?t:p})(e.currentTarget)+t:"Home"===e.key?0:"End"===e.key?a.length-1:null;null!==n&&(e.preventDefault(),((e,t)=>{const n=Math.min(a.length-1,Math.max(0,e)),r=t.children[n];z(e=>({...e,[o]:n})),r instanceof HTMLElement&&(r.focus({preventScroll:!0}),G(r))})(n,e.currentTarget))},children:a.map((r,a)=>{const d=((e,t)=>T(w,"hour"===e?{hours:c?t%12+(w.getHours()>=12?12:0):t}:"minute"===e?{minutes:t}:"second"===e?{seconds:t}:{hours:w.getHours()%12+12*t}))(o,r),f=null!==l&&i(r),y=g?.(d,o)??!1;return t("button",{type:"button",role:"option","aria-selected":f,"aria-disabled":y||void 0,"data-chosen":f?"true":void 0,tabIndex:a===p?0:-1,className:[H,"rounded-mp-full h-(--_mp-cell) w-full shrink-0",h[n],y?"bg-transparent cursor-default text-mp-on-surface/38":f?"bg-(--_mp-accent) text-(--_mp-on-accent)":"bg-transparent text-mp-on-surface"].join(" "),onFocus:()=>z(e=>({...e,[o]:a})),onClick:()=>{y||s(d)},children:[y?null:e(u,{}),m(r)]},r)})},o)};return t("div",{ref:b,className:"mp-time-grid flex gap-1",style:{"--_mp-cell":B[n]},children:[A("hour",v.hour,M,e=>e===k,e=>c?String(e):_(e)),A("minute",v.minute,N,e=>e===w.getMinutes(),_),i?A("second",v.second,P,e=>e===w.getSeconds(),_):null,c?A("meridiem",v.meridiem,[0,1],e=>(w.getHours()>=12?1:0)===e,e=>0===e?D:S):null,e("span",{className:p,"aria-live":"polite",children:null===l?"":x(r,{hour:"numeric",minute:"2-digit",...i?{second:"2-digit"}:{}}).format(l)})]})}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { MPPickerLabels } from './Calendar.js';
|
|
3
|
-
import type { MPColor, MPSize, MPStyleProps } from '../types.js';
|
|
3
|
+
import type { MPColor, MPControlEventProps, MPSize, MPStyleProps } from '../types.js';
|
|
4
4
|
/**
|
|
5
5
|
* The strings a trigger is held open by, kept across renders that did not
|
|
6
6
|
* change what it could say.
|
|
@@ -25,6 +25,18 @@ import type { MPColor, MPSize, MPStyleProps } from '../types.js';
|
|
|
25
25
|
* never a wrong answer.
|
|
26
26
|
*/
|
|
27
27
|
export declare function useDisplaySamples(locale: string | undefined, options: Intl.DateTimeFormatOptions): string[];
|
|
28
|
+
/**
|
|
29
|
+
* The popup's room, one track tighter than a control's.
|
|
30
|
+
*
|
|
31
|
+
* A calendar is already a grid of forty-two padded cells; giving the sheet
|
|
32
|
+
* around it a control's 16px as well would put 24px of nothing between the last
|
|
33
|
+
* column and the edge.
|
|
34
|
+
*
|
|
35
|
+
* Exported because `MPCalendar` draws the same grid on a surface of its own, and
|
|
36
|
+
* a standalone calendar sitting one track wider than the identical calendar in a
|
|
37
|
+
* picker's popup is the drift a shared table exists to prevent.
|
|
38
|
+
*/
|
|
39
|
+
export declare const POPUP_PAD: Record<MPSize, string>;
|
|
28
40
|
/**
|
|
29
41
|
* The props a picker takes from its shell rather than inventing.
|
|
30
42
|
*
|
|
@@ -32,7 +44,7 @@ export declare function useDisplaySamples(locale: string | undefined, options: I
|
|
|
32
44
|
* the rows a reader of the docs is actually looking at — every one of the four
|
|
33
45
|
* pickers lists them, and they mean the same thing on all four.
|
|
34
46
|
*/
|
|
35
|
-
export interface MPPickerShellProps extends MPStyleProps {
|
|
47
|
+
export interface MPPickerShellProps extends MPStyleProps, MPControlEventProps<HTMLButtonElement> {
|
|
36
48
|
/**
|
|
37
49
|
* Which accent family the popup reads: the chosen day's fill, the band across
|
|
38
50
|
* a range, today's outline, the footer's confirm button.
|
|
@@ -130,7 +142,7 @@ interface InternalShellProps extends MPPickerShellProps {
|
|
|
130
142
|
* treatment, and the popup's `surface-container` at elevation 2 — which is the
|
|
131
143
|
* same floating sheet a menu and a select's list are drawn on.
|
|
132
144
|
*/
|
|
133
|
-
export declare function MPPickerShell({ slug, size, color, fullWidth, label, floatingLabel, description, errorMessage, startIcon, required, disabled, readOnly, id, className, style, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, children, triggerRef }: InternalShellProps): React.JSX.Element;
|
|
145
|
+
export declare function MPPickerShell({ slug, size, color, fullWidth, label, floatingLabel, description, errorMessage, startIcon, required, disabled, readOnly, id, className, style, onKeyDown, onKeyUp, onFocus, onBlur, onClick, onDoubleClick, onContextMenu, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, children, triggerRef }: InternalShellProps): React.JSX.Element;
|
|
134
146
|
/**
|
|
135
147
|
* The row of shortcuts under a picker's panel.
|
|
136
148
|
*
|
package/dist/internal/Picker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{jsx as e,jsxs as
|
|
2
|
+
import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{Field as r}from"@base-ui/react/field";import{Popover as i}from"@base-ui/react/popover";import{MPIcon as t}from"../components/icon/MPIcon.js";import{CloseIcon as l}from"../constants/icons.js";import{accentSlots as s}from"./accent.js";import{MPFieldLabel as a,MPFieldOutline as p,useFloatingLabel as c}from"./FieldOutline.js";import{MPStateLayer as u}from"./StateLayer.js";import{MPSupportingText as m}from"./SupportingText.js";import{MPWidthSizer as d}from"./WidthSizer.js";import{displaySamples as f}from"./date.js";import{CONTROL_ICON as h,hasContent as x,PROSE_TEXT as g}from"./scale.js";import{FADE as b,PORTAL_LAYER as y}from"./surface.js";export function useDisplaySamples(e,n){const r=`${e??""} ${JSON.stringify(n)}`;return o.useMemo(()=>f(e,n),[r])}const j={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"}};export const POPUP_PAD={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function MPPickerShell({slug:f,size:v="md",color:P="primary",fullWidth:N=!1,label:k,floatingLabel:w=!0,description:C,errorMessage:O,startIcon:M,required:D=!1,disabled:F=!1,readOnly:S=!1,id:z,className:B,style:_,onKeyDown:I,onKeyUp:K,onFocus:R,onBlur:U,onClick:$,onDoubleClick:q,onContextMenu:T,display:A,samples:E,empty:L,clearable:W=!1,onClear:J,open:V,onOpenChange:Z,labels:G,hiddenValues:H,children:Q,triggerRef:X}){const Y=x(O),ee=j[v],ne=o.useId(),oe=z??ne,re=W&&!L&&!(F||S),{shrunk:ie,focusProps:te}=c({floating:w&&x(k),filled:!L,pinned:V||x(M)});return n(r.Root,{disabled:F,invalid:Y,"data-mp-size":v,className:[`mp-${f} group flex-col align-top`,N?"flex w-full":"inline-flex w-fit",B??""].filter(Boolean).join(" "),style:{...s(P),..._},...te,children:[n(i.Root,{open:V,onOpenChange:Z,children:[n("div",{className:"relative w-full",children:[n(i.Trigger,{id:oe,ref:X,disabled:F,nativeButton:!0,onKeyDown:I,onKeyUp:K,onFocus:R,onBlur:U,onClick:$,onDoubleClick:q,onContextMenu:T,className:["relative flex w-full items-center gap-2 select-none","appearance-none bg-transparent font-[inherit] outline-none",ee.padding,re?"pe-10":"",ee.height,g[v],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,n("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:["w-full truncate text-start",L&&!F?"text-mp-on-surface-variant":""].filter(Boolean).join(" "),children:L&&!ie?null:A}),e(d,{samples:E??[]})]})]}),re?n("button",{type:"button","aria-label":G.clear,onClick:J,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(u,{className:"group-hover/clear:opacity-8 group-focus-visible/clear:opacity-10"}),e(t,{icon:l,size:h[v]})]}):null,e(p,{label:k,required:D,notched:ie}),x(k)?e(a,{size:v,label:k,required:D,htmlFor:oe,shrunk:ie}):null]}),e(i.Portal,{children:e(i.Positioner,{className:y,sideOffset:4,align:"start",children:e(i.Popup,{initialFocus:!1,style:s(P),className:[`mp-${f}__popup rounded-mp-md shadow-mp-2 bg-mp-surface-container`,"text-mp-on-surface outline-none",POPUP_PAD[v],g[v],b].join(" "),children:Q})})})]}),e(m,{description:C,errorMessage:O,className:ee.padding}),H?.map((n,o)=>e("input",{type:"hidden",name:n.name,value:n.value},o))]})}export function MPPickerFooter({children:n}){return e("div",{className:"border-mp-outline-variant flex items-center justify-end gap-1 border-t pt-1.5",children:n})}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,28 @@
|
|
|
1
|
+
/** What a page can be set to. `'system'` is the absence of a choice. */
|
|
2
|
+
export type MPColorScheme = 'light' | 'dark' | 'system';
|
|
3
|
+
/** What is actually painted, once `'system'` has been resolved. */
|
|
4
|
+
export type MPResolvedColorScheme = 'light' | 'dark';
|
|
5
|
+
export declare const SCHEME_ATTRIBUTE = "data-mp-scheme";
|
|
6
|
+
export declare const DEFAULT_STORAGE_KEY = "mp-color-scheme";
|
|
7
|
+
/**
|
|
8
|
+
* Puts the choice on the document element, or takes it off.
|
|
9
|
+
*
|
|
10
|
+
* `'system'` **removes** the attribute rather than writing it, which is the
|
|
11
|
+
* whole of how the media query gets its say back: the dark block is reached
|
|
12
|
+
* either by `prefers-color-scheme` on a root that is not forced light, or by the
|
|
13
|
+
* attribute. An attribute spelling out `system` would match neither.
|
|
14
|
+
*/
|
|
15
|
+
export declare function applyScheme(scheme: MPColorScheme): void;
|
|
16
|
+
export declare function setScheme(storageKey: string, scheme: MPColorScheme): void;
|
|
17
|
+
export declare function useChosenScheme(storageKey: string): MPColorScheme;
|
|
18
|
+
/**
|
|
19
|
+
* What the operating system is asking for, followed live.
|
|
20
|
+
*
|
|
21
|
+
* Subscribed to even while a page has chosen `'light'` or `'dark'`, which costs
|
|
22
|
+
* one listener and buys the thing a toggle is usually for: switching back to
|
|
23
|
+
* `'system'` reports the right answer immediately rather than on the next
|
|
24
|
+
* change.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useSystemScheme(): MPResolvedColorScheme;
|
|
27
|
+
/** Test seam: forgets the page's choice so a suite can start from nothing. */
|
|
28
|
+
export declare function resetScheme(): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import*as e from"react";export const SCHEME_ATTRIBUTE="data-mp-scheme";export const DEFAULT_STORAGE_KEY="mp-color-scheme";const t="(prefers-color-scheme: dark)";function n(e){return"light"===e||"dark"===e||"system"===e}let o;const r=new Set;function c(){for(const e of r)e()}export function applyScheme(e){if("undefined"==typeof document)return;const t=document.documentElement;"system"===e?t.removeAttribute("data-mp-scheme"):t.setAttribute("data-mp-scheme",e)}export function setScheme(e,t){o=t,function(e,t){try{"system"===t?localStorage.removeItem(e):localStorage.setItem(e,t)}catch{}}(e,t),applyScheme(t),c()}function s(e){return r.add(e),()=>{r.delete(e)}}function u(e){return o??=function(){if("undefined"==typeof document)return;const e=document.documentElement.getAttribute("data-mp-scheme");return n(e)&&"system"!==e?e:void 0}()??function(e){try{if("undefined"==typeof localStorage)return"system";const t=localStorage.getItem(e);return n(t)?t:"system"}catch{return"system"}}(e),o}export function useChosenScheme(t){const n=e.useCallback(()=>u(t),[t]);return e.useSyncExternalStore(s,n,()=>"system")}function m(e){if("undefined"==typeof window||!window.matchMedia)return()=>{};const n=window.matchMedia(t);return n.addEventListener("change",e),()=>n.removeEventListener("change",e)}function i(){return"undefined"!=typeof window&&window.matchMedia?.(t).matches?"dark":"light"}export function useSystemScheme(){return e.useSyncExternalStore(m,i,()=>"light")}export function resetScheme(){o=void 0,c()}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two prop defaults an application can move for the whole page.
|
|
3
|
+
*
|
|
4
|
+
* `size` and `color` are the only axes where every component in this library
|
|
5
|
+
* starts from the *same* answer — `md` and `primary` — which is what makes a
|
|
6
|
+
* single app-wide default meaningful for them and meaningless for anything else.
|
|
7
|
+
* A `variant` default is per component by design (`MPAccordion` is `outlined`,
|
|
8
|
+
* `MPAlert` is `tonal`, `MPBadge` is `filled`), so one global value would be
|
|
9
|
+
* overwriting six considered decisions with one arbitrary one.
|
|
10
|
+
*
|
|
11
|
+
* The same rule decides which components read this at all: a component that was
|
|
12
|
+
* taking the library's default takes the configured one instead, and a component
|
|
13
|
+
* that had chosen its own keeps it. `MPBadge` stays `error`, `MPTooltip` stays
|
|
14
|
+
* `sm`, `MPDialog`, `MPPill` and `MPShortcut` stay `secondary` — those are not
|
|
15
|
+
* unfilled defaults, they are answers.
|
|
16
|
+
*
|
|
17
|
+
* ## Why this needs context at all
|
|
18
|
+
*
|
|
19
|
+
* Which is the question `MPLocaleProvider` answers for itself, and the answer
|
|
20
|
+
* here is the same shape. Everything a theme normally carries — the colour
|
|
21
|
+
* roles, the type scale, the corners, the motion — is a CSS custom property and
|
|
22
|
+
* reaches a component through the cascade. `size` cannot: it resolves to literal
|
|
23
|
+
* Tailwind class strings (`h-14`, `text-mp-body-large`), because Tailwind finds
|
|
24
|
+
* classes by scanning source text and an interpolated `h-${n}` generates no rule
|
|
25
|
+
* at all. See `internal/scale.ts`. A value that cannot be a custom property and
|
|
26
|
+
* has to reach every call site is exactly what context is for.
|
|
27
|
+
*/
|
|
28
|
+
import * as React from 'react';
|
|
29
|
+
import type { MPColor, MPSize } from '../types.js';
|
|
30
|
+
/** What an `MPConfigProvider` can set. Anything unset is inherited, then default. */
|
|
31
|
+
export interface MPConfigValue {
|
|
32
|
+
size?: MPSize;
|
|
33
|
+
color?: MPColor;
|
|
34
|
+
}
|
|
35
|
+
export declare const MPConfigContext: React.Context<MPConfigValue>;
|
|
36
|
+
/** The configuration in force at this point in the tree. */
|
|
37
|
+
export declare function useMPConfig(): MPConfigValue;
|
|
38
|
+
/**
|
|
39
|
+
* `prop ?? config ?? the library's own`, which is the order of specificity: what
|
|
40
|
+
* this call site said, then what the application said, then what Material says.
|
|
41
|
+
*/
|
|
42
|
+
export declare function useMPSize(size: MPSize | undefined): MPSize;
|
|
43
|
+
export declare function useMPColor(color: MPColor | undefined): MPColor;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import*as t from"react";const e=Object.freeze({});export const MPConfigContext=/*@__PURE__*/t.createContext(e);export function useMPConfig(){return t.useContext(MPConfigContext)}export function useMPSize(e){const o=t.useContext(MPConfigContext);return e??o.size??"md"}export function useMPColor(e){const o=t.useContext(MPConfigContext);return e??o.color??"primary"}
|
package/dist/internal/date.d.ts
CHANGED
|
@@ -25,6 +25,16 @@
|
|
|
25
25
|
import type { MPWeekday } from '../types.js';
|
|
26
26
|
/** Which unit the calendar is currently letting you pick. */
|
|
27
27
|
export type MPCalendarView = 'day' | 'month' | 'year';
|
|
28
|
+
/**
|
|
29
|
+
* Which unit a picker asks for at all — the view the calendar stops at.
|
|
30
|
+
*
|
|
31
|
+
* The same three words as `MPCalendarView` and deliberately a second name: one
|
|
32
|
+
* is what is on screen at this moment, the other is what the control is *for*.
|
|
33
|
+
* A day picker passes through all three views and answers with a day; a month
|
|
34
|
+
* picker never draws a day grid, and the year view above it is a way of
|
|
35
|
+
* reaching a month rather than an answer of its own.
|
|
36
|
+
*/
|
|
37
|
+
export type MPDatePrecision = MPCalendarView;
|
|
28
38
|
/** How many years one page of the year grid holds. Four columns of three. */
|
|
29
39
|
export declare const YEAR_PAGE_SIZE = 12;
|
|
30
40
|
/**
|
|
@@ -44,8 +54,22 @@ export declare function isValidDate(value: unknown): value is Date;
|
|
|
44
54
|
export declare function startOfDay(date: Date): Date;
|
|
45
55
|
/** The first day of the month this date is in, at midnight. */
|
|
46
56
|
export declare function startOfMonth(date: Date): Date;
|
|
57
|
+
/** The first day of the year this date is in, at midnight. */
|
|
58
|
+
export declare function startOfYear(date: Date): Date;
|
|
47
59
|
/** How many days a month has, leap years included. */
|
|
48
60
|
export declare function daysInMonth(year: number, month: number): number;
|
|
61
|
+
/**
|
|
62
|
+
* The first instant of the day, month or year a date falls in.
|
|
63
|
+
*
|
|
64
|
+
* Which of the three is the picker's question rather than the calendar's. A
|
|
65
|
+
* control asked for a month holds a `Date` standing for a whole month, and the
|
|
66
|
+
* only honest one is that month's first day: a picker whose trigger says
|
|
67
|
+
* *July 2026* and whose form submits the 31st is printing one thing and sending
|
|
68
|
+
* another.
|
|
69
|
+
*/
|
|
70
|
+
export declare function startOfUnit(date: Date, unit: MPCalendarView): Date;
|
|
71
|
+
/** The last day of that same unit, at midnight — the other end of its span. */
|
|
72
|
+
export declare function endOfUnit(date: Date, unit: MPCalendarView): Date;
|
|
49
73
|
/** Today, at midnight. The one place the pickers read the clock for a *date*. */
|
|
50
74
|
export declare function today(): Date;
|
|
51
75
|
export declare function addDays(date: Date, amount: number): Date;
|
|
@@ -71,6 +95,21 @@ export declare function isSameMonth(a: Date | null | undefined, b: Date | null |
|
|
|
71
95
|
* has been chosen.
|
|
72
96
|
*/
|
|
73
97
|
export declare function isDayOutside(date: Date, min?: Date | null, max?: Date | null): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* The same question asked of a whole month or a whole year.
|
|
100
|
+
*
|
|
101
|
+
* A unit is outside the span only when *every* day in it is, which is what
|
|
102
|
+
* leaves July reachable under a `minDate` of 10 July: the bound is about which
|
|
103
|
+
* months exist, and where inside one it falls is a day grid's problem. It is
|
|
104
|
+
* the widening `isDayOutside` already applies to the time of day, one rung up —
|
|
105
|
+
* and it is the rule both the month grid and the year grid were already
|
|
106
|
+
* spelling out for themselves.
|
|
107
|
+
*
|
|
108
|
+
* The day case is handed to `isDayOutside` rather than written as this rule
|
|
109
|
+
* with a one-day span, because that is the one that runs forty-two times per
|
|
110
|
+
* calendar per render and it can answer without building either end.
|
|
111
|
+
*/
|
|
112
|
+
export declare function isUnitOutside(date: Date, unit: MPCalendarView, min?: Date | null, max?: Date | null): boolean;
|
|
74
113
|
/** Seconds since local midnight — what `minTime`/`maxTime` are compared on. */
|
|
75
114
|
export declare function secondsOfDay(date: Date): number;
|
|
76
115
|
/** Which column of a clock a candidate time is being offered for. */
|
|
@@ -127,16 +166,24 @@ export declare function displaySamples(locale: string | undefined, options: Intl
|
|
|
127
166
|
*/
|
|
128
167
|
export declare function withPlaceholder(samples: string[], placeholder: unknown): string[];
|
|
129
168
|
/**
|
|
130
|
-
* The
|
|
169
|
+
* The machine-readable spellings, for the hidden input that makes a picker
|
|
131
170
|
* submit with a form.
|
|
132
171
|
*
|
|
133
172
|
* Local, not UTC, and that is the whole point: `toISOString()` on a `Date`
|
|
134
173
|
* standing for 27 July in Seoul gives `2026-07-26T15:00:00Z`, and a form field
|
|
135
174
|
* that quietly reports the day before the one on screen is the single most
|
|
136
175
|
* expensive bug a date picker can ship. The shapes are the ones the native
|
|
137
|
-
* `<input type="date">`, `type="
|
|
138
|
-
* server that already parses those needs no
|
|
176
|
+
* `<input type="date">`, `type="month"`, `type="time"` and
|
|
177
|
+
* `type="datetime-local"` submit, so a server that already parses those needs no
|
|
178
|
+
* new code.
|
|
179
|
+
*
|
|
180
|
+
* A year on its own is the one with no input type behind it, and `YYYY` is what
|
|
181
|
+
* is left of the others once the parts a year picker was never asked about are
|
|
182
|
+
* taken off. Each spelling is built from the one above it, so there is one
|
|
183
|
+
* answer to how a year is written and not three.
|
|
139
184
|
*/
|
|
185
|
+
export declare function toISOYear(date: Date): string;
|
|
186
|
+
export declare function toISOMonth(date: Date): string;
|
|
140
187
|
export declare function toISODate(date: Date): string;
|
|
141
188
|
export declare function toISOTime(date: Date, withSeconds?: boolean): string;
|
|
142
189
|
export declare function toISODateTime(date: Date, withSeconds?: boolean): string;
|