@allxsmith/bestax-bulma 5.27.0 → 5.27.1
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/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/columns/Column.js +48 -0
- package/dist/esm/columns/Column.js.map +1 -0
- package/dist/esm/columns/Columns.js +53 -0
- package/dist/esm/columns/Columns.js.map +1 -0
- package/dist/esm/components/Avatar.js +299 -0
- package/dist/esm/components/Avatar.js.map +1 -0
- package/dist/esm/components/Avatars.js +81 -0
- package/dist/esm/components/Avatars.js.map +1 -0
- package/dist/esm/components/Badge.js +105 -0
- package/dist/esm/components/Badge.js.map +1 -0
- package/dist/esm/components/Breadcrumb.js +36 -0
- package/dist/esm/components/Breadcrumb.js.map +1 -0
- package/dist/esm/components/Card.js +252 -0
- package/dist/esm/components/Card.js.map +1 -0
- package/dist/esm/components/Carousel.js +351 -0
- package/dist/esm/components/Carousel.js.map +1 -0
- package/dist/esm/components/Collapse.js +193 -0
- package/dist/esm/components/Collapse.js.map +1 -0
- package/dist/esm/components/Collapses.js +99 -0
- package/dist/esm/components/Collapses.js.map +1 -0
- package/dist/esm/components/Dialog.js +230 -0
- package/dist/esm/components/Dialog.js.map +1 -0
- package/dist/esm/components/Dropdown.js +362 -0
- package/dist/esm/components/Dropdown.js.map +1 -0
- package/dist/esm/components/Loading.js +87 -0
- package/dist/esm/components/Loading.js.map +1 -0
- package/dist/esm/components/Menu.js +117 -0
- package/dist/esm/components/Menu.js.map +1 -0
- package/dist/esm/components/Message.js +56 -0
- package/dist/esm/components/Message.js.map +1 -0
- package/dist/esm/components/Modal.js +354 -0
- package/dist/esm/components/Modal.js.map +1 -0
- package/dist/esm/components/Navbar.js +287 -0
- package/dist/esm/components/Navbar.js.map +1 -0
- package/dist/esm/components/Pagination.js +191 -0
- package/dist/esm/components/Pagination.js.map +1 -0
- package/dist/esm/components/Panel.js +100 -0
- package/dist/esm/components/Panel.js.map +1 -0
- package/dist/esm/components/Popover.js +298 -0
- package/dist/esm/components/Popover.js.map +1 -0
- package/dist/esm/components/Reveal.js +157 -0
- package/dist/esm/components/Reveal.js.map +1 -0
- package/dist/esm/components/Sidebar.js +209 -0
- package/dist/esm/components/Sidebar.js.map +1 -0
- package/dist/esm/components/Steps.js +128 -0
- package/dist/esm/components/Steps.js.map +1 -0
- package/dist/esm/components/Tabs.js +335 -0
- package/dist/esm/components/Tabs.js.map +1 -0
- package/dist/esm/components/Toast.js +322 -0
- package/dist/esm/components/Toast.js.map +1 -0
- package/dist/esm/components/Tooltip.js +202 -0
- package/dist/esm/components/Tooltip.js.map +1 -0
- package/dist/esm/components/collapsesContext.js +12 -0
- package/dist/esm/components/collapsesContext.js.map +1 -0
- package/dist/esm/elements/Block.js +29 -0
- package/dist/esm/elements/Block.js.map +1 -0
- package/dist/esm/elements/Box.js +32 -0
- package/dist/esm/elements/Box.js.map +1 -0
- package/dist/esm/elements/Button.js +139 -0
- package/dist/esm/elements/Button.js.map +1 -0
- package/dist/esm/elements/Buttons.js +42 -0
- package/dist/esm/elements/Buttons.js.map +1 -0
- package/dist/esm/elements/Code.js +25 -0
- package/dist/esm/elements/Code.js.map +1 -0
- package/dist/esm/elements/Content.js +33 -0
- package/dist/esm/elements/Content.js.map +1 -0
- package/dist/esm/elements/Delete.js +35 -0
- package/dist/esm/elements/Delete.js.map +1 -0
- package/dist/esm/elements/Divider.js +27 -0
- package/dist/esm/elements/Divider.js.map +1 -0
- package/dist/esm/elements/Emphasis.js +25 -0
- package/dist/esm/elements/Emphasis.js.map +1 -0
- package/dist/esm/elements/Figure.js +58 -0
- package/dist/esm/elements/Figure.js.map +1 -0
- package/dist/esm/elements/Icon.js +256 -0
- package/dist/esm/elements/Icon.js.map +1 -0
- package/dist/esm/elements/IconText.js +36 -0
- package/dist/esm/elements/IconText.js.map +1 -0
- package/dist/esm/elements/Image.js +46 -0
- package/dist/esm/elements/Image.js.map +1 -0
- package/dist/esm/elements/Link.js +36 -0
- package/dist/esm/elements/Link.js.map +1 -0
- package/dist/esm/elements/LinkButton.js +37 -0
- package/dist/esm/elements/LinkButton.js.map +1 -0
- package/dist/esm/elements/ListItem.js +28 -0
- package/dist/esm/elements/ListItem.js.map +1 -0
- package/dist/esm/elements/Loader.js +37 -0
- package/dist/esm/elements/Loader.js.map +1 -0
- package/dist/esm/elements/Notification.js +316 -0
- package/dist/esm/elements/Notification.js.map +1 -0
- package/dist/esm/elements/OrderedList.js +31 -0
- package/dist/esm/elements/OrderedList.js.map +1 -0
- package/dist/esm/elements/Paragraph.js +28 -0
- package/dist/esm/elements/Paragraph.js.map +1 -0
- package/dist/esm/elements/Pre.js +25 -0
- package/dist/esm/elements/Pre.js.map +1 -0
- package/dist/esm/elements/Progress.js +33 -0
- package/dist/esm/elements/Progress.js.map +1 -0
- package/dist/esm/elements/Skeleton.js +30 -0
- package/dist/esm/elements/Skeleton.js.map +1 -0
- package/dist/esm/elements/Span.js +28 -0
- package/dist/esm/elements/Span.js.map +1 -0
- package/dist/esm/elements/Strong.js +25 -0
- package/dist/esm/elements/Strong.js.map +1 -0
- package/dist/esm/elements/SubTitle.js +51 -0
- package/dist/esm/elements/SubTitle.js.map +1 -0
- package/dist/esm/elements/Table.js +51 -0
- package/dist/esm/elements/Table.js.map +1 -0
- package/dist/esm/elements/Tag.js +49 -0
- package/dist/esm/elements/Tag.js.map +1 -0
- package/dist/esm/elements/Tags.js +34 -0
- package/dist/esm/elements/Tags.js.map +1 -0
- package/dist/esm/elements/Tbody.js +26 -0
- package/dist/esm/elements/Tbody.js.map +1 -0
- package/dist/esm/elements/Td.js +61 -0
- package/dist/esm/elements/Td.js.map +1 -0
- package/dist/esm/elements/Tfoot.js +26 -0
- package/dist/esm/elements/Tfoot.js.map +1 -0
- package/dist/esm/elements/Th.js +34 -0
- package/dist/esm/elements/Th.js.map +1 -0
- package/dist/esm/elements/Thead.js +26 -0
- package/dist/esm/elements/Thead.js.map +1 -0
- package/dist/esm/elements/Title.js +44 -0
- package/dist/esm/elements/Title.js.map +1 -0
- package/dist/esm/elements/Tr.js +31 -0
- package/dist/esm/elements/Tr.js.map +1 -0
- package/dist/esm/elements/UnorderedList.js +31 -0
- package/dist/esm/elements/UnorderedList.js.map +1 -0
- package/dist/esm/elements/iconProps.js +49 -0
- package/dist/esm/elements/iconProps.js.map +1 -0
- package/dist/esm/form/Autocomplete.js +279 -0
- package/dist/esm/form/Autocomplete.js.map +1 -0
- package/dist/esm/form/Checkbox.js +111 -0
- package/dist/esm/form/Checkbox.js.map +1 -0
- package/dist/esm/form/Checkboxes.js +89 -0
- package/dist/esm/form/Checkboxes.js.map +1 -0
- package/dist/esm/form/Control.js +79 -0
- package/dist/esm/form/Control.js.map +1 -0
- package/dist/esm/form/DateInput.js +87 -0
- package/dist/esm/form/DateInput.js.map +1 -0
- package/dist/esm/form/DateInputBase.js +263 -0
- package/dist/esm/form/DateInputBase.js.map +1 -0
- package/dist/esm/form/DateRangeInput.js +76 -0
- package/dist/esm/form/DateRangeInput.js.map +1 -0
- package/dist/esm/form/DateRangeInputBase.js +301 -0
- package/dist/esm/form/DateRangeInputBase.js.map +1 -0
- package/dist/esm/form/DateTimeInput.js +87 -0
- package/dist/esm/form/DateTimeInput.js.map +1 -0
- package/dist/esm/form/DateTimeInputBase.js +333 -0
- package/dist/esm/form/DateTimeInputBase.js.map +1 -0
- package/dist/esm/form/Field.js +153 -0
- package/dist/esm/form/Field.js.map +1 -0
- package/dist/esm/form/File.js +109 -0
- package/dist/esm/form/File.js.map +1 -0
- package/dist/esm/form/FormContext.js +170 -0
- package/dist/esm/form/FormContext.js.map +1 -0
- package/dist/esm/form/Input.js +88 -0
- package/dist/esm/form/Input.js.map +1 -0
- package/dist/esm/form/InputBase.js +40 -0
- package/dist/esm/form/InputBase.js.map +1 -0
- package/dist/esm/form/Numberinput.js +199 -0
- package/dist/esm/form/Numberinput.js.map +1 -0
- package/dist/esm/form/Radio.js +108 -0
- package/dist/esm/form/Radio.js.map +1 -0
- package/dist/esm/form/Radios.js +91 -0
- package/dist/esm/form/Radios.js.map +1 -0
- package/dist/esm/form/Rate.js +279 -0
- package/dist/esm/form/Rate.js.map +1 -0
- package/dist/esm/form/Select.js +81 -0
- package/dist/esm/form/Select.js.map +1 -0
- package/dist/esm/form/SelectBase.js +54 -0
- package/dist/esm/form/SelectBase.js.map +1 -0
- package/dist/esm/form/Slider.js +459 -0
- package/dist/esm/form/Slider.js.map +1 -0
- package/dist/esm/form/Switch.js +96 -0
- package/dist/esm/form/Switch.js.map +1 -0
- package/dist/esm/form/Taginput.js +352 -0
- package/dist/esm/form/Taginput.js.map +1 -0
- package/dist/esm/form/TextArea.js +77 -0
- package/dist/esm/form/TextArea.js.map +1 -0
- package/dist/esm/form/TextAreaBase.js +45 -0
- package/dist/esm/form/TextAreaBase.js.map +1 -0
- package/dist/esm/form/TimeInput.js +83 -0
- package/dist/esm/form/TimeInput.js.map +1 -0
- package/dist/esm/form/TimeInputBase.js +246 -0
- package/dist/esm/form/TimeInputBase.js.map +1 -0
- package/dist/esm/form/_pickerInternals/Calendar.js +760 -0
- package/dist/esm/form/_pickerInternals/Calendar.js.map +1 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js +95 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -0
- package/dist/esm/form/_pickerInternals/TimeWheels.js +721 -0
- package/dist/esm/form/_pickerInternals/TimeWheels.js.map +1 -0
- package/dist/esm/form/_pickerInternals/audioTick.js +109 -0
- package/dist/esm/form/_pickerInternals/audioTick.js.map +1 -0
- package/dist/esm/form/_pickerInternals/dateUtils.js +267 -0
- package/dist/esm/form/_pickerInternals/dateUtils.js.map +1 -0
- package/dist/esm/form/_pickerInternals/formatters.js +322 -0
- package/dist/esm/form/_pickerInternals/formatters.js.map +1 -0
- package/dist/esm/form/_pickerInternals/haptics.js +38 -0
- package/dist/esm/form/_pickerInternals/haptics.js.map +1 -0
- package/dist/esm/form/_pickerInternals/nativeInputSupport.js +25 -0
- package/dist/esm/form/_pickerInternals/nativeInputSupport.js.map +1 -0
- package/dist/esm/form/_pickerInternals/pickerTypes.js +50 -0
- package/dist/esm/form/_pickerInternals/pickerTypes.js.map +1 -0
- package/dist/esm/form/_pickerInternals/segmentMap.js +315 -0
- package/dist/esm/form/_pickerInternals/segmentMap.js.map +1 -0
- package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js +49 -0
- package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js.map +1 -0
- package/dist/esm/form/_pickerInternals/useSegmentedEntry.js +427 -0
- package/dist/esm/form/_pickerInternals/useSegmentedEntry.js.map +1 -0
- package/dist/esm/form/controlLoading.js +18 -0
- package/dist/esm/form/controlLoading.js.map +1 -0
- package/dist/esm/form/useAutoLabelId.js +54 -0
- package/dist/esm/form/useAutoLabelId.js.map +1 -0
- package/dist/esm/grid/Cell.js +35 -0
- package/dist/esm/grid/Cell.js.map +1 -0
- package/dist/esm/grid/Grid.js +51 -0
- package/dist/esm/grid/Grid.js.map +1 -0
- package/dist/esm/helpers/ClientOnly.js +33 -0
- package/dist/esm/helpers/ClientOnly.js.map +1 -0
- package/dist/esm/helpers/Config.js +60 -0
- package/dist/esm/helpers/Config.js.map +1 -0
- package/dist/esm/helpers/Theme.js +947 -0
- package/dist/esm/helpers/Theme.js.map +1 -0
- package/dist/esm/helpers/anchorAttrs.js +72 -0
- package/dist/esm/helpers/anchorAttrs.js.map +1 -0
- package/dist/esm/helpers/bulmaClassHelpers.js +415 -0
- package/dist/esm/helpers/bulmaClassHelpers.js.map +1 -0
- package/dist/esm/helpers/buttonType.js +24 -0
- package/dist/esm/helpers/buttonType.js.map +1 -0
- package/dist/esm/helpers/classNames.js +137 -0
- package/dist/esm/helpers/classNames.js.map +1 -0
- package/dist/esm/helpers/colorDeprecations.js +50 -0
- package/dist/esm/helpers/colorDeprecations.js.map +1 -0
- package/dist/esm/helpers/devWarnings.js +27 -0
- package/dist/esm/helpers/devWarnings.js.map +1 -0
- package/dist/esm/helpers/inertProps.js +27 -0
- package/dist/esm/helpers/inertProps.js.map +1 -0
- package/dist/esm/helpers/mergeBulmaStyles.js +20 -0
- package/dist/esm/helpers/mergeBulmaStyles.js.map +1 -0
- package/dist/esm/helpers/polymorphic.js +18 -0
- package/dist/esm/helpers/polymorphic.js.map +1 -0
- package/dist/esm/helpers/portal.js +76 -0
- package/dist/esm/helpers/portal.js.map +1 -0
- package/dist/esm/helpers/positionStacks.js +45 -0
- package/dist/esm/helpers/positionStacks.js.map +1 -0
- package/dist/esm/helpers/scrollLock.js +38 -0
- package/dist/esm/helpers/scrollLock.js.map +1 -0
- package/dist/esm/helpers/shadowDom.js +71 -0
- package/dist/esm/helpers/shadowDom.js.map +1 -0
- package/dist/esm/helpers/statusRegion.js +282 -0
- package/dist/esm/helpers/statusRegion.js.map +1 -0
- package/dist/esm/helpers/useAnchoredPosition.js +86 -0
- package/dist/esm/helpers/useAnchoredPosition.js.map +1 -0
- package/dist/esm/helpers/useBulmaClasses.js +158 -0
- package/dist/esm/helpers/useBulmaClasses.js.map +1 -0
- package/dist/esm/helpers/useClientLayoutEffect.js +13 -0
- package/dist/esm/helpers/useClientLayoutEffect.js.map +1 -0
- package/dist/esm/helpers/useColorClasses.js +84 -0
- package/dist/esm/helpers/useColorClasses.js.map +1 -0
- package/dist/esm/helpers/useFlexboxClasses.js +92 -0
- package/dist/esm/helpers/useFlexboxClasses.js.map +1 -0
- package/dist/esm/helpers/useFocusTrap.js +470 -0
- package/dist/esm/helpers/useFocusTrap.js.map +1 -0
- package/dist/esm/helpers/useIsHydrated.js +31 -0
- package/dist/esm/helpers/useIsHydrated.js.map +1 -0
- package/dist/esm/helpers/useOtherClasses.js +115 -0
- package/dist/esm/helpers/useOtherClasses.js.map +1 -0
- package/dist/esm/helpers/useSpacingClasses.js +82 -0
- package/dist/esm/helpers/useSpacingClasses.js.map +1 -0
- package/dist/esm/helpers/useTypographyClasses.js +93 -0
- package/dist/esm/helpers/useTypographyClasses.js.map +1 -0
- package/dist/esm/helpers/useVisibilityClasses.js +134 -0
- package/dist/esm/helpers/useVisibilityClasses.js.map +1 -0
- package/dist/esm/helpers/withSubComponents.js +24 -0
- package/dist/esm/helpers/withSubComponents.js.map +1 -0
- package/dist/esm/layout/Container.js +48 -0
- package/dist/esm/layout/Container.js.map +1 -0
- package/dist/esm/layout/Footer.js +33 -0
- package/dist/esm/layout/Footer.js.map +1 -0
- package/dist/esm/layout/Hero.js +90 -0
- package/dist/esm/layout/Hero.js.map +1 -0
- package/dist/esm/layout/Level.js +110 -0
- package/dist/esm/layout/Level.js.map +1 -0
- package/dist/esm/layout/Media.js +86 -0
- package/dist/esm/layout/Media.js.map +1 -0
- package/dist/esm/layout/Section.js +30 -0
- package/dist/esm/layout/Section.js.map +1 -0
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +75 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +115 -17516
- package/dist/index.esm.js.map +1 -1
- package/dist/types/elements/Icon.d.ts +10 -7
- package/dist/types/form/DateInputBase.d.ts +3 -4
- package/dist/types/form/DateTimeInputBase.d.ts +3 -4
- package/dist/types/form/File.d.ts +3 -3
- package/dist/types-cjs/elements/Icon.d.ts +10 -7
- package/dist/types-cjs/form/DateInputBase.d.ts +3 -4
- package/dist/types-cjs/form/DateTimeInputBase.d.ts +3 -4
- package/dist/types-cjs/form/File.d.ts +3 -3
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/form/_dateinput.scss +37 -6
- package/src/scss/form/_datetimeinput.scss +7 -2
- package/src/scss/form/_picker-popover.scss +1 -4
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
import { makeDate, FIRST_YEAR } from './dateUtils.js';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD';
|
|
5
|
+
const DEFAULT_MONTH_FORMAT = 'YYYY-MM';
|
|
6
|
+
const DEFAULT_YEAR_FORMAT = 'YYYY';
|
|
7
|
+
const DEFAULT_TIME_FORMAT_24 = 'HH:mm';
|
|
8
|
+
const DEFAULT_TIME_FORMAT_12 = 'hh:mm A';
|
|
9
|
+
const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DD HH:mm';
|
|
10
|
+
const pad = (n, width = 2) => String(n).padStart(width, '0');
|
|
11
|
+
const TOKEN_RE = /YYYY|YY|MM|M|DD|D|HH|H|hh|h|mm|m|ss|s|A|a/g;
|
|
12
|
+
function formatToken(d, token) {
|
|
13
|
+
switch (token) {
|
|
14
|
+
case 'YYYY':
|
|
15
|
+
// Zero-pad to a fixed 4 chars so the rendered width matches the
|
|
16
|
+
// segment-map width during digit-by-digit keyboard entry (and to match
|
|
17
|
+
// ISO 8601), so year 19 shows as `0019`. Years >9999 keep their natural
|
|
18
|
+
// width. The pickers commit no year below 1, so a minus sign reaches
|
|
19
|
+
// this only from a `value` passed in.
|
|
20
|
+
return pad(d.getFullYear(), 4);
|
|
21
|
+
case 'YY':
|
|
22
|
+
return pad(d.getFullYear() % 100);
|
|
23
|
+
case 'MM':
|
|
24
|
+
return pad(d.getMonth() + 1);
|
|
25
|
+
case 'M':
|
|
26
|
+
return String(d.getMonth() + 1);
|
|
27
|
+
case 'DD':
|
|
28
|
+
return pad(d.getDate());
|
|
29
|
+
case 'D':
|
|
30
|
+
return String(d.getDate());
|
|
31
|
+
case 'HH':
|
|
32
|
+
return pad(d.getHours());
|
|
33
|
+
case 'H':
|
|
34
|
+
return String(d.getHours());
|
|
35
|
+
case 'hh': {
|
|
36
|
+
const h12 = d.getHours() % 12 || 12;
|
|
37
|
+
return pad(h12);
|
|
38
|
+
}
|
|
39
|
+
case 'h': {
|
|
40
|
+
const h12 = d.getHours() % 12 || 12;
|
|
41
|
+
return String(h12);
|
|
42
|
+
}
|
|
43
|
+
case 'mm':
|
|
44
|
+
return pad(d.getMinutes());
|
|
45
|
+
case 'm':
|
|
46
|
+
return String(d.getMinutes());
|
|
47
|
+
case 'ss':
|
|
48
|
+
return pad(d.getSeconds());
|
|
49
|
+
case 's':
|
|
50
|
+
return String(d.getSeconds());
|
|
51
|
+
case 'A':
|
|
52
|
+
return d.getHours() < 12 ? 'AM' : 'PM';
|
|
53
|
+
case 'a':
|
|
54
|
+
return d.getHours() < 12 ? 'am' : 'pm';
|
|
55
|
+
default:
|
|
56
|
+
return token;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function formatTokenString(d, fmt) {
|
|
60
|
+
return fmt.replace(TOKEN_RE, t => formatToken(d, t));
|
|
61
|
+
}
|
|
62
|
+
function formatWithIntl(d, options, locale) {
|
|
63
|
+
return new Intl.DateTimeFormat(locale, options).format(d);
|
|
64
|
+
}
|
|
65
|
+
function formatDate(d, fmt, locale) {
|
|
66
|
+
const f = fmt ?? DEFAULT_DATE_FORMAT;
|
|
67
|
+
if (typeof f === 'string')
|
|
68
|
+
return formatTokenString(d, f);
|
|
69
|
+
return formatWithIntl(d, f, locale);
|
|
70
|
+
}
|
|
71
|
+
function formatTime(d, fmt, locale) {
|
|
72
|
+
const f = fmt ?? DEFAULT_TIME_FORMAT_24;
|
|
73
|
+
if (typeof f === 'string')
|
|
74
|
+
return formatTokenString(d, f);
|
|
75
|
+
return formatWithIntl(d, f, locale);
|
|
76
|
+
}
|
|
77
|
+
function formatDateTime(d, fmt, locale) {
|
|
78
|
+
const f = fmt ?? DEFAULT_DATETIME_FORMAT;
|
|
79
|
+
if (typeof f === 'string')
|
|
80
|
+
return formatTokenString(d, f);
|
|
81
|
+
return formatWithIntl(d, f, locale);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The value as a native input and a hidden form input carry it:
|
|
85
|
+
* `YYYY-MM-DD`, `YYYY-MM` or `YYYY`, the shapes `<input type="date">` and
|
|
86
|
+
* `<input type="month">` use. The year is padded to four digits, as those
|
|
87
|
+
* inputs require and as the `YYYY` token displays it. HTML has no such shape
|
|
88
|
+
* for a year before 1, so a date then is empty, as those inputs would make it.
|
|
89
|
+
*/
|
|
90
|
+
function toIsoValue(d, granularity) {
|
|
91
|
+
if (d.getFullYear() < FIRST_YEAR)
|
|
92
|
+
return '';
|
|
93
|
+
const year = pad(d.getFullYear(), 4);
|
|
94
|
+
if (granularity === 'year')
|
|
95
|
+
return year;
|
|
96
|
+
const month = `${year}-${pad(d.getMonth() + 1)}`;
|
|
97
|
+
return granularity === 'month' ? month : `${month}-${pad(d.getDate())}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Read a native `type="date"` or `type="month"` value back into a Date. HTML
|
|
101
|
+
* allows a year of four or more digits, as `toIsoValue` writes one past 9999.
|
|
102
|
+
*/
|
|
103
|
+
function fromIsoValue(s, granularity) {
|
|
104
|
+
if (granularity === 'month') {
|
|
105
|
+
const m = /^(\d{4,})-(\d{2})$/.exec(s);
|
|
106
|
+
return m ? makeDate(Number(m[1]), Number(m[2]) - 1) : null;
|
|
107
|
+
}
|
|
108
|
+
const m = /^(\d{4,})-(\d{2})-(\d{2})$/.exec(s);
|
|
109
|
+
if (!m)
|
|
110
|
+
return null;
|
|
111
|
+
return makeDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Derive the hour cycle (`'12'` or `'24'`) a display format will render, from
|
|
115
|
+
* its first hour token: `h`/`hh` → 12-hour with meridiem, `H`/`HH` → 24-hour.
|
|
116
|
+
*
|
|
117
|
+
* Returns `null` when the cycle can't be read from the format — it's an
|
|
118
|
+
* `Intl.DateTimeFormat` options object (no token string), `undefined`, or has
|
|
119
|
+
* no hour token — so callers fall back to the raw `hourFormat` prop. Scans with
|
|
120
|
+
* the same {@link TOKEN_RE} grammar the input renders with, so the derived cycle
|
|
121
|
+
* always agrees with what the field actually displays.
|
|
122
|
+
*/
|
|
123
|
+
function hourCycleFromFormat(fmt) {
|
|
124
|
+
if (typeof fmt !== 'string')
|
|
125
|
+
return null;
|
|
126
|
+
for (const [token] of fmt.matchAll(TOKEN_RE)) {
|
|
127
|
+
if (token === 'H' || token === 'HH')
|
|
128
|
+
return '24';
|
|
129
|
+
if (token === 'h' || token === 'hh')
|
|
130
|
+
return '12';
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Parse a date string against a token format. Returns null on mismatch.
|
|
136
|
+
* For Intl-options formats parsing is the consumer's responsibility — pass
|
|
137
|
+
* a custom `parse` prop on the picker.
|
|
138
|
+
*/
|
|
139
|
+
function parseDate(s, fmt,
|
|
140
|
+
// locale arg accepted for symmetry; locale-aware parsing is not supported.
|
|
141
|
+
_locale) {
|
|
142
|
+
if (!s)
|
|
143
|
+
return null;
|
|
144
|
+
const format = fmt ?? DEFAULT_DATE_FORMAT;
|
|
145
|
+
const parts = parseTokens(s, format);
|
|
146
|
+
if (!parts)
|
|
147
|
+
return null;
|
|
148
|
+
const year = parts.year ?? new Date().getFullYear();
|
|
149
|
+
const month = (parts.month ?? 1) - 1;
|
|
150
|
+
const day = parts.day ?? 1;
|
|
151
|
+
const hours = parts.hours ?? 0;
|
|
152
|
+
const minutes = parts.minutes ?? 0;
|
|
153
|
+
const seconds = parts.seconds ?? 0;
|
|
154
|
+
const d = makeDate(year, month, day);
|
|
155
|
+
d.setHours(hours, minutes, seconds, 0);
|
|
156
|
+
if (d.getFullYear() !== year ||
|
|
157
|
+
d.getMonth() !== month ||
|
|
158
|
+
d.getDate() !== day) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
return d;
|
|
162
|
+
}
|
|
163
|
+
function parseTime(s, fmt) {
|
|
164
|
+
if (!s)
|
|
165
|
+
return null;
|
|
166
|
+
const format = fmt ?? DEFAULT_TIME_FORMAT_24;
|
|
167
|
+
const parts = parseTokens(s, format);
|
|
168
|
+
if (!parts)
|
|
169
|
+
return null;
|
|
170
|
+
const today = new Date();
|
|
171
|
+
return new Date(today.getFullYear(), today.getMonth(), today.getDate(), parts.hours ?? 0, parts.minutes ?? 0, parts.seconds ?? 0, 0);
|
|
172
|
+
}
|
|
173
|
+
function escapeRegExp(s) {
|
|
174
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
175
|
+
}
|
|
176
|
+
function parseTokens(input, fmt) {
|
|
177
|
+
const tokenOrder = [];
|
|
178
|
+
let regex = '';
|
|
179
|
+
let i = 0;
|
|
180
|
+
while (i < fmt.length) {
|
|
181
|
+
const four = fmt.slice(i, i + 4);
|
|
182
|
+
const two = fmt.slice(i, i + 2);
|
|
183
|
+
const one = fmt[i];
|
|
184
|
+
let token = null;
|
|
185
|
+
if (four === 'YYYY')
|
|
186
|
+
token = 'YYYY';
|
|
187
|
+
else if (two === 'YY' ||
|
|
188
|
+
two === 'MM' ||
|
|
189
|
+
two === 'DD' ||
|
|
190
|
+
two === 'HH' ||
|
|
191
|
+
two === 'hh' ||
|
|
192
|
+
two === 'mm' ||
|
|
193
|
+
two === 'ss')
|
|
194
|
+
token = two;
|
|
195
|
+
else if (one === 'M' ||
|
|
196
|
+
one === 'D' ||
|
|
197
|
+
one === 'H' ||
|
|
198
|
+
one === 'h' ||
|
|
199
|
+
one === 'm' ||
|
|
200
|
+
one === 's' ||
|
|
201
|
+
one === 'A' ||
|
|
202
|
+
one === 'a')
|
|
203
|
+
token = one;
|
|
204
|
+
if (token) {
|
|
205
|
+
tokenOrder.push(token);
|
|
206
|
+
switch (token) {
|
|
207
|
+
case 'YYYY':
|
|
208
|
+
regex += '(\\d{4})';
|
|
209
|
+
break;
|
|
210
|
+
case 'YY':
|
|
211
|
+
regex += '(\\d{2})';
|
|
212
|
+
break;
|
|
213
|
+
case 'MM':
|
|
214
|
+
case 'DD':
|
|
215
|
+
case 'HH':
|
|
216
|
+
case 'hh':
|
|
217
|
+
case 'mm':
|
|
218
|
+
case 'ss':
|
|
219
|
+
regex += '(\\d{1,2})';
|
|
220
|
+
break;
|
|
221
|
+
case 'M':
|
|
222
|
+
case 'D':
|
|
223
|
+
case 'H':
|
|
224
|
+
case 'h':
|
|
225
|
+
case 'm':
|
|
226
|
+
case 's':
|
|
227
|
+
regex += '(\\d{1,2})';
|
|
228
|
+
break;
|
|
229
|
+
case 'A':
|
|
230
|
+
regex += '(AM|PM)';
|
|
231
|
+
break;
|
|
232
|
+
case 'a':
|
|
233
|
+
regex += '(am|pm)';
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
i += token.length;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
regex += escapeRegExp(one);
|
|
240
|
+
i += 1;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const m = new RegExp('^' + regex + '$').exec(input);
|
|
244
|
+
if (!m)
|
|
245
|
+
return null;
|
|
246
|
+
const out = {};
|
|
247
|
+
tokenOrder.forEach((token, idx) => {
|
|
248
|
+
const v = m[idx + 1];
|
|
249
|
+
switch (token) {
|
|
250
|
+
case 'YYYY':
|
|
251
|
+
out.year = Number(v);
|
|
252
|
+
break;
|
|
253
|
+
case 'YY':
|
|
254
|
+
out.year = 2000 + Number(v);
|
|
255
|
+
break;
|
|
256
|
+
case 'MM':
|
|
257
|
+
case 'M':
|
|
258
|
+
out.month = Number(v);
|
|
259
|
+
break;
|
|
260
|
+
case 'DD':
|
|
261
|
+
case 'D':
|
|
262
|
+
out.day = Number(v);
|
|
263
|
+
break;
|
|
264
|
+
case 'HH':
|
|
265
|
+
case 'H':
|
|
266
|
+
out.hours = Number(v);
|
|
267
|
+
break;
|
|
268
|
+
case 'hh':
|
|
269
|
+
case 'h':
|
|
270
|
+
out.hours = Number(v);
|
|
271
|
+
break;
|
|
272
|
+
case 'mm':
|
|
273
|
+
case 'm':
|
|
274
|
+
out.minutes = Number(v);
|
|
275
|
+
break;
|
|
276
|
+
case 'ss':
|
|
277
|
+
case 's':
|
|
278
|
+
out.seconds = Number(v);
|
|
279
|
+
break;
|
|
280
|
+
case 'A':
|
|
281
|
+
out.meridiem = v.toLowerCase() === 'am' ? 'am' : 'pm';
|
|
282
|
+
break;
|
|
283
|
+
case 'a':
|
|
284
|
+
out.meridiem = v === 'am' ? 'am' : 'pm';
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
if (out.meridiem !== undefined && out.hours !== undefined) {
|
|
289
|
+
if (out.meridiem === 'pm' && out.hours < 12)
|
|
290
|
+
out.hours += 12;
|
|
291
|
+
if (out.meridiem === 'am' && out.hours === 12)
|
|
292
|
+
out.hours = 0;
|
|
293
|
+
}
|
|
294
|
+
return out;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Locale-aware day name labels in calendar order (Sunday → Saturday).
|
|
298
|
+
* Caller rotates by `firstDayOfWeek`.
|
|
299
|
+
*/
|
|
300
|
+
function getDayNames(locale, length = 'short') {
|
|
301
|
+
const fmt = new Intl.DateTimeFormat(locale, { weekday: length });
|
|
302
|
+
// 2021-01-03 was a Sunday; use it as the anchor.
|
|
303
|
+
const sunday = new Date(2021, 0, 3);
|
|
304
|
+
const out = [];
|
|
305
|
+
for (let i = 0; i < 7; i++) {
|
|
306
|
+
const d = new Date(sunday);
|
|
307
|
+
d.setDate(sunday.getDate() + i);
|
|
308
|
+
out.push(fmt.format(d));
|
|
309
|
+
}
|
|
310
|
+
return out;
|
|
311
|
+
}
|
|
312
|
+
function getMonthNames(locale, length = 'long') {
|
|
313
|
+
const fmt = new Intl.DateTimeFormat(locale, { month: length });
|
|
314
|
+
const out = [];
|
|
315
|
+
for (let i = 0; i < 12; i++) {
|
|
316
|
+
out.push(fmt.format(new Date(2021, i, 1)));
|
|
317
|
+
}
|
|
318
|
+
return out;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export { DEFAULT_DATETIME_FORMAT, DEFAULT_DATE_FORMAT, DEFAULT_MONTH_FORMAT, DEFAULT_TIME_FORMAT_12, DEFAULT_TIME_FORMAT_24, DEFAULT_YEAR_FORMAT, formatDate, formatDateTime, formatTime, fromIsoValue, getDayNames, getMonthNames, hourCycleFromFormat, parseDate, parseTime, toIsoValue };
|
|
322
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sources":["../../../../src/form/_pickerInternals/formatters.ts"],"sourcesContent":["import { FIRST_YEAR, makeDate } from './dateUtils';\nimport type { DateGranularity } from './pickerTypes';\n\nexport type DateFormatOption = Intl.DateTimeFormatOptions | string;\n\nexport const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD';\nexport const DEFAULT_MONTH_FORMAT = 'YYYY-MM';\nexport const DEFAULT_YEAR_FORMAT = 'YYYY';\nexport const DEFAULT_TIME_FORMAT_24 = 'HH:mm';\nexport const DEFAULT_TIME_FORMAT_12 = 'hh:mm A';\nexport const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DD HH:mm';\n\nconst pad = (n: number, width = 2): string => String(n).padStart(width, '0');\n\nconst TOKEN_RE = /YYYY|YY|MM|M|DD|D|HH|H|hh|h|mm|m|ss|s|A|a/g;\n\nfunction formatToken(d: Date, token: string): string {\n switch (token) {\n case 'YYYY':\n // Zero-pad to a fixed 4 chars so the rendered width matches the\n // segment-map width during digit-by-digit keyboard entry (and to match\n // ISO 8601), so year 19 shows as `0019`. Years >9999 keep their natural\n // width. The pickers commit no year below 1, so a minus sign reaches\n // this only from a `value` passed in.\n return pad(d.getFullYear(), 4);\n case 'YY':\n return pad(d.getFullYear() % 100);\n case 'MM':\n return pad(d.getMonth() + 1);\n case 'M':\n return String(d.getMonth() + 1);\n case 'DD':\n return pad(d.getDate());\n case 'D':\n return String(d.getDate());\n case 'HH':\n return pad(d.getHours());\n case 'H':\n return String(d.getHours());\n case 'hh': {\n const h12 = d.getHours() % 12 || 12;\n return pad(h12);\n }\n case 'h': {\n const h12 = d.getHours() % 12 || 12;\n return String(h12);\n }\n case 'mm':\n return pad(d.getMinutes());\n case 'm':\n return String(d.getMinutes());\n case 'ss':\n return pad(d.getSeconds());\n case 's':\n return String(d.getSeconds());\n case 'A':\n return d.getHours() < 12 ? 'AM' : 'PM';\n case 'a':\n return d.getHours() < 12 ? 'am' : 'pm';\n default:\n return token;\n }\n}\n\nfunction formatTokenString(d: Date, fmt: string): string {\n return fmt.replace(TOKEN_RE, t => formatToken(d, t));\n}\n\nfunction formatWithIntl(\n d: Date,\n options: Intl.DateTimeFormatOptions,\n locale?: string\n): string {\n return new Intl.DateTimeFormat(locale, options).format(d);\n}\n\nexport function formatDate(\n d: Date,\n fmt: DateFormatOption | undefined,\n locale?: string\n): string {\n const f = fmt ?? DEFAULT_DATE_FORMAT;\n if (typeof f === 'string') return formatTokenString(d, f);\n return formatWithIntl(d, f, locale);\n}\n\nexport function formatTime(\n d: Date,\n fmt: DateFormatOption | undefined,\n locale?: string\n): string {\n const f = fmt ?? DEFAULT_TIME_FORMAT_24;\n if (typeof f === 'string') return formatTokenString(d, f);\n return formatWithIntl(d, f, locale);\n}\n\nexport function formatDateTime(\n d: Date,\n fmt: DateFormatOption | undefined,\n locale?: string\n): string {\n const f = fmt ?? DEFAULT_DATETIME_FORMAT;\n if (typeof f === 'string') return formatTokenString(d, f);\n return formatWithIntl(d, f, locale);\n}\n\n/**\n * The value as a native input and a hidden form input carry it:\n * `YYYY-MM-DD`, `YYYY-MM` or `YYYY`, the shapes `<input type=\"date\">` and\n * `<input type=\"month\">` use. The year is padded to four digits, as those\n * inputs require and as the `YYYY` token displays it. HTML has no such shape\n * for a year before 1, so a date then is empty, as those inputs would make it.\n */\nexport function toIsoValue(d: Date, granularity: DateGranularity): string {\n if (d.getFullYear() < FIRST_YEAR) return '';\n const year = pad(d.getFullYear(), 4);\n if (granularity === 'year') return year;\n const month = `${year}-${pad(d.getMonth() + 1)}`;\n return granularity === 'month' ? month : `${month}-${pad(d.getDate())}`;\n}\n\n/**\n * Read a native `type=\"date\"` or `type=\"month\"` value back into a Date. HTML\n * allows a year of four or more digits, as `toIsoValue` writes one past 9999.\n */\nexport function fromIsoValue(\n s: string,\n granularity: DateGranularity\n): Date | null {\n if (granularity === 'month') {\n const m = /^(\\d{4,})-(\\d{2})$/.exec(s);\n return m ? makeDate(Number(m[1]), Number(m[2]) - 1) : null;\n }\n const m = /^(\\d{4,})-(\\d{2})-(\\d{2})$/.exec(s);\n if (!m) return null;\n return makeDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));\n}\n\n/**\n * Derive the hour cycle (`'12'` or `'24'`) a display format will render, from\n * its first hour token: `h`/`hh` → 12-hour with meridiem, `H`/`HH` → 24-hour.\n *\n * Returns `null` when the cycle can't be read from the format — it's an\n * `Intl.DateTimeFormat` options object (no token string), `undefined`, or has\n * no hour token — so callers fall back to the raw `hourFormat` prop. Scans with\n * the same {@link TOKEN_RE} grammar the input renders with, so the derived cycle\n * always agrees with what the field actually displays.\n */\nexport function hourCycleFromFormat(\n fmt: DateFormatOption | undefined\n): '12' | '24' | null {\n if (typeof fmt !== 'string') return null;\n for (const [token] of fmt.matchAll(TOKEN_RE)) {\n if (token === 'H' || token === 'HH') return '24';\n if (token === 'h' || token === 'hh') return '12';\n }\n return null;\n}\n\n/**\n * Parse a date string against a token format. Returns null on mismatch.\n * For Intl-options formats parsing is the consumer's responsibility — pass\n * a custom `parse` prop on the picker.\n */\nexport function parseDate(\n s: string,\n fmt?: string,\n // locale arg accepted for symmetry; locale-aware parsing is not supported.\n _locale?: string\n): Date | null {\n if (!s) return null;\n const format = fmt ?? DEFAULT_DATE_FORMAT;\n const parts = parseTokens(s, format);\n if (!parts) return null;\n const year = parts.year ?? new Date().getFullYear();\n const month = (parts.month ?? 1) - 1;\n const day = parts.day ?? 1;\n const hours = parts.hours ?? 0;\n const minutes = parts.minutes ?? 0;\n const seconds = parts.seconds ?? 0;\n const d = makeDate(year, month, day);\n d.setHours(hours, minutes, seconds, 0);\n if (\n d.getFullYear() !== year ||\n d.getMonth() !== month ||\n d.getDate() !== day\n ) {\n return null;\n }\n return d;\n}\n\nexport function parseTime(s: string, fmt?: string): Date | null {\n if (!s) return null;\n const format = fmt ?? DEFAULT_TIME_FORMAT_24;\n const parts = parseTokens(s, format);\n if (!parts) return null;\n const today = new Date();\n return new Date(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n parts.hours ?? 0,\n parts.minutes ?? 0,\n parts.seconds ?? 0,\n 0\n );\n}\n\ninterface ParsedParts {\n year?: number;\n month?: number;\n day?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n meridiem?: 'am' | 'pm';\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction parseTokens(input: string, fmt: string): ParsedParts | null {\n const tokenOrder: string[] = [];\n let regex = '';\n let i = 0;\n while (i < fmt.length) {\n const four = fmt.slice(i, i + 4);\n const two = fmt.slice(i, i + 2);\n const one = fmt[i];\n let token: string | null = null;\n if (four === 'YYYY') token = 'YYYY';\n else if (\n two === 'YY' ||\n two === 'MM' ||\n two === 'DD' ||\n two === 'HH' ||\n two === 'hh' ||\n two === 'mm' ||\n two === 'ss'\n )\n token = two;\n else if (\n one === 'M' ||\n one === 'D' ||\n one === 'H' ||\n one === 'h' ||\n one === 'm' ||\n one === 's' ||\n one === 'A' ||\n one === 'a'\n )\n token = one;\n\n if (token) {\n tokenOrder.push(token);\n switch (token) {\n case 'YYYY':\n regex += '(\\\\d{4})';\n break;\n case 'YY':\n regex += '(\\\\d{2})';\n break;\n case 'MM':\n case 'DD':\n case 'HH':\n case 'hh':\n case 'mm':\n case 'ss':\n regex += '(\\\\d{1,2})';\n break;\n case 'M':\n case 'D':\n case 'H':\n case 'h':\n case 'm':\n case 's':\n regex += '(\\\\d{1,2})';\n break;\n case 'A':\n regex += '(AM|PM)';\n break;\n case 'a':\n regex += '(am|pm)';\n break;\n }\n i += token.length;\n } else {\n regex += escapeRegExp(one);\n i += 1;\n }\n }\n const m = new RegExp('^' + regex + '$').exec(input);\n if (!m) return null;\n const out: ParsedParts = {};\n tokenOrder.forEach((token, idx) => {\n const v = m[idx + 1];\n switch (token) {\n case 'YYYY':\n out.year = Number(v);\n break;\n case 'YY':\n out.year = 2000 + Number(v);\n break;\n case 'MM':\n case 'M':\n out.month = Number(v);\n break;\n case 'DD':\n case 'D':\n out.day = Number(v);\n break;\n case 'HH':\n case 'H':\n out.hours = Number(v);\n break;\n case 'hh':\n case 'h':\n out.hours = Number(v);\n break;\n case 'mm':\n case 'm':\n out.minutes = Number(v);\n break;\n case 'ss':\n case 's':\n out.seconds = Number(v);\n break;\n case 'A':\n out.meridiem = v.toLowerCase() === 'am' ? 'am' : 'pm';\n break;\n case 'a':\n out.meridiem = v === 'am' ? 'am' : 'pm';\n break;\n }\n });\n if (out.meridiem !== undefined && out.hours !== undefined) {\n if (out.meridiem === 'pm' && out.hours < 12) out.hours += 12;\n if (out.meridiem === 'am' && out.hours === 12) out.hours = 0;\n }\n return out;\n}\n\n/**\n * Locale-aware day name labels in calendar order (Sunday → Saturday).\n * Caller rotates by `firstDayOfWeek`.\n */\nexport function getDayNames(\n locale: string | undefined,\n length: 'narrow' | 'short' | 'long' = 'short'\n): string[] {\n const fmt = new Intl.DateTimeFormat(locale, { weekday: length });\n // 2021-01-03 was a Sunday; use it as the anchor.\n const sunday = new Date(2021, 0, 3);\n const out: string[] = [];\n for (let i = 0; i < 7; i++) {\n const d = new Date(sunday);\n d.setDate(sunday.getDate() + i);\n out.push(fmt.format(d));\n }\n return out;\n}\n\nexport function getMonthNames(\n locale: string | undefined,\n length: 'short' | 'long' = 'long'\n): string[] {\n const fmt = new Intl.DateTimeFormat(locale, { month: length });\n const out: string[] = [];\n for (let i = 0; i < 12; i++) {\n out.push(fmt.format(new Date(2021, i, 1)));\n }\n return out;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
/**
|
|
3
|
+
* Tiny haptic blip used to signal each item tick on the time-wheel scroller.
|
|
4
|
+
*
|
|
5
|
+
* Implementation: feature-detect `navigator.vibrate()` and call it with a
|
|
6
|
+
* 5ms duration. Supported on Android Chrome (since v30), Firefox Android,
|
|
7
|
+
* and Samsung Internet. Silently no-ops elsewhere.
|
|
8
|
+
*
|
|
9
|
+
* iOS Safari does not expose `navigator.vibrate` and has no other web-
|
|
10
|
+
* accessible haptic API as of May 2026. We previously shipped a fallback
|
|
11
|
+
* that toggled a hidden `<input type="checkbox" switch>` element via
|
|
12
|
+
* `.click()` — that produced toggle haptics on iOS 17.4 through 26.4, but
|
|
13
|
+
* Apple patched the loophole in iOS 26.5: haptics now only fire on
|
|
14
|
+
* genuine, user-initiated taps on a visible switch, not on programmatic
|
|
15
|
+
* invocation. There is no public WebKit ticket for the patch; it's
|
|
16
|
+
* documented in the `tijnjh/ios-haptics` README and downstream community
|
|
17
|
+
* write-ups. The Web Audio "silent buffer" trick unlocks audio playback
|
|
18
|
+
* but never produced Taptic Engine output. PWAs added to the Home Screen
|
|
19
|
+
* use the same WebKit and gain no extra haptic capability.
|
|
20
|
+
*
|
|
21
|
+
* If you need haptics on iOS, the only path today is wrapping the web view
|
|
22
|
+
* in a native shell (Capacitor, react-native-webview) and bridging to
|
|
23
|
+
* `UIImpactFeedbackGenerator`. Pure web cannot do it.
|
|
24
|
+
*/
|
|
25
|
+
const tickHaptic = () => {
|
|
26
|
+
if (typeof navigator !== 'undefined' &&
|
|
27
|
+
typeof navigator.vibrate === 'function') {
|
|
28
|
+
try {
|
|
29
|
+
navigator.vibrate(5);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Some browsers throw on hidden documents — swallow.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { tickHaptic };
|
|
38
|
+
//# sourceMappingURL=haptics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"haptics.js","sources":["../../../../src/form/_pickerInternals/haptics.ts"],"sourcesContent":["/**\n * Tiny haptic blip used to signal each item tick on the time-wheel scroller.\n *\n * Implementation: feature-detect `navigator.vibrate()` and call it with a\n * 5ms duration. Supported on Android Chrome (since v30), Firefox Android,\n * and Samsung Internet. Silently no-ops elsewhere.\n *\n * iOS Safari does not expose `navigator.vibrate` and has no other web-\n * accessible haptic API as of May 2026. We previously shipped a fallback\n * that toggled a hidden `<input type=\"checkbox\" switch>` element via\n * `.click()` — that produced toggle haptics on iOS 17.4 through 26.4, but\n * Apple patched the loophole in iOS 26.5: haptics now only fire on\n * genuine, user-initiated taps on a visible switch, not on programmatic\n * invocation. There is no public WebKit ticket for the patch; it's\n * documented in the `tijnjh/ios-haptics` README and downstream community\n * write-ups. The Web Audio \"silent buffer\" trick unlocks audio playback\n * but never produced Taptic Engine output. PWAs added to the Home Screen\n * use the same WebKit and gain no extra haptic capability.\n *\n * If you need haptics on iOS, the only path today is wrapping the web view\n * in a native shell (Capacitor, react-native-webview) and bridging to\n * `UIImpactFeedbackGenerator`. Pure web cannot do it.\n */\nexport const tickHaptic = (): void => {\n if (\n typeof navigator !== 'undefined' &&\n typeof navigator.vibrate === 'function'\n ) {\n try {\n navigator.vibrate(5);\n } catch {\n // Some browsers throw on hidden documents — swallow.\n }\n }\n};\n"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACI,MAAM,UAAU,GAAG,MAAW;IACnC,IACE,OAAO,SAAS,KAAK,WAAW;AAChC,QAAA,OAAO,SAAS,CAAC,OAAO,KAAK,UAAU,EACvC;AACA,QAAA,IAAI;AACF,YAAA,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACtB;AAAE,QAAA,MAAM;;QAER;IACF;AACF;;"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
const support = new Map();
|
|
3
|
+
/**
|
|
4
|
+
* Whether this browser implements `<input type={type}>`. A browser that
|
|
5
|
+
* doesn't know a type reads it back as `'text'`, so this sets the type on a
|
|
6
|
+
* detached input and checks what sticks. The answer can't change within a
|
|
7
|
+
* page, so it is worked out once per type.
|
|
8
|
+
*
|
|
9
|
+
* It needs a DOM, so callers ask only after hydration. It also can't see a
|
|
10
|
+
* browser that recognises a type without drawing a control for it: desktop
|
|
11
|
+
* Safari reports `'month'` but shows a plain text box.
|
|
12
|
+
*/
|
|
13
|
+
function supportsInputType(type) {
|
|
14
|
+
let supported = support.get(type);
|
|
15
|
+
if (supported === undefined) {
|
|
16
|
+
const input = document.createElement('input');
|
|
17
|
+
input.setAttribute('type', type);
|
|
18
|
+
supported = input.type === type;
|
|
19
|
+
support.set(type, supported);
|
|
20
|
+
}
|
|
21
|
+
return supported;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { supportsInputType };
|
|
25
|
+
//# sourceMappingURL=nativeInputSupport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeInputSupport.js","sources":["../../../../src/form/_pickerInternals/nativeInputSupport.ts"],"sourcesContent":["const support = new Map<string, boolean>();\n\n/**\n * Whether this browser implements `<input type={type}>`. A browser that\n * doesn't know a type reads it back as `'text'`, so this sets the type on a\n * detached input and checks what sticks. The answer can't change within a\n * page, so it is worked out once per type.\n *\n * It needs a DOM, so callers ask only after hydration. It also can't see a\n * browser that recognises a type without drawing a control for it: desktop\n * Safari reports `'month'` but shows a plain text box.\n */\nexport function supportsInputType(type: string): boolean {\n let supported = support.get(type);\n if (supported === undefined) {\n const input = document.createElement('input');\n input.setAttribute('type', type);\n supported = input.type === type;\n support.set(type, supported);\n }\n return supported;\n}\n"],"names":[],"mappings":";AAAA,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB;AAE1C;;;;;;;;;AASG;AACG,SAAU,iBAAiB,CAAC,IAAY,EAAA;IAC5C,IAAI,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACjC,IAAA,IAAI,SAAS,KAAK,SAAS,EAAE;QAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC7C,QAAA,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC;AAChC,QAAA,SAAS,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI;AAC/B,QAAA,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC;IAC9B;AACA,IAAA,OAAO,SAAS;AAClB;;"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
/**
|
|
3
|
+
* Whether a key is Alt+ArrowDown or Alt+ArrowUp, which open and close a
|
|
4
|
+
* picker's popover. The calendar and the time wheels leave both to it rather
|
|
5
|
+
* than reading them as plain arrows.
|
|
6
|
+
*/
|
|
7
|
+
const isPopoverToggleKey = (e) => e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp');
|
|
8
|
+
const DEFAULT_PICKER_LABELS = {
|
|
9
|
+
prevMonth: 'Previous month',
|
|
10
|
+
nextMonth: 'Next month',
|
|
11
|
+
prevYear: 'Previous year',
|
|
12
|
+
nextYear: 'Next year',
|
|
13
|
+
chooseDate: 'Choose date',
|
|
14
|
+
chooseMonth: 'Choose month',
|
|
15
|
+
chooseYear: 'Choose year',
|
|
16
|
+
rangeStart: 'Start date',
|
|
17
|
+
rangeEnd: 'End date',
|
|
18
|
+
rangePreviewEnd: 'Choose as end date',
|
|
19
|
+
rangeSeparator: '–',
|
|
20
|
+
chooseDateRange: 'Choose date range',
|
|
21
|
+
hours: 'hours',
|
|
22
|
+
minutes: 'minutes',
|
|
23
|
+
seconds: 'seconds',
|
|
24
|
+
ampm: 'ampm',
|
|
25
|
+
increaseHours: 'Increase hours',
|
|
26
|
+
decreaseHours: 'Decrease hours',
|
|
27
|
+
increaseMinutes: 'Increase minutes',
|
|
28
|
+
decreaseMinutes: 'Decrease minutes',
|
|
29
|
+
increaseSeconds: 'Increase seconds',
|
|
30
|
+
decreaseSeconds: 'Decrease seconds',
|
|
31
|
+
toggleAmPm: 'Toggle AM/PM',
|
|
32
|
+
chooseTime: 'Choose time',
|
|
33
|
+
chooseDateTime: 'Choose date and time',
|
|
34
|
+
now: 'Now',
|
|
35
|
+
today: 'Today',
|
|
36
|
+
clear: 'Clear',
|
|
37
|
+
cancel: 'Cancel',
|
|
38
|
+
ok: 'OK',
|
|
39
|
+
reset: 'Reset',
|
|
40
|
+
done: 'Done',
|
|
41
|
+
time: 'Time',
|
|
42
|
+
};
|
|
43
|
+
/** Merge user-supplied label overrides with the defaults. */
|
|
44
|
+
const mergeLabels = (overrides) => ({
|
|
45
|
+
...DEFAULT_PICKER_LABELS,
|
|
46
|
+
...(overrides ?? {}),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export { DEFAULT_PICKER_LABELS, isPopoverToggleKey, mergeLabels };
|
|
50
|
+
//# sourceMappingURL=pickerTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pickerTypes.js","sources":["../../../../src/form/_pickerInternals/pickerTypes.ts"],"sourcesContent":["export type PickerPosition =\n 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto';\n\nexport type HourFormat = '12' | '24';\n\nexport type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\n/**\n * Whether a key is Alt+ArrowDown or Alt+ArrowUp, which open and close a\n * picker's popover. The calendar and the time wheels leave both to it rather\n * than reading them as plain arrows.\n */\nexport const isPopoverToggleKey = (e: {\n altKey: boolean;\n key: string;\n}): boolean => e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp');\n\n/** The unit a date picker selects: a day, a month or a year. */\nexport type DateGranularity = 'day' | 'month' | 'year';\n\n/**\n * A range of days, start first. Either end may be `null` while the range is\n * half filled, and `[null, null]` is empty.\n */\nexport type DateRangeValue = [Date | null, Date | null];\n\n/**\n * Translatable strings used across all four pickers. Pass via the `labels`\n * prop to override defaults; consumers manage their own locale-driven mapping.\n */\nexport interface PickerLabels {\n // Calendar\n prevMonth?: string;\n nextMonth?: string;\n /** Month grid header: steps back a year. */\n prevYear?: string;\n /** Month grid header: steps forward a year. */\n nextYear?: string;\n chooseDate?: string;\n /** Launcher and popover name when the picker selects a month. */\n chooseMonth?: string;\n /** Launcher, popover and year list name when the picker selects a year. */\n chooseYear?: string;\n /** Range picking: names the start of a range, in the calendar and the field. */\n rangeStart?: string;\n /** Range picking: names the end of a range, in the calendar and the field. */\n rangeEnd?: string;\n /**\n * Range picking: describes the day a pending range would end on, the one\n * the pointer or the keyboard is on, until it is picked.\n */\n rangePreviewEnd?: string;\n /** Range picking: shown between the start and end inputs. */\n rangeSeparator?: string;\n /** Range picking: names the launcher and the popover. */\n chooseDateRange?: string;\n // Time spinner\n hours?: string;\n minutes?: string;\n seconds?: string;\n ampm?: string;\n increaseHours?: string;\n decreaseHours?: string;\n increaseMinutes?: string;\n decreaseMinutes?: string;\n increaseSeconds?: string;\n decreaseSeconds?: string;\n toggleAmPm?: string;\n chooseTime?: string;\n chooseDateTime?: string;\n // Footer buttons\n now?: string;\n today?: string;\n clear?: string;\n cancel?: string;\n ok?: string;\n /** Mobile footer: text link that reverts to the value at open (like iOS). */\n reset?: string;\n /** Mobile footer: aria-label for the circular checkmark commit button. */\n done?: string;\n /** DateTimeInput footer: label preceding the selected-time display. */\n time?: string;\n}\n\nexport const DEFAULT_PICKER_LABELS: Required<PickerLabels> = {\n prevMonth: 'Previous month',\n nextMonth: 'Next month',\n prevYear: 'Previous year',\n nextYear: 'Next year',\n chooseDate: 'Choose date',\n chooseMonth: 'Choose month',\n chooseYear: 'Choose year',\n rangeStart: 'Start date',\n rangeEnd: 'End date',\n rangePreviewEnd: 'Choose as end date',\n rangeSeparator: '–',\n chooseDateRange: 'Choose date range',\n hours: 'hours',\n minutes: 'minutes',\n seconds: 'seconds',\n ampm: 'ampm',\n increaseHours: 'Increase hours',\n decreaseHours: 'Decrease hours',\n increaseMinutes: 'Increase minutes',\n decreaseMinutes: 'Decrease minutes',\n increaseSeconds: 'Increase seconds',\n decreaseSeconds: 'Decrease seconds',\n toggleAmPm: 'Toggle AM/PM',\n chooseTime: 'Choose time',\n chooseDateTime: 'Choose date and time',\n now: 'Now',\n today: 'Today',\n clear: 'Clear',\n cancel: 'Cancel',\n ok: 'OK',\n reset: 'Reset',\n done: 'Done',\n time: 'Time',\n};\n\n/** Merge user-supplied label overrides with the defaults. */\nexport const mergeLabels = (\n overrides?: PickerLabels\n): Required<PickerLabels> => ({\n ...DEFAULT_PICKER_LABELS,\n ...(overrides ?? {}),\n});\n"],"names":[],"mappings":";AAOA;;;;AAIG;AACI,MAAM,kBAAkB,GAAG,CAAC,CAGlC,KAAc,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;AAqEjE,MAAM,qBAAqB,GAA2B;AAC3D,IAAA,SAAS,EAAE,gBAAgB;AAC3B,IAAA,SAAS,EAAE,YAAY;AACvB,IAAA,QAAQ,EAAE,eAAe;AACzB,IAAA,QAAQ,EAAE,WAAW;AACrB,IAAA,UAAU,EAAE,aAAa;AACzB,IAAA,WAAW,EAAE,cAAc;AAC3B,IAAA,UAAU,EAAE,aAAa;AACzB,IAAA,UAAU,EAAE,YAAY;AACxB,IAAA,QAAQ,EAAE,UAAU;AACpB,IAAA,eAAe,EAAE,oBAAoB;AACrC,IAAA,cAAc,EAAE,GAAG;AACnB,IAAA,eAAe,EAAE,mBAAmB;AACpC,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,aAAa,EAAE,gBAAgB;AAC/B,IAAA,aAAa,EAAE,gBAAgB;AAC/B,IAAA,eAAe,EAAE,kBAAkB;AACnC,IAAA,eAAe,EAAE,kBAAkB;AACnC,IAAA,eAAe,EAAE,kBAAkB;AACnC,IAAA,eAAe,EAAE,kBAAkB;AACnC,IAAA,UAAU,EAAE,cAAc;AAC1B,IAAA,UAAU,EAAE,aAAa;AACzB,IAAA,cAAc,EAAE,sBAAsB;AACtC,IAAA,GAAG,EAAE,KAAK;AACV,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,EAAE,EAAE,IAAI;AACR,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,IAAI,EAAE,MAAM;;AAGd;MACa,WAAW,GAAG,CACzB,SAAwB,MACI;AAC5B,IAAA,GAAG,qBAAqB;AACxB,IAAA,IAAI,SAAS,IAAI,EAAE,CAAC;AACrB,CAAA;;"}
|