@moneyforward/mfui-components 3.21.0 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/FormFooter/FormFooter.types.d.ts +2 -3
- package/dist/src/SidePane/SidePane.d.ts +1 -1
- package/dist/src/SidePane/SidePane.types.d.ts +1 -3
- package/dist/src/Tooltip/Tooltip.js +12 -3
- package/dist/src/Tooltip/hooks/useTooltipDisplayController.d.ts +1 -0
- package/dist/src/Tooltip/hooks/useTooltipDisplayController.js +1 -0
- package/dist/styled-system/recipes/form-footer-slot-recipe.d.ts +1 -1
- package/dist/styled-system/recipes/form-footer-slot-recipe.js +0 -1
- package/dist/styled-system/tokens/index.js +892 -44
- package/dist/styled-system/tokens/tokens.d.ts +4 -4
- package/dist/styles.css +27 -34
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
export type FormFooterPosition = '
|
|
2
|
+
export type FormFooterPosition = 'stacking' | 'sticky';
|
|
3
3
|
export type FormFooterSectionPosition = 'fill' | 'center';
|
|
4
4
|
export type FormFooterProps = {
|
|
5
5
|
/**
|
|
@@ -10,8 +10,7 @@ export type FormFooterProps = {
|
|
|
10
10
|
* It's for controlling the position of the component.
|
|
11
11
|
*
|
|
12
12
|
* - `"stacking"`: Displayed inline at the bottom of its container. Use for creation forms where preventing mid-session abandonment is important.
|
|
13
|
-
* - `"
|
|
14
|
-
* - `"sticky"`: Sits inline below the last form field, and pins to the bottom of the nearest scrolling ancestor (e.g. inside `SidePane`) when the form overflows. Use inside scrollable containers such as `SidePane`.
|
|
13
|
+
* - `"sticky"`: Sits inline below the last form field, and pins to the bottom of the nearest scrolling ancestor when the form overflows. Use inside scrollable containers such as `SidePane`.
|
|
15
14
|
*
|
|
16
15
|
* @default "stacking"
|
|
17
16
|
*/
|
|
@@ -18,7 +18,7 @@ export declare const SidePane: import("react").ForwardRefExoticComponent<{
|
|
|
18
18
|
disableBackdropClose?: boolean;
|
|
19
19
|
enableAutoUnmount?: boolean;
|
|
20
20
|
formFooterProps?: Pick<import("..").FormFooterProps, "optionsSlot" | "actionsSlot"> & {
|
|
21
|
-
position?:
|
|
21
|
+
position?: import("..").FormFooterProps["position"];
|
|
22
22
|
};
|
|
23
23
|
insideProps?: {
|
|
24
24
|
className?: string;
|
|
@@ -116,12 +116,10 @@ export type SidePaneProps = {
|
|
|
116
116
|
* - `position: 'sticky'` (default): the footer is always pinned to the pane bottom, outside the scrollable content area.
|
|
117
117
|
* - `position: 'stacking'`: the footer flows after the content inside the scroll area.
|
|
118
118
|
*
|
|
119
|
-
* `position: 'fixed'` is not supported here because it anchors to the viewport rather than the pane.
|
|
120
|
-
*
|
|
121
119
|
* @default undefined
|
|
122
120
|
*/
|
|
123
121
|
formFooterProps?: Pick<FormFooterProps, 'optionsSlot' | 'actionsSlot'> & {
|
|
124
|
-
position?:
|
|
122
|
+
position?: FormFooterProps['position'];
|
|
125
123
|
};
|
|
126
124
|
/**
|
|
127
125
|
* Additional props to apply to the inside container element of the SidePane.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef, useId, useRef, isValidElement, cloneElement, useEffect } from 'react';
|
|
3
|
+
import { forwardRef, useId, useRef, isValidElement, cloneElement, useEffect, useMemo } from 'react';
|
|
4
4
|
import { getOverflowAncestors } from '@floating-ui/react-dom';
|
|
5
5
|
import { cx } from '../../styled-system/css';
|
|
6
6
|
import { tooltipSlotRecipe } from '../../styled-system/recipes';
|
|
7
7
|
import { Typography } from '../Typography';
|
|
8
8
|
import { mergeRefs } from '../utilities/dom/mergeRefs';
|
|
9
|
+
import { useOnClickOutside } from '../utilities/dom/useOnClickOutside';
|
|
9
10
|
import { useTooltipDisplayController } from './hooks/useTooltipDisplayController';
|
|
10
11
|
import { ArrowIcon } from './icons/ArrowIcon';
|
|
11
12
|
import { usePopoverController } from './hooks/usePopoverController';
|
|
@@ -46,11 +47,12 @@ export const DEFAULT_MAX_WIDTH = '268px';
|
|
|
46
47
|
export const Tooltip = forwardRef(({ children, open, onOpenStateChanged, content, targetDOMNode, placement, trigger = ['hover', 'focus'], disabled = false, hideFromScreenReader = false, maxWidth = DEFAULT_MAX_WIDTH, className, contentProps, ...wrapperProps }, ref) => {
|
|
47
48
|
const rootRef = useRef(null);
|
|
48
49
|
const arrowRef = useRef(null);
|
|
50
|
+
const tooltipRef = useRef(null);
|
|
49
51
|
const tooltipId = useId();
|
|
50
52
|
// Use automatic target resolution matching Portal.tsx pattern
|
|
51
53
|
// Resolution order: explicit prop → parent context → document.body fallback
|
|
52
54
|
const targetElement = useAutomaticTargetDomNode(targetDOMNode, rootRef.current);
|
|
53
|
-
const { open: calculatedOpen, rootAttributes, tooltipAttributes, closeImmediate, } = useTooltipDisplayController({
|
|
55
|
+
const { open: calculatedOpen, rootAttributes, tooltipAttributes, closeImmediate, closeWithManager, } = useTooltipDisplayController({
|
|
54
56
|
trigger,
|
|
55
57
|
wrapperProps,
|
|
56
58
|
tooltipOpen: open,
|
|
@@ -77,6 +79,13 @@ export const Tooltip = forwardRef(({ children, open, onOpenStateChanged, content
|
|
|
77
79
|
});
|
|
78
80
|
};
|
|
79
81
|
}, [calculatedOpen, closeImmediate]);
|
|
82
|
+
const hasClickTrigger = useMemo(() => (Array.isArray(trigger) ? trigger : [trigger]).includes('click'), [trigger]);
|
|
83
|
+
// Skip the trigger (rootRef) so the existing onClick toggle handles re-clicks —
|
|
84
|
+
// closing here would race with onClick and immediately reopen the tooltip.
|
|
85
|
+
useOnClickOutside(rootRef, closeWithManager, {
|
|
86
|
+
ignoreRefs: [tooltipRef],
|
|
87
|
+
disabled: !calculatedOpen || !hasClickTrigger || open !== undefined,
|
|
88
|
+
});
|
|
80
89
|
const triggerRef = mergeRefs(setTriggerReference, rootRef, ref);
|
|
81
90
|
const classes = tooltipSlotRecipe();
|
|
82
91
|
const ariaDescribedBy = !hideFromScreenReader && content != null ? tooltipId : undefined;
|
|
@@ -90,5 +99,5 @@ export const Tooltip = forwardRef(({ children, open, onOpenStateChanged, content
|
|
|
90
99
|
clip: 'rect(0, 0, 0, 0)',
|
|
91
100
|
whiteSpace: 'nowrap',
|
|
92
101
|
borderWidth: 0,
|
|
93
|
-
}, children: content }) })), calculatedOpen ? (_jsx(Portal, { targetDOMNode: targetElement, children: _jsxs("div", { ref: setTooltipReference, className: cx(classes.tooltip, 'mfui-Tooltip__tooltip', contentProps?.className), role: "tooltip", id: tooltipId, "aria-hidden": hideFromScreenReader ? true : undefined, style: { maxWidth, ...tooltipStyles }, ...tooltipAttributes, children: [typeof content === 'string' ? _jsx(Typography, { variant: "helpMessage", children: content }) : content, _jsx(ArrowIcon, { ref: arrowRef, "aria-hidden": true, placement: calculatedPlacement, className: cx(classes.arrow, 'mfui-Tooltip__arrow'), style: arrowStyles })] }) })) : null] }));
|
|
102
|
+
}, children: content }) })), calculatedOpen ? (_jsx(Portal, { targetDOMNode: targetElement, children: _jsxs("div", { ref: mergeRefs(setTooltipReference, tooltipRef), className: cx(classes.tooltip, 'mfui-Tooltip__tooltip', contentProps?.className), role: "tooltip", id: tooltipId, "aria-hidden": hideFromScreenReader ? true : undefined, style: { maxWidth, ...tooltipStyles }, ...tooltipAttributes, children: [typeof content === 'string' ? _jsx(Typography, { variant: "helpMessage", children: content }) : content, _jsx(ArrowIcon, { ref: arrowRef, "aria-hidden": true, placement: calculatedPlacement, className: cx(classes.arrow, 'mfui-Tooltip__arrow'), style: arrowStyles })] }) })) : null] }));
|
|
94
103
|
});
|
|
@@ -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 FormFooterSlotRecipeVariant {
|
|
6
|
-
position: "stacking" | "
|
|
6
|
+
position: "stacking" | "sticky"
|
|
7
7
|
sectionPosition: "center" | "fill"
|
|
8
8
|
}
|
|
9
9
|
|