@moneyforward/mfui-components 3.33.0 → 3.34.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.
@@ -33,7 +33,7 @@ export declare const FileDropZone: import("react").ForwardRefExoticComponent<{
33
33
  multiple?: import("react").ComponentPropsWithoutRef<'input'>['multiple'];
34
34
  accept?: import("react").ComponentPropsWithoutRef<'input'>['accept'];
35
35
  clearButtonProps?: Pick<import("..").IconButtonProps, 'aria-label'>;
36
- errorMessage?: string;
36
+ errorMessage?: string | string[];
37
37
  helperMessage?: string;
38
38
  illustrationUrl?: string;
39
39
  extraElement?: React.ReactNode;
@@ -70,6 +70,8 @@ fileSelectButtonLabel = 'ファイルを選択', instructionText, fileCountLabel
70
70
  const previousValueRef = useRef(value);
71
71
  const isUserInitiatedClearRef = useRef(false);
72
72
  const displayValues = isControlled ? value : internalValues;
73
+ const errorMessages = (Array.isArray(errorMessage) ? errorMessage : [errorMessage]).filter((message) => Boolean(message));
74
+ const fileBoxMaxWidthStyle = { maxWidth: fileBoxWidth };
73
75
  const isNarrowViewport = useIsNarrowViewport();
74
76
  const clearButtonWidth = isNarrowViewport ? 32 : 24;
75
77
  const truncatedSingleName = useMiddleTruncatedText(displayValues?.[0] ?? '', fileNameRef, clearButtonWidth);
@@ -206,9 +208,9 @@ fileSelectButtonLabel = 'ファイルを選択', instructionText, fileCountLabel
206
208
  }
207
209
  return '';
208
210
  }, [displayValues, truncatedSingleName, classes.span, getFileCountText]);
209
- return (_jsxs("div", { className: cx(classes.root, 'mfui-FileDropZone__root'), children: [_jsx("input", { ref: mergeRefs(ref, inputRef), id: id, type: "file", disabled: disabled, multiple: multiple, accept: accept, className: cx(classes.input, 'mfui-FileDropZone__input'), tabIndex: -1, "aria-hidden": "true", onChange: handleChange, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDrop: handleDrop, ...props }, key), _jsxs("div", { "data-mfui-content": "file-drop-zone-container", className: cx(classes.container, 'mfui-FileDropZone__container', className), style: style, onClick: handleContainerClick, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [illustrationUrl ? (_jsx("div", { "data-mfui-content": "file-drop-zone-illustration", className: cx(classes.illustration, 'mfui-FileDropZone__illustration'), children: _jsx("img", { src: illustrationUrl, alt: "illustration" }) })) : null, _jsxs("div", { "data-mfui-content": "file-drop-zone-main-container", className: cx(classes.mainContainer, 'mfui-FileDropZone__mainContainer'), style: { maxWidth: fileBoxWidth }, children: [_jsx("div", { "data-mfui-content": "file-drop-zone-instruction", className: cx(classes.instruction, 'mfui-FileDropZone__instruction'), children: _jsx("p", { className: cx(classes.phrase, 'mfui-FileDropZone__phrase'), children: normalizedInstructionText }) }), _jsxs("div", { "data-mfui-content": "file-drop-zone-button-container", className: cx(classes.buttonContainer, 'mfui-FileDropZone__buttonContainer'), children: [_jsx(Button, { ref: buttonRef, className: cx(classes.button, 'mfui-FileDropZone__button'), disabled: disabled, "aria-describedby": errorMessage || helperMessage || (displayValues && displayValues.length > 0)
211
+ return (_jsxs("div", { className: cx(classes.root, 'mfui-FileDropZone__root'), children: [_jsx("input", { ref: mergeRefs(ref, inputRef), id: id, type: "file", disabled: disabled, multiple: multiple, accept: accept, className: cx(classes.input, 'mfui-FileDropZone__input'), tabIndex: -1, "aria-hidden": "true", onChange: handleChange, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDrop: handleDrop, ...props }, key), _jsxs("div", { "data-mfui-content": "file-drop-zone-container", className: cx(classes.container, 'mfui-FileDropZone__container', className), style: style, onClick: handleContainerClick, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [illustrationUrl ? (_jsx("div", { "data-mfui-content": "file-drop-zone-illustration", className: cx(classes.illustration, 'mfui-FileDropZone__illustration'), children: _jsx("img", { src: illustrationUrl, alt: "illustration" }) })) : null, _jsxs("div", { "data-mfui-content": "file-drop-zone-main-container", className: cx(classes.mainContainer, 'mfui-FileDropZone__mainContainer'), children: [_jsx("div", { "data-mfui-content": "file-drop-zone-instruction", className: cx(classes.instruction, 'mfui-FileDropZone__instruction'), style: fileBoxMaxWidthStyle, children: _jsx("p", { className: cx(classes.phrase, 'mfui-FileDropZone__phrase'), children: normalizedInstructionText }) }), _jsxs("div", { "data-mfui-content": "file-drop-zone-button-container", className: cx(classes.buttonContainer, 'mfui-FileDropZone__buttonContainer'), style: fileBoxMaxWidthStyle, children: [_jsx(Button, { ref: buttonRef, className: cx(classes.button, 'mfui-FileDropZone__button'), disabled: disabled, "aria-describedby": errorMessages.length > 0 || helperMessage || (displayValues && displayValues.length > 0)
210
212
  ? `${id ? `${id}-` : ''}file-drop-zone-messages`
211
- : undefined, onClick: handleFileInputTrigger, children: fileSelectButtonLabel }), displayValues !== undefined && displayValues.length > 0 && (_jsxs("div", { "data-mfui-content": "file-drop-zone-file-info", className: cx(classes.fileInfo, 'mfui-FileDropZone__fileInfo'), style: { maxWidth: `${(fileInfoWidth || 147).toString()}px` }, children: [renderDisplayValues, _jsx(ClearButton, { ...clearButtonProps, "aria-label": clearButtonProps?.['aria-label'] ?? 'ファイルをクリアする', className: cx(classes.clearButton, 'mfui-FileDropZone__clearButton'), disabled: disabled, onClick: handleClear })] }))] }), _jsxs("div", { id: id ? `${id}-file-drop-zone-messages` : 'file-drop-zone-messages', "data-mfui-content": "file-drop-zone-help-message", className: cx(classes.helpMessage, 'mfui-FileDropZone__helpMessage'), children: [errorMessage ? (_jsx(HelpMessage, { messageType: "error", messageAlign: "center", children: errorMessage })) : null, helperMessage ? _jsx(HelpMessage, { messageAlign: "center", children: helperMessage }) : null, displayValues && displayValues.length > 0 ? (_jsx("div", { className: "sr-only", children: displayValues.length === 1
213
+ : undefined, onClick: handleFileInputTrigger, children: fileSelectButtonLabel }), displayValues !== undefined && displayValues.length > 0 && (_jsxs("div", { "data-mfui-content": "file-drop-zone-file-info", className: cx(classes.fileInfo, 'mfui-FileDropZone__fileInfo'), style: { maxWidth: `${(fileInfoWidth || 147).toString()}px` }, children: [renderDisplayValues, _jsx(ClearButton, { ...clearButtonProps, "aria-label": clearButtonProps?.['aria-label'] ?? 'ファイルをクリアする', className: cx(classes.clearButton, 'mfui-FileDropZone__clearButton'), disabled: disabled, onClick: handleClear })] }))] }), _jsxs("div", { id: id ? `${id}-file-drop-zone-messages` : 'file-drop-zone-messages', "data-mfui-content": "file-drop-zone-help-message", className: cx(classes.helpMessage, 'mfui-FileDropZone__helpMessage'), children: [errorMessages.length > 0 ? (_jsx("div", { role: "alert", "data-mfui-content": "file-drop-zone-error-messages", className: cx(classes.errorMessages, 'mfui-FileDropZone__errorMessages'), children: errorMessages.map((message, index) => (_jsx(HelpMessage, { role: undefined, messageType: "error", messageAlign: "center", children: message }, index))) })) : null, helperMessage ? _jsx(HelpMessage, { messageAlign: "center", children: helperMessage }) : null, displayValues && displayValues.length > 0 ? (_jsx("div", { className: "sr-only", children: displayValues.length === 1
212
214
  ? getScreenReaderText('single', displayValues[0] || '')
213
215
  : getScreenReaderText('multiple', displayValues.length) })) : null] })] }), extraElement ? (_jsx("div", { "data-mfui-content": "file-drop-zone-extra", className: cx(classes.extra, 'mfui-FileDropZone__extra'), children: extraElement })) : null] })] }));
214
216
  });
@@ -41,11 +41,12 @@ export type FileDropZoneProps = {
41
41
  */
42
42
  clearButtonProps?: Pick<IconButtonProps, 'aria-label'>;
43
43
  /**
44
- * The error message for the file drop zone.
44
+ * The error message or messages for the file drop zone.
45
+ * Empty strings are not rendered.
45
46
  *
46
47
  * @default undefined
47
48
  */
48
- errorMessage?: string;
49
+ errorMessage?: string | string[];
49
50
  /**
50
51
  * The helper message for the file drop zone.
51
52
  *
@@ -117,7 +118,8 @@ export type FileDropZoneProps = {
117
118
  */
118
119
  onValueCleared?: () => void;
119
120
  /**
120
- * The width of the filebox element.
121
+ * The maximum width of the instruction text and button row.
122
+ * Error and helper messages are intentionally not constrained by this value.
121
123
  *
122
124
  * @default 280
123
125
  */
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
- import { Error, Approval, Caution, Close, Pending } from '@moneyforward/mfui-icons-react';
3
+ import { Error, Approval, Caution, Close, Info, Pending } from '@moneyforward/mfui-icons-react';
4
4
  import { cx } from '../../styled-system/css';
5
5
  import { sectionMessageSlotRecipe } from '../../styled-system/recipes';
6
6
  import { IconButton } from '../IconButton';
@@ -28,6 +28,7 @@ export const SectionMessage = forwardRef(({ messageType = 'neutral', region = 'i
28
28
  const statusIconA11yProps = statusIconLabel === undefined ? { 'aria-hidden': true } : { 'aria-label': statusIconLabel };
29
29
  const StatusIcon = {
30
30
  neutral: null,
31
+ info: _jsx(Info, { ...statusIconA11yProps, className: cx(classes.statusIcon, 'mfui-SectionMessage__statusIcon') }),
31
32
  success: (_jsx(Approval, { ...statusIconA11yProps, className: cx(classes.statusIcon, 'mfui-SectionMessage__statusIcon') })),
32
33
  error: _jsx(Error, { ...statusIconA11yProps, className: cx(classes.statusIcon, 'mfui-SectionMessage__statusIcon') }),
33
34
  caution: (_jsx(Caution, { ...statusIconA11yProps, className: cx(classes.statusIcon, 'mfui-SectionMessage__statusIcon') })),
@@ -1,2 +1,2 @@
1
1
  import { type TabListProps } from './TabList.types';
2
- export declare function TabList({ children, scrollLeftButtonProps, scrollRightButtonProps, allTabsDropdownMenuProps, }: TabListProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function TabList({ children, scrollLeftButtonProps, scrollRightButtonProps, allTabsDropdownMenuProps, className, style, }: TabListProps): import("react/jsx-runtime").JSX.Element;
@@ -5,10 +5,10 @@ import { tabListSlotRecipe } from '../../../styled-system/recipes';
5
5
  import { TabMenu } from './TabMenu';
6
6
  import { useShouldShowMenuController } from './hooks/useShouldShowMenuController';
7
7
  import { cx } from '../../../styled-system/css';
8
- export function TabList({ children, scrollLeftButtonProps, scrollRightButtonProps, allTabsDropdownMenuProps, }) {
8
+ export function TabList({ children, scrollLeftButtonProps, scrollRightButtonProps, allTabsDropdownMenuProps, className, style, }) {
9
9
  const classNames = tabListSlotRecipe({});
10
10
  const containerRef = useRef(null);
11
11
  const tabListRef = useRef(null);
12
12
  const isOverflowed = useShouldShowMenuController(tabListRef, containerRef);
13
- return (_jsxs("div", { ref: containerRef, className: cx(classNames.root, 'mfui-TabList__root'), children: [_jsx("div", { ref: tabListRef, role: "tablist", className: cx(classNames.tabList, isOverflowed && classNames.isOverflowed, 'mfui-TabList__tabList'), children: children }), _jsx("div", { className: cx(classNames.blankSpace, 'mfui-TabList__blankSpace') }), isOverflowed ? (_jsx(TabMenu, { tabListRef: tabListRef, scrollLeftButtonProps: scrollLeftButtonProps, scrollRightButtonProps: scrollRightButtonProps, allTabsDropdownMenuProps: allTabsDropdownMenuProps })) : null] }));
13
+ return (_jsxs("div", { ref: containerRef, className: cx(classNames.root, 'mfui-TabList__root', className), style: style, children: [_jsx("div", { ref: tabListRef, role: "tablist", className: cx(classNames.tabList, isOverflowed && classNames.isOverflowed, 'mfui-TabList__tabList'), children: children }), _jsx("div", { className: cx(classNames.blankSpace, 'mfui-TabList__blankSpace') }), isOverflowed ? (_jsx(TabMenu, { tabListRef: tabListRef, scrollLeftButtonProps: scrollLeftButtonProps, scrollRightButtonProps: scrollRightButtonProps, allTabsDropdownMenuProps: allTabsDropdownMenuProps })) : null] }));
14
14
  }
@@ -1,2 +1,2 @@
1
1
  import { type TabPanelProps } from './TabPanel.types';
2
- export declare function TabPanel({ forTabId, enableAutoUnmount, children, style, ...props }: TabPanelProps): import("react/jsx-runtime").JSX.Element | null;
2
+ export declare function TabPanel({ forTabId, enableAutoUnmount, children, className, style, ...props }: TabPanelProps): import("react/jsx-runtime").JSX.Element | null;
@@ -4,7 +4,7 @@ import { useContext } from 'react';
4
4
  import { tabPanelSlotRecipe } from '../../../styled-system/recipes';
5
5
  import { TabContext } from '../TabContext';
6
6
  import { cx } from '../../../styled-system/css';
7
- export function TabPanel({ forTabId, enableAutoUnmount, children, style, ...props }) {
7
+ export function TabPanel({ forTabId, enableAutoUnmount, children, className, style, ...props }) {
8
8
  const { selectedTabId, enableAutoUnmount: contextEnableAutoUnmount } = useContext(TabContext);
9
9
  // Use prop value if provided, otherwise fall back to context value
10
10
  const shouldAutoUnmount = enableAutoUnmount ?? contextEnableAutoUnmount;
@@ -12,7 +12,7 @@ export function TabPanel({ forTabId, enableAutoUnmount, children, style, ...prop
12
12
  if (shouldAutoUnmount && !isSelected)
13
13
  return null;
14
14
  const classNames = tabPanelSlotRecipe();
15
- return (_jsx("div", { role: "tabpanel", id: `tabpanel-${forTabId}`, className: cx(classNames.root, 'mfui-TabPanel__root'), "aria-labelledby": forTabId, style: {
15
+ return (_jsx("div", { role: "tabpanel", id: `tabpanel-${forTabId}`, className: cx(classNames.root, 'mfui-TabPanel__root', className), "aria-labelledby": forTabId, style: {
16
16
  ...style,
17
17
  display: !shouldAutoUnmount && !isSelected ? 'none' : undefined,
18
18
  }, ...props, children: children }));
@@ -2,7 +2,7 @@ import { type TabsProps } from './Tabs.types';
2
2
  import { TabItem } from './TabItem';
3
3
  import { TabList } from './TabList';
4
4
  import { TabPanel } from './TabPanel';
5
- declare function Base({ selectedTabId, onSelectedTabChange, targetDOMNode, enableAutoUnmount, children }: TabsProps): import("react/jsx-runtime").JSX.Element;
5
+ declare function Base({ selectedTabId, onSelectedTabChange, targetDOMNode, enableAutoUnmount, children, className, style, }: TabsProps): import("react/jsx-runtime").JSX.Element;
6
6
  /**
7
7
  * The Tabs component manages the tabs, tab lists, and tab panels within a tab section.
8
8
  * It provides the necessary context for handling tab selection and rendering the appropriate content.
@@ -9,7 +9,7 @@ import { TabPanel } from './TabPanel';
9
9
  import { TabContext } from './TabContext';
10
10
  import { getTargetDomNode } from '../utilities/dom/getTargetDomNode';
11
11
  import { cx } from '../../styled-system/css';
12
- function Base({ selectedTabId, onSelectedTabChange, targetDOMNode, enableAutoUnmount = true, children }) {
12
+ function Base({ selectedTabId, onSelectedTabChange, targetDOMNode, enableAutoUnmount = true, children, className, style, }) {
13
13
  const classNames = tabsSlotRecipe();
14
14
  const [shouldShowMenu, setShouldShowMenu] = useState(false);
15
15
  const wrapperRef = useRef(null);
@@ -59,7 +59,7 @@ function Base({ selectedTabId, onSelectedTabChange, targetDOMNode, enableAutoUnm
59
59
  unregisterTab,
60
60
  enableAutoUnmount,
61
61
  ]);
62
- return (_jsx(TabContext.Provider, { value: contextValue, children: _jsx("div", { ref: wrapperRef, className: cx(classNames.root, 'mfui-Tabs__root'), children: children }) }));
62
+ return (_jsx(TabContext.Provider, { value: contextValue, children: _jsx("div", { ref: wrapperRef, className: cx(classNames.root, 'mfui-Tabs__root', className), style: style, children: children }) }));
63
63
  }
64
64
  /**
65
65
  * The Tabs component manages the tabs, tab lists, and tab panels within a tab section.
@@ -17,7 +17,7 @@ type FileDropZoneSlotRecipeVariantMap = {
17
17
  [key in keyof FileDropZoneSlotRecipeVariant]: Array<FileDropZoneSlotRecipeVariant[key]>
18
18
  }
19
19
 
20
- type FileDropZoneSlotRecipeSlot = "root" | "input" | "container" | "illustration" | "mainContainer" | "instruction" | "buttonContainer" | "button" | "fileInfo" | "span" | "clearButton" | "helpMessage" | "extra" | "phrase"
20
+ type FileDropZoneSlotRecipeSlot = "root" | "input" | "container" | "illustration" | "mainContainer" | "instruction" | "buttonContainer" | "button" | "fileInfo" | "span" | "clearButton" | "helpMessage" | "errorMessages" | "extra" | "phrase"
21
21
 
22
22
  export type FileDropZoneSlotRecipeVariantProps = {
23
23
  [key in keyof FileDropZoneSlotRecipeVariant]?: FileDropZoneSlotRecipeVariant[key] | undefined
@@ -64,6 +64,10 @@ const fileDropZoneSlotRecipeSlotNames = [
64
64
  "helpMessage",
65
65
  "file-drop-zone__helpMessage"
66
66
  ],
67
+ [
68
+ "errorMessages",
69
+ "file-drop-zone__errorMessages"
70
+ ],
67
71
  [
68
72
  "extra",
69
73
  "file-drop-zone__extra"
@@ -3,7 +3,7 @@ import type { ConditionalValue } from '../types/index';
3
3
  import type { DistributiveOmit, Pretty } from '../types/system-types';
4
4
 
5
5
  interface SectionMessageSlotRecipeVariant {
6
- messageType: "neutral" | "success" | "error" | "caution" | "busy" | "progress"
6
+ messageType: "neutral" | "info" | "success" | "error" | "caution" | "busy" | "progress"
7
7
  region: "inline" | "page"
8
8
  disableResponsive: boolean
9
9
  }
@@ -59,6 +59,7 @@ export const sectionMessageSlotRecipe = /* @__PURE__ */ Object.assign(sectionMes
59
59
  variantMap: {
60
60
  "messageType": [
61
61
  "neutral",
62
+ "info",
62
63
  "success",
63
64
  "error",
64
65
  "caution",
package/dist/styles.css CHANGED
@@ -4685,8 +4685,6 @@
4685
4685
  background-color: var(--mfui-colors-mfui\.color\.neutral\.thin-background\.none);
4686
4686
  font-family: var(--mfui-fonts-mfui\.typography\.font-family\.label);
4687
4687
  font-size: var(--mfui-font-sizes-mfui\.typography\.font-size\.control-label);
4688
- width: 100%;
4689
- min-width: max-content;
4690
4688
  height: 100%;
4691
4689
  }
4692
4690
 
@@ -4695,6 +4693,7 @@
4695
4693
  flex-direction: column;
4696
4694
  align-items: center;
4697
4695
  justify-content: center;
4696
+ width: 100%;
4698
4697
  }
4699
4698
 
4700
4699
  .mfui-fqNMeO {
@@ -4715,6 +4714,7 @@
4715
4714
  align-items: center;
4716
4715
  justify-content: center;
4717
4716
  width: 100%;
4717
+ min-width: max-content;
4718
4718
  }
4719
4719
 
4720
4720
  .mfui-juYDJw {
@@ -4767,6 +4767,12 @@
4767
4767
  height: 1px;
4768
4768
  }
4769
4769
 
4770
+ .mfui-VkDTa {
4771
+ display: flex;
4772
+ flex-direction: column;
4773
+ align-items: center;
4774
+ }
4775
+
4770
4776
  .mfui-kakNKU {
4771
4777
  padding-inline: var(--mfui-spacing-mfui\.size\.padding\.main-content\.horizontal\.comfort);
4772
4778
  padding-block: var(--mfui-spacing-mfui\.size\.padding\.content\.vertical\.comfort);
@@ -6858,6 +6864,10 @@ li:last-child > .mfui-cXGJls {
6858
6864
  resize: horizontal;
6859
6865
  }
6860
6866
 
6867
+ .mfui-dpIccs {
6868
+ color: var(--mfui-colors-mfui\.color\.neutral\.content\.none);
6869
+ }
6870
+
6861
6871
  .mfui-cFyzwg {
6862
6872
  background-color: var(--mfui-colors-mfui\.color\.signal-green\.sub-background\.none);
6863
6873
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneyforward/mfui-components",
3
- "version": "3.33.0",
3
+ "version": "3.34.0",
4
4
  "description": "React UI Component Library for all Money Forward products",
5
5
  "repository": {
6
6
  "type": "git",