import{html as e,render as t,Directives as o}from"../../third_party/lit-html/lit-html.js";const r=t=>{const o=String(t);return e`${o}`};var s=Object.freeze({__proto__:null,stringRenderer:r,codeBlockRenderer:t=>e`<code>${t}</code>`});const i=new Set(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"]);function n(e){return i.has(e)}function l(e,t){const o=e.cells.find(e=>e.columnId===t);if(void 0===o)throw new Error(`Found a row that was missing an entry for column ${t}.`);return o}function a(e){return e.renderer?e.renderer(e.value):r(e.value)}function d(e){if("string"==typeof e.value)return e.value;const o=a(e),r=document.createElement("div");return t(o,r),r.innerText}function c(e,t){const o=e.filter(e=>!e.hidden).reduce((e,t)=>e+t.widthWeighting,0),r=e.find(e=>e.id===t);if(!r)throw new Error("Could not find column with ID "+t);if(r.widthWeighting<1)throw new Error(`Error with column ${t}: width weightings must be >= 1.`);return r.hidden?0:Math.round(r.widthWeighting/o*100)}function h(e){const{key:t,currentFocusedCell:o,columns:r,rows:s}=e,[i,n]=o;switch(t){case"ArrowLeft":{if(i===r.findIndex(e=>!e.hidden))return[i,n];let e=i;for(let t=e-1;t>=0;t--){if(!r[t].hidden){e=t;break}}return[e,n]}case"ArrowRight":{let e=i;for(let t=e+1;t<r.length;t++){if(!r[t].hidden){e=t;break}}return[e,n]}case"ArrowUp":{const e=r.some(e=>!0===e.sortable)?0:1;if(n===e)return[i,n];let t=n;for(let o=n-1;o>=e;o--){if(0===o){t=0;break}if(!s[o-1].hidden){t=o;break}}return[i,t]}case"ArrowDown":{if(0===n){const e=s.findIndex(e=>!e.hidden);return e>-1?[i,e+1]:[i,n]}let e=n;for(let t=e+1;t<s.length+1;t++){if(!s[t-1].hidden){e=t;break}}return[i,e]}}}const u=e=>{const{columns:t,rows:o}=e,r=t.some(e=>!0===e.sortable)?0:o.findIndex(e=>!e.hidden)+1;return[t.findIndex(e=>!e.hidden),r]};var f=Object.freeze({__proto__:null,ARROW_KEYS:i,keyIsArrowKey:n,getRowEntryForColumnId:l,renderCellValue:a,stringValueForCell:d,calculateColumnWidthPercentageFromWeighting:c,handleArrowKeyNavigation:h,calculateFirstFocusableCell:u});class m extends Event{constructor(e,t){super("column-header-click"),this.data={column:e,columnIndex:t}}}class w extends Event{constructor(e,t){super("cell-focused"),this.data={cell:e,row:t}}}const b=new Set([" ","Enter"]);class g extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.columns=[],this.rows=[],this.sortState=null,this.focusableCell=[0,1],this.hasRenderedAtLeastOnce=!1}get data(){return{columns:this.columns,rows:this.rows,activeSort:this.sortState}}set data(e){if(this.columns=e.columns,this.rows=e.rows,this.sortState=e.activeSort,this.hasRenderedAtLeastOnce||(this.focusableCell=u({columns:this.columns,rows:this.rows})),this.hasRenderedAtLeastOnce){const[e,t]=this.focusableCell,o=e>this.columns.length,r=t>this.rows.length;this.focusableCell=o||r?[o?this.columns.length:e,r?this.rows.length:t]:u({columns:this.columns,rows:this.rows})}this.render()}scrollToBottomIfRequired(){if(!1===this.hasRenderedAtLeastOnce)return;const e=this.getCurrentlyFocusableCell();if(e&&e===this.shadow.activeElement)return;const t=this.shadow.querySelector("tbody tr:not(.hidden):last-child");t&&t.scrollIntoView()}getCurrentlyFocusableCell(){const[e,t]=this.focusableCell;return this.shadow.querySelector(`[data-row-index="${t}"][data-col-index="${e}"]`)}focusCell([e,t]){const[o,r]=this.focusableCell;o===e&&r===t||(this.focusableCell=[e,t],this.render());const s=this.getCurrentlyFocusableCell();if(!s)throw new Error("Unexpected error: could not find cell marked as focusable");s!==this.shadow.activeElement&&s.focus()}onTableKeyDown(e){const t=e.key;if(b.has(t)){const e=this.getCurrentlyFocusableCell(),[t,o]=this.focusableCell,r=this.columns[t];e&&0===o&&r&&r.sortable&&this.onColumnHeaderClick(r,t)}if(!n(t))return;const o=h({key:t,currentFocusedCell:this.focusableCell,columns:this.columns,rows:this.rows});this.focusCell(o)}onColumnHeaderClick(e,t){this.dispatchEvent(new m(e,t))}ariaSortForHeader(e){return!e.sortable||this.sortState&&this.sortState.columnId===e.id?this.sortState&&this.sortState.columnId===e.id?"ASC"===this.sortState.direction?"ascending":"descending":void 0:"none"}renderEmptyRow(){const t=this.columns.filter(e=>!e.hidden).map((t,r)=>{const s=o.classMap({firstVisibleColumn:0===r});return e`<td class=${s}></td>`});return e`<tr>${t}</tr>`}render(){const r=this.columns.findIndex(e=>!e.hidden),s=this.columns.some(e=>!0===e.sortable),i=this.rows.filter(e=>!e.hidden).length;t(e`
    <style>
      :host {
        --table-divider-color: #aaa;
        --toolbar-bg-color: #f3f3f3;
        --selected-row-color: rgb(212, 212, 212);
        --selection-bg-color: #1a73e8;

        height: 100%;
        display: block;
      }
      /* Ensure that vertically we don't overflow */
      .wrapping-container {
        overflow-y: scroll;
        /* Use max-height instead of height to ensure that the
           table does not use more space than necessary. */
        height: 100%;
        position: relative;
      }

      table {
        border-spacing: 0;
        width: 100%;
        height: 100%;
        /* To make sure that we properly hide overflowing text
           when horizontal space is too narrow. */
        table-layout: fixed;
      }

      tr {
        outline: none;
      }


      tbody tr.selected {
        background-color: var(--selected-row-color);
      }

      table:focus tr.selected {
        background-color: var(--selection-bg-color)
      }

      td, th {
        padding: 1px 4px;
        /* Divider between each cell, except the first one (see below) */
        border-left: 1px solid var(--table-divider-color);
        line-height: 18px;
        height: 18px;
        user-select: text;
        /* Ensure that text properly cuts off if horizontal space is too narrow */
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
      }
      /* There is no divider before the first cell */
      td.firstVisibleColumn, th.firstVisibleColumn {
        border-left: none;
      }

      th {
        font-weight: normal;
        text-align: left;
        border-bottom: 1px solid var(--table-divider-color);
        position: sticky;
        top: 0;
        z-index: 2;
        background-color: var(--toolbar-bg-color);
      }

      .hidden {
        display: none;
      }

      [aria-sort]:hover {
        cursor: pointer;
      }

      [aria-sort="descending"]::after {
        content: " ";
        border-left: 0.3em solid transparent;
        border-right: 0.3em solid transparent;
        border-top: 0.3em solid black;
        position: absolute;
        right: 0.5em;
        top: 0.6em;
      }
      [aria-sort="ascending"]::after {
        content: " ";
        border-bottom: 0.3em solid black;
        border-left: 0.3em solid transparent;
        border-right: 0.3em solid transparent;
        position: absolute;
        right: 0.5em;
        top: 0.6em;
      }
    </style>
    <div class="wrapping-container">
      <table
        aria-rowcount=${this.rows.length}
        aria-colcount=${this.columns.length}
        @keydown=${this.onTableKeyDown}
      >
        <colgroup>
          ${this.columns.filter(e=>!e.hidden).map(t=>{const o=c(this.columns,t.id);return e`<col style=${`width: ${o}%`}>`})}
        </colgroup>
        <thead>
          <tr>
            ${this.columns.map((t,i)=>{const n=o.classMap({hidden:!0===t.hidden,firstVisibleColumn:i===r}),l=s&&i===this.focusableCell[0]&&0===this.focusableCell[1];return e`<th class=${n}
                data-grid-header-cell=${t.id}
                @click=${()=>{this.focusCell([i,0]),this.onColumnHeaderClick(t,i)}}
                title=${t.title}
                aria-sort=${o.ifDefined(this.ariaSortForHeader(t))}
                aria-colindex=${i+1}
                data-row-index='0'
                data-col-index=${i}
                tabindex=${o.ifDefined(s?l?"0":"-1":void 0)}
              >${t.title}</th>`})}
          </tr>
        </thead>
        <tbody>
          ${0===i?this.renderEmptyRow():this.rows.map((t,s)=>{const i=this.getCurrentlyFocusableCell(),[,n]=this.focusableCell,c=s+1,h=!!i&&(i===document.activeElement&&c===n),u=o.classMap({selected:h,hidden:!0===t.hidden});return e`
              <tr
                aria-rowindex=${s+1}
                class=${u}
              >${this.columns.map((s,i)=>{const n=l(t,s.id),h=o.classMap({hidden:!0===s.hidden,firstVisibleColumn:i===r}),u=i===this.focusableCell[0]&&c===this.focusableCell[1],f=d(n),m=a(n);return e`<td
                  class=${h}
                  title=${f}
                  tabindex=${u?"0":"-1"}
                  aria-colindex=${i+1}
                  data-row-index=${c}
                  data-col-index=${i}
                  data-grid-value-cell-for-column=${s.id}
                  @focus=${()=>{this.dispatchEvent(new w(n,t))}}
                  @click=${()=>{this.focusCell([i,c])}}
                >${m}</td>`})}
            `})}
        </tbody>
      </table>
    </div>
    `,this.shadow,{eventContext:this}),this.scrollToBottomIfRequired(),this.hasRenderedAtLeastOnce=!0}}customElements.define("devtools-data-grid",g);var p=Object.freeze({__proto__:null,ColumnHeaderClickEvent:m,BodyCellFocusedEvent:w,DataGrid:g});class C extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.columns=[],this.rows=[],this.originalColumns=[],this.originalRows=[],this.sortState=null}get data(){return{columns:this.originalColumns,rows:this.originalRows,filterText:this.filterText}}set data(e){this.originalColumns=e.columns,this.originalRows=e.rows,this.filterText=e.filterText,this.columns=[...this.originalColumns],this.rows=this.cloneAndFilterRows(e.rows,this.filterText),this.render()}cloneAndFilterRows(e,t){return t?e.map(e=>{const o=e.cells.some(e=>d(e).toLowerCase().includes(t.toLowerCase()));return{...e,hidden:!o}}):[...e]}sortRows(e){const{columnId:t,direction:o}=e;this.rows.sort((e,r)=>{const s=l(e,t),i=l(r,t),n=d(s).toUpperCase(),a=d(i).toUpperCase();return n<a?"ASC"===o?-1:1:n>a?"ASC"===o?1:-1:0}),this.render()}onColumnHeaderClick(e){const{column:t}=e.data;if(this.sortState&&this.sortState.columnId===t.id){const{columnId:e,direction:t}=this.sortState;this.sortState="DESC"===t?null:{columnId:e,direction:"DESC"}}else this.sortState={columnId:t.id,direction:"ASC"};this.sortState?this.sortRows(this.sortState):(this.rows=[...this.originalRows],this.render())}render(){t(e`
      <style>
        :host {
          display: block;
          height: 100%;
          overflow: hidden;
        }
      </style>
      <devtools-data-grid .data=${{columns:this.columns,rows:this.rows,activeSort:this.sortState}}
        @column-header-click=${this.onColumnHeaderClick}
      ></devtools-data-grid>
    `,this.shadow,{eventContext:this})}}customElements.define("devtools-data-grid-controller",C);var v=Object.freeze({__proto__:null,DataGridController:C});export{p as DataGrid,v as DataGridController,s as DataGridRenderers,f as DataGridUtils};
