react-dyn-tabs
Version:
React dynamic tabs with full API
1,391 lines (1,354 loc) • 48.6 kB
JavaScript
/**
* react-dyn-tabs - React dynamic tabs with full API
*
* @version v6.2.2
* @homepage https://dev-javascript.github.io/react-dyn-tabs/
* @author dev-javascript javascript.code.dev@gmail.com
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react'), require('prop-types')) :
typeof define === 'function' && define.amd ? define(['react', 'prop-types'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.useDynTabs = factory(global.React));
})(this, (function (React) { 'use strict';
var actions = {
open: 'open',
close: 'close',
active: 'active',
refresh: 'refresh',
sort: 'sort'
};
var counter = 1;
var helper = {
checkArrIndex: function checkArrIndex(index, arrLength) {
return index >= 0 && index < arrLength;
},
resolve: function resolve(result) {
return Promise.resolve(result);
},
getCopyState: function getCopyState(state) {
return {
selectedTabID: state.selectedTabID,
openTabIDs: (state.openTabIDs || []).slice()
};
},
assingAll: function assingAll(targetObj) {
for (var _len = arguments.length, sourcObjs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
sourcObjs[_key - 1] = arguments[_key];
}
// copy all enumerable and not enumerable properties into the target
sourcObjs.forEach(function (sourcObj) {
var enum_only = Object.keys(sourcObj);
Object.getOwnPropertyNames(sourcObj).forEach(function (prop) {
if (enum_only.indexOf(prop) >= 0) targetObj[prop] = sourcObj[prop];else Object.defineProperty(targetObj, prop, {
value: sourcObj[prop],
writable: true
});
});
});
return targetObj;
},
setNoneEnumProps: function setNoneEnumProps(obj, props) {
var noneEnum = {};
Object.keys(props).forEach(function (prop) {
noneEnum[prop] = {
writable: true,
value: props[prop]
};
});
return Object.defineProperties(obj, noneEnum);
},
getArraysDiff: function getArraysDiff(arr1, arr2) {
var arr1Copy = [].concat(arr1),
arr2Copy = [].concat(arr2);
arr1.forEach(function (item) {
if (arr2.indexOf(item) >= 0) {
arr1Copy.splice(arr1Copy.indexOf(item), 1);
arr2Copy.splice(arr2Copy.indexOf(item), 1);
}
});
return [arr1Copy, arr2Copy];
},
filterArrayUntilFirstValue: function filterArrayUntilFirstValue(arr, callback, isRightToLeft) {
isRightToLeft && arr.reverse();
for (var i = 0, l = arr.length; i < l; i++) {
if (callback(arr[i], i, arr)) return arr[i];
}
return null;
},
throwMissingParam: function throwMissingParam(FnName) {
throw new Error("Missing parameter in \"" + FnName + "\" function");
},
thorwInvalidParam: function thorwInvalidParam(FnName) {
throw new Error("Invalid parameter values passed to " + FnName + " function");
},
isObj: function isObj(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
},
isArray: function isArray(arr) {
return typeof arr === 'object' && arr.constructor === Array;
},
module: function module(fn, obj, noneEnums) {
return this.assingAll(fn.prototype, noneEnums ? this.setNoneEnumProps(obj, noneEnums) : obj).constructor;
},
uuid: function uuid() {
counter++;
return "" + new Date().getTime() + Math.random() + counter;
}
};
function reducer(state, action) {
switch (action.type) {
case actions.close:
{
var arr = state.openTabIDs,
removedItemIndex = arr.indexOf(action.tabId);
if (removedItemIndex >= 0) {
var newArr = arr.slice();
newArr.splice(removedItemIndex, 1);
return {
selectedTabID: state.selectedTabID,
openTabIDs: newArr
};
}
return state;
}
case actions.open:
{
var _arr = state.openTabIDs,
tabId = action.tabId;
if (_arr.indexOf(tabId) === -1) {
var _newArr = _arr.slice();
_newArr.push(tabId);
return {
selectedTabID: state.selectedTabID,
openTabIDs: _newArr
};
}
return state;
}
case actions.refresh:
return helper.getCopyState(state);
case actions.active:
{
var _tabId = action.tabId;
if (state.selectedTabID !== _tabId) return {
selectedTabID: _tabId,
openTabIDs: state.openTabIDs
};
return state;
}
case actions.sort:
{
var _arr2 = state.openTabIDs,
_newArr2 = action.tabId,
newArrCount = _newArr2.length;
if (_arr2.length !== newArrCount) return state;
for (var i = 0; i < newArrCount; i++) {
if (_arr2.indexOf(_newArr2[i]) === -1) return state;
}
return {
selectedTabID: state.selectedTabID,
openTabIDs: _newArr2
};
}
default:
throw new Error("Undefined action type '" + action.type + "'");
}
}
var missingParamEr$1 = helper.throwMissingParam,
isArray = helper.isArray,
thorwInvalidParam = helper.thorwInvalidParam;
var apiConstructor = function apiConstructor(getDeps, param, modules, Components) {
var _this = this;
if (param === void 0) {
param = {
options: {}
};
}
if (modules === void 0) {
modules = [];
}
var _getDeps$call = getDeps.call(this, param.options),
optionsManager = _getDeps$call.optionsManager,
helper = _getDeps$call.helper,
activedTabsHistory = _getDeps$call.activedTabsHistory;
helper.setNoneEnumProps(this, {
optionsManager: optionsManager,
helper: helper,
activedTabsHistory: activedTabsHistory,
userProxy: {}
});
this._setUserProxy()._subscribeOnReadyEvent()._createReadyFunction()._subscribeSelectedTabsHistory()._subscribeCallbacksOptions();
modules.forEach(function (module) {
return module(_this, Components);
});
};
var _apiProps = {
_setUserProxy: function _setUserProxy() {
var _this2 = this;
var userProxy = {};
var _loop = function _loop(prop) {
if (prop[0] !== '_' && prop !== 'constructor') {
(function (that) {
var propValue = that[prop];
if (typeof propValue === 'function') {
userProxy[prop] = function () {
var result = propValue.apply(that, arguments);
return result === that ? userProxy : result;
};
} else {
userProxy[prop] = propValue;
}
})(_this2);
}
};
for (var prop in this) {
_loop(prop);
}
this.userProxy = userProxy;
return this;
},
_subscribeOnReadyEvent: function _subscribeOnReadyEvent() {
var _this3 = this;
this.one('_onReady', function () {
_this3._isReady = true;
});
return this;
},
_createReadyFunction: function _createReadyFunction() {
var _this4 = this;
var ready = function ready(fn) {
if (_this4._isReady === true) {
fn.call(_this4.userProxy, _this4.userProxy);
} else {
_this4.one('_onReady', function () {
fn.call(_this4.userProxy, _this4.userProxy);
});
}
};
ready = ready.bind(this);
this.helper.setNoneEnumProps(this, {
ready: ready
});
return this;
},
_subscribeSelectedTabsHistory: function _subscribeSelectedTabsHistory() {
var _this5 = this;
this.on('onChange', function (_ref) {
var currentData = _ref.currentData,
previousData = _ref.previousData,
closedTabIDs = _ref.closedTabIDs;
for (var i = 0, l = closedTabIDs.length; i < l; i++) {
_this5.activedTabsHistory.remove(closedTabIDs[i]);
}
var isSwitched = previousData.selectedTabID !== currentData.selectedTabID;
if (isSwitched && _this5.isOpen(previousData.selectedTabID) && !_this5.isSelected(previousData.selectedTabID)) _this5.activedTabsHistory.add(previousData.selectedTabID);
});
return this;
},
_subscribeCallbacksOptions: function _subscribeCallbacksOptions() {
var _this6 = this;
var op = this.optionsManager.options;
Object.keys(this._publishers).forEach(function (eventName) {
if (eventName[0] !== '_') _this6.on(eventName, function () {
op[eventName].apply(this, arguments);
});
});
return this;
},
getOption: function getOption(name) {
return this.optionsManager.getOption(name);
},
setOption: function setOption(name, value) {
this.optionsManager.setOption(name, value);
return this;
},
getPreviousData: function getPreviousData() {
return this.helper.getCopyState(this.previousState);
},
getCopyPerviousData: function getCopyPerviousData() {
return this.getPreviousData();
},
getData: function getData() {
return this.helper.getCopyState(this.stateRef);
},
getCopyData: function getCopyData() {
return this.getData();
},
isSelected: function isSelected(id) {
if (id === void 0) {
id = missingParamEr$1('isSelected');
}
return this.stateRef.selectedTabID == id;
},
isOpen: function isOpen(id) {
if (id === void 0) {
id = missingParamEr$1('isOpen');
}
return this.stateRef.openTabIDs.indexOf(id) >= 0;
},
_getFlushEffectsPromise: function _getFlushEffectsPromise() {
var _this7 = this;
return new Promise(function (resolve) {
_this7.one('_onFlushEffects', function () {
resolve.apply(this, arguments);
});
});
},
select: function select(id) {
if (id === void 0) {
id = missingParamEr$1('select');
}
if (id) id = id + ''; //make sure id is string
var result = this._getFlushEffectsPromise();
this._select(id);
return result;
},
_getPreSelectedTabId: function _getPreSelectedTabId() {
var selectedTabHistory = [].concat(this.activedTabsHistory.tabsId);
var tabID = '';
while (!tabID && selectedTabHistory.length) {
var _tabID = selectedTabHistory.pop();
if (_tabID) {
var _tabData = this.getTab(_tabID);
if (_tabData && !_tabData.disable && this.isOpen(_tabID) && !this.isSelected(_tabID)) tabID = _tabID;
}
}
return tabID;
},
_getPreSiblingTabId: function _getPreSiblingTabId() {
var _this8 = this;
var _this$stateRef = this.stateRef,
selectedTabID = _this$stateRef.selectedTabID,
openTabIDs = _this$stateRef.openTabIDs;
var isRightToLeft = true;
var arr = openTabIDs.slice(0, openTabIDs.indexOf(selectedTabID));
return this.helper.filterArrayUntilFirstValue(arr, function (id) {
return !_this8.getTab(id).disable;
}, isRightToLeft);
},
_getNextSiblingTabId: function _getNextSiblingTabId() {
var _this9 = this;
var _this$stateRef2 = this.stateRef,
selectedTabID = _this$stateRef2.selectedTabID,
openTabIDs = _this$stateRef2.openTabIDs;
var isRightToLeft = false;
var arr = openTabIDs.slice(openTabIDs.indexOf(selectedTabID) + 1);
return this.helper.filterArrayUntilFirstValue(arr, function (id) {
return !_this9.getTab(id).disable;
}, isRightToLeft);
},
_findTabIdForSwitching: function _findTabIdForSwitching() {
var tabId = '';
tabId = this._getPreSelectedTabId();
tabId = tabId || this._getPreSiblingTabId();
tabId = tabId || this._getNextSiblingTabId();
return tabId || '';
},
setTab: function setTab(id, newData) {
if (newData === void 0) {
newData = {};
}
this.optionsManager.validateObjectiveTabData(newData).validatePanelComponent(newData);
this._setTab(id, newData);
return this;
},
open: function open(tabObj) {
if (tabObj === void 0) {
tabObj = missingParamEr$1('open');
}
var newTabObj = this.optionsManager.validateTabData(tabObj);
var result = this._getFlushEffectsPromise();
this._addTab(newTabObj);
this._open(newTabObj.id);
return result;
},
sort: function sort(tabIDs) {
if (tabIDs === void 0) {
tabIDs = missingParamEr$1('sort');
}
if (!isArray(tabIDs)) {
thorwInvalidParam('sort');
}
var result = this._getFlushEffectsPromise();
this._sort(tabIDs);
return result;
},
__close: function __close(id) {
var result = this._getFlushEffectsPromise();
this._close(id);
this._removeTab(id);
return result;
},
close: function close(id, switching) {
if (id === void 0) {
id = missingParamEr$1('close');
}
if (switching === void 0) {
switching = true;
}
if (id) id = id + ''; //make sure id is string
if (switching && this.isOpen(id) && this.isSelected(id)) {
var _openTabsId = [].concat(this.stateRef.openTabIDs);
_openTabsId.splice(_openTabsId.indexOf(id), 1);
this.select(this._findTabIdForSwitching());
return this.__close(id);
} else return this.__close(id);
},
refresh: function refresh() {
var result = this._getFlushEffectsPromise();
this._refresh();
return result;
}
};
helper.setNoneEnumProps(_apiProps, {
onChange: function onChange(_ref2) {
var _this10 = this;
var newState = _ref2.newState,
oldState = _ref2.oldState,
closedTabIDs = _ref2.closedTabIDs,
openedTabIDs = _ref2.openedTabIDs,
isSwitched = _ref2.isSwitched;
if (isSwitched || openedTabIDs.length || closedTabIDs.length) {
this.trigger('onChange', this.userProxy, function () {
return [{
currentData: _this10.helper.getCopyState(newState),
previousData: _this10.helper.getCopyState(oldState),
closedTabIDs: closedTabIDs.slice(),
openedTabIDs: openedTabIDs.slice()
}];
});
openedTabIDs.length && this.trigger('onOpen', this.userProxy, function () {
return [openedTabIDs.slice()];
});
closedTabIDs.length && this.trigger('onClose', this.userProxy, function () {
return [closedTabIDs.slice()];
});
if (isSwitched) {
if (newState.selectedTabID && this.activedTabsHistory.tabsId.indexOf(newState.selectedTabID) === -1) {
this.trigger('onFirstSelect', this.userProxy, function () {
return [{
currentSelectedTabId: newState.selectedTabID,
previousSelectedTabId: oldState.selectedTabID
}];
});
}
this.trigger('onSelect', this.userProxy, function () {
return [{
currentSelectedTabId: newState.selectedTabID,
previousSelectedTabId: oldState.selectedTabID
}];
});
}
}
return this;
},
eventHandlerFactory: function eventHandlerFactory(_ref3) {
var e = _ref3.e,
id = _ref3.id;
var el = e.target,
parentEl = el.parentElement,
_this$optionsManager$ = this.optionsManager.setting,
closeClass = _this$optionsManager$.closeClass,
tabClass = _this$optionsManager$.tabClass;
if (el.className.includes(closeClass) && parentEl && parentEl.lastChild && parentEl.lastChild == el && parentEl.className.includes(tabClass)) {
this.getOption('beforeClose').call(this.userProxy, e, id) !== false && this.close(id, true);
} else {
this.getOption('beforeSelect').call(this.userProxy, e, id) !== false && this.select(id);
}
},
getSetting: function getSetting(settingName) {
var st = this.optionsManager.setting;
if (Object.prototype.hasOwnProperty.call(st, settingName)) {
if (typeof st[settingName] === 'function') {
return st[settingName].apply(st, Array.prototype.slice.call(arguments, 1));
}
return st[settingName];
}
}
});
var apiProps = _apiProps;
function _extends$3() { return _extends$3 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$3.apply(null, arguments); }
var missingParamEr = helper.throwMissingParam,
uuid = helper.uuid;
var factory = helper.module(function (getDeps, _ref) {
var options = _ref.options;
var _getDeps = getDeps(),
globalDefaultOptions = _getDeps.globalDefaultOptions;
this._defaultOptions = globalDefaultOptions;
this._validateOptions(options);
this.options = Object.assign({}, this._defaultOptions, options);
this.setting = {};
this.initialState = {};
this.initialTabs = [];
this._setSetting()._setInitialData();
}, {
getOption: function getOption(optionName) {
if (optionName === 'tabs') {
// returned result should be immutable
var arr = [];
for (var i = 0, tabs = this.options.tabs, l = tabs.length; i < l; i++) {
arr.push(_extends$3({}, tabs[i]));
}
return arr;
}
return this.options[optionName];
},
setOption: function setOption(name, value) {
if (name === void 0) {
name = missingParamEr('setOption');
}
if (value === void 0) {
value = missingParamEr('setOption');
}
if (['SELECTEDTABID', 'TABS'].indexOf(name.toUpperCase()) >= 0) return this;
this.options[name] = value;
return this;
},
validatePanelComponent: function validatePanelComponent(tabData) {
// convert panel element into a function component.
if (tabData.panelComponent && typeof tabData.panelComponent !== 'function' && /*#__PURE__*/React.isValidElement(tabData.panelComponent)) {
var PanelElement = tabData.panelComponent;
tabData.panelComponent = function () {
return PanelElement;
};
}
return this;
},
validateObjectiveTabData: function validateObjectiveTabData(tabData) {
if (Object.prototype.toString.call(tabData) !== '[object Object]') throw new Error('tabData must be type of Object');
return this;
},
validateTabData: function validateTabData(tabData) {
this.validateObjectiveTabData(tabData).validatePanelComponent(tabData);
tabData = Object.assign(this.setting.getDefaultTabData(), tabData);
tabData.id = tabData.id + ''; //make sure id is string
return tabData;
},
_validateOptions: function _validateOptions(options) {
if (Object.prototype.toString.call(options) !== '[object Object]') throw 'Invalid argument in "useDynamicTabs" function. Argument must be type of an object';
return this;
},
_setInitialData: function _setInitialData() {
var _this = this;
// set this.initialTabs and this.initialState
var _this$options = this.options,
selectedTabID = _this$options.selectedTabID,
tabs = _this$options.tabs,
openTabIDs = [];
tabs.forEach(function (tab) {
var newTab = _this.validateTabData(tab);
_this.initialTabs.push(newTab);
openTabIDs.push(newTab.id);
});
this.initialState = {
selectedTabID: selectedTabID + '',
//make sure it is type of string
openTabIDs: openTabIDs
};
return this;
},
_setSetting: function _setSetting() {
var _this2 = this;
this.setting = {
tabClass: 'rc-dyn-tabs-tab',
titleClass: 'rc-dyn-tabs-title',
iconClass: 'rc-dyn-tabs-icon',
selectedClass: 'rc-dyn-tabs-selected',
hoverClass: 'rc-dyn-tabs-hover',
closeClass: 'rc-dyn-tabs-close',
panelClass: 'rc-dyn-tabs-panel',
panellistClass: 'rc-dyn-tabs-panellist',
disableClass: 'rc-dyn-tabs-disable',
ltrClass: 'rc-dyn-tabs-ltr',
rtlClass: 'rc-dyn-tabs-rtl',
verticalClass: 'rc-dyn-tabs-vertical',
tablistViewClass: 'rc-dyn-tabs-tablist-view',
tablistContainerClass: 'rc-dyn-tabs-tablist-container',
tablistOverflowClass: 'rc-dyn-tabs-tablist-overflow',
tablistClass: 'rc-dyn-tabs-tablist',
panelIdTemplate: function panelIdTemplate(id) {
return "rc-dyn-tabs-p-" + id;
},
ariaLabelledbyIdTemplate: function ariaLabelledbyIdTemplate(id) {
return "rc-dyn-tabs-l-" + id;
},
getDefaultTabData: function getDefaultTabData() {
return {
title: '',
tooltip: '',
panelComponent: _this2.options.defaultPanelComponent,
closable: true,
iconClass: '',
disable: false,
lazy: false,
id: "tab_" + uuid()
};
}
};
return this;
}
});
var DefaulTabInner = function DefaulTabInner(props) {
return /*#__PURE__*/React.createElement("button", props.tabProps, props.children, Object.prototype.hasOwnProperty.call(props, 'iconProps') && /*#__PURE__*/React.createElement("span", props.iconProps));
};
/* eslint react/prop-types: 0 */
var DefaultOptions = helper.module(function (DefaulTabInnerComponent) {
if (DefaulTabInnerComponent === void 0) {
DefaulTabInnerComponent = null;
}
this.defaultDirection = 'ltr';
this._DefaulTabInnerComponent = DefaulTabInnerComponent;
this.directionsRange = ['ltr', 'rtl'];
}, {
getOptions: function getOptions() {
return this._getOptions();
},
_getOptions: function _getOptions() {
var _options = {
tabs: [],
selectedTabID: '',
theme: 'all-themes',
tablistStyle: {},
beforeSelect: function beforeSelect() {
return true;
},
beforeClose: function beforeClose() {
return true;
},
onOpen: function onOpen() {},
onClose: function onClose() {},
onFirstSelect: function onFirstSelect() {},
onSelect: function onSelect() {},
onChange: function onChange() {},
onLoad: function onLoad() {},
onDestroy: function onDestroy() {},
onInit: function onInit() {},
accessibility: true,
isVertical: false,
defaultPanelComponent: function defaultPanelComponent() {
return /*#__PURE__*/React.createElement("div", null);
}
};
var _direction = this.defaultDirection,
_tabComponent = this._DefaulTabInnerComponent;
var that = this;
Object.defineProperties(_options, {
direction: {
get: function get() {
return _direction;
},
set: function set(value) {
if (that.directionsRange.indexOf(value) === -1) throw 'Invalid direction value! it can be eather of "ltr" or "rtl" ';
_direction = value;
},
enumerable: true
},
tabComponent: {
get: function get() {
return _tabComponent;
},
set: function set(fn) {
if (fn && typeof fn !== 'function') throw 'tabComponent property must be type of a function.';
_tabComponent = fn ? fn : that._DefaulTabInnerComponent;
},
enumerable: true
}
});
return _options;
}
});
var getDeps$2 = function getDeps() {
var op = new DefaultOptions(DefaulTabInner);
return {
globalDefaultOptions: op.getOptions()
};
};
var OptionManager = factory.bind(null, getDeps$2);
var ActivedTabsHistory = helper.module(function () {
this.tabsId = [];
}, {
reset: function reset() {
this.tabsId = [];
},
add: function add(id) {
if (id) this.tabsId.push(id);
},
remove: function remove(id) {
var tabIDs = this.tabsId;
while (tabIDs.indexOf(id) >= 0) {
tabIDs.splice(tabIDs.indexOf(id), 1);
}
return this;
}
});
var Pub_Sub = helper.module(function () {
this._publishers = {
onChange: [],
onLoad: [],
onDestroy: [],
onOpen: [],
onClose: [],
onSelect: [],
onInit: [],
_onFlushEffects: [],
_onReady: [],
onFirstSelect: []
};
}, {
//unSubscribe
off: function off(publisherName, fn) {
if (typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this._publishers, publisherName)) {
var _index = this._publishers[publisherName].indexOf(fn);
_index >= 0 && this._publishers[publisherName].splice(_index, 1);
}
return this;
},
//subscribe
on: function on(publisherName, fn) {
if (typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this._publishers, publisherName)) {
// check if it has not existed
if (this._publishers[publisherName].indexOf(fn) === -1) {
this._publishers[publisherName].push(fn);
}
}
return this;
},
//oneSubscribe
one: function one(publisherName, fn) {
if (typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this._publishers, publisherName)) {
var _fn = function _fn() {
fn.apply(this, arguments);
this.off(publisherName, _fn);
};
return this.on(publisherName, _fn);
}
return this;
}
}, {
trigger: function trigger(publisherName, context, generateParamsCallback) {
if (generateParamsCallback === void 0) {
generateParamsCallback = function generateParamsCallback() {
return [];
};
}
context = context || null;
var result = [];
var _subscribers = [].concat(this._publishers[publisherName]);
_subscribers.forEach(function (subscriber) {
result.push(subscriber.apply(context, generateParamsCallback()));
});
return result;
}
});
var BaseApi = helper.module(function (_ref) {
var helper = _ref.helper,
initialState = _ref.initialState;
this._helper = helper;
this._dispatch = null;
this._setFlushState = null;
this._isReady = false;
helper.setNoneEnumProps(this, {
state: this._helper.getCopyState(initialState),
// it will be updated after each render
forceUpdateState: {},
previousState: this._helper.getCopyState(initialState),
// it is a previous value of this.state
stateRef: {} // have a same reference with state . It will be updated in each execution of useDynamicTabs.js
});
}, {
_select: function _select(tabId) {
this._dispatch({
type: actions.active,
tabId: tabId
});
this.__flushEffects();
},
_close: function _close(tabId) {
this._dispatch({
type: actions.close,
tabId: tabId
});
this.__flushEffects();
},
_open: function _open(tabId) {
this._dispatch({
type: actions.open,
tabId: tabId
});
this.__flushEffects();
},
_refresh: function _refresh() {
this.forceUpdateState = {};
this._dispatch({
type: actions.refresh
});
this.__flushEffects();
},
_sort: function _sort(tabId) {
this._dispatch({
type: actions.sort,
tabId: tabId
});
this.__flushEffects();
},
__flushEffects: function __flushEffects() {
this._setFlushState({});
}
}, {
updateStateRef: function updateStateRef(state, dispatch) {
this.stateRef = state;
this._dispatch = dispatch;
return this;
},
updateState: function updateState(state) {
this.previousState = this._helper.getCopyState(this.state);
this.state = this._helper.getCopyState(state);
return this;
},
updateFlushState: function updateFlushState(setFlushState) {
this._setFlushState = setFlushState;
return this;
}
});
var Tabs$1 = helper.module(function Tabs(_temp) {
var _this = this;
var _ref = _temp === void 0 ? {
initialTabs: []
} : _temp,
initialTabs = _ref.initialTabs;
this._data = [];
if (initialTabs && initialTabs.constructor === Array && initialTabs.length) {
initialTabs.forEach(function (tab) {
_this._addTab(tab);
});
}
}, {
_addTab: function _addTab(tabObj) {
this._data.push(tabObj);
return this;
},
_removeTab: function _removeTab(id) {
var delIndex = this._data.findIndex(function (tab) {
return tab.id === id;
});
delIndex >= 0 && this._data.splice(delIndex, 1);
return this;
},
getTab: function getTab(id) {
return this._data.find(function (tab) {
return tab.id === id;
});
},
_setTab: function _setTab(id, newData) {
var _index = this._data.findIndex(function (tab) {
return tab.id == id;
});
if (_index >= 0) {
var oldData = this._data[_index];
newData.id = oldData.id; // id can not be changed.
Object.assign(this._data[_index], newData);
}
return this;
}
});
var getDeps$1 = function getDeps(options) {
if (options === void 0) {
options = {};
}
var activedTabsHistory = new ActivedTabsHistory(),
optionsManager = new OptionManager({
options: options
});
BaseApi.call(this, {
helper: helper,
initialState: optionsManager.initialState
});
Tabs$1.call(this, {
initialTabs: optionsManager.initialTabs
});
Pub_Sub.call(this);
return {
activedTabsHistory: activedTabsHistory,
helper: helper,
optionsManager: optionsManager
};
};
apiConstructor.prototype = Object.create(BaseApi.prototype);
var Api = (helper.assingAll(apiConstructor.prototype, Tabs$1.prototype, Pub_Sub.prototype, apiProps).constructor = apiConstructor).bind(null, getDeps$1);
function _extends$2() { return _extends$2 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$2.apply(null, arguments); }
function useDynamicTabs$1(getDeps, options, modules) {
if (options === void 0) {
options = {};
}
var _getDeps = getDeps(),
reducer = _getDeps.reducer,
getApiInstance = _getDeps.getApiInstance,
ApiContext = _getDeps.ApiContext,
StateContext = _getDeps.StateContext,
ForceUpdateContext = _getDeps.ForceUpdateContext,
Components = _getDeps.Components;
var ref = React.useRef(null);
if (ref.current === null) {
ref.current = {
Components: _extends$2({}, Components),
TabListComponent: null,
PanelListComponent: null
};
ref.current.api = getApiInstance(options, modules, ref.current.Components);
}
var api = ref.current.api,
_ref = ref.current,
_useReducer = React.useReducer(reducer, api.optionsManager.initialState),
state = _useReducer[0],
dispatch = _useReducer[1],
_useState = React.useState({}),
flushState = _useState[0],
setFlushState = _useState[1];
api.updateStateRef(state, dispatch).updateFlushState(setFlushState);
React.useLayoutEffect(function () {
api.updateState(state);
}, [state]);
React.useLayoutEffect(function () {
api.trigger('onLoad', api.userProxy);
return function () {
api.trigger('onDestroy', api.userProxy);
};
}, []);
React.useLayoutEffect(function () {
api.trigger('onInit', api.userProxy);
});
React.useLayoutEffect(function () {
api.trigger('_onReady', api.userProxy);
}, []);
React.useLayoutEffect(function () {
var oldState = api.previousState,
_api$helper$getArrays = api.helper.getArraysDiff(state.openTabIDs, oldState.openTabIDs),
openedTabIDs = _api$helper$getArrays[0],
closedTabIDs = _api$helper$getArrays[1],
isSwitched = oldState.selectedTabID !== state.selectedTabID;
api.onChange({
newState: state,
oldState: oldState,
closedTabIDs: closedTabIDs,
openedTabIDs: openedTabIDs,
isSwitched: isSwitched
});
}, [state]);
React.useLayoutEffect(function () {
api.trigger('_onFlushEffects', api.userProxy, function () {
return [{
currentData: api.getData(),
instance: api.userProxy
}];
});
}, [flushState]);
if (!_ref.TabListComponent) _ref.TabListComponent = function TabListComponent(props) {
if (props === void 0) {
props = {};
}
return /*#__PURE__*/React.createElement(ApiContext.Provider, {
value: api
}, /*#__PURE__*/React.createElement(StateContext.Provider, {
value: api.stateRef
}, /*#__PURE__*/React.createElement(ForceUpdateContext.Provider, {
value: api.forceUpdateState
}, /*#__PURE__*/React.createElement(_ref.Components.TablistView, null, /*#__PURE__*/React.createElement(_ref.Components.TablistContainer, null, /*#__PURE__*/React.createElement(_ref.Components.TablistOverflow, null, /*#__PURE__*/React.createElement(_ref.Components.TabList, props))), props.children))));
};
if (!_ref.PanelListCompoent) _ref.PanelListCompoent = function PanelListCompoent(props) {
return /*#__PURE__*/React.createElement(ApiContext.Provider, {
value: api
}, /*#__PURE__*/React.createElement(StateContext.Provider, {
value: api.stateRef
}, /*#__PURE__*/React.createElement(ForceUpdateContext.Provider, {
value: api.forceUpdateState
}, /*#__PURE__*/React.createElement(Components.PanelList, props, "props.children"))));
};
return [_ref.TabListComponent, _ref.PanelListCompoent, api.ready];
}
var ApiContext = /*#__PURE__*/React.createContext({});
var StateContext = /*#__PURE__*/React.createContext({});
var ForceUpdateContext = /*#__PURE__*/React.createContext({});
function TabList(deps, props, ref) {
var state = React.useContext(StateContext);
var _deps = deps(React.useContext(ApiContext)),
Tabs = _deps.Tabs,
tablistPropsManager = _deps.tablistPropsManager;
return /*#__PURE__*/React.createElement(Tabs, tablistPropsManager(ref, state));
}
function _extends$1() { return _extends$1 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$1.apply(null, arguments); }
function TabsComponent(deps, props, ref) {
var openTabIDs = props.openTabIDs,
selectedTabID = props.selectedTabID;
var _deps = deps(React.useContext(ApiContext)),
TabsPropsManager = _deps.TabsPropsManager,
Tab = _deps.Tab;
return /*#__PURE__*/React.createElement("ul", _extends$1({}, TabsPropsManager(props), {
ref: ref || null
}), openTabIDs.map(function (id) {
return /*#__PURE__*/React.createElement(Tab, {
key: id,
id: id,
selectedTabID: selectedTabID
});
}));
}
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
var TabComponent = function TabComponent(deps, props) {
React.useContext(ForceUpdateContext);
var api = React.useContext(ApiContext);
var _deps = deps(api),
tabPropsManager = _deps.tabPropsManager,
tabInnerPropsManager = _deps.tabInnerPropsManager,
closeIconPropsManager = _deps.closeIconPropsManager;
var id = props.id;
props.selectedTabID;
var TabInnerComponent = api.getOption('tabComponent'),
tabObj = api.getTab(id),
clkHandler = function clkHandler(e) {
api.eventHandlerFactory({
e: e,
id: id
});
};
return /*#__PURE__*/React.createElement("li", _extends({}, tabPropsManager(props), {
onClick: function onClick(e) {
clkHandler(e);
}
}), /*#__PURE__*/React.createElement(TabInnerComponent, tabInnerPropsManager(props), tabObj.title), tabObj.closable ? /*#__PURE__*/React.createElement("span", closeIconPropsManager(), "\xD7") : null);
};
var memomizeTabComponent = (function (TabComponent) {
return /*#__PURE__*/React.memo(TabComponent, function (oldProps, newProps) {
var id = oldProps.id,
oldActiveId = oldProps.selectedTabID,
newActiveId = newProps.selectedTabID;
return oldActiveId === newActiveId || id !== oldActiveId && id !== newActiveId;
});
});
var _tabPropsManager = function tabPropsManager(ins, props) {
var id = props.id,
selectedTabID = props.selectedTabID;
var isSelected = selectedTabID === id;
var _ins$getTab = ins.getTab(id),
disable = _ins$getTab.disable,
title = _ins$getTab.title,
tooltip = _ins$getTab.tooltip;
var outputProps = {
'tab-id': id,
className: ins.getSetting('tabClass'),
tabIndex: -1,
title: tooltip || title
};
//check if tab is selected
if (isSelected) {
outputProps.tabIndex = 0;
outputProps.className += ' ' + ins.getSetting('selectedClass');
}
// check if tab is disable
if (disable) {
outputProps.tabIndex = -1;
outputProps.className += ' ' + ins.getSetting('disableClass');
}
// check if accessibility option is enable
if (ins.getOption('accessibility')) {
outputProps.role = 'tab';
outputProps.id = ins.getSetting('ariaLabelledbyIdTemplate', id);
outputProps['aria-controls'] = ins.getSetting('panelIdTemplate', id);
outputProps['aria-label'] = tooltip || title;
outputProps['aria-selected'] = outputProps['aria-expanded'] = isSelected;
}
return outputProps;
};
var _tabInnerPropsManager = function tabInnerPropsManager(ins, props) {
var id = props.id,
selectedTabID = props.selectedTabID;
var isSelected = selectedTabID == id;
var _ins$getTab2 = ins.getTab(id),
iconClass = _ins$getTab2.iconClass;
var outputProps = {
id: id,
isSelected: isSelected,
api: ins.userProxy,
tabProps: {
'tab-id': id,
className: ins.getSetting('titleClass'),
tabIndex: -1,
role: 'presentation'
}
};
// check if there is a iconClass option
if (iconClass) {
outputProps.iconProps = {
className: ins.getSetting('iconClass') + ' ' + iconClass,
role: 'presentation'
};
}
return outputProps;
};
var _closeIconPropsManager = function closeIconPropsManager(ins) {
var outputProps = {
className: ins.getSetting('closeClass')
};
// check if accessibility option is enable
if (ins.getOption('accessibility')) {
outputProps.role = 'button';
}
return outputProps;
};
var memomizeTab = memomizeTabComponent;
var Tab = memomizeTabComponent(TabComponent.bind(undefined, function (ins) {
return {
tabPropsManager: function tabPropsManager(props) {
return _tabPropsManager(ins, props);
},
tabInnerPropsManager: function tabInnerPropsManager(props) {
return _tabInnerPropsManager(ins, props);
},
closeIconPropsManager: function closeIconPropsManager() {
return _closeIconPropsManager(ins);
}
};
}));
var _TabsPropsManager = function TabsPropsManager(ins, props) {
var dir = props.dir,
isVertical = props.isVertical;
var result = {
className: ins.getSetting('tablistClass') + ' ' + ins.getSetting(dir + "Class")
};
if (isVertical) {
result.className += ' ' + ins.getSetting('verticalClass');
}
if (ins.getOption('accessibility')) {
result.role = 'tablist';
}
return result;
};
var Tabs = /*#__PURE__*/React.forwardRef(TabsComponent.bind(undefined, function (ins) {
return {
Tab: Tab,
TabsPropsManager: function TabsPropsManager(props) {
return _TabsPropsManager(ins, props);
}
};
}));
var _tablistPropsManager = function tablistPropsManager(ins, ref, state) {
var openTabIDs = state.openTabIDs,
selectedTabID = state.selectedTabID;
return {
openTabIDs: openTabIDs,
selectedTabID: selectedTabID,
ref: ref,
dir: ins.getOption('direction'),
isVertical: ins.getOption('isVertical')
};
};
var MemomizedTabList = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef(TabList.bind(undefined, function (ins) {
return {
Tabs: Tabs,
tablistPropsManager: function tablistPropsManager(ref, state) {
return _tablistPropsManager(ins, ref, state);
}
};
})), function () {
return true;
});
function panelPropsManager (_ref) {
var isSelected = _ref.isSelected,
api = _ref.api,
id = _ref.id;
var op = api.optionsManager.options,
setting = api.optionsManager.setting,
result = {
'tab-id': id,
className: setting.panelClass
};
// check if it is selected
if (isSelected) {
result.className += " " + setting.selectedClass;
}
// check if accessibility is enable
if (op.accessibility) {
result.role = 'tabpanel';
result.id = setting.panelIdTemplate(id);
result['aria-hidden'] = isSelected ? false : true;
result['aria-labelledby'] = setting.ariaLabelledbyIdTemplate(id);
}
return result;
}
var PanelComponent = function PanelComponent(props) {
React.useContext(ForceUpdateContext);
var id = props.id,
selectedTabID = props.selectedTabID,
api = React.useContext(ApiContext),
isSelected = id === selectedTabID,
panelProps = panelPropsManager({
isSelected: isSelected,
api: api,
id: id
}),
previousSelectedTabID = api.state.selectedTabID,
_api$getTab = api.getTab(id),
PanelComponent = _api$getTab.panelComponent,
lazy = _api$getTab.lazy;
var hasBeenSelected = false;
if (!lazy || isSelected || previousSelectedTabID === id || api.activedTabsHistory.tabsId.indexOf(id) >= 0) {
hasBeenSelected = true;
}
return /*#__PURE__*/React.createElement("div", panelProps, hasBeenSelected ? PanelComponent ? /*#__PURE__*/React.createElement(PanelComponent, {
id: id,
isSelected: isSelected,
api: api.userProxy
}) : null : null);
};
var Panel = /*#__PURE__*/React.memo(PanelComponent, function (oldProps, newProps) {
var id = oldProps.id,
oldActiveId = oldProps.selectedTabID,
newActiveId = newProps.selectedTabID;
return oldActiveId === newActiveId || id !== oldActiveId && id !== newActiveId;
});
var PanelList = /*#__PURE__*/React.memo(function PanelList() {
var _React$useContext = React.useContext(StateContext),
openTabIDs = _React$useContext.openTabIDs,
selectedTabID = _React$useContext.selectedTabID,
api = React.useContext(ApiContext),
setting = api.optionsManager.setting,
options = api.optionsManager.options;
var className = setting.panellistClass + ' ' + setting[options.direction + 'Class'];
if (options.isVertical) {
className += ' ' + setting.verticalClass;
}
return /*#__PURE__*/React.createElement("div", {
className: className
}, openTabIDs.map(function (id) {
return /*#__PURE__*/React.createElement(Panel, {
key: id,
id: id,
selectedTabID: selectedTabID
});
}));
}, function () {
return true;
});
function TablistView$1(deps, props) {
var _deps = deps(React.useContext(ApiContext)),
tablistViewPropsManager = _deps.tablistViewPropsManager;
return /*#__PURE__*/React.createElement("div", tablistViewPropsManager(), props.children);
}
var _tablistViewPropsManager = function tablistViewPropsManager(ins) {
var className = ins.getSetting('tablistViewClass') + ' ' + ins.getSetting(ins.getOption('direction') + "Class");
if (ins.getOption('isVertical')) {
className += ' ' + ins.getSetting('verticalClass');
}
var themeName = ins.getOption('theme');
if (themeName) {
className += ' ' + themeName;
}
var tablistStyle = ins.getOption('tablistStyle') || {};
var result = {
className: className
};
if (typeof tablistStyle === 'object') {
result.style = tablistStyle;
}
return result;
};
var TablistView = TablistView$1.bind(undefined, function (ins) {
return {
tablistViewPropsManager: function tablistViewPropsManager() {
return _tablistViewPropsManager(ins);
}
};
});
function TablistContainer$1(deps, props) {
var _deps = deps(React.useContext(ApiContext)),
tablistContainerPropsManager = _deps.tablistContainerPropsManager;
return /*#__PURE__*/React.createElement("div", tablistContainerPropsManager(), props.children);
}
var _tablistContainerPropsManager = function tablistContainerPropsManager(ins) {
var className = ins.getSetting('tablistContainerClass');
return {
className: className
};
};
var TablistContainer = TablistContainer$1.bind(undefined, function (ins) {
return {
tablistContainerPropsManager: function tablistContainerPropsManager() {
return _tablistContainerPropsManager(ins);
}
};
});
var useApi = function useApi() {
return React.useContext(ApiContext);
};
var useRootState = function useRootState() {
return React.useContext(StateContext);
};
var useForceUpdate = function useForceUpdate() {
return React.useContext(ForceUpdateContext);
};
function TablistOverflow$1(deps, props) {
var _deps = deps(useApi()),
tablistOverflowPropsManager = _deps.tablistOverflowPropsManager;
return /*#__PURE__*/React.createElement("div", tablistOverflowPropsManager(), props.children);
}
var _tablistOverflowPropsManager = function tablistOverflowPropsManager(ins) {
return {
style: {
overflow: 'visible'
},
className: ins.getSetting('tablistOverflowClass')
};
};
var TablistOverflow = TablistOverflow$1.bind(undefined, function (ins) {
return {
tablistOverflowPropsManager: function tablistOverflowPropsManager() {
return _tablistOverflowPropsManager(ins);
}
};
});
var Components = {
TablistView: TablistView,
tablistViewPropsManager: _tablistViewPropsManager,
TablistViewFactory: TablistView$1,
TablistContainer: TablistContainer,
tablistContainerPropsManager: _tablistContainerPropsManager,
TablistContainerFactory: TablistContainer$1,
TablistOverflow: TablistOverflow,
TablistOverflowFactory: TablistOverflow$1,
tablistOverflowPropsManager: _tablistOverflowPropsManager,
TabList: MemomizedTabList,
tablistPropsManager: _tablistPropsManager,
TabListFactory: TabList,
Tabs: Tabs,
TabsPropsManager: _TabsPropsManager,
TabsFactory: TabsComponent,
Tab: Tab,
tabPropsManager: _tabPropsManager,
tabInnerPropsManager: _tabInnerPropsManager,
closeIconPropsManager: _closeIconPropsManager,
memomizeTab: memomizeTab,
TabFactory: TabComponent,
PanelList: PanelList,
useApi: useApi,
useRootState: useRootState,
useForceUpdate: useForceUpdate
};
var getDeps = function getDeps() {
var getApiInstance = function getApiInstance(options, modules, Components) {
return new Api({
options: options
}, modules, Components);
};
return {
reducer: reducer,
getApiInstance: getApiInstance,
ApiContext: ApiContext,
StateContext: StateContext,
ForceUpdateContext: ForceUpdateContext,
Components: Components
};
};
var useDynamicTabs = useDynamicTabs$1.bind(null, getDeps);
return useDynamicTabs;
}));
//# sourceMappingURL=react-dyn-tabs.umd.js.map