@moneyforward/mfui-components 3.18.0 → 3.20.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/dist/src/CheckboxCard/CheckboxCard.js +1 -7
- package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerProvider/DateRangePickerProvider.js +11 -12
- package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerTrigger/hooks/useDateRangeTriggerValueController.js +4 -3
- package/dist/src/DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.d.ts +6 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.js +33 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.types.d.ts +17 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.d.ts +14 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.js +42 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.types.d.ts +78 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.types.js +1 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/index.d.ts +2 -0
- package/dist/src/DateTimeSelection/FilterDateRangePicker/index.js +1 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/FilterMonthPicker.d.ts +14 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/FilterMonthPicker.js +75 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/FilterMonthPicker.types.d.ts +83 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/FilterMonthPicker.types.js +1 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/MonthPickerPopover/MonthPickerPopover.d.ts +6 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/MonthPickerPopover/MonthPickerPopover.js +45 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/MonthPickerPopover/MonthPickerPopover.types.d.ts +24 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/MonthPickerPopover/MonthPickerPopover.types.js +1 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/index.d.ts +2 -0
- package/dist/src/DateTimeSelection/FilterMonthPicker/index.js +1 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/FilterMonthRangePicker.d.ts +15 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/FilterMonthRangePicker.js +89 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/FilterMonthRangePicker.types.d.ts +75 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/FilterMonthRangePicker.types.js +1 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/MonthRangePickerPopover/MonthRangePickerPopover.d.ts +5 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/MonthRangePickerPopover/MonthRangePickerPopover.js +54 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/MonthRangePickerPopover/MonthRangePickerPopover.types.d.ts +19 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/MonthRangePickerPopover/MonthRangePickerPopover.types.js +1 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/index.d.ts +2 -0
- package/dist/src/DateTimeSelection/FilterMonthRangePicker/index.js +1 -0
- package/dist/src/DateTimeSelection/MonthRangePicker/MonthRangePicker.js +1 -1
- package/dist/src/DateTimeSelection/index.d.ts +3 -0
- package/dist/src/DateTimeSelection/index.js +3 -0
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePicker.d.ts +1 -1
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePicker.js +26 -10
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePicker.types.d.ts +9 -0
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerProvider/BaseRangePickerProvider.js +32 -15
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerProvider/BaseRangePickerProvider.types.d.ts +10 -0
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerTrigger/BaseRangePickerTrigger.js +4 -6
- package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerTrigger/hooks/useDateRangeTriggerValueController.js +4 -3
- package/dist/src/DateTimeSelection/shared/MonthGrid/MonthGrid.js +3 -3
- package/dist/src/DateTimeSelection/shared/utilities/dateParsing.js +11 -0
- package/dist/src/MultilineTextBox/index.d.ts +10 -2
- package/dist/src/MultilineTextBox/index.js +9 -1
- package/dist/src/MultipleSelectBox/MultipleSelectBoxTrigger/MultipleSelectBoxTrigger.js +1 -3
- package/dist/src/RadioButtonCard/RadioButtonCard.js +1 -7
- package/dist/src/TextBox/TextBox.js +2 -6
- package/dist/src/{MultilineTextBox/MultilineTextBox.d.ts → Textarea/Textarea.d.ts} +5 -2
- package/dist/src/{MultilineTextBox/MultilineTextBox.js → Textarea/Textarea.js} +9 -5
- package/dist/src/{MultilineTextBox/MultilineTextBox.types.d.ts → Textarea/Textarea.types.d.ts} +2 -2
- package/dist/src/Textarea/Textarea.types.js +1 -0
- package/dist/src/Textarea/index.d.ts +2 -0
- package/dist/src/Textarea/index.js +1 -0
- package/dist/src/Tooltip/Tooltip.js +12 -3
- package/dist/src/Typography/Typography.js +1 -3
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/styled-system/recipes/filter-date-range-picker-slot-recipe.d.ts +33 -0
- package/dist/styled-system/recipes/filter-date-range-picker-slot-recipe.js +48 -0
- package/dist/styled-system/recipes/filter-month-picker-slot-recipe.d.ts +33 -0
- package/dist/styled-system/recipes/filter-month-picker-slot-recipe.js +44 -0
- package/dist/styled-system/recipes/filter-month-range-picker-slot-recipe.d.ts +33 -0
- package/dist/styled-system/recipes/filter-month-range-picker-slot-recipe.js +44 -0
- package/dist/styled-system/recipes/index.d.ts +4 -1
- package/dist/styled-system/recipes/index.js +4 -1
- package/dist/styled-system/recipes/textarea-slot-recipe.d.ts +52 -0
- package/dist/styled-system/recipes/textarea-slot-recipe.js +64 -0
- package/dist/styles.css +433 -24
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +11 -9
- package/dist/styled-system/recipes/multiline-text-box-slot-recipe.d.ts +0 -52
- package/dist/styled-system/recipes/multiline-text-box-slot-recipe.js +0 -64
- /package/dist/src/{MultilineTextBox/MultilineTextBox.types.js → DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.types.js} +0 -0
|
@@ -29,11 +29,5 @@ export const CheckboxCard = forwardRef(({ label, layout = 'vertical', renderDeta
|
|
|
29
29
|
disableResponsive,
|
|
30
30
|
isResponsive: Boolean(responsiveSlot.narrowViewport),
|
|
31
31
|
});
|
|
32
|
-
return (_jsxs("div", { className: cx(classes.root, 'mfui-CheckboxCard__root', className), children: [_jsx(FocusIndicator, { disableNestedFocus: true, children: _jsxs(Typography, { variant: "label", className: cx(classes.inputWrapper, 'mfui-CheckboxCard__inputWrapper'), as: "label", htmlFor: props.id, children: [_jsx(Checkbox, { ref: ref, ...props, className: cx(classes.input, 'mfui-CheckboxCard__input') }), _jsx("span", { className: cx(classes.label, 'mfui-CheckboxCard__label'), children: label })] }) }), responsiveSlot.narrowViewport && disableResponsive ? (
|
|
33
|
-
/* When responsive is disabled, render single element but with both contents using CSS for switching */
|
|
34
|
-
_jsxs(_Fragment, { children: [_jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsWide, 'mfui-CheckboxCard__details'), children: responsiveSlot.base(checkboxState) }), _jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsNarrow, 'mfui-CheckboxCard__details'), children: responsiveSlot.narrowViewport(checkboxState) })] })) : responsiveSlot.narrowViewport ? (
|
|
35
|
-
/* When responsive is enabled, render separate wide/narrow elements */
|
|
36
|
-
_jsxs(_Fragment, { children: [_jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsWide, 'mfui-CheckboxCard__details'), children: responsiveSlot.base(checkboxState) }), _jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsNarrow, 'mfui-CheckboxCard__details'), children: responsiveSlot.narrowViewport(checkboxState) })] })) : responsiveSlot.base ? (
|
|
37
|
-
/* For function-based renderDetailsSlot or ResponsiveSlot with only base, use single details element */
|
|
38
|
-
_jsx("div", { "data-mfui-content": "details", className: cx(classes.details, 'mfui-CheckboxCard__details'), children: responsiveSlot.base(checkboxState) })) : null] }));
|
|
32
|
+
return (_jsxs("div", { className: cx(classes.root, 'mfui-CheckboxCard__root', className), children: [_jsx(FocusIndicator, { disableNestedFocus: true, children: _jsxs(Typography, { variant: "label", className: cx(classes.inputWrapper, 'mfui-CheckboxCard__inputWrapper'), as: "label", htmlFor: props.id, children: [_jsx(Checkbox, { ref: ref, ...props, className: cx(classes.input, 'mfui-CheckboxCard__input') }), _jsx("span", { className: cx(classes.label, 'mfui-CheckboxCard__label'), children: label })] }) }), responsiveSlot.narrowViewport && disableResponsive ? (_jsxs(_Fragment, { children: [_jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsWide, 'mfui-CheckboxCard__details'), children: responsiveSlot.base(checkboxState) }), _jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsNarrow, 'mfui-CheckboxCard__details'), children: responsiveSlot.narrowViewport(checkboxState) })] })) : responsiveSlot.narrowViewport ? (_jsxs(_Fragment, { children: [_jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsWide, 'mfui-CheckboxCard__details'), children: responsiveSlot.base(checkboxState) }), _jsx("div", { "data-mfui-content": "details", className: cx(classes.details, classes.detailsNarrow, 'mfui-CheckboxCard__details'), children: responsiveSlot.narrowViewport(checkboxState) })] })) : responsiveSlot.base ? (_jsx("div", { "data-mfui-content": "details", className: cx(classes.details, 'mfui-CheckboxCard__details'), children: responsiveSlot.base(checkboxState) })) : null] }));
|
|
39
33
|
});
|
|
@@ -5,6 +5,7 @@ import { flushSync } from 'react-dom';
|
|
|
5
5
|
import { dayjs } from '../../../utilities/date/dayjs';
|
|
6
6
|
import { useUpdateEffect } from '../../../utilities/effect/useUpdateEffect';
|
|
7
7
|
import { useTransformedState } from '../../../utilities/state/useTransformedState';
|
|
8
|
+
import { parseInputDateSimple } from '../../shared/utilities/dateParsing';
|
|
8
9
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
9
10
|
const noop = () => { };
|
|
10
11
|
// Normalizes a date to the first of the month
|
|
@@ -92,14 +93,13 @@ const useDateRangePickerContextValue = ({ value, defaultValue, disabled = false,
|
|
|
92
93
|
const handleStartDateStringChange = useCallback((value) => {
|
|
93
94
|
setDateStrings([value, endDateString]);
|
|
94
95
|
// Parse and update both viewing month and temporary selection for immediate visual feedback
|
|
95
|
-
const parsedDate =
|
|
96
|
-
if (parsedDate
|
|
97
|
-
|
|
98
|
-
setViewingMonth(newDate);
|
|
96
|
+
const parsedDate = parseInputDateSimple(value, format);
|
|
97
|
+
if (parsedDate && !isDateOutsideConstraints(parsedDate, minDate, maxDate)) {
|
|
98
|
+
setViewingMonth(parsedDate);
|
|
99
99
|
// Update temporary selection for immediate calendar visual feedback
|
|
100
|
-
setTemporaryStart(
|
|
100
|
+
setTemporaryStart(parsedDate);
|
|
101
101
|
// Set pending focus date so when calendar opens, it focuses on this date
|
|
102
|
-
setPendingFocusDate(parsedDate.format('YYYY-MM-DD'));
|
|
102
|
+
setPendingFocusDate(dayjs(parsedDate).format('YYYY-MM-DD'));
|
|
103
103
|
}
|
|
104
104
|
else if (value === '') {
|
|
105
105
|
// Clear temporary selection if input is empty
|
|
@@ -110,14 +110,13 @@ const useDateRangePickerContextValue = ({ value, defaultValue, disabled = false,
|
|
|
110
110
|
const handleEndDateStringChange = useCallback((value) => {
|
|
111
111
|
setDateStrings([startDateString, value]);
|
|
112
112
|
// Parse and update both viewing month and temporary selection for immediate visual feedback
|
|
113
|
-
const parsedDate =
|
|
114
|
-
if (parsedDate
|
|
115
|
-
|
|
116
|
-
setViewingMonth(newDate);
|
|
113
|
+
const parsedDate = parseInputDateSimple(value, format);
|
|
114
|
+
if (parsedDate && !isDateOutsideConstraints(parsedDate, minDate, maxDate)) {
|
|
115
|
+
setViewingMonth(parsedDate);
|
|
117
116
|
// Update temporary selection for immediate calendar visual feedback
|
|
118
|
-
setTemporaryEnd(
|
|
117
|
+
setTemporaryEnd(parsedDate);
|
|
119
118
|
// Set pending focus date so when calendar opens, it focuses on this date
|
|
120
|
-
setPendingFocusDate(parsedDate.format('YYYY-MM-DD'));
|
|
119
|
+
setPendingFocusDate(dayjs(parsedDate).format('YYYY-MM-DD'));
|
|
121
120
|
}
|
|
122
121
|
else if (value === '') {
|
|
123
122
|
// Clear temporary selection if input is empty
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { dayjs } from '../../../../utilities/date/dayjs';
|
|
3
3
|
import { useDateRangePickerContext } from '../../DateRangePickerProvider';
|
|
4
|
+
import { parseInputDateSimple } from '../../../shared/utilities/dateParsing';
|
|
4
5
|
const createInputProps = (baseProps, value, format, onStringChange, onDateChange, otherDate, isDateDisabled) => ({
|
|
5
6
|
...baseProps,
|
|
6
7
|
value,
|
|
@@ -15,12 +16,12 @@ const createInputProps = (baseProps, value, format, onStringChange, onDateChange
|
|
|
15
16
|
if (event.defaultPrevented)
|
|
16
17
|
return;
|
|
17
18
|
baseProps.onBlur?.(event);
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
19
|
+
const parsedDate = parseInputDateSimple(value, format);
|
|
20
|
+
if (!parsedDate) {
|
|
20
21
|
onDateChange(undefined, otherDate);
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
|
-
const currentDate =
|
|
24
|
+
const currentDate = dayjs(parsedDate).startOf('day').toDate();
|
|
24
25
|
// Check if the date is disabled due to constraints
|
|
25
26
|
if (isDateDisabled?.(currentDate)) {
|
|
26
27
|
// Clear the input if the date violates constraints
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type InternalDateRangePickerContentProps } from './DateRangePickerContent.types';
|
|
2
|
+
/**
|
|
3
|
+
* Internal component that accesses BaseRangePickerContext for display and clear handling.
|
|
4
|
+
* Must be rendered inside a BaseRangePickerProvider.
|
|
5
|
+
*/
|
|
6
|
+
export declare function InternalDateRangePickerContent({ classes, triggerRef, dialogId, label, format, disabled, className, clearButtonProps, targetDOMNode, isCalendarOpen, toggleCalendar, calendarLocale, }: InternalDateRangePickerContentProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { Calendar as CalendarIcon } from '@moneyforward/mfui-icons-react';
|
|
5
|
+
import { Popover } from '../../../Popover';
|
|
6
|
+
import { FocusIndicator } from '../../../FocusIndicator';
|
|
7
|
+
import { ClearButton } from '../../../shared';
|
|
8
|
+
import { Typography } from '../../../Typography';
|
|
9
|
+
import { cx } from '../../../../styled-system/css';
|
|
10
|
+
import { dayjs } from '../../../utilities/date/dayjs';
|
|
11
|
+
import { DateRangePickerPopover } from '../../DateRangePicker/DateRangePickerPopover';
|
|
12
|
+
import { CalendarLocaleProvider } from '../../shared/CalendarLocale/CalendarLocaleContext';
|
|
13
|
+
import { useBaseRangePickerContext } from '../../shared/BaseRangePicker/BaseRangePickerProvider';
|
|
14
|
+
/**
|
|
15
|
+
* Internal component that accesses BaseRangePickerContext for display and clear handling.
|
|
16
|
+
* Must be rendered inside a BaseRangePickerProvider.
|
|
17
|
+
*/
|
|
18
|
+
export function InternalDateRangePickerContent({ classes, triggerRef, dialogId, label, format, disabled, className, clearButtonProps, targetDOMNode, isCalendarOpen, toggleCalendar, calendarLocale, }) {
|
|
19
|
+
const { startDate, endDate, handleClear: contextHandleClear, setPendingFocusDate } = useBaseRangePickerContext();
|
|
20
|
+
const formattedStartDate = startDate ? dayjs(startDate).format(format) : undefined;
|
|
21
|
+
const formattedEndDate = endDate ? dayjs(endDate).format(format) : undefined;
|
|
22
|
+
const hasValue = !!(formattedStartDate && formattedEndDate);
|
|
23
|
+
const formattedValue = hasValue ? `${formattedStartDate}〜${formattedEndDate}` : undefined;
|
|
24
|
+
const handleTriggerClear = useCallback((event) => {
|
|
25
|
+
event.stopPropagation();
|
|
26
|
+
contextHandleClear();
|
|
27
|
+
}, [contextHandleClear]);
|
|
28
|
+
const handlePopoverOpen = useCallback(() => {
|
|
29
|
+
const dateToFocus = startDate ?? endDate ?? new Date();
|
|
30
|
+
setPendingFocusDate(dayjs(dateToFocus).format('YYYY-MM-DD'));
|
|
31
|
+
}, [startDate, endDate, setPendingFocusDate]);
|
|
32
|
+
return (_jsx(Popover, { open: isCalendarOpen, targetDOMNode: targetDOMNode, minWidth: "min-content", allowedPlacements: ['bottom-start', 'top-start'], renderTrigger: ({ setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsxs("div", { ref: setTriggerRef, "data-selected": hasValue, className: cx(classes.wrapper, 'mfui-FilterDateRangePicker__wrapper'), children: [_jsx(FocusIndicator, { children: _jsxs("button", { ref: triggerRef, type: "button", disabled: disabled, className: cx(classes.trigger, 'mfui-FilterDateRangePicker__trigger', className), "data-selected": hasValue, "data-mfui-has-clear-button": hasValue, "aria-controls": dialogId, "aria-expanded": isCalendarOpen, "aria-haspopup": "dialog", onClick: togglePopover, onKeyDown: handleTriggerKeyDown, onBlur: handleTriggerBlur, children: [_jsx("span", { className: cx(classes.content, 'mfui-FilterDateRangePicker__content'), "data-mfui-content": "filter-date-range-picker-display-value", children: hasValue ? (_jsxs(Typography, { variant: "strongBody", children: [_jsx("span", { "data-mfui-content": "filter-date-range-picker-label", children: `${label}:` }), _jsx("span", { "data-mfui-content": "filter-date-range-picker-value", children: formattedValue })] })) : (_jsx(Typography, { variant: "controlLabel", children: _jsx("span", { "data-mfui-content": "filter-date-range-picker-label", children: label }) })) }), _jsx("span", { className: cx(classes.calendarIcon, 'mfui-FilterDateRangePicker__calendarIcon'), children: _jsx(CalendarIcon, { "aria-hidden": true }) })] }) }), hasValue ? (_jsx("div", { className: cx(classes.clearButtonWrapper, 'mfui-FilterDateRangePicker__clearButtonWrapper'), children: _jsx(ClearButton, { "aria-label": clearButtonProps?.['aria-label'] ?? '値をクリアする', "data-mfui-content": "filter-date-range-picker-clear-button", disabled: disabled, onClick: handleTriggerClear }) })) : null] })), renderContent: () => (_jsx("div", { id: dialogId, role: "dialog", "aria-label": label, className: cx(classes.popoverWrapper, 'mfui-FilterDateRangePicker__popoverWrapper'), children: _jsx(CalendarLocaleProvider, { value: calendarLocale, children: _jsx(DateRangePickerPopover, {}) }) })), onOpenStateChanged: toggleCalendar, onOpen: handlePopoverOpen }));
|
|
33
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type filterDateRangePickerSlotRecipe } from '../../../../styled-system/recipes';
|
|
2
|
+
import { type FilterDateRangePickerProps } from '../FilterDateRangePicker.types';
|
|
3
|
+
import { type BasePickerProps } from '../../shared/BasePicker';
|
|
4
|
+
export type InternalDateRangePickerContentProps = {
|
|
5
|
+
classes: ReturnType<typeof filterDateRangePickerSlotRecipe>;
|
|
6
|
+
triggerRef: React.RefObject<HTMLButtonElement | null>;
|
|
7
|
+
dialogId: string;
|
|
8
|
+
label: string;
|
|
9
|
+
format: string;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
className: string | undefined;
|
|
12
|
+
clearButtonProps: FilterDateRangePickerProps['clearButtonProps'];
|
|
13
|
+
targetDOMNode: FilterDateRangePickerProps['targetDOMNode'];
|
|
14
|
+
isCalendarOpen: boolean;
|
|
15
|
+
toggleCalendar: () => void;
|
|
16
|
+
calendarLocale: NonNullable<BasePickerProps['calendarLocale']>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type FilterDateRangePickerProps } from './FilterDateRangePicker.types';
|
|
2
|
+
/**
|
|
3
|
+
* FilterDateRangePicker component.
|
|
4
|
+
*
|
|
5
|
+
* A filter trigger component that allows selecting a date range via a dual-calendar picker.
|
|
6
|
+
* Displays the label alone when no range is selected, and "label:startDate〜endDate"
|
|
7
|
+
* after a range is applied. Conforms to the FilterSelectBox visual style.
|
|
8
|
+
*
|
|
9
|
+
* Note: The trigger markup intentionally does not reuse FilterTrigger because
|
|
10
|
+
* FilterTrigger hardcodes the DropdownIcon and adds a hidden <input> element,
|
|
11
|
+
* neither of which are appropriate here. FilterDateRangePicker uses CalendarIcon and
|
|
12
|
+
* has no form-field semantics.
|
|
13
|
+
*/
|
|
14
|
+
export declare function FilterDateRangePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format, clearButtonProps, disabled, className, targetDOMNode, minDate, maxDate, calendarLocale, }: FilterDateRangePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useRef } from 'react';
|
|
4
|
+
import { filterDateRangePickerSlotRecipe } from '../../../styled-system/recipes';
|
|
5
|
+
import { useDisclosure } from '../../utilities/state/useDisclosure';
|
|
6
|
+
import { BaseRangePickerProvider } from '../shared/BaseRangePicker/BaseRangePickerProvider';
|
|
7
|
+
import { InternalDateRangePickerContent } from './DateRangePickerContent/DateRangePickerContent';
|
|
8
|
+
const DEFAULT_FORMAT = 'YYYY/MM/DD';
|
|
9
|
+
/**
|
|
10
|
+
* FilterDateRangePicker component.
|
|
11
|
+
*
|
|
12
|
+
* A filter trigger component that allows selecting a date range via a dual-calendar picker.
|
|
13
|
+
* Displays the label alone when no range is selected, and "label:startDate〜endDate"
|
|
14
|
+
* after a range is applied. Conforms to the FilterSelectBox visual style.
|
|
15
|
+
*
|
|
16
|
+
* Note: The trigger markup intentionally does not reuse FilterTrigger because
|
|
17
|
+
* FilterTrigger hardcodes the DropdownIcon and adds a hidden <input> element,
|
|
18
|
+
* neither of which are appropriate here. FilterDateRangePicker uses CalendarIcon and
|
|
19
|
+
* has no form-field semantics.
|
|
20
|
+
*/
|
|
21
|
+
export function FilterDateRangePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format = DEFAULT_FORMAT, clearButtonProps, disabled = false, className, targetDOMNode, minDate, maxDate, calendarLocale = 'ja', }) {
|
|
22
|
+
const classes = filterDateRangePickerSlotRecipe();
|
|
23
|
+
const triggerRef = useRef(null);
|
|
24
|
+
const dialogId = useId();
|
|
25
|
+
const { isOpen: isCalendarOpen, open: openCalendar, close: closeCalendar, toggle: toggleCalendar, } = useDisclosure({
|
|
26
|
+
// disabled takes precedence: never open the calendar when the trigger is disabled.
|
|
27
|
+
value: disabled ? false : open,
|
|
28
|
+
// onToggle fires for Escape and outside-click; focus trigger on close.
|
|
29
|
+
onToggle: (nextOpen) => {
|
|
30
|
+
if (!nextOpen) {
|
|
31
|
+
triggerRef.current?.focus();
|
|
32
|
+
}
|
|
33
|
+
onOpenStateChanged?.(nextOpen);
|
|
34
|
+
},
|
|
35
|
+
// onClose fires for programmatic close (Apply/Cancel buttons); focus trigger there too.
|
|
36
|
+
onClose: () => {
|
|
37
|
+
triggerRef.current?.focus();
|
|
38
|
+
onOpenStateChanged?.(false);
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
return (_jsx(BaseRangePickerProvider, { value: value, defaultValue: defaultValue, format: format, isOpen: isCalendarOpen, open: openCalendar, close: closeCalendar, minDate: minDate, maxDate: maxDate, disabled: disabled, onChange: onChange, children: _jsx(InternalDateRangePickerContent, { classes: classes, triggerRef: triggerRef, dialogId: dialogId, label: label, format: format, disabled: disabled, className: className, clearButtonProps: clearButtonProps, targetDOMNode: targetDOMNode, isCalendarOpen: isCalendarOpen, toggleCalendar: toggleCalendar, calendarLocale: calendarLocale }) }));
|
|
42
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type PopoverProps } from '../../Popover';
|
|
2
|
+
import { type BasePickerProps } from '../shared/BasePicker';
|
|
3
|
+
import { type DateRangeInput } from '../shared/BaseRangePicker/BaseRangePicker.types';
|
|
4
|
+
export type FilterDateRangePickerProps = {
|
|
5
|
+
/**
|
|
6
|
+
* The label to display for the filter.
|
|
7
|
+
*/
|
|
8
|
+
label: string;
|
|
9
|
+
/**
|
|
10
|
+
* The selected date range value (controlled).
|
|
11
|
+
* Pass `[undefined, undefined]` to clear the selection in controlled mode.
|
|
12
|
+
*/
|
|
13
|
+
value?: DateRangeInput;
|
|
14
|
+
/**
|
|
15
|
+
* The default selected date range value for uncontrolled usage.
|
|
16
|
+
*/
|
|
17
|
+
defaultValue?: DateRangeInput;
|
|
18
|
+
/**
|
|
19
|
+
* Callback fired when the selected date range changes.
|
|
20
|
+
* Called with `[startDate, endDate]` when a range is applied, or `[undefined, undefined]` when cleared.
|
|
21
|
+
*
|
|
22
|
+
* @param dates - The new selected date range.
|
|
23
|
+
*/
|
|
24
|
+
onChange?: (dates: DateRangeInput) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the calendar popover is open (controlled).
|
|
27
|
+
*/
|
|
28
|
+
open?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Callback fired when the open state of the calendar changes.
|
|
31
|
+
*
|
|
32
|
+
* @param open - The new open state.
|
|
33
|
+
*/
|
|
34
|
+
onOpenStateChanged?: (open: boolean) => void;
|
|
35
|
+
/**
|
|
36
|
+
* The display format for the selected dates.
|
|
37
|
+
* Follows dayjs format tokens.
|
|
38
|
+
*
|
|
39
|
+
* @default 'YYYY/MM/DD'
|
|
40
|
+
*/
|
|
41
|
+
format?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Props for the clear button, shown automatically when a date range is selected.
|
|
44
|
+
*
|
|
45
|
+
* @property aria-label - The alternative text for the clear button. Default is '値をクリアする'.
|
|
46
|
+
*/
|
|
47
|
+
clearButtonProps?: {
|
|
48
|
+
'aria-label'?: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Whether the component is disabled.
|
|
52
|
+
*
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
disabled?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Additional class name applied to the trigger button.
|
|
58
|
+
*/
|
|
59
|
+
className?: string;
|
|
60
|
+
/**
|
|
61
|
+
* The target DOM node to render the calendar popover into.
|
|
62
|
+
*/
|
|
63
|
+
targetDOMNode?: PopoverProps['targetDOMNode'];
|
|
64
|
+
/**
|
|
65
|
+
* The minimum selectable date.
|
|
66
|
+
*/
|
|
67
|
+
minDate?: Date;
|
|
68
|
+
/**
|
|
69
|
+
* The maximum selectable date.
|
|
70
|
+
*/
|
|
71
|
+
maxDate?: Date;
|
|
72
|
+
/**
|
|
73
|
+
* The locale of the calendar (affects navigation labels and month display format).
|
|
74
|
+
*
|
|
75
|
+
* @default 'ja'
|
|
76
|
+
*/
|
|
77
|
+
calendarLocale?: BasePickerProps['calendarLocale'];
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FilterDateRangePicker } from './FilterDateRangePicker';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type FilterMonthPickerProps } from './FilterMonthPicker.types';
|
|
2
|
+
/**
|
|
3
|
+
* FilterMonthPicker component.
|
|
4
|
+
*
|
|
5
|
+
* A filter trigger component that allows selecting a month via a month picker.
|
|
6
|
+
* Displays the label alone when no month is selected, and "label:formatted month"
|
|
7
|
+
* after a month is selected. Conforms to the FilterSelectBox visual style.
|
|
8
|
+
*
|
|
9
|
+
* Note: The trigger markup intentionally does not reuse FilterTrigger because
|
|
10
|
+
* FilterTrigger hardcodes the DropdownIcon and adds a hidden <input> element,
|
|
11
|
+
* neither of which are appropriate here. FilterMonthPicker uses CalendarIcon and
|
|
12
|
+
* has no form-field semantics.
|
|
13
|
+
*/
|
|
14
|
+
export declare function FilterMonthPicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format, clearButtonProps, disabled, className, targetDOMNode, checkDisabledMonth, minMonth, maxMonth, calendarLocale, }: FilterMonthPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useId, useRef, useState } from 'react';
|
|
4
|
+
import { BasePickerProvider } from '../shared/BasePicker/BasePickerProvider';
|
|
5
|
+
import { useDisclosure } from '../../utilities/state/useDisclosure';
|
|
6
|
+
import { dayjs } from '../../utilities/date/dayjs';
|
|
7
|
+
import { filterMonthPickerSlotRecipe } from '../../../styled-system/recipes';
|
|
8
|
+
import { InternalMonthPickerPopover } from './MonthPickerPopover/MonthPickerPopover';
|
|
9
|
+
const DEFAULT_FORMAT = 'YYYY/MM';
|
|
10
|
+
/**
|
|
11
|
+
* FilterMonthPicker component.
|
|
12
|
+
*
|
|
13
|
+
* A filter trigger component that allows selecting a month via a month picker.
|
|
14
|
+
* Displays the label alone when no month is selected, and "label:formatted month"
|
|
15
|
+
* after a month is selected. Conforms to the FilterSelectBox visual style.
|
|
16
|
+
*
|
|
17
|
+
* Note: The trigger markup intentionally does not reuse FilterTrigger because
|
|
18
|
+
* FilterTrigger hardcodes the DropdownIcon and adds a hidden <input> element,
|
|
19
|
+
* neither of which are appropriate here. FilterMonthPicker uses CalendarIcon and
|
|
20
|
+
* has no form-field semantics.
|
|
21
|
+
*/
|
|
22
|
+
export function FilterMonthPicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format = DEFAULT_FORMAT, clearButtonProps, disabled = false, className, targetDOMNode, checkDisabledMonth, minMonth, maxMonth, calendarLocale = 'ja', }) {
|
|
23
|
+
const classes = filterMonthPickerSlotRecipe();
|
|
24
|
+
const triggerRef = useRef(null);
|
|
25
|
+
const dialogId = useId();
|
|
26
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
27
|
+
const currentValue = value !== undefined ? value : internalValue;
|
|
28
|
+
// When a controlled value transitions back to undefined, clear any stale internal value
|
|
29
|
+
// so the component doesn't show a previously-selected uncontrolled month.
|
|
30
|
+
const previousValueRef = useRef(value);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const previousValue = previousValueRef.current;
|
|
33
|
+
previousValueRef.current = value;
|
|
34
|
+
if (previousValue !== undefined && value === undefined) {
|
|
35
|
+
setInternalValue(undefined);
|
|
36
|
+
}
|
|
37
|
+
}, [value]);
|
|
38
|
+
const { isOpen: isPickerOpen, toggle: togglePicker, close: closePicker, } = useDisclosure({
|
|
39
|
+
// disabled takes precedence: never open the picker when the trigger is disabled.
|
|
40
|
+
value: disabled ? false : open,
|
|
41
|
+
// onToggle fires for Escape and outside-click (via togglePicker); focus trigger on close.
|
|
42
|
+
onToggle: (nextOpen) => {
|
|
43
|
+
if (!nextOpen) {
|
|
44
|
+
triggerRef.current?.focus();
|
|
45
|
+
}
|
|
46
|
+
onOpenStateChanged?.(nextOpen);
|
|
47
|
+
},
|
|
48
|
+
// onClose fires for programmatic close (month selection); focus trigger there too.
|
|
49
|
+
onClose: () => {
|
|
50
|
+
triggerRef.current?.focus();
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
const handleValueChange = useCallback((date) => {
|
|
54
|
+
if (value === undefined) {
|
|
55
|
+
setInternalValue(date);
|
|
56
|
+
}
|
|
57
|
+
onChange?.(date);
|
|
58
|
+
// closePicker() fires useDisclosure.onClose (returns focus to trigger) but intentionally
|
|
59
|
+
// does NOT fire onToggle. The explicit onOpenStateChanged call below is the single path
|
|
60
|
+
// for notifying the parent when a month selection closes the popover.
|
|
61
|
+
closePicker();
|
|
62
|
+
onOpenStateChanged?.(false);
|
|
63
|
+
}, [value, onChange, closePicker, onOpenStateChanged]);
|
|
64
|
+
const handleClear = useCallback((event) => {
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
if (value === undefined) {
|
|
67
|
+
setInternalValue(undefined);
|
|
68
|
+
}
|
|
69
|
+
onChange?.();
|
|
70
|
+
triggerRef.current?.focus();
|
|
71
|
+
}, [value, onChange, triggerRef]);
|
|
72
|
+
const formattedValue = currentValue ? dayjs(currentValue).format(format) : undefined;
|
|
73
|
+
const hasValue = !!formattedValue;
|
|
74
|
+
return (_jsx(BasePickerProvider, { value: currentValue, baseFormat: "YYYY-MM", children: _jsx(InternalMonthPickerPopover, { currentValue: currentValue, defaultValue: defaultValue, isPickerOpen: isPickerOpen, togglePicker: togglePicker, handleValueChange: handleValueChange, handleClear: handleClear, disabled: disabled, className: className, classes: classes, formattedValue: formattedValue, hasValue: hasValue, label: label, clearButtonProps: clearButtonProps, checkDisabledMonth: checkDisabledMonth, minMonth: minMonth, maxMonth: maxMonth, calendarLocale: calendarLocale, triggerRef: triggerRef, targetDOMNode: targetDOMNode, dialogId: dialogId }) }));
|
|
75
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type PopoverProps } from '../../Popover';
|
|
2
|
+
import { type BasePickerProps } from '../shared/BasePicker';
|
|
3
|
+
export type FilterMonthPickerProps = {
|
|
4
|
+
/**
|
|
5
|
+
* The label to display for the filter.
|
|
6
|
+
*/
|
|
7
|
+
label: string;
|
|
8
|
+
/**
|
|
9
|
+
* The selected month value (controlled).
|
|
10
|
+
*/
|
|
11
|
+
value?: Date;
|
|
12
|
+
/**
|
|
13
|
+
* The default selected month value for uncontrolled usage.
|
|
14
|
+
*/
|
|
15
|
+
defaultValue?: Date;
|
|
16
|
+
/**
|
|
17
|
+
* Callback fired when the selected month changes.
|
|
18
|
+
*
|
|
19
|
+
* @param value - The new selected month, or undefined when cleared.
|
|
20
|
+
*/
|
|
21
|
+
onChange?: (value?: Date) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the month picker popover is open (controlled).
|
|
24
|
+
*/
|
|
25
|
+
open?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Callback fired when the open state of the picker changes.
|
|
28
|
+
*
|
|
29
|
+
* @param open - The new open state.
|
|
30
|
+
*/
|
|
31
|
+
onOpenStateChanged?: (open: boolean) => void;
|
|
32
|
+
/**
|
|
33
|
+
* The display format for the selected month.
|
|
34
|
+
* Follows dayjs format tokens.
|
|
35
|
+
*
|
|
36
|
+
* @default 'YYYY/MM'
|
|
37
|
+
*/
|
|
38
|
+
format?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Props for the clear button, shown automatically when a month is selected.
|
|
41
|
+
*
|
|
42
|
+
* @property aria-label - The alternative text for the clear button. Default is '値をクリアする'.
|
|
43
|
+
*/
|
|
44
|
+
clearButtonProps?: {
|
|
45
|
+
'aria-label'?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Whether the component is disabled.
|
|
49
|
+
*
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Additional class name applied to the trigger button.
|
|
55
|
+
*/
|
|
56
|
+
className?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The target DOM node to render the month picker popover into.
|
|
59
|
+
*/
|
|
60
|
+
targetDOMNode?: PopoverProps['targetDOMNode'];
|
|
61
|
+
/**
|
|
62
|
+
* Function to check if a month should be disabled in the picker.
|
|
63
|
+
*
|
|
64
|
+
* @param date - The date to check (first day of the month).
|
|
65
|
+
*
|
|
66
|
+
* @returns true if the month should be disabled.
|
|
67
|
+
*/
|
|
68
|
+
checkDisabledMonth?: (date: Date) => boolean;
|
|
69
|
+
/**
|
|
70
|
+
* The minimum selectable month.
|
|
71
|
+
*/
|
|
72
|
+
minMonth?: Date;
|
|
73
|
+
/**
|
|
74
|
+
* The maximum selectable month.
|
|
75
|
+
*/
|
|
76
|
+
maxMonth?: Date;
|
|
77
|
+
/**
|
|
78
|
+
* The locale of the calendar (affects navigation labels and month display format).
|
|
79
|
+
*
|
|
80
|
+
* @default 'ja'
|
|
81
|
+
*/
|
|
82
|
+
calendarLocale?: BasePickerProps['calendarLocale'];
|
|
83
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/src/DateTimeSelection/FilterMonthPicker/MonthPickerPopover/MonthPickerPopover.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type InternalMonthPickerPopoverProps } from './MonthPickerPopover.types';
|
|
2
|
+
/**
|
|
3
|
+
* Internal component that accesses BasePickerContext for viewing-month reset and focus trap.
|
|
4
|
+
* Must be rendered inside a BasePickerProvider.
|
|
5
|
+
*/
|
|
6
|
+
export declare function InternalMonthPickerPopover({ currentValue, defaultValue, isPickerOpen, togglePicker, handleValueChange, handleClear, disabled, className, classes, formattedValue, hasValue, label, clearButtonProps, checkDisabledMonth, minMonth, maxMonth, calendarLocale, triggerRef, targetDOMNode, dialogId, }: InternalMonthPickerPopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { Calendar as CalendarIcon } from '@moneyforward/mfui-icons-react';
|
|
5
|
+
import { Popover } from '../../../Popover';
|
|
6
|
+
import { FocusIndicator } from '../../../FocusIndicator';
|
|
7
|
+
import { ClearButton } from '../../../shared';
|
|
8
|
+
import { Typography } from '../../../Typography';
|
|
9
|
+
import { cx } from '../../../../styled-system/css';
|
|
10
|
+
import { dayjs } from '../../../utilities/date/dayjs';
|
|
11
|
+
import { MonthPickerPanel } from '../../MonthPicker/MonthPickerPanel/MonthPickerPanel';
|
|
12
|
+
import { CalendarLocaleProvider } from '../../shared/CalendarLocale/CalendarLocaleContext';
|
|
13
|
+
import { useBasePickerContext } from '../../shared/BasePicker/BasePickerProvider';
|
|
14
|
+
import { useFocusTrap } from '../../../utilities/dom/useFocusTrap';
|
|
15
|
+
import { getFocusableNodes } from '../../../utilities/dom/getFocusableNodes';
|
|
16
|
+
const MONTH_BASE_FORMAT = 'YYYY-MM';
|
|
17
|
+
/**
|
|
18
|
+
* Internal component that accesses BasePickerContext for viewing-month reset and focus trap.
|
|
19
|
+
* Must be rendered inside a BasePickerProvider.
|
|
20
|
+
*/
|
|
21
|
+
export function InternalMonthPickerPopover({ currentValue, defaultValue, isPickerOpen, togglePicker, handleValueChange, handleClear, disabled, className, classes, formattedValue, hasValue, label, clearButtonProps, checkDisabledMonth, minMonth, maxMonth, calendarLocale = 'ja', triggerRef, targetDOMNode, dialogId, }) {
|
|
22
|
+
const { viewingValue, setViewingValue, setPendingFocusDate } = useBasePickerContext();
|
|
23
|
+
const { handleOnKeyDown } = useFocusTrap({
|
|
24
|
+
onPressingTabOnNotFocusableElement: (event) => {
|
|
25
|
+
const nodes = getFocusableNodes(event.currentTarget);
|
|
26
|
+
const focusableNodeAfterFocusingNode = nodes.find((element) =>
|
|
27
|
+
// eslint-disable-next-line no-bitwise
|
|
28
|
+
element.compareDocumentPosition(event.target) & Node.DOCUMENT_POSITION_PRECEDING);
|
|
29
|
+
const firstFocusableNode = nodes.at(0);
|
|
30
|
+
const nextFocusableNode = focusableNodeAfterFocusingNode ?? firstFocusableNode;
|
|
31
|
+
nextFocusableNode?.focus();
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
const handlePopoverOpen = useCallback(() => {
|
|
36
|
+
const monthToFocus = dayjs(currentValue ?? defaultValue ?? new Date())
|
|
37
|
+
.startOf('month')
|
|
38
|
+
.toDate();
|
|
39
|
+
setViewingValue(monthToFocus);
|
|
40
|
+
setPendingFocusDate(dayjs(monthToFocus).format(MONTH_BASE_FORMAT));
|
|
41
|
+
}, [currentValue, defaultValue, setViewingValue, setPendingFocusDate]);
|
|
42
|
+
return (_jsx(Popover, { open: isPickerOpen, targetDOMNode: targetDOMNode, renderTrigger: ({ setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsxs("div", { ref: setTriggerRef, "data-selected": hasValue, className: cx(classes.wrapper, 'mfui-FilterMonthPicker__wrapper'), children: [_jsx(FocusIndicator, { children: _jsxs("button", { ref: triggerRef, type: "button", disabled: disabled, className: cx(classes.trigger, 'mfui-FilterMonthPicker__trigger', className), "data-selected": hasValue, "data-mfui-has-clear-button": hasValue, "aria-controls": dialogId, "aria-expanded": isPickerOpen, "aria-haspopup": "dialog", onClick: togglePopover, onKeyDown: handleTriggerKeyDown, onBlur: handleTriggerBlur, children: [_jsx("span", { className: cx(classes.content, 'mfui-FilterMonthPicker__content'), "data-mfui-content": "filter-month-picker-display-value", children: hasValue ? (_jsxs(Typography, { variant: "strongBody", children: [_jsx("span", { "data-mfui-content": "filter-month-picker-label", children: `${label}:` }), _jsx("span", { "data-mfui-content": "filter-month-picker-value", children: formattedValue })] })) : (_jsx(Typography, { variant: "controlLabel", children: _jsx("span", { "data-mfui-content": "filter-month-picker-label", children: label }) })) }), _jsx("span", { className: cx(classes.calendarIcon, 'mfui-FilterMonthPicker__calendarIcon'), children: _jsx(CalendarIcon, { "aria-hidden": true }) })] }) }), hasValue ? (_jsx("div", { className: cx(classes.clearButtonWrapper, 'mfui-FilterMonthPicker__clearButtonWrapper'), children: _jsx(ClearButton, { "aria-label": clearButtonProps?.['aria-label'] ?? '値をクリアする', "data-mfui-content": "filter-month-picker-clear-button", disabled: disabled, onClick: handleClear }) })) : null] })), renderContent: () => (_jsx("div", { id: dialogId, role: "dialog", "aria-label": label, className: "mfui-FilterMonthPicker__popoverWrapper", onKeyDown: handleOnKeyDown, children: _jsx(CalendarLocaleProvider, { value: calendarLocale, children: _jsx(MonthPickerPanel, { viewingValue: viewingValue, setViewingValue: setViewingValue, value: currentValue, minMonth: minMonth, maxMonth: maxMonth, checkDisabledMonth: checkDisabledMonth, onChange: (date) => {
|
|
43
|
+
handleValueChange(date);
|
|
44
|
+
} }) }) })), minWidth: "min-content", allowedPlacements: ['bottom-start', 'top-start'], onOpenStateChanged: togglePicker, onOpen: handlePopoverOpen }));
|
|
45
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type filterMonthPickerSlotRecipe } from '../../../../styled-system/recipes';
|
|
2
|
+
import { type FilterMonthPickerProps } from '../FilterMonthPicker.types';
|
|
3
|
+
export type InternalMonthPickerPopoverProps = {
|
|
4
|
+
currentValue: Date | undefined;
|
|
5
|
+
defaultValue: Date | undefined;
|
|
6
|
+
isPickerOpen: boolean;
|
|
7
|
+
togglePicker: () => void;
|
|
8
|
+
handleValueChange: (date: Date | undefined) => void;
|
|
9
|
+
handleClear: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
className: string | undefined;
|
|
12
|
+
classes: ReturnType<typeof filterMonthPickerSlotRecipe>;
|
|
13
|
+
formattedValue: string | undefined;
|
|
14
|
+
hasValue: boolean;
|
|
15
|
+
label: string;
|
|
16
|
+
clearButtonProps: FilterMonthPickerProps['clearButtonProps'];
|
|
17
|
+
checkDisabledMonth: FilterMonthPickerProps['checkDisabledMonth'];
|
|
18
|
+
minMonth: Date | undefined;
|
|
19
|
+
maxMonth: Date | undefined;
|
|
20
|
+
calendarLocale: FilterMonthPickerProps['calendarLocale'];
|
|
21
|
+
triggerRef: React.RefObject<HTMLButtonElement | null>;
|
|
22
|
+
targetDOMNode: FilterMonthPickerProps['targetDOMNode'];
|
|
23
|
+
dialogId: string;
|
|
24
|
+
};
|
package/dist/src/DateTimeSelection/FilterMonthPicker/MonthPickerPopover/MonthPickerPopover.types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FilterMonthPicker } from './FilterMonthPicker';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type FilterMonthRangePickerProps } from './FilterMonthRangePicker.types';
|
|
2
|
+
/**
|
|
3
|
+
* FilterMonthRangePicker component.
|
|
4
|
+
*
|
|
5
|
+
* A filter trigger component that allows selecting a month range via the same panel as
|
|
6
|
+
* {@link MonthRangePicker}. Displays the label alone when no range is selected, and
|
|
7
|
+
* `label:start〜end` after both bounds are selected. Conforms to the FilterSelectBox / FilterDateBox
|
|
8
|
+
* visual style.
|
|
9
|
+
*
|
|
10
|
+
* Note: The trigger markup intentionally does not reuse FilterTrigger because
|
|
11
|
+
* FilterTrigger hardcodes the DropdownIcon and adds a hidden `<input>` element,
|
|
12
|
+
* neither of which are appropriate here. FilterMonthRangePicker uses CalendarIcon and
|
|
13
|
+
* has no form-field semantics.
|
|
14
|
+
*/
|
|
15
|
+
export declare function FilterMonthRangePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format, initialDisplayedMonths, clearButtonProps, disabled, className, targetDOMNode, minMonth, maxMonth, }: FilterMonthRangePickerProps): import("react/jsx-runtime").JSX.Element;
|