@moneyforward/mfui-components 3.29.1 → 3.31.1

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 (129) hide show
  1. package/dist/src/Button/Button.d.ts +4 -4
  2. package/dist/src/CheckboxCard/CheckboxCard.d.ts +2 -2
  3. package/dist/src/CheckboxCard/CheckboxCard.js +1 -1
  4. package/dist/src/DataTable/DataTable.js +2 -2
  5. package/dist/src/DataTable/DataTable.types.d.ts +9 -0
  6. package/dist/src/DataTable/DataTableCell/DataTableCell.js +3 -2
  7. package/dist/src/DataTable/DataTableHeaderCell/DataTableHeaderCell.js +2 -1
  8. package/dist/src/DataTable/DataTableProvider.d.ts +2 -2
  9. package/dist/src/DataTable/DataTableProvider.js +4 -1
  10. package/dist/src/DataTable/DataTableRow/DataTableRow.js +34 -3
  11. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerProvider/DateRangePickerProvider.d.ts +2 -2
  12. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerTrigger/constants.d.ts +4 -4
  13. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerTrigger/hooks/useDateRangeTriggerInputClick.d.ts +1 -1
  14. package/dist/src/DateTimeSelection/DateRangePicker/utilities/createDateRangePickerTestUtility.d.ts +1 -1
  15. package/dist/src/DateTimeSelection/MonthRangePicker/MonthRangePickerMonthCell/constants.d.ts +5 -5
  16. package/dist/src/DateTimeSelection/TimePicker/TimePicker.d.ts +9 -9
  17. package/dist/src/DateTimeSelection/shared/BasePicker/basePickerUtilities/useBasePickerValueController.d.ts +1 -1
  18. package/dist/src/DateTimeSelection/shared/BasePicker/constants.d.ts +1 -1
  19. package/dist/src/DateTimeSelection/shared/BasePicker/constants.js +2 -0
  20. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerPopover/BaseRangePickerCalendar/constants.d.ts +6 -6
  21. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerProvider/BaseRangePickerProvider.d.ts +2 -2
  22. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerTrigger/BaseRangePickerTrigger.js +1 -1
  23. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerTrigger/hooks/useDateRangeTriggerInputClick.d.ts +1 -1
  24. package/dist/src/DateTimeSelection/shared/BaseRangePicker/utilities/createBaseRangePickerTestUtility.d.ts +1 -1
  25. package/dist/src/DateTimeSelection/shared/YearSelector/YearSelector.js +7 -1
  26. package/dist/src/DateTimeSelection/shared/accessibility/constants.d.ts +6 -6
  27. package/dist/src/Dialog/Dialog.d.ts +4 -4
  28. package/dist/src/Disclosure/Disclosure.d.ts +21 -10
  29. package/dist/src/DropdownMenu/DropdownMenu.d.ts +3 -3
  30. package/dist/src/DropdownMenu/DropdownMenu.js +26 -2
  31. package/dist/src/DropdownMenu/DropdownMenuButtonTrigger.d.ts +2 -2
  32. package/dist/src/DropdownMenu/DropdownMenuContainer/DropdownMenuContainer.js +28 -3
  33. package/dist/src/DropdownMenu/DropdownMenuContainer/DropdownMenuContainer.types.d.ts +5 -2
  34. package/dist/src/DropdownMenu/DropdownMenuItem/DropdownMenuItem.d.ts +1 -1
  35. package/dist/src/DropdownMenu/DropdownMenuItem/DropdownMenuItem.js +29 -6
  36. package/dist/src/DropdownMenu/DropdownMenuItem/DropdownMenuItem.types.d.ts +6 -0
  37. package/dist/src/EmbeddedSidePane/EmbeddedSidePane.d.ts +1 -1
  38. package/dist/src/FileBox/FileBox.d.ts +4 -4
  39. package/dist/src/FileBox/FileBox.js +1 -1
  40. package/dist/src/FileDropZone/FileDropZone.d.ts +4 -4
  41. package/dist/src/FileDropZone/utils/fileHelpers.d.ts +3 -3
  42. package/dist/src/FilterTrigger/FilterTrigger.d.ts +2 -2
  43. package/dist/src/Heading/Heading.d.ts +2 -2
  44. package/dist/src/HelpMessage/HelpMessage.d.ts +3 -3
  45. package/dist/src/IconButton/IconButton.d.ts +6 -6
  46. package/dist/src/KeyValue/KeyValue.d.ts +2 -2
  47. package/dist/src/MainNavigation/BaseMainNavigation.d.ts +1 -1
  48. package/dist/src/MainNavigation/BaseMainNavigation.js +4 -2
  49. package/dist/src/MainNavigation/MainNavigation.js +3 -3
  50. package/dist/src/MainNavigation/MainNavigation.types.d.ts +18 -0
  51. package/dist/src/MultipleSelectBox/MultipleSelectBox.js +1 -1
  52. package/dist/src/MultipleSelectBox/hooks/useApplyControls.d.ts +1 -1
  53. package/dist/src/MultipleSelectBox/hooks/useSelectedValues.d.ts +1 -1
  54. package/dist/src/NumberBox/NumberBox.d.ts +1 -1
  55. package/dist/src/NumberBox/NumberBox.js +68 -21
  56. package/dist/src/Pagination/ItemsCount/ItemsCount.js +1 -1
  57. package/dist/src/Popover/Popover.js +1 -1
  58. package/dist/src/RadioButton/RadioButton.d.ts +1 -1
  59. package/dist/src/RadioButtonCard/RadioButtonCard.d.ts +2 -2
  60. package/dist/src/RadioButtonCard/RadioButtonCard.js +1 -1
  61. package/dist/src/RadioGroup/RadioGroup.d.ts +1 -1
  62. package/dist/src/SearchBox/SearchBox.js +18 -4
  63. package/dist/src/SectionMessage/SectionMessage.d.ts +5 -5
  64. package/dist/src/SectionMessage/SectionMessage.js +11 -4
  65. package/dist/src/SectionMessage/SectionMessage.types.d.ts +4 -4
  66. package/dist/src/SelectBox/SelectBox.js +1 -1
  67. package/dist/src/SelectBox/SelectBoxOption.js +1 -1
  68. package/dist/src/SelectBox/SelectBoxOptionGroup.js +1 -1
  69. package/dist/src/SidePane/SidePane.d.ts +9 -7
  70. package/dist/src/SidePane/SidePane.js +8 -4
  71. package/dist/src/SidePane/hooks/useSidePaneStateController.d.ts +7 -2
  72. package/dist/src/SidePane/hooks/useSidePaneStateController.js +11 -5
  73. package/dist/src/Sidebar/Sidebar.d.ts +10 -1
  74. package/dist/src/Sidebar/Sidebar.js +40 -10
  75. package/dist/src/Sidebar/Sidebar.types.d.ts +39 -2
  76. package/dist/src/Sidebar/SidebarContext.d.ts +3 -0
  77. package/dist/src/Sidebar/SidebarContext.js +2 -0
  78. package/dist/src/Sidebar/SidebarMenuHeading/SidebarMenuHeading.d.ts +49 -0
  79. package/dist/src/Sidebar/SidebarMenuHeading/SidebarMenuHeading.js +113 -0
  80. package/dist/src/Sidebar/SidebarMenuHeading/SidebarMenuHeading.types.d.ts +36 -0
  81. package/dist/src/Sidebar/SidebarMenuHeading/SidebarMenuHeading.types.js +1 -0
  82. package/dist/src/Sidebar/SidebarMenuHeading/index.d.ts +2 -0
  83. package/dist/src/Sidebar/SidebarMenuHeading/index.js +1 -0
  84. package/dist/src/Sidebar/SidebarNavigationItem.js +6 -3
  85. package/dist/src/Sidebar/hooks/useSidebarResize.d.ts +2 -1
  86. package/dist/src/Sidebar/hooks/useSidebarResize.js +31 -3
  87. package/dist/src/Sidebar/index.d.ts +2 -1
  88. package/dist/src/Stack/Stack.d.ts +5 -5
  89. package/dist/src/StatusLabel/StatusLabel.d.ts +2 -2
  90. package/dist/src/Stepper/Step/Step.js +1 -1
  91. package/dist/src/SubNavigation/SubNavigation.js +1 -1
  92. package/dist/src/Tag/Tag.d.ts +1 -1
  93. package/dist/src/Tag/Tag.js +2 -2
  94. package/dist/src/Tag/Tag.types.d.ts +7 -0
  95. package/dist/src/TextBox/TextBox.d.ts +6 -6
  96. package/dist/src/TextLink/TextLink.d.ts +2 -2
  97. package/dist/src/Textarea/Textarea.d.ts +4 -4
  98. package/dist/src/Toast/Toast.d.ts +3 -3
  99. package/dist/src/Toast/Toast.js +9 -5
  100. package/dist/src/Toast/Toast.types.d.ts +3 -5
  101. package/dist/src/Toast/api/toast.d.ts +18 -2
  102. package/dist/src/Tooltip/Tooltip.d.ts +3 -3
  103. package/dist/src/Tooltip/Tooltip.js +1 -1
  104. package/dist/src/Tooltip/Tooltip.types.d.ts +2 -0
  105. package/dist/src/Tooltip/hooks/useTooltipDisplayController.js +14 -2
  106. package/dist/src/utilities/dom/dispatchNativeInputValueWithEvent.d.ts +1 -1
  107. package/dist/src/utilities/dom/useFocusTrap.d.ts +1 -1
  108. package/dist/src/utilities/react/useIsomorphicLayoutEffect.d.ts +2 -2
  109. package/dist/styled-system/css/conditions.d.ts +3 -3
  110. package/dist/styled-system/helpers.d.ts +36 -35
  111. package/dist/styled-system/jsx/factory-helper.d.ts +4 -4
  112. package/dist/styled-system/recipes/create-recipe.d.ts +2 -2
  113. package/dist/styled-system/recipes/data-table-cell-slot-recipe.d.ts +1 -0
  114. package/dist/styled-system/recipes/data-table-cell-slot-recipe.js +4 -0
  115. package/dist/styled-system/recipes/data-table-header-cell-slot-recipe.d.ts +1 -0
  116. package/dist/styled-system/recipes/data-table-header-cell-slot-recipe.js +4 -0
  117. package/dist/styled-system/recipes/dropdown-menu-item-slot-recipe.d.ts +1 -1
  118. package/dist/styled-system/recipes/dropdown-menu-item-slot-recipe.js +12 -0
  119. package/dist/styled-system/recipes/index.d.ts +2 -1
  120. package/dist/styled-system/recipes/index.js +1 -0
  121. package/dist/styled-system/recipes/section-message-slot-recipe.d.ts +1 -1
  122. package/dist/styled-system/recipes/section-message-slot-recipe.js +3 -1
  123. package/dist/styled-system/recipes/sidebar-menu-heading-slot-recipe.d.ts +33 -0
  124. package/dist/styled-system/recipes/sidebar-menu-heading-slot-recipe.js +44 -0
  125. package/dist/styled-system/recipes/sidebar-slot-recipe.d.ts +1 -1
  126. package/dist/styled-system/recipes/sidebar-slot-recipe.js +4 -0
  127. package/dist/styles.css +158 -14
  128. package/dist/tsconfig.build.tsbuildinfo +1 -1
  129. package/package.json +11 -11
@@ -0,0 +1,113 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { Copy, Current } from '@moneyforward/mfui-icons-react';
5
+ import { cx } from '../../../styled-system/css';
6
+ import { sidebarMenuHeadingSlotRecipe } from '../../../styled-system/recipes';
7
+ import { DropdownMenu } from '../../DropdownMenu';
8
+ import { Tooltip } from '../../Tooltip';
9
+ import { CLOSE_DELAY } from '../../Tooltip/Tooltip.constants';
10
+ import { Typography } from '../../Typography';
11
+ // How long the "copied" feedback stays while the user remains on the row.
12
+ const COPIED_FEEDBACK_DURATION_MS = 5000;
13
+ // Copy-to-clipboard feedback for the identification-number row: `copied` drives the tooltip text,
14
+ // the icon swap, and the live region; the handlers are spread onto the `DropdownMenu.Item`.
15
+ function useCopyFeedback(text) {
16
+ const [copied, setCopied] = useState(false);
17
+ const timerRef = useRef(undefined);
18
+ useEffect(() => () => {
19
+ window.clearTimeout(timerRef.current);
20
+ }, []);
21
+ // On blur (keyboard focus moved on), dismiss immediately so the tooltip never lingers next to a
22
+ // newly focused item; the copy result is still announced by the `role="status"` live region.
23
+ const onBlur = () => {
24
+ window.clearTimeout(timerRef.current);
25
+ setCopied(false);
26
+ };
27
+ // On mouse leave, dismiss after the same delay as the Tooltip's own close behavior.
28
+ const onMouseLeave = () => {
29
+ window.clearTimeout(timerRef.current);
30
+ timerRef.current = window.setTimeout(() => {
31
+ setCopied(false);
32
+ }, CLOSE_DELAY);
33
+ };
34
+ // Copy the text, keep the menu open, and show the "copied" feedback (tooltip + icon) while the
35
+ // user stays on the row. The feedback only appears once the clipboard write succeeds; on failure
36
+ // the row keeps its copy label so the user can retry.
37
+ const onClick = (event) => {
38
+ event.preventDefault(); // keep the menu open after copying
39
+ navigator.clipboard
40
+ .writeText(text ?? '')
41
+ .then(() => {
42
+ setCopied(true);
43
+ window.clearTimeout(timerRef.current);
44
+ timerRef.current = window.setTimeout(() => {
45
+ setCopied(false);
46
+ }, COPIED_FEEDBACK_DURATION_MS);
47
+ })
48
+ .catch(() => {
49
+ // Swallow the rejection (insecure context, missing clipboard-write permission, etc.) so it
50
+ // does not surface as an unhandled promise rejection.
51
+ });
52
+ };
53
+ return { copied, onClick, onBlur, onMouseLeave };
54
+ }
55
+ function SidebarMenuHeading({ name, identificationNumber, copy }) {
56
+ const classes = sidebarMenuHeadingSlotRecipe();
57
+ const { copied, ...copyHandlers } = useCopyFeedback(copy?.text);
58
+ const copiedLabel = copy?.copiedLabel ?? 'コピーしました';
59
+ const numberRow = (_jsxs(DropdownMenu.Item, { className: cx(classes.numberRow, 'mfui-SidebarMenuHeading__numberRow'), ...(copy ? copyHandlers : {}), children: [_jsx(Typography, { className: cx(classes.numberText, 'mfui-SidebarMenuHeading__numberText'), children: identificationNumber }), copy ? (copied ? (_jsx(Current, { "aria-hidden": true, className: cx(classes.numberIcon, 'mfui-SidebarMenuHeading__numberIcon') })) : (_jsx(Copy, { "aria-hidden": true, className: cx(classes.numberIcon, 'mfui-SidebarMenuHeading__numberIcon') }))) : null] }));
60
+ return (_jsxs(_Fragment, { children: [_jsx(DropdownMenu.Heading, { children: name }), copy ? (_jsxs(_Fragment, { children: [_jsx(Tooltip, { content: copied ? copiedLabel : copy.label, open: copied || undefined, placement: "right", targetDOMNode: typeof document === 'undefined' ? undefined : document.body, className: cx(classes.tooltip, 'mfui-SidebarMenuHeading__tooltip'), children: numberRow }), _jsx("span", { role: "status", className: cx(classes.status, 'mfui-SidebarMenuHeading__status'), children: copied ? copiedLabel : '' })] })) : (numberRow)] }));
61
+ }
62
+ /**
63
+ * The heading block of the Sidebar tenant menu: the tenant name heading and the
64
+ * identification-number row. Place it as the first child of `Sidebar.TenantMenu`.
65
+ *
66
+ * Pass the `copy` prop to make the identification-number row copy its value to the clipboard,
67
+ * with a tooltip and a screen-reader announcement. The feedback after copying reads `コピーしました`
68
+ * by default and can be changed via `copy.copiedLabel`. Without `copy`, the row is static text.
69
+ *
70
+ * @param props - The props of the `Sidebar.TenantMenuHeading` component.
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * <Sidebar.TenantMenu name="株式会社サンプル" tooltipLabel="事業者">
75
+ * <Sidebar.TenantMenuHeading
76
+ * name="株式会社サンプル"
77
+ * identificationNumber="事業者番号:0123-4567"
78
+ * copy={{ text: '0123-4567', label: '事業者番号をコピーする' }}
79
+ * />
80
+ * <DropdownMenu.Divider />
81
+ * <DropdownMenu.Item href="https://example.com">事業者設定</DropdownMenu.Item>
82
+ * </Sidebar.TenantMenu>
83
+ * ```
84
+ */
85
+ export function SidebarTenantMenuHeading(props) {
86
+ return _jsx(SidebarMenuHeading, { ...props });
87
+ }
88
+ /**
89
+ * The heading block of the Sidebar user menu: the user (account) name heading and the
90
+ * identification-number row. Place it as the first child of `Sidebar.UserMenu`.
91
+ *
92
+ * Pass the `copy` prop to make the identification-number row copy its value to the clipboard,
93
+ * with a tooltip and a screen-reader announcement. The feedback after copying reads `コピーしました`
94
+ * by default and can be changed via `copy.copiedLabel`. Without `copy`, the row is static text.
95
+ *
96
+ * @param props - The props of the `Sidebar.UserMenuHeading` component.
97
+ *
98
+ * @example
99
+ * ```tsx
100
+ * <Sidebar.UserMenu name="山田 太郎" tooltipLabel="アカウント">
101
+ * <Sidebar.UserMenuHeading
102
+ * name="山田 太郎"
103
+ * identificationNumber="従業員番号:1234"
104
+ * copy={{ text: '1234', label: '従業員番号をコピーする' }}
105
+ * />
106
+ * <DropdownMenu.Divider />
107
+ * <DropdownMenu.Item onClick={handleLogout}>ログアウト</DropdownMenu.Item>
108
+ * </Sidebar.UserMenu>
109
+ * ```
110
+ */
111
+ export function SidebarUserMenuHeading(props) {
112
+ return _jsx(SidebarMenuHeading, { ...props });
113
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The copy-to-clipboard settings for the identification-number row.
3
+ */
4
+ export type SidebarMenuHeadingCopy = {
5
+ /**
6
+ * The text written to the clipboard when the row is selected (e.g. `"0123-4567"`).
7
+ */
8
+ text: string;
9
+ /**
10
+ * The tooltip label prompting the copy action (e.g. `"事業者番号をコピーする"`).
11
+ */
12
+ label: string;
13
+ /**
14
+ * The label shown in the tooltip and announced to screen readers right after copying.
15
+ *
16
+ * @default 'コピーしました'
17
+ */
18
+ copiedLabel?: string;
19
+ };
20
+ export type SidebarMenuHeadingProps = {
21
+ /**
22
+ * The tenant (business) or user (account) name shown as the menu heading.
23
+ */
24
+ name: string;
25
+ /**
26
+ * The identification-number row text (e.g. `"事業者番号:0123-4567"`).
27
+ */
28
+ identificationNumber: string;
29
+ /**
30
+ * Enables copy-to-clipboard on the identification-number row: the row becomes a menu item button
31
+ * with a copy icon, a tooltip, and a screen-reader announcement. When omitted, the row is static text.
32
+ */
33
+ copy?: SidebarMenuHeadingCopy;
34
+ };
35
+ export type SidebarTenantMenuHeadingProps = SidebarMenuHeadingProps;
36
+ export type SidebarUserMenuHeadingProps = SidebarMenuHeadingProps;
@@ -0,0 +1,2 @@
1
+ export { SidebarTenantMenuHeading, SidebarUserMenuHeading } from './SidebarMenuHeading';
2
+ export { type SidebarMenuHeadingCopy, type SidebarTenantMenuHeadingProps, type SidebarUserMenuHeadingProps, } from './SidebarMenuHeading.types';
@@ -0,0 +1 @@
1
+ export { SidebarTenantMenuHeading, SidebarUserMenuHeading } from './SidebarMenuHeading';
@@ -1,12 +1,13 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cloneElement, useRef, useState } from 'react';
3
+ import { cloneElement, useContext, useRef, useState, } from 'react';
4
4
  import { cx } from '../../styled-system/css';
5
5
  import { sidebarSlotRecipe } from '../../styled-system/recipes';
6
6
  import { FocusIndicator } from '../FocusIndicator';
7
7
  import { Tooltip } from '../Tooltip';
8
8
  import { Typography } from '../Typography';
9
9
  import { useIsomorphicLayoutEffect } from '../utilities/react/useIsomorphicLayoutEffect';
10
+ import { SidebarContext } from './SidebarContext';
10
11
  /**
11
12
  * A single navigation item shown in the Sidebar.
12
13
  *
@@ -15,6 +16,7 @@ import { useIsomorphicLayoutEffect } from '../utilities/react/useIsomorphicLayou
15
16
  */
16
17
  export function SidebarNavigationItem({ label, icon, isCurrent, maxLines, ...rest }) {
17
18
  const classes = sidebarSlotRecipe();
19
+ const { isCollapsed } = useContext(SidebarContext);
18
20
  const labelRef = useRef(null);
19
21
  const [isTruncated, setIsTruncated] = useState(false);
20
22
  useIsomorphicLayoutEffect(() => {
@@ -40,9 +42,10 @@ export function SidebarNavigationItem({ label, icon, isCurrent, maxLines, ...res
40
42
  const href = isAnchor ? rest.href : undefined;
41
43
  const target = 'target' in rest ? rest.target : undefined;
42
44
  const onClick = 'onClick' in rest ? rest.onClick : undefined;
43
- return (_jsx("li", { className: cx(classes.navigationListItem, 'mfui-Sidebar__navigationListItem'), style: maxLines !== undefined ? { '--mfui-sidebar-max-lines': maxLines } : undefined, children: _jsx(Tooltip, { content: label, disabled: !isTruncated, placement: "right", children: _jsx(FocusIndicator, { children: _jsx(Tag, { "data-mfui-focusable": true, href: href, target: target, type: isAnchor ? undefined : 'button', "aria-current": isCurrent ? 'page' : undefined, className: cx(classes.navigationLink, 'mfui-Sidebar__navigationLink'), onClick: onClick, children: _jsxs("div", { className: cx(classes.navigationLinkInner, 'mfui-Sidebar__navigationLinkInner'), children: [_jsx("span", { className: cx(classes.navigationLinkIcon, 'mfui-Sidebar__navigationLinkIcon'), children: cloneElement(icon, {
45
+ const shouldShowTooltip = isCollapsed || isTruncated;
46
+ return (_jsx("li", { className: cx(classes.navigationListItem, 'mfui-Sidebar__navigationListItem'), style: maxLines !== undefined ? { '--mfui-sidebar-max-lines': maxLines } : undefined, children: _jsx(Tooltip, { content: label, disabled: !shouldShowTooltip, placement: "right", children: _jsx(FocusIndicator, { children: _jsx(Tag, { "data-mfui-focusable": true, href: href, target: target, type: isAnchor ? undefined : 'button', "aria-label": isCollapsed ? label : undefined, "aria-current": isCurrent ? 'page' : undefined, className: cx(classes.navigationLink, 'mfui-Sidebar__navigationLink'), onClick: onClick, children: _jsxs("div", { className: cx(classes.navigationLinkInner, 'mfui-Sidebar__navigationLinkInner'), children: [_jsx("span", { className: cx(classes.navigationLinkIcon, 'mfui-Sidebar__navigationLinkIcon'), children: cloneElement(icon, {
44
47
  width: 18,
45
48
  height: 18,
46
49
  'aria-hidden': true,
47
- }) }), _jsx(Typography, { ref: labelRef, variant: "controlLabel", className: cx(classes.navigationLinkLabel, 'mfui-Sidebar__navigationLinkLabel'), children: label })] }) }) }) }) }));
50
+ }) }), isCollapsed ? null : (_jsx(Typography, { ref: labelRef, variant: "controlLabel", className: cx(classes.navigationLinkLabel, 'mfui-Sidebar__navigationLinkLabel'), children: label }))] }) }) }) }) }));
48
51
  }
@@ -12,11 +12,12 @@ import { type KeyboardEvent, type PointerEvent as ReactPointerEvent } from 'reac
12
12
  *
13
13
  * @returns Object containing the current width, resolved bounds, refs, and resize handlers
14
14
  */
15
- export declare function useSidebarResize({ minWidth, maxWidth, defaultWidth, onWidthChange, }?: {
15
+ export declare function useSidebarResize({ minWidth, maxWidth, defaultWidth, onWidthChange, isCollapsed, }?: {
16
16
  minWidth?: number;
17
17
  maxWidth?: number;
18
18
  defaultWidth?: number;
19
19
  onWidthChange?: (width: number) => void;
20
+ isCollapsed?: boolean;
20
21
  }): {
21
22
  width: number;
22
23
  minWidth: number;
@@ -1,7 +1,8 @@
1
- import { useCallback, useEffect, useRef, useState, } from 'react';
1
+ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
2
2
  const DEFAULT_WIDTH = 200;
3
3
  const DEFAULT_MIN_WIDTH = 180;
4
4
  const DEFAULT_MAX_WIDTH = 280;
5
+ const COLLAPSED_WIDTH = 48;
5
6
  const KEYBOARD_STEP_PX = 14;
6
7
  /**
7
8
  * Hook to manage the resizable width of the Sidebar via pointer dragging and keyboard control.
@@ -16,10 +17,11 @@ const KEYBOARD_STEP_PX = 14;
16
17
  *
17
18
  * @returns Object containing the current width, resolved bounds, refs, and resize handlers
18
19
  */
19
- export function useSidebarResize({ minWidth = DEFAULT_MIN_WIDTH, maxWidth = DEFAULT_MAX_WIDTH, defaultWidth, onWidthChange, } = {}) {
20
+ export function useSidebarResize({ minWidth = DEFAULT_MIN_WIDTH, maxWidth = DEFAULT_MAX_WIDTH, defaultWidth, onWidthChange, isCollapsed = false, } = {}) {
20
21
  const rootRef = useRef(null);
21
22
  const [isDragging, setIsDragging] = useState(false);
22
23
  const pointerIdRef = useRef(null);
24
+ const isCollapsedRef = useRef(isCollapsed);
23
25
  const onWidthChangeRef = useRef(onWidthChange);
24
26
  useEffect(() => {
25
27
  onWidthChangeRef.current = onWidthChange;
@@ -37,6 +39,7 @@ export function useSidebarResize({ minWidth = DEFAULT_MIN_WIDTH, maxWidth = DEFA
37
39
  // not re-synced on later changes, so the user's drag/keyboard adjustments are never overridden.
38
40
  const initialWidth = clamp(defaultWidth ?? DEFAULT_WIDTH);
39
41
  const widthRef = useRef(initialWidth);
42
+ const lastExpandedWidthRef = useRef(initialWidth);
40
43
  const [width, setWidth] = useState(initialWidth);
41
44
  const notify = useCallback((value) => {
42
45
  onWidthChangeRef.current?.(value);
@@ -47,6 +50,9 @@ export function useSidebarResize({ minWidth = DEFAULT_MIN_WIDTH, maxWidth = DEFA
47
50
  }, []);
48
51
  // --- Drag ---
49
52
  const handlePointerDown = useCallback((event) => {
53
+ if (isCollapsedRef.current) {
54
+ return;
55
+ }
50
56
  event.preventDefault();
51
57
  event.currentTarget.setPointerCapture(event.pointerId);
52
58
  pointerIdRef.current = event.pointerId;
@@ -82,6 +88,9 @@ export function useSidebarResize({ minWidth = DEFAULT_MIN_WIDTH, maxWidth = DEFA
82
88
  }, [isDragging, handlePointerMove, handlePointerUp]);
83
89
  // --- Keyboard ---
84
90
  const handleKeyDown = useCallback((event) => {
91
+ if (isCollapsedRef.current) {
92
+ return;
93
+ }
85
94
  let newWidth;
86
95
  switch (event.key) {
87
96
  case 'ArrowRight':
@@ -107,5 +116,24 @@ export function useSidebarResize({ minWidth = DEFAULT_MIN_WIDTH, maxWidth = DEFA
107
116
  notify(newWidth);
108
117
  }
109
118
  }, [minWidth, maxWidth, applyWidth, notify]);
110
- return { width, minWidth, maxWidth, rootRef, isDragging, handlePointerDown, handleKeyDown };
119
+ useEffect(() => {
120
+ if (isCollapsedRef.current === isCollapsed) {
121
+ return;
122
+ }
123
+ if (isCollapsed) {
124
+ lastExpandedWidthRef.current = widthRef.current;
125
+ setIsDragging(false);
126
+ pointerIdRef.current = null;
127
+ }
128
+ else {
129
+ // width/widthRef never change while collapsed (handlePointerDown/handleKeyDown
130
+ // early-return above), so this is a no-op today. Kept as a defensive restore in
131
+ // case a future change allows width-affecting state (e.g. minWidth/maxWidth) to
132
+ // change while collapsed.
133
+ applyWidth(lastExpandedWidthRef.current);
134
+ }
135
+ isCollapsedRef.current = isCollapsed;
136
+ }, [applyWidth, isCollapsed]);
137
+ const effectiveWidth = useMemo(() => (isCollapsed ? COLLAPSED_WIDTH : width), [isCollapsed, width]);
138
+ return { width: effectiveWidth, minWidth, maxWidth, rootRef, isDragging, handlePointerDown, handleKeyDown };
111
139
  }
@@ -1,6 +1,7 @@
1
1
  export { Sidebar } from './Sidebar';
2
- export type { SidebarProps, SidebarNavigationItem, SidebarNavigationDivider, SidebarNavigationEntry, } from './Sidebar.types';
2
+ export type { SidebarProps, SidebarFooterIconMenuSlotState, SidebarNavigationItem, SidebarNavigationDivider, SidebarNavigationEntry, } from './Sidebar.types';
3
3
  export type { SidebarNavigationItemProps } from './SidebarNavigationItem';
4
4
  export type { SidebarServiceMenuProps } from './SidebarServiceMenu';
5
5
  export type { SidebarTenantMenuProps } from './SidebarTenantMenu';
6
6
  export type { SidebarUserMenuProps } from './SidebarUserMenu';
7
+ export type { SidebarTenantMenuHeadingProps, SidebarUserMenuHeadingProps, SidebarMenuHeadingCopy, } from './SidebarMenuHeading';
@@ -13,11 +13,11 @@ import { type StackProps } from './Stack.types';
13
13
  */
14
14
  export declare const Stack: import("react").ForwardRefExoticComponent<{
15
15
  children?: import("react").ReactNode;
16
- direction?: import("react").CSSProperties["flexDirection"];
17
- gap?: ("horizontal.1" | "horizontal.2" | "horizontal.3" | "horizontal.4" | "horizontal.5" | "horizontal.6" | "horizontal.7" | "horizontal.8" | "horizontal.20" | "horizontal.0-1of8" | "horizontal.0-1of4" | "horizontal.0-1of2" | "horizontal.1-1of2" | "horizontal.2-1of2" | "horizontal.3-1of7" | "horizontal.3-1of2" | "horizontal.4-1of2" | "horizontal.5-1of2" | "horizontal.6-1of2" | "horizontal.7-1of2" | "vertical.1" | "vertical.2" | "vertical.3" | "vertical.0-1of8" | "vertical.0-1of6" | "vertical.0-1of4" | "vertical.0-1of3" | "vertical.0-1of2" | "vertical.0-2of3" | "vertical.0-3of4" | "vertical.0-5of6" | "vertical.0-7of8" | "vertical.1-1of8" | "vertical.1-1of4" | "vertical.1-1of3" | "vertical.1-1of2" | "vertical.1-2of3" | "vertical.2-1of2") | `${number}px` | number;
18
- wrap?: import("react").CSSProperties["flexWrap"];
19
- alignItems?: import("react").CSSProperties["alignItems"];
20
- justifyContent?: import("react").CSSProperties["justifyContent"];
16
+ direction?: import("react").CSSProperties['flexDirection'];
17
+ gap?: ("horizontal.0-1of2" | "horizontal.0-1of4" | "horizontal.0-1of8" | "horizontal.1" | "horizontal.1-1of2" | "horizontal.2" | "horizontal.2-1of2" | "horizontal.20" | "horizontal.3" | "horizontal.3-1of2" | "horizontal.3-1of7" | "horizontal.4" | "horizontal.4-1of2" | "horizontal.5" | "horizontal.5-1of2" | "horizontal.6" | "horizontal.6-1of2" | "horizontal.7" | "horizontal.7-1of2" | "horizontal.8" | "vertical.0-1of2" | "vertical.0-1of3" | "vertical.0-1of4" | "vertical.0-1of6" | "vertical.0-1of8" | "vertical.0-2of3" | "vertical.0-3of4" | "vertical.0-5of6" | "vertical.0-7of8" | "vertical.1" | "vertical.1-1of2" | "vertical.1-1of3" | "vertical.1-1of4" | "vertical.1-1of8" | "vertical.1-2of3" | "vertical.2" | "vertical.2-1of2" | "vertical.3") | `${number}px` | number;
18
+ wrap?: import("react").CSSProperties['flexWrap'];
19
+ alignItems?: import("react").CSSProperties['alignItems'];
20
+ justifyContent?: import("react").CSSProperties['justifyContent'];
21
21
  } & Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
22
22
  /**
23
23
  * This component is inherited from the Stack component and helps you create a horizontal stack layout.
@@ -11,7 +11,7 @@
11
11
  export declare const StatusLabel: import("react").ForwardRefExoticComponent<{
12
12
  label: string;
13
13
  icon?: import("react").ReactNode;
14
- status?: import("../../styled-system/recipes").StatusLabelSlotRecipeVariant["status"];
15
- size?: import("../../styled-system/recipes").StatusLabelSlotRecipeVariant["size"];
14
+ status?: import("../../styled-system/recipes").StatusLabelSlotRecipeVariant['status'];
15
+ size?: import("../../styled-system/recipes").StatusLabelSlotRecipeVariant['size'];
16
16
  className?: string;
17
17
  } & Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { createElement, useContext } from 'react';
4
4
  import { cx } from '../../../styled-system/css';
5
5
  import { stepperSlotRecipe } from '../../../styled-system/recipes';
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { DisclosureBasicCollapsed, Lock } from '@moneyforward/mfui-icons-react';
3
3
  import { cx } from '../../styled-system/css';
4
4
  import { subNavigationSlotRecipe } from '../../styled-system/recipes';
@@ -7,4 +7,4 @@ import { type TagProps } from './Tag.types';
7
7
  * - If `disabled` is `true` and `onClick` is provided, the tag will be displayed as disabled button.
8
8
  * - If `showCloseButton` is `true`, the tag will be displayed with a close button.
9
9
  */
10
- export declare function Tag({ label, onClick, href, customLinkComponent, disabled, onClose, target, rel, className, }: TagProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Tag({ label, onClick, href, customLinkComponent, disabled, onClose, closeButtonProps, target, rel, className, }: TagProps): import("react/jsx-runtime").JSX.Element;
@@ -14,10 +14,10 @@ import { cx } from '../../styled-system/css';
14
14
  * - If `disabled` is `true` and `onClick` is provided, the tag will be displayed as disabled button.
15
15
  * - If `showCloseButton` is `true`, the tag will be displayed with a close button.
16
16
  */
17
- export function Tag({ label, onClick, href, customLinkComponent, disabled = false, onClose, target, rel, className, }) {
17
+ export function Tag({ label, onClick, href, customLinkComponent, disabled = false, onClose, closeButtonProps, target, rel, className, }) {
18
18
  const isClickable = !!onClick || !!href;
19
19
  const classes = tagSlotRecipe({ interactable: isClickable, showCloseButton: !!onClose });
20
- const closeButton = (_jsx(IconButton, { disabled: disabled, className: cx(classes.closeButton, 'mfui-Tag__closeButton'), "aria-label": `${label}を削除する`, onClick: onClose, children: _jsx(Close, {}) }));
20
+ const closeButton = (_jsx(IconButton, { disabled: disabled, className: cx(classes.closeButton, 'mfui-Tag__closeButton'), "aria-label": closeButtonProps?.['aria-label'] ?? `${label}を削除する`, onClick: onClose, children: _jsx(Close, {}) }));
21
21
  if (!isClickable) {
22
22
  return (_jsx(FocusIndicator, { children: _jsxs("span", { className: cx(classes.root, 'mfui-Tag__root', className), children: [_jsx(Typography, { variant: "condensedInput", children: label }), onClose ? closeButton : null] }) }));
23
23
  }
@@ -33,6 +33,13 @@ export type TagProps = {
33
33
  * The handler to close the tag. When this prop is provided, the close button will be shown
34
34
  */
35
35
  onClose?: (event: MouseEvent<HTMLButtonElement>) => void;
36
+ /**
37
+ * The properties for the close button.
38
+ * If this prop is not passed, the default values for each property will be applied.
39
+ *
40
+ * @property aria-label - The alternative text for the close button. default is '{label}を削除する'.
41
+ */
42
+ closeButtonProps?: Pick<ComponentPropsWithoutRef<'button'>, 'aria-label'>;
36
43
  /**
37
44
  * Class name to be applied to the wrapper element.
38
45
  */
@@ -9,13 +9,13 @@ import React from 'react';
9
9
  */
10
10
  export declare const TextBox: React.ForwardRefExoticComponent<{
11
11
  enableClearButton?: boolean;
12
- onClear?: import("..").IconButtonProps["onClick"];
13
- invalid?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant["invalid"];
14
- textBoxSize?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant["size"];
15
- disabled?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant["disabled"];
16
- wrapperProps?: React.ComponentPropsWithRef<"div">;
12
+ onClear?: import("..").IconButtonProps['onClick'];
13
+ invalid?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant['invalid'];
14
+ textBoxSize?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant['size'];
15
+ disabled?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant['disabled'];
16
+ wrapperProps?: React.ComponentPropsWithRef<'div'>;
17
17
  prefixSlot?: React.ReactNode;
18
18
  suffixSlot?: React.ReactNode;
19
- clearButtonProps?: Pick<React.ComponentPropsWithoutRef<"input">, "aria-label">;
19
+ clearButtonProps?: Pick<React.ComponentPropsWithoutRef<'input'>, 'aria-label'>;
20
20
  touchDeviceReadOnly?: boolean;
21
21
  } & Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "prefix"> & React.RefAttributes<HTMLInputElement>>;
@@ -7,9 +7,9 @@
7
7
  */
8
8
  export declare const TextLink: import("react").ForwardRefExoticComponent<{
9
9
  children?: React.ReactNode;
10
- variant?: import("../../styled-system/recipes").TextLinkSlotRecipeVariant["variant"];
10
+ variant?: import("../../styled-system/recipes").TextLinkSlotRecipeVariant['variant'];
11
11
  className?: string;
12
12
  customLinkComponent?: import("react").ElementType;
13
13
  showExternalIcon?: boolean;
14
- externalIconProps?: import("react").ComponentPropsWithoutRef<"svg">["aria-label"];
14
+ externalIconProps?: import("react").ComponentPropsWithoutRef<'svg'>['aria-label'];
15
15
  } & Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & import("react").RefAttributes<HTMLAnchorElement>>;
@@ -10,9 +10,9 @@
10
10
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea
11
11
  */
12
12
  export declare const Textarea: import("react").ForwardRefExoticComponent<{
13
- invalid?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant["invalid"];
14
- size?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant["size"];
15
- disabled?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant["disabled"];
13
+ invalid?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant['invalid'];
14
+ size?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant['size'];
15
+ disabled?: import("../../styled-system/recipes").TextBoxSlotRecipeVariant['disabled'];
16
16
  enableAutoResize?: boolean;
17
- resize?: "none" | "vertical" | "horizontal" | "both";
17
+ resize?: 'none' | 'vertical' | 'horizontal' | 'both';
18
18
  } & Omit<import("react").DetailedHTMLProps<import("react").TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & import("react").RefAttributes<HTMLTextAreaElement>>;
@@ -3,12 +3,12 @@
3
3
  * This component switches the variants of looks depends on the props: type and actionText.
4
4
  */
5
5
  export declare const Toast: import("react").ForwardRefExoticComponent<{
6
- type?: import("../../styled-system/recipes").ToastSlotRecipeVariant["type"];
6
+ type?: import("../../styled-system/recipes").ToastSlotRecipeVariant['type'];
7
7
  message: import("react").ReactNode;
8
8
  onClose?: () => void;
9
9
  actionSlot?: import("react").ReactNode;
10
- statusIconProps?: Pick<import("react").ComponentPropsWithoutRef<"svg">, "aria-label">;
11
- closeButtonProps?: Pick<import("react").ComponentPropsWithoutRef<"button">, "aria-label">;
10
+ statusIconProps?: Pick<import("react").ComponentPropsWithoutRef<'svg'>, 'aria-label'>;
11
+ closeButtonProps?: Pick<import("react").ComponentPropsWithoutRef<'button'>, 'aria-label'>;
12
12
  duration?: number;
13
13
  activeElement?: Element | null;
14
14
  customIcon?: import("react").ReactElement;
@@ -18,20 +18,24 @@ export const Toast = forwardRef(({ className, type = 'success', actionSlot, mess
18
18
  const timerRef = useRef(null);
19
19
  const startTimeRef = useRef(null);
20
20
  const localDurationRef = useRef(null);
21
+ // The status is conveyed by the message content itself, so the status icon is decorative
22
+ // and hidden from assistive technology unless a label is explicitly provided.
23
+ const statusIconLabel = statusIconProps?.['aria-label'];
24
+ const statusIconA11yProps = statusIconLabel === undefined ? { 'aria-hidden': true } : { 'aria-label': statusIconLabel };
21
25
  const icon = (() => {
22
26
  if (type === 'success') {
23
- return _jsx(Approval, { "aria-label": statusIconProps?.['aria-label'] ?? '完了' });
27
+ return _jsx(Approval, { ...statusIconA11yProps });
24
28
  }
25
29
  if (type === 'failure') {
26
- return _jsx(Error, { "aria-label": statusIconProps?.['aria-label'] ?? '失敗' });
30
+ return _jsx(Error, { ...statusIconA11yProps });
27
31
  }
28
32
  if (type === 'caution') {
29
- return _jsx(Caution, { "aria-label": statusIconProps?.['aria-label'] ?? '注意' });
33
+ return _jsx(Caution, { ...statusIconA11yProps });
30
34
  }
31
35
  if (type === 'progress') {
32
- return _jsx(ProgressIndicator, {});
36
+ return _jsx(ProgressIndicator, { "aria-hidden": true });
33
37
  }
34
- return _jsx(Pending, { "aria-label": statusIconProps?.['aria-label'] ?? '進行中' });
38
+ return _jsx(Pending, { ...statusIconA11yProps });
35
39
  })();
36
40
  // Handle the duration of the toast
37
41
  useEffect(() => {
@@ -26,13 +26,11 @@ export type ToastProps = {
26
26
  actionSlot?: ReactNode;
27
27
  /**
28
28
  * The properties for the status icon.
29
- * If this prop is not passed, the default values for each property will be applied.
30
29
  *
31
30
  * @property aria-label - The alternative text for the status icon.
32
- * Default is as follows:
33
- * - 'success' type: '完了'
34
- * - 'failure' type: '失敗'
35
- * - 'busy' type: '進行中'
31
+ * By default, the status icon is decorative and hidden from assistive technology (`aria-hidden`),
32
+ * because the message content itself conveys the status.
33
+ * Pass an `aria-label` only when the icon needs to be announced.
36
34
  */
37
35
  statusIconProps?: Pick<ComponentPropsWithoutRef<'svg'>, 'aria-label'>;
38
36
  /**
@@ -1,11 +1,27 @@
1
1
  import { type ToastSlotRecipeVariant } from '../../../styled-system/recipes';
2
2
  import { type ToastApiProps } from './toast.types';
3
+ /**
4
+ * Show a toast message
5
+ *
6
+ * @param props - The toast message properties.
7
+ *
8
+ * @param type - The type of the toast message.
9
+ */
10
+ declare const showToast: (props: ToastApiProps | string, type?: ToastSlotRecipeVariant['type']) => void;
11
+ /**
12
+ * Destroy a toast message.
13
+ * If the key is not provided, all toasts will be destroyed.
14
+ *
15
+ * @param key - The key of the toast message to destroy.
16
+ */
17
+ declare const destroyToast: (key?: string) => void;
3
18
  export declare const toast: {
4
- show: (props: ToastApiProps | string, type?: ToastSlotRecipeVariant["type"]) => void;
19
+ show: typeof showToast;
5
20
  success: (props: ToastApiProps | string) => void;
6
21
  failure: (props: ToastApiProps | string) => void;
7
22
  busy: (props: ToastApiProps | string) => void;
8
23
  progress: (props: ToastApiProps | string) => void;
9
24
  caution: (props: ToastApiProps | string) => void;
10
- destroy: (key?: string) => void;
25
+ destroy: typeof destroyToast;
11
26
  };
27
+ export {};
@@ -41,6 +41,6 @@ export declare const Tooltip: import("react").ForwardRefExoticComponent<{
41
41
  targetDOMNode?: HTMLElement | null;
42
42
  disabled?: boolean;
43
43
  hideFromScreenReader?: boolean;
44
- maxWidth?: import("react").CSSProperties["maxWidth"];
45
- contentProps?: Pick<import("react").ComponentPropsWithoutRef<"div">, "className" | "id">;
46
- } & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref">, "disabled" | "content"> & import("react").RefAttributes<HTMLDivElement>>;
44
+ maxWidth?: import("react").CSSProperties['maxWidth'];
45
+ contentProps?: Pick<import("react").ComponentPropsWithoutRef<'div'>, 'className' | 'id'>;
46
+ } & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref">, "content" | "disabled"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
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';
@@ -16,6 +16,8 @@ export type TooltipProps = {
16
16
  /**
17
17
  * Controls the visibility of the tooltip.
18
18
  * If not specified, the tooltip will automatically show or hidden by using trigger.
19
+ * When this prop changes back from a boolean to `undefined`, the tooltip closes and
20
+ * returns to trigger-based control (a fresh hover/focus is required to reopen it).
19
21
  *
20
22
  * @default undefined
21
23
  */
@@ -42,6 +42,7 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
42
42
  const isHoveringTooltip = useRef(false);
43
43
  const isHoveringTrigger = useRef(false);
44
44
  const previousDisabled = useRef(disabled);
45
+ const previousTooltipOpen = useRef(tooltipOpen);
45
46
  const triggers = useMemo(() => (typeof trigger === 'string' ? [trigger] : trigger), [trigger]);
46
47
  const onActualClose = useCallback(() => {
47
48
  const id = tooltipId.current;
@@ -218,8 +219,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
218
219
  }, [closeImmediate]);
219
220
  // Handle programmatic control with TooltipManager integration
220
221
  useEffect(() => {
222
+ const id = tooltipId.current;
221
223
  if (tooltipOpen !== undefined) {
222
- const id = tooltipId.current;
223
224
  if (tooltipOpen) {
224
225
  tooltipManager.requestOpen(id);
225
226
  }
@@ -227,7 +228,18 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
227
228
  tooltipManager.onClose(id);
228
229
  }
229
230
  }
230
- }, [tooltipOpen]);
231
+ else if (previousTooltipOpen.current !== undefined) {
232
+ // Leaving controlled mode (`open` became undefined): reset to closed instead of leaking
233
+ // the last state into uncontrolled mode. Trigger handlers are detached while controlled,
234
+ // so the hover/focus tracking refs may be stale — clear them and require a fresh trigger.
235
+ tooltipManager.onClose(id);
236
+ triggerSource.current = undefined;
237
+ isHoveringTrigger.current = false;
238
+ isHoveringTooltip.current = false;
239
+ closeImmediate();
240
+ }
241
+ previousTooltipOpen.current = tooltipOpen;
242
+ }, [tooltipOpen, closeImmediate]);
231
243
  useEffect(() => {
232
244
  if (disabled && !previousDisabled.current) {
233
245
  const id = tooltipId.current;
@@ -11,4 +11,4 @@
11
11
  *
12
12
  * @param value - The value to set, is string
13
13
  */
14
- export declare const dispatchNativeInputValueWithEvent: <Element extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement>(input: Element, value: Element["value"]) => void;
14
+ export declare const dispatchNativeInputValueWithEvent: <Element extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement>(input: Element, value: Element['value']) => void;
@@ -22,6 +22,6 @@ type Options = {
22
22
  * @returns The props for the focus trap.
23
23
  */
24
24
  export declare function useFocusTrap({ onKeyDown, onPressingTabOnNotFocusableElement }?: Options): {
25
- handleOnKeyDown: React.KeyboardEventHandler<HTMLElement>;
25
+ handleOnKeyDown: KeyboardEventHandler<HTMLElement>;
26
26
  };
27
27
  export {};