UNPKG

6.03 kBTypeScriptView Raw
1import { Component, ReactElement, Ref as ElementRef, ReactNode, ComponentType } from 'react';
2import { createPortal } from 'react-dom';
3import { CSSObject } from '@emotion/serialize';
4
5import { animatedScrollTo, getBoundingClientObj, RectType, getScrollParent, getScrollTop, scrollTo } from '../utils';
6import { borderRadius, colors, spacing } from '../theme';
7import { InnerRef, MenuPlacement, MenuPosition, CommonProps, OptionTypeBase, GroupTypeBase } from '../types';
8
9// ==============================
10// Menu
11// ==============================
12
13// Get Menu Placement
14// ------------------------------
15
16export interface MenuState {
17 placement: 'bottom' | 'top' | null;
18 maxHeight: number;
19}
20export interface PlacementArgs {
21 maxHeight: number;
22 menuEl: ElementRef<any>;
23 minHeight: number;
24 placement: 'bottom' | 'top' | 'auto';
25 shouldScroll: boolean;
26 isFixedPosition: boolean;
27}
28
29export function getMenuPlacement(args: PlacementArgs): MenuState;
30
31// Menu Component
32// ------------------------------
33
34export type MenuProps<
35 OptionType extends OptionTypeBase,
36 IsMulti extends boolean,
37 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
38> = CommonProps<OptionType, IsMulti, GroupType> & {
39 /** The children to be rendered. */
40 children: ReactElement;
41 /** Callback to update the portal after possible flip. */
42 getPortalPlacement: (state: MenuState) => void;
43 /** Props to be passed to the menu wrapper. */
44 innerProps: object;
45 /** Reference to the internal element, consumed by the MenuPlacer component */
46 innerRef: InnerRef;
47 /** Set the maximum height of the menu. */
48 maxMenuHeight: number;
49 /** Set whether the menu should be at the top, at the bottom. The auto options sets it to bottom. */
50 menuPlacement: MenuPlacement;
51 /* The CSS position value of the menu, when "fixed" extra layout management is required */
52 menuPosition: MenuPosition;
53 /** Set the minimum height of the menu. */
54 minMenuHeight: number;
55 /** Set whether the page should scroll to show the menu. */
56 menuShouldScrollIntoView: boolean;
57};
58
59export function menuCSS(state: MenuState): CSSObject;
60
61declare function Menu<
62 OptionType extends OptionTypeBase,
63 IsMulti extends boolean,
64 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
65 // tslint:disable-next-line:no-unnecessary-generics
66>(props: MenuProps<OptionType, IsMulti, GroupType>): ReactElement;
67
68export default Menu;
69
70// ==============================
71// Menu List
72// ==============================
73
74interface MenuListState {
75 /** Set classname for isMulti */
76 isMulti: boolean;
77 /* Set the max height of the Menu component */
78 maxHeight: number;
79}
80
81export interface MenuListProps {
82 /** The children to be rendered. */
83 children: ReactNode;
84 /** Inner ref to DOM Node */
85 innerRef: InnerRef;
86}
87
88// TODO: Remove this and merge it into `MenuListProps` so that naming pattern is adhered to.
89export type MenuListComponentProps<
90 OptionType extends OptionTypeBase,
91 IsMulti extends boolean,
92 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
93> = CommonProps<OptionType, IsMulti, GroupType> & MenuListProps & MenuListState;
94
95export function menuListCSS(state: MenuState): CSSObject;
96export function MenuList<
97 OptionType extends OptionTypeBase,
98 IsMulti extends boolean,
99 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
100 // tslint:disable-next-line:no-unnecessary-generics
101>(props: MenuListComponentProps<OptionType, IsMulti, GroupType>): ReactElement;
102
103// ==============================
104// Menu Notices
105// ==============================
106
107export function noOptionsMessageCSS(): CSSObject;
108export function loadingMessageCSS(): CSSObject;
109
110export type NoticeProps<
111 OptionType extends OptionTypeBase,
112 IsMulti extends boolean,
113 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
114> = CommonProps<OptionType, IsMulti, GroupType> & {
115 /** The children to be rendered. */
116 children: ReactNode;
117 /** Props to be passed on to the wrapper. */
118 innerProps: { [key: string]: any };
119};
120
121export function NoOptionsMessage<
122 OptionType extends OptionTypeBase,
123 IsMulti extends boolean,
124 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
125 // tslint:disable-next-line:no-unnecessary-generics
126>(props: NoticeProps<OptionType, IsMulti, GroupType>): ReactElement;
127// NoOptionsMessage.defaultProps = {
128// children: 'No options',
129// };
130
131export function LoadingMessage<
132 OptionType extends OptionTypeBase,
133 IsMulti extends boolean,
134 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
135 // tslint:disable-next-line:no-unnecessary-generics
136>(props: NoticeProps<OptionType, IsMulti, GroupType>): ReactElement;
137// LoadingMessage.defaultProps = {
138// children: 'Loading...',
139// };
140
141// ==============================
142// Menu Portal
143// ==============================
144
145export type MenuPortalProps<
146 OptionType extends OptionTypeBase,
147 IsMulti extends boolean,
148 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
149> = CommonProps<OptionType, IsMulti, GroupType> & {
150 appendTo: HTMLElement;
151 children: ReactNode; // ideally Menu<MenuProps>
152 controlElement: HTMLElement;
153 menuPlacement: MenuPlacement;
154 menuPosition: MenuPosition;
155};
156interface MenuPortalState {
157 placement: 'bottom' | 'top' | null;
158}
159interface PortalStyleArgs {
160 offset: number;
161 position: MenuPosition;
162 rect: RectType;
163}
164
165export function menuPortalCSS(args: PortalStyleArgs): CSSObject;
166
167export class MenuPortal<
168 OptionType extends OptionTypeBase,
169 IsMulti extends boolean,
170 GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
171> extends Component<MenuPortalProps<OptionType, IsMulti, GroupType>, MenuPortalState> {
172 // callback for occassions where the menu must "flip"
173 getPortalPlacement: (state: MenuState) => void;
174}