tabs.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var lodashUnified = require('lodash-unified');
  5. var index$2 = require('../../icon/index.js');
  6. var iconsVue = require('@element-plus/icons-vue');
  7. var constants = require('./constants.js');
  8. var tabNav = require('./tab-nav.js');
  9. var runtime = require('../../../utils/vue/props/runtime.js');
  10. var event = require('../../../constants/event.js');
  11. var index = require('../../../hooks/use-namespace/index.js');
  12. var index$1 = require('../../../hooks/use-ordered-children/index.js');
  13. var types = require('../../../utils/types.js');
  14. var shared = require('@vue/shared');
  15. var event$1 = require('../../../utils/dom/event.js');
  16. var aria = require('../../../constants/aria.js');
  17. const tabsProps = runtime.buildProps({
  18. type: {
  19. type: String,
  20. values: ["card", "border-card", ""],
  21. default: ""
  22. },
  23. closable: Boolean,
  24. addable: Boolean,
  25. modelValue: {
  26. type: [String, Number]
  27. },
  28. defaultValue: {
  29. type: [String, Number]
  30. },
  31. editable: Boolean,
  32. tabPosition: {
  33. type: String,
  34. values: ["top", "right", "bottom", "left"],
  35. default: "top"
  36. },
  37. beforeLeave: {
  38. type: runtime.definePropType(Function),
  39. default: () => true
  40. },
  41. stretch: Boolean,
  42. tabindex: {
  43. type: [String, Number],
  44. default: 0
  45. }
  46. });
  47. const isPaneName = (value) => shared.isString(value) || types.isNumber(value);
  48. const tabsEmits = {
  49. [event.UPDATE_MODEL_EVENT]: (name) => isPaneName(name),
  50. tabClick: (pane, ev) => ev instanceof Event,
  51. tabChange: (name) => isPaneName(name),
  52. edit: (paneName, action) => ["remove", "add"].includes(action),
  53. tabRemove: (name) => isPaneName(name),
  54. tabAdd: () => true
  55. };
  56. const Tabs = vue.defineComponent({
  57. name: "ElTabs",
  58. props: tabsProps,
  59. emits: tabsEmits,
  60. setup(props, {
  61. emit,
  62. slots,
  63. expose
  64. }) {
  65. var _a;
  66. const ns = index.useNamespace("tabs");
  67. const isVertical = vue.computed(() => ["left", "right"].includes(props.tabPosition));
  68. const {
  69. children: panes,
  70. addChild: registerPane,
  71. removeChild: unregisterPane,
  72. ChildrenSorter: PanesSorter
  73. } = index$1.useOrderedChildren(vue.getCurrentInstance(), "ElTabPane");
  74. const nav$ = vue.ref();
  75. const currentName = vue.ref((_a = types.isUndefined(props.modelValue) ? props.defaultValue : props.modelValue) != null ? _a : "0");
  76. const setCurrentName = async (value, trigger = false) => {
  77. var _a2, _b, _c, _d;
  78. if (currentName.value === value || types.isUndefined(value))
  79. return;
  80. try {
  81. let canLeave;
  82. if (props.beforeLeave) {
  83. const result = props.beforeLeave(value, currentName.value);
  84. canLeave = result instanceof Promise ? await result : result;
  85. } else {
  86. canLeave = true;
  87. }
  88. if (canLeave !== false) {
  89. const isFocusInsidePane = (_a2 = panes.value.find((item) => item.paneName === currentName.value)) == null ? void 0 : _a2.isFocusInsidePane();
  90. currentName.value = value;
  91. if (trigger) {
  92. emit(event.UPDATE_MODEL_EVENT, value);
  93. emit("tabChange", value);
  94. }
  95. (_c = (_b = nav$.value) == null ? void 0 : _b.removeFocus) == null ? void 0 : _c.call(_b);
  96. if (isFocusInsidePane) {
  97. (_d = nav$.value) == null ? void 0 : _d.focusActiveTab();
  98. }
  99. }
  100. } catch (e) {
  101. }
  102. };
  103. const handleTabClick = (tab, tabName, event) => {
  104. if (tab.props.disabled)
  105. return;
  106. emit("tabClick", tab, event);
  107. setCurrentName(tabName, true);
  108. };
  109. const handleTabRemove = (pane, ev) => {
  110. if (pane.props.disabled || types.isUndefined(pane.props.name))
  111. return;
  112. ev.stopPropagation();
  113. emit("edit", pane.props.name, "remove");
  114. emit("tabRemove", pane.props.name);
  115. };
  116. const handleTabAdd = () => {
  117. emit("edit", void 0, "add");
  118. emit("tabAdd");
  119. };
  120. const handleKeydown = (event) => {
  121. const code = event$1.getEventCode(event);
  122. if ([aria.EVENT_CODE.enter, aria.EVENT_CODE.numpadEnter].includes(code))
  123. handleTabAdd();
  124. };
  125. const swapChildren = (vnode) => {
  126. const actualFirstChild = vnode.el.firstChild;
  127. const firstChild = ["bottom", "right"].includes(props.tabPosition) ? vnode.children[0].el : vnode.children[1].el;
  128. if (actualFirstChild !== firstChild) {
  129. actualFirstChild.before(firstChild);
  130. }
  131. };
  132. vue.watch(() => props.modelValue, (modelValue) => setCurrentName(modelValue));
  133. vue.watch(currentName, async () => {
  134. var _a2;
  135. await vue.nextTick();
  136. (_a2 = nav$.value) == null ? void 0 : _a2.scrollToActiveTab();
  137. });
  138. vue.provide(constants.tabsRootContextKey, {
  139. props,
  140. currentName,
  141. registerPane,
  142. unregisterPane,
  143. nav$
  144. });
  145. expose({
  146. currentName,
  147. get tabNavRef() {
  148. return lodashUnified.omit(nav$.value, ["scheduleRender"]);
  149. }
  150. });
  151. return () => {
  152. const addSlot = slots["add-icon"];
  153. const newButton = props.editable || props.addable ? vue.createVNode("div", {
  154. "class": [ns.e("new-tab"), isVertical.value && ns.e("new-tab-vertical")],
  155. "tabindex": props.tabindex,
  156. "onClick": handleTabAdd,
  157. "onKeydown": handleKeydown
  158. }, [addSlot ? vue.renderSlot(slots, "add-icon") : vue.createVNode(index$2.ElIcon, {
  159. "class": ns.is("icon-plus")
  160. }, {
  161. default: () => [vue.createVNode(iconsVue.Plus, null, null)]
  162. })]) : null;
  163. const tabNav$1 = () => vue.createVNode(tabNav["default"], {
  164. "ref": nav$,
  165. "currentName": currentName.value,
  166. "editable": props.editable,
  167. "type": props.type,
  168. "panes": panes.value,
  169. "stretch": props.stretch,
  170. "onTabClick": handleTabClick,
  171. "onTabRemove": handleTabRemove
  172. }, null);
  173. const header = vue.createVNode("div", {
  174. "class": [ns.e("header"), isVertical.value && ns.e("header-vertical"), ns.is(props.tabPosition)]
  175. }, [vue.createVNode(PanesSorter, null, {
  176. default: tabNav$1,
  177. $stable: true
  178. }), newButton]);
  179. const panels = vue.createVNode("div", {
  180. "class": ns.e("content")
  181. }, [vue.renderSlot(slots, "default")]);
  182. return vue.createVNode("div", {
  183. "class": [ns.b(), ns.m(props.tabPosition), {
  184. [ns.m("card")]: props.type === "card",
  185. [ns.m("border-card")]: props.type === "border-card"
  186. }],
  187. "onVnodeMounted": swapChildren,
  188. "onVnodeUpdated": swapChildren
  189. }, [panels, header]);
  190. };
  191. }
  192. });
  193. exports["default"] = Tabs;
  194. exports.tabsEmits = tabsEmits;
  195. exports.tabsProps = tabsProps;
  196. //# sourceMappingURL=tabs.js.map