UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

1 lines 11.8 kB
import"../../CommonImports";import"../../Core/core.css";import"./ListBox.css";import*as React from"react";import{ObservableLike}from"../../Core/Observable";import*as Utils_Accessibility from"../../Core/Util/Accessibility";import{format}from"../../Core/Util/String";import{Icon}from"../../Icon";import{renderListCell}from"../../List";import{ItemsObserver,Observer}from"../../Observer";import*as Resources from"../../Resources.Dropdown";import{Spinner,SpinnerSize}from"../../Spinner";import{ColumnSelect,SimpleTableCell,Table,TableRow}from"../../Table";import{Tree,TreeRow}from"../../TreeEx";import{css}from"../../Util";import{DropdownSelection}from"../../Utilities/DropdownSelection";import{ArrayItemProvider,getItemsValue}from"../../Utilities/Provider";import{TreeItemProvider}from"../../Utilities/TreeItemProvider";import{ListBoxItemType}from"./ListBox.Props";const DefaultListBoxWidth=-100;class ListBox extends React.Component{constructor(e){super(e),this.tabbableIndex=-1,this.positions=[],this.count=0,this.table=React.createRef(),this.tree=React.createRef(),this.getItemWidth=()=>{var e=this.props["width"];return this.multiSelect&&e&&0<e?e-40:e},this.loadingChanged=()=>{var e;return ObservableLike.getValue(this.props.loading)?Utils_Accessibility.announce(Resources.AnnounceLoadingItems):(Utils_Accessibility.announce(Resources.AnnounceFinishedLoadingItems),e=this.props.items.length,Utils_Accessibility.announce(format(0<e?format(Resources.AnnounceItemCount,e):Resources.NoFilterResults),!0)),!0},this.searchingChanged=()=>{var e;return ObservableLike.getValue(this.props.searching)?Utils_Accessibility.announce(Resources.Searching):!1===ObservableLike.getValue(this.props.searching)&&(e=this.props.items.length,Utils_Accessibility.announce(0<e?format(Resources.AnnounceFilterResultCount,e):Resources.NoFilterResults,!0)),!0},this.onItemsChanged=()=>{var e=getListBoxItemsValue(this.wrappedItems||this.props.items);this.tabbableIndex=-1,this.positions=[],this.count=0;for(const s of e){var t=ObservableLike.getValue(s);t&&!listBoxItemSelectable(t)?this.positions.push(-1):(-1===this.tabbableIndex&&this.selection.selectable(this.positions.length)&&(this.tabbableIndex=this.positions.length),this.positions.push(++this.count))}return!0},this.onActivate=(e,t)=>{this.props.onActivate&&this.props.onActivate(e,t.data)},this.onSelect=(e,t)=>{this.props.onSelect&&this.props.onSelect(e,t.data)},this.onTreeActivate=(e,t)=>{var s=this.getListBoxItems();if(this.props.onActivate&&s){const i=t.data.underlyingItem;t=s.find(e=>e.id===i.id);t&&this.props.onActivate(e,t)}},this.onTreeSelect=(e,t)=>{var s=this.getListBoxItems();if(this.props.onSelect&&s){const i=t.data.underlyingItem;t=s.find(e=>e.id===i.id);t&&this.props.onSelect(e,t)}},this.renderListBoxRow=(s,i,e)=>{var{excludeFocusZone:t,excludeTabStop:o}=this.props,t=(getListBoxItemsValue(this.wrappedItems||this.props.items),!t&&this.selection.selectable(s));const l=Object.assign(Object.assign({tooltipProps:i.tooltipProps||{text:i.text,overflowOnly:!0,overflowDetected:overflowDetected}},e),{ariaLabel:i.ariaLabel,ariaDescribedBy:i.type!==ListBoxItemType.Divider&&i.type!==ListBoxItemType.Header&&i.groupId?"__bolt-"+i.groupId:void 0,ariaPosInSet:0<=this.positions[s]?this.positions[s]:null,ariaSetSize:0<=this.positions[s]?this.count:null,excludeTabStop:o||this.tabbableIndex!==s,excludeFocusZone:!t,id:i.id,singleClickActivation:!1,role:i.type===ListBoxItemType.Header||i.type===ListBoxItemType.Divider?"presentation":"option"});return React.createElement(Observer,{key:i.id||s,item:i},()=>React.createElement(TableRow,{key:i.id||s,index:s,details:l,className:css("bolt-list-box-row",i.type===ListBoxItemType.Header&&"bolt-list-box-header-row",i.type===ListBoxItemType.Divider&&"bolt-list-box-divider-row",i.type===ListBoxItemType.Loading&&"bolt-list-box-loading-row",this.multiSelect&&"bolt-list-box-multi-select-row",i.type!==ListBoxItemType.Header&&i.type!==ListBoxItemType.Divider&&"cursor-pointer",i.disabled&&"bolt-list-box-item-disabled")},this.columns.map((e,t)=>{if(this.multiSelect&&0===t){if(i.type===ListBoxItemType.Divider||i.type===ListBoxItemType.Loading)return null;if(i.type===ListBoxItemType.Header)return React.createElement("span",{className:"bolt-table-cell bolt-list-cell bolt-header-cell","data-column-index":"0",role:"presentation"})}return(e=Object.assign(Object.assign({},e),{className:"dropdown-list"})).renderCell(s,t,e,i)})))},this.renderListBoxTreeRow=(s,i,e)=>{var{excludeFocusZone:t,excludeTabStop:o}=this.props,t=!t&&this.selection.selectable(s);const l=i.underlyingItem.data,r=Object.assign(Object.assign({tooltipProps:{text:i.underlyingItem.text,overflowOnly:!0,overflowDetected:overflowDetected}},e),{ariaPosInSet:0<=this.positions[s]?this.positions[s]:null,ariaSetSize:0<=this.positions[s]?this.count:null,excludeTabStop:o||this.tabbableIndex!==s,excludeFocusZone:!t,id:i.underlyingItem.id,singleClickActivation:!1,role:l.type===ListBoxItemType.Header||l.type===ListBoxItemType.Divider?"row":"treeitem"});return React.createElement(Observer,{key:"observer-"+(i.underlyingItem.id||s),item:i},()=>React.createElement(TreeRow,{key:"row-"+(i.underlyingItem.id||s),index:s,details:r,className:css("bolt-list-box-row",l.type===ListBoxItemType.Header&&"bolt-list-box-header-row",l.type===ListBoxItemType.Divider&&"bolt-list-box-divider-row",l.type===ListBoxItemType.Loading&&"bolt-list-box-loading-row",this.multiSelect&&"bolt-list-box-multi-select-row",l.type!==ListBoxItemType.Header&&l.type!==ListBoxItemType.Divider&&"cursor-pointer",l.disabled&&"bolt-list-box-item-disabled")},this.columns.map((e,t)=>e.renderCell(s,t,e,i))))},this.renderListBoxCell=(e,t,s,i)=>renderListBoxCell(e,t,s,i,this.multiSelect);var{selection:e,renderItem:t,items:s}=this.props;this.selection=e||new DropdownSelection,this.multiSelect=!this.props.enforceSingleSelect&&!this.props.showTree&&this.selection.multiSelect,this.props.columns?this.columns=this.props.columns:(this.columns=[],this.multiSelect&&!1!==this.props.showChecksColumn?this.columns.push(new ColumnSelect({excludeFocusZone:!0})):this.multiSelect||!0!==this.props.showChecksColumn||this.columns.push({id:"column-check",width:24,renderCell:(e,t)=>React.createElement("div",{className:"dropdown-list checkmark-icon","data-column-index":t,key:"column-check",role:"presentation"},React.createElement(Icon,{ariaHidden:"removed",className:css(!this.selection.selected(e)&&"invisible"),iconName:"CheckMark"})),readonly:!0}),this.columns.push({id:"text",width:this.getItemWidth(),renderCell:t||this.renderListBoxCell,className:css("bolt-list-box-text",this.multiSelect?"bolt-list-box-text-multi-select":"bolt-list-box-text-single-select"),readonly:!0})),this.wrappedItems=wrapListBoxItems(s),this.onItemsChanged()}componentDidUpdate(){this.props.didUpdate&&this.props.didUpdate()}render(){const{ariaLabel:t,className:i,containerClassName:o,enforceSingleSelect:l,focuszoneProps:r,getUnselectableRanges:e,items:s,loading:n,searching:a,searchResultsLoadingText:c,showItemsWhileSearching:m,width:d}=this.props;var p={observableValue:s,filter:this.onItemsChanged},h=this.getListBoxItems();const u=h?this.props.showTree?new TreeItemProvider(convertListBoxItemsToTreeItems(h)):new ArrayItemProvider(h):s;return this.props.columns||(this.columns[this.columns.length-1].width=this.getItemWidth()),React.createElement(ItemsObserver,{getUnselectableRanges:e,items:s,selection:this.selection},React.createElement(Observer,{items:p,loading:{observableValue:n||!1,filter:this.loadingChanged},searching:{observableValue:a||!1,filter:this.searchingChanged}},e=>{if(e.searching&&!m)return React.createElement("div",{className:"bolt-list-box-loading",style:{width:d}},React.createElement(Spinner,{size:SpinnerSize.medium,label:c||Resources.Searching}));if(this.props.showTree){const s=u;return React.createElement(Tree,{ariaLabel:t||void 0,className:css(i,"bolt-list-box","bolt-list-box-tree"),columns:this.columns,containerClassName:o,focuszoneProps:r,itemProvider:s,onActivate:this.onTreeActivate,onSelect:this.onTreeSelect,onToggle:(e,t)=>{e.target.className.includes("bolt-tree-expand-button")&&(s.toggle(t.underlyingItem),this.props.onToggle)&&this.props.onToggle(e,t.underlyingItem.data)},ref:this.tree,renderRow:this.renderListBoxTreeRow,role:"listbox",scrollable:!0,singleClickActivation:!1,selection:this.selection,showHeader:!1,showLines:!1})}return React.createElement(Table,{ariaLabel:t||void 0,className:css(i,"bolt-list-box"),columns:this.columns,containerClassName:o,enforceSingleSelect:l,focuszoneProps:r,itemProvider:u,onActivate:this.onActivate,onSelect:this.onSelect,renderRow:this.renderListBoxRow,ref:this.table,role:"listbox",scrollable:!0,singleClickActivation:!1,selection:this.selection,showHeader:!1,showLines:!1,spacerWidth:0})}))}scrollIntoView(e,t){return this.table.current?this.table.current.scrollIntoView(e,t):this.tree.current?this.tree.current.scrollIntoView(e,t):void 0}getListBoxItems(){var e;return null!=(e=null!=(e=this.wrappedItems)?e:this.props.items&&(Array.isArray(this.props.items)?this.props.items:this.props.items.value))?e:void 0}}function renderListBoxCell(e,t,s,i,o){return i.render?i.render(e,t,s,i):i.type===ListBoxItemType.Divider?React.createElement(SimpleTableCell,{className:css(s.className,i.className,o&&"bolt-list-box-divider-multi-select"),columnIndex:t,colspan:o?2:1,key:i.id,role:"presentation",tableColumn:s},React.createElement("div",{className:"bolt-list-box-divider flex-grow"})):i.type===ListBoxItemType.Loading?React.createElement(LoadingCell,{columnIndex:t,key:i.id,tableColumn:s,tableItem:i}):React.createElement(SimpleTableCell,{className:css(s.className,i.className,i.type===ListBoxItemType.Header&&"bolt-list-box-header"),columnIndex:t,key:i.id,role:"presentation",tableColumn:s},React.createElement("div",{id:i.type===ListBoxItemType.Header?"header-"+i.groupId:void 0,"aria-label":void 0,className:"bolt-list-box-cell-container"},i&&renderListCell(i,!1)))}function overflowDetected(e){e=e.querySelector(".text-ellipsis");return!!e&&e.scrollWidth>Math.ceil(e.offsetWidth)}function getUnselectableRanges(t,s=listBoxItemSelectable){var i=[];let o=-1;for(let e=0;e<t.length;e++)!s(t[e])&&o<0?o=e:s(t[e])&&0<=o&&(i.push({beginIndex:o,endIndex:e-1}),o=-1);return 0<=o&&i.push({beginIndex:o,endIndex:t.length-1}),i}function listBoxItemSelectable(e){return e.type!==ListBoxItemType.Header&&e.type!==ListBoxItemType.Divider&&e.type!==ListBoxItemType.Loading&&!e.disabled}function wrapListBoxItems(e){if(Array.isArray(e)&&e.length&&"string"==typeof e[0])return e.map(e=>({id:e,text:e}))}function convertListBoxItemsToTreeItems(e){var t=[],s=new Map;for(const l of e){var i,o=s.get(l.id),o={childItems:null==o?void 0:o.childItems,expanded:l.expanded,data:l,id:l.id,text:l.text};l.parent?(i=s.get(l.parent.id))?i.childItems?i.childItems.push(o):i.childItems=[o]:s.set(l.parent.id,{childItems:[o]}):t.push(o),s.set(o.id,o)}return t}function getListBoxItemsValue(e){return getItemsValue(e)}ListBox.defaultProps={getUnselectableRanges:getUnselectableRanges,width:DefaultListBoxWidth};class LoadingCell extends React.Component{componentDidMount(){this.props.onMount&&this.props.onMount()}render(){var{columnIndex:e,tableColumn:t,tableItem:s}=this.props;return React.createElement(SimpleTableCell,{className:css(t.className,s.className),columnIndex:e,colspan:2,contentClassName:"justify-center",key:e,tableColumn:t},React.createElement("div",{className:"bolt-list-box-loading"},React.createElement(Spinner,{size:SpinnerSize.medium,label:Resources.Loading})))}}function isListBoxItemVisible(e){let t=e.parent;for(;t;){if(!t.expanded)return!1;t=t.parent}return!0}export{DefaultListBoxWidth,ListBox,renderListBoxCell,getUnselectableRanges,listBoxItemSelectable,wrapListBoxItems,convertListBoxItemsToTreeItems,getListBoxItemsValue,LoadingCell,isListBoxItemVisible};