{"mappings":"AACA,SAAwB,mBAAgC;AACxD,cAAyB,sBAAsB;AAE/C,cAA8C,gBAAgB;;;;;;;AAa9D,cAyEM,aAAa,YAAY;CAC7B,AACA,UAAU;;;;;;;;CASV,AACA,WAAW,aAAa,aAAa;;;;;;CAOrC,AACA,QAAQ,WAAW;;;;;;;;CASnB,AACA,WAAW,eAAe;;;;CAK1B,AACA;;;;CAKA,AACA;CAEA,UAAU;CAEV,UACU,QAAQ,iBAAiB;CAEnC,UACU,aAAa,iBAAiB;CAExC;CAKA,UAAU,eAAe;CA2BzB,cAAc;CAId;CAKA,UAAU;CAQV,KAAK,qBAAqB;CAsC1B,OAAO;;AAWT,eAAe;AACf,SAAS","names":[],"sources":["../../../../src/web-components/tabs/component.ts"],"sourcesContent":["import { attr, godown, htmlSlot, StyleController, styles, tokenList } from \"@godown/element\";\nimport { cssGlobalVars, GlobalStyle, scopePrefix } from \"../../internal/global-style.js\";\nimport { css, html, type TemplateResult } from \"lit\";\nimport { property, queryAll } from \"lit/decorators.js\";\nimport { RingBuilder, ringTypeAttribute, type RingType } from \"../../internal/ring.js\";\n\nconst protoName = \"tabs\";\nconst cssScope = scopePrefix(protoName);\n\nconst hoverToken = \"hover\";\n\n/**\n * {@linkcode Tabs} used to render a set of tabs.\n *\n * @fires select - Fires when the tab index is changed.\n * @category display\n */\n@godown(protoName)\n@styles(css`\n  :host {\n    ${cssScope}--indicator-background: var(${cssGlobalVars.passive});\n    ${cssScope}--selected-background: var(${cssGlobalVars.passive});\n    transition: 0.2s ease-in-out;\n    display: flex;\n    cursor: default;\n  }\n\n  [part=\"root\"] {\n    gap: 0.25em;\n    padding: 0.25em;\n    position: relative;\n    z-index: 1;\n    display: flex;\n    flex-direction: inherit;\n    overflow-x: clip;\n    border-radius: inherit;\n    transition: inherit;\n    transition-property: width, transform, opacity;\n  }\n\n  [part~=\"item\"] {\n    position: relative;\n    width: 100%;\n    display: block;\n    text-align: center;\n    position: relative;\n    white-space: nowrap;\n    transition: inherit;\n    border-radius: inherit;\n    transition-property: inherit;\n  }\n\n  [part=\"indicator\"],\n  [part~=\"item\"]::after {\n    width: 100%;\n    height: 100%;\n    inset: 0;\n    position: absolute;\n    transition: inherit;\n    border-radius: inherit;\n    transition-property: inherit;\n    background: var(${cssScope}--indicator-background);\n  }\n\n  [part=\"indicator\"] {\n    opacity: 0;\n    z-index: -1;\n  }\n\n  [part~=\"item\"]::after {\n    z-index: -2;\n  }\n\n  [indicator=\"underline\"] [part=\"indicator\"],\n  [indicator=\"underline\"] [part~=\"item\"]::after {\n    top: 100%;\n    height: 0.15em;\n    border-radius: 0.075em;\n    margin-top: 0.15em;\n  }\n\n  [part~=\"selected\"]::after {\n    content: \"\";\n    background: var(${cssScope}--selected-background);\n  }\n\n  [part~=\"hover\"] [part=\"indicator\"] {\n    opacity: 1;\n  }\n`)\nclass Tabs extends GlobalStyle {\n  @property({ attribute: ringTypeAttribute })\n  ringType: RingType = \"border\";\n\n  /**\n   * If \"select\", the indicator moves from the selected content to the hover position.\n   *\n   * If \"previous\", the indicator moves from the last moved position to the hover position.\n   *\n   * If \"none\", the indicator does not move.\n   */\n  @property()\n  beginning: \"selected\" | \"previous\" | \"none\" = \"selected\";\n\n  /**\n   * If \"remain\", the indicator remain on the selected item.\n   *\n   * If \"none\", the indicator dose not display.\n   */\n  @property()\n  ending: \"remain\" | \"none\" = \"remain\";\n\n  /**\n   * The behavior of the indicator:\n   *\n   * If \"background\", its size will be consistent with that of a single tab.\n   *\n   * If \"underline\", an underline will be displayed at the bottom of the tab.\n   */\n  @property()\n  indicator: \"background\" | \"underline\" = \"background\";\n\n  /**\n   * Tab list or slot list.\n   */\n  @property({ type: Array })\n  tabs: string[];\n\n  /**\n   * The index of the currently selected tab.\n   */\n  @property({ type: Number })\n  index = 0;\n\n  protected previousIndex: number;\n\n  @queryAll(\"[part~=item]\")\n  protected _items: HTMLCollectionOf<HTMLLIElement>;\n\n  @queryAll(\"[part=indicator]\")\n  protected _indicators: HTMLCollectionOf<HTMLDivElement>;\n\n  constructor() {\n    super();\n    new StyleController(this, () => new RingBuilder({ type: this.ringType }).css);\n  }\n\n  render(): TemplateResult<1> {\n    const isRemain = this.ending === \"remain\";\n    return html`\n      <ul\n        part=\"root\"\n        ${attr(this.observedRecord)}\n        @mouseleave=\"${this._handleMouseLeave}\"\n      >\n        ${this.tabs?.map(\n          (tab, index) => html`\n            <li\n              part=\"${tokenList(\"item\", isRemain && this.index === index && \"selected\")}\"\n              @mouseenter=${() => {\n                this.move(this.previousIndex, index);\n                this.previousIndex = index;\n              }}\n              @click=${() => this.select(index)}\n            >\n              ${htmlSlot(tab, tab)}\n              <div part=\"indicator\"></div>\n            </li>\n          `,\n        )}\n      </ul>\n    `;\n  }\n\n  protected get _finalIndex(): number {\n    return this.ending === \"none\" && this.beginning === \"selected\" ? this.index : -1;\n  }\n\n  connectedCallback(): void {\n    super.connectedCallback();\n    this.previousIndex = this._finalIndex;\n  }\n\n  protected _handleMouseLeave(): void {\n    const lastItem = this._items[this.previousIndex];\n    if (lastItem) {\n      lastItem.part.remove(hoverToken);\n    }\n    this.previousIndex = this._finalIndex;\n  }\n\n  move(sourceIndex: number, targetIndex: number): void {\n    if (sourceIndex === targetIndex) {\n      return;\n    }\n    const { _items, _indicators } = this;\n    const targetElement = _items[targetIndex];\n    if (!targetElement) {\n      return;\n    }\n    targetElement.part.add(hoverToken);\n    const fromItem = _items[sourceIndex];\n    if (!fromItem) {\n      return;\n    }\n    fromItem.part.remove(hoverToken);\n    if (this.beginning === \"none\") {\n      return;\n    }\n    const targetIndicator = _indicators[targetIndex];\n    const sourceIndicator = _indicators[sourceIndex];\n    if (!targetIndicator || !sourceIndicator) {\n      return;\n    }\n    const { x: sourceX, y: sourceY, width: sourceWidth } = sourceIndicator.getBoundingClientRect();\n    const { x, y } = targetIndicator.getBoundingClientRect();\n    const transformX = sourceX - x;\n    const transformY = sourceY - y;\n\n    const { style: targetStyle } = targetIndicator;\n    const { style: sourceStyle } = sourceIndicator;\n\n    targetStyle.transform = `translate3d(${transformX}px,${transformY}px,0)`;\n    targetStyle.width = `${sourceWidth}px`;\n    targetStyle.transition = sourceStyle.transition = \"none\";\n    targetIndicator.getBoundingClientRect();\n    targetStyle.width = targetStyle.transform = targetStyle.transition = sourceStyle.transition = \"\";\n  }\n\n  select(selected: number): void {\n    const { index, previousIndex } = this;\n    this.move(previousIndex, selected);\n    if (selected !== index) {\n      this.previousIndex = selected;\n      this.index = selected;\n      this.dispatchCustomEvent(\"select\", selected);\n    }\n  }\n}\n\nexport default Tabs;\nexport { Tabs };\n"],"version":3,"file":"component.d.ts"}