{"version":3,"file":"tabs.mjs","sources":["../../../../../../packages/components/tabs/src/tabs.tsx"],"sourcesContent":["import {\n  defineComponent,\n  createVNode,\n  getCurrentInstance,\n  provide,\n  ref,\n  renderSlot,\n  watch,\n  computed,\n  nextTick,\n} from 'vue'\nimport {\n  buildProps,\n  definePropType,\n  isFunction,\n  isNumber,\n  isString,\n  isUndefined,\n} from '@hongluan-ui/utils'\nimport {\n  EVENT_CODE,\n  INPUT_EVENT,\n  UPDATE_MODEL_EVENT,\n} from '@hongluan-ui/constants'\nimport HlIcon from '@hongluan-ui/components/icon'\nimport { SystemAdd } from '@hongluan-ui/components/system-icon'\nimport { tabsRootContextKey } from '@hongluan-ui/tokens'\nimport { useDeprecated, useNamespace, useOrderedChildren } from '@hongluan-ui/hooks'\nimport TabNav from './tab-nav'\nimport type { TabNavInstance } from './tab-nav'\nimport type { TabsPaneContext } from '@hongluan-ui/tokens'\n\nimport type { ExtractPropTypes, FunctionalComponent, VNode } from 'vue'\nimport type { Awaitable } from '@hongluan-ui/utils'\n\nexport type TabPaneName = string | number\n\nexport const tabsProps = buildProps({\n  /**\n   * @description type of Tab\n   */\n  type: {\n    type: String,\n    values: ['line', 'button', ''],\n    default: '',\n  },\n  activeName: {\n    type: [String, Number],\n  },\n  /**\n   * @description whether Tab is closable\n   */\n  closable: Boolean,\n  /**\n   * @description whether Tab is addable\n   */\n  addable: Boolean,\n  /**\n   * @description binding value, name of the selected tab\n   */\n  modelValue: {\n    type: [String, Number],\n  },\n  /**\n   * @description whether Tab is addable and closable\n   */\n  editable: Boolean,\n  /**\n   * @description position of tabs\n   */\n  tabPosition: {\n    type: String,\n    values: ['top', 'right', 'bottom', 'left'],\n    default: 'top',\n  },\n  /**\n   * @description hook function before switching tab. If `false` is returned or a `Promise` is returned and then is rejected, switching will be prevented\n   */\n  beforeLeave: {\n    type: definePropType<\n    (\n    newName: TabPaneName,\n    oldName: TabPaneName\n    ) => Awaitable<void | boolean>\n    >(Function),\n    default: () => true,\n  },\n  showPane: {\n    type: Boolean,\n    default: true,\n  },\n  paneHeight: {\n    type: String,\n  },\n  navHeight: {\n    type: String,\n  },\n  navPadding: {\n    type: String,\n  },\n  gap: {\n    type: String,\n  },\n  /**\n   * @description whether width of tab automatically fits its container\n   */\n  stretch: Boolean,\n} as const)\nexport type TabsProps = ExtractPropTypes<typeof tabsProps>\n\nconst isPanelName = (value: unknown): value is string | number =>\n  isString(value) || isNumber(value)\n\nexport const tabsEmits = {\n  [UPDATE_MODEL_EVENT]: (name: TabPaneName) => isPanelName(name),\n  /** @deprecated use `tab-change` instead */\n  [INPUT_EVENT]: (name: TabPaneName) => isPanelName(name),\n  tabClick: (pane: TabsPaneContext, ev: Event) => ev instanceof Event,\n  tabChange: (name: TabPaneName) => isPanelName(name),\n  edit: (paneName: TabPaneName | undefined, action: 'remove' | 'add') =>\n    ['remove', 'add'].includes(action),\n  tabRemove: (name: TabPaneName) => isPanelName(name),\n  tabAdd: () => true,\n}\nexport type TabsEmits = typeof tabsEmits\nexport type TabsPanes = Record<number, TabsPaneContext>\n\nconst Tabs = defineComponent({\n  name: 'Tabs',\n\n  props: tabsProps,\n  emits: tabsEmits,\n\n  setup(props, { emit, slots, expose }) {\n    const isVertical = computed(() =>\n      ['left', 'right'].includes(props.tabPosition),\n    )\n    const {\n      children: panes,\n      addChild: sortPane,\n      removeChild: unregisterPane,\n    } = useOrderedChildren<TabsPaneContext>(getCurrentInstance()!, 'TabPane')\n\n    const instance = getCurrentInstance()!\n    const nav$ = ref<TabNavInstance>()\n    const currentName = ref<TabPaneName>(\n      props.modelValue ?? props.activeName ?? '0',\n    )\n\n    useDeprecated(\n      {\n        scope: 'Tabs',\n        type: 'Event',\n        from: 'input',\n        replacement: 'tab-change',\n        version: '2.5.0',\n        ref: 'https://hongluan-ui.github.io/hongluan-ui/2x/#/zh-CN/component/tabs.html#tabs-events',\n      },\n      computed(() => isFunction(instance.vnode.props?.onInput)),\n    )\n\n    useDeprecated(\n      {\n        from: '\"activeName\"',\n        replacement: '\"model-value\" or \"v-model\"',\n        scope: 'Tabs',\n        version: '2.5.0',\n        ref: 'https://hongluan-ui.github.io/hongluan-ui/2x/#/zh-CN/component/tabs.html#attributes',\n        type: 'Attribute',\n      },\n      computed(() => !!props.activeName),\n    )\n\n    const { namespace } = useNamespace('tabs')\n\n    const setCurrentName = async (value?: TabPaneName, trigger = false) => {\n      // should do nothing.\n      if (currentName.value === value || isUndefined(value)) return\n\n      try {\n        const canLeave = await props.beforeLeave?.(value, currentName.value)\n        if (canLeave !== false) {\n          currentName.value = value\n          if (trigger) {\n            emit(UPDATE_MODEL_EVENT, value)\n            emit('tabChange', value)\n          }\n          nav$.value?.removeFocus?.()\n        }\n      } catch {}\n    }\n\n    const handleTabClick = (\n      tab: TabsPaneContext,\n      tabName: TabPaneName,\n      event: Event,\n    ) => {\n      if (tab.props.disabled) return\n      setCurrentName(tabName, true)\n      emit('tabClick', tab, event)\n    }\n\n    const handleTabRemove = (pane: TabsPaneContext, ev: Event) => {\n      if (pane.props.disabled || isUndefined(pane.props.name)) return\n      ev.stopPropagation()\n      emit('edit', pane.props.name, 'remove')\n      emit('tabRemove', pane.props.name)\n    }\n\n    const handleTabAdd = () => {\n      emit('edit', undefined, 'add')\n      emit('tabAdd')\n    }\n\n    watch(\n      () => props.activeName,\n      modelValue => setCurrentName(modelValue),\n    )\n\n    watch(\n      () => props.modelValue,\n      modelValue => setCurrentName(modelValue),\n    )\n\n    watch(currentName, async () => {\n      await nextTick()\n      nav$.value?.scrollToActiveTab()\n    })\n\n    provide(tabsRootContextKey, {\n      props,\n      currentName,\n      registerPane: (pane: TabsPaneContext) => {\n        panes.value.push(pane)\n      },\n      sortPane,\n      unregisterPane,\n    })\n\n    expose({\n      currentName,\n    })\n\n    const TabNavRenderer: FunctionalComponent<{ render: () => VNode; }> = ({\n      render,\n    }) => {\n      return render()\n    }\n\n    return () => {\n      const addSlot = slots['add-icon']\n      const newButton =\n        props.editable || props.addable ? (\n          <div\n            class={['tab-new', isVertical.value && 'new-tab-vertical']}\n            tabindex=\"0\"\n            onClick={handleTabAdd}\n            onKeydown={(ev: KeyboardEvent) => {\n              if (ev.code === EVENT_CODE.enter) handleTabAdd()\n            }}\n          >\n            {addSlot ? (\n              renderSlot(slots, 'add-icon')\n            ) : (\n              <HlIcon>\n                <SystemAdd />\n              </HlIcon>\n            )}\n          </div>\n        ) : null\n\n      const header = (\n        <div class={['tabs-header', `at-${props.tabPosition}`, isVertical.value && 'header-vertical']}>\n          <TabNavRenderer\n            render={() => {\n              const hasLabelSlot = panes.value.some(pane => pane.slots.label)\n              return createVNode(\n                TabNav,\n                {\n                  ref: nav$,\n                  currentName: currentName.value,\n                  editable: props.editable,\n                  type: props.type,\n                  panes: panes.value,\n                  stretch: props.stretch,\n                  onTabClick: handleTabClick,\n                  onTabRemove: handleTabRemove,\n                },\n                { $stable: !hasLabelSlot },\n              )\n            }}\n          />\n          {newButton}\n        </div>\n      )\n\n      const panels = (\n        <div class={'tabs-content'}>{renderSlot(slots, 'default')}</div>\n      )\n\n      return (\n        <div\n          class={{\n            [namespace.value]: true,\n            'tabs-line': props.type === 'line',\n            'tabs-button': props.type === 'button',\n            'no-pane': !props.showPane,\n            [`tabs-${props.tabPosition}`]: true,\n          }}\n          style={[\n            props.paneHeight ? `--tabs-pane-height:${props.paneHeight}` : '',\n            props.navHeight ? `--tabs-height:${props.navHeight}` : '',\n            props.navPadding ? `--tabs-padding:${props.navPadding}` : '',\n            props.gap ? `--tabs-gap:${props.gap}` : '',\n          ]}\n        >\n          {...props.tabPosition !== 'bottom'\n            ? [header, panels]\n            : [panels, header]}\n        </div>\n      )\n    }\n  },\n})\n\nexport type TabsInstance = InstanceType<typeof Tabs> & {\n  currentName: TabPaneName\n}\n\nexport default Tabs\n"],"names":["tabsProps","buildProps","type","values","default","activeName","String","closable","addable","modelValue","editable","tabPosition","beforeLeave","Function","showPane","Boolean","paneHeight","navHeight","navPadding","gap","stretch","isPanelName","tabsEmits","tabClick","tabChange","edit","tabRemove","tabAdd","Tabs","name","props","emits","setup","emit","slots","expose","isVertical","children","addChild","removeChild","currentName","useDeprecated","scope","from","replacement","version","ref","namespace","value","nav$","handleTabClick","tab","setCurrentName","disabled","ev","watch","_createVNode","provide","tabsRootContextKey","registerPane","panes","pane","sortPane","unregisterPane","render"],"mappings":";;;;;;;;;;;;;;;;;;;MAqCaA,SAAS,GAAGC,UAAU,CAAC;AAClC;AACF;AACA;AACEC;AACEA;AACAC,YAAQ;AACRC,IAAAA,OAAO;AAHH,GAJ4B;AASlCC,EAAAA,UAAU;AACRH,WAAOI;AADG;;AAGZ;AACF;AACA;AACEC,UAAQ;;AACR;AACF;AACA;AACEC;;AACA;AACF;AACA;AACEC;AACEP;AADU;;AAGZ;AACF;AACA;AACEQ;;AACA;AACF;AACA;AACEC;AACET;AACAC,kBAAQ;AACRC;AAHW;;AAKb;AACF;AACA;AACEQ,EAAAA,WAAW;AACTV,QAAI,iBAKFW;AACFT,WAAO,EAAE;AAPE;AASbU,EAAAA;UACQC;AACNX;AAFQ;AAIVY,EAAAA;AACEd,QAAI;AADM;AAGZe;AACEf,IAAAA,MAAMI;AADG,GAzDuB;AA4DlCY,YAAU,EAAE;AACVhB,IAAAA,MAAMI;AADI;AAGZa;AACEjB;AADG;;AAGL;AACF;AACA;AACEkB;AArEkC;;AAyEpC,MAAMC;;AAGN,aAAaC,SAAS;AACpB;;AACA;AACA,yBAAsCD;AACtCE;AACAC,iBAAW;AACXC,MAAI;AAEJC,iBAAW;AACXC;AATuB;AAczB,MAAMC;AACJC,MAAI;AAEJC,OAAK;AACLC;;AAEAC,QAAMF;AAASG,IAAAA;AAAMC;AAAOC;AAAf;AACX,UAAMC;AAGN;AACEC;AACAC;AACAC;AAHI;AAMN;AACA;AACA,UAAMC,iBAAiB,CACrBV,KAAK,qBAAqBzB;AAG5BoC;AAEIC;AACAxC;AACAyC,MAAAA;AACAC,+BAJF;AAKEC,MAAAA,OAAO;AACPC;AANF;AAWFL;AAEIE,MAAAA;AACAC;AACAF,MAAAA;AACAG,eAAS;AACTC,MAAAA,GAAG;AACH5C,MAAAA,IAAI;AANN,sBAQe,EAAE4B,KAAK,WAAd,CATG;AAYb;AAAQiB;AAAF,2BAA4B;;AAElC;AACE;AACA,UAAIP,WAAW,CAACQ,UAAUA;;AAE1B,UAAI;AACF,sBAAc;;AACd;AACER,8BAAoBQ;;AACpB;AACEf;AACAA,8BAAkBe;AACnB;;AACDC,oBAAA;AACD;AACF;AACF;;AAED,UAAMC,cAAc,GAAG,CACrBC;AAIA;AACAC;AACAnB,MAAAA,eAAI;AACL,KARD;;AAUA,4BAAwB;AACtB,qBAAeoB,QAAX,0BAAmC;AACvCC,QAAE;AACFrB,uBAAiB;AACjBA;AACD;;AAED;AACEA;AACAA,UAAI,UAAJ;AACD;;AAEDsB,qBACaC,YACX/C;AAGF8C,kCAEE9C,UAAU;AAGZ8C,SAAK,CAACf,YAAa;AACjB;AACAS,UAAI,MAAJ;AACD;AAEDQ,YAAQC;AACN5B;AACAU;AACAmB,kBAAY,MAAE,IAA2B;AACvCC,mBAAA,KAAA,CAAiBC;AAClB;AACDC;AACAC;AAP0B;AAU5B5B;AACEK;AADK;;AAIP;AACEwB;AADqE,UAEjE;AACJ,aAAOA;AACR;;AAED;AACE;AACA,qBAAe;AACb,iBAEW,4BAAY;AAFvB;AAAA;AAAA;AAMM;AACD;AAPL;;;;"}