@moneyforward/mfui-components 4.5.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/src/Badge/Badge.d.ts +1 -1
  2. package/dist/src/Badge/Badge.js +4 -4
  3. package/dist/src/Badge/Badge.types.d.ts +3 -1
  4. package/dist/src/Checkbox/Checkbox.js +7 -3
  5. package/dist/src/DataTable/DataTable.d.ts +1 -1
  6. package/dist/src/DataTable/DataTable.js +23 -3
  7. package/dist/src/DataTable/DataTable.types.d.ts +2 -2
  8. package/dist/src/DataTable/DataTableBody/DataTableBody.d.ts +2 -1
  9. package/dist/src/DataTable/DataTableBody/DataTableBody.js +72 -8
  10. package/dist/src/DataTable/DataTableBody/DataTableBody.types.d.ts +81 -1
  11. package/dist/src/DataTable/DataTableBody/hooks/useVirtualizedRows.d.ts +64 -0
  12. package/dist/src/DataTable/DataTableBody/hooks/useVirtualizedRows.js +53 -0
  13. package/dist/src/DataTable/DataTableBody/index.d.ts +1 -1
  14. package/dist/src/DataTable/DataTableCell/DataTableCell.js +21 -4
  15. package/dist/src/DataTable/DataTableCell/DataTableCell.types.d.ts +1 -1
  16. package/dist/src/DataTable/DataTableHeader/DataTableHeader.js +13 -2
  17. package/dist/src/DataTable/DataTableHeaderRow/DataTableHeaderRow.js +12 -7
  18. package/dist/src/DataTable/DataTableHeaderRow/DataTableHeaderRow.types.d.ts +9 -0
  19. package/dist/src/DataTable/DataTableProvider.d.ts +29 -2
  20. package/dist/src/DataTable/DataTableProvider.js +20 -1
  21. package/dist/src/DataTable/DataTableRow/DataTableRow.js +104 -32
  22. package/dist/src/DataTable/DataTableRow/DataTableRow.types.d.ts +44 -15
  23. package/dist/src/DataTable/DataTableRowActionContext.d.ts +34 -0
  24. package/dist/src/DataTable/DataTableRowActionContext.js +8 -0
  25. package/dist/src/DataTable/index.d.ts +1 -1
  26. package/dist/src/DateTimeSelection/DatePicker/DatePickerCalendar/DatePickerCalendar.js +7 -3
  27. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerPopover/DateRangePickerCalendar/DateRangePickerCalendar.js +1 -1
  28. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerPopover/utilities/createDateRangePickerPopoverTestUtility.js +2 -2
  29. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerProvider/DateRangePickerProvider.js +13 -7
  30. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerTrigger/DateRangePickerTrigger.js +1 -1
  31. package/dist/src/DateTimeSelection/FilterDatePicker/FilterDatePicker.js +1 -1
  32. package/dist/src/DateTimeSelection/FilterMonthPicker/FilterMonthPicker.js +1 -1
  33. package/dist/src/DateTimeSelection/FilterMonthRangePicker/FilterMonthRangePicker.js +1 -1
  34. package/dist/src/DateTimeSelection/MonthPicker/MonthPickerPanel/MonthPickerPanel.js +1 -1
  35. package/dist/src/DateTimeSelection/MonthPicker/constants.d.ts +2 -2
  36. package/dist/src/DateTimeSelection/MonthPicker/constants.js +6 -6
  37. package/dist/src/DateTimeSelection/MonthRangePicker/MonthRangePickerMonthCell/MonthRangePickerMonthCell.js +1 -1
  38. package/dist/src/DateTimeSelection/MonthRangePicker/MonthRangePickerNavigation/MonthRangePickerNavigation.js +2 -2
  39. package/dist/src/DateTimeSelection/TimePicker/TimePicker.js +1 -1
  40. package/dist/src/DateTimeSelection/shared/BasePicker/constants.d.ts +2 -2
  41. package/dist/src/DateTimeSelection/shared/BasePicker/constants.js +10 -10
  42. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerPopover/BaseRangePickerCalendar/BaseRangePickerCalendar.js +1 -1
  43. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerPopover/constants.js +4 -4
  44. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerProvider/BaseRangePickerProvider.js +13 -7
  45. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerTrigger/BaseRangePickerTrigger.js +2 -2
  46. package/dist/src/DateTimeSelection/shared/CalendarGrid/CalendarGrid.js +1 -1
  47. package/dist/src/DateTimeSelection/shared/utilities/japaneseCalendar.js +2 -2
  48. package/dist/src/FileDropZone/FileDropZone.js +1 -1
  49. package/dist/src/FileDropZone/utils/fileHelpers.js +1 -1
  50. package/dist/src/MainNavigation/BaseMainNavigation.js +1 -1
  51. package/dist/src/MainNavigation/NarrowViewportMainNavigation.js +1 -1
  52. package/dist/src/MultipleSelectBox/MultipleSelectBox.js +12 -3
  53. package/dist/src/MultipleSelectBox/MultipleSelectBoxTrigger/MultipleSelectBoxTrigger.js +1 -1
  54. package/dist/src/MultipleSelectBox/hooks/useCreateOption.js +8 -4
  55. package/dist/src/MultipleSelectBox/hooks/useOptionKeyboardNavigation.d.ts +1 -0
  56. package/dist/src/MultipleSelectBox/hooks/useOptionKeyboardNavigation.js +24 -12
  57. package/dist/src/MultipleSelectBox/hooks/useSelectedValues.js +16 -50
  58. package/dist/src/NumberBox/NumberBox.js +8 -4
  59. package/dist/src/PageHeader/PageHeader.types.d.ts +2 -0
  60. package/dist/src/Popover/Popover.js +11 -2
  61. package/dist/src/SelectBox/SelectBox.js +21 -13
  62. package/dist/src/SelectBox/hooks/useKeyboardNavigation.d.ts +1 -0
  63. package/dist/src/SelectBox/hooks/useKeyboardNavigation.js +29 -8
  64. package/dist/src/SplitView/hooks/useSplitViewPanelVisibility.js +5 -2
  65. package/dist/src/SubNavigation/SubNavigation.js +80 -19
  66. package/dist/src/SubNavigation/SubNavigation.types.d.ts +18 -6
  67. package/dist/src/Tabs/Tabs.js +8 -4
  68. package/dist/src/Tabs/hooks/useCalculatedSelectedTabId.js +7 -5
  69. package/dist/src/Toast/ToastContainer/ToastContainer.js +11 -2
  70. package/dist/src/Tooltip/Tooltip.d.ts +6 -0
  71. package/dist/src/Tooltip/Tooltip.js +14 -3
  72. package/dist/src/Tooltip/hooks/useTooltipDisplayController.js +77 -88
  73. package/dist/src/utilities/dom/getFocusableNodes.js +1 -3
  74. package/dist/src/utilities/dom/useFixedColumns.js +6 -8
  75. package/dist/src/utilities/react/flattenChildren.d.ts +15 -0
  76. package/dist/src/utilities/react/flattenChildren.js +28 -0
  77. package/dist/src/utilities/state/useLatest.d.ts +1 -1
  78. package/dist/src/utilities/state/useLatest.js +8 -2
  79. package/dist/styled-system/recipes/badge-slot-recipe.d.ts +1 -1
  80. package/dist/styled-system/recipes/badge-slot-recipe.js +4 -0
  81. package/dist/styled-system/recipes/data-table-body-slot-recipe.d.ts +1 -1
  82. package/dist/styled-system/recipes/data-table-body-slot-recipe.js +4 -0
  83. package/dist/styled-system/recipes/data-table-cell-slot-recipe.d.ts +1 -1
  84. package/dist/styled-system/recipes/data-table-cell-slot-recipe.js +4 -0
  85. package/dist/styled-system/recipes/data-table-row-slot-recipe.js +13 -6
  86. package/dist/styled-system/recipes/sub-navigation-slot-recipe.d.ts +1 -1
  87. package/dist/styled-system/recipes/sub-navigation-slot-recipe.js +12 -0
  88. package/dist/styled-system/tokens/index.js +4 -0
  89. package/dist/styled-system/tokens/tokens.d.ts +1 -1
  90. package/dist/styles.css +164 -39
  91. package/dist/tsconfig.build.tsbuildinfo +1 -1
  92. package/package.json +12 -12
@@ -5,10 +5,37 @@ export type DataTableSize = 'small' | 'medium';
5
5
  * The props for the `DataTableContext` component.
6
6
  */
7
7
  export type DataTableContextProps = Pick<DataTableProps, 'size' | 'enableRowSelection' | 'enableRowClickSelection' | 'fixedHeader' | 'showVerticalBorder' | 'leftFixedColumnIndex' | 'rightFixedColumnIndex' | 'loading' | 'layout'>;
8
+ /**
9
+ * The values the `DataTable` owns and shares with its composition components.
10
+ *
11
+ * This should only be used in DataTable component.
12
+ */
13
+ export type DataTableVirtualizationValues = {
14
+ /**
15
+ * The wrapper element of the table, which is the element that scrolls.
16
+ * It is `null` until the wrapper is mounted, and when the body is used outside a `DataTable`.
17
+ */
18
+ scrollElement: HTMLElement | null;
19
+ /**
20
+ * The number of rows the body holds while it is virtualized, or `null` when it is not.
21
+ * The body publishes it so that the table can report the real row count to assistive technology
22
+ * even though only a window of rows is mounted.
23
+ */
24
+ virtualizedRowCount: number | null;
25
+ setVirtualizedRowCount: (rowCount: number | null) => void;
26
+ /**
27
+ * The number of mounted header rows, which offsets the `aria-rowindex` of the body rows.
28
+ */
29
+ headerRowCount: number;
30
+ /**
31
+ * Registers a header row and returns the function to unregister it.
32
+ */
33
+ registerHeaderRow: () => () => void;
34
+ };
8
35
  export type DataTableProviderValues = {
9
36
  numberColumns: number;
10
37
  setNumberColumns: (number: number) => void;
11
- } & DataTableContextProps;
38
+ } & DataTableContextProps & DataTableVirtualizationValues;
12
39
  /**
13
40
  * The context for the `DataTable` component.
14
41
  *
@@ -24,4 +51,4 @@ export declare const useDataTableContext: () => DataTableProviderValues;
24
51
  *
25
52
  * This should only be used in DataTable component.
26
53
  */
27
- export declare function DataTableProvider({ children, size, enableRowSelection, enableRowClickSelection, fixedHeader, showVerticalBorder, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout, }: PropsWithChildren<DataTableContextProps>): import("react/jsx-runtime").JSX.Element;
54
+ export declare function DataTableProvider({ children, size, enableRowSelection, enableRowClickSelection, fixedHeader, showVerticalBorder, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout, scrollElement, virtualizedRowCount, setVirtualizedRowCount, headerRowCount, registerHeaderRow, }: PropsWithChildren<DataTableContextProps & DataTableVirtualizationValues>): import("react/jsx-runtime").JSX.Element;
@@ -19,6 +19,15 @@ export const DataTableContext = createContext({
19
19
  setNumberColumns: () => {
20
20
  // Do nothing
21
21
  },
22
+ scrollElement: null,
23
+ virtualizedRowCount: null,
24
+ setVirtualizedRowCount: () => {
25
+ // Do nothing
26
+ },
27
+ headerRowCount: 0,
28
+ registerHeaderRow: () => () => {
29
+ // Do nothing
30
+ },
22
31
  });
23
32
  /**
24
33
  * The hook to use the `DataTableContext`.
@@ -29,7 +38,7 @@ export const useDataTableContext = () => useContext(DataTableContext);
29
38
  *
30
39
  * This should only be used in DataTable component.
31
40
  */
32
- export function DataTableProvider({ children, size = 'medium', enableRowSelection = false, enableRowClickSelection = false, fixedHeader = false, showVerticalBorder = false, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout = 'default', }) {
41
+ export function DataTableProvider({ children, size = 'medium', enableRowSelection = false, enableRowClickSelection = false, fixedHeader = false, showVerticalBorder = false, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout = 'default', scrollElement, virtualizedRowCount, setVirtualizedRowCount, headerRowCount, registerHeaderRow, }) {
33
42
  const [numberColumns, setNumberColumns] = useState(0);
34
43
  const contextValue = useMemo(() => ({
35
44
  size,
@@ -43,6 +52,11 @@ export function DataTableProvider({ children, size = 'medium', enableRowSelectio
43
52
  layout,
44
53
  numberColumns,
45
54
  setNumberColumns,
55
+ scrollElement,
56
+ virtualizedRowCount,
57
+ setVirtualizedRowCount,
58
+ headerRowCount,
59
+ registerHeaderRow,
46
60
  }), [
47
61
  size,
48
62
  enableRowSelection,
@@ -54,6 +68,11 @@ export function DataTableProvider({ children, size = 'medium', enableRowSelectio
54
68
  loading,
55
69
  layout,
56
70
  numberColumns,
71
+ scrollElement,
72
+ virtualizedRowCount,
73
+ setVirtualizedRowCount,
74
+ headerRowCount,
75
+ registerHeaderRow,
57
76
  ]);
58
77
  return _jsx(DataTableContext.Provider, { value: contextValue, children: children });
59
78
  }
@@ -1,11 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Children, cloneElement, forwardRef, isValidElement, useRef } from 'react';
2
+ import { cloneElement, forwardRef, isValidElement, useCallback, useMemo, useRef, useState } from 'react';
3
+ import { DataTableRowActionContext, } from '../DataTableRowActionContext';
3
4
  import { dataTableRowSlotRecipe } from '../../../styled-system/recipes';
4
5
  import { DataTableCell } from '../DataTableCell';
5
6
  import { Checkbox } from '../../Checkbox';
6
7
  import { useDataTableContext } from '../DataTableProvider';
7
8
  import { cx } from '../../../styled-system/css';
8
9
  import { isComponentOrWrapped } from '../../utilities/react/isComponentOrWrapped';
10
+ import { flattenChildren } from '../../utilities/react/flattenChildren';
11
+ import { useIsomorphicLayoutEffect } from '../../utilities/react/useIsomorphicLayoutEffect';
12
+ const ROW_ACTION_BUTTON_SELECTOR = '[data-mfui-content="data-table-row-action-button"]';
9
13
  const INTERACTIVE_ELEMENT_SELECTOR = [
10
14
  'a[href]',
11
15
  'button',
@@ -33,17 +37,32 @@ function isClickFromNestedInteractiveElement(event) {
33
37
  if (!(event.target instanceof Element)) {
34
38
  return false;
35
39
  }
40
+ // A click inside a nested table (e.g. a DataTable rendered in a cell) belongs to the inner row.
41
+ if (event.target.closest('tr') !== event.currentTarget) {
42
+ return true;
43
+ }
36
44
  const interactiveElement = event.target.closest(INTERACTIVE_ELEMENT_SELECTOR);
37
- return interactiveElement !== null && interactiveElement !== event.currentTarget;
45
+ if (interactiveElement === null || interactiveElement === event.currentTarget) {
46
+ return false;
47
+ }
48
+ // The visually hidden row action button exists to trigger the row click itself,
49
+ // so its click must not be treated as a nested interactive element's click.
50
+ return !interactiveElement.matches(ROW_ACTION_BUTTON_SELECTOR);
38
51
  }
39
- export const DataTableRow = forwardRef(({ children, disabled = false, highlighted, checkboxProps, className, onClickRow, selectable, ...props }, ref) => {
52
+ export const DataTableRow = forwardRef(({ children, disabled = false, highlighted, checkboxProps, className, onClickRow, rowActionButtonProps, selectable, 'aria-expanded': ariaExpandedProp, ...props }, ref) => {
40
53
  const { enableRowSelection: contextEnableRowSelection, enableRowClickSelection, layout } = useDataTableContext();
41
54
  const selectionCheckboxRef = useRef(null);
42
55
  const isSelectable = selectable ?? contextEnableRowSelection;
43
- const isRowHighlighted = isSelectable ? (checkboxProps?.checked ?? highlighted) : highlighted;
56
+ // A selected row is always highlighted, and `highlighted` stays an independent signal on top of it,
57
+ // so that a row can be marked (e.g. as the one opened in a detail panel) while it is not selected.
58
+ const isRowHighlighted = isSelectable ? highlighted === true || checkboxProps?.checked === true : highlighted;
44
59
  // Only a row whose selection can actually be toggled becomes the trigger of the row selection.
45
60
  const isRowClickSelectable = !!enableRowClickSelection && isSelectable && !disabled && !checkboxProps?.disabled;
46
61
  const isInteractive = (onClickRow !== undefined || isRowClickSelectable) && !disabled;
62
+ // The row click itself is exposed to keyboard and screen reader users through the row action
63
+ // button. The row click selection is exposed through the selection checkbox instead.
64
+ // A disabled row keeps the button as a disabled one so that the row action stays discoverable.
65
+ const hasRowActionButton = onClickRow !== undefined;
47
66
  const classes = dataTableRowSlotRecipe({
48
67
  layout,
49
68
  highlighted: isRowHighlighted,
@@ -51,20 +70,85 @@ export const DataTableRow = forwardRef(({ children, disabled = false, highlighte
51
70
  rowClickSelectable: isRowClickSelectable,
52
71
  disabled,
53
72
  });
73
+ // Fragments are expanded so that cells wrapped in a Fragment (e.g. `<>{items.map(...)}</>`)
74
+ // are recognized by the cell inspection below.
75
+ const flatChildren = useMemo(() => flattenChildren(children), [children]);
76
+ const isCellElement = (child) => isValidElement(child) && isComponentOrWrapped(child, DataTableCell);
54
77
  // When the interactive row itself toggles a disclosure (a child cell shows the disclosure icon
55
- // but does not handle the click by itself), expose the expanded state on the row.
56
- const disclosureIconProps = Children.toArray(children)
57
- .filter((child) => isValidElement(child) && isComponentOrWrapped(child, DataTableCell))
78
+ // but does not handle the click by itself), expose the expanded state on the row action button.
79
+ const disclosureIconProps = flatChildren
80
+ .filter(isCellElement)
58
81
  .find((cell) => cell.props.disclosureIconProps && !cell.props.onClickCell)?.props.disclosureIconProps;
59
- const ariaExpanded = onClickRow !== undefined && !disabled && disclosureIconProps ? (disclosureIconProps.isOpen ?? false) : undefined;
82
+ const derivedAriaExpanded = hasRowActionButton && disclosureIconProps ? (disclosureIconProps.isOpen ?? false) : undefined;
83
+ const rowActionAriaExpanded = ariaExpandedProp ?? derivedAriaExpanded;
84
+ // The default name is given by `aria-label`, so a consumer `aria-label` replaces it and a consumer
85
+ // `aria-labelledby` takes precedence over it by the accessible name computation.
86
+ // A row that toggles a disclosure says so, since its expanded state is exposed on the button.
87
+ const defaultRowActionLabel = disclosureIconProps ? '行を開閉' : '行の操作';
88
+ const resolvedRowActionButtonProps = useMemo(() => hasRowActionButton
89
+ ? {
90
+ ...rowActionButtonProps,
91
+ // An explicitly undefined consumer label must not leave the button without a name.
92
+ 'aria-label': rowActionButtonProps?.['aria-label'] ?? defaultRowActionLabel,
93
+ ...(rowActionAriaExpanded !== undefined && { 'aria-expanded': rowActionAriaExpanded }),
94
+ ...(disabled && { disabled }),
95
+ }
96
+ : undefined, [hasRowActionButton, rowActionButtonProps, defaultRowActionLabel, rowActionAriaExpanded, disabled]);
97
+ // The cells register themselves through the context, so the button reaches a cell wherever the
98
+ // consumer renders it (intermediate components, wrappers, Fragments). The version state makes the
99
+ // host selection below run again whenever a cell mounts or unmounts.
100
+ const rowActionCellEntries = useRef(new Set());
101
+ const [rowActionCellsVersion, setRowActionCellsVersion] = useState(0);
102
+ const registerRowActionCell = useCallback((entry) => {
103
+ rowActionCellEntries.current.add(entry);
104
+ setRowActionCellsVersion((version) => version + 1);
105
+ return () => {
106
+ rowActionCellEntries.current.delete(entry);
107
+ setRowActionCellsVersion((version) => version + 1);
108
+ };
109
+ }, []);
110
+ // The first cell in the row hosts the button, skipping a row header cell so that the button label
111
+ // does not become part of the row header name. The selection cell, rendered by the row itself,
112
+ // therefore hosts it whenever the row is selectable.
113
+ const hasWarnedMissingRowActionHost = useRef(false);
114
+ useIsomorphicLayoutEffect(() => {
115
+ // The registration order follows the mount order, which differs from the visual order when a
116
+ // cell mounts later, so sort by the position of the cell element in the row.
117
+ const entries = [...rowActionCellEntries.current].toSorted((a, b) => a.element.cellIndex - b.element.cellIndex);
118
+ const host = hasRowActionButton ? (entries.find((entry) => !entry.isRowHeader) ?? entries[0]) : undefined;
119
+ entries.forEach((entry) => {
120
+ entry.setIsHost(entry === host);
121
+ });
122
+ if (hasRowActionButton && host === undefined && !hasWarnedMissingRowActionHost.current) {
123
+ hasWarnedMissingRowActionHost.current = true;
124
+ console.warn('[MFUI] DataTable.Row received onClickRow, but the row action button was not rendered because ' +
125
+ 'the row contains no DataTable.Cell, so the row cannot be operated with a keyboard or screen reader. ' +
126
+ 'Render the cells of the row with DataTable.Cell.');
127
+ }
128
+ }, [hasRowActionButton, rowActionCellsVersion]);
129
+ // The cells of a row without the button do not register, so such a row does not pay for the host selection.
130
+ const rowActionContextValue = useMemo(() => ({
131
+ buttonProps: resolvedRowActionButtonProps,
132
+ registerCell: hasRowActionButton ? registerRowActionCell : undefined,
133
+ }), [hasRowActionButton, resolvedRowActionButtonProps, registerRowActionCell]);
60
134
  // Forwarding the interaction to the checkbox lets the consumer keep handling the row selection in
61
135
  // `checkboxProps.onChange` only, and the change event carries the real next checked state.
62
136
  const toggleSelectionByRowInteraction = () => {
63
137
  selectionCheckboxRef.current?.click();
64
138
  };
139
+ // The focus indicator is displayed on the whole row while the selection checkbox is focused, so the
140
+ // selection also toggles with Enter, which a native checkbox ignores, in addition to Space.
141
+ const handleKeyDownSelectionCheckbox = (event) => {
142
+ if (isRowClickSelectable && event.key === 'Enter') {
143
+ // Prevents the implicit form submission.
144
+ event.preventDefault();
145
+ toggleSelectionByRowInteraction();
146
+ }
147
+ };
65
148
  // Building the element before wrapping keeps everything the row owns on the Checkbox itself, so that the
66
149
  // ref-based toggle and the recipe selectors keep working with a consumer-supplied wrapper in between.
67
- const selectionCheckbox = (_jsx(Checkbox, { ref: selectionCheckboxRef, className: cx(classes.selectionCheckbox, 'mfui-DataTableRow__selectionCheckbox'), checked: checkboxProps?.checked, "aria-label": checkboxProps?.['aria-label'] ?? '行を選択', disabled: disabled || checkboxProps?.disabled, tabIndex: isRowClickSelectable ? -1 : undefined, onChange: checkboxProps?.onChange, onClick: checkboxProps?.onClick }));
150
+ const selectionCheckbox = (_jsx(Checkbox, { ref: selectionCheckboxRef, className: cx(classes.selectionCheckbox, 'mfui-DataTableRow__selectionCheckbox'), checked: checkboxProps?.checked, "aria-label": checkboxProps?.['aria-label'] ?? '行を選択', disabled: disabled || checkboxProps?.disabled, onChange: checkboxProps?.onChange, onClick: checkboxProps?.onClick, onKeyDown: handleKeyDownSelectionCheckbox }));
151
+ // Handles pointer clicks anywhere in the row and the bubbled click of the row action button.
68
152
  const handleClickRow = (event) => {
69
153
  if (disabled || isClickFromNestedInteractiveElement(event)) {
70
154
  return;
@@ -74,29 +158,17 @@ export const DataTableRow = forwardRef(({ children, disabled = false, highlighte
74
158
  }
75
159
  onClickRow?.(event);
76
160
  };
77
- const handleKeyDownRow = (event) => {
78
- if (!disabled && event.target === event.currentTarget && (event.key === 'Enter' || event.key === ' ')) {
79
- if (isRowClickSelectable) {
80
- // Not to scroll the page when the Space key is pressed on the focused row.
81
- event.preventDefault();
82
- toggleSelectionByRowInteraction();
83
- }
84
- onClickRow?.(event);
85
- }
86
- };
87
- return (_jsxs("tr", { ref: ref, className: cx(classes.root, 'mfui-DataTableRow__root',
88
- /* TODO: Remove in v5.0.0 */ 'mfui-DataGridRow__root', className), ...(ariaExpanded !== undefined && { 'aria-expanded': ariaExpanded }), ...props,
89
- // When the row is clickable, the role should be 'button' in order to allow screen readers to understand the row is clickable.
90
- role: isInteractive ? 'button' : 'row', tabIndex: isInteractive ? 0 : undefined, ...(disabled && { 'aria-disabled': disabled }), onClick: handleClickRow, onKeyDown: handleKeyDownRow, children: [isSelectable ? (_jsx(DataTableCell, { columnIndex: 0, isRowHighlighted: isRowHighlighted, disabled: disabled, children: checkboxProps?.wrapper ? checkboxProps.wrapper(selectionCheckbox) : selectionCheckbox })) : null, Children.map(children, (child, index) => {
91
- if (!isValidElement(child)) {
161
+ return (_jsx(DataTableRowActionContext.Provider, { value: rowActionContextValue, children: _jsxs("tr", { ref: ref, className: cx(classes.root, 'mfui-DataTableRow__root',
162
+ /* TODO: Remove in v5.0.0 */ 'mfui-DataGridRow__root', className), ...(!hasRowActionButton && ariaExpandedProp !== undefined && { 'aria-expanded': ariaExpandedProp }), ...props, ...(disabled && { 'aria-disabled': disabled }), onClick: handleClickRow, children: [isSelectable ? (_jsx(DataTableCell, { columnIndex: 0, isRowHighlighted: isRowHighlighted, disabled: disabled, children: checkboxProps?.wrapper ? checkboxProps.wrapper(selectionCheckbox) : selectionCheckbox })) : null, flatChildren.map((child, index) => {
163
+ if (!isValidElement(child)) {
164
+ return child;
165
+ }
166
+ if (isComponentOrWrapped(child, DataTableCell)) {
167
+ // Add selectable offset to columnIndex if selectable is true
168
+ const columnIndex = isSelectable ? index + 1 : index;
169
+ return cloneElement(child, { isRowHighlighted, columnIndex, disabled });
170
+ }
92
171
  return child;
93
- }
94
- if (isComponentOrWrapped(child, DataTableCell)) {
95
- // Add selectable offset to columnIndex if selectable is true
96
- const columnIndex = isSelectable ? index + 1 : index;
97
- return cloneElement(child, { isRowHighlighted, columnIndex, disabled });
98
- }
99
- return child;
100
- })] }));
172
+ })] }) }));
101
173
  });
102
174
  DataTableRow.displayName = 'DataTableRow';
@@ -1,4 +1,4 @@
1
- import { type ComponentPropsWithRef } from 'react';
1
+ import { type ComponentPropsWithRef, type ComponentPropsWithoutRef } from 'react';
2
2
  import { type CheckboxProps } from '../../Checkbox';
3
3
  import { type DataTableSelectionCheckboxWrapper } from '../DataTable.types';
4
4
  /**
@@ -11,7 +11,7 @@ import { type DataTableSelectionCheckboxWrapper } from '../DataTable.types';
11
11
  export type DataTableRowProps = {
12
12
  /**
13
13
  * Whether the row is disabled.
14
- * When true, interaction when the row is clicked and the checkbox for selectable feature will be disabled.
14
+ * When true, interaction when the row is clicked, the row action button and the checkbox for selectable feature will be disabled.
15
15
  * The row content remains visible with appropriate styling for readability.
16
16
  * Interactive elements passed as a children for DataTable.Cell won't be disabled automatically.
17
17
  *
@@ -19,8 +19,13 @@ export type DataTableRowProps = {
19
19
  */
20
20
  disabled?: boolean;
21
21
  /**
22
- * The state of the row whether it is highlighted without a selected.
23
- * This prop displays a highlighted background color regardless of the `enableRowSelection` prop of the DataTable component.
22
+ * Whether the row displays the highlighted background color.
23
+ * This prop works regardless of the `enableRowSelection` prop of the `DataTable` component: on a selectable table
24
+ * the row is highlighted when this prop is `true` OR when `checkboxProps.checked` is `true`, so a row can be
25
+ * highlighted while it is not selected.
26
+ *
27
+ * Note that the highlighted background is the same color as the selected one, so on a selectable table the
28
+ * selection checkbox, not the background, is what tells a selected row from a merely highlighted one.
24
29
  *
25
30
  * @default false
26
31
  */
@@ -47,10 +52,6 @@ export type DataTableRowProps = {
47
52
  * When the content restates the accessible name of the checkbox, pass `hideFromScreenReader` to the `Tooltip`
48
53
  * component to avoid announcing the same information twice.
49
54
  *
50
- * Note that when the `enableRowClickSelection` prop of the `DataTable` component is `true`, the checkbox is removed
51
- * from the tab order and the focusable element is the row, which is outside the wrapper. A tooltip in the wrapper is
52
- * then opened by hover only, so do not put information that keyboard users need in it in that case.
53
- *
54
55
  * ```tsx
55
56
  * <DataTable.Row
56
57
  * checkboxProps={{
@@ -64,25 +65,53 @@ export type DataTableRowProps = {
64
65
  };
65
66
  /**
66
67
  * The callback function that is called when the row is clicked.
67
- * If provided, the row can be focused and the focus indicator is displayed.
68
68
  *
69
- * This prop will be passed to the `onClick` and `onKeyDown` of the `tr` element.
70
- * When the element is clicked, the event is passed to the `onClickRow` prop, but event isn't passed when the Enter or Space key is pressed.
69
+ * If provided, a visually hidden button is rendered inside the row so that keyboard and
70
+ * screen reader users can perform the row action without making the `tr` element itself
71
+ * interactive. The `tr` element keeps the `row` role and is not focusable, so the controls
72
+ * inside the cells stay reachable. Activating the button (Enter or Space) triggers this
73
+ * callback via the bubbled click event, and the focus indicator is displayed on the row
74
+ * while the button is focused. The accessible name of the button can be customized with
75
+ * the `rowActionButtonProps` prop.
76
+ *
77
+ * The button is hosted by the first `DataTableCell` of the row that is not a row header (the
78
+ * selection checkbox cell when the row is selectable), wherever the cell is rendered in the
79
+ * React tree: intermediate components, wrapper components and Fragments are all fine. If the
80
+ * row renders no `DataTableCell` at all, the button is not rendered, the row becomes unusable
81
+ * with a keyboard or screen reader, and a warning is logged.
71
82
  *
72
83
  * Note that this callback is NOT called when the click originates from an interactive
73
84
  * descendant inside the row — e.g. a button, link, input (including `Checkbox`), select,
74
85
  * label, or an element with an interactive ARIA role such as `checkbox` or `menuitem`.
75
86
  * Handle those interactions on the descendant itself (e.g. the `Checkbox`'s `onChange`).
76
- * Likewise, Enter or Space triggers this callback only while the row itself is focused,
77
- * not while a focusable descendant is focused.
78
87
  *
79
88
  * When the `enableRowClickSelection` prop of the `DataTable` component is `true`, the selection checkbox stops
80
- * responding to clicks on its own, so this callback is called for the clicks on the checkbox cell as well.
89
+ * responding to pointer clicks on its own, so this callback is called for the clicks on the checkbox cell as well.
81
90
  * Do not toggle the row selection here in that case, otherwise the selection is toggled twice.
91
+ * Toggling the checkbox with the keyboard does not call this callback.
82
92
  *
83
93
  * @default undefined
84
94
  */
85
- onClickRow?: (event: React.MouseEvent<HTMLTableRowElement> | React.KeyboardEvent<HTMLTableRowElement>) => void;
95
+ onClickRow?: (event: React.MouseEvent<HTMLTableRowElement>) => void;
96
+ /**
97
+ * The properties for the visually hidden button that makes the clickable row accessible
98
+ * to keyboard and screen reader users.
99
+ * This prop is available when the `onClickRow` prop is provided.
100
+ * If this prop is not passed, the default values for each property will be applied.
101
+ *
102
+ * @property aria-label - The alternative text for the button. default is '行の操作', or '行を開閉' when the
103
+ * row toggles a disclosure (a cell has `disclosureIconProps` without `onClickCell`).
104
+ *
105
+ * @property aria-labelledby - The id of the element that names the button, e.g. the row header cell.
106
+ * It takes precedence over `aria-label`.
107
+ *
108
+ * @property aria-describedby - The id of the element that describes the button.
109
+ *
110
+ * @property aria-controls - The id of the element that the row action expands or collapses.
111
+ *
112
+ * @property id - The id of the button, e.g. to move the focus back to the row action after closing a dialog.
113
+ */
114
+ rowActionButtonProps?: Pick<ComponentPropsWithoutRef<'button'>, 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'aria-controls' | 'id'>;
86
115
  /**
87
116
  * Whether the table rows are selectable.
88
117
  * If `true`, the checkbox cell will be added to the first column of header and each row.
@@ -0,0 +1,34 @@
1
+ import { type ComponentPropsWithoutRef } from 'react';
2
+ /**
3
+ * The attributes of the visually hidden row action button, resolved by `DataTableRow`.
4
+ */
5
+ export type RowActionButtonProps = Pick<ComponentPropsWithoutRef<'button'>, 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'aria-controls' | 'aria-expanded' | 'id' | 'disabled'>;
6
+ /**
7
+ * A cell that registered itself as a candidate host of the row action button.
8
+ */
9
+ export type RowActionCellEntry = {
10
+ /** The rendered cell element, used to order the candidates by their position in the row. */
11
+ element: HTMLTableCellElement;
12
+ /** Row header cells host the button only when the row has no other cell. */
13
+ isRowHeader: boolean;
14
+ /** Called by the row when the cell becomes, or stops being, the host. */
15
+ setIsHost: (isHost: boolean) => void;
16
+ };
17
+ export type DataTableRowActionContextValue = {
18
+ /** The attributes of the row action button, or `undefined` when the row has no row action. */
19
+ buttonProps: RowActionButtonProps | undefined;
20
+ /**
21
+ * Registers a cell as a candidate host of the row action button, or `undefined` when the row has
22
+ * no row action so that the cells skip the registration.
23
+ *
24
+ * @returns The function that unregisters the cell.
25
+ */
26
+ registerCell: ((entry: RowActionCellEntry) => () => void) | undefined;
27
+ };
28
+ /**
29
+ * Lets any `DataTableCell` rendered inside a `DataTableRow` take part in hosting the row action
30
+ * button, regardless of how the consumer composes the cells (intermediate components, wrappers,
31
+ * Fragments). The row decides which registered cell hosts the button.
32
+ */
33
+ export declare const DataTableRowActionContext: import("react").Context<DataTableRowActionContextValue | null>;
34
+ export declare const useDataTableRowActionContext: () => DataTableRowActionContextValue | null;
@@ -0,0 +1,8 @@
1
+ import { createContext, useContext } from 'react';
2
+ /**
3
+ * Lets any `DataTableCell` rendered inside a `DataTableRow` take part in hosting the row action
4
+ * button, regardless of how the consumer composes the cells (intermediate components, wrappers,
5
+ * Fragments). The row decides which registered cell hosts the button.
6
+ */
7
+ export const DataTableRowActionContext = createContext(null);
8
+ export const useDataTableRowActionContext = () => useContext(DataTableRowActionContext);
@@ -1,7 +1,7 @@
1
1
  export { DataTable } from './DataTable';
2
2
  export { getColumnWidthFromContentWidth } from './utils/getColumnWidthFromContentWidth';
3
3
  export type { DataTableProps } from './DataTable.types';
4
- export type { DataTableBodyProps } from './DataTableBody';
4
+ export type { DataTableBodyProps, DataTableBodyVirtualizationOptions } from './DataTableBody';
5
5
  export type { DataTableCellProps } from './DataTableCell';
6
6
  export type { DataTableHeaderProps } from './DataTableHeader';
7
7
  export type { DataTableHeaderCellProps } from './DataTableHeaderCell';
@@ -22,9 +22,13 @@ export function DatePickerCalendar({ value, onChange, minDate, maxDate, checkDis
22
22
  const { viewingValue, setViewingValue, pendingFocusDate, setPendingFocusDate } = useBasePickerContext();
23
23
  const [internalValue, setInternalValue] = useState(value);
24
24
  const calendarLocale = useCalendarLocale();
25
- useEffect(() => {
25
+ // Adjusted during render (React's documented pattern for resyncing state to a changed
26
+ // prop) rather than in an effect, so the UI never flashes the stale value for one frame.
27
+ const [prevValueProp, setPrevValueProp] = useState(value);
28
+ if (value !== prevValueProp) {
29
+ setPrevValueProp(value);
26
30
  setInternalValue(value);
27
- }, [value]);
31
+ }
28
32
  const setValue = useCallback((date, event) => {
29
33
  setInternalValue(date);
30
34
  onChange?.(date, event);
@@ -81,7 +85,7 @@ export function DatePickerCalendar({ value, onChange, minDate, maxDate, checkDis
81
85
  newDate.setFullYear(year);
82
86
  setViewingValue(newDate);
83
87
  }, [setViewingValue, viewingValue]);
84
- const shouldFilterYears = !!(minDate || maxDate);
88
+ const shouldFilterYears = !!(minDate ?? maxDate);
85
89
  const filterYear = useCallback((y) => {
86
90
  const normalizedMinDate = minDate ? new Date(minDate) : undefined;
87
91
  const normalizedMaxDate = maxDate ? new Date(maxDate) : undefined;
@@ -39,5 +39,5 @@ export function DateRangePickerCalendar({ viewingMonth, handleKeyboardNavigation
39
39
  };
40
40
  return (_jsx(DateRangePickerDateCell, { ...rest, date: date, selected: selected, inRange: inRange, disabled: disabled, isRangeStart: isStart, isRangeEnd: isEnd, onClick: handleClick, onMouseEnter: handleMouseEnter, onFocus: handleFocus, onMouseLeave: clearPreview, onBlur: clearPreview }, date.toISOString()));
41
41
  }, [isDateDisabled, isRangeStart, isRangeEnd, isInRange, handleDateClick, handlePreview, clearPreview]);
42
- return (_jsx("div", { className: cx(classNames.root, 'mfui-DateRangePickerCalendar__root'), children: _jsx(CalendarGrid, { viewingValue: viewingMonth, renderDateCell: renderDateCell, pendingFocusDate: pendingFocusDate ?? undefined, value: temporaryStart || temporaryEnd, onDateClick: undefined, onPendingFocusDateChange: setPendingFocusDate, onKeyboardNavigation: handleKeyboardNavigation }) }));
42
+ return (_jsx("div", { className: cx(classNames.root, 'mfui-DateRangePickerCalendar__root'), children: _jsx(CalendarGrid, { viewingValue: viewingMonth, renderDateCell: renderDateCell, pendingFocusDate: pendingFocusDate ?? undefined, value: temporaryStart ?? temporaryEnd, onDateClick: undefined, onPendingFocusDateChange: setPendingFocusDate, onKeyboardNavigation: handleKeyboardNavigation }) }));
43
43
  }
@@ -5,7 +5,7 @@ export function createDateRangePickerPopoverTestUtility({ user }) {
5
5
  // Look for the previous month button by finding buttons that might contain previous month indicators
6
6
  const allButtons = screen.getAllByRole('button');
7
7
  // The previous month button is typically the first IconButton in the navigation
8
- return (allButtons.find((button) => button.getAttribute('aria-label')?.includes('月') || button.getAttribute('aria-label')?.includes('month')) ??
8
+ return (allButtons.find((button) => !!button.getAttribute('aria-label')?.includes('月') || !!button.getAttribute('aria-label')?.includes('month')) ??
9
9
  allButtons.find((button) => button.querySelector('svg')) ??
10
10
  allButtons[0]);
11
11
  }
@@ -15,7 +15,7 @@ export function createDateRangePickerPopoverTestUtility({ user }) {
15
15
  // Find the button with next month aria-label
16
16
  const nextButton = allButtons.find((button) => {
17
17
  const label = button.getAttribute('aria-label');
18
- return label?.includes('次の') || label?.includes('Next');
18
+ return !!label?.includes('次の') || !!label?.includes('Next');
19
19
  });
20
20
  return nextButton ?? allButtons[1]; // fallback to second button
21
21
  }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
3
+ import { createContext, useCallback, useContext, useMemo, useState } from 'react';
4
4
  import { flushSync } from 'react-dom';
5
5
  import { dayjs } from '../../../utilities/date/dayjs';
6
6
  import { useUpdateEffect } from '../../../utilities/effect/useUpdateEffect';
@@ -48,7 +48,7 @@ const useDateRangePickerContextValue = ({ value, defaultValue, disabled = false,
48
48
  const today = useMemo(() => new Date(), []);
49
49
  const [viewingMonth, setViewingMonth] = useTransformedState(value?.[0] ?? defaultValue?.[0] ?? new Date(today.getFullYear(), today.getMonth(), 1), normalizeToFirstOfMonth);
50
50
  // --- Selection/Preview State and Logic ---
51
- const [selecting, setSelecting] = useState('start');
51
+ const [selecting, setSelecting] = useState(() => (!startDate || endDate ? 'start' : 'end'));
52
52
  const [temporaryStart, setTemporaryStart] = useState(startDate);
53
53
  const [temporaryEnd, setTemporaryEnd] = useState(endDate);
54
54
  const [previewDate, setPreviewDate] = useState();
@@ -85,10 +85,10 @@ const useDateRangePickerContextValue = ({ value, defaultValue, disabled = false,
85
85
  onChange?.([newStartDate, newEndDate]);
86
86
  }, [onChange, format, setDates]);
87
87
  const handleStartDateChange = useCallback((date, nextEndDate) => {
88
- handleChange([date, nextEndDate !== undefined ? nextEndDate : endDate]);
88
+ handleChange([date, nextEndDate ?? endDate]);
89
89
  }, [endDate, handleChange]);
90
90
  const handleEndDateChange = useCallback((date, nextStartDate) => {
91
- handleChange([nextStartDate !== undefined ? nextStartDate : startDate, date]);
91
+ handleChange([nextStartDate ?? startDate, date]);
92
92
  }, [startDate, handleChange]);
93
93
  const handleStartDateStringChange = useCallback((value) => {
94
94
  setDateStrings([value, endDateString]);
@@ -131,12 +131,18 @@ const useDateRangePickerContextValue = ({ value, defaultValue, disabled = false,
131
131
  setTemporaryEnd(undefined);
132
132
  close();
133
133
  }, [handleChange, close]);
134
- useEffect(() => {
134
+ // Adjusted during render (React's documented pattern for resyncing state to changed
135
+ // props) rather than in an effect, so the UI never flashes the stale value for one frame.
136
+ const [prevStartDate, setPrevStartDate] = useState(startDate);
137
+ const [prevEndDate, setPrevEndDate] = useState(endDate);
138
+ if (startDate !== prevStartDate || endDate !== prevEndDate) {
139
+ setPrevStartDate(startDate);
140
+ setPrevEndDate(endDate);
135
141
  setTemporaryStart(startDate);
136
142
  setTemporaryEnd(endDate);
137
143
  setSelecting(!startDate || endDate ? 'start' : 'end');
138
144
  setPreviewDate(undefined);
139
- }, [startDate, endDate]);
145
+ }
140
146
  const handleDateClick = useCallback((date) => {
141
147
  // Prevent selection of disabled dates
142
148
  if (isDateOutsideConstraints(date, minDate, maxDate)) {
@@ -200,7 +206,7 @@ const useDateRangePickerContextValue = ({ value, defaultValue, disabled = false,
200
206
  }
201
207
  // handleChange already calls setDates and setDateStrings, so we don't need to call them again
202
208
  handleChange([newStart, newEnd]);
203
- // Do not setTemporaryStart/setTemporaryEnd here; let the effect sync them from startDate/endDate
209
+ // Do not setTemporaryStart/setTemporaryEnd here; the render-time adjustment above syncs them from startDate/endDate
204
210
  close();
205
211
  }, [handleChange, close, temporaryStart, temporaryEnd, minDate, maxDate]);
206
212
  const handleCancel = useCallback(() => {
@@ -34,7 +34,7 @@ export const DateRangePickerTrigger = forwardRef(({ enableClearValue = false, in
34
34
  });
35
35
  const { placeholder: startPlaceholder = LOCALE.START_DATE_PLACEHOLDER } = startInputProps;
36
36
  const { placeholder: endPlaceholder = LOCALE.END_DATE_PLACEHOLDER } = endInputProps;
37
- const shouldShowClearButton = enableClearValue && (enhancedStartInputProps.value || enhancedEndInputProps.value);
37
+ const shouldShowClearButton = enableClearValue && ((enhancedStartInputProps.value ?? '') || (enhancedEndInputProps.value ?? ''));
38
38
  // The error state takes precedence over the caution state
39
39
  const classes = baseRangePickerTriggerSlotRecipe({ invalid, caution: caution && !invalid, disabled, size });
40
40
  const handleClickClearButton = useCallback((event) => {
@@ -25,7 +25,7 @@ export function FilterDatePicker({ label, value, defaultValue, onChange, open, o
25
25
  const triggerRef = useRef(null);
26
26
  const dialogId = useId();
27
27
  const [internalValue, setInternalValue] = useState(defaultValue);
28
- const currentValue = value !== undefined ? value : internalValue;
28
+ const currentValue = value ?? internalValue;
29
29
  // When a controlled value transitions back to undefined, clear any stale internal value
30
30
  // so the component doesn't show a previously-selected uncontrolled date.
31
31
  const previousValueRef = useRef(value);
@@ -24,7 +24,7 @@ export function FilterMonthPicker({ label, value, defaultValue, onChange, open,
24
24
  const triggerRef = useRef(null);
25
25
  const dialogId = useId();
26
26
  const [internalValue, setInternalValue] = useState(defaultValue);
27
- const currentValue = value !== undefined ? value : internalValue;
27
+ const currentValue = value ?? internalValue;
28
28
  // When a controlled value transitions back to undefined, clear any stale internal value
29
29
  // so the component doesn't show a previously-selected uncontrolled month.
30
30
  const previousValueRef = useRef(value);
@@ -26,7 +26,7 @@ export function FilterMonthRangePicker({ label, value, defaultValue, onChange, o
26
26
  const triggerRef = useRef(null);
27
27
  const dialogId = useId();
28
28
  const [internalValue, setInternalValue] = useState(() => defaultValue ?? [undefined, undefined]);
29
- const currentValue = value !== undefined ? value : internalValue;
29
+ const currentValue = value ?? internalValue;
30
30
  const previousValueRef = useRef(value);
31
31
  useEffect(() => {
32
32
  const previousValue = previousValueRef.current;
@@ -88,7 +88,7 @@ export function MonthPickerPanel({ viewingValue, setViewingValue, value, onChang
88
88
  const handleYearSelect = useCallback((newYear) => {
89
89
  setViewingValue(new Date(newYear, 0, 1));
90
90
  }, [setViewingValue]);
91
- const shouldFilterYears = !!(minMonth || maxMonth || checkDisabledMonth);
91
+ const shouldFilterYears = !!(minMonth ?? maxMonth ?? checkDisabledMonth);
92
92
  const filterYear = useCallback((y) => {
93
93
  const normalizedMinMonth = minMonth ? new Date(minMonth) : undefined;
94
94
  const normalizedMaxMonth = maxMonth ? new Date(maxMonth) : undefined;
@@ -1,5 +1,5 @@
1
- export declare const LABEL_PREV_YEAR = "\u524D\u306E\u5E74";
2
- export declare const LABEL_NEXT_YEAR = "\u6B21\u306E\u5E74";
1
+ export declare const LABEL_PREV_YEAR = "\u524D\u306E\u5E74\u3092\u8868\u793A";
2
+ export declare const LABEL_NEXT_YEAR = "\u6B21\u306E\u5E74\u3092\u8868\u793A";
3
3
  export declare const LABEL_OPEN_CALENDAR = "\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u958B\u304F";
4
4
  export declare const LABEL_CLOSE_CALENDAR = "\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9589\u3058\u308B";
5
5
  type MonthPickerLabelKey = 'prevYear' | 'nextYear';