1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | import { __assign, __decorate, __extends } from "tslib";
|
17 | import classNames from "classnames";
|
18 | import * as React from "react";
|
19 | import { polyfill } from "react-lifecycles-compat";
|
20 | import { AbstractPureComponent2, Classes, Keys } from "../../common";
|
21 | import { DISPLAYNAME_PREFIX } from "../../common/props";
|
22 | import * as Utils from "../../common/utils";
|
23 | import { Tab } from "./tab";
|
24 | import { generateTabPanelId, generateTabTitleId, TabTitle } from "./tabTitle";
|
25 | export var Expander = function () { return React.createElement("div", { className: Classes.FLEX_EXPANDER }); };
|
26 | var TAB_SELECTOR = "." + Classes.TAB;
|
27 |
|
28 |
|
29 | var Tabs = (function (_super) {
|
30 | __extends(Tabs, _super);
|
31 | function Tabs(props) {
|
32 | var _this = _super.call(this, props) || this;
|
33 | _this.tablistElement = null;
|
34 | _this.refHandlers = {
|
35 | tablist: function (tabElement) { return (_this.tablistElement = tabElement); },
|
36 | };
|
37 | _this.handleKeyDown = function (e) {
|
38 | var _a;
|
39 | var focusedElement = (_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(TAB_SELECTOR);
|
40 |
|
41 | if (focusedElement == null) {
|
42 | return;
|
43 | }
|
44 |
|
45 | var enabledTabElements = _this.getTabElements().filter(function (el) { return el.getAttribute("aria-disabled") === "false"; });
|
46 | var focusedIndex = enabledTabElements.indexOf(focusedElement);
|
47 | var direction = _this.getKeyCodeDirection(e);
|
48 | if (focusedIndex >= 0 && direction !== undefined) {
|
49 | e.preventDefault();
|
50 | var length_1 = enabledTabElements.length;
|
51 |
|
52 | var nextFocusedIndex = (focusedIndex + direction + length_1) % length_1;
|
53 | enabledTabElements[nextFocusedIndex].focus();
|
54 | }
|
55 | };
|
56 | _this.handleKeyPress = function (e) {
|
57 | var targetTabElement = e.target.closest(TAB_SELECTOR);
|
58 |
|
59 |
|
60 | if (targetTabElement != null && Keys.isKeyboardClick(e.which)) {
|
61 | e.preventDefault();
|
62 | targetTabElement.click();
|
63 | }
|
64 | };
|
65 | _this.handleTabClick = function (newTabId, event) {
|
66 | var _a, _b;
|
67 | (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, newTabId, _this.state.selectedTabId, event);
|
68 | if (_this.props.selectedTabId === undefined) {
|
69 | _this.setState({ selectedTabId: newTabId });
|
70 | }
|
71 | };
|
72 | _this.renderTabPanel = function (tab) {
|
73 | var _a = tab.props, className = _a.className, panel = _a.panel, id = _a.id, panelClassName = _a.panelClassName;
|
74 | if (panel === undefined) {
|
75 | return undefined;
|
76 | }
|
77 | return (React.createElement("div", { "aria-labelledby": generateTabTitleId(_this.props.id, id), "aria-hidden": id !== _this.state.selectedTabId, className: classNames(Classes.TAB_PANEL, className, panelClassName), id: generateTabPanelId(_this.props.id, id), key: id, role: "tabpanel" }, panel));
|
78 | };
|
79 | _this.renderTabTitle = function (child) {
|
80 | if (isTabElement(child)) {
|
81 | var id = child.props.id;
|
82 | return (React.createElement(TabTitle, __assign({}, child.props, { parentId: _this.props.id, onClick: _this.handleTabClick, selected: id === _this.state.selectedTabId })));
|
83 | }
|
84 | return child;
|
85 | };
|
86 | var selectedTabId = _this.getInitialSelectedTabId();
|
87 | _this.state = { selectedTabId: selectedTabId };
|
88 | return _this;
|
89 | }
|
90 | Tabs.getDerivedStateFromProps = function (_a) {
|
91 | var selectedTabId = _a.selectedTabId;
|
92 | if (selectedTabId !== undefined) {
|
93 |
|
94 | return { selectedTabId: selectedTabId };
|
95 | }
|
96 | return null;
|
97 | };
|
98 | Tabs.prototype.render = function () {
|
99 | var _a, _b;
|
100 | var _c = this.state, indicatorWrapperStyle = _c.indicatorWrapperStyle, selectedTabId = _c.selectedTabId;
|
101 | var tabTitles = React.Children.map(this.props.children, this.renderTabTitle);
|
102 | var tabPanels = this.getTabChildren()
|
103 | .filter(this.props.renderActiveTabPanelOnly ? function (tab) { return tab.props.id === selectedTabId; } : function () { return true; })
|
104 | .map(this.renderTabPanel);
|
105 | var tabIndicator = this.props.animate ? (React.createElement("div", { className: Classes.TAB_INDICATOR_WRAPPER, style: indicatorWrapperStyle },
|
106 | React.createElement("div", { className: Classes.TAB_INDICATOR }))) : null;
|
107 | var classes = classNames(Classes.TABS, (_a = {}, _a[Classes.VERTICAL] = this.props.vertical, _a), this.props.className);
|
108 | var tabListClasses = classNames(Classes.TAB_LIST, (_b = {},
|
109 | _b[Classes.LARGE] = this.props.large,
|
110 | _b));
|
111 | return (React.createElement("div", { className: classes },
|
112 | React.createElement("div", { className: tabListClasses, onKeyDown: this.handleKeyDown, onKeyPress: this.handleKeyPress, ref: this.refHandlers.tablist, role: "tablist" },
|
113 | tabIndicator,
|
114 | tabTitles),
|
115 | tabPanels));
|
116 | };
|
117 | Tabs.prototype.componentDidMount = function () {
|
118 | this.moveSelectionIndicator(false);
|
119 | };
|
120 | Tabs.prototype.componentDidUpdate = function (prevProps, prevState) {
|
121 | if (this.state.selectedTabId !== prevState.selectedTabId) {
|
122 | this.moveSelectionIndicator();
|
123 | }
|
124 | else if (prevState.selectedTabId != null) {
|
125 |
|
126 |
|
127 | var didChildrenChange = !Utils.arraysEqual(this.getTabChildrenProps(prevProps), this.getTabChildrenProps(), Utils.shallowCompareKeys);
|
128 | if (didChildrenChange) {
|
129 | this.moveSelectionIndicator();
|
130 | }
|
131 | }
|
132 | };
|
133 | Tabs.prototype.getInitialSelectedTabId = function () {
|
134 |
|
135 | var _a = this.props, defaultSelectedTabId = _a.defaultSelectedTabId, selectedTabId = _a.selectedTabId;
|
136 | if (selectedTabId !== undefined) {
|
137 | return selectedTabId;
|
138 | }
|
139 | else if (defaultSelectedTabId !== undefined) {
|
140 | return defaultSelectedTabId;
|
141 | }
|
142 | else {
|
143 |
|
144 | var tabs = this.getTabChildren();
|
145 | return tabs.length === 0 ? undefined : tabs[0].props.id;
|
146 | }
|
147 | };
|
148 | Tabs.prototype.getKeyCodeDirection = function (e) {
|
149 | if (isEventKeyCode(e, Keys.ARROW_LEFT, Keys.ARROW_UP)) {
|
150 | return -1;
|
151 | }
|
152 | else if (isEventKeyCode(e, Keys.ARROW_RIGHT, Keys.ARROW_DOWN)) {
|
153 | return 1;
|
154 | }
|
155 | return undefined;
|
156 | };
|
157 | Tabs.prototype.getTabChildrenProps = function (props) {
|
158 | if (props === void 0) { props = this.props; }
|
159 | return this.getTabChildren(props).map(function (child) { return child.props; });
|
160 | };
|
161 |
|
162 | Tabs.prototype.getTabChildren = function (props) {
|
163 | if (props === void 0) { props = this.props; }
|
164 | return React.Children.toArray(props.children).filter(isTabElement);
|
165 | };
|
166 |
|
167 | Tabs.prototype.getTabElements = function (subselector) {
|
168 | if (subselector === void 0) { subselector = ""; }
|
169 | if (this.tablistElement == null) {
|
170 | return [];
|
171 | }
|
172 | return Array.from(this.tablistElement.querySelectorAll(TAB_SELECTOR + subselector));
|
173 | };
|
174 | |
175 |
|
176 |
|
177 |
|
178 | Tabs.prototype.moveSelectionIndicator = function (animate) {
|
179 | if (animate === void 0) { animate = true; }
|
180 | if (this.tablistElement == null || !this.props.animate) {
|
181 | return;
|
182 | }
|
183 | var tabIdSelector = TAB_SELECTOR + "[data-tab-id=\"" + this.state.selectedTabId + "\"]";
|
184 | var selectedTabElement = this.tablistElement.querySelector(tabIdSelector);
|
185 | var indicatorWrapperStyle = { display: "none" };
|
186 | if (selectedTabElement != null) {
|
187 | var clientHeight = selectedTabElement.clientHeight, clientWidth = selectedTabElement.clientWidth, offsetLeft = selectedTabElement.offsetLeft, offsetTop = selectedTabElement.offsetTop;
|
188 | indicatorWrapperStyle = {
|
189 | height: clientHeight,
|
190 | transform: "translateX(" + Math.floor(offsetLeft) + "px) translateY(" + Math.floor(offsetTop) + "px)",
|
191 | width: clientWidth,
|
192 | };
|
193 | if (!animate) {
|
194 | indicatorWrapperStyle.transition = "none";
|
195 | }
|
196 | }
|
197 | this.setState({ indicatorWrapperStyle: indicatorWrapperStyle });
|
198 | };
|
199 |
|
200 | Tabs.Expander = Expander;
|
201 | Tabs.Tab = Tab;
|
202 | Tabs.defaultProps = {
|
203 | animate: true,
|
204 | large: false,
|
205 | renderActiveTabPanelOnly: false,
|
206 | vertical: false,
|
207 | };
|
208 | Tabs.displayName = DISPLAYNAME_PREFIX + ".Tabs";
|
209 | Tabs = __decorate([
|
210 | polyfill
|
211 | ], Tabs);
|
212 | return Tabs;
|
213 | }(AbstractPureComponent2));
|
214 | export { Tabs };
|
215 | function isEventKeyCode(e) {
|
216 | var codes = [];
|
217 | for (var _i = 1; _i < arguments.length; _i++) {
|
218 | codes[_i - 1] = arguments[_i];
|
219 | }
|
220 |
|
221 |
|
222 | return codes.indexOf(e.which) >= 0;
|
223 | }
|
224 | function isTabElement(child) {
|
225 | return Utils.isElementOfType(child, Tab);
|
226 | }
|
227 |
|
\ | No newline at end of file |