@moneyforward/mfui-components 3.25.1 → 3.27.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 (46) hide show
  1. package/dist/src/DateTimeSelection/DatePicker/DatePickerCalendar/DatePickerCalendar.js +5 -3
  2. package/dist/src/DateTimeSelection/shared/BasePicker/BasePicker.d.ts +1 -1
  3. package/dist/src/DateTimeSelection/shared/BasePicker/BasePicker.js +7 -7
  4. package/dist/src/DateTimeSelection/shared/BasePicker/BasePicker.types.d.ts +11 -0
  5. package/dist/src/DropdownMenu/DropdownMenu.d.ts +1 -1
  6. package/dist/src/DropdownMenu/DropdownMenu.js +3 -3
  7. package/dist/src/DropdownMenu/DropdownMenu.types.d.ts +57 -5
  8. package/dist/src/DropdownMenu/DropdownMenuButtonTrigger.d.ts +46 -0
  9. package/dist/src/DropdownMenu/DropdownMenuButtonTrigger.js +56 -0
  10. package/dist/src/MultipleSelectBox/MultipleSelectBox.js +31 -23
  11. package/dist/src/SelectBox/SelectBox.js +25 -17
  12. package/dist/src/Sidebar/Sidebar.d.ts +63 -0
  13. package/dist/src/Sidebar/Sidebar.js +82 -0
  14. package/dist/src/Sidebar/Sidebar.types.d.ts +143 -0
  15. package/dist/src/Sidebar/Sidebar.types.js +1 -0
  16. package/dist/src/Sidebar/SidebarNavigationItem.d.ts +9 -0
  17. package/dist/src/Sidebar/SidebarNavigationItem.js +48 -0
  18. package/dist/src/Sidebar/SidebarServiceMenu.d.ts +23 -0
  19. package/dist/src/Sidebar/SidebarServiceMenu.js +20 -0
  20. package/dist/src/Sidebar/SidebarTenantMenu.d.ts +23 -0
  21. package/dist/src/Sidebar/SidebarTenantMenu.js +18 -0
  22. package/dist/src/Sidebar/SidebarUserMenu.d.ts +23 -0
  23. package/dist/src/Sidebar/SidebarUserMenu.js +18 -0
  24. package/dist/src/Sidebar/hooks/useSidebarResize.d.ts +28 -0
  25. package/dist/src/Sidebar/hooks/useSidebarResize.js +111 -0
  26. package/dist/src/Sidebar/index.d.ts +6 -0
  27. package/dist/src/Sidebar/index.js +1 -0
  28. package/dist/src/SplitView/SplitView.js +3 -1
  29. package/dist/src/SplitView/SplitView.types.d.ts +6 -0
  30. package/dist/src/SplitView/hooks/useSplitViewDrag.d.ts +1 -0
  31. package/dist/src/SplitView/hooks/useSplitViewDrag.js +11 -1
  32. package/dist/src/SplitView/hooks/useSplitViewKeyboard.d.ts +1 -0
  33. package/dist/src/SplitView/hooks/useSplitViewKeyboard.js +9 -2
  34. package/dist/src/Tooltip/hooks/useTooltipDisplayController.js +28 -1
  35. package/dist/src/index.d.ts +1 -0
  36. package/dist/src/index.js +1 -0
  37. package/dist/src/utilities/react/useIsomorphicLayoutEffect.d.ts +11 -0
  38. package/dist/src/utilities/react/useIsomorphicLayoutEffect.js +11 -0
  39. package/dist/styled-system/recipes/index.d.ts +2 -1
  40. package/dist/styled-system/recipes/index.js +1 -0
  41. package/dist/styled-system/recipes/sidebar-slot-recipe.d.ts +33 -0
  42. package/dist/styled-system/recipes/sidebar-slot-recipe.js +112 -0
  43. package/dist/styled-system/tokens/index.js +6 -6
  44. package/dist/styles.css +346 -6
  45. package/dist/tsconfig.build.tsbuildinfo +1 -1
  46. package/package.json +3 -3
@@ -10,6 +10,7 @@ export declare function useSplitViewKeyboard(options: {
10
10
  initialPanelSize: number;
11
11
  minPanelSize: number;
12
12
  maxPanelSize: number;
13
+ onWidthChange?: (width: number) => void;
13
14
  setControlledPanelSize: (size: number | undefined) => void;
14
15
  setLastControlledPanelSize: (size: number | undefined) => void;
15
16
  }): {
@@ -1,4 +1,4 @@
1
- import { useCallback } from 'react';
1
+ import { useCallback, useEffect, useRef } from 'react';
2
2
  import { KEYBOARD_STEP_PX } from '../constants';
3
3
  import { calculateConstrainedPanelSize } from '../utils/calculatePanelSize';
4
4
  /**
@@ -7,7 +7,11 @@ import { calculateConstrainedPanelSize } from '../utils/calculatePanelSize';
7
7
  * @param options - Keyboard hook options
8
8
  */
9
9
  export function useSplitViewKeyboard(options) {
10
- const { containerRef, targetPanel, controlledPanelSize, initialPanelSize, minPanelSize, maxPanelSize, setControlledPanelSize, setLastControlledPanelSize, } = options;
10
+ const { containerRef, targetPanel, controlledPanelSize, initialPanelSize, minPanelSize, maxPanelSize, onWidthChange, setControlledPanelSize, setLastControlledPanelSize, } = options;
11
+ const onWidthChangeRef = useRef(onWidthChange);
12
+ useEffect(() => {
13
+ onWidthChangeRef.current = onWidthChange;
14
+ });
11
15
  /**
12
16
  * Handle keyboard navigation for the divider.
13
17
  *
@@ -36,6 +40,9 @@ export function useSplitViewKeyboard(options) {
36
40
  const constrainedSize = calculateConstrainedPanelSize(newSize, minPanelSize, maxPanelSize);
37
41
  setControlledPanelSize(constrainedSize);
38
42
  setLastControlledPanelSize(constrainedSize);
43
+ if (constrainedSize !== currentSize) {
44
+ onWidthChangeRef.current?.(constrainedSize);
45
+ }
39
46
  }, [
40
47
  containerRef,
41
48
  targetPanel,
@@ -1,7 +1,22 @@
1
- import { useCallback, useEffect, useId, useMemo, useRef } from 'react';
1
+ import { useCallback, useEffect, useId, useMemo, useRef, } from 'react';
2
2
  import { useUpdateEffect } from '../../utilities/effect/useUpdateEffect';
3
3
  import { tooltipManager } from '../GlobalTooltipManager';
4
4
  import { useOpenStateDelayed } from './useOpenStateDelayed';
5
+ /**
6
+ * Returns `true` only when the event originated from an element that is a real DOM
7
+ * descendant of the wrapper (i.e. the trigger itself).
8
+ *
9
+ * React dispatches synthetic events along the React tree, not the DOM tree, so events
10
+ * from portaled descendants (e.g. a DropdownMenu popover rendered into `document.body`)
11
+ * still bubble up to the wrapper's handlers. Those elements are not DOM descendants of
12
+ * the wrapper, so this check filters them out and prevents the tooltip from reacting to
13
+ * interactions that happen inside portaled content.
14
+ *
15
+ * @param event - The synthetic event dispatched to the wrapper handler.
16
+ */
17
+ function isEventFromTrigger(event) {
18
+ return event.currentTarget.contains(event.target);
19
+ }
5
20
  /**
6
21
  * A hook to control the display of the tooltip.
7
22
  *
@@ -82,6 +97,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
82
97
  if (triggers.includes('hover')) {
83
98
  Object.assign(updatedWrapperProps, {
84
99
  onMouseEnter: (event) => {
100
+ if (!isEventFromTrigger(event))
101
+ return;
85
102
  triggerSource.current = 'hover';
86
103
  isHoveringTrigger.current = true;
87
104
  cancelClose(); // Cancel any pending close
@@ -91,6 +108,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
91
108
  onMouseLeave: (event) => {
92
109
  if (triggerSource.current !== 'hover')
93
110
  return;
111
+ if (!isEventFromTrigger(event))
112
+ return;
94
113
  isHoveringTrigger.current = false;
95
114
  // Only start close timer if also not hovering tooltip
96
115
  // Use queueMicrotask to avoid race conditions with rapid mouse events
@@ -104,6 +123,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
104
123
  if (triggers.includes('click')) {
105
124
  Object.assign(updatedWrapperProps, {
106
125
  onClick: (event) => {
126
+ if (!isEventFromTrigger(event))
127
+ return;
107
128
  if (!open) {
108
129
  triggerSource.current = 'click';
109
130
  openWithManager('immediate');
@@ -119,6 +140,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
119
140
  // When click is not a trigger, clicking should close the tooltip if it's open
120
141
  Object.assign(updatedWrapperProps, {
121
142
  onClick: (event) => {
143
+ if (!isEventFromTrigger(event))
144
+ return;
122
145
  if (open) {
123
146
  closeWithManager();
124
147
  }
@@ -129,6 +152,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
129
152
  if (triggers.includes('focus')) {
130
153
  Object.assign(updatedWrapperProps, {
131
154
  onFocus: (event) => {
155
+ if (!isEventFromTrigger(event))
156
+ return;
132
157
  // onFocus event is triggered before onClick event when the mouse is clicked, so we need to skip it
133
158
  if (isMouseTriggered.current)
134
159
  return;
@@ -139,6 +164,8 @@ export function useTooltipDisplayController({ trigger, wrapperProps, tooltipOpen
139
164
  onBlur: (event) => {
140
165
  if (triggerSource.current !== 'focus')
141
166
  return;
167
+ if (!isEventFromTrigger(event))
168
+ return;
142
169
  closeWithManager();
143
170
  wrapperProps.onBlur?.(event);
144
171
  },
@@ -42,6 +42,7 @@ export * from './RadioGroup';
42
42
  export * from './SearchBox';
43
43
  export * from './SectionMessage';
44
44
  export * from './SelectBox';
45
+ export * from './Sidebar';
45
46
  export * from './SidePane';
46
47
  export * from './Skeleton';
47
48
  export * from './SplitView';
package/dist/src/index.js CHANGED
@@ -42,6 +42,7 @@ export * from './RadioGroup';
42
42
  export * from './SearchBox';
43
43
  export * from './SectionMessage';
44
44
  export * from './SelectBox';
45
+ export * from './Sidebar';
45
46
  export * from './SidePane';
46
47
  export * from './Skeleton';
47
48
  export * from './SplitView';
@@ -0,0 +1,11 @@
1
+ import { useEffect } from 'react';
2
+ /**
3
+ * `useLayoutEffect` that falls back to `useEffect` on the server.
4
+ *
5
+ * `useLayoutEffect` does nothing during server rendering and React logs a warning when it is used
6
+ * there. Using this hook keeps the synchronous, pre-paint timing on the client while avoiding the
7
+ * SSR warning.
8
+ *
9
+ * @see https://react.dev/reference/react/useLayoutEffect#caveats
10
+ */
11
+ export declare const useIsomorphicLayoutEffect: typeof useEffect;
@@ -0,0 +1,11 @@
1
+ import { useEffect, useLayoutEffect } from 'react';
2
+ /**
3
+ * `useLayoutEffect` that falls back to `useEffect` on the server.
4
+ *
5
+ * `useLayoutEffect` does nothing during server rendering and React logs a warning when it is used
6
+ * there. Using this hook keeps the synchronous, pre-paint timing on the client while avoiding the
7
+ * SSR warning.
8
+ *
9
+ * @see https://react.dev/reference/react/useLayoutEffect#caveats
10
+ */
11
+ export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
@@ -98,4 +98,5 @@ export * from './split-view-slot-recipe';
98
98
  export * from './toggle-switch-slot-recipe';
99
99
  export * from './navigation-list-slot-recipe';
100
100
  export * from './navigation-list-item-slot-recipe';
101
- export * from './form-footer-slot-recipe';
101
+ export * from './form-footer-slot-recipe';
102
+ export * from './sidebar-slot-recipe';
@@ -98,3 +98,4 @@ export * from './toggle-switch-slot-recipe.js';
98
98
  export * from './navigation-list-slot-recipe.js';
99
99
  export * from './navigation-list-item-slot-recipe.js';
100
100
  export * from './form-footer-slot-recipe.js';
101
+ export * from './sidebar-slot-recipe.js';
@@ -0,0 +1,33 @@
1
+ /* eslint-disable */
2
+ import type { ConditionalValue } from '../types/index';
3
+ import type { DistributiveOmit, Pretty } from '../types/system-types';
4
+
5
+ interface SidebarSlotRecipeVariant {
6
+
7
+ }
8
+
9
+ type SidebarSlotRecipeVariantMap = {
10
+ [key in keyof SidebarSlotRecipeVariant]: Array<SidebarSlotRecipeVariant[key]>
11
+ }
12
+
13
+ type SidebarSlotRecipeSlot = "root" | "header" | "leftPane" | "logo" | "navigationWrapper" | "mainNavigation" | "extraNavigation" | "navigationList" | "navigationListItem" | "navigationDivider" | "navigationLink" | "navigationLinkInner" | "navigationLinkIcon" | "navigationLinkLabel" | "navigationLinkLabelInner" | "footer" | "footerSlot" | "serviceMenu" | "footerIconMenu" | "footerUserIdMenu" | "footerUserIdMenuItem" | "handle"
14
+
15
+ export type SidebarSlotRecipeVariantProps = {
16
+ [key in keyof SidebarSlotRecipeVariant]?: ConditionalValue<SidebarSlotRecipeVariant[key]> | undefined
17
+ }
18
+
19
+ export interface SidebarSlotRecipeRecipe {
20
+ __slot: SidebarSlotRecipeSlot
21
+ __type: SidebarSlotRecipeVariantProps
22
+ (props?: SidebarSlotRecipeVariantProps): Pretty<Record<SidebarSlotRecipeSlot, string>>
23
+ raw: (props?: SidebarSlotRecipeVariantProps) => SidebarSlotRecipeVariantProps
24
+ variantMap: SidebarSlotRecipeVariantMap
25
+ variantKeys: Array<keyof SidebarSlotRecipeVariant>
26
+ splitVariantProps<Props extends SidebarSlotRecipeVariantProps>(props: Props): [SidebarSlotRecipeVariantProps, Pretty<DistributiveOmit<Props, keyof SidebarSlotRecipeVariantProps>>]
27
+ getVariantProps: (props?: SidebarSlotRecipeVariantProps) => SidebarSlotRecipeVariantProps
28
+ }
29
+
30
+ /**
31
+ * Slot class created for the MFUI Sidebar component.
32
+ */
33
+ export declare const sidebarSlotRecipe: SidebarSlotRecipeRecipe
@@ -0,0 +1,112 @@
1
+ import { compact, getSlotCompoundVariant, memo, splitProps } from '../helpers.js';
2
+ import { createRecipe } from './create-recipe.js';
3
+ const sidebarSlotRecipeDefaultVariants = {};
4
+ const sidebarSlotRecipeCompoundVariants = [];
5
+ const sidebarSlotRecipeSlotNames = [
6
+ [
7
+ "root",
8
+ "Sidebar__root"
9
+ ],
10
+ [
11
+ "header",
12
+ "Sidebar__header"
13
+ ],
14
+ [
15
+ "leftPane",
16
+ "Sidebar__leftPane"
17
+ ],
18
+ [
19
+ "logo",
20
+ "Sidebar__logo"
21
+ ],
22
+ [
23
+ "navigationWrapper",
24
+ "Sidebar__navigationWrapper"
25
+ ],
26
+ [
27
+ "mainNavigation",
28
+ "Sidebar__mainNavigation"
29
+ ],
30
+ [
31
+ "extraNavigation",
32
+ "Sidebar__extraNavigation"
33
+ ],
34
+ [
35
+ "navigationList",
36
+ "Sidebar__navigationList"
37
+ ],
38
+ [
39
+ "navigationListItem",
40
+ "Sidebar__navigationListItem"
41
+ ],
42
+ [
43
+ "navigationDivider",
44
+ "Sidebar__navigationDivider"
45
+ ],
46
+ [
47
+ "navigationLink",
48
+ "Sidebar__navigationLink"
49
+ ],
50
+ [
51
+ "navigationLinkInner",
52
+ "Sidebar__navigationLinkInner"
53
+ ],
54
+ [
55
+ "navigationLinkIcon",
56
+ "Sidebar__navigationLinkIcon"
57
+ ],
58
+ [
59
+ "navigationLinkLabel",
60
+ "Sidebar__navigationLinkLabel"
61
+ ],
62
+ [
63
+ "navigationLinkLabelInner",
64
+ "Sidebar__navigationLinkLabelInner"
65
+ ],
66
+ [
67
+ "footer",
68
+ "Sidebar__footer"
69
+ ],
70
+ [
71
+ "footerSlot",
72
+ "Sidebar__footerSlot"
73
+ ],
74
+ [
75
+ "serviceMenu",
76
+ "Sidebar__serviceMenu"
77
+ ],
78
+ [
79
+ "footerIconMenu",
80
+ "Sidebar__footerIconMenu"
81
+ ],
82
+ [
83
+ "footerUserIdMenu",
84
+ "Sidebar__footerUserIdMenu"
85
+ ],
86
+ [
87
+ "footerUserIdMenuItem",
88
+ "Sidebar__footerUserIdMenuItem"
89
+ ],
90
+ [
91
+ "handle",
92
+ "Sidebar__handle"
93
+ ]
94
+ ];
95
+ const sidebarSlotRecipeSlotFns = /* @__PURE__ */ sidebarSlotRecipeSlotNames.map(([slotName, slotKey]) => [slotName, createRecipe(slotKey, sidebarSlotRecipeDefaultVariants, getSlotCompoundVariant(sidebarSlotRecipeCompoundVariants, slotName))]);
96
+ const sidebarSlotRecipeFn = memo((props = {}) => {
97
+ return Object.fromEntries(sidebarSlotRecipeSlotFns.map(([slotName, slotFn]) => [slotName, slotFn.recipeFn(props)]));
98
+ });
99
+ const sidebarSlotRecipeVariantKeys = [];
100
+ const getVariantProps = (variants) => ({ ...sidebarSlotRecipeDefaultVariants, ...compact(variants) });
101
+ export const sidebarSlotRecipe = /* @__PURE__ */ Object.assign(sidebarSlotRecipeFn, {
102
+ __recipe__: false,
103
+ __name__: 'sidebarSlotRecipe',
104
+ raw: (props) => props,
105
+ classNameMap: {},
106
+ variantKeys: sidebarSlotRecipeVariantKeys,
107
+ variantMap: {},
108
+ splitVariantProps(props) {
109
+ return splitProps(props, sidebarSlotRecipeVariantKeys);
110
+ },
111
+ getVariantProps
112
+ });
@@ -5744,15 +5744,15 @@ const tokens = {
5744
5744
  "variable": "var(--mfui-colors-mfui\\.color\\.base\\.content\\.pressed)"
5745
5745
  },
5746
5746
  "colors.mfui.color.base.sub-content.none": {
5747
- "value": "#747474ff",
5747
+ "value": "#5e5e5eff",
5748
5748
  "variable": "var(--mfui-colors-mfui\\.color\\.base\\.sub-content\\.none)"
5749
5749
  },
5750
5750
  "colors.mfui.color.base.sub-content.hovered": {
5751
- "value": "#595959ff",
5751
+ "value": "#474747ff",
5752
5752
  "variable": "var(--mfui-colors-mfui\\.color\\.base\\.sub-content\\.hovered)"
5753
5753
  },
5754
5754
  "colors.mfui.color.base.sub-content.pressed": {
5755
- "value": "#424242ff",
5755
+ "value": "#303030ff",
5756
5756
  "variable": "var(--mfui-colors-mfui\\.color\\.base\\.sub-content\\.pressed)"
5757
5757
  },
5758
5758
  "colors.mfui.color.base.inverted-content.none": {
@@ -5940,15 +5940,15 @@ const tokens = {
5940
5940
  "variable": "var(--mfui-colors-mfui\\.color\\.disabled\\.background)"
5941
5941
  },
5942
5942
  "colors.mfui.color.link.content.none": {
5943
- "value": "#2e72d8ff",
5943
+ "value": "#165cb7ff",
5944
5944
  "variable": "var(--mfui-colors-mfui\\.color\\.link\\.content\\.none)"
5945
5945
  },
5946
5946
  "colors.mfui.color.link.content.hovered": {
5947
- "value": "#0d57b1ff",
5947
+ "value": "#004396ff",
5948
5948
  "variable": "var(--mfui-colors-mfui\\.color\\.link\\.content\\.hovered)"
5949
5949
  },
5950
5950
  "colors.mfui.color.link.content.pressed": {
5951
- "value": "#003e90ff",
5951
+ "value": "#072977ff",
5952
5952
  "variable": "var(--mfui-colors-mfui\\.color\\.link\\.content\\.pressed)"
5953
5953
  },
5954
5954
  "colors.mfui.color.neutral.content.none": {