material-plus-ui 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -28
- package/dist/components/accordion/MPAccordion.d.ts +115 -0
- package/dist/components/accordion/MPAccordion.js +1 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +1 -0
- package/dist/components/alert/MPAlert.d.ts +91 -0
- package/dist/components/alert/MPAlert.js +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/animate-appear/MPAnimateAppear.d.ts +56 -0
- package/dist/components/animate-appear/MPAnimateAppear.js +1 -0
- package/dist/components/animate-appear/index.d.ts +2 -0
- package/dist/components/animate-appear/index.js +1 -0
- package/dist/components/animate-blink/MPAnimateBlink.d.ts +41 -0
- package/dist/components/animate-blink/MPAnimateBlink.js +1 -0
- package/dist/components/animate-blink/index.d.ts +2 -0
- package/dist/components/animate-blink/index.js +1 -0
- package/dist/components/animate-fade/MPAnimateFade.d.ts +38 -0
- package/dist/components/animate-fade/MPAnimateFade.js +1 -0
- package/dist/components/animate-fade/index.d.ts +2 -0
- package/dist/components/animate-fade/index.js +1 -0
- package/dist/components/animate-grow/MPAnimateGrow.d.ts +52 -0
- package/dist/components/animate-grow/MPAnimateGrow.js +1 -0
- package/dist/components/animate-grow/index.d.ts +2 -0
- package/dist/components/animate-grow/index.js +1 -0
- package/dist/components/animate-headline/MPAnimateHeadline.d.ts +63 -0
- package/dist/components/animate-headline/MPAnimateHeadline.js +1 -0
- package/dist/components/animate-headline/index.d.ts +2 -0
- package/dist/components/animate-headline/index.js +1 -0
- package/dist/components/animate-lighting/MPAnimateLighting.d.ts +68 -0
- package/dist/components/animate-lighting/MPAnimateLighting.js +1 -0
- package/dist/components/animate-lighting/index.d.ts +2 -0
- package/dist/components/animate-lighting/index.js +1 -0
- package/dist/components/animate-marquee/MPAnimateMarquee.d.ts +66 -0
- package/dist/components/animate-marquee/MPAnimateMarquee.js +1 -0
- package/dist/components/animate-marquee/index.d.ts +2 -0
- package/dist/components/animate-marquee/index.js +1 -0
- package/dist/components/animate-rotate/MPAnimateRotate.d.ts +56 -0
- package/dist/components/animate-rotate/MPAnimateRotate.js +1 -0
- package/dist/components/animate-rotate/index.d.ts +2 -0
- package/dist/components/animate-rotate/index.js +1 -0
- package/dist/components/animate-slide/MPAnimateSlide.d.ts +53 -0
- package/dist/components/animate-slide/MPAnimateSlide.js +1 -0
- package/dist/components/animate-slide/index.d.ts +2 -0
- package/dist/components/animate-slide/index.js +1 -0
- package/dist/components/animate-typing/MPAnimateTyping.d.ts +59 -0
- package/dist/components/animate-typing/MPAnimateTyping.js +1 -0
- package/dist/components/animate-typing/index.d.ts +2 -0
- package/dist/components/animate-typing/index.js +1 -0
- package/dist/components/animate-zoom/MPAnimateZoom.d.ts +44 -0
- package/dist/components/animate-zoom/MPAnimateZoom.js +1 -0
- package/dist/components/animate-zoom/index.d.ts +2 -0
- package/dist/components/animate-zoom/index.js +1 -0
- package/dist/components/aspect-ratio/MPAspectRatio.d.ts +69 -0
- package/dist/components/aspect-ratio/MPAspectRatio.js +1 -0
- package/dist/components/aspect-ratio/index.d.ts +2 -0
- package/dist/components/aspect-ratio/index.js +1 -0
- package/dist/components/avatar/MPAvatar.d.ts +104 -0
- package/dist/components/avatar/MPAvatar.js +1 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +1 -0
- package/dist/components/badge/MPBadge.d.ts +104 -0
- package/dist/components/badge/MPBadge.js +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/blockquote/MPBlockquote.d.ts +73 -0
- package/dist/components/blockquote/MPBlockquote.js +1 -0
- package/dist/components/blockquote/index.d.ts +2 -0
- package/dist/components/blockquote/index.js +1 -0
- package/dist/components/bottom-navigation/MPBottomNavigation.d.ts +144 -0
- package/dist/components/bottom-navigation/MPBottomNavigation.js +1 -0
- package/dist/components/bottom-navigation/index.d.ts +2 -0
- package/dist/components/bottom-navigation/index.js +1 -0
- package/dist/components/box/MPBox.d.ts +78 -0
- package/dist/components/box/MPBox.js +1 -0
- package/dist/components/box/index.d.ts +2 -0
- package/dist/components/box/index.js +1 -0
- package/dist/components/breadcrumb/MPBreadcrumb.d.ts +127 -0
- package/dist/components/breadcrumb/MPBreadcrumb.js +1 -0
- package/dist/components/breadcrumb/index.d.ts +2 -0
- package/dist/components/breadcrumb/index.js +1 -0
- package/dist/components/button/MPButton.d.ts +75 -0
- package/dist/components/button/MPButton.js +1 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/button-group/MPButtonGroup.d.ts +31 -0
- package/dist/components/button-group/MPButtonGroup.js +1 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.js +1 -0
- package/dist/components/card/MPCard.d.ts +73 -0
- package/dist/components/card/MPCard.js +1 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/carousel/MPCarousel.d.ts +116 -0
- package/dist/components/carousel/MPCarousel.js +1 -0
- package/dist/components/carousel/index.d.ts +2 -0
- package/dist/components/carousel/index.js +1 -0
- package/dist/components/chat-bubble/MPChatBubble.d.ts +132 -0
- package/dist/components/chat-bubble/MPChatBubble.js +1 -0
- package/dist/components/chat-bubble/index.d.ts +2 -0
- package/dist/components/chat-bubble/index.js +1 -0
- package/dist/components/checkbox/MPCheckbox.d.ts +76 -0
- package/dist/components/checkbox/MPCheckbox.js +1 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/chip/MPChip.d.ts +74 -0
- package/dist/components/chip/MPChip.js +1 -0
- package/dist/components/chip/index.d.ts +2 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/collapsible/MPCollapsible.d.ts +97 -0
- package/dist/components/collapsible/MPCollapsible.js +1 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/color-picker/MPColorPicker.d.ts +131 -0
- package/dist/components/color-picker/MPColorPicker.js +1 -0
- package/dist/components/color-picker/index.d.ts +2 -0
- package/dist/components/color-picker/index.js +1 -0
- package/dist/components/combobox/MPCombobox.d.ts +175 -0
- package/dist/components/combobox/MPCombobox.js +1 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/container/MPContainer.d.ts +75 -0
- package/dist/components/container/MPContainer.js +1 -0
- package/dist/components/container/index.d.ts +2 -0
- package/dist/components/container/index.js +1 -0
- package/dist/components/date-picker/MPDatePicker.d.ts +98 -0
- package/dist/components/date-picker/MPDatePicker.js +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-range-picker/MPDateRangePicker.d.ts +98 -0
- package/dist/components/date-range-picker/MPDateRangePicker.js +1 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/date-time-picker/MPDateTimePicker.d.ts +78 -0
- package/dist/components/date-time-picker/MPDateTimePicker.js +1 -0
- package/dist/components/date-time-picker/index.d.ts +2 -0
- package/dist/components/date-time-picker/index.js +1 -0
- package/dist/components/dialog/MPDialog.d.ts +150 -0
- package/dist/components/dialog/MPDialog.js +1 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/divider/MPDivider.d.ts +80 -0
- package/dist/components/divider/MPDivider.js +1 -0
- package/dist/components/divider/index.d.ts +2 -0
- package/dist/components/divider/index.js +1 -0
- package/dist/components/drawer/MPDrawer.d.ts +168 -0
- package/dist/components/drawer/MPDrawer.js +1 -0
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/drawer/index.js +1 -0
- package/dist/components/empty/MPEmpty.d.ts +74 -0
- package/dist/components/empty/MPEmpty.js +1 -0
- package/dist/components/empty/index.d.ts +2 -0
- package/dist/components/empty/index.js +1 -0
- package/dist/components/file-picker/MPFilePicker.d.ts +113 -0
- package/dist/components/file-picker/MPFilePicker.js +1 -0
- package/dist/components/file-picker/index.d.ts +2 -0
- package/dist/components/file-picker/index.js +1 -0
- package/dist/components/floating-action-button/MPFloatingActionButton.d.ts +126 -0
- package/dist/components/floating-action-button/MPFloatingActionButton.js +1 -0
- package/dist/components/floating-action-button/index.d.ts +2 -0
- package/dist/components/floating-action-button/index.js +1 -0
- package/dist/components/grid/MPGrid.d.ts +155 -0
- package/dist/components/grid/MPGrid.js +1 -0
- package/dist/components/grid/index.d.ts +2 -0
- package/dist/components/grid/index.js +1 -0
- package/dist/components/highlight/MPHighlight.d.ts +95 -0
- package/dist/components/highlight/MPHighlight.js +1 -0
- package/dist/components/highlight/index.d.ts +2 -0
- package/dist/components/highlight/index.js +1 -0
- package/dist/components/icon-button/MPIconButton.d.ts +59 -0
- package/dist/components/icon-button/MPIconButton.js +1 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/icon-button/index.js +1 -0
- package/dist/components/list/MPList.d.ts +96 -0
- package/dist/components/list/MPList.js +1 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.js +1 -0
- package/dist/components/locale/MPLocaleProvider.d.ts +63 -0
- package/dist/components/locale/MPLocaleProvider.js +1 -0
- package/dist/components/locale/index.d.ts +2 -0
- package/dist/components/locale/index.js +1 -0
- package/dist/components/menu/MPMenu.d.ts +232 -0
- package/dist/components/menu/MPMenu.js +1 -0
- package/dist/components/menu/index.d.ts +2 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/number-field/MPNumberField.d.ts +117 -0
- package/dist/components/number-field/MPNumberField.js +1 -0
- package/dist/components/number-field/index.d.ts +2 -0
- package/dist/components/number-field/index.js +1 -0
- package/dist/components/otp-field/MPOtpField.d.ts +89 -0
- package/dist/components/otp-field/MPOtpField.js +1 -0
- package/dist/components/otp-field/index.d.ts +2 -0
- package/dist/components/otp-field/index.js +1 -0
- package/dist/components/overlay/MPOverlay.d.ts +96 -0
- package/dist/components/overlay/MPOverlay.js +1 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.js +1 -0
- package/dist/components/pagination/MPPagination.d.ts +106 -0
- package/dist/components/pagination/MPPagination.js +1 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/panes/MPPanes.d.ts +100 -0
- package/dist/components/panes/MPPanes.js +1 -0
- package/dist/components/panes/index.d.ts +2 -0
- package/dist/components/panes/index.js +1 -0
- package/dist/components/pill/MPPill.d.ts +117 -0
- package/dist/components/pill/MPPill.js +1 -0
- package/dist/components/pill/index.d.ts +2 -0
- package/dist/components/pill/index.js +1 -0
- package/dist/components/popover/MPPopover.d.ts +143 -0
- package/dist/components/popover/MPPopover.js +1 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +1 -0
- package/dist/components/progress-box/MPProgressBox.d.ts +40 -0
- package/dist/components/progress-box/MPProgressBox.js +1 -0
- package/dist/components/progress-box/index.d.ts +2 -0
- package/dist/components/progress-box/index.js +1 -0
- package/dist/components/progress-circular/MPProgressCircular.d.ts +32 -0
- package/dist/components/progress-circular/MPProgressCircular.js +1 -0
- package/dist/components/progress-circular/index.d.ts +2 -0
- package/dist/components/progress-circular/index.js +1 -0
- package/dist/components/progress-linear/MPProgressLinear.d.ts +32 -0
- package/dist/components/progress-linear/MPProgressLinear.js +1 -0
- package/dist/components/progress-linear/index.d.ts +2 -0
- package/dist/components/progress-linear/index.js +1 -0
- package/dist/components/radio-group/MPRadioGroup.d.ts +81 -0
- package/dist/components/radio-group/MPRadioGroup.js +1 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +1 -0
- package/dist/components/rating/MPRating.d.ts +135 -0
- package/dist/components/rating/MPRating.js +1 -0
- package/dist/components/rating/index.d.ts +2 -0
- package/dist/components/rating/index.js +1 -0
- package/dist/components/segmented-button/MPSegmentedButton.d.ts +75 -0
- package/dist/components/segmented-button/MPSegmentedButton.js +1 -0
- package/dist/components/segmented-button/index.d.ts +2 -0
- package/dist/components/segmented-button/index.js +1 -0
- package/dist/components/select/MPSelect.d.ts +103 -0
- package/dist/components/select/MPSelect.js +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/shortcut/MPShortcut.d.ts +67 -0
- package/dist/components/shortcut/MPShortcut.js +1 -0
- package/dist/components/shortcut/index.d.ts +2 -0
- package/dist/components/shortcut/index.js +1 -0
- package/dist/components/skeleton/MPSkeleton.d.ts +76 -0
- package/dist/components/skeleton/MPSkeleton.js +1 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/slider/MPSlider.d.ts +77 -0
- package/dist/components/slider/MPSlider.js +1 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +1 -0
- package/dist/components/snackbar/MPSnackbar.d.ts +175 -0
- package/dist/components/snackbar/MPSnackbar.js +1 -0
- package/dist/components/snackbar/index.d.ts +2 -0
- package/dist/components/snackbar/index.js +1 -0
- package/dist/components/spoiler/MPSpoiler.d.ts +106 -0
- package/dist/components/spoiler/MPSpoiler.js +1 -0
- package/dist/components/spoiler/index.d.ts +2 -0
- package/dist/components/spoiler/index.js +1 -0
- package/dist/components/switch/MPSwitch.d.ts +75 -0
- package/dist/components/switch/MPSwitch.js +1 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/MPTable.d.ts +120 -0
- package/dist/components/table/MPTable.js +1 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/tabs/MPTabs.d.ts +145 -0
- package/dist/components/tabs/MPTabs.js +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/text-field/MPTextField.d.ts +51 -22
- package/dist/components/text-field/MPTextField.js +1 -1
- package/dist/components/text-link/MPTextLink.d.ts +88 -0
- package/dist/components/text-link/MPTextLink.js +1 -0
- package/dist/components/text-link/index.d.ts +2 -0
- package/dist/components/text-link/index.js +1 -0
- package/dist/components/time-picker/MPTimePicker.d.ts +108 -0
- package/dist/components/time-picker/MPTimePicker.js +1 -0
- package/dist/components/time-picker/index.d.ts +2 -0
- package/dist/components/time-picker/index.js +1 -0
- package/dist/components/timeline/MPTimeline.d.ts +96 -0
- package/dist/components/timeline/MPTimeline.js +1 -0
- package/dist/components/timeline/index.d.ts +2 -0
- package/dist/components/timeline/index.js +1 -0
- package/dist/components/tooltip/MPTooltip.d.ts +117 -0
- package/dist/components/tooltip/MPTooltip.js +1 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/typography/MPTypography.d.ts +94 -0
- package/dist/components/typography/MPTypography.js +1 -0
- package/dist/components/typography/index.d.ts +2 -0
- package/dist/components/typography/index.js +1 -0
- package/dist/constants/icons.d.ts +49 -0
- package/dist/constants/icons.js +1 -1
- package/dist/index.d.ts +73 -0
- package/dist/index.js +1 -1
- package/dist/internal/Calendar.d.ts +118 -0
- package/dist/internal/Calendar.js +1 -0
- package/dist/internal/FieldOutline.d.ts +109 -0
- package/dist/internal/FieldOutline.js +1 -0
- package/dist/internal/Picker.d.ts +153 -0
- package/dist/internal/Picker.js +1 -0
- package/dist/internal/StateLayer.d.ts +45 -0
- package/dist/internal/StateLayer.js +1 -0
- package/dist/internal/SupportingText.d.ts +23 -0
- package/dist/internal/SupportingText.js +1 -0
- package/dist/internal/WidthSizer.d.ts +31 -0
- package/dist/internal/WidthSizer.js +1 -0
- package/dist/internal/accent.d.ts +39 -0
- package/dist/internal/accent.js +1 -0
- package/dist/internal/animate.d.ts +179 -0
- package/dist/internal/animate.js +1 -0
- package/dist/internal/button-group.d.ts +21 -0
- package/dist/internal/button-group.js +1 -0
- package/dist/internal/color.d.ts +125 -0
- package/dist/internal/color.js +1 -0
- package/dist/internal/date.d.ts +179 -0
- package/dist/internal/date.js +1 -0
- package/dist/internal/i18n.d.ts +241 -0
- package/dist/internal/i18n.js +1 -0
- package/dist/internal/inert.d.ts +11 -0
- package/dist/internal/inert.js +1 -0
- package/dist/internal/locale.d.ts +43 -0
- package/dist/internal/locale.js +1 -0
- package/dist/internal/menu.d.ts +23 -0
- package/dist/internal/menu.js +1 -0
- package/dist/internal/progress.d.ts +126 -0
- package/dist/internal/progress.js +1 -0
- package/dist/internal/scale.d.ts +127 -0
- package/dist/internal/scale.js +1 -0
- package/dist/internal/surface.d.ts +76 -0
- package/dist/internal/surface.js +1 -0
- package/dist/internal/visually-hidden.d.ts +23 -0
- package/dist/internal/visually-hidden.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +1871 -20
- package/dist/types.d.ts +262 -16
- package/package.json +16 -21
|
@@ -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,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The machinery every `MPAnimate*` component runs on.
|
|
3
|
+
*
|
|
4
|
+
* It lives in `internal/` for the reason `menu.ts` and `button-group.ts` do:
|
|
5
|
+
* eleven components need it and none of them should have to import another.
|
|
6
|
+
*
|
|
7
|
+
* ## The shape of it
|
|
8
|
+
*
|
|
9
|
+
* Every effect is one `@keyframes` in `styles.css` running from a state written
|
|
10
|
+
* entirely in `--_mp-anim-*` custom properties to the element's natural one.
|
|
11
|
+
* Nothing here generates CSS: it fills slots, and the stylesheet decides what
|
|
12
|
+
* they mean. That is the same split `accentSlots()` makes for colour, for the
|
|
13
|
+
* same reason — Tailwind only ever sees class names that appear literally in
|
|
14
|
+
* the source, so a per-value class would not survive the first prop.
|
|
15
|
+
*
|
|
16
|
+
* Because the from-state is the *keyframe* rather than a second class, running
|
|
17
|
+
* an effect backwards is `animation-direction: reverse` and nothing else. That
|
|
18
|
+
* is what makes `mode="out"` free on all five of the effects that take one —
|
|
19
|
+
* the fade, the grow, the zoom, the slide and the rotate — and, as it happens,
|
|
20
|
+
* correct:
|
|
21
|
+
* CSS mirrors the timing function along with the keyframes, so an entrance
|
|
22
|
+
* eased on `emphasized-decelerate` comes out accelerating on the way back. The
|
|
23
|
+
* specification asks for exactly that pair, and the browser supplies it.
|
|
24
|
+
*
|
|
25
|
+
* ## Why the defaults are `var()` rather than numbers
|
|
26
|
+
*
|
|
27
|
+
* A duration nobody set resolves to `var(--mp-sys-motion-duration-medium4)`,
|
|
28
|
+
* not to `400ms`. Both would draw the same animation today; only one of them
|
|
29
|
+
* moves when a page retunes its motion tokens. Same rule as everywhere else in
|
|
30
|
+
* this library: the value a caller does not name is the *token*, so a theme can
|
|
31
|
+
* still reach it.
|
|
32
|
+
*
|
|
33
|
+
* ## What is deliberately not here
|
|
34
|
+
*
|
|
35
|
+
* An animation that has to know what its children *are* — a marquee that
|
|
36
|
+
* duplicates them, a headline that swaps between them, a typewriter that counts
|
|
37
|
+
* characters — cannot be a class name and a few numbers. Those are components,
|
|
38
|
+
* and their logic stays in their own files.
|
|
39
|
+
*/
|
|
40
|
+
import * as React from 'react';
|
|
41
|
+
import type { MPAnimateMode, MPAnimateRepeat, MPAnimateTrigger, MPAnimation, MPEasing, MPSide } from '../types';
|
|
42
|
+
/** The class that reads the slots. Always paired with one of the below. */
|
|
43
|
+
export declare const ANIM_BASE = "mp-anim";
|
|
44
|
+
/**
|
|
45
|
+
* Which keyframe an effect runs.
|
|
46
|
+
*
|
|
47
|
+
* `grow` and `zoom` share one: they are the same arithmetic at two strengths,
|
|
48
|
+
* and a second identical `@keyframes` would only be a second place to fix a
|
|
49
|
+
* bug. What separates them is their defaults and their origin, which is a
|
|
50
|
+
* property rather than a keyframe.
|
|
51
|
+
*/
|
|
52
|
+
export declare const ANIMATION_CLASS: Record<MPAnimation, string>;
|
|
53
|
+
/** A curve, as the stylesheet spells it. */
|
|
54
|
+
export declare function easingValue(easing: MPEasing): string;
|
|
55
|
+
/**
|
|
56
|
+
* A duration, as the stylesheet spells it.
|
|
57
|
+
*
|
|
58
|
+
* A number is milliseconds and lands as milliseconds. Nothing at all lands as
|
|
59
|
+
* the effect's own Material token, so a page that retunes its motion moves this
|
|
60
|
+
* animation with it.
|
|
61
|
+
*/
|
|
62
|
+
export declare function durationValue(duration: number | undefined, effect: MPAnimation, mode?: MPAnimateMode): string;
|
|
63
|
+
/** A number is pixels; a string is already a CSS length. */
|
|
64
|
+
export declare function lengthValue(value: number | string): string;
|
|
65
|
+
/** `'infinite'` reaches CSS as the word; a count reaches it as the number. */
|
|
66
|
+
export declare function repeatValue(repeat: MPAnimateRepeat): string;
|
|
67
|
+
export declare function isInfinite(repeat: MPAnimateRepeat | undefined): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* `normal`, `reverse`, `alternate`, `alternate-reverse` — the four CSS already
|
|
70
|
+
* has, assembled from the two props that mean something to a caller.
|
|
71
|
+
*
|
|
72
|
+
* `mode="out"` is a reversed run rather than a keyframe of its own, which is
|
|
73
|
+
* also why a reversed animation ends held on its own first frame: `fill-mode`
|
|
74
|
+
* is `both`, so a faded-out element stays faded out instead of snapping back.
|
|
75
|
+
*/
|
|
76
|
+
export declare function directionValue(mode: MPAnimateMode, alternate: boolean | undefined): string;
|
|
77
|
+
export interface AnimationSlotOptions {
|
|
78
|
+
/** Which effect's tokens to fall back to, and which keyframe to run. */
|
|
79
|
+
effect: MPAnimation;
|
|
80
|
+
/** Milliseconds. Unset takes the effect's Material duration token. */
|
|
81
|
+
duration?: number;
|
|
82
|
+
/** Milliseconds. */
|
|
83
|
+
delay: number;
|
|
84
|
+
/** Unset takes the effect's Material easing token. */
|
|
85
|
+
easing?: MPEasing;
|
|
86
|
+
repeat: MPAnimateRepeat;
|
|
87
|
+
alternate?: boolean;
|
|
88
|
+
mode?: MPAnimateMode;
|
|
89
|
+
/** Where the animated properties start. Only the ones an effect reads. */
|
|
90
|
+
opacity?: number;
|
|
91
|
+
scale?: number;
|
|
92
|
+
x?: string;
|
|
93
|
+
y?: string;
|
|
94
|
+
angle?: string;
|
|
95
|
+
angleTo?: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The `--_mp-anim-*` slots, as an inline style object.
|
|
99
|
+
*
|
|
100
|
+
* Inline rather than utilities for the reason the accent slots are: these are
|
|
101
|
+
* per-instance numbers, and Tailwind cannot generate a class for a duration it
|
|
102
|
+
* has never seen written down.
|
|
103
|
+
*/
|
|
104
|
+
export declare function animationSlots(options: AnimationSlotOptions): React.CSSProperties;
|
|
105
|
+
/**
|
|
106
|
+
* Which way a slide starts, given the edge it comes from.
|
|
107
|
+
*
|
|
108
|
+
* `MPSide` is physical everywhere in this library, and it stays physical here:
|
|
109
|
+
* something sliding in from the top of the window comes from the top in every
|
|
110
|
+
* writing direction.
|
|
111
|
+
*/
|
|
112
|
+
export declare function slideOffsets(from: MPSide, distance: number | string): {
|
|
113
|
+
x: string;
|
|
114
|
+
y: string;
|
|
115
|
+
};
|
|
116
|
+
export declare function usePrefersReducedMotion(): boolean;
|
|
117
|
+
export interface AnimationRunOptions {
|
|
118
|
+
trigger: MPAnimateTrigger;
|
|
119
|
+
play?: boolean;
|
|
120
|
+
once: boolean;
|
|
121
|
+
threshold: number;
|
|
122
|
+
paused?: boolean;
|
|
123
|
+
/** An infinite effect stops when the pointer leaves; a finite one finishes. */
|
|
124
|
+
infinite: boolean;
|
|
125
|
+
}
|
|
126
|
+
export interface AnimationRun {
|
|
127
|
+
/** Goes on the animated element. */
|
|
128
|
+
ref: React.RefCallback<HTMLElement>;
|
|
129
|
+
/** `running` or `paused`, for `--_mp-anim-state`. */
|
|
130
|
+
state: 'running' | 'paused';
|
|
131
|
+
/** Whether the animation has been let go at all. */
|
|
132
|
+
started: boolean;
|
|
133
|
+
/** Spread onto the element when `trigger` is `hover`; empty otherwise. */
|
|
134
|
+
handlers: React.HTMLAttributes<HTMLElement>;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Starts, restarts and holds an animation.
|
|
138
|
+
*
|
|
139
|
+
* Two things here are less obvious than they look.
|
|
140
|
+
*
|
|
141
|
+
* **Waiting is `animation-play-state: paused`, not a second class.** An element
|
|
142
|
+
* that has not been triggered yet has to already look like its own first frame,
|
|
143
|
+
* or a `visible` fade would be fully drawn until it scrolled into view and then
|
|
144
|
+
* blink out to start. With `fill-mode: both` a paused animation shows exactly
|
|
145
|
+
* that frame, so waiting and running are one animation in two states rather
|
|
146
|
+
* than two states to keep in step.
|
|
147
|
+
*
|
|
148
|
+
* **Restarting reaches for the DOM.** There is no way to rewind a CSS animation
|
|
149
|
+
* from React: re-rendering with the same class changes nothing, and a `key`
|
|
150
|
+
* would restart the animation by unmounting the children, taking their state
|
|
151
|
+
* with it. Clearing `animation-name`, reading a layout property to force the
|
|
152
|
+
* style to settle, and putting it back is the one move that rewinds the element
|
|
153
|
+
* and leaves everything inside it alone.
|
|
154
|
+
*/
|
|
155
|
+
export declare function useAnimationRun({ trigger, play, once, threshold, paused, infinite }: AnimationRunOptions): AnimationRun;
|
|
156
|
+
export interface AnimateElementParams extends AnimationSlotOptions, AnimationRunOptions {
|
|
157
|
+
}
|
|
158
|
+
export interface AnimateElement {
|
|
159
|
+
ref: React.RefCallback<HTMLElement>;
|
|
160
|
+
className: string;
|
|
161
|
+
style: React.CSSProperties;
|
|
162
|
+
/** The hover handlers and the two data attributes, ready to be spread. */
|
|
163
|
+
props: React.HTMLAttributes<HTMLElement> & Record<string, unknown>;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Everything an `MPAnimate*` root needs, in one call.
|
|
167
|
+
*
|
|
168
|
+
* The six effect components differ only in their defaults and in which slots
|
|
169
|
+
* they fill, so this is where the identical two-thirds of each of them lives.
|
|
170
|
+
* The ones that have to understand their children — Typing, Marquee, Headline,
|
|
171
|
+
* Appear — call `useAnimationRun` directly and put the classes where their own
|
|
172
|
+
* structure needs them.
|
|
173
|
+
*
|
|
174
|
+
* `data-mp-animation` and `data-mp-state` are here rather than in each
|
|
175
|
+
* component because they are the same two facts every time, and because a test
|
|
176
|
+
* that has to assert on a class name is a test that breaks when a class name
|
|
177
|
+
* changes.
|
|
178
|
+
*/
|
|
179
|
+
export declare function useAnimateElement(params: AnimateElementParams): AnimateElement;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as e from"react";export const ANIM_BASE="mp-anim";export const ANIMATION_CLASS={fade:"mp-anim-fade",grow:"mp-anim-scale",slide:"mp-anim-slide",zoom:"mp-anim-scale",rotate:"mp-anim-rotate",blink:"mp-anim-blink"};const n={fade:{in:"medium2",out:"short4"},grow:{in:"medium4",out:"short4"},slide:{in:"medium4",out:"short4"},zoom:{in:"medium4",out:"short4"},rotate:{in:"long2",out:"medium2"},blink:{in:"extra-long4",out:"extra-long4"}},t={fade:"emphasized-decelerate",grow:"emphasized-decelerate",slide:"emphasized-decelerate",zoom:"emphasized-decelerate",rotate:"emphasized-decelerate",blink:"standard"};export function easingValue(e){return`var(--mp-sys-motion-easing-${e})`}export function durationValue(e,t,i="in"){return void 0!==e?`${e}ms`:`var(--mp-sys-motion-duration-${n[t][i]})`}export function lengthValue(e){return"number"==typeof e?`${e}px`:e}export function repeatValue(e){return"infinite"===e?"infinite":String(e)}export function isInfinite(e){return"infinite"===e}export function directionValue(e,n){return"out"===e?n?"alternate-reverse":"reverse":n?"alternate":"normal"}export function animationSlots(e){const n=e.mode??"in",i={"--_mp-anim-duration":durationValue(e.duration,e.effect,n),"--_mp-anim-delay":`${e.delay}ms`,"--_mp-anim-ease":easingValue(e.easing??t[e.effect]),"--_mp-anim-repeat":repeatValue(e.repeat),"--_mp-anim-direction":directionValue(n,e.alternate)};return void 0!==e.opacity&&(i["--_mp-anim-opacity"]=String(e.opacity)),void 0!==e.scale&&(i["--_mp-anim-scale"]=String(e.scale)),void 0!==e.x&&(i["--_mp-anim-x"]=e.x),void 0!==e.y&&(i["--_mp-anim-y"]=e.y),void 0!==e.angle&&(i["--_mp-anim-angle"]=e.angle),void 0!==e.angleTo&&(i["--_mp-anim-angle-to"]=e.angleTo),i}export function slideOffsets(e,n){const t=lengthValue(n),i="number"==typeof n?-n+"px":`calc(-1 * ${t})`;switch(e){case"top":return{x:"0px",y:i};case"bottom":return{x:"0px",y:t};case"left":return{x:i,y:"0px"};default:return{x:t,y:"0px"}}}const i="(prefers-reduced-motion: reduce)";function a(e){if("undefined"==typeof window||!window.matchMedia)return()=>{};const n=window.matchMedia(i);return n.addEventListener("change",e),()=>n.removeEventListener("change",e)}function r(){return!("undefined"==typeof window||!window.matchMedia)&&window.matchMedia(i).matches}function o(){return!1}export function usePrefersReducedMotion(){return e.useSyncExternalStore(a,r,o)}export function useAnimationRun({trigger:n,play:t,once:i,threshold:a,paused:r,infinite:o}){const s=e.useRef(null),[u,m]=e.useState("mount"===n),[c,d]=e.useState(0),l=e.useCallback(()=>{m(!0),d(e=>e+1)},[]);e.useLayoutEffect(()=>{const e=s.current;if(!e||0===c)return;const n=[e,...e.querySelectorAll(".mp-anim, .mp-marquee-track")];for(const e of n)e.style.animationName="none";e.offsetWidth;for(const e of n)e.style.animationName=""},[c]),e.useEffect(()=>{if("visible"!==n)return;const e=s.current;if(!e||"undefined"==typeof IntersectionObserver)return void m(!0);const t=new IntersectionObserver(([e])=>{e.isIntersecting?(l(),i&&t.disconnect()):i||m(!1)},{threshold:a});return t.observe(e),()=>t.disconnect()},[n,i,a,l]),e.useEffect(()=>{"manual"===n&&(t?l():m(!1))},[n,t,l]);const p=e.useCallback(()=>{o&&m(!1)},[o]),f="hover"===n?{onPointerEnter:l,onFocus:l,onPointerLeave:p,onBlur:p}:{};return{ref:e.useCallback(e=>{s.current=e},[]),state:u&&!r?"running":"paused",started:u,handlers:f}}export function useAnimateElement(e){const{trigger:n,play:t,once:i,threshold:a,paused:r,infinite:o,...s}=e,u=useAnimationRun({trigger:n,play:t,once:i,threshold:a,paused:r,infinite:o});return{ref:u.ref,className:`mp-anim ${ANIMATION_CLASS[s.effect]}`,style:{...animationSlots(s),"--_mp-anim-state":u.state},props:{...u.handlers,"data-mp-animation":s.effect,"data-mp-state":u.state}}}
|
|
@@ -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'): readonly 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'): readonly 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),n=new Map;export function weekdayLabels(t,e,o="narrow"){const a=`w ${t??""} ${e} ${o}`;let s=n.get(a);if(!s){const i=dateFormatter(t,{weekday:o});s=Array.from({length:7},(t,n)=>i.format(addDays(r,(e+n)%7))),n.set(a,s)}return s}export function monthLabels(t,e="short"){const r=`m ${t??""} ${e}`;let o=n.get(r);if(!o){const a=dateFormatter(t,{month:e});o=Array.from({length:12},(t,e)=>a.format(makeDate(2021,e,1))),n.set(r,o)}return o}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}
|