@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
@@ -53,9 +53,11 @@ export function DatePickerCalendar({ value, onChange, minDate, maxDate, checkDis
53
53
  setViewingValue(newDate);
54
54
  }, [setViewingValue, viewingValue]);
55
55
  const { isPrevYearDisabled, isNextYearDisabled } = useMemo(() => ({
56
- isPrevYearDisabled: viewingValue.getFullYear() <= MINIMUM_VIEWABLE_YEAR,
57
- isNextYearDisabled: viewingValue.getFullYear() >= MAXIMUM_VIEWABLE_YEAR,
58
- }), [viewingValue]);
56
+ isPrevYearDisabled: viewingValue.getFullYear() <= MINIMUM_VIEWABLE_YEAR ||
57
+ (minDate ? viewingValue.getFullYear() <= minDate.getFullYear() : false),
58
+ isNextYearDisabled: viewingValue.getFullYear() >= MAXIMUM_VIEWABLE_YEAR ||
59
+ (maxDate ? viewingValue.getFullYear() >= maxDate.getFullYear() : false),
60
+ }), [viewingValue, minDate, maxDate]);
59
61
  const { isPrevMonthDisabled, isNextMonthDisabled } = useMemo(() => {
60
62
  const firstDayOfMonth = new Date(viewingValue.getFullYear(), viewingValue.getMonth(), 1);
61
63
  const firstDayOfNextMonth = new Date(viewingValue.getFullYear(), viewingValue.getMonth() + 1, 1);
@@ -4,4 +4,4 @@ import { type BasePickerProps } from './BasePicker.types';
4
4
  * This component uses the composition component of the TextBox component. Please refer to the TextBox documentation for their usage.
5
5
  * This component extends the props of TextBox component.
6
6
  */
7
- export declare function BasePicker({ targetDOMNode, enableAutoUnmount, open, onOpenStateChanged, disableAutoOpen, format, baseFormat, customFormatValue, value, defaultValue, onChange, calendarIconButtonProps, renderPopoverContent, onBlur, allowedPlacements, enableViewportConstraint, calendarLocale, disabled, ...textBoxProps }: BasePickerProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function BasePicker({ targetDOMNode, enableAutoUnmount, open, onOpenStateChanged, disableAutoOpen, format, baseFormat, customFormatValue, value, defaultValue, initialViewingDate, onChange, calendarIconButtonProps, renderPopoverContent, onBlur, allowedPlacements, enableViewportConstraint, calendarLocale, disabled, ...textBoxProps }: BasePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -18,7 +18,7 @@ import { getBasePickerLabel } from './constants';
18
18
  * This component uses the composition component of the TextBox component. Please refer to the TextBox documentation for their usage.
19
19
  * This component extends the props of TextBox component.
20
20
  */
21
- export function BasePicker({ targetDOMNode, enableAutoUnmount = true, open = false, onOpenStateChanged, disableAutoOpen = false, format = 'YYYY/MM/DD', baseFormat = 'YYYY-MM-DD', customFormatValue, value, defaultValue, onChange, calendarIconButtonProps, renderPopoverContent, onBlur, allowedPlacements, enableViewportConstraint, calendarLocale = 'ja', disabled, ...textBoxProps }) {
21
+ export function BasePicker({ targetDOMNode, enableAutoUnmount = true, open = false, onOpenStateChanged, disableAutoOpen = false, format = 'YYYY/MM/DD', baseFormat = 'YYYY-MM-DD', customFormatValue, value, defaultValue, initialViewingDate, onChange, calendarIconButtonProps, renderPopoverContent, onBlur, allowedPlacements, enableViewportConstraint, calendarLocale = 'ja', disabled, ...textBoxProps }) {
22
22
  const textBoxRef = useRef(null);
23
23
  const basePickerPopoverWrapperRef = useRef(null);
24
24
  const triggerRef = useRef(null);
@@ -76,7 +76,7 @@ export function BasePicker({ targetDOMNode, enableAutoUnmount = true, open = fal
76
76
  }
77
77
  openPopover(event);
78
78
  }, [textBoxProps.wrapperProps, textBoxRef]);
79
- return (_jsx(BasePickerProvider, { initialViewingValue: value ?? defaultValue, value: value, internalValue: inputValueProps.value, format: format, baseFormat: baseFormat, children: _jsx(InternalPopover, { renderTrigger: ({ setTriggerRef, togglePopover, openPopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsx(TextBox, { ref: textBoxRef, ...inputValueProps, touchDeviceReadOnly: true, suffixSlot: _jsx(IconButton, { size: textBoxProps.textBoxSize === 'small' ? 'small' : 'default', "aria-label": calendarIconButtonProps?.['aria-label'] ?? calendarIconLabel, "data-active": shouldCalendarIconActive, "data-mfui-content": "calendar-icon-button", disabled: disabled, onClick: togglePopover, onBlur: handleTriggerBlur, children: _jsx(Calendar, {}) }), disabled: disabled, ...textBoxProps, wrapperProps: {
79
+ return (_jsx(BasePickerProvider, { initialViewingValue: value ?? defaultValue ?? initialViewingDate, value: value, internalValue: inputValueProps.value, format: format, baseFormat: baseFormat, children: _jsx(InternalPopover, { renderTrigger: ({ setTriggerRef, togglePopover, openPopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsx(TextBox, { ref: textBoxRef, ...inputValueProps, touchDeviceReadOnly: true, suffixSlot: _jsx(IconButton, { size: textBoxProps.textBoxSize === 'small' ? 'small' : 'default', "aria-label": calendarIconButtonProps?.['aria-label'] ?? calendarIconLabel, "data-active": shouldCalendarIconActive, "data-mfui-content": "calendar-icon-button", disabled: disabled, onClick: togglePopover, onBlur: handleTriggerBlur, children: _jsx(Calendar, {}) }), disabled: disabled, ...textBoxProps, wrapperProps: {
80
80
  ...textBoxProps.wrapperProps,
81
81
  ref: mergeRefs(setTriggerRef, triggerRef, textBoxProps.wrapperProps?.ref),
82
82
  onKeyDown: (event) => {
@@ -93,7 +93,7 @@ export function BasePicker({ targetDOMNode, enableAutoUnmount = true, open = fal
93
93
  inputValueProps.onBlur(event);
94
94
  // Then call the Popover's smart blur detection
95
95
  handleTriggerBlur(event);
96
- } })), open: isBasePickerOpen, targetDOMNode: targetDOMNode, enableAutoUnmount: enableAutoUnmount, minWidth: "min-content", value: value, defaultValue: defaultValue, baseFormat: baseFormat, renderPopoverContent: renderPopoverContent, textBoxRef: textBoxRef, triggerRef: triggerRef, basePickerPopoverWrapperRef: basePickerPopoverWrapperRef, handleOnKeyDown: handleOnKeyDown, pickerPopoverProps: pickerPopoverProps, allowedPlacements: allowedPlacements, enableViewportConstraint: enableViewportConstraint, onOpenStateChanged: toggleBasePicker, onBlur: onBlur }) }));
96
+ } })), open: isBasePickerOpen, targetDOMNode: targetDOMNode, enableAutoUnmount: enableAutoUnmount, minWidth: "min-content", value: value, defaultValue: defaultValue, initialViewingDate: initialViewingDate, baseFormat: baseFormat, renderPopoverContent: renderPopoverContent, textBoxRef: textBoxRef, triggerRef: triggerRef, basePickerPopoverWrapperRef: basePickerPopoverWrapperRef, handleOnKeyDown: handleOnKeyDown, pickerPopoverProps: pickerPopoverProps, allowedPlacements: allowedPlacements, enableViewportConstraint: enableViewportConstraint, onOpenStateChanged: toggleBasePicker, onBlur: onBlur }) }));
97
97
  }
98
98
  /**
99
99
  * Internal Popover component that needs access to BasePickerContext.
@@ -101,7 +101,7 @@ export function BasePicker({ targetDOMNode, enableAutoUnmount = true, open = fal
101
101
  * which requires being within a BasePickerProvider. Creating it as an internal
102
102
  * component ensures proper context access while keeping the logic encapsulated.
103
103
  */
104
- function InternalPopover({ value, defaultValue, textBoxRef, triggerRef, baseFormat = 'YYYY-MM-DD', renderPopoverContent, basePickerPopoverWrapperRef, handleOnKeyDown, pickerPopoverProps, onOpenStateChanged, allowedPlacements, enableViewportConstraint, ...popoverProps }) {
104
+ function InternalPopover({ value, defaultValue, initialViewingDate, textBoxRef, triggerRef, baseFormat = 'YYYY-MM-DD', renderPopoverContent, basePickerPopoverWrapperRef, handleOnKeyDown, pickerPopoverProps, onOpenStateChanged, allowedPlacements, enableViewportConstraint, ...popoverProps }) {
105
105
  // Always call the hook at the top level to ensure consistent hook order
106
106
  const { viewingValue, setViewingValue, setPendingFocusDate } = useBasePickerContext();
107
107
  const handlePopoverOpen = useCallback((event) => {
@@ -119,8 +119,8 @@ function InternalPopover({ value, defaultValue, textBoxRef, triggerRef, baseForm
119
119
  !isClickOnClearButton;
120
120
  if (isClickOnTextBox || isClickOnWrapper)
121
121
  return;
122
- // Get the date to focus on (selected date or today)
123
- const dateToFocus = dayjs(value ?? defaultValue ?? new Date())
122
+ // Get the date to focus on: selected value initialViewingDate → today
123
+ const dateToFocus = dayjs(value ?? defaultValue ?? initialViewingDate ?? new Date())
124
124
  .startOf('day')
125
125
  .toDate();
126
126
  const formattedDate = dayjs(dateToFocus).format(baseFormat);
@@ -128,7 +128,7 @@ function InternalPopover({ value, defaultValue, textBoxRef, triggerRef, baseForm
128
128
  setViewingValue(dayjs(dateToFocus).startOf('month').startOf('day').toDate());
129
129
  // Set the pending focus date to ensure proper focus after month change
130
130
  setPendingFocusDate(formattedDate);
131
- }, [textBoxRef, triggerRef, value, defaultValue, baseFormat, setViewingValue, setPendingFocusDate]);
131
+ }, [textBoxRef, triggerRef, value, defaultValue, initialViewingDate, baseFormat, setViewingValue, setPendingFocusDate]);
132
132
  return (_jsx(Popover, { enableAutomaticPortalTargetResolution: true, enableViewportConstraint: enableViewportConstraint ?? false, enableAutoFocusOnPopover: false, ...popoverProps, renderContent: () => (_jsx("div", { ref: basePickerPopoverWrapperRef, className: "mfui-BasePicker__popoverWrapper", onKeyDown: handleOnKeyDown, children: renderPopoverContent({
133
133
  viewingValue,
134
134
  setViewingValue,
@@ -97,6 +97,17 @@ export type BasePickerProps = {
97
97
  * @default 'ja'
98
98
  */
99
99
  calendarLocale?: 'ja' | 'en';
100
+ /**
101
+ * The initial date the calendar view is centered on when the picker is opened without a selected value.
102
+ * Useful when `minDate` is in the future — without this, the calendar would open showing today
103
+ * even though all visible dates are disabled.
104
+ *
105
+ * When `value` or `defaultValue` is set, this prop is ignored because the calendar always
106
+ * navigates to the selected date's month.
107
+ *
108
+ * @default undefined (falls back to today)
109
+ */
110
+ initialViewingDate?: Date;
100
111
  /**
101
112
  * Custom render function for the popover content. This is required to make BasePicker truly generic.
102
113
  *
@@ -19,7 +19,7 @@ import { DropdownMenuHeading } from './DropdownMenuHeading';
19
19
  * </DropdownMenu>
20
20
  * ```
21
21
  */
22
- export declare function DropdownMenu({ icon, label, children, triggerProps, menuPopoverProps, disabled, targetDOMNode, enableAutoUnmount, onOpenStateChanged, onBlur, }: DropdownMenuProps<ReactElement | undefined>): import("react/jsx-runtime").JSX.Element;
22
+ export declare function DropdownMenu({ icon, label, children, triggerProps, tooltipLabel, tooltipPlacement, triggerMiddleTruncate, triggerTypographyVariant, menuPopoverProps, disabled, targetDOMNode, enableAutoUnmount, onOpenStateChanged, onBlur, }: DropdownMenuProps<ReactElement | undefined>): import("react/jsx-runtime").JSX.Element;
23
23
  export declare namespace DropdownMenu {
24
24
  var Divider: typeof DropdownMenuDivider;
25
25
  var Item: typeof DropdownMenuItem;
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useCallback, useState } from 'react';
4
- import { Button } from '../Button';
4
+ import { DropdownMenuButtonTrigger } from './DropdownMenuButtonTrigger';
5
5
  import { DropdownMenuContainer } from './DropdownMenuContainer';
6
6
  import { DropdownMenuDivider } from './DropdownMenuDivider';
7
7
  import { DropdownMenuItem } from './DropdownMenuItem';
@@ -27,7 +27,7 @@ import { DropdownMenuHeading } from './DropdownMenuHeading';
27
27
  * </DropdownMenu>
28
28
  * ```
29
29
  */
30
- export function DropdownMenu({ icon, label, children, triggerProps, menuPopoverProps, disabled, targetDOMNode, enableAutoUnmount, onOpenStateChanged, onBlur, }) {
30
+ export function DropdownMenu({ icon, label, children, triggerProps, tooltipLabel, tooltipPlacement, triggerMiddleTruncate, triggerTypographyVariant, menuPopoverProps, disabled, targetDOMNode, enableAutoUnmount, onOpenStateChanged, onBlur, }) {
31
31
  const [menuDefaultFocusPosition, setMenuDefaultFocusPosition] = useState('first');
32
32
  const handleTriggerKeyDownLocal = useCallback((event) => {
33
33
  switch (event.key) {
@@ -49,7 +49,7 @@ export function DropdownMenu({ icon, label, children, triggerProps, menuPopoverP
49
49
  handleTriggerKeyDownLocal(event);
50
50
  handleTriggerKeyDown(event);
51
51
  };
52
- return icon ? (_jsx(IconButton, { ref: setTriggerRef, "aria-expanded": isPopoverOpen, "aria-haspopup": "menu", disabled: disabled, onKeyDown: handleKeyDownCommon, onBlur: handleTriggerBlur, onClick: togglePopover, ...triggerProps, "aria-label": label, children: icon })) : (_jsx(Button, { ref: setTriggerRef, "aria-expanded": isPopoverOpen, "aria-haspopup": "menu", disabled: disabled, onKeyDown: handleKeyDownCommon, onBlur: handleTriggerBlur, onClick: togglePopover, ...triggerProps, isDropdownTrigger: true, children: label }));
52
+ return icon ? (_jsx(IconButton, { ref: setTriggerRef, "aria-expanded": isPopoverOpen, "aria-haspopup": "menu", disabled: disabled, onKeyDown: handleKeyDownCommon, onBlur: handleTriggerBlur, onClick: togglePopover, ...triggerProps, "aria-label": label, children: icon })) : (_jsx(DropdownMenuButtonTrigger, { label: label, tooltipLabel: tooltipLabel, tooltipPlacement: tooltipPlacement, triggerMiddleTruncate: triggerMiddleTruncate, triggerTypographyVariant: triggerTypographyVariant, triggerProps: triggerProps, disabled: disabled, isPopoverOpen: isPopoverOpen, setTriggerRef: setTriggerRef, togglePopover: togglePopover, handleTriggerKeyDown: handleKeyDownCommon, handleTriggerBlur: handleTriggerBlur }));
53
53
  }, renderContent: ({ closePopover }) => (_jsx(DropdownMenuProvider, { value: { closeMenuPopover: closePopover }, children: _jsx(DropdownMenuContainer, { defaultFocusItem: menuDefaultFocusPosition, onClose: closePopover, children: children }) })), enableAutoFocusOnPopover: false, enableAutoUnmount: enableAutoUnmount, contentProps: {
54
54
  className: cx(classes.popover, menuPopoverProps?.className),
55
55
  }, onBlur: onBlur, onOpenStateChanged: onOpenStateChanged }));
@@ -2,6 +2,47 @@ import { type ComponentPropsWithoutRef, type ReactElement, type ReactNode } from
2
2
  import { type ButtonProps } from '../Button';
3
3
  import { type IconButtonProps } from '../IconButton';
4
4
  import { type PopoverProps } from '../Popover';
5
+ import { type TooltipProps } from '../Tooltip';
6
+ import { type TypographyProps } from '../Typography';
7
+ /**
8
+ * The props of the default Button-based trigger that are managed by the DropdownMenu itself
9
+ * (as opposed to `triggerProps`, which is forwarded to the underlying Button).
10
+ *
11
+ * These describe trigger-presentation concerns that the Button cannot express on its own:
12
+ * a describing tooltip and middle truncation of the label.
13
+ */
14
+ export type DropdownMenuButtonTriggerProps = {
15
+ /**
16
+ * The tooltip label describing what the trigger is (e.g. `"事業者"`).
17
+ * Shown on hover/focus and wired to the trigger via `aria-describedby` for screen readers.
18
+ * When omitted, no tooltip is shown.
19
+ */
20
+ tooltipLabel?: string;
21
+ /**
22
+ * The placement of the trigger tooltip (only applied when `tooltipLabel` is set).
23
+ *
24
+ * Accepts a single placement (e.g. `"top"`) for fixed positioning, or an array
25
+ * (e.g. `["top", "bottom"]`) for priority-based positioning with fallbacks.
26
+ * When omitted, the tooltip is placed automatically.
27
+ */
28
+ tooltipPlacement?: TooltipProps['placement'];
29
+ /**
30
+ * Whether the trigger label is middle-truncated (e.g. `"Money…ward"`) when it overflows
31
+ * the available width. When omitted, the label is not truncated by the component.
32
+ *
33
+ * @default false
34
+ */
35
+ triggerMiddleTruncate?: boolean;
36
+ /**
37
+ * The Typography variant of the trigger label. Use this when the label needs a different
38
+ * type style than the default (e.g. `"condensedControlLabel"`).
39
+ *
40
+ * Only applied when `tooltipLabel` or `triggerMiddleTruncate` is set.
41
+ *
42
+ * @default 'controlLabel'
43
+ */
44
+ triggerTypographyVariant?: TypographyProps['variant'];
45
+ };
5
46
  type DropdownMenuCommonProps = {
6
47
  /**
7
48
  * The list of the dropdown menu.
@@ -26,7 +67,7 @@ type DropdownMenuCommonProps = {
26
67
  * If the icon prop is provided, the label prop will be set as the aria-label of the icon button.
27
68
  * If the icon prop is not provided, the label prop will be set as the label of the button.
28
69
  */
29
- label: string;
70
+ label?: string;
30
71
  /**
31
72
  * The properties for the popover content panel.
32
73
  *
@@ -77,7 +118,14 @@ type DropdownMenuCommonProps = {
77
118
  */
78
119
  onBlur?: (event: React.FocusEvent<HTMLElement>) => void;
79
120
  };
80
- type DropdownMenuPropsWithIcon = {
121
+ type DropdownMenuButtonTriggerPropsNever = {
122
+ [K in keyof DropdownMenuButtonTriggerProps]?: undefined;
123
+ };
124
+ type DropdownMenuPropsWithIcon = DropdownMenuButtonTriggerPropsNever & {
125
+ /**
126
+ * The aria-label of the trigger icon button of the dropdown menu.
127
+ */
128
+ label: string;
81
129
  icon: ReactElement;
82
130
  /**
83
131
  * Button component and the IconButton component.
@@ -90,6 +138,10 @@ type DropdownMenuPropsWithIcon = {
90
138
  triggerProps?: Pick<IconButtonProps, 'outlined' | 'className'>;
91
139
  };
92
140
  type DropdownMenuPropsWithoutIcon = {
141
+ /**
142
+ * The label of the trigger button of the dropdown menu.
143
+ */
144
+ label: string;
93
145
  icon?: undefined;
94
146
  /**
95
147
  * Button component and the IconButton component.
@@ -97,9 +149,9 @@ type DropdownMenuPropsWithoutIcon = {
97
149
  * Use this prop if you need to customize the style of the trigger button.
98
150
  *
99
151
  * If the icon prop is not provided, the following props are acceptable as props of the Button component:
100
- * 'size' | 'priority' | 'destructive' | 'leftIcon' | 'loading' | 'className'
152
+ * 'size' | 'priority' | 'destructive' | 'leftIcon' | 'loading' | 'className' | 'isDropdownTrigger'
101
153
  */
102
- triggerProps?: Pick<ButtonProps, 'size' | 'priority' | 'destructive' | 'leftIcon' | 'loading' | 'className'>;
103
- };
154
+ triggerProps?: Pick<ButtonProps, 'size' | 'priority' | 'destructive' | 'leftIcon' | 'loading' | 'className' | 'isDropdownTrigger'>;
155
+ } & DropdownMenuButtonTriggerProps;
104
156
  export type DropdownMenuProps<IconType = undefined> = DropdownMenuCommonProps & (IconType extends ReactElement ? DropdownMenuPropsWithIcon : DropdownMenuPropsWithoutIcon) & Pick<PopoverProps, 'targetDOMNode' | 'enableAutoUnmount'>;
105
157
  export {};
@@ -0,0 +1,46 @@
1
+ import { type FocusEventHandler, type KeyboardEventHandler, type SyntheticEvent } from 'react';
2
+ import { type ButtonProps } from '../Button';
3
+ import { type DropdownMenuButtonTriggerProps } from './DropdownMenu.types';
4
+ type DropdownMenuButtonTriggerComponentProps = DropdownMenuButtonTriggerProps & {
5
+ /**
6
+ * The accessible label / visible text of the trigger button.
7
+ */
8
+ label: string;
9
+ /**
10
+ * Props forwarded to the underlying Button for design customization.
11
+ */
12
+ triggerProps?: Pick<ButtonProps, 'size' | 'priority' | 'destructive' | 'leftIcon' | 'loading' | 'className' | 'isDropdownTrigger'>;
13
+ /**
14
+ * The disabled state of the trigger.
15
+ */
16
+ disabled?: boolean;
17
+ /**
18
+ * The current open state of the dropdown menu, used for `aria-expanded`.
19
+ */
20
+ isPopoverOpen: boolean;
21
+ /**
22
+ * Ref setter for the trigger element so the popover can position itself.
23
+ */
24
+ setTriggerRef: (element: HTMLElement | null) => void;
25
+ /**
26
+ * Toggles the open state of the dropdown menu.
27
+ */
28
+ togglePopover: (event?: SyntheticEvent) => void;
29
+ /**
30
+ * Keyboard handler for the trigger (ArrowUp / ArrowDown focus behavior already merged in).
31
+ */
32
+ handleTriggerKeyDown: KeyboardEventHandler<HTMLElement>;
33
+ /**
34
+ * Blur handler for the trigger with smart blur detection.
35
+ */
36
+ handleTriggerBlur: FocusEventHandler<HTMLElement>;
37
+ };
38
+ /**
39
+ * The default Button-based trigger of the DropdownMenu.
40
+ *
41
+ * On top of the plain Button trigger, it wires up the optional trigger features that are owned by
42
+ * the DropdownMenu rather than the Button: a describing tooltip (`tooltipLabel`) and middle
43
+ * truncation of the label (`triggerMiddleTruncate`). Design customization stays on `triggerProps`.
44
+ */
45
+ export declare function DropdownMenuButtonTrigger({ label, tooltipLabel, tooltipPlacement, triggerMiddleTruncate, triggerTypographyVariant, triggerProps, disabled, isPopoverOpen, setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur, }: DropdownMenuButtonTriggerComponentProps): import("react/jsx-runtime").JSX.Element;
46
+ export {};
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useRef } from 'react';
4
+ import { Button } from '../Button';
5
+ import { Tooltip } from '../Tooltip';
6
+ import { Typography } from '../Typography';
7
+ import { useMiddleTruncatedText } from '../utilities/dom/useMiddleTruncatedText';
8
+ const TRUNCATED_LABEL_STYLE = {
9
+ overflow: 'hidden',
10
+ textOverflow: 'ellipsis',
11
+ whiteSpace: 'nowrap',
12
+ flex: '1 0 0',
13
+ minWidth: '1px',
14
+ color: 'inherit',
15
+ };
16
+ // The tooltip wraps the trigger Button (so focus on the button bubbles up to the tooltip and shows
17
+ // it on keyboard focus). The wrapper must not shrink the full-width trigger, hence `width: 100%`.
18
+ const TOOLTIP_WRAPPER_STYLE = {
19
+ display: 'flex',
20
+ minWidth: 0,
21
+ };
22
+ /**
23
+ * The default Button-based trigger of the DropdownMenu.
24
+ *
25
+ * On top of the plain Button trigger, it wires up the optional trigger features that are owned by
26
+ * the DropdownMenu rather than the Button: a describing tooltip (`tooltipLabel`) and middle
27
+ * truncation of the label (`triggerMiddleTruncate`). Design customization stays on `triggerProps`.
28
+ */
29
+ export function DropdownMenuButtonTrigger({ label, tooltipLabel, tooltipPlacement, triggerMiddleTruncate = false, triggerTypographyVariant = 'controlLabel', triggerProps, disabled, isPopoverOpen, setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur, }) {
30
+ const labelRef = useRef(null);
31
+ // The ref is only attached when middle truncation is enabled, so the hook is a no-op otherwise.
32
+ const truncatedLabel = useMiddleTruncatedText(label, labelRef);
33
+ const sharedButtonProps = {
34
+ ref: setTriggerRef,
35
+ 'aria-expanded': isPopoverOpen,
36
+ 'aria-haspopup': 'menu',
37
+ disabled,
38
+ onKeyDown: handleTriggerKeyDown,
39
+ onBlur: handleTriggerBlur,
40
+ onClick: togglePopover,
41
+ };
42
+ // The label needs custom rendering (Typography / truncation span) only when one of the managed
43
+ // trigger features is requested. Otherwise the plain string label is passed to the Button,
44
+ // preserving the existing default-trigger behavior.
45
+ const needsCustomLabel = tooltipLabel != null || triggerMiddleTruncate;
46
+ if (!needsCustomLabel) {
47
+ return (_jsx(Button, { isDropdownTrigger: true, ...sharedButtonProps, ...triggerProps, children: label }));
48
+ }
49
+ const trigger = (_jsx(Button, { isDropdownTrigger: true, ...sharedButtonProps, ...triggerProps, "aria-label": label, children: _jsx(Typography, { variant: triggerTypographyVariant, style: TRUNCATED_LABEL_STYLE, children: triggerMiddleTruncate ? _jsx("span", { ref: labelRef, children: truncatedLabel }) : label }) }));
50
+ if (tooltipLabel == null) {
51
+ return trigger;
52
+ }
53
+ // Wrap the trigger (not its inner label) so the tooltip opens on keyboard focus of the button and
54
+ // its content is wired to the button via `aria-describedby` automatically by the Tooltip.
55
+ return (_jsx(Tooltip, { content: tooltipLabel, placement: tooltipPlacement, style: TOOLTIP_WRAPPER_STYLE, children: trigger }));
56
+ }
@@ -295,10 +295,15 @@ placeholder, emptyMessage, disabled, invalid, targetDOMNode, name, onChange, val
295
295
  tabbableOptionIndex,
296
296
  ]);
297
297
  // Render infinite scroll error message with retry button
298
- const renderInfiniteScrollError = useCallback(() => infiniteScrollError ? (_jsxs("li", { className: cx(classes.infiniteScrollError, 'mfui-MultipleSelectBox__infiniteScrollError'), role: "alert", children: [_jsxs("div", { className: cx(classes.infiniteScrollErrorMessage, 'mfui-MultipleSelectBox__infiniteScrollErrorMessage'), "aria-live": "polite", children: [_jsx(Error, { "aria-hidden": true, className: cx(classes.infiniteScrollErrorIcon, 'mfui-MultipleSelectBox__infiniteScrollErrorIcon') }), _jsx(Typography, { variant: "body", children: infiniteScrollErrorMessage })] }), _jsx("div", { className: cx(classes.infiniteScrollErrorButton, 'mfui-MultipleSelectBox__infiniteScrollErrorButton'), children: _jsx(Button, { size: "small", onClick: (event) => {
299
- event.stopPropagation();
300
- retryInfiniteScroll();
301
- }, children: infiniteScrollRetryButtonText }) })] })) : null, [
298
+ const renderInfiniteScrollError = useCallback((as = 'li') => {
299
+ if (!infiniteScrollError)
300
+ return null;
301
+ const Tag = as;
302
+ return (_jsxs(Tag, { className: cx(classes.infiniteScrollError, 'mfui-MultipleSelectBox__infiniteScrollError'), role: "alert", children: [_jsxs("div", { className: cx(classes.infiniteScrollErrorMessage, 'mfui-MultipleSelectBox__infiniteScrollErrorMessage'), "aria-live": "polite", children: [_jsx(Error, { "aria-hidden": true, className: cx(classes.infiniteScrollErrorIcon, 'mfui-MultipleSelectBox__infiniteScrollErrorIcon') }), _jsx(Typography, { variant: "body", children: infiniteScrollErrorMessage })] }), _jsx("div", { className: cx(classes.infiniteScrollErrorButton, 'mfui-MultipleSelectBox__infiniteScrollErrorButton'), children: _jsx(Button, { size: "small", onClick: (event) => {
303
+ event.stopPropagation();
304
+ retryInfiniteScroll();
305
+ }, children: infiniteScrollRetryButtonText }) })] }));
306
+ }, [
302
307
  infiniteScrollError,
303
308
  classes.infiniteScrollError,
304
309
  classes.infiniteScrollErrorIcon,
@@ -317,26 +322,29 @@ placeholder, emptyMessage, disabled, invalid, targetDOMNode, name, onChange, val
317
322
  : (selectedCountProps?.render?.(localSelectedValuesSet.size) ??
318
323
  `${String(localSelectedValuesSet.size)}件選択中`) })) : null;
319
324
  const applyControlsNode = enableApplyControls ? (_jsxs(HStack, { gap: "horizontal.0-1of2", children: [_jsx(Button, { ref: cancelButtonRef, size: "small", priority: "secondary", onClick: handleCancelButtonClick, children: cancelButtonProps?.label ?? 'キャンセル' }), _jsx(Button, { ref: applyButtonRef, size: "small", priority: "primary", onClick: handleApplyButtonClick, children: applyButtonProps?.label ?? '適用' })] })) : null;
320
- const optionsNode = (_jsx("div", { ref: scrollWrapperRef, className: cx(classes.scrollWrapper, 'mfui-MultipleSelectBox__scrollWrapper'), onScroll: enableInfiniteScroll ? handleInfiniteScroll : undefined, children: _jsx("ul", { ref: listBoxRef, role: "listbox", id: listBoxId, className: cx(classes.listBox, 'mfui-MultipleSelectBox__listBox'), tabIndex: -1, style: isVirtualized && totalSize > 0
321
- ? {
322
- height: `${String(totalSize)}px`,
323
- position: 'relative',
324
- }
325
- : undefined, children: loading
326
- ? Array.from({ length: SKELETON_ITEM_COUNT }).map((_, index) => (_jsx("li", { className: cx(classes.skeletonItem, 'mfui-MultipleSelectBox__skeletonItem'), children: _jsx(Skeleton, {}) }, index)))
327
- : isVirtualized && virtualItems.length > 0
328
- ? // Virtualized rendering with group support
329
- [...renderVirtualizedItems(), renderInfiniteScrollLoading(), renderInfiniteScrollError()].filter(Boolean)
330
- : filteredOptions.length > 0
331
- ? [...renderNonVirtualizedItems(), renderInfiniteScrollLoading(), renderInfiniteScrollError()].filter(Boolean)
332
- : [
333
- _jsx("li", { className: cx(classes.emptyMessage, 'mfui-MultipleSelectBox__emptyMessage'), children: _jsx(Typography, { variant: "body", children: enableSearchOptions && searchText && notFoundMessage
334
- ? notFoundMessage
335
- : options.length > 0
325
+ const optionsNode = (_jsxs("div", { ref: scrollWrapperRef, className: cx(classes.scrollWrapper, 'mfui-MultipleSelectBox__scrollWrapper'), onScroll: enableInfiniteScroll ? handleInfiniteScroll : undefined, children: [_jsx("ul", { ref: listBoxRef, role: "listbox", id: listBoxId, className: cx(classes.listBox, 'mfui-MultipleSelectBox__listBox'), tabIndex: -1, style: isVirtualized && totalSize > 0
326
+ ? {
327
+ height: `${String(totalSize)}px`,
328
+ position: 'relative',
329
+ }
330
+ : undefined, children: loading
331
+ ? Array.from({ length: SKELETON_ITEM_COUNT }).map((_, index) => (_jsx("li", { className: cx(classes.skeletonItem, 'mfui-MultipleSelectBox__skeletonItem'), children: _jsx(Skeleton, {}) }, index)))
332
+ : isVirtualized && virtualItems.length > 0
333
+ ? renderVirtualizedItems()
334
+ : filteredOptions.length > 0
335
+ ? [
336
+ ...renderNonVirtualizedItems(),
337
+ !isVirtualized && renderInfiniteScrollLoading(),
338
+ !isVirtualized && renderInfiniteScrollError(),
339
+ ].filter(Boolean)
340
+ : [
341
+ _jsx("li", { className: cx(classes.emptyMessage, 'mfui-MultipleSelectBox__emptyMessage'), children: _jsx(Typography, { variant: "body", children: enableSearchOptions && searchText && notFoundMessage
336
342
  ? notFoundMessage
337
- : emptyMessage }) }, "empty"),
338
- renderInfiniteScrollError(),
339
- ].filter(Boolean) }) }));
343
+ : options.length > 0
344
+ ? notFoundMessage
345
+ : emptyMessage }) }, "empty"),
346
+ !isVirtualized && renderInfiniteScrollError(),
347
+ ].filter(Boolean) }), isVirtualized ? renderInfiniteScrollLoading() : null, isVirtualized ? renderInfiniteScrollError('div') : null] }));
340
348
  const createOptionAreaNode = isCreateOptionVisible ? (_jsxs("div", { className: cx(classes.createOptionArea, 'mfui-MultipleSelectBox__createOptionArea'), children: [_jsxs("button", { "data-mfui-content": "create-new-option", type: "button", className: cx(classes.createOptionButton, 'mfui-MultipleSelectBox__createOptionButton'), disabled: isCreating, onClick: handleCreateOption, children: [_jsx(Add, { "aria-hidden": true }), createOptionProps?.renderLabel?.(searchText.trim()) ?? (_jsxs(_Fragment, { children: [_jsx(Typography, { variant: "strongBody", children: searchText.trim() }), _jsx(Typography, { variant: "body", children: "\u3092\u8FFD\u52A0" })] }))] }), createError ? (_jsx("div", { className: cx(classes.createOptionErrorMessage, 'mfui-MultipleSelectBox__createOptionErrorMessage'), children: _jsx(HelpMessage, { messageType: "error", children: createOptionProps?.renderErrorMessage?.(searchText.trim()) ??
341
349
  `${searchText.trim()}を追加できませんでした。` }) })) : null] })) : null;
342
350
  return (_jsx(Popover, { renderTrigger: ({ setTriggerRef, togglePopover, handleTriggerKeyDown, handleTriggerBlur }) => (_jsx(MultipleSelectBoxTrigger, { ref: triggerRef, wrapperRef: setTriggerRef, selectedOptions: localSelectedOptions, id: id, disabled: disabled, triggerProps: triggerProps, triggerWrapperProps: triggerWrapperProps, name: name,
@@ -284,10 +284,15 @@ export const SelectBox = forwardRef((props, ref) => {
284
284
  ? notFoundMessage
285
285
  : emptyMessage }) }, "empty-message")), [classes.emptyMessage, enableSearchOptions, searchText, notFoundMessage, options.length, emptyMessage]);
286
286
  // Render infinite scroll error message with retry button
287
- const renderInfiniteScrollError = useCallback(() => infiniteScrollError ? (_jsxs("li", { className: cx(classes.infiniteScrollError, 'mfui-SelectBox__infiniteScrollError'), role: "alert", children: [_jsxs("div", { className: cx(classes.infiniteScrollErrorMessage, 'mfui-SelectBox__infiniteScrollErrorMessage'), "aria-live": "polite", children: [_jsx(Error, { "aria-hidden": true, className: cx(classes.infiniteScrollErrorIcon, 'mfui-SelectBox__infiniteScrollErrorIcon') }), _jsx(Typography, { variant: "body", children: infiniteScrollErrorMessage })] }), _jsx("div", { className: cx(classes.infiniteScrollErrorButton, 'mfui-SelectBox__infiniteScrollErrorButton'), children: _jsx(Button, { size: "small", onClick: (event) => {
288
- event.stopPropagation();
289
- retryInfiniteScroll();
290
- }, children: infiniteScrollRetryButtonText }) })] }, "infinite-scroll-error")) : null, [
287
+ const renderInfiniteScrollError = useCallback((as = 'li') => {
288
+ if (!infiniteScrollError)
289
+ return null;
290
+ const Tag = as;
291
+ return (_jsxs(Tag, { className: cx(classes.infiniteScrollError, 'mfui-SelectBox__infiniteScrollError'), role: "alert", children: [_jsxs("div", { className: cx(classes.infiniteScrollErrorMessage, 'mfui-SelectBox__infiniteScrollErrorMessage'), "aria-live": "polite", children: [_jsx(Error, { "aria-hidden": true, className: cx(classes.infiniteScrollErrorIcon, 'mfui-SelectBox__infiniteScrollErrorIcon') }), _jsx(Typography, { variant: "body", children: infiniteScrollErrorMessage })] }), _jsx("div", { className: cx(classes.infiniteScrollErrorButton, 'mfui-SelectBox__infiniteScrollErrorButton'), children: _jsx(Button, { size: "small", onClick: (event) => {
292
+ event.stopPropagation();
293
+ retryInfiniteScroll();
294
+ }, children: infiniteScrollRetryButtonText }) })] }, "infinite-scroll-error"));
295
+ }, [
291
296
  infiniteScrollError,
292
297
  classes.infiniteScrollError,
293
298
  classes.infiniteScrollErrorIcon,
@@ -299,19 +304,22 @@ export const SelectBox = forwardRef((props, ref) => {
299
304
  ]);
300
305
  // Render infinite scroll loading indicator
301
306
  const renderInfiniteScrollLoading = useCallback(() => isInfiniteScrollLoading && enableInfiniteScroll ? (_jsx("div", { className: cx(classes.infiniteScrollLoading, 'mfui-SelectBox__infiniteScrollLoading'), children: _jsx(ProgressIndicator, {}) }, "infinite-scroll-loading")) : null, [isInfiniteScrollLoading, enableInfiniteScroll, classes.infiniteScrollLoading]);
302
- const optionsNode = (_jsx("div", { ref: scrollWrapperRef, className: cx(classes.scrollWrapper, 'mfui-SelectBox__scrollWrapper'), onScroll: enableInfiniteScroll ? handleInfiniteScroll : undefined, children: _jsx("ul", { role: "listbox", id: listBoxId, className: cx(classes.listBox, 'mfui-SelectBox__listBox'), tabIndex: -1, style: isVirtualized
303
- ? {
304
- height: `${String(totalSize)}px`,
305
- position: 'relative',
306
- }
307
- : undefined, children: loading
308
- ? Array.from({ length: SKELETON_ITEM_COUNT }).map((_, index) => (_jsx("li", { className: cx(classes.skeletonItem, 'mfui-SelectBox__skeletonItem'), children: _jsx(Skeleton, {}) }, index)))
309
- : isVirtualized && virtualItems.length > 0
310
- ? // Virtualized rendering with group support
311
- [...renderVirtualizedItems(), renderInfiniteScrollLoading(), renderInfiniteScrollError()].filter(Boolean)
312
- : filteredOptions.length > 0
313
- ? [...renderNonVirtualizedItems(), renderInfiniteScrollLoading(), renderInfiniteScrollError()].filter(Boolean)
314
- : [renderEmptyMessage(), renderInfiniteScrollError()].filter(Boolean) }) }));
307
+ const optionsNode = (_jsxs("div", { ref: scrollWrapperRef, className: cx(classes.scrollWrapper, 'mfui-SelectBox__scrollWrapper'), onScroll: enableInfiniteScroll ? handleInfiniteScroll : undefined, children: [_jsx("ul", { role: "listbox", id: listBoxId, className: cx(classes.listBox, 'mfui-SelectBox__listBox'), tabIndex: -1, style: isVirtualized
308
+ ? {
309
+ height: `${String(totalSize)}px`,
310
+ position: 'relative',
311
+ }
312
+ : undefined, children: loading
313
+ ? Array.from({ length: SKELETON_ITEM_COUNT }).map((_, index) => (_jsx("li", { className: cx(classes.skeletonItem, 'mfui-SelectBox__skeletonItem'), children: _jsx(Skeleton, {}) }, index)))
314
+ : isVirtualized && virtualItems.length > 0
315
+ ? renderVirtualizedItems()
316
+ : filteredOptions.length > 0
317
+ ? [
318
+ ...renderNonVirtualizedItems(),
319
+ !isVirtualized && renderInfiniteScrollLoading(),
320
+ !isVirtualized && renderInfiniteScrollError(),
321
+ ].filter(Boolean)
322
+ : [renderEmptyMessage(), !isVirtualized && renderInfiniteScrollError()].filter(Boolean) }), isVirtualized ? renderInfiniteScrollLoading() : null, isVirtualized ? renderInfiniteScrollError('div') : null] }));
315
323
  const handleClearValue = () => {
316
324
  setLocalSelectedOption(null);
317
325
  onChange?.(null);
@@ -0,0 +1,63 @@
1
+ import { type SidebarProps } from './Sidebar.types';
2
+ import { SidebarServiceMenu } from './SidebarServiceMenu';
3
+ import { SidebarTenantMenu } from './SidebarTenantMenu';
4
+ import { SidebarUserMenu } from './SidebarUserMenu';
5
+ import { SidebarNavigationItem } from './SidebarNavigationItem';
6
+ declare function SidebarBase({ className, logoSlot, mainNavigationItems, extraNavigationSlot, footerSlot, serviceMenuSlot, footerIconMenuSlot, tenantSlot, userSlot, minWidth, maxWidth, defaultWidth, onWidthChange, mainNavigationLabel, extraNavigationLabel, resizeHandleLabel, }: SidebarProps): import("react/jsx-runtime").JSX.Element;
7
+ /**
8
+ * The sidebar component.
9
+ * A navigation layout component that combines a logo header, a navigation area,
10
+ * and a footer with icon menu and user information.
11
+ *
12
+ * **EXPERIMENTAL**: This component is experimental and may be changed or removed in the future.
13
+ *
14
+ * The width is resizable via the drag handle on the right edge. See the `WidthPersistence` story for
15
+ * an example of persisting the width across reloads via `onWidthChange` and `defaultWidth`.
16
+ *
17
+ * The following composition components are provided as sub-components:
18
+ * - `Sidebar.NavigationItem` — a single navigation item; `mainNavigationItems` renders these for you,
19
+ * but it can also be used directly inside `extraNavigationSlot`.
20
+ * - `Sidebar.ServiceMenu` — the footer service menu trigger, intended to wrap a list of services.
21
+ * - `Sidebar.TenantMenu` — the footer tenant (business) name and its menu.
22
+ * - `Sidebar.UserMenu` — the footer user (account) name and its menu.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <Sidebar
27
+ * logoSlot={<YourLogo />}
28
+ * defaultWidth={savedWidth}
29
+ * onWidthChange={(width) => persistWidth(width)}
30
+ * mainNavigationItems={[
31
+ * { label: 'Home', icon: <HomeIcon />, href: '/', isCurrent: true },
32
+ * { label: 'Search', icon: <SearchIcon />, onClick: handleSearch },
33
+ * ]}
34
+ * serviceMenuSlot={
35
+ * <Sidebar.ServiceMenu label="サービス" icon={<ApplicationsIcon />}>
36
+ * <DropdownMenu.Item href="https://example.com">マイページ</DropdownMenu.Item>
37
+ * </Sidebar.ServiceMenu>
38
+ * }
39
+ * footerIconMenuSlot={<YourIconButtons />}
40
+ * tenantSlot={
41
+ * <Sidebar.TenantMenu name="株式会社サンプル" tooltipLabel="事業者">
42
+ * <DropdownMenu.Item href="https://example.com">事業者設定</DropdownMenu.Item>
43
+ * </Sidebar.TenantMenu>
44
+ * }
45
+ * userSlot={
46
+ * <Sidebar.UserMenu name="山田 太郎" tooltipLabel="アカウント">
47
+ * <DropdownMenu.Item onClick={handleLogout}>ログアウト</DropdownMenu.Item>
48
+ * </Sidebar.UserMenu>
49
+ * }
50
+ * />
51
+ * ```
52
+ */
53
+ export declare const Sidebar: typeof SidebarBase & {
54
+ /** @see {@link SidebarNavigationItem} */
55
+ NavigationItem: typeof SidebarNavigationItem;
56
+ /** @see {@link SidebarServiceMenu} */
57
+ ServiceMenu: typeof SidebarServiceMenu;
58
+ /** @see {@link SidebarTenantMenu} */
59
+ TenantMenu: typeof SidebarTenantMenu;
60
+ /** @see {@link SidebarUserMenu} */
61
+ UserMenu: typeof SidebarUserMenu;
62
+ };
63
+ export {};