@moneyforward/mfui-components 3.27.2 → 3.28.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.
@@ -11,7 +11,7 @@ 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, disabled = false, depth = 0, columnIndex, disclosureIconProps: nestingIconProps, style, ...props }, ref) => {
14
- const { size, leftFixedColumnIndex, rightFixedColumnIndex, loading, enableRowSelection } = useDataTableContext();
14
+ const { size, leftFixedColumnIndex, rightFixedColumnIndex, loading, enableRowSelection, layout } = useDataTableContext();
15
15
  const { cellRef, isFixedColumn, isEdgeFixedColumn, fixedPositionStyles } = useFixedColumns({
16
16
  enableRowSelection,
17
17
  columnIndex,
@@ -25,6 +25,7 @@ export const DataTableCell = forwardRef(({ onClickCell, children, type = 'text',
25
25
  fixedColumn: isFixedColumn,
26
26
  edgeFixedColumn: isEdgeFixedColumn,
27
27
  isCheckboxCell: enableRowSelection && columnIndex === 0,
28
+ layout,
28
29
  });
29
30
  const handleClick = (event) => {
30
31
  onClickCell?.(event);
@@ -236,7 +236,9 @@ export function Popover({ renderTrigger, renderContent, open, onOpenStateChanged
236
236
  const scrollableAncestors = getOverflowAncestors(referenceElement).filter((ancestor) => ancestor instanceof Element);
237
237
  const popoverElement = refs.floating.current;
238
238
  const preventScroll = (event) => {
239
- if (popoverElement?.contains(event.target))
239
+ // `event.target` is retargeted at shadow boundaries, so use the composed path
240
+ // to detect events coming from inside the popover across Shadow DOM.
241
+ if (popoverElement && event.composedPath().includes(popoverElement))
240
242
  return;
241
243
  event.preventDefault();
242
244
  };
@@ -38,7 +38,7 @@ const SKELETON_ITEM_COUNT = 4;
38
38
  export const SelectBox = forwardRef((props, ref) => {
39
39
  const { id, triggerProps, clearButtonProps, enableClearButton = false, size, options = [], defaultValue,
40
40
  // eslint-disable-next-line @typescript-eslint/no-deprecated
41
- placeholder, emptyMessage, disabled, invalid, targetDOMNode, name, onChange, onBlur, value, enableSearchOptions = false, notFoundMessage, searchBoxProps, loading = false, onSearchOptions, renderDisplayValue, renderOption, renderPopoverContent, enableAutoScrollToSelectedOption, popoverContentProps, popoverWrapperProps, onOpenStateChanged, showGroupOptionDivider, triggerWrapperProps, enableAutoUnmount = true, enableConstrainedPopoverWidth = false, enableVirtualization = false, virtualizationOptions, infiniteScroll, } = props;
41
+ placeholder, emptyMessage, disabled, invalid, required, targetDOMNode, name, onChange, onBlur, value, enableSearchOptions = false, notFoundMessage, searchBoxProps, loading = false, onSearchOptions, renderDisplayValue, renderOption, renderPopoverContent, enableAutoScrollToSelectedOption, popoverContentProps, popoverWrapperProps, onOpenStateChanged, showGroupOptionDivider, triggerWrapperProps, enableAutoUnmount = true, enableConstrainedPopoverWidth = false, enableVirtualization = false, virtualizationOptions, infiniteScroll, } = props;
42
42
  const classes = selectBoxSlotRecipe({ size, showGroupOptionDivider });
43
43
  const triggerRef = useRef(null);
44
44
  const listBoxId = useId();
@@ -328,7 +328,7 @@ export const SelectBox = forwardRef((props, ref) => {
328
328
  const hasSelectedValue = value !== undefined || localSelectedOption !== null;
329
329
  const showClearButton = enableClearButton && hasSelectedValue;
330
330
  // Use Popover's centralized blur handling instead of custom logic
331
- return (_jsx(Popover, { open: isOptionPanelOpen, targetDOMNode: targetDOMNode, minWidth: popoverContentProps?.minWidth, maxHeight: popoverWrapperProps?.maxHeight, allowedPlacements: popoverContentProps?.allowedPlacements, enableConstrainedContentWidth: enableConstrainedPopoverWidth, renderContent: () => (_jsx("div", { ref: optionPanelRef, id: listBoxId, className: cx(classes.optionPanel, 'mfui-SelectBox__optionPanel', popoverContentProps?.className), tabIndex: -1, onKeyDown: handleKeyDownMenu, children: renderPopoverContent ? (renderPopoverContent({ searchNode, optionsNode })) : (_jsxs(_Fragment, { children: [searchNode, optionsNode] })) })), renderTrigger: ({ setTriggerRef, togglePopover, isPopoverOpen, handleTriggerKeyDown, handleTriggerBlur }) => (_jsxs("div", { ref: setTriggerRef, ...triggerWrapperProps, className: cx(classes.triggerWrapper, 'mfui-SelectBox__triggerWrapper', triggerWrapperProps?.className), children: [_jsx(FocusIndicator, { children: _jsxs("button", { ref: triggerRef, id: id, type: "button", role: "combobox", disabled: disabled, "aria-label": triggerProps?.['aria-label'], "aria-controls": listBoxId, "aria-expanded": isPopoverOpen, "aria-haspopup": "listbox", "aria-invalid": invalid, className: cx(classes.trigger, 'mfui-SelectBox__trigger', triggerProps?.className), "data-placeholder": !!placeholder && !localSelectedOption, "data-selected": !!localSelectedOption, "data-mfui-has-clear-button": showClearButton, onClick: togglePopover, onKeyDown: (event) => {
331
+ return (_jsx(Popover, { open: isOptionPanelOpen, targetDOMNode: targetDOMNode, minWidth: popoverContentProps?.minWidth, maxHeight: popoverWrapperProps?.maxHeight, allowedPlacements: popoverContentProps?.allowedPlacements, enableConstrainedContentWidth: enableConstrainedPopoverWidth, renderContent: () => (_jsx("div", { ref: optionPanelRef, id: listBoxId, className: cx(classes.optionPanel, 'mfui-SelectBox__optionPanel', popoverContentProps?.className), tabIndex: -1, onKeyDown: handleKeyDownMenu, children: renderPopoverContent ? (renderPopoverContent({ searchNode, optionsNode })) : (_jsxs(_Fragment, { children: [searchNode, optionsNode] })) })), renderTrigger: ({ setTriggerRef, togglePopover, isPopoverOpen, handleTriggerKeyDown, handleTriggerBlur }) => (_jsxs("div", { ref: setTriggerRef, ...triggerWrapperProps, className: cx(classes.triggerWrapper, 'mfui-SelectBox__triggerWrapper', triggerWrapperProps?.className), children: [_jsx(FocusIndicator, { children: _jsxs("button", { ref: triggerRef, id: id, type: "button", role: "combobox", disabled: disabled, "aria-label": triggerProps?.['aria-label'], "aria-controls": listBoxId, "aria-expanded": isPopoverOpen, "aria-haspopup": "listbox", "aria-invalid": invalid, "aria-required": required, className: cx(classes.trigger, 'mfui-SelectBox__trigger', triggerProps?.className), "data-placeholder": !!placeholder && !localSelectedOption, "data-selected": !!localSelectedOption, "data-mfui-has-clear-button": showClearButton, onClick: togglePopover, onKeyDown: (event) => {
332
332
  handleTypeAhead(event.nativeEvent);
333
333
  handleTriggerKeyDown(event);
334
334
  }, onBlur: handleTriggerBlur, children: [_jsx("span", { "data-mfui-content": "select-box-trigger-display-value", children: renderTriggerLabel() }), _jsx(DropdownIcon, { "aria-hidden": "true", focusable: false }), _jsx("input", { ref: ref, type: "hidden", value: localSelectedOption?.value ?? '', name: name, disabled: disabled })] }) }), showClearButton ? (_jsx("div", { className: cx(classes.clearButtonWrapper, 'mfui-SelectBox__clearButtonWrapper'), children: _jsx(ClearButton, { size: size === 'small' ? 'small' : size === 'large' ? 'large' : 'default', "aria-label": clearButtonProps?.['aria-label'] ?? '値をクリアする', "data-mfui-content": "select-box-clear-button", onClick: (event) => {
@@ -227,6 +227,12 @@ export type SelectBoxProps<T extends AllowedValueTypes = string, AdditionalProps
227
227
  * Whether the trigger is invalid.
228
228
  */
229
229
  invalid?: boolean;
230
+ /**
231
+ * Whether the trigger is required.
232
+ * When true, `aria-required="true"` is forwarded to the trigger so that
233
+ * assistive technologies announce the field as required.
234
+ */
235
+ required?: boolean;
230
236
  /**
231
237
  * Whether the popover width should be constrained to match the trigger element width.
232
238
  *
@@ -8,6 +8,7 @@ isCheckboxCell: boolean
8
8
  rowHighlighted: boolean
9
9
  fixedColumn: boolean
10
10
  edgeFixedColumn: "left" | "right"
11
+ layout: "default" | "edge-to-edge"
11
12
  type: "text" | "amount"
12
13
  }
13
14
 
@@ -18,7 +19,7 @@ type DataTableCellSlotRecipeVariantMap = {
18
19
  type DataTableCellSlotRecipeSlot = "root" | "defaultCell" | "interactiveCell" | "disclosureIconWrapper" | "disclosureSpacing" | "skeletonCell"
19
20
 
20
21
  export type DataTableCellSlotRecipeVariantProps = {
21
- [key in keyof DataTableCellSlotRecipeVariant]?: ConditionalValue<DataTableCellSlotRecipeVariant[key]> | undefined
22
+ [key in keyof DataTableCellSlotRecipeVariant]?: DataTableCellSlotRecipeVariant[key] | undefined
22
23
  }
23
24
 
24
25
  export interface DataTableCellSlotRecipeRecipe {
@@ -1,7 +1,22 @@
1
1
  import { compact, getSlotCompoundVariant, memo, splitProps } from '../helpers.js';
2
2
  import { createRecipe } from './create-recipe.js';
3
3
  const dataTableCellSlotRecipeDefaultVariants = {};
4
- const dataTableCellSlotRecipeCompoundVariants = [];
4
+ const dataTableCellSlotRecipeCompoundVariants = [
5
+ {
6
+ "edgeFixedColumn": [
7
+ "left",
8
+ "right"
9
+ ],
10
+ "layout": "default",
11
+ "css": {
12
+ "root": {
13
+ "tr:last-child > &::before": {
14
+ "height": "[100%]"
15
+ }
16
+ }
17
+ }
18
+ }
19
+ ];
5
20
  const dataTableCellSlotRecipeSlotNames = [
6
21
  [
7
22
  "root",
@@ -38,6 +53,7 @@ const dataTableCellSlotRecipeVariantKeys = [
38
53
  "rowHighlighted",
39
54
  "fixedColumn",
40
55
  "edgeFixedColumn",
56
+ "layout",
41
57
  "type"
42
58
  ];
43
59
  const getVariantProps = (variants) => ({ ...dataTableCellSlotRecipeDefaultVariants, ...compact(variants) });
@@ -65,6 +81,10 @@ export const dataTableCellSlotRecipe = /* @__PURE__ */ Object.assign(dataTableCe
65
81
  "left",
66
82
  "right"
67
83
  ],
84
+ "layout": [
85
+ "default",
86
+ "edge-to-edge"
87
+ ],
68
88
  "type": [
69
89
  "text",
70
90
  "amount"
package/dist/styles.css CHANGED
@@ -636,9 +636,10 @@
636
636
  .mfui-ipiOcH {
637
637
  display: inline-flex;
638
638
  align-items: center;
639
- vertical-align: middle;
639
+ vertical-align: bottom;
640
640
  padding-right: var(--mfui-spacing-mfui\.size\.padding\.icon-inline\.horizontal\.comfort);
641
641
  padding-left: var(--mfui-spacing-mfui\.size\.padding\.icon-inline\.horizontal\.comfort);
642
+ height: 1lh;
642
643
  }
643
644
 
644
645
  .mfui-eBBgyo {
@@ -8571,6 +8572,10 @@ li:last-child > .mfui-cXGJls {
8571
8572
  cursor: not-allowed;
8572
8573
  }
8573
8574
 
8575
+ tr:last-child > .mfui-gtOHny::before {
8576
+ height: 100%;
8577
+ }
8578
+
8574
8579
  .mfui-kSeSQV:is(:focus-visible, [data-focus-visible]),.mfui-dqyxbp:has(input:focus-visible, input[data-focus-visible=true], textarea:focus-visible, textarea[data-focus-visible=true]) {
8575
8580
  outline: 2px solid var(--mfui-colors-mfui\.color\.primary\.border\.none);
8576
8581
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneyforward/mfui-components",
3
- "version": "3.27.2",
3
+ "version": "3.28.0",
4
4
  "description": "React UI Component Library for all Money Forward products",
5
5
  "repository": {
6
6
  "type": "git",
@@ -63,8 +63,8 @@
63
63
  "@floating-ui/react-dom": "^2.1.2",
64
64
  "@tanstack/react-virtual": "^3.13.18",
65
65
  "dayjs": "^1.11.13",
66
- "@moneyforward/mfui-design-tokens": "^3.2.1",
67
- "@moneyforward/mfui-icons-react": "^3.5.0"
66
+ "@moneyforward/mfui-icons-react": "^3.5.1",
67
+ "@moneyforward/mfui-design-tokens": "^3.2.1"
68
68
  },
69
69
  "scripts": {
70
70
  "prepare:panda": "panda codegen",