UNPKG

2.88 kBTypeScriptView Raw
1/*
2 * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import classNames from "classnames";
18import * as React from "react";
19import { polyfill } from "react-lifecycles-compat";
20
21import { AbstractPureComponent2, Classes, DISPLAYNAME_PREFIX } from "../../common";
22import { HOTKEYS_HOTKEY_CHILDREN } from "../../common/errors";
23import { isElementOfType, isReactChildrenElementOrElements } from "../../common/utils";
24import { H4 } from "../html/html";
25import { Hotkey, IHotkeyProps } from "./hotkey";
26import { IHotkeysProps } from "./hotkeysTypes";
27
28@polyfill
29export class Hotkeys extends AbstractPureComponent2<IHotkeysProps> {
30 public static displayName = `${DISPLAYNAME_PREFIX}.Hotkeys`;
31
32 public static defaultProps = {
33 tabIndex: 0,
34 };
35
36 public render() {
37 if (!isReactChildrenElementOrElements(this.props.children)) {
38 return null;
39 }
40
41 const hotkeys = React.Children.map(
42 this.props.children,
43 (child: React.ReactElement<IHotkeyProps>) => child.props,
44 );
45
46 // sort by group label alphabetically, prioritize globals
47 hotkeys.sort((a, b) => {
48 if (a.global === b.global && a.group && b.group) {
49 return a.group.localeCompare(b.group);
50 }
51 return a.global ? -1 : 1;
52 });
53
54 let lastGroup: string | undefined;
55 const elems = [] as JSX.Element[];
56 for (const hotkey of hotkeys) {
57 const groupLabel = hotkey.group;
58 if (groupLabel !== lastGroup) {
59 elems.push(<H4 key={`group-${elems.length}`}>{groupLabel}</H4>);
60 lastGroup = groupLabel;
61 }
62 elems.push(<Hotkey key={elems.length} {...hotkey} />);
63 }
64 const rootClasses = classNames(Classes.HOTKEY_COLUMN, this.props.className);
65 return <div className={rootClasses}>{elems}</div>;
66 }
67
68 protected validateProps(props: IHotkeysProps & { children: React.ReactNode }) {
69 if (!isReactChildrenElementOrElements(props.children)) {
70 return;
71 }
72
73 React.Children.forEach(props.children, (child: JSX.Element) => {
74 if (!isElementOfType(child, Hotkey)) {
75 throw new Error(HOTKEYS_HOTKEY_CHILDREN);
76 }
77 });
78 }
79}