@moneyforward/mfui-components 3.37.2 → 4.0.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 (87) hide show
  1. package/README.md +1 -1
  2. package/dist/src/Button/Button.js +1 -1
  3. package/dist/src/Button/Button.types.d.ts +6 -0
  4. package/dist/src/DataGrid/index.d.ts +40 -8
  5. package/dist/src/DataGrid/index.js +5 -1
  6. package/dist/src/DataTable/DataTable.js +2 -2
  7. package/dist/src/DataTable/DataTable.types.d.ts +20 -0
  8. package/dist/src/DataTable/DataTableCell/DataTableCell.js +8 -5
  9. package/dist/src/DataTable/DataTableHeaderCell/DataTableHeaderCell.js +3 -3
  10. package/dist/src/DataTable/DataTableProvider.d.ts +2 -2
  11. package/dist/src/DataTable/DataTableProvider.js +4 -1
  12. package/dist/src/DataTable/DataTableRow/DataTableRow.js +22 -5
  13. package/dist/src/DataTable/DataTableRow/DataTableRow.types.d.ts +4 -0
  14. package/dist/src/DateTimeSelection/DatePicker/DatePicker.d.ts +8 -1
  15. package/dist/src/DateTimeSelection/DatePicker/DatePicker.js +4 -2
  16. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePicker.d.ts +1 -1
  17. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePicker.js +4 -2
  18. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePicker.types.d.ts +7 -0
  19. package/dist/src/DateTimeSelection/FilterDatePicker/CalendarPopover/CalendarPopover.d.ts +1 -1
  20. package/dist/src/DateTimeSelection/FilterDatePicker/CalendarPopover/CalendarPopover.js +5 -4
  21. package/dist/src/DateTimeSelection/FilterDatePicker/CalendarPopover/CalendarPopover.types.d.ts +1 -0
  22. package/dist/src/DateTimeSelection/FilterDatePicker/FilterDatePicker.d.ts +1 -1
  23. package/dist/src/DateTimeSelection/FilterDatePicker/FilterDatePicker.js +3 -2
  24. package/dist/src/DateTimeSelection/FilterDatePicker/FilterDatePicker.types.d.ts +7 -0
  25. package/dist/src/DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.d.ts +1 -1
  26. package/dist/src/DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.js +3 -2
  27. package/dist/src/DateTimeSelection/FilterDateRangePicker/DateRangePickerContent/DateRangePickerContent.types.d.ts +1 -0
  28. package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.d.ts +1 -1
  29. package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.js +3 -2
  30. package/dist/src/DateTimeSelection/FilterDateRangePicker/FilterDateRangePicker.types.d.ts +7 -0
  31. package/dist/src/DateTimeSelection/shared/BasePicker/constants.d.ts +28 -2
  32. package/dist/src/DateTimeSelection/shared/BasePicker/constants.js +15 -4
  33. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerPopover/BaseRangePickerPopover.d.ts +4 -0
  34. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerPopover/BaseRangePickerPopover.js +4 -0
  35. package/dist/src/DateTimeSelection/shared/CalendarGrid/CalendarGrid.js +9 -5
  36. package/dist/src/DateTimeSelection/shared/CalendarGrid/utilities/computeDataForStyling.d.ts +3 -1
  37. package/dist/src/DateTimeSelection/shared/CalendarGrid/utilities/computeDataForStyling.js +20 -18
  38. package/dist/src/DateTimeSelection/shared/CalendarGrid/utilities/useDates.d.ts +6 -3
  39. package/dist/src/DateTimeSelection/shared/CalendarGrid/utilities/useDates.js +9 -5
  40. package/dist/src/DateTimeSelection/shared/CalendarLocale/FirstDayOfWeekContext.d.ts +8 -0
  41. package/dist/src/DateTimeSelection/shared/CalendarLocale/FirstDayOfWeekContext.js +11 -0
  42. package/dist/src/DateTimeSelection/shared/DateCell/DateCell.types.d.ts +1 -1
  43. package/dist/src/DateTimeSelection/shared/DayCell/DayCell.d.ts +4 -3
  44. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueList.d.ts +22 -0
  45. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueList.js +28 -0
  46. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueList.types.d.ts +21 -0
  47. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueList.types.js +1 -0
  48. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueListItem/DecoratedKeyValueListItem.d.ts +8 -0
  49. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueListItem/DecoratedKeyValueListItem.js +18 -0
  50. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueListItem/DecoratedKeyValueListItem.types.d.ts +25 -0
  51. package/dist/src/DecoratedKeyValueList/DecoratedKeyValueListItem/DecoratedKeyValueListItem.types.js +1 -0
  52. package/dist/src/DecoratedKeyValueList/index.d.ts +4 -0
  53. package/dist/src/DecoratedKeyValueList/index.js +2 -0
  54. package/dist/src/DisplayTable/DisplayTable.d.ts +1 -1
  55. package/dist/src/DisplayTable/DisplayTable.js +8 -3
  56. package/dist/src/DisplayTable/DisplayTable.types.d.ts +44 -2
  57. package/dist/src/EmbeddedSidePane/EmbeddedSidePane.d.ts +2 -3
  58. package/dist/src/EmbeddedSidePane/EmbeddedSidePane.types.d.ts +2 -2
  59. package/dist/src/MainNavigation/BaseMainNavigation.js +2 -2
  60. package/dist/src/MainNavigation/NarrowViewportMainNavigation.js +2 -2
  61. package/dist/src/MultilineTextBox/index.d.ts +10 -2
  62. package/dist/src/MultilineTextBox/index.js +5 -1
  63. package/dist/src/SectionMessage/SectionMessage.js +2 -2
  64. package/dist/src/SidePane/SidePane.d.ts +4 -22
  65. package/dist/src/SidePane/SidePane.js +8 -4
  66. package/dist/src/SidePane/SidePane.types.d.ts +50 -8
  67. package/dist/src/SidePane/index.d.ts +1 -1
  68. package/dist/src/Sidebar/Sidebar.d.ts +0 -2
  69. package/dist/src/Sidebar/Sidebar.js +0 -2
  70. package/dist/src/SubNavigation/SubNavigation.js +2 -2
  71. package/dist/src/TextLink/TextLink.js +1 -1
  72. package/dist/src/Toast/Toast.js +1 -1
  73. package/dist/src/index.d.ts +1 -0
  74. package/dist/src/index.js +1 -0
  75. package/dist/styled-system/recipes/data-table-cell-slot-recipe.d.ts +1 -0
  76. package/dist/styled-system/recipes/data-table-cell-slot-recipe.js +5 -0
  77. package/dist/styled-system/recipes/data-table-row-slot-recipe.d.ts +2 -1
  78. package/dist/styled-system/recipes/data-table-row-slot-recipe.js +9 -0
  79. package/dist/styled-system/recipes/decorated-key-value-list-item-slot-recipe.d.ts +33 -0
  80. package/dist/styled-system/recipes/decorated-key-value-list-item-slot-recipe.js +40 -0
  81. package/dist/styled-system/recipes/decorated-key-value-list-slot-recipe.d.ts +36 -0
  82. package/dist/styled-system/recipes/decorated-key-value-list-slot-recipe.js +37 -0
  83. package/dist/styled-system/recipes/index.d.ts +2 -0
  84. package/dist/styled-system/recipes/index.js +2 -0
  85. package/dist/styles.css +140 -13
  86. package/dist/tsconfig.build.tsbuildinfo +1 -1
  87. package/package.json +3 -3
package/README.md CHANGED
@@ -99,7 +99,7 @@ import { IconButton } from '@moneyforward/mfui-components';
99
99
 
100
100
  export function Bar() {
101
101
  return (
102
- <IconButton>
102
+ <IconButton aria-label="Add">
103
103
  <Add />
104
104
  </IconButton>
105
105
  );
@@ -50,5 +50,5 @@ type = 'button', href, customLinkComponent, ...props }, ref) => {
50
50
  ...props,
51
51
  };
52
52
  }, [isButton, classes.root, className, href, isDisabled, type, props, ref]);
53
- return (_jsx(FocusIndicator, { children: _jsxs(Tag, { ...tagProps, children: [leftIcon ? _jsx("div", { className: cx(classes.leftIcon, 'mfui-Button__leftIcon'), children: leftIcon }) : null, loading ? (_jsx(ProgressIndicator, { className: cx(classes.loadingIndicator, 'mfui-Button__loadingIndicator') })) : null, typeof children === 'string' ? _jsx(Typography, { variant: typographyVariant, children: children }) : children, rightIcon ? _jsx("div", { className: cx(classes.rightIcon, 'mfui-Button__rightIcon'), children: rightIcon }) : null, isDropdownTrigger ? (_jsx(Dropdown, { "aria-hidden": "true", className: cx(classes.dropdownIcon, 'mfui-Button__dropdownIcon') })) : null] }) }));
53
+ return (_jsx(FocusIndicator, { children: _jsxs(Tag, { ...tagProps, children: [leftIcon ? (_jsx("div", { "aria-hidden": "true", className: cx(classes.leftIcon, 'mfui-Button__leftIcon'), children: leftIcon })) : null, loading ? (_jsx(ProgressIndicator, { className: cx(classes.loadingIndicator, 'mfui-Button__loadingIndicator') })) : null, typeof children === 'string' ? _jsx(Typography, { variant: typographyVariant, children: children }) : children, rightIcon ? (_jsx("div", { "aria-hidden": "true", className: cx(classes.rightIcon, 'mfui-Button__rightIcon'), children: rightIcon })) : null, isDropdownTrigger ? (_jsx(Dropdown, { "aria-hidden": "true", className: cx(classes.dropdownIcon, 'mfui-Button__dropdownIcon') })) : null] }) }));
54
54
  });
@@ -38,6 +38,9 @@ export type ButtonProps = {
38
38
  * Icon element to be rendered on the left side within the button
39
39
  * Only one element is allowed
40
40
  *
41
+ * The icon is treated as decorative and hidden from assistive technologies.
42
+ * If the icon conveys meaning, express it in the button's text content or `aria-label` instead.
43
+ *
41
44
  * @default undefined
42
45
  */
43
46
  leftIcon?: React.ReactElement;
@@ -59,6 +62,9 @@ export type ButtonProps = {
59
62
  * Icon element to be rendered on the right side and before dropdown trigger within the button
60
63
  * Only one element is allowed
61
64
  *
65
+ * The icon is treated as decorative and hidden from assistive technologies.
66
+ * If the icon conveys meaning, express it in the button's text content or `aria-label` instead.
67
+ *
62
68
  * @default undefined
63
69
  */
64
70
  rightIcon?: React.ReactElement;
@@ -6,11 +6,43 @@
6
6
  *
7
7
  * @see DataTable
8
8
  */
9
- export { DataTable as DataGrid } from '../DataTable';
10
- export type { DataTableProps as DataGridProps } from '../DataTable';
11
- export type { DataTableBodyProps as DataGridBodyProps } from '../DataTable';
12
- export type { DataTableCellProps as DataGridCellProps } from '../DataTable';
13
- export type { DataTableHeaderProps as DataGridHeaderProps } from '../DataTable';
14
- export type { DataTableHeaderCellProps as DataGridHeaderCellProps } from '../DataTable';
15
- export type { DataTableHeaderRowProps as DataGridHeaderRowProps } from '../DataTable';
16
- export type { DataTableRowProps as DataGridRowProps } from '../DataTable';
9
+ export {
10
+ /**
11
+ * @deprecated Use `DataTable` instead. `DataGrid` will be removed in v5.0.0.
12
+ */
13
+ DataTable as DataGrid, } from '../DataTable';
14
+ export type {
15
+ /**
16
+ * @deprecated Use `DataTableProps` instead. `DataGridProps` will be removed in v5.0.0.
17
+ */
18
+ DataTableProps as DataGridProps, } from '../DataTable';
19
+ export type {
20
+ /**
21
+ * @deprecated Use `DataTableBodyProps` instead. `DataGridBodyProps` will be removed in v5.0.0.
22
+ */
23
+ DataTableBodyProps as DataGridBodyProps, } from '../DataTable';
24
+ export type {
25
+ /**
26
+ * @deprecated Use `DataTableCellProps` instead. `DataGridCellProps` will be removed in v5.0.0.
27
+ */
28
+ DataTableCellProps as DataGridCellProps, } from '../DataTable';
29
+ export type {
30
+ /**
31
+ * @deprecated Use `DataTableHeaderProps` instead. `DataGridHeaderProps` will be removed in v5.0.0.
32
+ */
33
+ DataTableHeaderProps as DataGridHeaderProps, } from '../DataTable';
34
+ export type {
35
+ /**
36
+ * @deprecated Use `DataTableHeaderCellProps` instead. `DataGridHeaderCellProps` will be removed in v5.0.0.
37
+ */
38
+ DataTableHeaderCellProps as DataGridHeaderCellProps, } from '../DataTable';
39
+ export type {
40
+ /**
41
+ * @deprecated Use `DataTableHeaderRowProps` instead. `DataGridHeaderRowProps` will be removed in v5.0.0.
42
+ */
43
+ DataTableHeaderRowProps as DataGridHeaderRowProps, } from '../DataTable';
44
+ export type {
45
+ /**
46
+ * @deprecated Use `DataTableRowProps` instead. `DataGridRowProps` will be removed in v5.0.0.
47
+ */
48
+ DataTableRowProps as DataGridRowProps, } from '../DataTable';
@@ -6,4 +6,8 @@
6
6
  *
7
7
  * @see DataTable
8
8
  */
9
- export { DataTable as DataGrid } from '../DataTable';
9
+ export {
10
+ /**
11
+ * @deprecated Use `DataTable` instead. `DataGrid` will be removed in v5.0.0.
12
+ */
13
+ DataTable as DataGrid, } from '../DataTable';
@@ -13,7 +13,7 @@ import { DataTableRow } from './DataTableRow';
13
13
  import { DataTableSortButton } from './DataTableSortButton';
14
14
  import { cx } from '../../styled-system/css';
15
15
  import { isComponentOrWrapped } from '../utilities/react/isComponentOrWrapped';
16
- const Base = forwardRef(({ className, size = 'medium', enableRowSelection = false, fixedHeader = false, showVerticalBorder = false, leftFixedColumnIndex, rightFixedColumnIndex, layout = 'default', wrapperProps, loading = false, emptyStateSlot, children, ...props }, ref) => {
16
+ const Base = forwardRef(({ className, size = 'medium', enableRowSelection = false, enableRowClickSelection = false, fixedHeader = false, showVerticalBorder = false, leftFixedColumnIndex, rightFixedColumnIndex, layout = 'default', wrapperProps, loading = false, emptyStateSlot, children, ...props }, ref) => {
17
17
  const classes = dataTableSlotRecipe({ layout });
18
18
  // Check if DataTable has any rows by looking for DataTable.Body with DataTable.Row children
19
19
  const hasRows = useMemo(() => {
@@ -38,7 +38,7 @@ const Base = forwardRef(({ className, size = 'medium', enableRowSelection = fals
38
38
  return false;
39
39
  }, [children, loading]);
40
40
  const shouldShowEmptyState = !hasRows && !!emptyStateSlot && !loading;
41
- return (_jsx(DataTableProvider, { size: size, enableRowSelection: enableRowSelection, fixedHeader: fixedHeader, showVerticalBorder: showVerticalBorder, leftFixedColumnIndex: leftFixedColumnIndex, rightFixedColumnIndex: rightFixedColumnIndex, loading: loading, layout: layout, children: _jsxs("div", { ...wrapperProps, className: cx(classes.wrapper, 'mfui-DataTable__wrapper',
41
+ return (_jsx(DataTableProvider, { size: size, enableRowSelection: enableRowSelection, enableRowClickSelection: enableRowClickSelection, fixedHeader: fixedHeader, showVerticalBorder: showVerticalBorder, leftFixedColumnIndex: leftFixedColumnIndex, rightFixedColumnIndex: rightFixedColumnIndex, loading: loading, layout: layout, children: _jsxs("div", { ...wrapperProps, className: cx(classes.wrapper, 'mfui-DataTable__wrapper',
42
42
  /* TODO: Remove in v5.0.0 */ 'mfui-DataGrid__wrapper', wrapperProps?.className), children: [_jsx("table", { ref: ref, className: cx(classes.table, 'mfui-DataTable__table',
43
43
  /* TODO: Remove in v5.0.0 */ 'mfui-DataGrid__table', className), ...props, children: children }), shouldShowEmptyState ? (_jsx("div", { className: cx(classes.emptyState, 'mfui-DataTable__emptyState',
44
44
  /* TODO: Remove in v5.0.0 */ 'mfui-DataGrid__emptyState'), role: "status", "aria-live": "polite", children: emptyStateSlot })) : null] }) }));
@@ -31,6 +31,26 @@ export type DataTableProps = {
31
31
  * @default false
32
32
  */
33
33
  enableRowSelection?: boolean;
34
+ /**
35
+ * Whether clicking anywhere in a selectable row toggles its selection.
36
+ * This prop is intended to be combined with the `enableRowSelection` prop, and has no effect on rows that are not selectable.
37
+ *
38
+ * If `true`, the whole row becomes the trigger of the row selection:
39
+ *
40
+ * - Clicking the row, including its checkbox cell, calls the `checkboxProps.onChange` of the `DataTable.Row` component once.
41
+ * The checkbox stops responding to clicks on its own, so a single click never toggles the selection twice.
42
+ * The checkbox cell does not have independent hover, focus, or active styles; the checkbox icon follows the row state.
43
+ * - The row is focusable, and pressing Enter or Space while the row itself is focused toggles the selection.
44
+ * The checkbox is removed from the tab order, so keyboard selection is handled through the row.
45
+ * - The row selection is not toggled when the click originates from another interactive element inside the row,
46
+ * such as a button or a link, or when the row or its checkbox is disabled.
47
+ *
48
+ * Note that the `onClickRow` prop of the `DataTable.Row` component is still called for the row clicks.
49
+ * Do not toggle the row selection in `onClickRow` while this prop is `true`, otherwise the selection is toggled twice.
50
+ *
51
+ * @default false
52
+ */
53
+ enableRowClickSelection?: boolean;
34
54
  /**
35
55
  * Whether the header is fixed when scrolling horizontally.
36
56
  * If `true`, the header will be sticky.
@@ -11,20 +11,23 @@ import { useFixedColumns } from '../../utilities/dom/useFixedColumns';
11
11
  import { handleCheckboxCellClick } from '../utils/handleCheckbox';
12
12
  import { mergeRefs } from '../../utilities/dom/mergeRefs';
13
13
  export const DataTableCell = forwardRef(({ onClickCell, children, type = 'text', className, isRowHighlighted, isRowHeader = false, disabled = false, depth = 0, columnIndex, disclosureIconProps: nestingIconProps, style, ...props }, ref) => {
14
- const { size, leftFixedColumnIndex, rightFixedColumnIndex, loading, enableRowSelection, showVerticalBorder, layout, } = useDataTableContext();
14
+ const { size, leftFixedColumnIndex, rightFixedColumnIndex, loading, enableRowSelection, enableRowClickSelection, showVerticalBorder, layout, } = useDataTableContext();
15
15
  const { cellRef, isFixedColumn, isEdgeFixedColumn, fixedPositionStyles } = useFixedColumns({
16
16
  enableRowSelection,
17
17
  columnIndex,
18
18
  leftFixedColumnIndex,
19
19
  rightFixedColumnIndex,
20
20
  });
21
+ const isCheckboxCell = enableRowSelection && columnIndex === 0;
22
+ const isCheckboxCellInteractive = isCheckboxCell && !enableRowClickSelection;
21
23
  const classes = dataTableCellSlotRecipe({
22
24
  size,
23
25
  type,
24
26
  rowHighlighted: isRowHighlighted,
25
27
  fixedColumn: isFixedColumn,
26
28
  edgeFixedColumn: isEdgeFixedColumn,
27
- isCheckboxCell: enableRowSelection && columnIndex === 0,
29
+ isCheckboxCell,
30
+ isCheckboxCellInteractive: isCheckboxCellInteractive || undefined,
28
31
  verticalBorder: showVerticalBorder,
29
32
  layout,
30
33
  // Passing `false` would emit a class for the unused `false` variant value, changing the
@@ -36,7 +39,6 @@ export const DataTableCell = forwardRef(({ onClickCell, children, type = 'text',
36
39
  const handleClick = (event) => {
37
40
  onClickCell?.(event);
38
41
  };
39
- const isCheckboxCell = enableRowSelection && columnIndex === 0;
40
42
  const cellContent = (() => {
41
43
  if (loading) {
42
44
  return (_jsx("div", { className: cx(classes.skeletonCell, 'mfui-DataTableCell__skeletonCell',
@@ -47,8 +49,9 @@ export const DataTableCell = forwardRef(({ onClickCell, children, type = 'text',
47
49
  /* TODO: Remove in v5.0.0 */ 'mfui-DataGridCell__interactiveCell'), ...(nestingIconProps && { 'aria-expanded': nestingIconProps.isOpen ?? false }), onClick: handleClick, children: _jsx(CellContent, { depth: depth, disclosureIconProps: nestingIconProps, classes: classes, children: children }) }) }));
48
50
  }
49
51
  if (isCheckboxCell) {
50
- return (_jsx(FocusIndicator, { position: "inside", children: _jsx("div", { className: cx(classes.defaultCell, 'mfui-DataTableCell__defaultCell',
51
- /* TODO: Remove in v5.0.0 */ 'mfui-DataGridCell__defaultCell'), "data-mfui-content": "data-table-checkbox-cell", ...(disabled && { 'data-disabled': true, 'aria-disabled': true }), onClick: disabled ? undefined : handleCheckboxCellClick, children: _jsx(CellContent, { depth: depth, disclosureIconProps: nestingIconProps, classes: classes, children: children }) }) }));
52
+ const checkboxCell = (_jsx("div", { className: cx(classes.defaultCell, 'mfui-DataTableCell__defaultCell',
53
+ /* TODO: Remove in v5.0.0 */ 'mfui-DataGridCell__defaultCell'), ...(isCheckboxCellInteractive && { 'data-mfui-content': 'data-table-checkbox-cell' }), ...(disabled && { 'data-disabled': true, 'aria-disabled': true }), onClick: disabled || !isCheckboxCellInteractive ? undefined : handleCheckboxCellClick, children: _jsx(CellContent, { depth: depth, disclosureIconProps: nestingIconProps, classes: classes, children: children }) }));
54
+ return isCheckboxCellInteractive ? (_jsx(FocusIndicator, { position: "inside", children: checkboxCell })) : (checkboxCell);
52
55
  }
53
56
  return (_jsx("div", { className: cx(classes.defaultCell, 'mfui-DataTableCell__defaultCell',
54
57
  /* TODO: Remove in v5.0.0 */ 'mfui-DataGridCell__defaultCell'), children: _jsx(CellContent, { depth: depth, disclosureIconProps: nestingIconProps, classes: classes, children: children }) }));
@@ -31,14 +31,14 @@ export const DataTableHeaderCell = forwardRef(({ children, type = 'text', sortBu
31
31
  const sortIcon = (() => {
32
32
  if (!sortOrder) {
33
33
  return (_jsx(SortUnsorted, { className: cx(classes.unsortedIcon, 'mfui-DataTableHeaderCell__unsortedIcon',
34
- /* TODO: Remove in v5.0.0 */ 'mfui-DataGridHeaderCell__unsortedIcon'), "aria-label": unsortedIconProps?.['aria-label'] ?? '並び替えを解除' }));
34
+ /* TODO: Remove in v5.0.0 */ 'mfui-DataGridHeaderCell__unsortedIcon'), role: "img", "aria-label": unsortedIconProps?.['aria-label'] ?? '並び替えを解除' }));
35
35
  }
36
36
  if (sortOrder === 'ascending') {
37
37
  return (_jsx(SortAscending, { className: cx(classes.sortIcon, 'mfui-DataTableHeaderCell__sortIcon',
38
- /* TODO: Remove in v5.0.0 */ 'mfui-DataGridHeaderCell__sortIcon'), "aria-label": ascendingIconProps?.['aria-label'] ?? '昇順で並び替え' }));
38
+ /* TODO: Remove in v5.0.0 */ 'mfui-DataGridHeaderCell__sortIcon'), role: "img", "aria-label": ascendingIconProps?.['aria-label'] ?? '昇順で並び替え' }));
39
39
  }
40
40
  return (_jsx(SortDescending, { className: cx(classes.sortIcon, 'mfui-DataTableHeaderCell__sortIcon',
41
- /* TODO: Remove in v5.0.0 */ 'mfui-DataGridHeaderCell__sortIcon'), "aria-label": descendingIconProps?.['aria-label'] ?? '降順で並び替え' }));
41
+ /* TODO: Remove in v5.0.0 */ 'mfui-DataGridHeaderCell__sortIcon'), role: "img", "aria-label": descendingIconProps?.['aria-label'] ?? '降順で並び替え' }));
42
42
  })();
43
43
  const handleClickSortButton = sortButtonProps?.onClick;
44
44
  const cellContent = (() => {
@@ -4,7 +4,7 @@ export type DataTableSize = 'small' | 'medium';
4
4
  /**
5
5
  * The props for the `DataTableContext` component.
6
6
  */
7
- export type DataTableContextProps = Pick<DataTableProps, 'size' | 'enableRowSelection' | 'fixedHeader' | 'showVerticalBorder' | 'leftFixedColumnIndex' | 'rightFixedColumnIndex' | 'loading' | 'layout'>;
7
+ export type DataTableContextProps = Pick<DataTableProps, 'size' | 'enableRowSelection' | 'enableRowClickSelection' | 'fixedHeader' | 'showVerticalBorder' | 'leftFixedColumnIndex' | 'rightFixedColumnIndex' | 'loading' | 'layout'>;
8
8
  export type DataTableProviderValues = {
9
9
  numberColumns: number;
10
10
  setNumberColumns: (number: number) => void;
@@ -24,4 +24,4 @@ export declare const useDataTableContext: () => DataTableProviderValues;
24
24
  *
25
25
  * This should only be used in DataTable component.
26
26
  */
27
- export declare function DataTableProvider({ children, size, enableRowSelection, fixedHeader, showVerticalBorder, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout, }: PropsWithChildren<DataTableContextProps>): import("react/jsx-runtime").JSX.Element;
27
+ export declare function DataTableProvider({ children, size, enableRowSelection, enableRowClickSelection, fixedHeader, showVerticalBorder, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout, }: PropsWithChildren<DataTableContextProps>): import("react/jsx-runtime").JSX.Element;
@@ -9,6 +9,7 @@ import { createContext, useContext, useMemo, useState } from 'react';
9
9
  export const DataTableContext = createContext({
10
10
  size: 'medium',
11
11
  enableRowSelection: false,
12
+ enableRowClickSelection: false,
12
13
  fixedHeader: false,
13
14
  showVerticalBorder: false,
14
15
  leftFixedColumnIndex: undefined,
@@ -28,11 +29,12 @@ export const useDataTableContext = () => useContext(DataTableContext);
28
29
  *
29
30
  * This should only be used in DataTable component.
30
31
  */
31
- export function DataTableProvider({ children, size = 'medium', enableRowSelection = false, fixedHeader = false, showVerticalBorder = false, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout = 'default', }) {
32
+ export function DataTableProvider({ children, size = 'medium', enableRowSelection = false, enableRowClickSelection = false, fixedHeader = false, showVerticalBorder = false, leftFixedColumnIndex, rightFixedColumnIndex, loading, layout = 'default', }) {
32
33
  const [numberColumns, setNumberColumns] = useState(0);
33
34
  const contextValue = useMemo(() => ({
34
35
  size,
35
36
  enableRowSelection,
37
+ enableRowClickSelection,
36
38
  fixedHeader,
37
39
  showVerticalBorder,
38
40
  leftFixedColumnIndex,
@@ -44,6 +46,7 @@ export function DataTableProvider({ children, size = 'medium', enableRowSelectio
44
46
  }), [
45
47
  size,
46
48
  enableRowSelection,
49
+ enableRowClickSelection,
47
50
  fixedHeader,
48
51
  showVerticalBorder,
49
52
  leftFixedColumnIndex,
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Children, cloneElement, forwardRef, isValidElement } from 'react';
2
+ import { Children, cloneElement, forwardRef, isValidElement, useRef } from 'react';
3
3
  import { dataTableRowSlotRecipe } from '../../../styled-system/recipes';
4
4
  import { DataTableCell } from '../DataTableCell';
5
5
  import { Checkbox } from '../../Checkbox';
@@ -37,14 +37,18 @@ function isClickFromNestedInteractiveElement(event) {
37
37
  return interactiveElement !== null && interactiveElement !== event.currentTarget;
38
38
  }
39
39
  export const DataTableRow = forwardRef(({ children, disabled = false, highlighted, checkboxProps, className, onClickRow, selectable, ...props }, ref) => {
40
- const { enableRowSelection: contextEnableRowSelection, layout } = useDataTableContext();
40
+ const { enableRowSelection: contextEnableRowSelection, enableRowClickSelection, layout } = useDataTableContext();
41
+ const selectionCheckboxRef = useRef(null);
41
42
  const isSelectable = selectable ?? contextEnableRowSelection;
42
43
  const isRowHighlighted = isSelectable ? (checkboxProps?.checked ?? highlighted) : highlighted;
43
- const isInteractive = onClickRow !== undefined && !disabled;
44
+ // Only a row whose selection can actually be toggled becomes the trigger of the row selection.
45
+ const isRowClickSelectable = !!enableRowClickSelection && isSelectable && !disabled && !checkboxProps?.disabled;
46
+ const isInteractive = (onClickRow !== undefined || isRowClickSelectable) && !disabled;
44
47
  const classes = dataTableRowSlotRecipe({
45
48
  layout,
46
49
  highlighted: isRowHighlighted,
47
50
  interactive: isInteractive,
51
+ rowClickSelectable: isRowClickSelectable,
48
52
  disabled,
49
53
  });
50
54
  // When the interactive row itself toggles a disclosure (a child cell shows the disclosure icon
@@ -52,22 +56,35 @@ export const DataTableRow = forwardRef(({ children, disabled = false, highlighte
52
56
  const disclosureIconProps = Children.toArray(children)
53
57
  .filter((child) => isValidElement(child) && isComponentOrWrapped(child, DataTableCell))
54
58
  .find((cell) => cell.props.disclosureIconProps && !cell.props.onClickCell)?.props.disclosureIconProps;
55
- const ariaExpanded = isInteractive && disclosureIconProps ? (disclosureIconProps.isOpen ?? false) : undefined;
59
+ const ariaExpanded = onClickRow !== undefined && !disabled && disclosureIconProps ? (disclosureIconProps.isOpen ?? false) : undefined;
60
+ // Forwarding the interaction to the checkbox lets the consumer keep handling the row selection in
61
+ // `checkboxProps.onChange` only, and the change event carries the real next checked state.
62
+ const toggleSelectionByRowInteraction = () => {
63
+ selectionCheckboxRef.current?.click();
64
+ };
56
65
  const handleClickRow = (event) => {
57
66
  if (disabled || isClickFromNestedInteractiveElement(event)) {
58
67
  return;
59
68
  }
69
+ if (isRowClickSelectable) {
70
+ toggleSelectionByRowInteraction();
71
+ }
60
72
  onClickRow?.(event);
61
73
  };
62
74
  const handleKeyDownRow = (event) => {
63
75
  if (!disabled && event.target === event.currentTarget && (event.key === 'Enter' || event.key === ' ')) {
76
+ if (isRowClickSelectable) {
77
+ // Not to scroll the page when the Space key is pressed on the focused row.
78
+ event.preventDefault();
79
+ toggleSelectionByRowInteraction();
80
+ }
64
81
  onClickRow?.(event);
65
82
  }
66
83
  };
67
84
  return (_jsxs("tr", { ref: ref, className: cx(classes.root, 'mfui-DataTableRow__root',
68
85
  /* TODO: Remove in v5.0.0 */ 'mfui-DataGridRow__root', className), ...(ariaExpanded !== undefined && { 'aria-expanded': ariaExpanded }), ...props,
69
86
  // When the row is clickable, the role should be 'button' in order to allow screen readers to understand the row is clickable.
70
- 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: _jsx(Checkbox, { checked: checkboxProps?.checked, "aria-label": checkboxProps?.['aria-label'] ?? '行を選択', disabled: disabled || checkboxProps?.disabled, onChange: checkboxProps?.onChange, onClick: checkboxProps?.onClick }) })) : null, Children.map(children, (child, index) => {
87
+ 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: _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 }) })) : null, Children.map(children, (child, index) => {
71
88
  if (!isValidElement(child)) {
72
89
  return child;
73
90
  }
@@ -54,6 +54,10 @@ export type DataTableRowProps = {
54
54
  * Likewise, Enter or Space triggers this callback only while the row itself is focused,
55
55
  * not while a focusable descendant is focused.
56
56
  *
57
+ * When the `enableRowClickSelection` prop of the `DataTable` component is `true`, the selection checkbox stops
58
+ * responding to clicks on its own, so this callback is called for the clicks on the checkbox cell as well.
59
+ * Do not toggle the row selection here in that case, otherwise the selection is toggled twice.
60
+ *
57
61
  * @default undefined
58
62
  */
59
63
  onClickRow?: (event: React.MouseEvent<HTMLTableRowElement> | React.KeyboardEvent<HTMLTableRowElement>) => void;
@@ -1,5 +1,6 @@
1
1
  import { type BasePickerProps } from '../shared/BasePicker';
2
2
  import { type IconButtonProps } from '../../IconButton';
3
+ import { type FirstDayOfWeek } from '../shared/BasePicker/constants';
3
4
  export type DatePickerProps = Omit<BasePickerProps, 'renderPopoverContent' | 'baseFormat'> & {
4
5
  /**
5
6
  * Function to check if a date should be disabled.
@@ -45,6 +46,12 @@ export type DatePickerProps = Omit<BasePickerProps, 'renderPopoverContent' | 'ba
45
46
  * @default 'ja'
46
47
  */
47
48
  calendarLocale?: BasePickerProps['calendarLocale'];
49
+ /**
50
+ * The day of the week that the calendar week starts on.
51
+ *
52
+ * @default 'monday'
53
+ */
54
+ firstDayOfWeek?: FirstDayOfWeek;
48
55
  };
49
56
  /**
50
57
  * DatePicker component
@@ -52,4 +59,4 @@ export type DatePickerProps = Omit<BasePickerProps, 'renderPopoverContent' | 'ba
52
59
  * This is a wrapper around BasePicker, setting default format to 'YYYY/MM/DD' and using DatePickerPanel.
53
60
  * See BasePicker for implementation details.
54
61
  */
55
- export declare function DatePicker({ format, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, displayJapaneseCalendar, calendarLocale, ...props }: DatePickerProps): import("react/jsx-runtime").JSX.Element;
62
+ export declare function DatePicker({ format, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, displayJapaneseCalendar, calendarLocale, firstDayOfWeek, ...props }: DatePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -4,6 +4,8 @@ import { BasePicker } from '../shared/BasePicker';
4
4
  import { DatePickerPanel } from './DatePickerPanel';
5
5
  import { CalendarLocaleProvider } from '../shared/CalendarLocale/CalendarLocaleContext';
6
6
  import { DisplayJapaneseCalendarProvider } from '../shared/CalendarLocale/DisplayJapaneseCalendarContext';
7
+ import { FirstDayOfWeekProvider } from '../shared/CalendarLocale/FirstDayOfWeekContext';
8
+ import { DEFAULT_FIRST_DAY_OF_WEEK } from '../shared/BasePicker/constants';
7
9
  import { dateToEnglishEraShort, dateToJapaneseEra } from '../shared/utilities/japaneseCalendar';
8
10
  /**
9
11
  * DatePicker component
@@ -11,11 +13,11 @@ import { dateToEnglishEraShort, dateToJapaneseEra } from '../shared/utilities/ja
11
13
  * This is a wrapper around BasePicker, setting default format to 'YYYY/MM/DD' and using DatePickerPanel.
12
14
  * See BasePicker for implementation details.
13
15
  */
14
- export function DatePicker({ format = 'YYYY/MM/DD', checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, displayJapaneseCalendar = false, calendarLocale = 'ja', ...props }) {
16
+ export function DatePicker({ format = 'YYYY/MM/DD', checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, displayJapaneseCalendar = false, calendarLocale = 'ja', firstDayOfWeek = DEFAULT_FIRST_DAY_OF_WEEK, ...props }) {
15
17
  const customFormatValue = useMemo(() => {
16
18
  if (!displayJapaneseCalendar)
17
19
  return;
18
20
  return calendarLocale === 'en' ? dateToEnglishEraShort : dateToJapaneseEra;
19
21
  }, [displayJapaneseCalendar, calendarLocale]);
20
- return (_jsx(BasePicker, { ...props, format: format, baseFormat: "YYYY-MM-DD", calendarLocale: calendarLocale, customFormatValue: customFormatValue, renderPopoverContent: ({ value, onChange }) => (_jsx(DisplayJapaneseCalendarProvider, { value: displayJapaneseCalendar, children: _jsx(CalendarLocaleProvider, { value: calendarLocale, children: _jsx(DatePickerPanel, { value: value, checkDisabledDate: checkDisabledDate, minDate: minDate, maxDate: maxDate, prevMonthIconButtonProps: prevMonthIconButtonProps, nextMonthIconButtonProps: nextMonthIconButtonProps, todayButtonProps: todayButtonProps, onChange: onChange }) }) })) }));
22
+ return (_jsx(BasePicker, { ...props, format: format, baseFormat: "YYYY-MM-DD", calendarLocale: calendarLocale, customFormatValue: customFormatValue, renderPopoverContent: ({ value, onChange }) => (_jsx(DisplayJapaneseCalendarProvider, { value: displayJapaneseCalendar, children: _jsx(CalendarLocaleProvider, { value: calendarLocale, children: _jsx(FirstDayOfWeekProvider, { value: firstDayOfWeek, children: _jsx(DatePickerPanel, { value: value, checkDisabledDate: checkDisabledDate, minDate: minDate, maxDate: maxDate, prevMonthIconButtonProps: prevMonthIconButtonProps, nextMonthIconButtonProps: nextMonthIconButtonProps, todayButtonProps: todayButtonProps, onChange: onChange }) }) }) })) }));
21
23
  }
@@ -5,4 +5,4 @@ import { type DateRangePickerProps } from './DateRangePicker.types';
5
5
  *
6
6
  * @param props - DateRangePicker props
7
7
  */
8
- export declare function DateRangePicker({ format, calendarLocale, displayJapaneseCalendar, ...restProps }: DateRangePickerProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function DateRangePicker({ format, calendarLocale, displayJapaneseCalendar, firstDayOfWeek, ...restProps }: DateRangePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -10,6 +10,8 @@ import { useMemo } from 'react';
10
10
  import { BaseRangePicker } from '../shared/BaseRangePicker';
11
11
  import { CalendarLocaleProvider } from '../shared/CalendarLocale/CalendarLocaleContext';
12
12
  import { DisplayJapaneseCalendarProvider } from '../shared/CalendarLocale/DisplayJapaneseCalendarContext';
13
+ import { FirstDayOfWeekProvider } from '../shared/CalendarLocale/FirstDayOfWeekContext';
14
+ import { DEFAULT_FIRST_DAY_OF_WEEK } from '../shared/BasePicker/constants';
13
15
  import { DateRangePickerPopover } from './DateRangePickerPopover/DateRangePickerPopover';
14
16
  import { dateToEnglishEraShort, dateToJapaneseEra } from '../shared/utilities/japaneseCalendar';
15
17
  /**
@@ -18,11 +20,11 @@ import { dateToEnglishEraShort, dateToJapaneseEra } from '../shared/utilities/ja
18
20
  *
19
21
  * @param props - DateRangePicker props
20
22
  */
21
- export function DateRangePicker({ format = 'YYYY/MM/DD', calendarLocale = 'ja', displayJapaneseCalendar = false, ...restProps }) {
23
+ export function DateRangePicker({ format = 'YYYY/MM/DD', calendarLocale = 'ja', displayJapaneseCalendar = false, firstDayOfWeek = DEFAULT_FIRST_DAY_OF_WEEK, ...restProps }) {
22
24
  const customFormatValue = useMemo(() => {
23
25
  if (!displayJapaneseCalendar)
24
26
  return;
25
27
  return calendarLocale === 'en' ? dateToEnglishEraShort : dateToJapaneseEra;
26
28
  }, [displayJapaneseCalendar, calendarLocale]);
27
- return (_jsx(BaseRangePicker, { ...restProps, format: format, calendarLocale: calendarLocale, customFormatValue: customFormatValue, renderPopoverContent: () => (_jsx(DisplayJapaneseCalendarProvider, { value: displayJapaneseCalendar, children: _jsx(CalendarLocaleProvider, { value: calendarLocale, children: _jsx(DateRangePickerPopover, {}) }) })) }));
29
+ return (_jsx(BaseRangePicker, { ...restProps, format: format, calendarLocale: calendarLocale, customFormatValue: customFormatValue, renderPopoverContent: () => (_jsx(DisplayJapaneseCalendarProvider, { value: displayJapaneseCalendar, children: _jsx(CalendarLocaleProvider, { value: calendarLocale, children: _jsx(FirstDayOfWeekProvider, { value: firstDayOfWeek, children: _jsx(DateRangePickerPopover, {}) }) }) })) }));
28
30
  }
@@ -1,5 +1,6 @@
1
1
  import { type BaseRangePickerProps } from '../shared/BaseRangePicker';
2
2
  import { type BasePickerProps } from '../shared/BasePicker';
3
+ import { type FirstDayOfWeek } from '../shared/BasePicker/constants';
3
4
  /**
4
5
  * The props for the DateRangePicker component
5
6
  */
@@ -10,6 +11,12 @@ export type DateRangePickerProps = BaseRangePickerProps & {
10
11
  * @default 'ja'
11
12
  */
12
13
  calendarLocale?: BasePickerProps['calendarLocale'];
14
+ /**
15
+ * The day of the week that the calendar week starts on.
16
+ *
17
+ * @default 'monday'
18
+ */
19
+ firstDayOfWeek?: FirstDayOfWeek;
13
20
  /**
14
21
  * Whether to display the date in Japanese calendar format (e.g., "令和7年1月15日")
15
22
  * When enabled, the text inputs will show dates in Japanese calendar format
@@ -3,4 +3,4 @@ import { type InternalCalendarPopoverProps } from './CalendarPopover.types';
3
3
  * Internal component that accesses BasePickerContext for viewing-month reset and focus trap.
4
4
  * Must be rendered inside a BasePickerProvider.
5
5
  */
6
- export declare function InternalCalendarPopover({ currentValue, defaultValue, isCalendarOpen, toggleCalendar, handleValueChange, handleClear, disabled, className, classes, formattedValue, hasValue, enableClearButton, label, clearButtonProps, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, triggerRef, targetDOMNode, dialogId, }: InternalCalendarPopoverProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function InternalCalendarPopover({ currentValue, defaultValue, isCalendarOpen, toggleCalendar, handleValueChange, handleClear, disabled, className, classes, formattedValue, hasValue, enableClearButton, label, clearButtonProps, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, firstDayOfWeek, triggerRef, targetDOMNode, dialogId, }: InternalCalendarPopoverProps): import("react/jsx-runtime").JSX.Element;
@@ -10,6 +10,7 @@ import { cx } from '../../../../styled-system/css';
10
10
  import { dayjs } from '../../../utilities/date/dayjs';
11
11
  import { DatePickerPanel } from '../../DatePicker/DatePickerPanel';
12
12
  import { useBasePickerContext } from '../../shared/BasePicker/BasePickerProvider';
13
+ import { FirstDayOfWeekProvider } from '../../shared/CalendarLocale/FirstDayOfWeekContext';
13
14
  import { useFocusTrap } from '../../../utilities/dom/useFocusTrap';
14
15
  import { getFocusableNodes } from '../../../utilities/dom/getFocusableNodes';
15
16
  const BASE_FORMAT = 'YYYY-MM-DD';
@@ -17,7 +18,7 @@ const BASE_FORMAT = 'YYYY-MM-DD';
17
18
  * Internal component that accesses BasePickerContext for viewing-month reset and focus trap.
18
19
  * Must be rendered inside a BasePickerProvider.
19
20
  */
20
- export function InternalCalendarPopover({ currentValue, defaultValue, isCalendarOpen, toggleCalendar, handleValueChange, handleClear, disabled, className, classes, formattedValue, hasValue, enableClearButton, label, clearButtonProps, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, triggerRef, targetDOMNode, dialogId, }) {
21
+ export function InternalCalendarPopover({ currentValue, defaultValue, isCalendarOpen, toggleCalendar, handleValueChange, handleClear, disabled, className, classes, formattedValue, hasValue, enableClearButton, label, clearButtonProps, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, firstDayOfWeek, triggerRef, targetDOMNode, dialogId, }) {
21
22
  const { setViewingValue, setPendingFocusDate } = useBasePickerContext();
22
23
  const { handleOnKeyDown } = useFocusTrap({
23
24
  onPressingTabOnNotFocusableElement: (event) => {
@@ -39,7 +40,7 @@ export function InternalCalendarPopover({ currentValue, defaultValue, isCalendar
39
40
  setViewingValue(dayjs(dateToFocus).startOf('month').startOf('day').toDate());
40
41
  setPendingFocusDate(formattedDate);
41
42
  }, [currentValue, defaultValue, setViewingValue, setPendingFocusDate]);
42
- return (_jsx(Popover, { open: isCalendarOpen, targetDOMNode: targetDOMNode, renderTrigger: ({ setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsxs("div", { ref: setTriggerRef, "data-selected": hasValue, className: cx(classes.wrapper, 'mfui-FilterDatePicker__wrapper'), children: [_jsx(FocusIndicator, { children: _jsxs("button", { ref: triggerRef, type: "button", disabled: disabled, className: cx(classes.trigger, 'mfui-FilterDatePicker__trigger', className), "data-selected": hasValue, "data-mfui-has-clear-button": enableClearButton ? hasValue : null, "aria-controls": dialogId, "aria-expanded": isCalendarOpen, "aria-haspopup": "dialog", onClick: togglePopover, onKeyDown: handleTriggerKeyDown, onBlur: handleTriggerBlur, children: [_jsx("span", { className: cx(classes.content, 'mfui-FilterDatePicker__content'), "data-mfui-content": "filter-date-picker-display-value", children: hasValue ? (_jsxs(Typography, { variant: "strongBody", children: [_jsx("span", { "data-mfui-content": "filter-date-picker-label", children: `${label}:` }), _jsx("span", { "data-mfui-content": "filter-date-picker-value", children: formattedValue })] })) : (_jsx(Typography, { variant: "controlLabel", children: _jsx("span", { "data-mfui-content": "filter-date-picker-label", children: label }) })) }), _jsx("span", { className: cx(classes.calendarIcon, 'mfui-FilterDatePicker__calendarIcon'), children: _jsx(CalendarIcon, { "aria-hidden": true }) })] }) }), enableClearButton && hasValue ? (_jsx("div", { className: cx(classes.clearButtonWrapper, 'mfui-FilterDatePicker__clearButtonWrapper'), children: _jsx(ClearButton, { "aria-label": clearButtonProps?.['aria-label'] ?? '値をクリアする', "data-mfui-content": "filter-date-picker-clear-button", disabled: disabled, onClick: handleClear }) })) : null] })), renderContent: () => (_jsx("div", { id: dialogId, role: "dialog", "aria-label": label, className: "mfui-FilterDatePicker__popoverWrapper", onKeyDown: handleOnKeyDown, children: _jsx(DatePickerPanel, { value: currentValue, checkDisabledDate: checkDisabledDate, minDate: minDate, maxDate: maxDate, prevMonthIconButtonProps: prevMonthIconButtonProps, nextMonthIconButtonProps: nextMonthIconButtonProps, todayButtonProps: todayButtonProps, onChange: (date) => {
43
- handleValueChange(date);
44
- } }) })), minWidth: "min-content", onOpenStateChanged: toggleCalendar, onOpen: handlePopoverOpen }));
43
+ return (_jsx(Popover, { open: isCalendarOpen, targetDOMNode: targetDOMNode, renderTrigger: ({ setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsxs("div", { ref: setTriggerRef, "data-selected": hasValue, className: cx(classes.wrapper, 'mfui-FilterDatePicker__wrapper'), children: [_jsx(FocusIndicator, { children: _jsxs("button", { ref: triggerRef, type: "button", disabled: disabled, className: cx(classes.trigger, 'mfui-FilterDatePicker__trigger', className), "data-selected": hasValue, "data-mfui-has-clear-button": enableClearButton ? hasValue : null, "aria-controls": dialogId, "aria-expanded": isCalendarOpen, "aria-haspopup": "dialog", onClick: togglePopover, onKeyDown: handleTriggerKeyDown, onBlur: handleTriggerBlur, children: [_jsx("span", { className: cx(classes.content, 'mfui-FilterDatePicker__content'), "data-mfui-content": "filter-date-picker-display-value", children: hasValue ? (_jsxs(Typography, { variant: "strongBody", children: [_jsx("span", { "data-mfui-content": "filter-date-picker-label", children: `${label}:` }), _jsx("span", { "data-mfui-content": "filter-date-picker-value", children: formattedValue })] })) : (_jsx(Typography, { variant: "controlLabel", children: _jsx("span", { "data-mfui-content": "filter-date-picker-label", children: label }) })) }), _jsx("span", { className: cx(classes.calendarIcon, 'mfui-FilterDatePicker__calendarIcon'), children: _jsx(CalendarIcon, { "aria-hidden": true }) })] }) }), enableClearButton && hasValue ? (_jsx("div", { className: cx(classes.clearButtonWrapper, 'mfui-FilterDatePicker__clearButtonWrapper'), children: _jsx(ClearButton, { "aria-label": clearButtonProps?.['aria-label'] ?? '値をクリアする', "data-mfui-content": "filter-date-picker-clear-button", disabled: disabled, onClick: handleClear }) })) : null] })), renderContent: () => (_jsx("div", { id: dialogId, role: "dialog", "aria-label": label, className: "mfui-FilterDatePicker__popoverWrapper", onKeyDown: handleOnKeyDown, children: _jsx(FirstDayOfWeekProvider, { value: firstDayOfWeek, children: _jsx(DatePickerPanel, { value: currentValue, checkDisabledDate: checkDisabledDate, minDate: minDate, maxDate: maxDate, prevMonthIconButtonProps: prevMonthIconButtonProps, nextMonthIconButtonProps: nextMonthIconButtonProps, todayButtonProps: todayButtonProps, onChange: (date) => {
44
+ handleValueChange(date);
45
+ } }) }) })), minWidth: "min-content", onOpenStateChanged: toggleCalendar, onOpen: handlePopoverOpen }));
45
46
  }
@@ -21,6 +21,7 @@ export type InternalCalendarPopoverProps = {
21
21
  prevMonthIconButtonProps: FilterDatePickerProps['prevMonthIconButtonProps'];
22
22
  nextMonthIconButtonProps: FilterDatePickerProps['nextMonthIconButtonProps'];
23
23
  todayButtonProps: FilterDatePickerProps['todayButtonProps'];
24
+ firstDayOfWeek: NonNullable<FilterDatePickerProps['firstDayOfWeek']>;
24
25
  triggerRef: React.RefObject<HTMLButtonElement | null>;
25
26
  targetDOMNode: FilterDatePickerProps['targetDOMNode'];
26
27
  dialogId: string;
@@ -11,4 +11,4 @@ import { type FilterDatePickerProps } from './FilterDatePicker.types';
11
11
  * neither of which are appropriate here. FilterDatePicker uses CalendarIcon and
12
12
  * has no form-field semantics.
13
13
  */
14
- export declare function FilterDatePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format, enableClearButton, clearButtonProps, disabled, className, targetDOMNode, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, }: FilterDatePickerProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function FilterDatePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format, enableClearButton, clearButtonProps, disabled, className, targetDOMNode, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, firstDayOfWeek, }: FilterDatePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -6,6 +6,7 @@ import { useDisclosure } from '../../utilities/state/useDisclosure';
6
6
  import { dayjs } from '../../utilities/date/dayjs';
7
7
  import { filterDatePickerSlotRecipe } from '../../../styled-system/recipes';
8
8
  import { InternalCalendarPopover } from './CalendarPopover/CalendarPopover';
9
+ import { DEFAULT_FIRST_DAY_OF_WEEK } from '../shared/BasePicker/constants';
9
10
  const DEFAULT_FORMAT = 'YYYY/MM/DD';
10
11
  /**
11
12
  * FilterDatePicker component.
@@ -19,7 +20,7 @@ const DEFAULT_FORMAT = 'YYYY/MM/DD';
19
20
  * neither of which are appropriate here. FilterDatePicker uses CalendarIcon and
20
21
  * has no form-field semantics.
21
22
  */
22
- export function FilterDatePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format = DEFAULT_FORMAT, enableClearButton = false, clearButtonProps, disabled = false, className, targetDOMNode, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, }) {
23
+ export function FilterDatePicker({ label, value, defaultValue, onChange, open, onOpenStateChanged, format = DEFAULT_FORMAT, enableClearButton = false, clearButtonProps, disabled = false, className, targetDOMNode, checkDisabledDate, minDate, maxDate, prevMonthIconButtonProps, nextMonthIconButtonProps, todayButtonProps, firstDayOfWeek = DEFAULT_FIRST_DAY_OF_WEEK, }) {
23
24
  const classes = filterDatePickerSlotRecipe();
24
25
  const triggerRef = useRef(null);
25
26
  const dialogId = useId();
@@ -71,5 +72,5 @@ export function FilterDatePicker({ label, value, defaultValue, onChange, open, o
71
72
  }, [value, onChange, triggerRef]);
72
73
  const formattedValue = currentValue ? dayjs(currentValue).format(format) : undefined;
73
74
  const hasValue = !!formattedValue;
74
- return (_jsx(BasePickerProvider, { value: currentValue, children: _jsx(InternalCalendarPopover, { currentValue: currentValue, defaultValue: defaultValue, isCalendarOpen: isCalendarOpen, toggleCalendar: toggleCalendar, handleValueChange: handleValueChange, handleClear: handleClear, disabled: disabled, className: className, classes: classes, formattedValue: formattedValue, hasValue: hasValue, enableClearButton: enableClearButton, label: label, clearButtonProps: clearButtonProps, checkDisabledDate: checkDisabledDate, minDate: minDate, maxDate: maxDate, prevMonthIconButtonProps: prevMonthIconButtonProps, nextMonthIconButtonProps: nextMonthIconButtonProps, todayButtonProps: todayButtonProps, triggerRef: triggerRef, targetDOMNode: targetDOMNode, dialogId: dialogId }) }));
75
+ return (_jsx(BasePickerProvider, { value: currentValue, children: _jsx(InternalCalendarPopover, { currentValue: currentValue, defaultValue: defaultValue, isCalendarOpen: isCalendarOpen, toggleCalendar: toggleCalendar, handleValueChange: handleValueChange, handleClear: handleClear, disabled: disabled, className: className, classes: classes, formattedValue: formattedValue, hasValue: hasValue, enableClearButton: enableClearButton, label: label, clearButtonProps: clearButtonProps, checkDisabledDate: checkDisabledDate, minDate: minDate, maxDate: maxDate, prevMonthIconButtonProps: prevMonthIconButtonProps, nextMonthIconButtonProps: nextMonthIconButtonProps, todayButtonProps: todayButtonProps, firstDayOfWeek: firstDayOfWeek, triggerRef: triggerRef, targetDOMNode: targetDOMNode, dialogId: dialogId }) }));
75
76
  }
@@ -1,5 +1,6 @@
1
1
  import { type IconButtonProps } from '../../IconButton';
2
2
  import { type PopoverProps } from '../../Popover';
3
+ import { type FirstDayOfWeek } from '../shared/BasePicker/constants';
3
4
  export type FilterDatePickerProps = {
4
5
  /**
5
6
  * The label to display for the filter.
@@ -94,4 +95,10 @@ export type FilterDatePickerProps = {
94
95
  todayButtonProps?: {
95
96
  label?: string;
96
97
  };
98
+ /**
99
+ * The day of the week that the calendar week starts on.
100
+ *
101
+ * @default 'monday'
102
+ */
103
+ firstDayOfWeek?: FirstDayOfWeek;
97
104
  };
@@ -3,4 +3,4 @@ import { type InternalDateRangePickerContentProps } from './DateRangePickerConte
3
3
  * Internal component that accesses BaseRangePickerContext for display and clear handling.
4
4
  * Must be rendered inside a BaseRangePickerProvider.
5
5
  */
6
- export declare function InternalDateRangePickerContent({ classes, triggerRef, dialogId, label, format, disabled, className, enableClearButton, clearButtonProps, targetDOMNode, isCalendarOpen, toggleCalendar, calendarLocale, }: InternalDateRangePickerContentProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function InternalDateRangePickerContent({ classes, triggerRef, dialogId, label, format, disabled, className, enableClearButton, clearButtonProps, targetDOMNode, isCalendarOpen, toggleCalendar, calendarLocale, firstDayOfWeek, }: InternalDateRangePickerContentProps): import("react/jsx-runtime").JSX.Element;
@@ -10,13 +10,14 @@ import { cx } from '../../../../styled-system/css';
10
10
  import { dayjs } from '../../../utilities/date/dayjs';
11
11
  import { DateRangePickerPopover } from '../../DateRangePicker/DateRangePickerPopover';
12
12
  import { CalendarLocaleProvider } from '../../shared/CalendarLocale/CalendarLocaleContext';
13
+ import { FirstDayOfWeekProvider } from '../../shared/CalendarLocale/FirstDayOfWeekContext';
13
14
  import { getBaseRangePickerTriggerLabel } from '../../shared/BaseRangePicker/BaseRangePickerTrigger/constants';
14
15
  import { useBaseRangePickerContext } from '../../shared/BaseRangePicker/BaseRangePickerProvider';
15
16
  /**
16
17
  * Internal component that accesses BaseRangePickerContext for display and clear handling.
17
18
  * Must be rendered inside a BaseRangePickerProvider.
18
19
  */
19
- export function InternalDateRangePickerContent({ classes, triggerRef, dialogId, label, format, disabled, className, enableClearButton, clearButtonProps, targetDOMNode, isCalendarOpen, toggleCalendar, calendarLocale, }) {
20
+ export function InternalDateRangePickerContent({ classes, triggerRef, dialogId, label, format, disabled, className, enableClearButton, clearButtonProps, targetDOMNode, isCalendarOpen, toggleCalendar, calendarLocale, firstDayOfWeek, }) {
20
21
  const { startDate, endDate, handleClear: contextHandleClear, setPendingFocusDate } = useBaseRangePickerContext();
21
22
  const formattedStartDate = startDate ? dayjs(startDate).format(format) : undefined;
22
23
  const formattedEndDate = endDate ? dayjs(endDate).format(format) : undefined;
@@ -31,5 +32,5 @@ export function InternalDateRangePickerContent({ classes, triggerRef, dialogId,
31
32
  setPendingFocusDate(dayjs(dateToFocus).format('YYYY-MM-DD'));
32
33
  }, [startDate, endDate, setPendingFocusDate]);
33
34
  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": enableClearButton ? hasValue : null, "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 }) })] }) }), enableClearButton && hasValue ? (_jsx("div", { className: cx(classes.clearButtonWrapper, 'mfui-FilterDateRangePicker__clearButtonWrapper'), children: _jsx(ClearButton, { "aria-label": clearButtonProps?.['aria-label'] ??
34
- getBaseRangePickerTriggerLabel('CLEAR_BUTTON_LABEL', calendarLocale), "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 }));
35
+ getBaseRangePickerTriggerLabel('CLEAR_BUTTON_LABEL', calendarLocale), "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(FirstDayOfWeekProvider, { value: firstDayOfWeek, children: _jsx(DateRangePickerPopover, {}) }) }) })), onOpenStateChanged: toggleCalendar, onOpen: handlePopoverOpen }));
35
36
  }