@deephaven/embed-grid 0.9.3-fix-fontawesome.2 → 0.9.4-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../icons/dist/index.es.js","../../src/ThemeExport.ts","../../src/LoadingSpinner.tsx","../../src/LoadingOverlay.tsx","../../src/LoggerLevel.js","../../src/Logger.js","../../src/DefaultLogger.js","../../src/LogProxy.ts","../../src/Log.js","../../src/CanceledPromiseError.ts","../../src/DbNameValidator.ts","../../src/DOMUtils.ts","../../src/EventTargetShimUtils.ts","../../src/TimeoutError.ts","../../src/PromiseUtils.ts","../../src/Pending.ts","../../src/RangeUtils.ts","../../src/TextUtils.ts","../../src/TimeUtils.ts","../../src/InvalidMetadataError.ts","../../src/ValidationError.ts","../../../src/context-actions/ContextActionUtils.ts","../../../src/context-actions/ContextMenuItem.tsx","../../../src/context-actions/ContextMenu.tsx","../../../src/context-actions/ContextMenuRoot.tsx","../../src/dh.ts","../../src/PropTypes.js","../../src/DateUtils.ts","../../../src/filters/FilterType.ts","../../../src/filters/FilterOperator.ts","../../src/TableUtils.ts","../../../src/formatters/TableColumnFormatter.ts","../../../src/formatters/DefaultColumnFormatter.ts","../../../src/formatters/BooleanColumnFormatter.ts","../../../src/formatters/CharColumnFormatter.ts","../../../src/formatters/DateTimeColumnFormatter.ts","../../../src/formatters/DecimalColumnFormatter.ts","../../../src/formatters/IntegerColumnFormatter.ts","../../../src/formatters/StringColumnFormatter.ts","../../src/Formatter.ts","../../../src/errors/AssertionError.ts","../../../src/errors/assertIsDefined.ts","../../../src/errors/PasteError.ts","../../src/EditableGridModel.ts","../../src/ExpandableGridModel.ts","../../src/GridRange.ts","../../src/GridUtils.ts","../../src/GridMetricCalculator.ts","../../src/GridTheme.ts","../../src/memoizeClear.ts","../../src/GridColorUtils.ts","../../src/GridRenderer.ts","../../src/GridMouseHandler.ts","../../../src/mouse-handlers/GridSelectionMouseHandler.ts","../../../src/mouse-handlers/GridColumnMoveMouseHandler.ts","../../../src/mouse-handlers/GridSeparatorMouseHandler.ts","../../../src/mouse-handlers/GridColumnSeparatorMouseHandler.ts","../../../src/mouse-handlers/GridHorizontalScrollBarMouseHandler.ts","../../../src/mouse-handlers/GridRowMoveMouseHandler.ts","../../../src/mouse-handlers/GridRowSeparatorMouseHandler.ts","../../../src/mouse-handlers/GridRowTreeMouseHandler.ts","../../../src/mouse-handlers/GridScrollBarCornerMouseHandler.ts","../../../src/mouse-handlers/GridVerticalScrollBarMouseHandler.ts","../../../src/mouse-handlers/EditMouseHandler.ts","../../src/KeyHandler.ts","../../../src/key-handlers/SelectionKeyHandler.ts","../../../src/key-handlers/TreeKeyHandler.ts","../../../src/key-handlers/EditKeyHandler.ts","../../../src/key-handlers/PasteKeyHandler.ts","../../src/CellInputField.tsx","../../src/Grid.tsx","../../src/GridModel.ts","../../src/MockGridModel.ts","../../src/MockTreeGridModel.ts","../../src/IrisGridModel.js","../../../../src/sidebar/aggregations/AggregationOperation.ts","../../../src/sidebar/AdvancedSettingsType.ts","../../../src/sidebar/AdvancedSettings.ts","../../../../src/sidebar/aggregations/AggregationUtils.ts","../../src/IrisGridUtils.js","../../src/MissingKeyError.ts","../../src/IrisGridTableModel.js","../../src/IrisGridTreeTableModel.js","../../src/IrisGridProxyModel.js","../../src/IrisGridModelFactory.js","../../src/DeephavenSpinner.tsx","../../../src/popper/Popper.tsx","../../../src/popper/Tooltip.tsx","../../src/usePrevious.ts","../../../src/navigation/Stack.tsx","../../../src/navigation/Page.tsx","../../src/UISwitch.tsx","../../../src/navigation/MenuItem.tsx","../../../src/navigation/Menu.tsx","../../../src/context-actions/GlobalContextAction.tsx","../../../src/context-actions/GlobalContextActions.tsx","../../../src/context-actions/ContextActions.tsx","../../src/Button.tsx","../../src/IrisGridBottomBar.tsx","../../src/PendingDataBottomBar.tsx","../../src/IrisGridCopyHandler.jsx","../../src/FilterInputField.jsx","../../../src/shortcuts/Shortcut.ts","../../../src/shortcuts/ShortcutRegistry.ts","../../src/IrisGridShortcuts.ts","../../../src/key-handlers/ReverseKeyHandler.ts","../../../src/key-handlers/ClearFilterKeyHandler.ts","../../../src/key-handlers/CopyKeyHandler.ts","../../../src/mousehandlers/IrisGridColumnSelectMouseHandler.js","../../../src/mousehandlers/IrisGridColumnTooltipMouseHandler.js","../../../src/mousehandlers/IrisGridSortMouseHandler.js","../../../src/mousehandlers/IrisGridFilterMouseHandler.js","../../../src/shortcuts/GlobalShortcuts.ts","../../../src/format-context-menus/CustomFormatAction.tsx","../../../src/format-context-menus/FormatContextMenuUtils.tsx","../../../src/format-context-menus/DateTimeFormatContextMenu.ts","../../../src/format-context-menus/DecimalFormatContextMenu.ts","../../../src/format-context-menus/IntegerFormatContextMenu.ts","../../../src/mousehandlers/IrisGridContextMenuHandler.jsx","../../../src/mousehandlers/IrisGridDataSelectMouseHandler.js","../../../src/mousehandlers/PendingMouseHandler.js","../../src/ToastBottomBar.tsx","../../src/IrisGridMetricCalculator.ts","../../src/IrisGridModelUpdater.jsx","../../src/IrisGridRenderer.js","../../src/IrisGridTheme.ts","../../src/ColumnStatistics.jsx","../../src/FormatterUtils.ts","../../src/AdvancedFilterCreatorFilterItem.tsx","../../src/Checkbox.tsx","../../src/useForwardedRef.ts","../../src/SelectValueList.tsx","../../src/AdvancedFilterCreatorSelectValueList.jsx","../../src/AdvancedFilterCreatorSelectValue.jsx","../../src/AdvancedFilterCreator.jsx","../../../src/sidebar/OptionType.ts","../../src/SearchInput.tsx","../../../src/sidebar/VisibilityOrderingBuilder.jsx","../../src/RadioGroup.tsx","../../src/RadioItem.tsx","../../../src/sidebar/TableCsvExporter.jsx","../../../../src/sidebar/icons/LineIcon.tsx","../../../../src/sidebar/icons/BarIcon.tsx","../../../../src/sidebar/icons/ScatterIcon.tsx","../../../../src/sidebar/icons/PieIcon.tsx","../../../../src/sidebar/icons/HistogramIcon.tsx","../../../src/sidebar/ChartBuilder.jsx","../../src/DragUtils.ts","../../../src/sidebar/InputEditor.jsx","../../../src/sidebar/CustomColumnInput.jsx","../../../src/sidebar/CustomColumnBuilder.jsx","../../src/ItemListItem.tsx","../../src/ItemList.tsx","../../src/DraggableItemList.tsx","../../src/ButtonOld.jsx","../../../src/sidebar/RollupRows.jsx","../../src/Select.tsx","../../src/Option.tsx","../../../../src/sidebar/aggregations/Aggregations.tsx","../../../../src/sidebar/aggregations/AggregationEdit.tsx","../../../src/sidebar/TableSaver.jsx","../../src/CrossColumnSearch.jsx","../../../src/menu-actions/Menu.tsx","../../../src/menu-actions/DropdownMenu.tsx","../../src/PartitionSelectorSearch.jsx","../../src/IrisGridPartitionSelector.jsx","../../../src/sidebar/SelectDistinctBuilder.jsx","../../../src/sidebar/AdvancedSettingsMenu.tsx","../../src/IrisGrid.jsx","App.tsx","index.tsx","../../src/TestUtils.ts","../../iris-grid/dist/IrisGridTheme.module.css","../../components/dist/ThemeExport.module.css"],"names":["vsCheck","prefix","iconName","icon","vsChevronDown","vsChevronLeft","vsChevronRight","vsChevronUp","vsCircleLargeFilled","vsCircleLargeOutline","vsClose","vsCloudDownload","vsCopy","vsEdit","vsFilter","vsGripper","vsIssues","vsLink","vsLoading","vsLock","vsMenu","vsPassFilled","vsPass","vsRemove","vsRuby","vsSearch","vsSplitHorizontal","vsSymbolOperator","vsTools","vsTrash","vsTriangleDown","vsTriangleRight","vsWarning","dhArrowToBottom","dhArrowToTop","dhCheckSquare","dhEyeSlash","dhEye","dhFilterFilled","dhFreeze","dhGearFilled","dhGraphLineUp","dhNewCircleLargeFilled","dhRefresh","dhRemoveSquareFilled","dhSortAlphaDown","dhSortAlphaUp","dhSortAmountDown","dhSortDown","dhSortUp","dhSquareFilled","dhTable","dhTriangleDownSquare","dhUnlink","dhWarningCircleFilled","dhWarningFilled","Object","transitionMs","transitionMidMs","transitionLongMs","transitionSlowMs","className","classNames","spin","isLoaded","isLoading","errorMessage","in","timeout","ThemeExport","mountOnEnter","unmountOnExit","DEBUG2","silent","constructor","name","level","this","setLogLevel","ERROR","console","WARN","INFO","DEBUG","super","envValue","process","LoggerLevel","envLevel","parseInt","Number","getDefaultLevel","module","modules","keys","i","LOG_PROXY_TYPE","CanceledPromiseError","Error","COLUMN_PREFIX","DB_RESERVED_VARIABLE_NAMES","Set","JAVA_KEYWORDS","STERILE_TABLE_AND_NAMESPACE_REGEX","STERILE_COLUMN_AND_QUERY_REGEX","DbNameValidator","legalName","checkReserved","headers","legalHeaders","header","legalHeader","getClosestByClassName","element","EventShimCustomEvent","typeArg","TimeoutError","hasCanceled","wrappedPromise","Promise","resolve","reject","val","cleanup","resolved","error","add","promise","PromiseUtils","remove","pending","cancel","allPromises","RangeUtils","range","selectedRanges","start","end","index","ranges","selectedRange","selectedStart","selectedEnd","Math","sum","items","conjunction","itemText","lastItem","text","a","isAscending","TimeUtils","time","hours","mins","seconds","timeInSeconds","String","divisorForMinutes","minutes","divisorForSeconds","s","RegExp","timeString","components","label","value","ValidationError","ContextActionUtils","e","Array","b","actions","sortedActions","platform","window","event","permissions","navigator","oldFocus","document","textArea","includePromises","menuItems","action","newMenuItems","firstIndex","delta","menuIndex","item","ContextMenuItem","props","onMenuItemMouseMove","menuItem","isMouseSelected","displayShortcut","menuItemIcon","React","style","color","iconColor","subMenuIndicator","isSubMenuActive","content","onMouseMove","handleMenuItemMouseMove","type","forwardedProps","renderCustomMenuElement","menuItemDisabled","iconHasOutline","disabled","active","isKeyboardSelected","onClick","onMenuItemClick","onContextMenu","onMenuItemContextMenu","title","outline","ref","children","log","Log","handleBlur","bind","handleCloseSubMenu","handleKeyDown","handleMenuItemClick","handleMenuItemContextMenu","handleMouseLeave","handleWindowResize","top","left","pendingItems","activeSubMenu","hasOverflow","subMenuTop","subMenuLeft","subMenuParentWidth","subMenuParentHeight","keyboardIndex","mouseIndex","componentDidMount","onMenuOpened","componentDidUpdate","prevState","prevProps","container","componentWillUnmount","cancelAnimationFrame","getKeyboardIndex","options","setKeyboardIndex","getMouseIndex","setMouseIndex","initMenu","nonPromiseItems","initMenuPromise","cancellablePromise","state","resolvedMenuItems","cancelPromises","setActiveSubMenuPosition","activeSubMenuRef","current","parentRect","width","verifyPosition","oldLeft","height","oldTop","updatePosition","contains","isContextMenuChild","isEscapeKey","key","newFocus","openSubMenu","newSubMenu","closeMenu","closeAll","onMenuClosed","closeSubMenu","closeAllMenus","focusIndex","render","menuItemElements","menuItemElement","pendingElement","menuStyle","showSubmenu","onBlur","onKeyDown","onMouseLeave","ContextMenu","role","tabIndex","verifiedTop","verifiedLeft","handleMenuClose","handleContextMenu","contextActions","mouseEvent","MouseEvent","clientX","clientY","bubbles","cancelable","menu","openMenu","dh","Column","PropTypes","description","constituentType","string","FilterCondition","not","and","or","isRequired","Sort","asc","desc","abs","column","direction","isAbs","Table","columns","customColumns","filter","addEventListener","removeEventListener","size","sort","copy","applyFilter","applySort","applyCustomColumns","TreeTable","isExpanded","saveExpandedState","VariableDefinition","VariableChanges","created","updated","removed","RollupConfig","groupingColumns","aggregations","includeConstituents","includeOriginalColumns","includeDescriptions","bool","IdeSession","onLogMessage","getTable","runCode","month","day","hour","minute","second","ns","yearString","monthString","dayString","hourString","minuteString","secondString","nanoString","dateString","DateUtils","sigNanos","zeros","repeat","nextNanoString","nanos","date","year","jsDate","Date","cleanMonthString","parseMonth","dateTimeString","result","regex","overflow","cleanText","now","values","dateWrapper","FilterType","FilterOperator","tableSort","sortIndex","TableUtils","columnType","table","columnIndex","addToExisting","newSort","modelColumn","sorts","type1","orComponents","orFilter","andComponents","orComponent","andFilter","j","andComponent","makeQuickNumberFilter","makeQuickBooleanFilter","makeQuickDateFilter","makeQuickCharFilter","makeQuickTextFilter","columnFilter","operation","negativeSign","abnormalValue","parseFloat","suffix","notEqual","cleanValue","boolValue","dateText","filterOperation","eq","timeZone","startDate","endDate","startValue","endValue","startFilter","endFilter","matcher","isPending","timeoutId","setTimeout","eventCleanup","clearTimeout","selectedValues","filterItems","filterItem","selectedType","newFilter","filterOperators","filterOperator","err","selectValueFilter","numberText","filterValue","eqFilter","notEqFilter","isNullSelected","aName","bName","TextUtils","BOOLEAN","CHAR","DATETIME","DECIMAL","INT","STRING","ascending","descending","reverse","none","NONE","PRE_SORT","POST_SORT","TableColumnFormatter","format","TYPE_CONTEXT_PRESET","formatA","formatB","separator","showTSeparator","tz","showTimeZone","Map","DateTimeColumnFormatter","timeZoneParam","defaultDateTimeFormatString","DEFAULT_DATETIME_FORMAT_STRING","getEffectiveFormatString","baseFormatString","formatStringMap","get","formatString","multiplier","DecimalColumnFormatter","defaultFormatString","DEFAULT_FORMAT_STRING","valueParam","IntegerColumnFormatter","columnFormattingRules","map","next","dataType","formatMap","dateTimeOptions","decimalFormatOptions","integerFormatOptions","Formatter","getColumnFormatMapForType","createIfNecessary","columnFormatMap","has","getColumnFormat","getColumnTypeFormatter","columnTypeFormatter","typeFormatterMap","getFormattedString","columnName","formatOverride","formatter","AssertionError","PasteError","isEditableGridModel","model","assertIsEditableGridModel","isExpandableGridModel","SELECTION_DIRECTION","GridRange","right","bottom","row","index1","index2","wasModified","other","endRow","startColumn","endColumn","startRow","start1","end1","start2","end2","ranges1","ranges2","otherRange","subtract","subtractRanges","columnCount","rowCount","r","DOWN","rangeIndex","nextCell","nextRange","cellCount","RIGHT","equals","containsCell","touches","startCell","forEach","c","callback","GridUtils","total","visibleStartIndex","visibleEndIndex","totalCount","itemX","itemCoordinates","itemSize","itemSizes","coordinate","floatingItem","gridX","x","getItemAtOffset","y","gridY","visibleItemIndex","visibleItems","modelIndex","modelIndexes","userSizes","userColumnWidths","userRowHeights","visibleColumnWidths","headerSeparatorHandleSize","columnHeaderHeight","halfSeparatorSize","isPreviousColumnHidden","floatingColumns","columnX","visibleColumnXs","columnWidth","isColumnHidden","midX","minX","visibleColumns","floatingLeftWidth","itemIndex","visibleSizes","hiddenItems","visibleRowHeights","rowHeaderWidth","isPreviousRowHidden","visibleRows","rowY","visibleRowYs","rowHeight","isRowHidden","midY","minY","rowIndex","oldMovedItems","from","movedItems","to","movedItem","nextResult","currentStart","currentEnd","startLength","movedColumns","movedRows","columnRanges","uiRange","rowRanges","modelRanges","uiRanges","visibleIndex","x1","y1","x2","y2","pageWidth","pageHeight","lineWidth","lineHeight","deltaY","wheelEvent","deltaX","WheelEvent","getOrThrow","defaultValue","undefined","trimMap","cacheSize","GridMetricCalculator","CACHE_SIZE","targetSize","iter","getFloatingCoordinates","coordinates","sizeMap","calculatedColumnWidths","calculatedRowHeights","fontWidths","modelRows","modelColumns","getMetrics","scrollBarSize","floatingRightColumnCount","firstRow","getFirstRow","firstColumn","getFirstColumn","getGridX","getGridY","treePaddingX","calculateTreePaddingX","getVisibleRowHeights","getVisibleColumnWidths","getFloatingRowHeights","getFloatingColumnWidths","getVisibleColumnXs","getVisibleRowYs","bottomViewport","getBottomViewport","rightViewport","getRightViewport","columnWidthValues","rowHeightValues","maxX","w","maxY","h","floatingBottomHeight","getFloatingBottomHeight","lastLeft","getLastLeft","lastTop","getLastTop","hasHorizontalBar","hasVerticalBar","horizontalBarHeight","verticalBarWidth","barWidth","barHeight","handleWidth","handleHeight","leftColumnWidth","topRowHeight","scrollX","leftOffset","scrollY","topOffset","floatingRows","floatingTopRowCount","floatingBottomRowCount","getFloatingRowYs","floatingLeftColumnCount","getFloatingColumnXs","allRows","allColumns","getModelRows","getModelColumns","visibleRowTreeBoxes","getVisibleRowTreeBoxes","topVisible","getTopVisible","leftVisible","getLeftVisible","bottomVisible","getBottomVisible","rightVisible","getRightVisible","floatingTopHeight","getFloatingTopHeight","getFloatingLeftWidth","floatingRightWidth","getFloatingRightWidth","theme","getVisibleHeight","getVisibleWidth","rowFooterWidth","getFirstIndex","max","getModelIndex","getModelColumn","getModelRow","visibleWidth","getVisibleColumnWidth","visibleHeight","getVisibleRowHeight","getTopForTopVisible","getTopForBottomVisible","availableHeight","getLeftForLeftVisible","getLeftForRightVisible","availableWidth","rowHeights","columnWidths","treeHorizontalPadding","modelRow","depth","floatingWidth","floatingHeight","getLastIndexViewport","lastIndex","dataSize","itemXs","maxSize","getVisibleItemSize","calculateSize","calculateRowHeight","calculateColumnWidth","visibleRow","visibleColumn","cachedValue","minColumnWidth","headerWidth","calculateColumnHeaderWidth","dataWidth","calculateColumnDataWidth","headerHorizontalPadding","headerText","headerFontWidth","getWidthForFont","headerFont","fontWidth","font","rowsPerPage","cellPadding","cellHorizontalPadding","treeDepthIndent","treePadding","context","textMetrics","setColumnWidth","resetColumnWidth","setRowHeight","resetRowHeight","allowColumnResize","allowRowResize","autoSelectRow","autoSelectColumn","autoSizeColumns","autoSizeRows","backgroundColor","gridColumnColor","gridRowColor","headerBackgroundColor","headerSeparatorColor","headerSeparatorHoverColor","headerHiddenSeparatorSize","headerHiddenSeparatorHoverColor","headerColor","columnHoverBackgroundColor","selectedColumnHoverBackgroundColor","rowBackgroundColors","rowHoverBackgroundColor","selectedRowHoverBackgroundColor","minScrollHandleSize","scrollBarBackgroundColor","scrollBarHoverBackgroundColor","scrollBarCasingColor","scrollBarCornerColor","scrollBarColor","scrollBarHoverColor","scrollBarActiveColor","scrollBarHoverSize","scrollBarCasingWidth","scrollSnapToColumn","scrollSnapToRow","selectionColor","selectionOutlineColor","selectionOutlineCasingColor","shadowBlur","shadowColor","textColor","maxDepth","treeLineColor","treeMarkerColor","treeMarkerHoverColor","minRowHeight","headerResizeSnapThreshold","headerResizeHiddenSnapThreshold","allowColumnReorder","allowRowReorder","reorderOffset","floatingGridColumnColor","floatingGridRowColor","floatingRowBackgroundColors","floatingDividerOuterColor","floatingDividerInnerColor","fn","isClearingCache","memoizedFn","memoizee","dispose","g","convert","darkenForDepth","lab","memoizeClear","GridRenderer","backgroundColors","colors","GridColorUtils","alpha","str","len","length","lo","hi","mid","truncatedStr","DEFAULT_FONT_WIDTH","drawCanvas","configureContext","drawBackground","metrics","drawGrid","draggingColumn","draggingRow","drawFloatingRows","drawFloatingColumns","drawFloatingBorders","drawGridBackground","drawHover","drawRowStripes","drawRowStripesForRows","colorSets","getCachedBackgroundColors","colorRowMap","topShadowRows","bottomShadowRows","addRowToColorMap","colorSet","rowAbove","depthAbove","rows","colorRows","startColor","getCachedColorWithAlpha","endColor","gradient","gradientY","drawMouseColumnHover","mouseX","mouseY","mouseColumn","drawMouseRowHover","mouseRow","drawFloatingMouseRowHover","drawMouseRowHoverForRow","drawGridLines","drawGridLinesForItems","columnColor","drawGridLinesForColumns","drawGridLinesForRows","metricsMaxX","drawCellBackgrounds","drawCellBackgroundsForItems","rowAfter","drawCellBackground","isFirstColumn","hasExpandableRows","drawCellContents","drawColumnCellContents","drawCellContent","textOverride","textAlign","treeIndent","textWidth","textX","textY","truncatedText","getCachedTruncatedString","drawCellRowTreeMarker","treeBox","drawTreeMarker","markerText","drawCellRowTreeDepthLines","depthRowAfter","depthDiff","lineX","drawHeaders","drawFooters","drawColumnHeaders","isDragging","hiddenSeparatorHeight","hiddenY","containsFrozenColumns","floatingLeftColumnsWidth","hiddenColumns","highlightedSeparator","draggingColumnSeparator","visibleColumnIndex","nextColumn","nextColumnWidth","isNextColumnHidden","drawColumnHeader","maxLength","drawRowHeaders","draggingRowSeparator","hiddenSeparatorWidth","hiddenX","hiddenRows","visibleRowIndex","nextRow","nextRowHeight","isNextRowHidden","drawRowHeader","drawRowFooters","drawSelectedRanges","viewport","cursorColumn","cursorRow","isCursorVisible","editingCell","endX","endY","drawActiveCell","borderWidth","ACTIVE_CELL_BORDER_WIDTH","drawRoundedRect","DEFAULT_EDGE_RADIUS","drawDraggingColumn","draggingColumnOffset","drawDraggingRow","draggingRowOffset","drawScrollBars","isInbounds","isVerticalBarHover","isDraggingVerticalScrollBar","isHorizontalBarHover","isDraggingHorizontalScrollBar","hScrollBarSize","vScrollBarSize","order","onDown","onMove","onDrag","onLeave","onDoubleClick","onUp","onWheel","gridMouseX","gridMouseY","isModifierKey","isShiftKey","grid","gridPoint","startPoint","dragBounds","moveSelection","selectionEndColumn","selectionEndRow","startTimer","lastTriggerTime","stopTimer","timer","draggingOffset","startingGridPoint","leftColumn","rightColumn","minMoveX","maxMoveX","separatorIndex","getSeparatorIndex","getHiddenItems","draggingIndex","point","visibleOffsets","margin","calculatedSizes","newSizes","resizeIndex","resizingItems","targetSizes","isResizingMultiple","hiddenIndex","indexOf","calculatedSize","newSize","getNextShownItem","metricCalculator","updateCursor","addTargetSize","removeTargetSize","GridColumnSeparatorMouseHandler","checkAllowResize","setSize","resetSize","updateSeparator","leftOffsetPercent","rawLeft","metricState","isInScrollBar","mouseBarX","newLeftOffset","GridHorizontalScrollBarMouseHandler","dragOffset","topRow","bottomRow","minMoveY","maxMoveY","GridRowSeparatorMouseHandler","GridRowTreeMouseHandler","isInCorner","topOffsetPercent","rawTop","mouseBarY","newTopOffset","GridVerticalScrollBarMouseHandler","handleArrowMove","handlePageUp","handlePageDown","maximizePreviousRange","moveToColumn","moveToRow","deltaColumn","deltaRow","clamp","selectRangeEndPosition","viewportPosition","lastRowIndex","handleExpandKey","dummyInput","listener","data","cells","rowData","cell","parseValueFromTable","childNodes","hasTabChar","hasFirefoxTab","nodes","node","parseValueFromNodes","parseValueFromElement","preventDefault","stopPropagation","CellInputField","selectionRange","propsValue","isQuickEdit","propsIsQuickEdit","onChange","onCancel","onDone","inputField","useRef","isCancelled","initialValue","useState","isChanged","setIsChanged","setIsQuickEdit","setValue","useEffect","field","sendUpdate","useCallback","newValue","handleChange","handleCancel","handleClick","handleCommit","fillRange","directionForKey","autoComplete","autoCorrect","autoCapitalize","spellCheck","legacyContext","cursor","memoize","keyHandlers","mouseHandlers","handleEditCellCancel","handleEditCellChange","handleEditCellCommit","handleDoubleClick","handleMouseDown","handleMouseDrag","handleMouseMove","handleMouseUp","handleResize","handleWheel","renderer","selectionStartRow","selectionStartColumn","lastSelectedRanges","isStuckToRight","passive","onMoveRowComplete","isStickyBottom","isStickyRight","prevPropMovedRows","prevStateMovedRows","currentStateMovedRows","prevPropMovedColumns","prevStateMovedColumns","onMovedColumnsChanged","onMoveColumnComplete","onMovedRowsChanged","isStuckToBottom","prevWidth","prevRowCount","prevColumnCount","animationFrame","getTheme","Grid","getGridPointFromEvent","assertIsDefined","rect","canvas","getGridPointFromXY","getMetricState","stateOverride","getKeyHandlers","getCachedKeyHandlers","getMouseHandlers","getCachedMouseHandlers","toggleRowExpanded","setSelectedRanges","gridRanges","newCursorRow","newCursorColumn","initContext","canvasOptions","requestUpdateCanvas","requestAnimationFrame","updateCanvas","updateMetrics","onViewChanged","updateCanvasScale","canvasContext","scale","checkSelectionChange","oldSelectedRanges","onSelectionChanged","validateSelection","clearSelectedRanges","trimSelectedRanges","beginSelection","extendSelection","lastSelectedRange","newRanges","selectedColumn","selectedRow","commitSelection","newSelectedRanges","lastRange","remainder","nextCursor","selectAll","moveCursor","moveCursorInDirection","gridRange","moveCursorToPosition","keepCursorInView","moveViewToCell","setViewState","viewState","forceUpdate","startEditing","isValidForCell","pasteValue","edits","tableHeight","tableWidth","onError","setValueForCell","setValueForRanges","isSelected","rowSelected","columnSelected","addDocumentCursor","documentCursor","removeDocumentCursor","startDragTimer","stopDragTimer","renderState","focus","isFocused","mouseHandler","keyHandler","notifyMouseHandlers","updateCoordinates","addCursorToDocument","renderInputField","wrapperStyle","position","opacity","inputStyle","isValid","onMouseDown","userTheme","textAlignForCell","colorForCell","backgroundColorForCell","textForColumnHeader","textForRowHeader","textForRowFooter","isColumnMovable","isRowMovable","isEditable","editedData","textForCell","setValues","edit","editValueForCell","isEditableRange","delete","MockTreeGridModel","childRowCount","MAX_DEPTH","offsetRow","sortedEntries","childRow","childModel","getCachedModelRowOffset","getCachedDepthForRow","getCachedTextForCell","getCachedTextForRowHeader","isRowExpandable","getCachedIsRowExpandable","isRowExpanded","getCachedIsRowExpanded","setRowExpanded","originalChildRowCount","child","numColumns","depthForRow","listenerCount","startListening","stopListening","getColumnIndexByName","originalColumns","groupedColumns","formatForCell","valueForCell","displayString","updateFrozenColumns","rollupConfig","totalsConfig","layoutHints","isColumnFrozen","isFilterRequired","isReversible","isColumnStatisticsAvailable","isCustomColumnsAvailable","isExportAvailable","isValuesTableAvailable","isChartBuilderAvailable","isRollupAvailable","isTotalsAvailable","pendingDataMap","pendingRowCount","count","pendingDataErrors","commitPending","isFilterable","setViewport","snapshot","textSnapshot","includeHeaders","formatValue","export","valuesTable","columnStatistics","close","IrisGridModel","UPDATED","FORMATTER_UPDATED","REQUEST_FAILED","COLUMNS_CHANGED","TABLE_CHANGED","FILTERS_CHANGED","SORTS_CHANGED","DISCONNECT","RECONNECT","TOTALS_UPDATED","PENDING_DATA_UPDATED","AggregationOperation","AdvancedSettingsType","DEFAULTS","filterValidColumns","isValidOperation","operationType","selected","gridState","customColumnNames","IrisGridUtils","columnNames","irisGridState","aggregationSettings","showOnTop","advancedSettings","frozenColumns","advancedFilters","customColumnFormatMap","quickFilters","selectDistinctColumns","invertSearchColumns","AdvancedSettings","irisGridPanelState","partitionColumn","quickFilter","savedQuickFilters","importedFilters","advancedFilter","savedAdvancedFilters","otherOptions","columnMap","getColumnIndex","columnSort","panelState","inputFilters","partition","tableSettings","filters","partitionColumnName","filterMap","customColumn","oldCustomColumns","oldCustomColumnsNames","oldCustomColumnName","removedColumnNames","newMoves","removedColumnName","removedColumnIndex","moves","move","newMove","tableColumns","columnsToFetch","alwaysFetchColumnNames","viewportColumns","bufferPages","columnsCenter","bufferWidth","columnsLeft","columnsRight","bufferedColumns","rangeSets","rangeMap","rowMapIndex","columnMapIndex","matchColumnRanges","columnSet","config","showConstituents","showNonAggregatedColumns","aggregationColumns","invert","AggregationUtils","aggregationMap","nonAggregatedColumnSet","existingColumns","MissingKeyError","inputTable","frontColumns","backColumns","finalFrontColumns","finalBackColumns","finalFrozenColumns","frontColumnSet","backColumnSet","frozenColumnSet","middleColumns","col","layoutHintsFrontColumns","layoutHintsBackColumns","layoutHintsFrozenColumns","userFrozenColumns","indices","_","columnFormat","viewHeight","IrisGridTableModel","keyColumnCount","handleTableDisconnect","handleTableReconnect","handleTableUpdate","handleTotalsUpdate","handleRequestFailed","handleCustomColumnsChanged","throttle","applyViewport","leading","totalsTable","totalsTablePromise","addTotalsListeners","removeTotalsListeners","CustomEvent","detail","getCachedPendingErrors","maxPendingDataRow","pendingNewDataMap","freeze","getColumnStatistics","selectDistinct","rollup","isSelectDistinctAvailable","getTotalsTable","cacheFormattedValue","formattedStringData","cachePendingValue","pendingStringData","clearPendingValue","textValueForCell","totalsColumn","getCachedCustomColumnFormatFlag","isKeyColumn","pendingRow","dataForCell","isPendingRow","totalsRow","totals","operationOrder","getColumnsWithLayoutHints","getMemoizedColumnMap","getMemoizedFrontColumns","getMemoizedBackColumns","getMemoizedFrozenColumns","totalsRowCount","viewportY","defaultOperation","tableColumn","find","isTotalsRow","copyViewportData","extractViewportData","copyTotalsData","totalsData","dataMap","operationMap","getColumnIndicesByNameMap","newData","offset","newRow","extractViewportRow","closeSubscription","getCachedFormattedString","setTotalsTable","viewportTop","viewportBottom","getCachedViewportRowRange","applyBufferedViewport","subscription","consolidated","topFloatingRowsSet","tableRanges","bottomFloatingRowsSet","topFloatingRows","rangeSet","bottomFloatingRows","getCachedFilterableColumnSet","includes","keyColumns","isDeletableRange","isEditableRanges","isDeletableRanges","getTableAreaRange","getPendingAreaRange","formattedText","pendingAreaRange","pendingRanges","newDataMap","newRowData","tableAreaRange","newRows","rowEditMap","rowMap","dataIndex","rangeRowCount","rowEdits","pendingRange","deleteTable","columnFilters","agg","curr","c1","c2","viewportRange","intersection","resultRow","viewportRow","makeModel","handleModelEvent","modelPromise","setModel","oldModel","setNextModel","addListeners","events","removeListeners","originalModel","deepEqual","isConsoleTable","show","viewBox","transform","d","fill","handleEnter","handleExit","isShown","popper","getVisibleElement","initPopper","referenceObject","placement","parent","closeOnBlur","elem","destroyPopper","updateState","hide","scheduleUpdate","onEntered","onExited","renderContent","interactive","display","ReactDOM","Popper","Tooltip","handleWindowMouseMove","handleTimeout","handleExited","stopShowingTooltip","oldIsShown","startListeningWindow","stopListeningWindow","matches","popperRect","reshowTimeout","timerTimeout","update","popperClassName","usePrevious","childrenArray","useMemo","prevChildrenArray","mainView","setMainView","pushingView","setPushingView","poppingView","setPoppingView","topChild","pushComplete","popComplete","onBack","onClose","on","isInvalid","id","isSwitchMenuItemType","onSelect","handleSelect","subtitle","evt","actionElements","shortcut","actionElement","globalActions","keyboardActions","ignoreClassNames","el","classList","ignoredClassName","keyboardAction","ContextActions","default","high","medium","low","global","Button","btnClassName","kind","iconOnly","getClassName","variantClassName","getVariantClasses","iconElem","tooltipElem","tooltip","button","variant","object","animation","onEntering","onExiting","onKeyPress","isSaving","isSuccessShown","setIsSuccessShown","wasSuccessShown","setWasSuccessShown","successTimeout","prevIsSaving","commitIcon","discardTooltip","saveTooltip","copyState","IrisGridCopyHandler","buttonState","handleBackgroundClick","handleCancelClick","handleCopyClick","handleHideTimeout","copyOperation","startCopy","CONFIRMATION_REQUIRED","stopCopy","textData","copyText","DONE","CLICK_REQUIRED","startFetch","FETCH_IN_PROGRESS","formatValues","FETCH_ERROR","stopFetch","startHideTimer","stopHideTimer","hideTimer","copyButtonText","statusMessageText","isButtonContainerVisible","isFetching","isDone","IDLE","COPY","CLICK_TO_COPY","RETRY","number","func","debounceMs","debounce","handleFocus","setGridFocus","defocusInput","relatedTarget","handleTab","backward","onTab","onAdvancedFiltersTriggered","onFocus","isAdvancedFilterSet","FilterInputField","MODIFIER","KEY","ALLOWED_SINGLE_KEY_SET","keyValue","Shortcut","keyState","altKey","ctrlKey","metaKey","shiftKey","keyCode","eventKey","state1","state2","activeShortcut","macShortcut","getDisplayText","getKeyState","setKeyState","JSON","getDefaultKeyState","isDefault","setToNull","isNull","setToDefault","matchesKeyState","matchesEvent","createAndAdd","params","existingShortcut","shortcutMap","dispatchEvent","category","shortcutsByCategory","getConflictingShortcuts","TOGGLE_QUICK_FILTER","CLEAR_ALL_FILTERS","CLEAR_FILTERS","REVERSE","TOGGLE_SEARCH","INPUT_TABLE","COMMIT","DISCARD","irisGrid","IrisGridShortcuts","reverseType","isActive","isSelectingColumn","isValidColumn","columnSelectionValidator","updateColumnSelectionStatus","getTableColumn","columnNotAllowedCursor","hoverSelectColumn","destroyColumnTooltip","shownColumnTooltip","hideColumnTooltip","newTooltip","getColumnFromGridPoint","isFilterBarShown","hoverAdvancedFilter","newHoverAdvancedFilter","PASTE","SAVE","SELECT_ALL","LINKER","LINKER_CLOSE","CustomFormatAction","defaultProps","handleInputChange","inputRef","closeContextMenu","revertToDefault","returnFocusToContextMenu","parentContextMenu","DOMUtils","iconElement","htmlFor","placeholder","focusInput","selectedFormat","menuElement","currentTime","presetFormatOptions","group","DateTimeFormatContextMenu","FormatContextMenuUtils","formatItems","DecimalFormatContextMenu","presetGroup","presetRoundGroup","defaultFormatOption","isCustomSelected","customFormat","newCustomFormat","onCustomFormatChange","IntegerFormatContextMenu","CONTEXT_MENU_DATE_FORMAT","filterText","newFilterText","additive","IrisGridContextMenuHandler","canCopy","valueText","searchFilter","contextMenuReverseIconColor","settings","modelSort","hasReverse","dateFilterFormatter","previewFilterFormatter","SHORTCUTS","sortByActions","additionalSortActions","dateFormatActions","numberFormatActions","filterMenu","andFilterMenu","numberValueText","numberFilterActions","booleanFilterActions","dateValueText","previewValue","dateFilterActions","stringFilterActions","nullFilterActions","GLOBAL_SHORTCUTS","formatOptions","isFinite","valueFilter","contextMenuSortIconColor","sortActions","checkColumnSort","setIsShown","prevChildren","existingWidth","IrisGridModelUpdater","sortsForModel","APIPropTypes","alwaysFetchColumns","ICON_NAMES","SORT_UP","SORT_DOWN","CARET_DOWN","CARET_RIGHT","ICON_SCALE","isAdvancedFilterValid","isQuickFilterValid","initIcons","setIcon","faIcon","Path2D","getIcon","icons","getSortIcon","originalFont","displayValue","drawGroupedColumnLine","lastGroupedColumn","drawPendingRowLine","firstPendingRow","drawScrim","loadingScrimProgress","scrimColor","scrimBlurSize","drawHeaderBar","interior","gradientX","drawFilterHeaders","drawExpandedFilterHeaders","filterBarHeight","drawExpandedFilterHeader","filterBarHorizontalPadding","IrisGridRenderer","rectLeft","rectTop","rectWidth","rectHeight","drawCollapsedFilterHeaders","filterBarCollapsedHeight","drawCollapsedFilterHeader","filterBarErrorColor","isFilterValid","markerIcon","iconX","iconY","IrisGridTheme","headerSortBarColor","headerReverseBarColor","headerBarCasingColor","positiveNumberColor","negativeNumberColor","zeroNumberColor","dateColor","pendingTextColor","errorTextColor","nullStringColor","filterBarActiveBackgroundColor","filterBarExpandedBackgroundColor","filterBarExpandedActiveBackgroundColor","filterBarExpandedActiveCellBackgroundColor","filterBarSeparatorColor","filterBarActiveColor","filterIconColor","groupedColumnDividerColor","sortHeaderBarHeight","reverseHeaderBarHeight","minScrimTransitionTime","maxScrimTransitionTime","linkerColumnHoverBackgroundColor","STATS_LABEL_OVERRIDES","SIZE","handleError","handleGenerateStatistics","handleStatistics","handleCopyHeader","loading","statistics","numRows","copied","maybeGenerateStatistics","ColumnStatistics","stats","onStatistics","showGenerateStatistics","statisticElements","formattedValue","statisticElement","rowCountLabel","formattedRowCount","filterType","AdvancedFilterCreatorFilterItem","handleDelete","handleTypeChange","handleValueChange","filterTypes","onDelete","showValueInput","typeOptionElements","typeDropdown","Checkbox","forwardedRef","checked","shortid","innerRef","useForwardedRef","handleOnChange","inputClassName","propName","checkedType","labelClassName","itemElements","getCachedItem","handleScroll","sendViewportUpdate","list","clientHeight","onViewportChange","getCachedItems","onScroll","itemCount","SelectValueList","v","handleViewportChange","handleSelectionUpdate","invertSelection","concat","selectedIndex","AdvancedFilterCreatorSelectValueList","isValueSelected","resetViewport","updateItemSelection","updateViewport","viewportSize","handleSelectAllClick","handleClearAllClick","handleListChange","handleSearchChange","handleUpdateFilterTimeout","searchText","searchTable","getColumnName","getDisplayedValuesCount","getDisplayedValueText","formattedCount","formattedTableSize","initSearchTable","searchTablePromise","resetSelection","startUpdateFilterTimer","AdvancedFilterCreatorSelectValue","stopUpdateFilterTimer","updateTableFilter","showSearch","displayedValuesText","placeholderText","totalSize","handleAddAnd","handleAddOr","handleChangeFilterOperator","handleDone","handleFilterChange","handleFilterDelete","handleSelectValueChange","handleReset","handleSortDown","handleSortUp","handleSubmit","handleFocusTrapStart","handleFocusTrapEnd","handleUpdateTimeout","valuesTableError","debounceTimeout","valuesTablePromise","getFilterChangeHandler","getFilterDeleteHandler","initValuesTable","focusTrapContainer","querySelectorAll","inputs","operator","filterIndex","makeFilterItem","updateKey","shouldShowAddFilter","sortTable","onSortChange","startUpdateTimer","AdvancedFilterCreator","stopUpdateTimer","onFilterChange","isBoolean","isDateType","getFilterTypes","filterItemElements","isAndFilter","operatorElement","showAddFilterItem","addFilterItem","hidden","onSubmit","sortDirection","rotation","OptionType","matchCount","SearchInput","draggableId","disableInteractiveElementBlocking","provided","isHidden","VisibilityOrderingBuilder","onMouseEnter","onMouseUp","isDragged","columnsDragged","handleSearchInputChange","searchColumns","handleOrderDraggingStart","handleOrderDraggingEnd","selectedColumns","lastSelectedColumns","isDraggingVisibility","visibilityDraggingOption","visibilityDraggingStartColumn","isDraggingOrder","orderDraggingColumn","resetVisibilityOrdering","onColumnVisibilityChanged","columnsMatch","visibleIndexToFocus","columnItemToFocus","block","handleVisibilityKeyDown","visibilityOption","handleVisibilityDraggingStart","isModifierKeyDown","isShiftKeyDown","handleVisibilityDraggingEnd","source","startIndex","destinationIndex","selectedColumnsSortByVisibleIndex","columnA","columnB","draggingVisibleIndex","upper","lower","columnVisibleIndex","bottomDestinationIndex","handleMouseEnter","targetModelIndex","draggingStartVisibleIndex","targetVisibleIndex","columnsToChangeVisibility","checkDownward","visibleIndexToCheck","modelIndexToCheck","handleMoveColumns","option","firstMovableIndex","getFirstMovableIndex","lastMovableIndex","getLastMovableIndex","sortedSelectedColumns","scrollListAfterMove","columnModelIndex","handleSortColumns","movableColumns","immovableColumns","movableColumnsSorted","modelIndexAlphaSorted","insertIndex","handleItemClick","modelIndexClicked","removeSelectionOnClick","columnsToBeAdded","lastSelectedColumn","lastSelectedColumnVisibleIndex","visibleIndexToBeSelected","columnsInBetween","addColumnToSelected","newSelectedColumns","newLastSelectedColumns","removeColumnFromSelected","makeVisibilityOrderingList","elements","wasMovable","isMovable","renderVisibilityOrderingItem","renderImmovableItem","noSelection","columnsToToggle","toggleToShow","selectedToggleText","columnItems","onDragStart","onDragEnd","droppableId","draggingFromThisWith","SHOW","HIDE","DSC","ASC","TOP","BOTTOM","UP","ALL","SELECTION","propsName","RadioItem","TableCsvExporter","handleDownloadClick","handleDownloadOptionChanged","handleCustomizedDownloadOptionChanged","handleCustomizedDownloadRowsChanged","fileName","downloadOption","customizedDownloadOption","customizedDownloadRows","getSnapshotRanges","snapshotRanges","rangeA","rangeB","resetDownloadState","onDownloadStart","frozenTable","tableSubscription","onDownload","validateOptionInput","tableDownloadStatus","isDownloading","ALL_ROWS","SELECTED_ROWS","CUSTOMIZED_ROWS","tableDownloadEstimatedTime","ClassNames","INITIATING","DOWNLOADING","FINISHED","CANCELED","FIRST","LAST","tableDownloadProgress","xmlns","fillRule","stroke","cx","cy","maxSeriesCount","ChartBuilder","handleAddSeries","handleLinkStateChange","handleSeriesChange","handleSeriesDeleteClick","handleTypeClick","handleXAxisChange","xAxis","seriesItems","isLinked","sendChange","xAxisLabel","seriesLabel","isSeriesVisible","isAddSeriesVisible","chartType","seriesItem","mask","sourceList","DragUtils","draggedItems","destinationList","sortedRanges","flatten","adjustedIndex","handleContentChanged","handleEditorFocus","handleEditorBlur","handleContainerClick","isEditorFocused","isEditorEmpty","initEditor","editorSettings","inputEditorSettings","copyWithSyntaxHighlighting","fixedOverflowWidgets","folding","fontFamily","glyphMargin","language","lineDecorationsWidth","lineNumbers","minimap","enabled","renderLineHighlight","scrollbar","arrowSize","horizontal","horizontalScrollbarSize","scrollBeyondLastLine","padding","tabCompletion","useTabStops","wordWrap","automaticLayout","monaco","tabSize","destroyEditor","onContentChanged","editor","getModel","editorIndex","invalid","focused","editorContainer","InputEditor","handleFormulaEditorContentChanged","formulaValue","CustomColumnInput","dragging","onDeleteColumn","NAME","FORMULA","inputIndex","formula","onTabInEditor","input","handleAddColumnClick","handleSaveClick","handleDeleteColumn","handleCustomColumnUpdated","handleDragEnd","resetRequestFailed","handleEditorTabNavigation","isCustomColumnApplying","hasRequestFailed","isSuccessShowing","resetErrorMessage","parseCustomColumns","customColumnInputs","CustomColumnBuilder","newInputs","customColumnIndex","getInputIndex","newCustomInput","getInput","setState","sourceIndex","sourceInput","focusEditorIndex","nextFocusIndex","onSave","renderInputs","renderSaveButton","saveText","handleDragStart","handleDrag","handleDragOver","handleDrop","onDragOver","onDrop","isDraggable","ItemListItem","draggable","disableSelect","ItemList","renderItem","component","handleItemBlur","handleItemContextMenu","handleItemFocus","handleItemDoubleClick","handleItemMouseDown","handleItemMouseMove","handleItemMouseUp","handleItemsRendered","handleWindowMouseUp","renderInnerElement","mouseDownIndex","overscanStartIndex","scrollOffset","propSelectedRanges","onSelectionChange","onFocusChange","getElement","listContainer","focusSelector","focusItem","scrollToItem","isModifierDown","isDragSelect","getItemSelected","isShiftDown","isDoubleClickSelect","isMultiSelect","isListAtBottom","resetMouseState","scrollToBottom","scrollIntoView","toggleSelect","isDeselectable","deselectAll","deselectItem","deselectRange","selectItem","selectRange","onResize","itemData","getItemData","onItemsRendered","outerElementType","getOuterElement","outerRef","innerElementType","overscanCount","isDeselectOnClick","badgeText","DraggableItemList","selectedCount","isClone","draggablePrefix","isDragDisabled","getCachedDraggableItem","rubric","handleSelectionChange","isDropDisabled","mode","renderClone","getCachedRenderClone","draggingOverWith","getCachedRenderDraggableItem","draggingItemClassName","GROUPED_LIST_ID","UNGROUPED_LIST_ID","currentGroupings","newGroupings","groupings","grouping","RollupRows","search","handleDeleteClicked","handleUngroupedSelect","handleUngroupedSelectionChange","handleGroupedSelectionChange","handleShowConstituentsChange","handleShowNonAggregatedColumnsChange","handleSortAscending","handleSortDescending","renderGroupedItem","ungroupedSelectedRanges","groupedSelectedRanges","dragSource","ASCENDING","DESCENDING","ungroupedList","destination","isSameList","newColumns","sourceItems","getSortedUngroupedColumns","sourceRanges","stateUngroupedSelectedRanges","stateGroupedSelectedRanges","updateFromConfig","getUngroupedColumns","getCachedUngroupedColumns","getCachedSortedColumns","indent","ungroupedColumns","groupListHeight","ungroupMaxListHeight","ungroupMinListHeight","maxHeight","minHeight","SortType","SELECTABLE_OPTIONS","onEdit","aggregation","selectedOperation","setSelectedOperation","changeSettings","changedSettings","changeAggregations","newAggregations","changeShowOnTop","newShowOnTop","handleOperationChange","handleAdd","handleAggregationSelectionChange","handleAggregationSelect","handleShowOnTopChange","renderAggregation","isRollupOperation","isRollup","isOptionsShown","isAggregationsShown","setTop","setBottom","setSort","validColumns","filteredColumns","newSelected","newInvert","newTop","newBottom","toggleAll","isModified","handlePortMessage","handleSnapshotResolved","handleDownloadTimeout","getDownloadWorker","sw","iframes","iframe","createWriterStream","port","useBlob","chunks","encode","TextEncoder","streamConfig","chunk","blob","Blob","link","URL","startDownload","encodedFileName","encodeURIComponent","messageChannel","finishDownload","onDownloadCompleted","cancelDownload","onDownloadCanceled","resetTableSaver","writeTableHeader","headerString","startWriteTableBody","TableSaver","rangedSnapshotsTotal","reduce","snapshotCount","writeCsvTable","writeSnapshot","snapshotIndex","snapshotStartRow","snapshotEndRow","currentSnapshotIndex","snapshotsBuffer","convertSnapshotIntoCsv","snapshotCounter","snapshotsTotal","updateDownloadProgress","onDownloadProgressUpdate","csvString","snapshotIterator","rowIdx","cellData","makeSnapshot","n","currentGridRange","readableStreamPulling","makeIframe","src","filterColumns","searchValue","handleSearchValueChange","toggleColumn","clear","selectNumbers","isConfigureColumnsShown","sendColumnChange","setInvertSelection","hasAllColumnsSelected","hasNoColumnsSelected","searchField","CrossColumnSearch","handleCloseMenu","Menu","popperOptions","separateKeyboardMouse","DropdownMenu","debounceUpdateFilter","handleInputFocus","handleListKeydown","handleTextChange","onListResized","itemList","selectedValue","offsetIndex","updateFilter","listHeight","PartitionSelectorSearch","searchInput","initialPageSize","debounceUpdate","handleAppendClick","handleCloseClick","handleIgnoreClick","handlePartitionChange","handlePartitionSelect","handlePartitionListResized","handleSearchOpened","handleSearchClosed","onAppend","sendDone","sendFetchAll","onFetchAll","partitionSelectorSearch","selectorSearch","searchMenu","IrisGridPartitionSelector","handleDropdownChanged","filteredInputs","prevInputs","disableAddButton","SelectDistinctBuilder","AdvancedSettingsMenu","isEmptyConfig","handleAdvancedMenuOpened","advancedFilterOptions","optionItems","toggleFilterBarAction","isOn","toggleSearchBarAction","normalizer","newOperations","o","getOperationMap","getOperationOrder","floatingLeftColumns","floatingRightColumns","handleAdvancedFilterChange","handleAdvancedFilterSortChange","handleAdvancedFilterDone","handleAdvancedMenuClosed","handleAggregationChange","handleAggregationsChange","handleAggregationEdit","handleAnimationLoop","handleAnimationStart","handleAnimationEnd","handleChartChange","handleChartCreate","handleGridError","handleFilterBarChange","handleFilterBarDone","handleFilterBarTab","handleMenu","handleMenuSelect","handleMenuBack","handleSelectionChanged","handleMovedColumnsChanged","handleUpdate","handleTooltipRef","handleViewChanged","handleFormatSelection","handleUpdateCustomColumns","handleSelectDistinctChanged","handlePendingDataUpdated","handlePendingCommitClicked","handlePendingDiscardClicked","handleDownloadTable","handleDownloadTableStart","handleCancelDownloadTable","handleDownloadCanceled","handleDownloadProgressUpdate","handleDownloadCompleted","handlePartitionAppend","handlePartitionFetchAll","handlePartitionDone","handleColumnVisibilityChanged","handleCrossColumnSearch","handleRollupChange","updateSearchFilter","showSearchBar","selectedSearchColumns","focusedFilterBarColumn","partitionTable","partitionFilters","shownAdvancedFilter","loadingText","loadingSpinnerShown","isMenuShown","isTableDownloading","isReady","rollupSelectedColumns","selectedAggregation","openOptions","pendingSavePromise","pendingSaveError","toastMessage","changedInputFilters","inputFilter","replaceExistingFilters","customFilters","loadingScrimFinishTime","loadingScrimStartTime","totalTime","getValueForCell","rawValue","getCachedTheme","getVisibleColumn","applyInputFilters","replaceExisting","newAdvancedFilters","newQuickFilters","applyQuickFilter","IrisGrid","setAdvancedFilter","setQuickFilter","setFilterMap","removeColumnFilter","clearAllFilters","clearCrossColumSearch","clearGridInputField","filterInputRef","rebuildFilters","setFilters","updateFormatterSettings","globalColumnFormats","FormatterUtils","dateTimeFormatterOptions","defaultDecimalFormatOptions","defaultIntegerFormatOptions","isColumnFormatChanged","isDateFormattingChanged","isDecimalFormattingChanged","isIntegerFormattingChanged","updateFormatter","updatedFormats","mergedColumnFormats","initFormatter","initState","inputFiltersWithValues","loadPartitionsTable","isSelectingPartition","updatePartition","copyCell","copyRanges","startLoading","resetRanges","scrimTransitionTime","stopLoading","rollback","canRollback","lastLoadedConfig","focusFilterBar","newLeft","hideColumnByVisibleIndex","freezeColumnByColumnName","allFrozenColumns","unFreezeColumnByColumnName","onPartitionAppend","handleTableLoadError","showAllColumns","entries","toggleSort","currentSorts","updateSorts","sortColumn","toggleFilterBar","lastFocusedFilterBarColumn","isTableSearchAvailable","canToggleSearch","searchDisplayMode","toggleSearchBar","crossColumnRef","newPendingSavePromise","discardPending","selectColumn","onColumnSelected","selectData","onDataSelected","oldSort","onCreateChart","prevCustomColumnFormatMap","normalizedType","columnFormattingRule","newOptions","bottomNonFloating","onChangeApplied","newSorts","newMovedColumns","newSelectDistinctColumns","canDownloadCsv","args","deleteRanges","resetColumnSelection","columnAllowedCursor","CURSOR_TYPE_DEFAULT","resetGridViewState","sendStateChange","onStateChange","getCachedFilter","getCachedStateOverride","isVisible","focusField","minWidth","isBarFiltered","loadingElement","loadingStatus","loader","cancelButton","columnTooltip","boundedLeft","boundedWidth","pointerEvents","gridRect","gridWrapper","virtualReference","clientWidth","getBoundingClientRect","modifiers","flip","behavior","filterBar","isFilterSet","isFilterVisible","advancedFilterMenus","xColumnHeader","getCachedOptionItems","openOptionsStack","CHART_BUILDER","VISIBILITY_ORDERING_BUILDER","CUSTOM_COLUMN_BUILDER","ROLLUP_ROWS","TABLE_EXPORTER","onAdvancedSettingsChange","getCachedHiddenColumns","onEnter","onExit","getAlwaysFetchColumns","getModelRollupConfig","getModelTotalsConfig","commitAction","discardAction","onDiscard","tableSaver","applyInputFiltersOnInit","defaultDateTimeFormat","onlyFetchVisibleColumns","App","setError","setInputFilters","setSorts","setIsLoading","searchParams","URLSearchParams","location","initApp","async","baseUrl","websocketUrl","protocol","host","debug","connection","IdeConnection","session","startSession","info","definition","VariableType","TABLE","getObject","loadTable","newModel","IrisGridModelFactory","receiveMessage","command","newInputFilters","getNormalizedType","getElementById","TestUtils","arc","jest","beginPath","clip","closePath","createLinearGradient","addColorStop","fillRect","fillText","lineTo","measureText","moveTo","restore","setTransform","save","strokeRect","translate","createPattern","operateAs","groups","isSuperUser","isQueryViewOnly","isNonInteractive","canUsePanels","canCreateDashboard","canCreateCodeStudio","canCreateQueryMonitor","exports"],"mappings":"wpCAuKIA,EAAU,CACZC,OAAQ,KACRC,SAAU,QACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,2HAO3BC,EAAgB,CAClBH,OAAQ,KACRC,SAAU,eACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,kHAE3BE,EAAgB,CAClBJ,OAAQ,KACRC,SAAU,eACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,kHAE3BG,EAAiB,CACnBL,OAAQ,KACRC,SAAU,gBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,mHAE3BI,EAAc,CAChBN,OAAQ,KACRC,SAAU,aACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,sHA2B3BK,EAAsB,CACxBP,OAAQ,KACRC,SAAU,sBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,krBAE3BM,EAAuB,CACzBR,OAAQ,KACRC,SAAU,uBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,ihDAgC3BO,EAAU,CACZT,OAAQ,KACRC,SAAU,QACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,gMAE3BQ,EAAkB,CACpBV,OAAQ,KACRC,SAAU,iBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,irBAyD3BS,EAAS,CACXX,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,iJAkP3BU,EAAS,CACXZ,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,8NAgH3BW,EAAW,CACbb,OAAQ,KACRC,SAAU,SACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,uHAwJ3BY,EAAY,CACdd,OAAQ,KACRC,SAAU,UACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,+GAyD3Ba,EAAW,CACbf,OAAQ,KACRC,SAAU,SACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,sGAmE3Bc,EAAS,CACXhB,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,mlBAqC3Be,EAAY,CACdjB,OAAQ,KACRC,SAAU,UACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,kGAO3BgB,EAAS,CACXlB,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,uJAgC3BiB,EAAS,CACXnB,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,4EAiG3BkB,EAAe,CACjBpB,OAAQ,KACRC,SAAU,cACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,0JAE3BmB,EAAS,CACXrB,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,qqBAoI3BoB,EAAW,CACbtB,OAAQ,KACRC,SAAU,SACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,4BA6E3BqB,EAAS,CACXvB,OAAQ,KACRC,SAAU,OACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,kOAoD3BsB,EAAW,CACbxB,OAAQ,KACRC,SAAU,SACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,iLAyD3BuB,EAAoB,CACtBzB,OAAQ,KACRC,SAAU,mBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,mGAqH3BwB,EAAmB,CACrB1B,OAAQ,KACRC,SAAU,kBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,0/BA+H3ByB,EAAU,CACZ3B,OAAQ,KACRC,SAAU,QACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,g7DAE3B0B,EAAU,CACZ5B,OAAQ,KACRC,SAAU,QACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,yNAE3B2B,EAAiB,CACnB7B,OAAQ,KACRC,SAAU,gBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,8EAO3B4B,EAAkB,CACpB9B,OAAQ,KACRC,SAAU,iBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,4EAiG3B6B,EAAY,CACd/B,OAAQ,KACRC,SAAU,UACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,+JAoD3B8B,EAAkB,CACpBhC,OAAQ,KACRC,SAAU,kBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,iHAE3B+B,EAAe,CACjBjC,OAAQ,KACRC,SAAU,eACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,wHAE3BgC,EAAgB,CAClBlC,OAAQ,KACRC,SAAU,eACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,sKAsB3BiC,EAAa,CACfnC,OAAQ,KACRC,SAAU,YACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,ugBAE3BkC,EAAQ,CACVpC,OAAQ,KACRC,SAAU,MACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,yYAgC3BmC,EAAiB,CACnBrC,OAAQ,KACRC,SAAU,gBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,2DAO3BoC,EAAW,CACbtC,OAAQ,KACRC,SAAU,SACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,iiBAE3BqC,EAAe,CACjBvC,OAAQ,KACRC,SAAU,cACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,gTAY3BsC,EAAgB,CAClBxC,OAAQ,KACRC,SAAU,gBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,2IAY3BuC,EAAyB,CAC3BzC,OAAQ,KACRC,SAAU,0BACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,uIAiB3BwC,EAAY,CACd1C,OAAQ,KACRC,SAAU,UACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,0SAE3ByC,EAAuB,CACzB3C,OAAQ,KACRC,SAAU,uBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,mFAiB3B0C,EAAkB,CACpB5C,OAAQ,KACRC,SAAU,kBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,8UAE3B2C,GAAgB,CAClB7C,OAAQ,KACRC,SAAU,gBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,iVAE3B4C,GAAmB,CACrB9C,OAAQ,KACRC,SAAU,mBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,4KAE3B6C,GAAa,CACf/C,OAAQ,KACRC,SAAU,YACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,+DAE3B8C,GAAW,CACbhD,OAAQ,KACRC,SAAU,UACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,mEAY3B+C,GAAiB,CACnBjD,OAAQ,KACRC,SAAU,gBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,2DAO3BgD,GAAU,CACZlD,OAAQ,KACRC,SAAU,QACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,2PAO3BiD,GAAuB,CACzBnD,OAAQ,KACRC,SAAU,uBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,2IAO3BkD,GAAW,CACbpD,OAAQ,KACRC,SAAU,SACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,ioBAY3BmD,GAAwB,CAC1BrD,OAAQ,KACRC,SAAU,wBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,wnBAE3BoD,GAAkB,CACpBtD,OAAQ,KACRC,SAAU,iBACVC,KAAM,CAAC,IAAK,IAAK,GAAI,OAAQ,uH,4WCtnEhB,OAAAqD,OAAA,O,kWAAA,EACbC,aADa,IAEbC,gBAFa,IAGbC,iBAHa,IAIbC,iBAAkB,KAJpB,OCeA,I,OATuB,QAAC,UACtBC,EAAY,IADS,SAGrB,yBAAKA,UAAWC,IAAW,4BAA6BD,IACtD,uBAAiB1D,KAAjB,EAA6C0D,UAAU,kBACvD,uBAAiB1D,KAAjB,EAAkC0D,UAAlC,eAA2DE,MAAI,OCmCnE,I,OAhCuB,QAAC,SACtBC,GADsB,YAEtBC,GAFsB,eAGtBC,EAAe,MAHM,SAKrB,mCACEC,KAAI,OADN,EAEEC,QAASC,GAFX,aAGEP,WAAYE,EAAW,OAHzB,GAIEM,cAJF,EAKEC,eAAa,GAEb,yBAAKV,UAAU,wBACb,yBACEA,UAAWC,IAAW,6BAAD,uBAGnB,CAAE,8BAA+BE,KAGnC,yBAAKH,UAAU,mBACb,yBAAKA,UAAU,gBACZI,GAAa,qBADhB,OAEIA,GAAaC,GAAgB,uBAAiB/D,KAAM6B,KAExD,yBAAK6B,UAAU,gBAzBF,SCXR,GAAAL,OAAA,OAAc,SAPtB,EAOsB,MANtB,EAMsB,KALtB,EAKsB,KAJtB,EAIsB,MAHtB,EASLgB,OARK,ICFDC,GAAS,OA0Bf,OAxBA,MACEC,YAAYC,EAAMC,GAChBC,KAAA,OACAA,KAAA,OAAcF,EAAO,IAAH,cAAlB,GAEAE,KAAA,eAGFC,YAAYF,GACVC,KAAA,QAEAA,KAAA,MDfG,GCgBDE,EAAiBC,2BAA4BH,KAA7CE,QADF,GAEAF,KAAA,KDhBG,GCiBDI,EAAgBD,0BAA2BH,KAA3CI,QADF,GAEAJ,KAAA,IDjBG,GCiBQK,EAAgBF,yBAA0BH,KAA1CK,QAAX,GACAL,KAAA,KAAYA,KAAZ,IACAA,KAAA,MDlBG,GCmBDM,EAAiBH,2BAA4BH,KAA7CM,QADF,GAEAN,KAAA,ODnBG,GCoBDL,EAAkBQ,2BAA4BH,KAA9CL,QADF,KC6CJ,ICjEA,GDiEA,GA7BA,iBACEE,cACEU,MAAA,KADqC,uDA9BzC,WAA2B,MACrBC,EAAJ,GACA,IACEA,EAAWC,mTAAXD,oBACA,UAGF,GAAIA,GAAYE,GAAhB,GACE,OAAOA,GAAP,GAEF,IAAMC,EAAWC,SAAQ,8BAAzB,IACA,IAAKC,aAAL,GACE,SAcF,OFlCK,EEsCeC,IAGlBd,KAAA,WAGFe,OAAOjB,GAKL,OAJKE,KAAKgB,QAAV,KACEhB,KAAA,WAAqB,IAAI,GAAJ,EAAiBA,KAAtC,QAGKA,KAAKgB,QAAZ,GAGFf,YAAYF,GAGV,GAFAQ,MAAA,eAEKP,KAAL,QAKA,IADA,IAAMiB,EAAOtC,YAAYqB,KAAzB,SACSkB,EAAT,EAAgBA,EAAID,EAApB,OAAiCC,GAAjC,EACElB,KAAA,QAAaiB,EAAb,qBE7DN,GADY,IAAZ,G,mBDEYE,K,UAAAA,E,QAAAA,E,SAAAA,E,UAAAA,E,oBAAAA,Q,KEJZ,MAAMC,WAA6BC,MAAM,c,UAAA,oB,GAAA,G,EAAA,gB,EAAA,M,uFAIzC,U,yHCJA,IAEMC,GAAN,UAGMC,GAA6B,IAAIC,IAAI,CAAC,KAAM,MAAO,IAAK,KAA9D,MAGMC,GAAgB,IAAID,IAAI,CAAC,WAAD,0bAA9B,UAyDME,GAAN,qBAGMC,GAAN,kBAMA,MAAMC,I,GAAAA,G,YACc,CAAC,EAAD,WAQhB,IAAIC,EAAY/B,yBAFL,KA0BX,OApBEgC,IACCP,WACCE,OAHJ,MAKEI,EAAYzG,EAAZyG,IAIFA,EAAYA,YAdD,OAkBTA,EAAYzG,EAAZyG,GAIGhB,aAAaA,OAAOgB,SAAzB,OACEA,EAAYzG,EAAZyG,GAGF,K,GAjCED,G,qBAoCwB9B,GAC1B8B,cA/GJ,SA+GIA,W,GArCEA,G,uBA6C0BG,IAC5B,IAAMC,EAAN,GAWA,OAVAD,WAAgB,CAACE,EAAQf,KACvB,IAAIgB,EAAcN,wBADW,GAIzBI,WAAJ,KACEE,EAAcZ,GAAdY,GAGFF,aAEF,K,GAzDEJ,G,sBA4DwB,gBAAiBV,EAAjB,gEAE1BU,6B,GA9DEA,G,oBAsEuB9B,GACzB8B,0BAA4C9B,I,GAvE1C8B,G,qBAyEwB9B,GAC1B8B,2BAA6C9B,IChIlC,QAAEqC,sBAVV,SAA+B,EAA/B,GAIL,SAGOC,qBAAP,IAFE,OCTG,MAAMC,WAAN,YAmBLxC,YAAYyC,EAAD,GACT/B,MAAA,MC1BJ,MAAMgC,WAAqBlB,MAAM,c,UAAA,oB,GAAA,G,EAAA,e,EAAA,M,uFAIjC,UCGO,MAAM,GAOU,2BAInB,IACA,EADImB,GAAJ,EAGMC,EAAiB,IAAIC,SAAQ,CAACC,EAASC,KAC3CF,yBACEG,IACE,GACE,GACEC,KAEFF,EAAO,IAAPA,MAEAG,IACAJ,SAGJK,GACgBJ,EAAdJ,EAAqB,IAAV,GAbfE,QA0BF,OARCD,EAAD,OAAiC,KAC/BD,KAEIO,SAAJ,GACED,MAIJ,EAGe,kBAACE,GAChB,OAAOA,aAAP,GAGe,kBAACA,GAChB,OAAOA,aAAP,I,yHCUJ,OA3DA,MAAc,2DAWZC,IAAG,KAID,IAAMC,EAAUC,oBAAhB,GAUA,OATAnD,KAAA,gBACAkD,QACE,KACElD,KAAA,cAEF,KACEA,KAAA,cAGJ,EAOFoD,OAAOF,GACL,IAAK,IAAIhC,EAAT,EAAgBA,EAAIlB,KAAKqD,QAAzB,OAAyCnC,GAAzC,EACE,GAAIlB,KAAKqD,QAAQnC,KAAjB,EAEE,YADAlB,KAAA,oBAMN2C,QAAQO,GACNlD,KAAA,UACAA,KAAA,iBAMFsD,SAEE,IADA,IAAMC,EAAc,IAAIvD,KAAJ,WAAqBA,KAAzC,UACSkB,EAAT,EAAgBA,EAAIqC,EAApB,OAAwCrC,GAAxC,EACEqC,cAEFvD,KAAA,WACAA,KAAA,cC3DJ,MAAMwD,GACe,oBAACC,GAClB,OACEA,aACAA,UACA5C,iBAAiB4C,EAFjBA,KAGA5C,iBAAiB4C,EAHjBA,KAIAA,MAAYA,EALd,GASkB,qBAACA,GACnB,IAAKD,gBAAL,GACE,MAAM,IAAInC,MAAM,kBAAV,OAAN,IAIa,kBAACqC,EAAD,GACf,IAAK,IAAIxC,EAAT,EAAgBA,EAAIwC,EAApB,OAA2CxC,GAA3C,EAAmD,CACjD,IAAMuC,EAAQC,EAAd,GACMC,EAAQF,EAAd,GACMG,EAAMH,EAAZ,GACA,GAAIE,MAAkBE,GAAtB,EACE,SAIJ,SAGgB,mBAACH,EAAD,GAKhB,IAJA,IAAKC,EAAOC,GAAZ,EACME,EAAS,IAFkD,GAKxD5C,EAAI4C,SAAb,EAAgC5C,GAAhC,EAAwCA,GAAxC,EAAgD,CAC9C,IAAM6C,EAAgBD,EAAtB,GACME,EAAgBD,EAAtB,GACME,EAAcF,EAApB,GAEA,GAAIC,MAA0BJ,GAA9B,EAEE,SAGED,MAAwBK,GAA5B,IAEEL,EAAQO,WAARP,GACAC,EAAMM,WAANN,GACAE,eAMJ,OAFAA,OAAY,CAACH,EAAbG,IAEA,EAGkB,qBAACJ,EAAD,GAIlB,IAHA,IAAOC,EAAOC,GAAd,EACME,EAAS,IAFoD,GAI1D5C,EAAI4C,SAAb,EAAgC5C,GAAhC,EAAwCA,GAAxC,EAAgD,CAC9C,IAAM6C,EAAgBD,EAAtB,GACME,EAAgBD,EAAtB,GACME,EAAcF,EAApB,GAEA,GAAIH,KAAuBK,EAA3B,OAEO,IAAID,KAAyBJ,EAA7B,EAAgD,CAErDE,KAAY,CAACE,EAAeL,EAA5BG,GACAA,SAAc5C,EAAd4C,IAAwB,CAACF,EAAD,EAAxBE,IACA,MACSH,MAA0BM,GAA9B,EAELH,cAGAA,KAFSE,EAAJ,EAEO,CAACA,EAAeL,EAA5BG,GAGY,CAACF,EAAD,EAAZE,IAGJ,SAQU,aAACA,GACX,OAAOA,UAAc,CAACK,EAAKV,IAAUU,GAAOV,KAAWA,EAAXA,GAArCK,IAAP,IAIJ,UCvCA,OA9DA,MAUa,YAACM,GAAqD,IAA7BC,EAA6B,uDAAf,MAChD,GAAID,SAAJ,IAAqBA,SACnB,SAGF,OAAIA,SACF,OAAOA,EAAP,GAGF,OAAIA,SACF,gBAAUA,EAAV,6BAAqCA,EAArC,IAGF,IAAME,EAAWF,UAAeA,SAAfA,QAAjB,MACMG,EAAWH,EAAMA,SAAvB,GACA,gDAQY,eAACI,GACb,SAAIA,EAAc,CAChB,KAF8D,yDAG5D,SAGF,MAAM,IAAInD,MAAV,8CAGF,OAAOmD,EAAP,cASS,YAACC,EAAD,GAAmD,IAA5BC,IAA4B,yDAC5D,OAAID,EAAJ,EACSC,GAAW,EAAlB,EAEED,EAAJ,EACSC,EAAc,GAArB,EAEF,I,yHCvDJ,MAAMC,GAiCoB,yBAACC,GACvB,GAAoB,kBAATA,IAAsB/D,iBAAjC,GACE,MAAM,IAAIQ,MAAM,GAAV,SAAN,+DAKF,IAAMwD,EAAQX,WAAWU,EAAzB,MACME,EAAOZ,WAAYU,EAAD,KAAxB,IACMG,EAAUH,EAAhB,GAEA,MACE,UAAGC,sBAAH,cACGC,KAAYD,EAAZC,oBADH,cAEGF,MAAa,4BAAbA,iBAHL,MAWe,kBAACI,GAChB,GAC2B,kBAAlBA,IACNnE,iBADD,IAEAmE,EAHF,EAKE,MAAM,IAAI3D,MAAM,GAAV,SAAN,+DAKF,IAAMwD,EAAQI,OAAOf,WAAWc,EAAgB,OAAlCC,WAAd,KAKMC,EAAoBF,EAAgB,KACpCG,EAAUF,OAAOf,WAAWgB,EAAlBD,gBAAhB,KAEMG,EAAoBF,EAA1B,GACMH,EAAUE,OAAOf,UAAPe,eAAhB,KAEA,+CAGiB,oBAACI,GAClB,OAAO,IAAIC,OAAOX,GAAX,mBAAP,GAOc,iBAACY,GACf,IAAKA,GAAL,kBAA0BA,EACxB,MAAM,IAAIlE,MAAM,GAAV,SAAN,2BAGF,IAAMmE,EAAaD,QAAnB,KAEA,OAAIC,SACF,MAAM,IAAInE,MAAM,GAAV,SAAN,6CAGF,OACER,UAAO2E,EAAP3E,UACAA,OAAO2E,EAAP3E,IACAA,OAAO2E,EAHT,K,GAnGEb,G,eACkB,4C,GADlBA,G,aAGgBhG,OAAA,OAAc,CAChC,CAAE8G,MAAF,qBAA+BC,MAAO,cACtC,CAAED,MAAF,qBAA+BC,MAAO,cACtC,CAAED,MAAF,yBAAmCC,MAAO,kBAC1C,CAAED,MAAF,yBAAmCC,MAAO,kBAC1C,CAAED,MAAF,0BAAoCC,MAAO,gBAC3C,CAAED,MAAF,eAAyBC,MAAO,iBAChC,CAAED,MAAF,sBAA6BC,MAAO,OACpC,CAAED,MAAF,kBAAyBC,MAAO,iBAChC,CAAED,MAAF,kBAA4BC,MAAO,qBACnC,CAAED,MAAF,yBAAmCC,MAAO,oBAC1C,CAAED,MAAF,gBAA0BC,MAAO,mBACjC,CAAED,MAAF,sBAA2BC,MAAO,oBAClC,CAAED,MAAF,gBAA0BC,MAAO,mBACjC,CAAED,MAAF,eAAyBC,MAAO,kBAChC,CAAED,MAAF,oBAA8BC,MAAO,uBACrC,CAAED,MAAF,kBAA4BC,MAAO,qBACnC,CAAED,MAAF,yBAAmCC,MAAO,oBAC1C,CAAED,MAAF,eAAyBC,MAAO,iBAChC,CAAED,MAAF,kBAA4BC,MAAO,oBACnC,CAAED,MAAF,sBAAgCC,MAAO,eACvC,CAAED,MAAF,gBAA0BC,MAAO,uBAmFrC,UC9GmCrE,MCAnC,MAAMsE,WAAwBtE,MAAM,c,UAAA,oB,GAAA,G,EAAA,e,EAAA,M,uFAIpC,I,SAAA,M,gIC2BA,MAAMuE,GAGoB,2BACtBA,sBAGqB,0BACrBA,sBAGyB,4BAACC,GAC1B,OAAOC,cAAeD,EAAtB,gBAQmB,sBAACpB,EAAD,GACnB,OAAIA,UAAYsB,EAAhB,OACUtB,SAAD,IAAkBsB,SAAlB,MAAP,EAGEtB,UAAYsB,EAAhB,OACUtB,SAAD,IAAkBsB,SAAlB,MAAP,EAGEtB,UAAYsB,EAAhB,OACUtB,SAAD,KAAmBsB,SAAnB,OAAP,EAGEtB,IAAJ,EACSA,OAAP,EAGF,EAOgB,mBAACuB,GACjB,IAAKA,IAAYF,cAAjB,GACE,SAGF,IAAMG,EAAgBD,EAAtB,QAEA,OADAC,OAAmBL,GAAnBK,gBACA,EAGkB,uBAClB,IAAM,SAAEC,GAAaC,OAArB,UACA,OAAOD,aAAP,OAMmB,wBACnB,OAAIN,GAAJ,gBACE,UAGF,UAOsB,yBAAC,GAIvB,OAAOQ,EADaR,GAApB,kBAS0B,uBAACpB,GAA6B,O,EAAA,YACxD,IACE,IAAM6B,QAAoBC,UAAA,kBAA4B,CACpDxG,KAAM,oBAER,GAAIuG,qBAAJ,WAAuCA,QACrC,MAAM,IAAIhF,MAAV,2CAEF,MAAOwE,GAGP,YADAD,uCAIIU,8BAAN,I,yLAQ+B,kCAAC9B,GAChC,IAAM+B,EAAWC,SAAjB,cACMC,EAAWD,uBAAjB,YAMA,GALAC,UACAD,6BACAC,UACAA,YAEKD,qBAAL,QACE,MAAM,IAAInF,MAAV,kCAGFmF,6BAEID,aAAJ,aACEA,UAoBe,oBAAC,GAGN,IADZG,IACY,yDACRC,EAAJ,GACIX,EAAJ,EACKF,cAAL,KACEE,EAAU,CAAVA,IAGF,IAAK,IAAI9E,EAAT,EAAgBA,EAAI8E,EAApB,OAAoC9E,GAApC,EAA4C,CAC1C,IAAM0F,EAASZ,EAAf,GACIa,OAGwB,EAO5B,OALEA,EADF,oBAAW,EACMD,IAEfC,KAIIA,aAAJ,QACE,GACEF,UAEOb,cAAJ,GACLa,EAAYA,SAAZA,GAEAA,WAYN,OAPAA,EAAYA,UACVC,GACGA,EAAD,OACCA,EADD,MAECA,EAJLD,cAgBoB,uBAAC,EAAD,KAKpB,IAAIG,EAAJ,EACIA,KAAkBC,EAAtB,IAEED,EAAaH,EAAbG,QAGF,IAAK,IAAI5F,EAAT,EAAgBA,EAAIyF,SAApB,EAA0CzF,GAA1C,EAAkD,CAChD,IAAM8F,GACHF,EAAaC,EAAbD,EAAyBH,EAA1B,QAA8CA,EADhD,OAEMM,EAAON,EAAb,GACA,KAAMM,aAAF,WAAJ,IAAkCA,WAChC,SAGJ,U,IApNuB,G,2BADrBrB,I,4FAyNN,UCvOMsB,GAAkB,gBACtB,CAACC,EAAD,KAAsC,MAMpC,cACE,IAAM,+BAAYC,GAAlB,EACAA,EAAoBC,EAApBD,GAoCF,IAAM,2DAA0CE,GAAhD,EAEMC,EAAe,UAAGF,EAAH,6BAAGA,EAAxB,iBACI/L,EAAJ,KACA,GAAI+L,EAAJ,KAAmB,CACjB,IAIE,EAJIG,EAAeH,EAArB,KACA,GAAII,mBAAJ,GACEnM,SAGI+L,cAAuBA,EAA3B,WACEK,EAAQ,CAAEC,MAAON,EAASO,YAE5BtM,EAAO,uBAAiBA,KAAjB,EAAqCoM,MAAOA,IAIvD,IAAIG,EAAJ,KACMC,IAAN,EACIT,EAAJ,UACEQ,EAAmB,uBAAiBvM,KAAMG,KAE5C,IAAIsM,EAAJ,KACA,GAAIV,EAAJ,YACEU,EACE,yBAAK/I,UAAL,mBAAkCgJ,YAAaC,GArDnD,gBAME,qBAAW7F,EAAP8F,KACF,SAEF,IAAM,4DAIJZ,GAJF,EAMMa,EAAiB,6EAMrBZ,mBAEF,OAAO,mBAA4B,CACjCY,mBA8BGC,CAAwBf,EAAD,cAF5BU,QAKK,CACL,IAAMM,EAAmBhB,EAAzB,SACMiB,EAAiBjB,EAAvB,YACAU,EACE,4BACEG,KADF,SAEElJ,UAAWC,IAAW,mBAEpB,CAAEsJ,SAAUF,GACZ,CACEG,QAASV,GAAD,KAAyCO,GAEnD,CAAE,kBAAmBI,IAAuBJ,IAE9CK,QAtFN,YACE,IAAM,2BAAYC,GAAlB,EACAA,EAAgBtB,EAAhBsB,IAqFIX,YAXF,EAYEY,cA9EN,YACE,IAAM,iCAAYC,GAAlB,EACAA,EAAsBxB,EAAtBwB,IA6EIC,MAAOzB,eAAwB,IAE/B,yBAAKrI,UAAU,4BACb,0BAAMA,UAAWC,IAAW,OAAQ,CAAE8J,QAAST,KADjD,GAIE,0BAAMtJ,UAAU,SAASqI,EAJ3B,OAKGE,GACC,0BAAMvI,UAAU,YANpB,GAQG6I,GACC,0BACE7I,UAAWC,IAAW,oBAAqB,CACzCsJ,SAAUF,KA3BtBN,KAsCF,OACE,yBAAK/I,UAAL,oBAAmCgK,IAAKA,GAAxC,EADF,MASJ9B,iCAEAA,gBAA+B,CAC7B+B,SAD6B,KAE7BR,oBAF6B,EAG7BnB,iBAAiB,GAGnB,U,6rBC1IA,IAAM4B,GAAMC,UAAZ,eAoCA,MAAM,WAAN,gBAiB0B,yBAACtD,GACnBA,EAAJ,UAIAA,oBACAA,oBAGFhG,YAAYsH,GACV5G,MAAA,GADmC,iLAGnCP,KAAA,WAAkBA,KAAKoJ,WAAWC,KAAlCrJ,MACAA,KAAA,mBAA0BA,KAAKsJ,mBAAmBD,KAAlDrJ,MACAA,KAAA,cAAqBA,KAAKuJ,cAAcF,KAAxCrJ,MACAA,KAAA,oBAA2BA,KAAKwJ,oBAAoBH,KAApDrJ,MACAA,KAAA,0BAAiCA,KAAKyJ,0BAA0BJ,KAAhErJ,MACAA,KAAA,wBAA+BA,KAAKiI,wBAAwBoB,KAA5DrJ,MACAA,KAAA,iBAAwBA,KAAK0J,iBAAiBL,KAA9CrJ,MACAA,KAAA,mBAA0BA,KAAK2J,mBAAmBN,KAAlDrJ,MAEAA,KAAA,UAAiByH,IAAjB,YACAzH,KAAA,SAAgBwG,SAAhB,cACAxG,KAAA,iBAAwByH,IAAxB,YACAzH,KAAA,eACAA,KAAA,MAEAA,KAAA,gBAAuB,CAAE4J,IAAKzC,EAAP,IAAkB0C,KAAM1C,EAAM0C,MAErD7J,KAAA,MAAa,CACX2G,UADW,GAEXmD,aAFW,GAGXC,cAHW,KAIXC,aAJW,EAKXC,WALW,KAMXC,YANW,KAOXC,mBAPW,EAQXC,oBARW,EASXC,eATW,EAUXC,YAAa,GAIjBC,oBACEvK,KAAA,WAEAA,KAAA,iBAEAmG,iCAAkCnG,KALV,oBAWxBA,KAAA,IAAWmG,OAAA,uBAA6B,KAAM,MAC5C,UAAAnG,KAAA,0CAEA,IAAM,aAAEwK,GAAiBxK,KAAzB,MACAwK,WAIJC,mBAAmB,EAAD,GAIhB,IAI6B,EASM,EAG8B,GAhB3D,QAAEzE,GAAYhG,KAApB,OACM,cAAE+J,GAAkB/J,KAA1B,MAEI+J,IAAkBW,EAAtB,gBACE,MAAIX,EAEF,UAAA/J,KAAA,0CAGAA,KAAA,4BAIA2K,YAAJ,IACE3K,KAAA,WAEI,UAACA,KAAK4K,UAAN,sBAAC,WAAiCpE,SAAtC,gBACE,UAAAxG,KAAA,2CAIJA,KAAA,iBAGF6K,uBACE7K,KAAA,iBACAmG,oCAAqCnG,KAArCmG,oBACA2E,qBAAqB9K,KAArB8K,KAeFC,mBACE,IAAM,QAAEC,GAAYhL,KAApB,MACA,GAAIgL,EAAJ,sBAAmC,CACjC,IAAM,cAAEX,GAAkBrK,KAA1B,MACA,SAGF,OAAOA,KAAP,gBAGFiL,iBAAiBpH,GACf,IAAM,QAAEmH,GAAYhL,KAApB,MACIgL,EAAJ,sBACEhL,KAAA,SAAc,CAAEqK,cAAexG,IAE/B7D,KAAA,iBAIJkL,gBACE,IAAM,WAAEZ,GAAetK,KAAvB,MACA,SAGFmL,cAActH,GACZ7D,KAAA,SAAc,CAAEsK,WAAYzG,IAG9BuH,WAEEpL,KAAA,iBACA8K,qBAAqB9K,KAArB8K,KAEA,IAAM,QAAEE,GAAYhL,KAApB,MACIqK,EAAgBW,EAApB,0BACA,IAAIX,IACFA,MAMF,IAHA,IAAM,QAAErE,GAAYhG,KAApB,MACM2G,EAAYf,gBAAlB,GACMyF,EAAN,GACSnK,EAAIyF,SAAb,EAAmCzF,GAAnC,EAA2CA,GAA3C,EAAmD,CACjD,IAAMmG,EAAWV,EAAjB,GACIU,aAAJ,QACErH,KAAA,mBAEAqL,UAIJrL,KAAA,SAAc,CACZsK,YADY,kBAGZP,cAHY,KAIZpD,UAAWf,oBAIf0F,gBAAgBpI,GAEd,IAAMqI,EAAqBpI,kBAA3B,GAEAnD,KAAA,UAAcwL,IAAS,CACrB1B,aAAc0B,6BAGhBD,QACEE,IACEzL,KAAA,UAAcwL,IACZ,IAAM3H,EAAQ2H,uBAAd,GACA,GAAI3H,GAAJ,EAAgB,CACd,IAAMiG,EAAe0B,eAArB,QAGA,OAFA1B,cAEO,CACLnD,UAAWf,eACT4F,mBAFG,IAIL1B,gBAIJ,kBAGJ9G,IACMG,cAAJ,KAKAnD,KAAA,UAAcwL,IACZ,IAAM3H,EAAQ2H,uBAAd,GACA,GAAI3H,GAAJ,EAAgB,CACd,IAAMiG,EAAe0B,eAArB,QAEA,OADA1B,cACO,CACLA,gBAGJ,eAIFZ,gBAKNwC,iBACE,IAAM,aAAE5B,GAAiB9J,KAAzB,MACA8J,OAAiB7C,GAAQA,EAAzB6C,WAOF6B,2BACE,UAAI3L,KAAK4L,iBAAiBC,QAA1B,CACA,IAAMC,EAAa9L,KAAK4L,iBAAiBC,QAFV,wBAK/B7L,KAAA,SAAc,CACZiK,WAAY6B,EADA,IAEZ5B,YAAa4B,EAFD,MAGZ1B,oBAAqB0B,EAHT,OAIZ3B,mBAAoB2B,EAAWC,SAYnCC,iBAAuB,aACf,sEAKJpC,IALI,EAMJC,KAAMoC,GACJjM,KAPJ,MASA,GAAKA,KAAK4K,UAAN,UAA2BI,EAA/B,qBAOA,IAAI,WAAOnB,GAAS7J,KAApB,iBACM,eAEJkM,GAFI,oBAGFlM,KAAK4K,UAHH,4BAGF,EAHE,uCAGiD,CACrDmB,MADqD,EAErDG,OAAQ,GAEJlC,GACJ,oBAAChK,KAAK4K,UAAN,4BAAC,EAAD,+BAA8CzE,OADhD,YAGI+F,OAAJ,IAAoBH,IAMhBnC,IAAezD,OAAnB,cAEMyD,MAAJ,EAEEA,GAAOsC,EAAPtC,EAGAA,EAAMzD,mBAANyD,GAIAC,IAAe1D,OAAnB,aAEE0D,EAAOA,IAAPA,GAGEoC,OAAoBE,IAAxB,IAEEnM,KAAA,SAAc,CAAEgK,gBAChBoC,EAAexC,EAAfwC,MAKJzC,qBACO3J,KAAK4K,UAAV,SAGA5K,KAAA,cAGFoJ,WAAWvD,GACT,GAAK7F,KAAK4K,UAAV,SAKA,IAAK5K,KAAK4K,UAAUiB,QAAQQ,SAASxG,EAArC,eAA+D,CAG7D,IAFA,IAAIzD,EAA8ByD,EAAlC,cACIyG,GAAJ,EACOlK,IAAP,GACEkK,EAAqBlK,eAArBkK,wBACAlK,EAAUA,EAAVA,cAGF,GAEEpC,KAAA,oBAdFkJ,8BAoBJqD,YAAYC,GACV,IAAM,KAAE3C,GAAS7J,KAAjB,MACA,MACEwM,cACC3C,KADD2C,eACaA,GAFf,cAGEA,EAIJjD,cAAc1D,GACZ,IAAM,UAAEc,GAAc3G,KAAtB,MACMuG,EAAWvG,KAAjB,mBACIyM,EAAJ,EACIC,GAAJ,EAEA,GAAI7G,iBAAJ,MAAyBA,MAAzB,CAwBA,GAdA,eAAIA,MACEU,MAAiBA,GAAYI,EAAjC,OACE+F,KAEAD,IAEOzM,KAAKuM,YAAY1G,EAArB,KACL4G,OACS5G,mBAAwBA,YAA5B,QAA0CA,MAC/C4G,EAAW7G,wBAAX6G,GACS5G,qBAAJ,QAA6BA,QAClC4G,EAAW7G,uBAAX6G,IAGF,EAIE,OAHAzM,KAAA,eACA6F,wBACAA,oBAIEU,IAAJ,IACE,OAAIkG,EACFzM,KAAA,qBAEAA,KAAA,YACIA,KAAKuG,oBAAT,aACEvG,KAAA,kBAIJ6F,mBACAA,0BAzCIU,MAAiBA,EAAWI,EAAhC,QACE3G,KAAA,oBACE2G,EADF,MA4CN+F,YAAY7I,GACV,IAAM,0BAAakG,GAAkB/J,KAArC,MACM2M,EAAahG,eAAnB,KACIoD,IAAJ,GACA/J,KAAA,SAAc,CACZ+J,cADY,EAEZE,WAFY,KAGZC,YAAa,OAIjB0C,YAAkC,IAAxBC,EAAwB,yDAC1B,yBAAaC,GAAiB9M,KAApC,MACA8K,qBAAqB9K,KAArB8K,KACA9K,KAAA,IAAWmG,OAAA,uBAA6B,KACtCyG,KACAE,WAIJC,eACE/M,KAAA,SAAc,CACZ+J,cAAe,OAInBT,mBAAmB0D,GACjB,EACEhN,KAAA,cAEAA,KAAA,eAIJwJ,oBAAoBnC,EAAD,GACjBxB,mBACAA,oBAEA,IAAM,UAAEc,GAAc3G,KAAtB,MACIqH,SAAqBA,EAAzB,WACE,MAAIA,UACFrH,KAAA,YAAiB2G,UAAjB,IACK,MAAIU,WACTA,WACArH,KAAA,gBAKNyJ,0BAA0B,EAAD,GAInB5D,EAAJ,SAIA7F,KAAA,yBAGFiI,wBAAwBZ,GACtB,IAAM,UAAEV,GAAc3G,KAAtB,MACMiN,EAAatG,UAAnB,GACA3G,KAAA,iBAGEiN,MACAA,EAAatG,EADbsG,SAEC5F,EAHH,UAKErH,KAAA,eAIJ0J,mBACE1J,KAAA,kBAGFkN,SAeE,IAdA,IAAMC,EAAN,IACM,WAAOtD,GAAS7J,KAAtB,OACM,0JAUJoK,GACEpK,KAXJ,MAYSkB,EAAT,EAAgBA,EAAIyF,EAApB,OAAsCzF,GAAtC,EAA8C,CAC5C,IAAMmG,EAAWV,EAAjB,GAEIzF,KAASmG,UAAmBV,EAAUzF,EAAVyF,GAAhC,OACEwG,OAAsB,wBAAIX,IAAG,6BAG/B,IAAMY,EACJ,sBACEZ,IADF,EAEExD,IAAKe,MAAsB/J,KAAtB+J,iBAFP,KAGEtB,mBAAoB4B,IAHtB,EAIE/C,gBAAiBgD,IAJnB,EAKEjD,SALF,EAMEuF,UAAW5M,KANb,mBAOE2I,gBAAiB3I,KAPnB,oBAQEoH,oBAAqBpH,KARvB,wBASE6I,sBAAuB7I,KAAKyJ,4BAIhC0D,UAGF,IAAIE,EAAJ,KACIvD,SAAJ,IACEuD,EACE,yBAAKrO,UAAU,WACb,qBAFJqO,QAOF,IAAM,UAAEC,GAActN,KAhDF,MAmDduN,EACJxD,iBAA0BE,GAD5B,OACmDC,EAEnD,OACE,oCACE,yBACElL,UAAWC,IACT,CAAE,eAAgB+K,GAFtB,0BAKEtC,MAAK,UAASmC,QALhB,GAMEb,IAAKhJ,KANP,UAOE,wBAPF,EAQEwN,OAAQxN,KARV,WASEyN,UAAWzN,KATb,cAUE0N,aAAc1N,KAVhB,iBAWE4I,cAAe+E,GAXjB,kBAYEC,KAZF,WAaEC,SAAU,GAbZ,EADF,GAmBGN,UACCxD,GADDwD,OAECtD,GAFDsD,OAGCrD,GACE,sBACEsC,IAAG,cADL,GAEExG,QAASW,cAFX,GAGEiG,UAAW5M,KAHb,mBAIE4J,IAJF,EAKEC,KALF,EAMEuC,eAAgB,CAAC0B,EAAaC,KAC5B/N,KAAA,SAAc,CACZiK,WADY,EAEZC,YAAa6D,KAGjB5D,mBAZF,EAaEC,oBAAqBA,M,GAtkB7BuD,G,eACkB,CACpBxD,mBADoB,EAEpBC,oBAFoB,EAGpBwC,cAGApC,iBAGAsC,iBAGA9B,QAZoB,GAapBsC,UAAW,KAgkBf,U,yHC7mBA,MAAM,WAAN,YAIEzN,YAAYsH,GACV5G,MAAA,GADuC,uDAGvCP,KAAA,gBAAuBA,KAAKgO,gBAAgB3E,KAA5CrJ,MACAA,KAAA,kBAAyBA,KAAKiO,kBAAkB5E,KAAhDrJ,MACAA,KAAA,UAAiByH,IAAjB,YACAzH,KAAA,SAAgByH,IAAhB,YAEAzH,KAAA,MAAa,CACXgG,QADW,KAEX6D,KAFW,EAGXD,IAAK,GAITW,oBAA0B,MACxB,UAAIvK,KAAK4K,UAAT,sBAAI,EAAJ,eACE5K,KAAA,+DAEEA,KAFF,mBAOJ6K,uBAA6B,MAC3B,UAAI7K,KAAK4K,UAAT,sBAAI,EAAJ,eACE5K,KAAA,kEAEEA,KAFF,mBAWJiO,kBAAkBpI,GAChB,GAAKD,wBAAL,IAIK5F,KAAK4K,UAAV,UAII/E,YAAaA,EAAjB,SAKA,IAAMqI,EAAiBtI,gBAAgCC,EAAvD,gBAEMiG,EAAa9L,KAAK4K,UAAUiB,QAAlC,wBACMjC,EAAM/D,UAAYiG,EAAxB,IACMjC,EAAOhE,UAAYiG,EAAzB,KAEA,OAAIoC,SAIF,OAAIrI,WAAa7F,KAAK4K,UAAtB,SAEE/E,EAFuC,sBAQvC7F,KAAA,SAAc,CAAEgG,QAAS,OAAQ,KAC/B,IAAM5D,EAAUoE,4BADqB,GAG/B2H,EAAa,IAAIC,WAAW,cAAe,CAC/CC,QAASxI,EADsC,QAE/CyI,QAASzI,EAFsC,QAG/C0I,SAH+C,EAI/CC,YAAY,IAGdpM,eAAO,IAAPA,+BAMJ,EAIFyD,mBACA7F,KAAA,SAAc,CACZgG,QADY,QAGZ6D,UAIJmE,gBAAgBS,GACVA,IAASzO,KAAK0O,SAAlB,SACE1O,KAAA,SAAc,CAAEgG,QAAS,OAI7BkH,SACE,IAAIuB,EAAJ,MACM,qBAAgB5E,GAAS7J,KAA/B,MAeA,OAdA,IACEyO,EACE,sBACEzF,IAAKhJ,KADP,SAEEgG,QAFF,EAGE8G,aAAc9M,KAHhB,gBAIE4J,IAJF,EAKEC,KALF,EAMEuC,eAAgB,CAAC0B,EAAaC,KAC5B/N,KAAA,SAAc,CAAE4J,IAAF,EAAoBC,KAAMkE,QAM9C,yBACE/O,UAAWC,IAAW,oBAAqB,CAAEuJ,OAAQxC,IACrDgD,IAAKhJ,KAAK4K,WAHd,IAWJ,WC7IM,GAAE+D,IAAR,WAEA,M,mBCVMC,GAAS,WAAgB,CAC7B9O,KAAM+O,YADuB,WAE7B3G,KAAM2G,YAFuB,WAG7BC,YAAaD,KAHgB,OAI7BE,gBAAiBF,KAAUG,SAGvBC,GAAkB,WAAgB,CACtCC,IAAKL,UADiC,WAEtCM,IAAKN,UAFiC,WAGtCO,GAAIP,UAAeQ,aAGfC,GAAO,WAAgB,CAC3BC,IAAKV,UADsB,WAE3BW,KAAMX,UAFqB,WAG3BY,IAAKZ,UAHsB,WAI3Ba,OAAQd,GAJmB,WAK3Be,UAAWd,YALgB,WAM3Be,MAAOf,UAAeQ,aAGlBQ,GAAQ,WAAgB,CAC5BC,QAASjB,iBADmB,WAE5BkB,cAAelB,aAAkBA,KAAlBA,QAFa,WAG5BmB,OAAQnB,aAHoB,IAI5BoB,iBAAkBpB,UAJU,WAK5BqB,oBAAqBrB,UALO,WAM5BsB,KAAMtB,YANsB,WAO5BuB,KAAMvB,aAAkBA,KAPI,KAQ5BwB,KAAMxB,UARsB,WAS5ByB,YAAazB,UATe,WAU5B0B,UAAW1B,UAViB,WAW5B2B,mBAAoB3B,UAXQ,WAY5BC,YAAaD,KAAUG,SAGnByB,GAAY,WAAgB,CAChCX,QAASjB,aADuB,IAEhCmB,OAAQnB,aAAkBA,KAFM,KAGhC6B,WAAY7B,UAHoB,WAIhC8B,kBAAmB9B,UAJa,WAKhCoB,iBAAkBpB,UALc,WAMhCqB,oBAAqBrB,UANW,WAOhCsB,KAAMtB,YAP0B,WAQhCuB,KAAMvB,aAAkBA,KARQ,KAShCyB,YAAazB,UATmB,WAUhC0B,UAAW1B,UAAeQ,aAGtBuB,GAAqB,WAAgB,CACzC9Q,KAAM+O,YADmC,WAEzC3G,KAAM2G,YAAiBQ,aAGnBwB,GAAkB,WAAgB,CACtCC,QAASjC,iBAD6B,WAEtCkC,QAASlC,iBAF6B,WAGtCmC,QAASnC,iBAAsCQ,aAG3C4B,GAAe,WAAgB,CACnCC,gBAAiBrC,aAAkBA,KADA,QAEnCsC,aAActC,WAFqB,IAGnCuC,oBAAqBvC,KAHc,KAInCwC,uBAAwBxC,KAJW,KAKnCyC,oBAAqBzC,KAAU0C,OAG3BC,GAAa,WAAgB,CACjCvB,iBAAkBpB,UADe,WAEjCqB,oBAAqBrB,UAFY,WAGjC4C,aAAc5C,KAHmB,KAIjC6C,SAAU7C,UAJuB,WAKjC8C,QAAS9C,UAAeQ,aAe1B,GAZoB1Q,OAAA,OAAc,6GAShCiS,wB,yHC3EF,MAAM,GA6BkB,uBAAC,EAAD,GASP,IANbgB,EAMa,uDANL,EACRC,EAKa,uDALP,EACNC,EAIa,uDAJN,EACPC,EAGa,uDAHJ,EACTC,EAEa,uDAFJ,EACTC,EACa,uDADR,EAECC,EAAa,wBAAnB,KACMC,EAAc,UAAGP,EAAH,cAApB,KACMQ,EAAY,wBAAlB,KACMC,EAAa,wBAAnB,KACMC,EAAe,wBAArB,KACMC,EAAe,wBAArB,KACMC,EAAa,wBAAnB,KAEMC,EAAa,GAAH,2FAAhB,GACA,OAAO9D,6BACL+D,GADK/D,mBAGLA,6BAHF,IAYiB,oBAAC6D,GAClB,IAAMG,EAAW/R,SAAS4R,EADoB,IAGxCI,EAAQ,IAAIC,OAAO,EAAIL,EAA7B,QACMM,EAAiB,GAAH,OAAMH,EAAN,UAApB,GACA,OAAO/R,SAASkS,EAAhB,IASgB,mBAAC,EAAD,KAKhB,IAAI,wDAA8CC,GAAlD,EAEA,SAAIvN,QAA0B,CAC5B,OAAIA,eAEF,aAEFuN,EAAQL,gBAAuBlN,EAA/BuN,QACA,YAEEhO,KACAgO,UAEG,MAAIvN,UACTT,KACK,MAAIS,UACTL,KACK,MAAIK,QACTX,KACK,MAAIW,OACTwN,KACK,MAAIxN,QACToM,KAEAqB,KAMF,IAAMC,EAAS,IAAIC,KAAKF,EAAMrB,EAAOoB,EAAMnO,EAAOM,EAAlD,GACA,OAAOuN,qBAELQ,EAFKR,cAGLQ,EAHKR,WAILQ,EAJKR,UAKLQ,EALKR,WAMLQ,EANKR,aAOLQ,EAPKR,aAAP,GAkBe,kBAACP,GAChB,IAAMP,EAAQhR,SAASuR,EAAvB,IACA,IAAKtR,aAAL,GACE,OAAI+Q,MAAcA,GAAlB,GACSA,EAAP,EAEF,IAGF,IAAMwB,EAAmBjB,SAAzB,cACA,GAAIiB,UAAJ,EACE,IAAK,IAAIlS,EAAT,EAAgBA,EAAIwR,UAApB,OAA6CxR,GAA7C,EACE,GAAIwR,wBAAJ,GACE,SAKN,WAeoB,uBAAC,EAAD,aASpB,IAAMO,EAAOrS,SAASsR,EAAtB,IACMN,EAAQO,QAAsBnS,KAAKqT,WAA3BlB,GAAd,EACMa,EAAOZ,QAAoBxR,SAASwR,EAA7BA,IAAb,EACMvN,EAAQwN,QAAqBzR,SAASyR,EAA9BA,IAAd,EACMlN,EAAUmN,QAAuB1R,SAAS0R,EAAhCA,IAAhB,EACMvN,EAAUwN,QAAuB3R,SAAS2R,EAAhCA,IAAhB,EACMQ,EACJP,QAAqB5R,SAAS4R,WAAD,KAA7BA,IADF,EAEA,OACE3R,iBACAA,aADAA,IAEAA,aAFAA,IAGAA,aAHAA,IAIAA,aAJAA,IAKAA,aALAA,IAMAA,aAPF,GASE,KAGK,mDAA8CkS,SAU7B,2BAACO,GACzB,IACMC,EADN,6GACeC,KAAf,GACA,SAAID,EACF,MAAM,IAAIlS,MAAM,2BAAV,OAAN,IAGF,IAAO,CAAD,uBAAN,EAiBA,GAAIoS,SAAoBA,SAAxB,EACE,MAAM,IAAIpS,MAAM,4CAAV,uBAAN,IAKF,MAAO,mDAA8C0R,SASlC,sBAAC,EAAD,GAInB,IAAMW,EAAYlP,SAAlB,cACA,OAAIkP,SACF,MAAM,IAAIrS,MAAV,6CAGF,YAAIqS,EACF,MAAO,CAAC,KAAR,MAGF,aAAIA,EAAuB,CACzB,IAAMC,EAAM,IAAIR,KAAKA,KAArB,OAaA,MAAO,CAZWT,qBAEhBiB,EAFgBjB,cAGhBiB,EAHgBjB,WAIhBiB,EAJF,WAMgBjB,qBAEdiB,EAFcjB,cAGdiB,EAHcjB,WAIdiB,YAJF,IASF,iBAAID,EAA2B,CAC7B,IAAMC,EAAM,IAAIR,KAAKA,KAArB,OAaA,MAAO,CAZWT,qBAEhBiB,EAFgBjB,cAGhBiB,EAHgBjB,WAIhBiB,YAJF,GAMgBjB,qBAEdiB,EAFcjB,cAGdiB,EAHcjB,WAIdiB,EAJF,YASF,WAAID,EAAqB,CACvB,IAAMC,EAAM,IAAIR,KAAKA,KAArB,OAEA,MAAO,CADMxE,wBAAb,GACA,MAGF,IAAMnJ,EAAakN,uBAAnB,GACA,GACElN,oBACAA,SAFF,MAGEA,OAEA,MAAM,IAAInE,MAAM,yCAAV,OAAN,IAGF,IAAMuS,EAASlB,mBACblN,EADakN,KAEblN,EAFakN,MAGblN,EAHakN,KAIblN,EAJakN,MAKblN,EALakN,QAMblN,EANakN,QAOblN,EAPF,OAUA,SAAIoO,EACF,MAAM,IAAIvS,MAAM,sCAAV,OAAN,IAeF,MAAO,CAZWqR,qBAEhBkB,EAFgBlB,KAGhBkB,EAHgBlB,MAIhBkB,EAJgBlB,KAKhBkB,EALgBlB,MAMhBkB,EANgBlB,QAOhBkB,EAPgBlB,QAQhBkB,EARF,OAWgBlB,mBAAhB,IASc,iBAACmB,GACf,wBAAWA,EACF,IAAIV,KAAX,GAEKU,EAAP,U,GAnVEnB,G,mBACsB,iC,GADtBA,G,SAGY,CAAC,UAAD,sGAoVlB,U,yHCnWO,MAAMoB,I,4HAAAA,G,KACU,M,GADVA,G,eAGoB,gB,GAHpBA,G,QAKa,S,GALbA,G,kBAOuB,mB,GAPvBA,G,cASmB,e,GATnBA,G,uBAW4B,wB,GAX5BA,G,WAagB,Y,GAbhBA,G,oBAeyB,qB,GAfzBA,G,KAiBU,M,GAjBVA,G,eAmBoB,gB,GAnBpBA,G,QAqBa,S,GArBbA,G,kBAuBuB,mB,GAvBvBA,G,SAyBc,U,GAzBdA,G,UA2Be,W,GA3BfA,G,SA6Bc,U,GA7BdA,G,SA+Bc,U,GA/BdA,G,WAiCgB,Y,GAjChBA,G,cAmCmB,e,GAnCnBA,G,aAqCkB,c,GArClBA,G,WAuCgB,Y,GAvChBA,G,cAyCmB,eC1CzB,MAAMC,I,4HAAAA,G,MACW,O,GADXA,G,MAGW,O,GAHXA,G,KAKU,MCqBvB,IAAM7K,GAAMC,UAAZ,cAOA,MAAM,GA0Be,oBAACiH,EAAD,GACjB,IAAK,IAAIlP,EAAT,EAAgBA,EAAIkP,EAApB,OAAiClP,GAAjC,EAAyC,OAEvC,IAAI,UADMkP,EAAV,GACI,sCAAJ,EACE,SAIJ,YAQqB,wBAAC4D,EAAD,GACrB,IAAMC,EAAYC,kBAAlB,GACA,aAAID,EACKD,EAAP,GAEF,KAGkB,qBAAChE,GACnB,SACSA,EAAP,WAEF,KAImB,sBAACmE,GACpB,OAAID,iBAAJ,GACS,CAACJ,GAAD,OAAoBA,GAApB,QAAwCA,GAA/C,QAKEI,cAAJ,GACS,CAACJ,GAAD,GAAgBA,GAAvB,OAGAI,oBACAA,cAFF,GAIS,CACLJ,GADK,GAELA,GAFK,MAGLA,GAHK,YAILA,GAJK,qBAKLA,GALK,SAMLA,GANF,mBASEI,cAAJ,GACS,CACLJ,GADK,GAELA,GAFK,aAGLA,GAHK,MAILA,GAJK,gBAKLA,GALK,SAMLA,GANK,YAOLA,GAPK,WAQLA,GARF,UAWF,GAGgB,mBAACM,EAAD,GAChB,IACGA,IACAA,EADD,SAEAC,EAFA,GAGAA,GAAeD,UAJjB,OAME,YAGF,IAAMhE,EAAO8D,oBAA4BE,EAA5BF,KAAb,GACA,cAAI9D,EACKgE,oBAAP,MAEEhE,cAAmB8D,iBAAvB,UACS9D,EAAP,OAEF,KAGmB,sBAAC,EAAD,OAMnB,IACGgE,IACAA,EADD,SAEAC,EAFA,GAGAA,GAAeD,UAJjB,OAME,YAGF,GAAIzE,IAAcuE,iBAAlB,KACE,YAGF,IAAI9D,EAAOgE,aAAX,OAEA,UACE,KAAKF,iBAAL,UACE9D,EAAOA,EAAPA,MACA,MACF,KAAK8D,iBAAL,WACE9D,EAAOA,EAAPA,OAQJ,OAHA,IACEA,EAAOA,EAAPA,OAEF,EAUwB,2BAAC,EAAD,KAKhB,IADRkE,EACQ,wDACR,IAAKF,GAASC,EAAV,GAA6BA,GAAeD,UAAhD,OACE,SAGF,IAAMG,EAAUL,iBAAhB,GAEA,OAAOA,0BAAP,GAQe,kBAAC,EAAD,SAOf,IAAKE,GAASI,EAAV,GAA6BA,GAAeJ,UAAhD,OACE,SAGF,IAAMG,EAAUL,wBAAhB,GAOA,OAAOA,oBACLE,EADKF,SAAP,GAgBqB,wBAAC,EAAD,KAKb,IADRI,EACQ,wDACFL,EAAYC,kBAAlB,GACIO,EAAJ,GAgBA,OAfA,IACEA,EAAQA,EAAA,OACNT,EAAA,QACE,QAAC,UAAErE,GAAH,SAAmBA,IAAcuE,iBAAjC,YAGJ,OAAID,GACFQ,eAIJ,OAAIrE,GACFqE,UAGF,EAGsB,yBAACN,GACvB,UACE,cACA,wBACA,KAAKD,YAAL,QACE,OAAOA,YAAP,QACF,WACA,0BACA,KAAKA,YAAL,KACE,OAAOA,YAAP,KACF,uBACA,KAAKA,YAAL,OACE,OAAOA,YAAP,OACF,8CACA,iCACA,kDACA,KAAKA,YAAL,SACE,OAAOA,YAAP,SACF,aACA,uBACA,YACA,sBACA,KAAKA,YAAL,QACE,OAAOA,YAAP,QACF,UACA,wBACA,WACA,qBACA,YACA,sBACA,WACA,qBACA,KAAKA,YAAL,IACE,OAAOA,YAAP,IACF,QACE,aAIW,kBAACC,GAChB,UACE,WACA,qBACE,SACF,QACE,UAIW,kBAACA,GAChB,UACE,8CACA,iCACA,kDACE,SACF,QACE,UAIa,oBAACA,GAClB,OACED,qBACAA,iBAFF,GAMkB,qBAACC,GACnB,UACE,UACA,wBACA,2BACA,WACA,qBACA,YACA,sBACA,WACA,qBACE,SACF,QACE,UAIc,qBAACA,GACnB,UACE,aACA,uBACA,2BACA,YACA,sBACE,SACF,QACE,UAIc,qBAACA,GACnB,UACE,cACA,wBACE,SACF,QACE,UAIW,kBAACA,GAChB,UACE,WACA,0BACE,SACF,QACE,UAIW,kBAACA,GAChB,UACE,WACA,0BACA,uBACE,SACF,QACE,UASY,mBAACA,GACjB,OAAOA,cAAP,GASqB,wBAACO,EAAD,GACrB,OACER,0BACAA,qBAFF,GAaoB,uBAAC,EAAD,KAOpB,IAFA,IAAMS,EAAenQ,QAArB,MACIoQ,EAAJ,KACS1T,EAAT,EAAgBA,EAAIyT,EAApB,OAAyCzT,GAAzC,EAAiD,CAI/C,I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","file":"static/js/main.0038e360.chunk.js","sourcesContent":["\nvar prefix = \"dh\";\nvar vsAccount = {\n prefix: \"vs\",\n iconName: \"account\",\n icon: [512, 512, [], \"f000\", \"M512 255.744C512 114.56 397.312 0 256 0S0 114.56 0 255.744c0 77.76 35.328 147.84 90.624 194.88 0.512 0.512 1.024 0.512 1.024 1.024 4.608 3.584 9.216 7.168 14.336 10.752 2.56 1.536 4.608 3.552 7.168 5.6A255.36 255.36 0 0 0 256.512 512a255.36 255.36 0 0 0 143.36 -44c2.56 -1.536 4.608 -3.552 7.168 -5.12 4.608 -3.552 9.728 -7.136 14.336 -10.72 0.512 -0.512 1.024 -0.512 1.024 -1.024 54.272 -47.584 89.6 -117.632 89.6 -195.392zm-256 224.032c-48.128 0 -92.16 -15.36 -128.512 -40.928 0.512 -4.096 1.536 -8.16 2.56 -12.256a133.44 133.44 0 0 1 13.312 -31.712c5.632 -9.728 12.288 -18.432 20.48 -26.112 7.68 -7.68 16.896 -14.816 26.112 -20.448 9.728 -5.632 19.968 -9.728 31.232 -12.8A132.8 132.8 0 0 1 256 330.944a133.92 133.92 0 0 1 93.696 37.312c11.776 11.776 20.992 25.6 27.648 41.44 3.584 9.216 6.144 18.944 7.68 29.152A224.96 224.96 0 0 1 256 479.776zm-78.336 -236.8a79.68 79.68 0 0 1 -6.656 -32.768c0 -11.232 2.048 -22.496 6.656 -32.736 4.608 -10.24 10.752 -19.424 18.432 -27.104 7.68 -7.68 16.896 -13.792 27.136 -18.4 10.24 -4.608 21.504 -6.656 32.768 -6.656 11.776 0 22.528 2.048 32.768 6.656 10.24 4.608 19.456 10.752 27.136 18.4 7.68 7.68 13.824 16.896 18.432 27.104 4.608 10.24 6.656 21.504 6.656 32.736 0 11.776 -2.048 22.528 -6.656 32.736a90.88 90.88 0 0 1 -18.432 27.136 90.88 90.88 0 0 1 -27.136 18.4 86.88 86.88 0 0 1 -66.048 0 90.88 90.88 0 0 1 -27.136 -18.4 80.832 80.832 0 0 1 -17.92 -27.136zm237.568 169.792c0 -1.024 -0.512 -1.536 -0.512 -2.56a167.04 167.04 0 0 0 -22.016 -44.992 156.256 156.256 0 0 0 -34.816 -36.32 166.624 166.624 0 0 0 -33.28 -19.456 90.24 90.24 0 0 0 14.848 -12.256 134.4 134.4 0 0 0 19.968 -25.088 115.968 115.968 0 0 0 16.896 -61.888 118.72 118.72 0 0 0 -9.216 -47.04 121.568 121.568 0 0 0 -26.112 -38.368 123.04 123.04 0 0 0 -38.4 -25.6 119.04 119.04 0 0 0 -47.104 -9.184 119.04 119.04 0 0 0 -47.104 9.216 116.192 116.192 0 0 0 -38.4 26.08 122.88 122.88 0 0 0 -25.6 38.368 118.72 118.72 0 0 0 -9.216 47.04c0 11.264 1.536 22.016 4.608 32.224 3.072 10.752 7.168 20.48 12.8 29.664 5.12 9.216 12.288 17.408 19.968 25.088 4.608 4.608 9.728 8.672 15.36 12.256a163.84 163.84 0 0 0 -33.28 19.968c-13.312 10.24 -25.088 22.496 -34.816 35.808a159.968 159.968 0 0 0 -22.016 44.992c-0.512 1.024 -0.512 2.048 -0.512 2.56C56.832 372.352 31.744 317.12 31.744 255.744 31.744 132.48 132.608 31.712 256 31.712s224.256 100.768 224.256 224.032a222.72 222.72 0 0 1 -65.024 157.024z\"]\n};\nvar vsActivateBreakpoints = {\n prefix: \"vs\",\n iconName: \"activate-breakpoints\",\n icon: [512, 512, [], \"f000\", \"M480 176a140.608 140.608 0 0 1 -128 144 94.56 94.56 0 0 0 -6.4 -32A114.08 114.08 0 0 0 448 176a112.224 112.224 0 0 0 -224 -9.6A113.664 113.664 0 0 0 192 160a147.904 147.904 0 0 1 144 -128A143.392 143.392 0 0 1 480 176zM176 192a144 144 0 1 0 0 288.032 144 144 0 0 0 0 -288z\"]\n};\nvar vsAdd = {\n prefix: \"vs\",\n iconName: \"add\",\n icon: [512, 512, [], \"f000\", \"M448 224v32H256v192H224V256H32V224h192V32h32v192h192z\"]\n};\nvar vsArchive = {\n prefix: \"vs\",\n iconName: \"archive\",\n icon: [512, 512, [], \"f000\", \"M464 32h-416l-16 16v96l16 16H64v272l16 16h352l16 -16V160h16l16 -16v-96l-16 -16zm-32 96H64V64h384v64h-16zM96 416V160h320v256H96zm256 -192H160v32h192V224z\"]\n};\nvar vsArrowBoth = {\n prefix: \"vs\",\n iconName: \"arrow-both\",\n icon: [512, 512, [], \"f000\", \"M96 288l68.672 68.672 -22.624 22.656 -96 -96v-22.656l96 -96 22.624 22.656L96 256h320l-68.672 -68.672 22.624 -22.656 96 96v22.656l-96 96 -22.624 -22.624L416 288H96z\"]\n};\nvar vsArrowDown = {\n prefix: \"vs\",\n iconName: \"arrow-down\",\n icon: [512, 512, [], \"f000\", \"M100.704 288l160 160h22.624l160 -160 -22.624 -22.624L288 398.048V64H256v334.08L123.328 265.344 100.704 288z\"]\n};\nvar vsArrowLeft = {\n prefix: \"vs\",\n iconName: \"arrow-left\",\n icon: [512, 512, [], \"f000\", \"M224 98.976l-160 160V281.6l160 160 22.624 -22.624 -132.672 -132.704H448v-32H113.92L246.656 121.6 224 98.976z\"]\n};\nvar vsArrowRight = {\n prefix: \"vs\",\n iconName: \"arrow-right\",\n icon: [512, 512, [], \"f000\", \"M288 444.384l160 -160V261.76l-160 -160 -22.624 22.624 132.672 132.704H64v32h334.08L265.344 421.76l22.624 22.624z\"]\n};\nvar vsArrowSmallDown = {\n prefix: \"vs\",\n iconName: \"arrow-small-down\",\n icon: [512, 512, [], \"f000\", \"M342.4 276.48l-80 80h-22.4L160 276.48l22.4 -22.72 52.8 52.48V128h32v178.24L320 253.44l22.4 23.04z\"]\n};\nvar vsArrowSmallLeft = {\n prefix: \"vs\",\n iconName: \"arrow-small-left\",\n icon: [512, 512, [], \"f000\", \"M208 342.4L128 262.4v-22.4L208 160l22.72 22.4 -52.48 52.8h178.24v32H178.24L231.04 320l-23.04 22.4z\"]\n};\nvar vsArrowSmallRight = {\n prefix: \"vs\",\n iconName: \"arrow-small-right\",\n icon: [512, 512, [], \"f000\", \"M276.48 160l80 80v22.4l-80 80 -22.72 -22.4 52.48 -52.8H128v-32h178.24L253.44 182.4l23.04 -22.4z\"]\n};\nvar vsArrowSmallUp = {\n prefix: \"vs\",\n iconName: \"arrow-small-up\",\n icon: [512, 512, [], \"f000\", \"M160 208L240 128h22.4l80 80 -22.4 22.72 -52.8 -52.48v178.24h-32V178.24L182.4 231.04 160 208z\"]\n};\nvar vsArrowSwap = {\n prefix: \"vs\",\n iconName: \"arrow-swap\",\n icon: [512, 512, [], \"f000\", \"M134.624 481.952L32 379.328v-22.624L134.624 254.08l22.624 22.624 -75.296 75.328H480v32H81.92l75.328 75.296 -22.624 22.624zm242.752 -224L480 155.328v-22.624L377.376 30.08l-22.624 22.624L430.048 128H32v32h398.08l-75.328 75.328 22.624 22.624z\"]\n};\nvar vsArrowUp = {\n prefix: \"vs\",\n iconName: \"arrow-up\",\n icon: [512, 512, [], \"f000\", \"M443.328 224l-160 -160h-22.624l-160 160 22.624 22.624L256 113.952V448h32V113.92l132.672 132.704 22.656 -22.624z\"]\n};\nvar vsAzure = {\n prefix: \"vs\",\n iconName: \"azure\",\n icon: [512, 512, [], \"f000\", \"M491.84 437.76l-128 -384a32 32 0 0 0 -32 -21.76H180.16a32 32 0 0 0 -30.4 21.76l-129.6 384a32 32 0 0 0 32 42.24h93.76a32 32 0 0 0 30.08 -21.76l19.52 -56.96 96 72.64a32 32 0 0 0 19.2 6.08h149.76a32 32 0 0 0 31.36 -42.24zm-179.84 21.12a10.24 10.24 0 0 1 -6.4 -2.24L124.8 322.56l-2.88 -2.24h96l2.56 -6.72 32 -80.96 71.68 212.16a10.88 10.88 0 0 1 -12.16 14.08zm149.44 0H342.4a32 32 0 0 0 0 -21.12l-129.6 -384h119.04a10.88 10.88 0 0 1 10.24 7.36l129.6 384a10.88 10.88 0 0 1 -10.24 13.76z\"]\n};\nvar vsBeakerStop = {\n prefix: \"vs\",\n iconName: \"beaker-stop\",\n icon: [512, 512, [], \"f000\", \"M96 480.192h160.224a160.96 160.96 0 0 1 -31.936 -31.776L96 448.544l49.344 -96.352H192V352c0 -10.88 1.088 -21.536 3.168 -31.808h-33.6l59.008 -115.136L224 198.176V65.152l64 -0.768v135.584l2.24 4.384c9.92 -4.16 20.352 -7.36 31.168 -9.44L320 192.192v-128h32v-32H319.808V32l-14.592 0.16H160V64h32v126.464l-124.608 243.488A32 32 0 0 0 96 480.192zm184.896 -234.624a128 128 0 1 1 142.208 212.864 128 128 0 0 1 -142.208 -212.864zm3.2 174.304A96 96 0 0 0 352 448a96 96 0 0 0 55.68 -17.6L273.6 296.32A96 96 0 0 0 256 352a96 96 0 0 0 28.128 67.872zm12.224 -146.24l134.08 134.048A96 96 0 0 0 448 352a96 96 0 0 0 -96 -96 96 96 0 0 0 -55.68 17.6z\"]\n};\nvar vsBeaker = {\n prefix: \"vs\",\n iconName: \"beaker\",\n icon: [512, 512, [], \"f000\", \"M444.576 433.856L320 192.192v-128h32v-32H319.808V32l-14.592 0.16H160V64h32v126.464l-124.608 243.488A32 32 0 0 0 96 480.192h320a32 32 0 0 0 28.576 -46.336zm-224 -228.8L224 198.176V65.152l64 -0.768v135.584l3.52 6.88 58.464 113.344H161.568l59.008 -115.136zM96 448.544l49.28 -96.352h221.312l49.504 96L96 448.544z\"]\n};\nvar vsBellDot = {\n prefix: \"vs\",\n iconName: \"bell-dot\",\n icon: [512, 512, [], \"f000\", \"M416 284.8c3.2 19.2 6.4 35.2 12.8 54.4l19.2 54.4 -16 22.4H320c0 16 -6.4 32 -19.2 44.8 -12.8 12.8 -28.8 19.2 -44.8 19.2 -16 0 -35.2 -6.4 -44.8 -19.2 -12.8 -12.8 -19.2 -28.8 -19.2 -44.8H80l-16 -22.4 19.2 -54.4c6.4 -25.6 12.8 -51.2 12.8 -76.8V192c0 -22.4 3.2 -44.8 12.8 -64 9.6 -22.4 22.4 -38.4 38.4 -54.4s35.2 -25.6 57.6 -32C220.8 35.2 240 32 256 32c-6.4 9.6 -12.8 22.4 -19.2 35.2 -6.4 0 -12.8 0 -22.4 6.4 -16 3.2 -32 12.8 -44.8 25.6 -12.8 9.6 -25.6 25.6 -32 41.6 -6.4 16 -9.6 32 -9.6 51.2v70.4c0 28.8 -6.4 57.6 -12.8 86.4L102.4 384h307.2l-12.8 -35.2c-5.6 -16.832 -8.768 -36.16 -11.616 -53.568L384 288c12.8 0 22.4 0 32 -3.2zM256 448c6.4 0 16 -3.2 22.4 -9.6 6.4 -6.4 9.6 -12.8 9.6 -22.4H224c0 9.6 3.2 16 9.6 22.4 6.4 6.4 16 9.6 22.4 9.6zm224 -320a96 96 0 1 1 -192 0 96 96 0 0 1 192 0z\"]\n};\nvar vsBell = {\n prefix: \"vs\",\n iconName: \"bell\",\n icon: [512, 512, [], \"f000\", \"M428.064 338.336a244.16 244.16 0 0 1 -12.256 -76.16V198.24a163.68 163.68 0 0 0 -40.576 -110.272 164.416 164.416 0 0 0 -103.744 -55.104c-22.208 -2.304 -44.8 0 -66.24 7.264 -21.44 6.88 -40.96 18.368 -57.408 33.696a157.536 157.536 0 0 0 -38.656 53.6 162.144 162.144 0 0 0 -13.792 64.704v70.4a243.52 243.52 0 0 1 -12.256 75.84L64 394.976l15.328 21.056h112.16c0 16.832 6.88 33.28 18.752 45.184 11.84 11.84 28.32 18.752 45.184 18.752 16.832 0 33.28 -6.88 45.152 -18.752s18.784 -28.352 18.784 -45.184h112.16l15.296 -21.056 -18.752 -56.64zm-150.08 100.704a31.904 31.904 0 0 1 -22.56 9.568 31.904 31.904 0 0 1 -22.592 -9.6 31.904 31.904 0 0 1 -9.6 -22.56h63.968a30.048 30.048 0 0 1 -9.184 22.592zm-176.48 -54.72l11.872 -35.648a276.256 276.256 0 0 0 14.176 -86.112V192.128c0 -18.016 3.84 -35.616 11.104 -51.712 7.264 -16.448 17.6 -31.008 31.008 -42.88 13.408 -12.224 29.12 -21.44 45.952 -26.784 17.216 -5.76 35.2 -7.68 52.8 -5.76a132.704 132.704 0 0 1 83.104 44.8 132.256 132.256 0 0 1 32.128 88.832v64.32c0 29.088 4.608 58.176 14.176 86.112l11.872 35.616h-308.16v-0.384z\"]\n};\nvar vsBold = {\n prefix: \"vs\",\n iconName: \"bold\",\n icon: [512, 512, [], \"f000\", \"M160 416V96h107.584c35.712 0 62.528 7.168 80.48 21.536 18.08 14.368 27.136 35.616 27.136 63.744 0 14.944 -4.384 28.192 -13.12 39.776 -8.736 11.424 -20.64 20.288 -35.712 26.592 17.792 4.832 31.776 14.08 42.048 27.68 10.4 13.504 15.584 29.6 15.584 48.352 0 28.736 -9.568 51.296 -28.704 67.712 -19.136 16.416 -46.176 24.608 -81.152 24.608H160zm43.392 -149.664v115.168h71.68c20.16 0 36.064 -5.056 47.68 -15.168 11.744 -10.24 17.6 -24.32 17.6 -42.208 0 -38.528 -21.536 -57.792 -64.64 -57.792h-72.32zm0 -33.856h65.568c18.976 0 34.112 -4.608 45.44 -13.856 11.424 -9.216 17.152 -21.76 17.152 -37.568 0 -17.6 -5.28 -30.336 -15.808 -38.24 -10.56 -8.064 -26.592 -12.096 -48.16 -12.096H203.392v101.76z\"]\n};\nvar vsBook = {\n prefix: \"vs\",\n iconName: \"book\",\n icon: [512, 512, [], \"f000\", \"M464 64H288l-11.2 4.8 -20.8 20.48 -20.8 -20.48L224 64H48l-16 16v320l16 16h169.28l27.52 27.2h22.4l27.52 -27.2h169.28l16 -16v-320l-16 -16zm-224 330.24l-5.76 -5.44L224 384H64V96h153.28l23.68 23.68 -0.96 274.56zM448 384H288l-11.2 4.8 -4.48 4.16V118.4l22.4 -22.4H448v288zM192 160H96v32h96V160zm0 128H96v32h96V288zM96 224h96v32H96V224zm320 -64h-96v32h96V160zm-96 64h96v32h-96V224zm0 64h96v32h-96V288z\"]\n};\nvar vsBookmark = {\n prefix: \"vs\",\n iconName: \"bookmark\",\n icon: [512, 512, [], \"f000\", \"M400 32h-288l-16 16v416l27.904 10.72L256 327.904l132.096 146.816L416 464v-416l-16 -16zM384 422.4L267.904 293.28h-23.808L128 422.4V64h256v358.4z\"]\n};\nvar vsBracketDot = {\n prefix: \"vs\",\n iconName: \"bracket-dot\",\n icon: [512, 512, [], \"f000\", \"M192 95.104v0.384h-2.88c-6.368 0 -12.352 1.28 -17.984 3.872a46.976 46.976 0 0 0 -14.624 10.24 47.04 47.04 0 0 0 -13.44 33.12c0 7.264 0.128 14.496 0.384 21.664 0.256 7.168 0.256 14.272 0 21.28a152.032 152.032 0 0 1 -1.76 20.48c-1.056 6.72 -2.848 13.12 -5.376 19.296A73.088 73.088 0 0 1 112.704 256a73.088 73.088 0 0 1 23.616 30.56c2.56 6.176 4.32 12.64 5.376 19.456 1.056 6.592 1.632 13.44 1.76 20.48 0.256 6.912 0.256 14.016 0 21.312 -0.256 7.04 -0.384 14.208 -0.384 21.504 0 6.496 1.184 12.608 3.552 18.336 2.528 5.664 5.824 10.656 9.888 14.976 4.16 4.16 9.056 7.584 14.624 10.208 5.6 2.464 11.616 3.68 18.016 3.68H192V448h-2.88c-10.016 0 -19.712 -1.984 -29.088 -5.92a74.56 74.56 0 0 1 -24.8 -16.96 71.36 71.36 0 0 1 -15.776 -24.096v-0.032a113.28 113.28 0 0 1 -6.336 -26.368v-0.064a197.952 197.952 0 0 1 -0.768 -27.84c0.384 -9.248 0.576 -18.496 0.576 -27.776 0 -6.336 -1.28 -12.384 -3.744 -18.112V300.8a45.248 45.248 0 0 0 -9.856 -14.88l-0.064 -0.064a44.064 44.064 0 0 0 -14.56 -10.176h-0.032a42.112 42.112 0 0 0 -17.824 -3.904H64v-31.488h2.88c6.24 0 12.16 -1.216 17.824 -3.68a48.128 48.128 0 0 0 24.48 -25.152v-0.064c2.496 -5.76 3.744 -11.84 3.744 -18.304 0 -9.28 -0.192 -18.56 -0.576 -27.808a194.56 194.56 0 0 1 0.768 -27.616V137.6c1.056 -9.184 3.168 -18.048 6.304 -26.56v-0.032a71.36 71.36 0 0 1 15.808 -24.096A74.56 74.56 0 0 1 160 69.92c9.376 -3.936 19.072 -5.92 29.12 -5.92H192v31.104zm253.536 176.64H448v-31.488h-2.88c-6.24 0 -12.16 -1.28 -17.792 -3.872l-0.032 -0.032a44.032 44.032 0 0 1 -14.56 -10.176l-0.064 -0.064a45.248 45.248 0 0 1 -9.824 -14.88l-0.032 -0.064a44.96 44.96 0 0 1 -3.744 -18.112c0 -9.28 0.192 -18.56 0.576 -27.808a198.08 198.08 0 0 0 -0.768 -27.84v-0.032a113.344 113.344 0 0 0 -6.304 -26.368v-0.032a71.36 71.36 0 0 0 -15.808 -24.096 74.56 74.56 0 0 0 -24.8 -16.96 74.4 74.4 0 0 0 -29.12 -5.92H320v31.488h2.88c6.4 0 12.352 1.216 17.984 3.68 5.568 2.624 10.432 6.016 14.624 10.24 4.064 4.288 7.36 9.28 9.888 14.944 2.368 5.76 3.52 11.84 3.52 18.336 0 7.296 -0.096 14.464 -0.352 21.504 -0.256 7.296 -0.256 14.4 0 21.28 0.128 7.104 0.704 13.92 1.76 20.48 1.056 6.848 2.848 13.312 5.376 19.488a73.024 73.024 0 0 0 23.616 30.56l-1.024 0.8c16.96 1.856 32.96 7.072 47.264 14.944zM384 288a96 96 0 1 0 0 192 96 96 0 0 0 0 -192z\"]\n};\nvar vsBracketError = {\n prefix: \"vs\",\n iconName: \"bracket-error\",\n icon: [512, 512, [], \"f000\", \"M192 95.104v0.384h-2.88c-6.368 0 -12.352 1.28 -17.984 3.872a46.976 46.976 0 0 0 -14.624 10.24 47.04 47.04 0 0 0 -13.44 33.12c0 7.264 0.128 14.496 0.384 21.664 0.256 7.168 0.256 14.272 0 21.28a152.032 152.032 0 0 1 -1.76 20.48c-1.056 6.72 -2.848 13.12 -5.376 19.296A73.088 73.088 0 0 1 112.704 256a73.088 73.088 0 0 1 23.616 30.56c2.56 6.176 4.32 12.64 5.376 19.456 1.056 6.592 1.632 13.44 1.76 20.48 0.256 6.912 0.256 14.016 0 21.312 -0.256 7.04 -0.384 14.208 -0.384 21.504 0 6.496 1.184 12.608 3.552 18.336 2.528 5.664 5.824 10.656 9.888 14.976 4.16 4.16 9.056 7.584 14.624 10.208 5.6 2.464 11.616 3.68 18.016 3.68H192V448h-2.88c-10.016 0 -19.712 -1.984 -29.088 -5.92a74.56 74.56 0 0 1 -24.8 -16.96 71.36 71.36 0 0 1 -15.776 -24.096v-0.032a113.28 113.28 0 0 1 -6.336 -26.368v-0.064a197.952 197.952 0 0 1 -0.768 -27.84c0.384 -9.248 0.576 -18.496 0.576 -27.776 0 -6.336 -1.28 -12.384 -3.744 -18.112V300.8a45.248 45.248 0 0 0 -9.856 -14.88l-0.064 -0.064a44.064 44.064 0 0 0 -14.56 -10.176h-0.032a42.112 42.112 0 0 0 -17.824 -3.904H64v-31.488h2.88c6.24 0 12.16 -1.216 17.824 -3.68a48.128 48.128 0 0 0 24.48 -25.152v-0.064c2.496 -5.76 3.744 -11.84 3.744 -18.304 0 -9.28 -0.192 -18.56 -0.576 -27.808a194.56 194.56 0 0 1 0.768 -27.616V137.6c1.056 -9.184 3.168 -18.048 6.304 -26.56v-0.032a71.36 71.36 0 0 1 15.808 -24.096A74.56 74.56 0 0 1 160 69.92c9.376 -3.936 19.072 -5.92 29.12 -5.92H192v31.104zm253.536 176.64H448v-31.488h-2.88c-6.24 0 -12.16 -1.28 -17.792 -3.872l-0.032 -0.032a44.032 44.032 0 0 1 -14.56 -10.176l-0.064 -0.064a45.248 45.248 0 0 1 -9.824 -14.88l-0.032 -0.064a44.96 44.96 0 0 1 -3.744 -18.112c0 -9.28 0.192 -18.56 0.576 -27.808a198.08 198.08 0 0 0 -0.768 -27.84v-0.032a113.344 113.344 0 0 0 -6.304 -26.368v-0.032a71.36 71.36 0 0 0 -15.808 -24.096 74.56 74.56 0 0 0 -24.8 -16.96 74.4 74.4 0 0 0 -29.12 -5.92H320v31.488h2.88c6.4 0 12.352 1.216 17.984 3.68 5.568 2.624 10.432 6.016 14.624 10.24 4.064 4.288 7.36 9.28 9.888 14.944 2.368 5.76 3.52 11.84 3.52 18.336 0 7.296 -0.096 14.464 -0.352 21.504 -0.256 7.296 -0.256 14.4 0 21.28 0.128 7.104 0.704 13.92 1.76 20.48 1.056 6.848 2.848 13.312 5.376 19.488a73.024 73.024 0 0 0 23.616 30.56l-1.024 0.8c16.96 1.856 32.96 7.072 47.264 14.944zm-114.88 32.448a96 96 0 1 1 106.688 159.616 96 96 0 0 1 -106.688 -159.616zm90.016 20.48L384 361.376l-36.672 -36.704 -22.624 22.624L361.376 384l-36.704 36.672 22.656 22.656L384 406.624l36.672 36.672 22.656 -22.624L406.624 384l36.704 -36.672 -22.656 -22.656z\"]\n};\nvar vsBriefcase = {\n prefix: \"vs\",\n iconName: \"briefcase\",\n icon: [512, 512, [], \"f000\", \"M464 128H352V80l-16 -16h-160l-16 16V128H48l-16 16v256l16 16h416l16 -16v-256l-16 -16zM192 96h128v32H192V96zm256 64v24.32L320 256v-16L304.32 224h-96L192 240V256L64 182.72V160h384zM288 256v32H224V256h64zm-224 128V219.52l128 73.28v11.2l16 16h96l16 -16v-9.92l128 -72.96V384H64z\"]\n};\nvar vsBroadcast = {\n prefix: \"vs\",\n iconName: \"broadcast\",\n icon: [512, 512, [], \"f000\", \"M149.344 64.352A192 192 0 0 1 256 32a192.224 192.224 0 0 1 192 192 192 192 0 0 1 -127.872 180.96v-1.408c0.512 -0.448 0.992 -0.96 1.472 -1.44a47.36 47.36 0 0 0 13.888 -33.472v-4.384A161.344 161.344 0 0 0 390.08 134.4a161.28 161.28 0 1 0 -214.08 229.632v4.608a47.36 47.36 0 0 0 15.36 34.88v1.28A191.968 191.968 0 0 1 149.344 64.32zm149.632 315.168a15.36 15.36 0 0 1 -10.88 4.48v80.64a15.36 15.36 0 0 1 -15.36 15.36H238.72c0.352 0 -0.128 -0.128 -1.088 -0.384 -2.4 -0.64 -7.712 -2.048 -9.76 -4.128a15.36 15.36 0 0 1 -4.512 -10.88V384a15.36 15.36 0 0 1 -15.36 -15.36V304a32 32 0 0 1 32 -32h31.488a32 32 0 0 1 32 32v64.64a15.36 15.36 0 0 1 -4.384 10.72l-0.128 0.128zM340.48 224c0 16.8 -5.024 33.088 -14.24 46.88 5.856 9.664 9.248 20.992 9.248 33.12v3.392a115.072 115.072 0 0 0 1.92 -164.8A115.2 115.2 0 1 0 176 306.88V304c0 -12.288 3.456 -23.776 9.472 -33.504A84.48 84.48 0 1 1 340.48 224zM288 224a32 32 0 1 1 -64 0 32 32 0 0 1 64 0z\"]\n};\nvar vsBrowser = {\n prefix: \"vs\",\n iconName: \"browser\",\n icon: [512, 512, [], \"f000\", \"M48 32h416l16 16v384l-16 16h-416l-16 -16v-384l16 -16zM64 160v256h384V160H64zm0 -32h384V64H64v64z\"]\n};\nvar vsBug = {\n prefix: \"vs\",\n iconName: \"bug\",\n icon: [512, 512, [], \"f000\", \"M348.064 144v-18.624a93.376 93.376 0 1 0 -186.752 0V144h-26.656L81.44 90.528l-18.976 18.88 51.552 51.808 -0.608 1.568a256.96 256.96 0 0 0 -16.096 90.592c0 6.272 0.224 12.48 0.64 18.56l0.096 1.44H32v26.752h69.408l0.192 1.088c5.504 30.112 16.128 57.664 30.528 80.992l1.088 1.76L70.4 446.784l18.944 18.944 59.872 -59.904 1.856 2.112c27.776 31.744 64.064 50.848 103.616 50.848 38.976 0 74.752 -18.528 102.368 -49.408l1.824 -2.048 61.12 61.44 18.976 -18.912 -63.872 -64.192 1.12 -1.792c14.944 -23.68 25.92 -51.808 31.552 -82.656l0.192 -1.088h69.472v-26.752h-66.08l0.096 -1.408a269.76 269.76 0 0 0 0.64 -18.56 256.64 256.64 0 0 0 -16.544 -91.712l-0.608 -1.6 50.24 -50.24 -18.944 -18.88L373.184 144h-25.12zm-160 0v-18.624a66.624 66.624 0 1 1 133.248 0V144H188.096zm182.304 26.784l0.64 1.696c9.056 24.096 14.304 51.52 14.304 80.896 0 51.52 -16.096 97.088 -40.768 129.184 -24.64 32.032 -56.672 49.44 -89.856 49.44 -33.152 0 -65.184 -17.408 -89.824 -49.44 -24.704 -32.096 -40.8 -77.664 -40.8 -129.184 0 -29.376 5.248 -56.8 14.336 -80.896l0.64 -1.696h231.328z\"]\n};\nvar vsCalendar = {\n prefix: \"vs\",\n iconName: \"calendar\",\n icon: [512, 512, [], \"f000\", \"M464 64H416V32h-32v32H128V32H96v32H48l-16 16v384l16 16h416l16 -16v-384l-16 -16zM448 448H64V160h384v288zm0 -320H64V96h384v32zM128 256H96v32h32V256zm-32 64h32v32H96v-32zm32 64H96v32h32v-32zm64 -128h32v32H192V256zm32 64H192v32h32v-32zm-32 64h32v32H192v-32zm32 -192H192v32h32V192zm64 64h32v32H288V256zm32 64H288v32h32v-32zm-32 64h32v32H288v-32zm32 -192H288v32h32V192zm64 64h32v32h-32V256zm32 64h-32v32h32v-32zm-32 -128h32v32h-32V192z\"]\n};\nvar vsCallIncoming = {\n prefix: \"vs\",\n iconName: \"call-incoming\",\n icon: [512, 512, [], \"f000\", \"M401.504 298.496a50.144 50.144 0 0 0 -19.008 -3.744 38.464 38.464 0 0 0 -17.76 3.232 88.384 88.384 0 0 0 -13.76 8.256 69.312 69.312 0 0 0 -11.488 10.496c-3.328 3.84 -6.56 7.36 -9.728 10.528a77.088 77.088 0 0 1 -9.28 8 17.088 17.088 0 0 1 -22.24 -2.016 1029.44 1029.44 0 0 1 -10.496 -9.984c-4.48 -4.352 -9.984 -9.6 -16.48 -15.776A1976.832 1976.832 0 0 1 251.008 288l-21.76 -21.248a827.104 827.104 0 0 1 -38.72 -40.512 169.984 169.984 0 0 1 -12.512 -15.488c-3.008 -4.32 -4.512 -7.488 -4.512 -9.504a14.72 14.72 0 0 1 3.232 -9.984c2.336 -3.008 5.12 -6.08 8.256 -9.28 3.2 -3.136 6.688 -6.496 10.496 -9.984 3.84 -3.52 7.36 -7.264 10.528 -11.264 3.136 -4 5.824 -8.576 8 -13.76 2.144 -5.12 3.232 -10.976 3.232 -17.472a50.144 50.144 0 0 0 -14.496 -35.264 243.328 243.328 0 0 1 -16.992 -18.496 207.584 207.584 0 0 0 -19.744 -20.48 134.624 134.624 0 0 0 -22.272 -16.512A46.72 46.72 0 0 0 119.744 32a50.144 50.144 0 0 0 -35.232 14.496c-8.672 8.672 -16.256 16.416 -22.752 23.264a128.192 128.192 0 0 0 -16.512 21.248 84.16 84.16 0 0 0 -9.984 24.48A140.48 140.48 0 0 0 32 148c0 17.664 2.848 36 8.512 55.008 5.664 18.976 13.312 37.92 22.976 56.736 9.664 18.848 21.44 37.344 35.264 55.52 13.824 18.144 28.832 35.392 44.992 51.744 16.16 16.32 33.344 31.424 51.52 45.248 18.144 13.824 36.736 25.76 55.744 35.744 18.976 10.016 38.08 17.824 57.248 23.488a197.024 197.024 0 0 0 56 8.512 150.272 150.272 0 0 0 32.256 -3.52 82.88 82.88 0 0 0 24.736 -9.984c7.36 -4.48 14.4 -9.984 21.248 -16.48 6.848 -6.528 14.496 -14.016 23.008 -22.528A50.176 50.176 0 0 0 480 392.224a64.288 64.288 0 0 0 -3.264 -16.48 53.568 53.568 0 0 0 -8.224 -15.488 231.68 231.68 0 0 0 -11.776 -14.24 172.192 172.192 0 0 0 -13.472 -13.504 2929.568 2929.568 0 0 0 -13.76 -12.256 264.864 264.864 0 0 1 -11.744 -11.008 48.512 48.512 0 0 0 -16.256 -10.752zm-11.744 146.752a100.16 100.16 0 0 1 -25.504 2.752 176.832 176.832 0 0 1 -48.512 -7.744 267.584 267.584 0 0 1 -50.752 -21.248 422.56 422.56 0 0 1 -97.504 -73.504 548.8 548.8 0 0 1 -41.248 -46.752 336.064 336.064 0 0 1 -32.96 -50.496 291.84 291.84 0 0 1 -21.536 -51.52A169.856 169.856 0 0 1 64 147.264a106.88 106.88 0 0 1 3.008 -25.28c1.824 -6.976 4.576 -13.248 8.256 -18.72 3.648 -5.504 8.16 -10.848 13.472 -16 5.344 -5.184 11.424 -11.2 18.24 -18.016a17.344 17.344 0 0 1 12.8 -5.248c1.984 -0.16 5.056 1.152 9.216 4 4.16 2.848 8.672 6.24 13.504 10.24a225.856 225.856 0 0 1 28.768 28.768c4 4.8 7.328 9.248 9.984 13.248 2.656 4 4 7.072 4 9.248a13.728 13.728 0 0 1 -3.232 9.984c-2.336 2.688 -5.12 5.76 -8.256 9.28 -3.2 3.488 -6.688 6.816 -10.496 9.984 -3.84 3.168 -7.36 6.912 -10.528 11.232a72.512 72.512 0 0 0 -8 14.016 43.04 43.04 0 0 0 -3.232 17.28c0.16 6.816 1.504 13.216 4 19.2 2.496 6.016 6.08 11.36 10.752 16l119.232 119.264a48.864 48.864 0 0 0 35.264 14.72 38.4 38.4 0 0 0 17.504 -3.2 77.248 77.248 0 0 0 25.248 -18.752c3.52 -3.84 6.72 -7.36 9.76 -10.528 2.976 -3.136 6.08 -5.824 9.248 -8a17.44 17.44 0 0 1 9.984 -3.232c2.336 0 5.504 1.344 9.504 4 4 2.656 8.416 6.08 13.248 10.24 4.832 4.16 9.824 8.768 15.008 13.76 5.152 4.992 9.76 9.984 13.76 15.008 3.968 4.992 7.328 9.504 9.984 13.504 2.656 4 4 7.04 4 9.248a17.056 17.056 0 0 1 -5.248 12.48c-7.168 7.008 -13.248 13.12 -18.24 18.24a101.088 101.088 0 0 1 -16 13.504 61.76 61.76 0 0 1 -18.752 8.512zM480 54.528l-148.48 148.736h105.216v32h-160v-160h32V180.48L457.504 32l22.496 22.496z\"]\n};\nvar vsCallOutgoing = {\n prefix: \"vs\",\n iconName: \"call-outgoing\",\n icon: [512, 512, [], \"f000\", \"M276.736 212.736L425.28 64H320V32h160v160h-32V86.72L299.264 235.296l-22.528 -22.528zm105.76 82.016a50.144 50.144 0 0 1 35.264 14.496c3.52 3.52 7.424 7.168 11.744 11.008l13.76 12.256c4.8 4.32 9.312 8.832 13.472 13.472 4.16 4.672 8.096 9.44 11.776 14.272 3.648 4.8 6.4 9.984 8.224 15.488 1.856 5.504 2.944 11.008 3.264 16.512a50.176 50.176 0 0 1 -14.496 35.232c-8.512 8.512 -16.16 16 -23.008 22.528a128.192 128.192 0 0 1 -21.248 16.48c-7.36 4.48 -15.584 7.84 -24.736 10.016a150.272 150.272 0 0 1 -32.256 3.488 197.024 197.024 0 0 1 -56 -8.512A314.208 314.208 0 0 1 250.976 448a398.24 398.24 0 0 1 -55.712 -35.744 490.528 490.528 0 0 1 -51.52 -45.248c-16.16 -16.32 -31.168 -33.6 -44.992 -51.744a372.48 372.48 0 0 1 -35.264 -55.52 332.16 332.16 0 0 1 -22.976 -56.736A192.16 192.16 0 0 1 32 148c0 -12.672 1.088 -23.488 3.264 -32.512a84.16 84.16 0 0 1 9.984 -24.48c4.48 -7.36 10.016 -14.4 16.512 -21.248 6.496 -6.848 14.08 -14.592 22.72 -23.264A50.144 50.144 0 0 1 119.776 32c8.32 0 16.32 2.24 24 6.72 7.68 4.544 15.104 10.016 22.272 16.544 7.136 6.496 13.76 13.312 19.744 20.48 5.984 7.168 11.648 13.344 16.96 18.496a50.144 50.144 0 0 1 14.496 35.264 44.8 44.8 0 0 1 -3.2 17.504 58.368 58.368 0 0 1 -8 13.76 95.456 95.456 0 0 1 -10.528 11.232c-3.84 3.52 -7.328 6.848 -10.496 10.016a100.096 100.096 0 0 0 -8.256 9.248 14.72 14.72 0 0 0 -3.232 9.984c0 2.016 1.504 5.184 4.48 9.504a169.6 169.6 0 0 0 12.512 15.488 780.352 780.352 0 0 0 38.752 40.512c7.488 7.36 14.752 14.4 21.76 21.248 6.976 6.848 13.76 13.344 20.256 19.52 6.496 6.144 12 11.392 16.48 15.744 4.48 4.32 8 7.68 10.496 9.984a17.088 17.088 0 0 0 22.272 2.016c2.976 -2.176 6.08 -4.864 9.248 -8 3.168 -3.2 6.4 -6.688 9.728 -10.528 3.328 -3.84 7.168 -7.328 11.52 -10.496 4.32 -3.168 8.896 -5.92 13.76 -8.256a38.72 38.72 0 0 1 17.728 -3.232zM364.256 448c10.176 0 18.656 -0.928 25.504 -2.752a61.76 61.76 0 0 0 18.752 -8.512c5.664 -3.84 10.976 -8.32 16 -13.472 4.992 -5.184 11.072 -11.264 18.24 -18.24 3.52 -3.52 5.248 -7.68 5.248 -12.512 0 -2.176 -1.344 -5.248 -4 -9.28a195.904 195.904 0 0 0 -10.016 -13.472 160.32 160.32 0 0 0 -13.76 -15.04c-5.12 -4.96 -10.144 -9.568 -14.976 -13.728a138.304 138.304 0 0 0 -13.248 -10.24c-4 -2.656 -7.168 -4 -9.504 -4a17.44 17.44 0 0 0 -9.984 3.232 57.632 57.632 0 0 0 -9.28 8c-2.976 3.2 -6.24 6.688 -9.728 10.528 -3.52 3.84 -7.36 7.328 -11.52 10.496 -4.16 3.168 -8.736 5.92 -13.76 8.256a38.656 38.656 0 0 1 -17.472 3.232 48.864 48.864 0 0 1 -35.264 -14.72L156.256 236.48a49.184 49.184 0 0 1 -10.752 -16 52.96 52.96 0 0 1 -4 -19.264c0 -6.496 1.088 -12.256 3.232 -17.248 2.176 -4.992 4.832 -9.664 8 -14.016 3.2 -4.32 6.688 -8.064 10.528 -11.232 3.84 -3.168 7.328 -6.496 10.496 -10.016 3.168 -3.488 5.92 -6.56 8.256 -9.248a13.728 13.728 0 0 0 3.232 -9.984c0 -2.176 -1.344 -5.248 -4 -9.28a162.72 162.72 0 0 0 -9.984 -13.216 217.312 217.312 0 0 0 -13.76 -15.008 217.184 217.184 0 0 0 -15.008 -13.76 181.568 181.568 0 0 0 -13.504 -10.24c-4.16 -2.848 -7.232 -4.16 -9.248 -4a17.344 17.344 0 0 0 -12.736 5.248 2087.68 2087.68 0 0 1 -18.24 18.016 98.336 98.336 0 0 0 -13.504 16 60.8 60.8 0 0 0 -8.256 18.752A108.064 108.064 0 0 0 64 147.232c0 16 2.56 32.48 7.744 49.472a291.84 291.84 0 0 0 21.504 51.52c9.184 17.312 20.16 34.176 32.992 50.496 12.832 16.32 26.592 31.904 41.28 46.72a422.56 422.56 0 0 0 97.472 73.536 267.84 267.84 0 0 0 50.752 21.248 176.832 176.832 0 0 0 48.512 7.744z\"]\n};\nvar vsCaseSensitive = {\n prefix: \"vs\",\n iconName: \"case-sensitive\",\n icon: [512, 512, [], \"f000\", \"M239.84 289.664l28.512 75.2h34.912L199.584 96h-32.64L64 364.864h35.04l26.816 -75.2h113.984zM185.952 142.496l1.408 4.32 42.176 114.368H136.16l41.824 -114.368 1.408 -4.32 1.216 -4.992 1.024 -4.864 0.672 -4.032h0.736l0.768 4.032 0.928 4.864 1.216 4.992zm255.488 192.352v29.952h30.72V239.936c0 -23.008 -5.76 -40.704 -17.248 -53.152 -11.488 -12.448 -28.448 -18.656 -50.816 -18.656 -6.368 0 -12.832 0.608 -19.392 1.792a156 156 0 0 0 -34.496 10.432 66.592 66.592 0 0 0 -10.976 6.016v31.488c8.512 -7.36 18.112 -13.152 28.928 -17.28a93.664 93.664 0 0 1 33.664 -6.176c6.016 0 11.456 0.896 16.416 2.72a31.36 31.36 0 0 1 12.672 8.544c3.488 3.872 6.176 8.928 8.064 15.104 1.888 6.176 2.816 13.664 2.816 22.4l-57.952 8.064c-11.008 1.504 -20.48 4.032 -28.416 7.584a62.304 62.304 0 0 0 -19.68 13.408 51.2 51.2 0 0 0 -11.52 18.56 68.288 68.288 0 0 0 -3.744 23.072c0 7.872 1.344 15.2 3.968 22.016 2.624 6.816 6.496 12.704 11.616 17.632 5.12 4.928 11.52 8.832 19.136 11.712 7.616 2.88 16.416 4.32 26.432 4.32 12.864 0 24.32 -2.944 34.4 -8.896 10.08 -5.952 18.304 -14.528 24.672 -25.792h0.736zm-68.096 -55.776c5.632 -2.048 12.832 -3.648 21.568 -4.768l46.88 -6.56v19.488c0 7.872 -1.312 15.2 -3.936 22.016a55.264 55.264 0 0 1 -10.976 17.824 50.336 50.336 0 0 1 -16.768 11.904 52.16 52.16 0 0 1 -21.376 4.32c-5.984 0 -11.296 -0.8 -15.84 -2.432a32.96 32.96 0 0 1 -11.424 -6.752 28.672 28.672 0 0 1 -7.04 -10.112A32.16 32.16 0 0 1 352 311.424a51.2 51.2 0 0 1 1.76 -14.08 23.648 23.648 0 0 1 6.464 -10.688 37.12 37.12 0 0 1 13.12 -7.584z\"]\n};\nvar vsCheckAll = {\n prefix: \"vs\",\n iconName: \"check-all\",\n icon: [512, 512, [], \"f000\", \"M499.84 115.072L250.08 409.92l-23.296 -1.056L128 268.224l24.128 -16.96 87.808 125.024L477.344 96l22.496 19.072zM231.488 280.768l140.352 -165.696L349.344 96l-135.36 159.808 17.504 24.96zm-49.6 12.896l17.536 24.96 -17.504 -24.96zm-51.744 61.12l17.504 24.96 -25.568 30.176 -23.296 -1.056L0 268.224l24.128 -16.96 87.808 125.024 18.24 -21.504z\"]\n};\nvar vsCheck = {\n prefix: \"vs\",\n iconName: \"check\",\n icon: [512, 512, [], \"f000\", \"M461.792 106.336l-271.04 320 -25.28 -1.152 -107.2 -152.64 26.176 -18.368 95.296 135.68 257.632 -304.192 24.448 20.672z\"]\n};\nvar vsChecklist = {\n prefix: \"vs\",\n iconName: \"checklist\",\n icon: [512, 512, [], \"f000\", \"M120 143.36h-22.72L64 109.76l22.72 -22.4 22.08 21.76L153.92 64l22.72 22.72 -56.64 56.64zM223.68 96h256v32h-256V96zm0 96h256v32h-256V192zm256 96h-256v32h256V288zm-256 96h256v32h-256v-32zM97.28 239.36h22.72l56.64 -56.64 -22.72 -22.4L108.8 205.44l-22.08 -22.08 -22.72 22.72 33.28 33.28zm22.72 96.32h-22.72L64 302.4l22.72 -22.72 22.08 22.08 45.12 -45.44 22.72 22.72 -56.64 56.64zm-22.72 96.32h22.72l56.64 -56.64 -22.72 -22.72 -45.12 45.44 -22.08 -22.08 -22.72 22.4 33.28 33.6z\"]\n};\nvar vsChevronDown = {\n prefix: \"vs\",\n iconName: \"chevron-down\",\n icon: [512, 512, [], \"f000\", \"M255.232 322.304l139.424 -139.424 19.84 19.776L265.088 352h-19.776L96 202.656l19.808 -19.776 139.424 139.424z\"]\n};\nvar vsChevronLeft = {\n prefix: \"vs\",\n iconName: \"chevron-left\",\n icon: [512, 512, [], \"f000\", \"M189.696 255.232l139.424 139.424 -19.776 19.84L160 265.088v-19.776L309.344 96l19.776 19.808 -139.424 139.424z\"]\n};\nvar vsChevronRight = {\n prefix: \"vs\",\n iconName: \"chevron-right\",\n icon: [512, 512, [], \"f000\", \"M322.304 256.768L182.88 117.344l19.776 -19.84L352 246.912v19.776L202.656 416l-19.776 -19.808 139.424 -139.424z\"]\n};\nvar vsChevronUp = {\n prefix: \"vs\",\n iconName: \"chevron-up\",\n icon: [512, 512, [], \"f000\", \"M256.768 189.696l-139.424 139.424 -19.84 -19.776L246.912 160h19.776L416 309.344l-19.808 19.776 -139.424 -139.424z\"]\n};\nvar vsChromeClose = {\n prefix: \"vs\",\n iconName: \"chrome-close\",\n icon: [512, 512, [], \"f000\", \"M227.712 256l-145.856 145.856 28.288 28.288L256 284.288l145.856 145.856 28.288 -28.288L284.288 256l145.856 -145.856 -28.288 -28.288L256 227.712 110.144 81.856l-28.288 28.288L227.712 256z\"]\n};\nvar vsChromeMaximize = {\n prefix: \"vs\",\n iconName: \"chrome-maximize\",\n icon: [512, 512, [], \"f000\", \"M96 96v320h320V96H96zm288 288H128V128h256v256z\"]\n};\nvar vsChromeMinimize = {\n prefix: \"vs\",\n iconName: \"chrome-minimize\",\n icon: [512, 512, [], \"f000\", \"M448 256v32H96V256h352z\"]\n};\nvar vsChromeRestore = {\n prefix: \"vs\",\n iconName: \"chrome-restore\",\n icon: [512, 512, [], \"f000\", \"M96 160v288h288V160H96zm256 256H128V192h224v224zM160 160h32V128h224v224h-32v32h64V96H160v64z\"]\n};\nvar vsCircleFilled = {\n prefix: \"vs\",\n iconName: \"circle-filled\",\n icon: [512, 512, [], \"f000\", \"M256 128c11.744 0 23.072 1.536 34.016 4.64a126.176 126.176 0 0 1 56.384 32.992 126.208 126.208 0 0 1 32.96 56.384c3.104 10.88 4.64 22.24 4.64 33.984 0 11.744 -1.536 23.072 -4.64 34.016a126.08 126.08 0 0 1 -32.96 56.48 128.544 128.544 0 0 1 -56.384 32.992C279.04 382.496 267.744 384 256 384s-23.072 -1.504 -34.016 -4.48a129.792 129.792 0 0 1 -56.48 -33.024A129.76 129.76 0 0 1 132.48 289.984 127.744 127.744 0 0 1 128 256c0 -11.744 1.504 -23.072 4.48 -34.016a128.64 128.64 0 0 1 13.024 -30.496A130.848 130.848 0 0 1 191.36 145.472a126.08 126.08 0 0 1 30.624 -12.832A124.48 124.48 0 0 1 256 128z\"]\n};\nvar vsCircleLargeFilled = {\n prefix: \"vs\",\n iconName: \"circle-large-filled\",\n icon: [512, 512, [], \"f000\", \"M256 32a217.6 217.6 0 0 1 59.52 8.096 220.768 220.768 0 0 1 98.656 57.76 220.896 220.896 0 0 1 57.728 98.656C477.312 215.616 480 235.424 480 256s-2.688 40.384 -8.096 59.52a220.8 220.8 0 0 1 -22.528 53.568 229.024 229.024 0 0 1 -80.512 80.288 222.912 222.912 0 0 1 -53.376 22.72A223.488 223.488 0 0 1 256 480a223.488 223.488 0 0 1 -59.52 -7.872 227.136 227.136 0 0 1 -53.568 -22.752 233.6 233.6 0 0 1 -45.28 -35.008 233.44 233.44 0 0 1 -35.008 -45.28 227.136 227.136 0 0 1 -22.72 -53.6A223.52 223.52 0 0 1 32 256c0 -20.576 2.624 -40.384 7.872 -59.52a222.976 222.976 0 0 1 22.752 -53.344 228.992 228.992 0 0 1 80.288 -80.512 220.64 220.64 0 0 1 53.6 -22.528A217.856 217.856 0 0 1 256 32z\"]\n};\nvar vsCircleLargeOutline = {\n prefix: \"vs\",\n iconName: \"circle-large-outline\",\n icon: [512, 512, [], \"f000\", \"M306.816 70.88A185.856 185.856 0 0 0 256 64c-17.728 0 -34.624 2.336 -50.816 6.88l-0.192 0.064c-16.448 4.512 -31.68 10.944 -45.824 19.232A196.992 196.992 0 0 0 90.24 159.36l-0.064 0.128A190.944 190.944 0 0 0 70.72 205.12 191.552 191.552 0 0 0 64 256c0 17.76 2.24 34.72 6.72 50.912a193.6 193.6 0 0 0 49.536 84.832c11.84 11.68 24.768 21.664 38.912 30.08a195.2 195.2 0 0 0 45.92 19.488A192.64 192.64 0 0 0 256 448c17.76 0 34.72 -2.24 50.912 -6.72 16.48 -4.64 31.68 -11.136 45.632 -19.424l0.128 -0.064a197.12 197.12 0 0 0 69.152 -68.96 187.2 187.2 0 0 0 19.2 -45.824l0.096 -0.192A185.824 185.824 0 0 0 448 256c0 -17.728 -2.304 -34.624 -6.88 -50.816l-0.064 -0.192a184.704 184.704 0 0 0 -19.2 -45.536l-0.064 -0.128a188.8 188.8 0 0 0 -30.144 -38.72l-0.256 -0.256a188.864 188.864 0 0 0 -38.72 -30.144l-0.128 -0.064a184.704 184.704 0 0 0 -45.536 -19.2l-0.192 -0.064zm142.56 298.24a229.024 229.024 0 0 1 -80.512 80.256 222.912 222.912 0 0 1 -53.376 22.72A223.488 223.488 0 0 1 256 480a223.488 223.488 0 0 1 -59.52 -7.872 227.136 227.136 0 0 1 -53.568 -22.752 233.6 233.6 0 0 1 -45.28 -35.008 233.44 233.44 0 0 1 -35.008 -45.28 227.136 227.136 0 0 1 -22.72 -53.6A223.52 223.52 0 0 1 32 256c0 -20.576 2.624 -40.384 7.872 -59.52a222.976 222.976 0 0 1 22.752 -53.344 228.992 228.992 0 0 1 80.288 -80.512 220.64 220.64 0 0 1 53.6 -22.528A217.856 217.856 0 0 1 256 32a217.6 217.6 0 0 1 59.52 8.096 220.768 220.768 0 0 1 98.656 57.76 220.896 220.896 0 0 1 57.728 98.656C477.312 215.616 480 235.424 480 256s-2.688 40.384 -8.096 59.52a220.8 220.8 0 0 1 -22.528 53.568z\"]\n};\nvar vsCircleOutline = {\n prefix: \"vs\",\n iconName: \"circle-outline\",\n icon: [512, 512, [], \"f000\", \"M256 384a128 128 0 1 0 0 -256 128 128 0 0 0 0 256zm83.52 -128a83.52 83.52 0 1 1 -167.04 0 83.52 83.52 0 0 1 167.04 0zM256 167.872z\"]\n};\nvar vsCircleSlash = {\n prefix: \"vs\",\n iconName: \"circle-slash\",\n icon: [512, 512, [], \"f000\", \"M256 32a224 224 0 1 1 -224 224 224.256 224.256 0 0 1 224 -224zM64 256c0 45.376 16.128 89.28 45.536 123.84l270.304 -270.304A191.776 191.776 0 0 0 64 256zm384 0c0 -45.376 -16.128 -89.28 -45.536 -123.84L132.16 402.464A191.776 191.776 0 0 0 448 256z\"]\n};\nvar vsCircuitBoard = {\n prefix: \"vs\",\n iconName: \"circuit-board\",\n icon: [512, 512, [], \"f000\", \"M464 32h-416l-16 16v416l16 16h416l16 -16v-416l-16 -16zM448 448H160v-64h73.6c9.6 19.2 32 32 54.4 32 35.2 0 64 -28.8 64 -64s-28.8 -64 -64 -64 -64 28.8 -64 64H128v96H64V64h64v73.6c-19.2 9.6 -32 32 -32 54.4 0 35.2 28.8 64 64 64s64 -28.8 64 -64h64c0 35.2 28.8 64 64 64s64 -28.8 64 -64 -28.8 -64 -64 -64c-22.4 0 -44.8 12.8 -54.4 32H214.4c-9.6 -19.2 -32 -32 -54.4 -32V64h288v384zm-192 -96c0 -19.2 12.8 -32 32 -32s32 12.8 32 32 -12.8 32 -32 32 -32 -12.8 -32 -32zM160 160c19.2 0 32 12.8 32 32s-12.8 32 -32 32 -32 -12.8 -32 -32 12.8 -32 32 -32zm192 0c19.2 0 32 12.8 32 32s-12.8 32 -32 32 -32 -12.8 -32 -32 12.8 -32 32 -32z\"]\n};\nvar vsClearAll = {\n prefix: \"vs\",\n iconName: \"clear-all\",\n icon: [512, 512, [], \"f000\", \"M320 403.2l22.4 22.4 51.2 -51.2 51.2 51.2 25.6 -22.4L416 352l54.4 -51.2 -25.6 -25.6 -51.2 54.4 -51.2 -54.4 -22.4 25.6 51.2 51.2 -51.2 51.2zM32 128h448V96H32v32zm0 96h448V192H32v32zm256 80V288H32v32h256v-16zM288 416v-32H32v32h256z\"]\n};\nvar vsClippy = {\n prefix: \"vs\",\n iconName: \"clippy\",\n icon: [512, 512, [], \"f000\", \"M224 447.744H128v-288h256v64h32v-80l-16 -16H352v-32h-32a64 64 0 0 0 -128 0H158.08v32H112l-16 16v320l16 16H224v-32zm0 -358.4a32 32 0 0 1 25.6 -25.6 32 32 0 0 1 18.56 1.92 30.08 30.08 0 0 1 14.4 11.52 32 32 0 1 1 -56 30.08 32 32 0 0 1 -2.56 -17.92zm226.56 302.72L416 426.944v-171.2h-32v170.88l-34.56 -34.56 -22.72 22.72 62.08 61.76h22.72l61.76 -61.76 -22.72 -22.72zm-189.44 -133.12h22.72l61.76 61.76 -22.72 22.72 -34.56 -34.56v170.88h-32v-171.2l-34.56 34.88 -22.72 -22.72 62.08 -61.76z\"]\n};\nvar vsCloseAll = {\n prefix: \"vs\",\n iconName: \"close-all\",\n icon: [512, 512, [], \"f000\", \"M275.872 258.752l-22.624 -22.624L208 281.376 162.752 236.128l-22.624 22.624L185.376 304l-45.248 45.248 22.624 22.624L208 326.624l45.248 45.248 22.624 -22.624L230.624 304l45.248 -45.248zM160 96l32 -32h224l32 32v224l-32 32h-64v64l-32 32H96l-32 -32V192l32 -32h64V96zm32 64h128l32 32v128h64V96H192v64zm128 32H96v224h224V192z\"]\n};\nvar vsClose = {\n prefix: \"vs\",\n iconName: \"close\",\n icon: [512, 512, [], \"f000\", \"M256 278.624l116.672 116.704 22.656 -22.624L278.624 256l116.704 -116.672 -22.624 -22.656L256 233.376 139.328 116.672l-22.624 22.656L233.376 256l-116.672 116.672 22.624 22.656L256 278.624z\"]\n};\nvar vsCloudDownload = {\n prefix: \"vs\",\n iconName: \"cloud-download\",\n icon: [512, 512, [], \"f000\", \"M382.624 192h1.6a95.68 95.68 0 0 1 67.712 28.128 96.096 96.096 0 0 1 0 135.744 95.68 95.68 0 0 1 -67.744 28.128v-32a64.064 64.064 0 0 0 0 -128h-29.248l-3.936 -27.424a79.68 79.68 0 0 0 -68.032 -67.904A79.296 79.296 0 0 0 199.392 176l-10.656 24.384 -25.888 -6.048A79.68 79.68 0 0 0 144.736 192c-21.184 0 -41.504 8.416 -56.448 23.424A80.096 80.096 0 0 0 144.736 352h15.936v32h-15.936a111.552 111.552 0 0 1 -84.096 -37.12 112.064 112.064 0 0 1 62.656 -184.96 110.784 110.784 0 0 1 46.976 1.28 111.552 111.552 0 0 1 117.024 -65.92A111.328 111.328 0 0 1 382.624 192zm-168 163.872l42.048 42.048V224h31.808v172.8l40.896 -40.928 22.624 22.624 -68.672 68.704h-22.656L192 378.528l22.624 -22.656z\"]\n};\nvar vsCloudUpload = {\n prefix: \"vs\",\n iconName: \"cloud-upload\",\n icon: [512, 512, [], \"f000\", \"M382.592 192h1.6a95.68 95.68 0 0 1 67.744 28.128 96.096 96.096 0 0 1 0 135.744 95.68 95.68 0 0 1 -67.744 28.128h-63.84v-32h63.84a64.064 64.064 0 0 0 0 -128h-29.248l-3.936 -27.424a79.68 79.68 0 0 0 -68.032 -67.904A79.296 79.296 0 0 0 199.36 176l-10.656 24.384 -25.888 -6.048A79.68 79.68 0 0 0 144.736 192c-21.184 0 -41.504 8.416 -56.448 23.424A80.096 80.096 0 0 0 144.736 352h79.808v32H144.736a111.552 111.552 0 0 1 -84.096 -37.12 112.064 112.064 0 0 1 -12.8 -132.384A111.904 111.904 0 0 1 123.296 161.92c15.552 -2.88 31.584 -2.464 46.976 1.312a111.552 111.552 0 0 1 117.024 -65.92A111.328 111.328 0 0 1 382.592 192zm-53.216 123.296L287.328 273.28v173.952h-31.808v-172.8L214.624 315.328 192 292.672 260.672 224h22.656L352 292.672l-22.624 22.624z\"]\n};\nvar vsCloud = {\n prefix: \"vs\",\n iconName: \"cloud\",\n icon: [512, 512, [], \"f000\", \"M382.624 192h1.6a95.68 95.68 0 0 1 67.712 28.128 96.096 96.096 0 0 1 0 135.744 95.68 95.68 0 0 1 -67.744 28.128v-0.416L384 384H144.736a111.552 111.552 0 0 1 -84.096 -37.12 112.064 112.064 0 0 1 62.656 -184.96 110.784 110.784 0 0 1 46.976 1.28 111.552 111.552 0 0 1 117.024 -65.92A111.328 111.328 0 0 1 382.624 192zM160 352h224.32a63.808 63.808 0 0 0 63.744 -64 64.064 64.064 0 0 0 -63.872 -64h-29.248l-3.936 -27.424a79.68 79.68 0 0 0 -68.032 -67.904A79.296 79.296 0 0 0 199.392 176l-10.656 24.384 -25.888 -6.048A79.68 79.68 0 0 0 144.736 192c-21.184 0 -41.504 8.416 -56.448 23.424A80.096 80.096 0 0 0 144.736 352H160z\"]\n};\nvar vsCode = {\n prefix: \"vs\",\n iconName: \"code\",\n icon: [512, 512, [], \"f000\", \"M150.656 178.496L65.952 263.168l84.704 84.672 -22.656 22.656 -96 -96V251.84l96 -96 22.656 22.656zm224 -22.656L352 178.496l84.704 84.672L352 347.84l22.656 22.656 96 -96V251.84l-96 -96zM157.056 416l28.608 14.336 160 -320L317.056 96l-160 320z\"]\n};\nvar vsCollapseAll = {\n prefix: \"vs\",\n iconName: \"collapse-all\",\n icon: [512, 512, [], \"f000\", \"M288 288H128v32h160V288zM160 96l32 -32h224l32 32v224l-32 32h-64v64l-32 32H96l-32 -32V192l32 -32h64V96zm32 64h128l32 32v128h64V96H192v64zm128 32H96v224h224V192z\"]\n};\nvar vsColorMode = {\n prefix: \"vs\",\n iconName: \"color-mode\",\n icon: [512, 512, [], \"f000\", \"M256 32a224 224 0 1 0 0 448A224 224 0 0 0 256 32zm0 416V64a192 192 0 1 1 0 384z\"]\n};\nvar vsCombine = {\n prefix: \"vs\",\n iconName: \"combine\",\n icon: [512, 512, [], \"f000\", \"M48 32l-16 16v96l16 16h96l16 -16v-96L144 32h-96zM64 128V64h64v64H64zm-16 64l-16 16v96l16 16h96l16 -16v-96L144 192h-96zM64 288V224h64v64H64zm-32 80l16 -16h96l16 16v96l-16 16h-96l-16 -16v-96zm32 16v64h64v-64H64zm336 -224l-16 16v192l16 16h96l16 -16v-192l-16 -16h-96zM480 256h-64V192h64v64zm0 96h-64V288h64v64zM291.2 256H192v32h99.2l-32 32 22.4 19.2 57.6 -57.6v-22.4L281.6 201.6l-22.4 22.4 32 32z\"]\n};\nvar vsCommentDiscussion = {\n prefix: \"vs\",\n iconName: \"comment-discussion\",\n icon: [512, 512, [], \"f000\", \"M128 361.28l32 -32v45.44l-36.8 36.48L96 400V320H48L32 304v-256l16 -16h384l16 16V192h-32V64H64v224h48l16 16v57.28zM329.28 416l59.52 59.2 27.2 -11.2V416h48l16 -16v-160l-16 -16h-256l-16 16v160l16 16h121.28zm6.72 -32H224V256h224v128h-48l-16 16v25.28l-36.8 -36.48 -11.2 -4.8z\"]\n};\nvar vsComment = {\n prefix: \"vs\",\n iconName: \"comment\",\n icon: [512, 512, [], \"f000\", \"M464 64h-416l-16 16v288l16 16H128v80l27.328 11.328L246.624 384H464l16 -16v-288l-16 -16zm-16 288H240l-11.328 4.672L160 425.376V368l-16 -16H64V96h384v256z\"]\n};\nvar vsCompassActive = {\n prefix: \"vs\",\n iconName: \"compass-active\",\n icon: [512, 512, [], \"f000\", \"M291.232 444.8a192.128 192.128 0 0 1 -19.232 2.56V416h-32v31.36a192.032 192.032 0 0 1 -175.424 -176.576H96v-32h-31.232A192.032 192.032 0 0 1 240 64.64V96h32v-31.36a192.032 192.032 0 0 1 175.36 175.36H416v32h31.36a192.128 192.128 0 0 1 -2.56 19.232c10.688 2.464 20.864 6.272 30.4 11.232a224 224 0 1 0 -172.704 172.704 127.136 127.136 0 0 1 -11.264 -30.4zm25.696 -109.856L223.68 288.32 158.944 158.944 288.288 223.68l46.688 93.216a128.64 128.64 0 0 0 -18.048 18.016zm-15.008 -33.024L271.392 240.64l-61.312 -30.56 30.528 61.344 61.312 30.528zm60.736 34.272a96 96 0 1 1 106.656 159.584 96 96 0 0 1 -106.656 -159.584zm54.336 122.144l57.28 -76.384 -25.6 -19.2 -47.36 63.168 -28.032 -22.4 -19.968 24.96 40.896 32.736 22.784 -2.88z\"]\n};\nvar vsCompassDot = {\n prefix: \"vs\",\n iconName: \"compass-dot\",\n icon: [512, 512, [], \"f000\", \"M291.232 444.8a192.128 192.128 0 0 1 -19.232 2.56V416h-32v31.36a192.032 192.032 0 0 1 -175.424 -176.576H96v-32h-31.232A192.032 192.032 0 0 1 240 64.64V96h32v-31.36a192.032 192.032 0 0 1 175.36 175.36H416v32h31.36a192.128 192.128 0 0 1 -2.56 19.232c10.688 2.464 20.864 6.272 30.4 11.232a224 224 0 1 0 -172.704 172.704 127.136 127.136 0 0 1 -11.264 -30.4zm25.696 -109.856L223.68 288.32 158.944 158.944 288.288 223.68l46.688 93.216a128.64 128.64 0 0 0 -18.048 18.016zm-15.008 -33.024L271.392 240.64l-61.312 -30.56 30.528 61.344 61.312 30.528z\"]\n};\nvar vsCompass = {\n prefix: \"vs\",\n iconName: \"compass\",\n icon: [512, 512, [], \"f000\", \"M288.288 223.712l64.768 129.344L223.712 288.32 158.944 158.944 288.288 223.68zm13.632 78.208L271.392 240.64l-61.312 -30.56 30.528 61.344 61.312 30.528zM447.36 272a192.064 192.064 0 0 1 -175.36 175.36V416h-32v31.36a192.032 192.032 0 0 1 -175.424 -176.576H96v-32h-31.232A192.032 192.032 0 0 1 240 64.64V96h32v-31.36a192.032 192.032 0 0 1 175.36 175.36H416v32h31.36zM256 480A224 224 0 1 0 256 32a224 224 0 0 0 0 448z\"]\n};\nvar vsCopy = {\n prefix: \"vs\",\n iconName: \"copy\",\n icon: [512, 512, [], \"f000\", \"M128 128l32 -32h173.248L448 210.752V448l-32 32H160l-32 -32V128zm288 96l-96 -96H160v320h256V224zM96 32L64 64v320l32 32V64h205.248l-32 -32H96z\"]\n};\nvar vsCreditCard = {\n prefix: \"vs\",\n iconName: \"credit-card\",\n icon: [512, 512, [], \"f000\", \"M448 160v32H64V160h384zM64 224h384v160H64V224zm384 -96H64a32 32 0 0 0 -32 32v224a32 32 0 0 0 32 32h384a32 32 0 0 0 32 -32V160a32 32 0 0 0 -32 -32zm-96 192h64v32h-64v-32z\"]\n};\nvar vsDash = {\n prefix: \"vs\",\n iconName: \"dash\",\n icon: [512, 512, [], \"f000\", \"M160 256h192v32H160z\"]\n};\nvar vsDashboard = {\n prefix: \"vs\",\n iconName: \"dashboard\",\n icon: [512, 512, [], \"f000\", \"M124.448 67.04a208 208 0 1 1 231.104 345.92A208 208 0 0 1 124.48 67.008zm17.76 319.296A176 176 0 0 0 240 416 176.192 176.192 0 0 0 416 240a176 176 0 1 0 -273.792 146.336zM329.408 128l22.592 22.624 -68.8 68.8a48.448 48.448 0 1 1 -22.624 -22.624L329.376 128zM231.072 253.312a16 16 0 1 0 17.792 -26.624 16 16 0 0 0 -17.792 26.624zm137.152 -78.368l-24.416 24.416c5.312 12.896 8.096 26.688 8.16 40.64a110.816 110.816 0 0 1 -16 56.864l23.52 23.52a143.264 143.264 0 0 0 8.768 -145.44h-0.032zM279.456 135.744A107.936 107.936 0 0 0 240 128 112 112 0 0 0 128 240a110.72 110.72 0 0 0 16 56.864l-23.488 23.52A144 144 0 0 1 304 111.136l-24.544 24.608z\"]\n};\nvar vsDatabase = {\n prefix: \"vs\",\n iconName: \"database\",\n icon: [512, 512, [], \"f000\", \"M416 112C416 67.808 344.352 32 256 32S96 67.808 96 112c0 1.28 0.64 2.464 0.768 3.744H96v283.904l1.792 11.424C106.752 449.792 173.728 480 256 480c82.272 0 149.248 -30.208 158.208 -68.928l1.792 -11.424V115.744h-0.768c0.128 -1.28 0.768 -2.464 0.768 -3.744zM256 65.024c78.144 0 128 30.848 128 46.976s-49.856 46.976 -128 46.976S128 128 128 112s49.856 -46.976 128 -46.976zm128 334.656l-0.96 4.192C379.36 419.712 333.792 448 256 448s-123.36 -28.288 -127.04 -44.128L128 399.68v-240A237.248 237.248 0 0 0 256 192a237.248 237.248 0 0 0 128 -32.448v240.128z\"]\n};\nvar vsDebugAll = {\n prefix: \"vs\",\n iconName: \"debug-all\",\n icon: [512, 512, [], \"f000\", \"M233.376 288.192l-28.16 28.16A79.488 79.488 0 0 0 128 256a79.616 79.616 0 0 0 -77.216 60.352l-28.16 -28.16L0 310.784l36.704 36.672 -4.704 4.672v32H0v31.968h32v1.696c1.632 10.432 4.576 20.576 8.736 30.272L0 489.408 22.624 512l35.2 -35.168A91.936 91.936 0 0 0 128 512a92 92 0 0 0 70.176 -35.168L233.376 512 256 489.408l-40.736 -41.344A125.44 125.44 0 0 0 224 417.152v-2.144h32v-30.88H224v-32l-4.704 -4.672L256 310.784l-22.624 -22.592zM128 288.192a48 48 0 0 1 48 47.968h-96A47.936 47.936 0 0 1 128 288.192zm64 127.904A70.944 70.944 0 0 1 128 480a71.04 71.04 0 0 1 -64 -63.936v-47.968h128v47.968zM120.96 64L96 77.12V224h32V107.2l243.2 162.24L288 324.8v38.4l120.96 -80.64V256l-288 -192zM288 427.2v-38.464l179.2 -119.296L224 107.2V68.704L504.96 256v26.56L288 427.2z\"]\n};\nvar vsDebugAltSmall = {\n prefix: \"vs\",\n iconName: \"debug-alt-small\",\n icon: [512, 512, [], \"f000\", \"M233.376 288.192l-28.16 28.16A79.488 79.488 0 0 0 128 256a79.616 79.616 0 0 0 -77.216 60.352l-28.16 -28.16L0 310.784l36.704 36.672 -4.704 4.672v32H0v31.968h32v1.696c1.632 10.432 4.576 20.576 8.736 30.272L0 489.408 22.624 512l35.2 -35.168A91.936 91.936 0 0 0 128 512a92 92 0 0 0 70.176 -35.168L233.376 512 256 489.408l-40.736 -41.344A125.44 125.44 0 0 0 224 417.152v-2.144h32v-30.88H224v-32l-4.704 -4.672L256 310.784l-22.624 -22.592zM128 288.192a48 48 0 0 1 48 47.968h-96A47.936 47.936 0 0 1 128 288.192zm64 127.904A70.944 70.944 0 0 1 128 480a71.04 71.04 0 0 1 -64 -63.936v-47.968h128v47.968zM160 77.12L184.96 64l288 192v26.56L288 405.856v-38.4l147.2 -98.016L192 107.2V224H160V77.12z\"]\n};\nvar vsDebugAlt = {\n prefix: \"vs\",\n iconName: \"debug-alt\",\n icon: [512, 512, [], \"f000\", \"M233.387 288l-28.16 28.16a79.573 79.573 0 0 0 -154.453 0L22.613 288 0 310.613l36.693 36.693 -4.693 4.693V384H0v32h32v1.707c1.643 10.432 4.565 20.608 8.747 30.293L0 489.387 22.613 512l35.2 -35.2A91.904 91.904 0 0 0 128 512a91.947 91.947 0 0 0 70.187 -35.2L233.387 512 256 489.387 215.253 448c4.224 -9.899 7.168 -20.288 8.747 -30.933v-2.133H256V384h-32v-32l-4.693 -4.693L256 310.613l-22.613 -22.613zM128 288a48 48 0 0 1 48 48h-96A48 48 0 0 1 128 288zm64 128a71.04 71.04 0 0 1 -64 64 71.04 71.04 0 0 1 -64 -64v-48h128v48zm314.88 -211.2v26.88L288 370.56V332.8l181.333 -114.56L192 42.667v201.813a108.16 108.16 0 0 0 -32 -15.36V13.44L184.32 0l322.56 204.8z\"]\n};\nvar vsDebugBreakpointConditionalUnverified = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-conditional-unverified\",\n icon: [512, 512, [], \"f000\", \"M184.896 149.568a128 128 0 1 1 142.208 212.864 128 128 0 0 1 -142.208 -212.864zm22.208 179.584a88 88 0 1 0 97.792 -146.304 88 88 0 0 0 -97.792 146.304zM304 208h-96v32h96v-32zm0 64h-96v32h96v-32z\"]\n};\nvar vsDebugBreakpointConditional = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-conditional\",\n icon: [512, 512, [], \"f000\", \"M256 128a128 128 0 1 0 0 256 128 128 0 0 0 0 -256zm64 160v32H192V288h128zm0 -96v32H192V192h128z\"]\n};\nvar vsDebugBreakpointDataUnverified = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-data-unverified\",\n icon: [512, 512, [], \"f000\", \"M317.792 128h-147.84l-73.92 128 73.92 128h147.84l73.92 -128 -73.92 -128zm-24 214.4h-99.84L144.032 256l49.92 -86.4h99.84l49.92 86.4 -49.92 86.4z\"]\n};\nvar vsDebugBreakpointData = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-data\",\n icon: [512, 512, [], \"f000\", \"M391.616 256l-73.92 128H169.92L96 256l73.92 -128h147.776l73.92 128z\"]\n};\nvar vsDebugBreakpointFunctionUnverified = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-function-unverified\",\n icon: [512, 512, [], \"f000\", \"M128 352h256L256 128l-128 224zm68.928 -40h118.144L256 208.64 196.928 312z\"]\n};\nvar vsDebugBreakpointFunction = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-function\",\n icon: [512, 512, [], \"f000\", \"M256 128l128 220.96H128L256 128z\"]\n};\nvar vsDebugBreakpointLogUnverified = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-log-unverified\",\n icon: [512, 512, [], \"f000\", \"M96.64 255.36L256 96l159.36 159.36L256 414.72 96.64 255.36zM256 344.64l89.28 -89.28L256 166.08 166.72 255.36 256 344.64z\"]\n};\nvar vsDebugBreakpointLog = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-log\",\n icon: [512, 512, [], \"f000\", \"M256 96l160 160 -160 160 -160 -160 160 -160z\"]\n};\nvar vsDebugBreakpointUnsupported = {\n prefix: \"vs\",\n iconName: \"debug-breakpoint-unsupported\",\n icon: [512, 512, [], \"f000\", \"M362.432 327.104a128 128 0 1 0 -212.896 -142.208 128 128 0 0 0 212.896 142.208zM276.8 320H236.8v32h40v-32zM236.8 288V160h40v128H236.8z\"]\n};\nvar vsDebugConsole = {\n prefix: \"vs\",\n iconName: \"debug-console\",\n icon: [512, 512, [], \"f000\", \"M150.187 29.035l2.965 -1.216H454.827l2.987 1.216 25.131 25.152 1.216 2.965V358.827l-1.216 2.987 -25.152 25.131 -2.965 1.216H298.667V384a42.453 42.453 0 0 0 -11.691 -29.333h163.691V61.333H157.333v155.349a122.24 122.24 0 0 0 -33.515 -3.499V57.152l1.216 -2.987L150.187 29.056zm203.328 201.643l-59.925 59.733a42.667 42.667 0 0 0 -7.424 -9.963l-8.939 -8.96 47.701 -47.68 -76.928 -78.805 17.344 -17.771 88.171 88.171v15.275zM205.227 316.16l28.16 -28.16L256 310.613l-36.693 36.693 4.693 4.693V384H256v30.933h-32v2.133a125.611 125.611 0 0 1 -8.747 30.933L256 489.387 233.387 512l-35.2 -35.2A91.904 91.904 0 0 1 128 512a91.947 91.947 0 0 1 -70.187 -35.2L22.613 512 0 489.387 40.747 448a125.632 125.632 0 0 1 -8.747 -30.293v-1.707H0V384h32v-32l4.693 -4.693L0 310.613l22.613 -22.613 28.16 28.16a79.573 79.573 0 0 1 154.453 0zm-43.285 -14.101A48 48 0 0 0 80 336h96a48 48 0 0 0 -14.059 -33.941zm9.579 157.44A71.04 71.04 0 0 0 192 416v-48H64v48a71.04 71.04 0 0 0 64 64 71.04 71.04 0 0 0 43.52 -20.48z\"]\n};\nvar vsDebugContinueSmall = {\n prefix: \"vs\",\n iconName: \"debug-continue-small\",\n icon: [512, 512, [], \"f000\", \"M128 64H96v384h32V64zm105.28 18.976L208 96v320l25.28 13.024 224 -160v-26.048l-224 -160zM420.48 256L240 384.896V127.104L420.48 256z\"]\n};\nvar vsDebugContinue = {\n prefix: \"vs\",\n iconName: \"debug-continue\",\n icon: [512, 512, [], \"f000\", \"M80 64H128v384H80V64zm157.952 12.48L200 96v320l37.952 19.52 224 -160V236.48l-224 -160zM406.72 256l-158.72 113.376V142.624L406.72 256z\"]\n};\nvar vsDebugCoverage = {\n prefix: \"vs\",\n iconName: \"debug-coverage\",\n icon: [512, 512, [], \"f000\", \"M160 77.12L184.96 64l288 192v26.56L288 405.856v-38.4l147.2 -98.016L192 107.2V224H160V77.12zm36.16 310.848c-5.824 5.76 -10.304 12.128 -13.44 19.2a55.808 55.808 0 0 0 -4.64 22.88v27.584a21.92 21.92 0 0 1 -6.56 15.84 22.496 22.496 0 0 1 -15.872 6.528h-27.68a22.112 22.112 0 0 1 -15.904 -6.528 22.432 22.432 0 0 1 -6.56 -15.84v-27.584c0 -8.256 -1.568 -15.872 -4.704 -22.912a61.216 61.216 0 0 0 -13.376 -19.2 80.8 80.8 0 0 1 -17.344 -24.736 72.16 72.16 0 0 1 -6.08 -29.664A76.352 76.352 0 0 1 74.624 294.4a76.928 76.928 0 0 1 27.84 -27.84A79.136 79.136 0 0 1 141.824 256a77.12 77.12 0 0 1 39.2 10.56 77.12 77.12 0 0 1 38.56 66.976c0 10.624 -2.016 20.512 -6.08 29.664a80.8 80.8 0 0 1 -17.344 24.768zm-35.296 31.712H122.72v37.952c0 1.376 0.512 2.56 1.568 3.648 1.056 1.056 2.24 1.536 3.68 1.536h27.68a4.992 4.992 0 0 0 3.648 -1.536 4.928 4.928 0 0 0 1.568 -3.648v-37.952z\"]\n};\nvar vsDebugDisconnect = {\n prefix: \"vs\",\n iconName: \"debug-disconnect\",\n icon: [512, 512, [], \"f000\", \"M435.744 123.008a91.84 91.84 0 0 0 -14.432 -27.776l43.328 -43.52L444.928 32l-43.52 43.328a92.064 92.064 0 0 0 -27.776 -14.464 98.336 98.336 0 0 0 -68.48 2.4 96.96 96.96 0 0 0 -31.712 21.248L224 134.144l138.464 138.496 49.664 -49.44c9.184 -9.184 16.256 -19.776 21.216 -31.744a98.368 98.368 0 0 0 2.4 -68.48zm-28.448 57.728a68.8 68.8 0 0 1 -15.072 22.56l-29.76 29.76 -98.88 -98.88 29.76 -29.76a68.8 68.8 0 0 1 22.528 -15.104 68.288 68.288 0 0 1 54.048 0.224c8.448 3.648 15.808 8.672 22.08 15.104 6.4 6.24 11.456 13.632 15.104 22.08a68.288 68.288 0 0 1 0.224 54.016zm-154.368 159.808l47.488 -49.44 -19.712 -19.904 -47.68 49.632 -59.52 -59.488 47.712 -49.664L201.312 192 153.856 241.44l-19.712 -19.68 -49.632 49.44a96 96 0 0 0 -21.216 31.936 96.736 96.736 0 0 0 -7.456 37.408c0 10.624 1.6 20.992 4.8 31.04 3.36 9.92 8.256 19.104 14.688 27.584L32 442.688l19.68 19.68 43.52 -43.296c8.48 6.4 17.664 11.296 27.584 14.656 10.048 3.2 20.416 4.8 31.04 4.8 12.992 0 25.472 -2.464 37.44 -7.424 12.096 -4.96 22.72 -12.032 31.936 -21.216l49.44 -49.664 -19.712 -19.68zm-72.384 64.736a69.12 69.12 0 0 1 -26.688 5.248c-9.632 0 -18.752 -1.824 -27.36 -5.44a72.896 72.896 0 0 1 -22.304 -14.912 72.96 72.96 0 0 1 -14.88 -22.304 69.344 69.344 0 0 1 -5.44 -27.328 69.12 69.12 0 0 1 20.544 -49.44l29.76 -29.76 98.88 98.88 -29.76 29.76a71.04 71.04 0 0 1 -22.752 15.296z\"]\n};\nvar vsDebugLineByLine = {\n prefix: \"vs\",\n iconName: \"debug-line-by-line\",\n icon: [512, 512, [], \"f000\", \"M192 320V288h288v32H192zm128 -128h160v32h-160V192zm160 -96v32H192V96h288zm-288 288v32h288v-32H192zM32 89.44l25.056 -13.408 171.872 114.592v26.816l-171.872 114.592L32 318.624V89.44zm32.224 30.08v168.992l126.72 -84.48 -126.72 -84.48z\"]\n};\nvar vsDebugPause = {\n prefix: \"vs\",\n iconName: \"debug-pause\",\n icon: [512, 512, [], \"f000\", \"M144 96H192v320H144V96zm224 0v320H320V96h48z\"]\n};\nvar vsDebugRerun = {\n prefix: \"vs\",\n iconName: \"debug-rerun\",\n icon: [512, 512, [], \"f000\", \"M229.344 384a96 96 0 0 1 -183.68 39.136l-29.696 12.032A128.032 128.032 0 1 0 32 305.792V266.656H0V352l16 16h74.656v-32H50.176A96 96 0 0 1 229.344 384zM160 77.12L184.96 64l288 192v26.56L320 384.544v-38.4l115.2 -76.704L192 107.2V224H160V77.12z\"]\n};\nvar vsDebugRestartFrame = {\n prefix: \"vs\",\n iconName: \"debug-restart-frame\",\n icon: [512, 512, [], \"f000\", \"M32 320V288h166.624a175.36 175.36 0 0 0 -5.92 32H32zm200.224 -96a177.28 177.28 0 0 1 34.56 -32H32v32h200.224zM211.2 416a174.88 174.88 0 0 1 -12.576 -32H32v32h179.2zM480 96v32H32V96h448zm-107.52 320.992a80.992 80.992 0 1 0 -70.144 -121.504h34.176v27.008h-63.04l-13.472 -13.504v-72h27.008v33.024a108 108 0 1 1 -13.536 109.184l25.024 -10.176a81.024 81.024 0 0 0 74.016 48z\"]\n};\nvar vsDebugRestart = {\n prefix: \"vs\",\n iconName: \"debug-restart\",\n icon: [512, 512, [], \"f000\", \"M408 256a144 144 0 0 1 -275.52 58.688l-44.512 18.08A192.032 192.032 0 0 0 456 256 192 192 0 0 0 112 138.688V80H64v128l24 24h112v-48H139.264A144 144 0 0 1 408 256z\"]\n};\nvar vsDebugReverseContinue = {\n prefix: \"vs\",\n iconName: \"debug-reverse-continue\",\n icon: [512, 512, [], \"f000\", \"M432 64H384v384h48V64zm-157.952 12.48L312 96v320l-37.952 19.52 -224 -160V236.48l224 -160zM105.28 256l158.72 113.376V142.624L105.28 256z\"]\n};\nvar vsDebugStackframeActive = {\n prefix: \"vs\",\n iconName: \"debug-stackframe-active\",\n icon: [512, 512, [], \"f000\", \"M320 256a64 64 0 1 1 -128 0 64 64 0 0 1 128 0zm144 -27.2l-136.32 -151.68L297.92 64H136L96 104v303.36l40 40h161.92l29.76 -13.44 136.32 -151.68V228.8zm-166.08 178.56H136V104h161.92l136.32 151.36 -136.32 152z\"]\n};\nvar vsDebugStackframeDot = {\n prefix: \"vs\",\n iconName: \"debug-stackframe-dot\",\n icon: [512, 512, [], \"f000\", \"M320 256a64 64 0 1 1 -128 0 64 64 0 0 1 128 0z\"]\n};\nvar vsDebugStackframe = {\n prefix: \"vs\",\n iconName: \"debug-stackframe\",\n icon: [512, 512, [], \"f000\", \"M464 228.8l-136.32 -151.68L297.92 64H136L96 104v303.36l40 40h161.92l29.76 -13.44 136.32 -151.68V228.8zm-166.08 178.56H136V104h161.92l136.32 151.36 -136.32 152z\"]\n};\nvar vsDebugStart = {\n prefix: \"vs\",\n iconName: \"debug-start\",\n icon: [512, 512, [], \"f000\", \"M136 96l37.312 -19.968 256 170.656v39.936l-256 170.688 -37.312 -19.968V96zm48 44.832v251.648l188.736 -125.824L184 140.832z\"]\n};\nvar vsDebugStepBack = {\n prefix: \"vs\",\n iconName: \"debug-step-back\",\n icon: [512, 512, [], \"f000\", \"M56 184v-128h48v81.344c36.64 -43.488 93.152 -70.688 154.88 -70.688 101.664 0 189.44 73.824 197.12 172.736l0.64 8.608h-48l-0.704 -7.232c-6.784 -70.24 -70.464 -126.08 -148.992 -126.08 -55.552 0 -103.808 28 -129.6 69.312h90.56v48H86.624l-30.752 -31.2V184h0.096zM256 448a64 64 0 1 1 0 -128 64 64 0 0 1 0 128z\"]\n};\nvar vsDebugStepInto = {\n prefix: \"vs\",\n iconName: \"debug-step-into\",\n icon: [512, 512, [], \"f000\", \"M256 305.024h17.344l124.96 -124.96 -33.952 -33.92 -84.384 83.52V32H232.032v197.664l-84.384 -83.52 -33.952 33.92 124.96 124.96H256zm62.592 111.392a64 64 0 1 1 -128 0 64 64 0 0 1 128 0z\"]\n};\nvar vsDebugStepOut = {\n prefix: \"vs\",\n iconName: \"debug-step-out\",\n icon: [512, 512, [], \"f000\", \"M256 32h-17.344L113.696 156.96l33.952 33.92 84.384 -83.52v197.664h47.936V107.36l84.384 83.52 33.952 -33.92L273.344 32H256zm62.592 384.416a64 64 0 1 1 -128 0 64 64 0 0 1 128 0z\"]\n};\nvar vsDebugStepOver = {\n prefix: \"vs\",\n iconName: \"debug-step-over\",\n icon: [512, 512, [], \"f000\", \"M456 184v-128h-48v81.344c-36.64 -43.488 -93.152 -70.688 -154.88 -70.688 -101.664 0 -189.44 73.824 -197.12 172.736l-0.64 8.608h48.032l0.704 -7.232c6.784 -70.24 70.464 -126.08 148.992 -126.08 55.552 0 103.808 28 129.6 69.312h-90.56v48h133.216l30.784 -31.2V184h-0.128zM256 448a64 64 0 1 0 0 -128 64 64 0 0 0 0 128z\"]\n};\nvar vsDebugStop = {\n prefix: \"vs\",\n iconName: \"debug-stop\",\n icon: [512, 512, [], \"f000\", \"M64 64v384h384V64H64zm344 344h-304v-304h304v304z\"]\n};\nvar vsDebug = {\n prefix: \"vs\",\n iconName: \"debug\",\n icon: [512, 512, [], \"f000\", \"M73.877 274.347l-0.107 -1.493 0.107 1.493zm154.965 14.72l-64.725 -65.045 21.632 -21.632 68.459 68.8 67.477 -67.477 21.632 21.632 -64.725 64.725 64.725 65.067 -21.632 21.632 -68.459 -68.8L185.749 375.467l-21.632 -21.632 64.725 -64.725zm132.395 -182.336V128h28.693l60.651 -60.629 21.632 21.632 -57.429 57.408 0.704 1.813a293.333 293.333 0 0 1 18.88 104.789c0 7.147 -0.235 14.229 -0.725 21.227l-0.107 1.6h75.52v30.592h-79.36l-0.213 1.237c-6.464 35.264 -19.008 67.413 -36.096 94.485l-1.28 2.005 73.024 73.387 -21.696 21.589 -69.845 -70.187 -2.112 2.347c-31.552 35.285 -72.427 56.448 -116.971 56.448 -45.227 0 -86.677 -21.824 -118.443 -58.091l-2.091 -2.411 -68.459 68.437 -21.632 -21.632 71.808 -71.787 -1.259 -2.027c-16.469 -26.667 -28.587 -58.133 -34.901 -92.587l-0.213 -1.216H0V275.84h75.477l-0.107 -1.6a303.573 303.573 0 0 1 -0.725 -21.227c0 -37.184 6.613 -72.32 18.411 -103.552l0.683 -1.792 -58.923 -59.221L56.533 66.88 117.333 128h30.443v-21.269a106.731 106.731 0 0 1 213.461 0zm-182.869 0V128H330.667v-21.269a76.139 76.139 0 0 0 -152.277 0zm209.067 53.803l-0.725 -1.92H122.304l-0.725 1.92a262.997 262.997 0 0 0 -16.341 92.48c0 58.88 18.389 110.955 46.592 147.627 28.16 36.608 64.768 56.512 102.677 56.512 37.909 0 74.496 -19.904 102.677 -56.533 28.203 -36.651 46.592 -88.747 46.592 -147.605 0 -33.579 -5.973 -64.939 -16.341 -92.48z\"]\n};\nvar vsDesktopDownload = {\n prefix: \"vs\",\n iconName: \"desktop-download\",\n icon: [512, 512, [], \"f000\", \"M128 480v-32c64 0 64 -19.2 64 -32H48l-16 -16v-320l16 -16h416l16 16v295.68l-32 -32V96H64v288h183.36l-16 16 80 80H128zm251.52 0l80 -80 -22.72 -22.4L384 430.4V224h-32v206.08l-52.48 -52.8 -22.72 22.72 80 80h22.72z\"]\n};\nvar vsDeviceCameraVideo = {\n prefix: \"vs\",\n iconName: \"device-camera-video\",\n icon: [512, 512, [], \"f000\", \"M456 151.68L352 211.84V144l-16 -16h-288l-16 16v224l16 16h288l16 -16v-64l104 59.84 24 -15.04V165.76l-24 -14.08zM320 352H64V160h256v192zm128 -32l-96 -54.4v-16.64L448 192v128z\"]\n};\nvar vsDeviceCamera = {\n prefix: \"vs\",\n iconName: \"device-camera\",\n icon: [512, 512, [], \"f000\", \"M342.624 96H464l16 16v288l-16 16h-416l-16 -16v-288l16 -16h121.376l27.296 -27.328L208 64h96l11.328 4.672 27.296 27.328zM64 384h384V128h-112l-11.328 -4.672L297.376 96H214.624l-27.296 27.328L176 128H64v256zm48 -224a16 16 0 1 0 0 32 16 16 0 0 0 0 -32zM256 192a64 64 0 1 1 0 128 64 64 0 0 1 0 -128zm0 -32a96 96 0 1 0 0 192 96 96 0 0 0 0 -192z\"]\n};\nvar vsDeviceMobile = {\n prefix: \"vs\",\n iconName: \"device-mobile\",\n icon: [512, 512, [], \"f000\", \"M144 32h256l16 16v416l-16 16h-256l-16 -16v-416l16 -16zM160 448h224V64H160v384zm80 -64h64v32h-64v-32z\"]\n};\nvar vsDiffAdded = {\n prefix: \"vs\",\n iconName: \"diff-added\",\n icon: [512, 512, [], \"f000\", \"M48 32h384l16 16v384l-16 16h-384l-16 -16v-384l16 -16zM64 416h352V64H64v352zm192 -288H224v96H128v32h96v96h32V256h96V224H256V128z\"]\n};\nvar vsDiffIgnored = {\n prefix: \"vs\",\n iconName: \"diff-ignored\",\n icon: [512, 512, [], \"f000\", \"M48 32h416l16 16v416l-16 16h-416l-16 -16v-416l16 -16zM64 448h384V64H64v384zm256 -320h64v64l-192 192H128v-64l192 -192z\"]\n};\nvar vsDiffModified = {\n prefix: \"vs\",\n iconName: \"diff-modified\",\n icon: [512, 512, [], \"f000\", \"M48 32h416l16 16v416l-16 16h-416l-16 -16v-416l16 -16zM64 64v384h384V64H64zm192 288a96 96 0 1 0 0 -192 96 96 0 0 0 0 192z\"]\n};\nvar vsDiffRemoved = {\n prefix: \"vs\",\n iconName: \"diff-removed\",\n icon: [512, 512, [], \"f000\", \"M320 224v32H160V224h160zM48 32h384l16 16v384l-16 16h-384l-16 -16v-384l16 -16zM64 416h352V64H64v352z\"]\n};\nvar vsDiffRenamed = {\n prefix: \"vs\",\n iconName: \"diff-renamed\",\n icon: [512, 512, [], \"f000\", \"M48 32h416l16 16v416l-16 16h-416l-16 -16v-416l16 -16zM64 448h384V64H64v384zm64 -160h96v96l160 -128 -160 -128v96H128v64z\"]\n};\nvar vsDiff = {\n prefix: \"vs\",\n iconName: \"diff\",\n icon: [512, 512, [], \"f000\", \"M64 112l16 -16h160l16 16v288l-16 16h-160l-16 -16v-288zM96 384h128V192H96v192zm0 -224h128V128H96v32zm208 -64h160l16 16v288l-16 16h-160l-16 -16v-288l16 -16zm16 288h128v-64h-128v64zm0 -128h128V128h-128v128z\"]\n};\nvar vsDiscard = {\n prefix: \"vs\",\n iconName: \"discard\",\n icon: [512, 512, [], \"f000\", \"M112 64v112L128 192h112V160H159.328l30.112 -30.112a113.664 113.664 0 1 1 160.736 160.736L183.872 456.96l23.04 23.04 166.336 -166.336A146.24 146.24 0 0 0 166.4 106.848l-22.4 22.4V64h-32z\"]\n};\nvar vsEdit = {\n prefix: \"vs\",\n iconName: \"edit\",\n icon: [512, 512, [], \"f000\", \"M423.36 32h-46.72L112.64 296l-5.12 7.04L32 434.88 77.12 480l131.84 -75.52 7.04 -5.12L480 135.36V88.64L423.36 32zM77.12 434.88l48.32 -96 46.4 46.4 -94.72 49.6zm122.56 -65.92L143.04 312.32l256 -256 56.64 56.64 -256 256z\"]\n};\nvar vsEditorLayout = {\n prefix: \"vs\",\n iconName: \"editor-layout\",\n icon: [512, 512, [], \"f000\", \"M480 208l-15.04 -16H224V47.04L208.96 32H47.04L32 47.04v257.92l15.04 15.04H128v144.96l15.04 15.04h321.92l15.04 -15.04V208zM64 288V96h128v192H64zm384 160H160v-128h48.96L224 304.96V256.416h224V448z\"]\n};\nvar vsEllipsis = {\n prefix: \"vs\",\n iconName: \"ellipsis\",\n icon: [512, 512, [], \"f000\", \"M128 256a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zm160 0a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zm160 0a32 32 0 1 1 -64 0 32 32 0 0 1 64 0z\"]\n};\nvar vsEmptyWindow = {\n prefix: \"vs\",\n iconName: \"empty-window\",\n icon: [512, 512, [], \"f000\", \"M128 128h96v32H128v96H96V160H0V128h96V32h32v96zM32 464V288h32v160h384V224H256V192h192V128H256V96h208l16 16v352l-16 16h-416l-16 -16z\"]\n};\nvar vsError = {\n prefix: \"vs\",\n iconName: \"error\",\n icon: [512, 512, [], \"f000\", \"M275.2 32c51.2 3.2 99.2 28.8 134.4 64 41.6 44.8 64 99.2 64 163.2 0 51.2 -19.2 99.2 -51.2 140.8 -32 38.4 -76.8 67.2 -128 76.8 -51.2 9.6 -102.4 3.2 -147.2 -22.4 -44.8 -25.6 -80 -64 -99.2 -112C28.8 294.4 25.6 240 41.6 192c16 -51.2 44.8 -92.8 89.6 -121.6C172.8 41.6 224 28.8 275.2 32zm16 412.8c41.6 -9.6 80 -32 108.8 -67.2 25.6 -35.2 41.6 -76.8 38.4 -121.6 0 -51.2 -19.2 -102.4 -54.4 -137.6 -32 -32 -70.4 -51.2 -115.2 -54.4 -41.6 -3.2 -86.4 6.4 -121.6 32 -35.2 25.6 -60.8 60.8 -73.6 105.6 -12.8 41.6 -12.8 86.4 6.4 128 19.2 41.6 48 73.6 86.4 96 38.4 22.4 83.2 28.8 124.8 19.2zM252.8 240L329.6 160l22.4 22.4 -76.8 80 76.8 80 -22.4 22.4 -76.8 -80 -76.8 80 -22.4 -22.4 76.8 -80 -76.8 -80 22.4 -22.4 76.8 80z\"]\n};\nvar vsExclude = {\n prefix: \"vs\",\n iconName: \"exclude\",\n icon: [512, 512, [], \"f000\", \"M301.184 32H210.816l-15.488 77.536 -65.792 -43.84 -63.872 63.84 43.84 65.792L32 210.816v90.368l77.536 15.488 -43.84 65.792 63.84 63.872 65.792 -43.84L210.816 480h66.656a144.832 144.832 0 0 1 -29.344 -32.16h-10.944l-9.216 -46.112a143.136 143.136 0 0 1 -2.144 -10.688l-3.712 -18.656 -24.448 -10.112 -64 42.688 -26.624 -26.592L149.76 314.336l-10.112 -24.448 -75.456 -15.072V237.184l75.456 -15.072 10.112 -24.448 -42.688 -64 26.592 -26.624 64 42.72 24.448 -10.112 15.072 -75.456h37.632l15.072 75.456 24.448 10.112 64 -42.688 26.624 26.592 -42.688 64.032 10.112 24.448 18.624 3.712c3.616 0.576 7.2 1.28 10.72 2.144l46.112 9.216v10.944c12.16 8.128 23.008 18.016 32.16 29.344V210.816l-77.504 -15.488 43.84 -65.792 -63.872 -63.872 -65.792 43.84L301.184 32zM256 192a64 64 0 0 1 60 41.664 142.72 142.72 0 0 0 -28.8 15.136 32 32 0 1 0 -38.4 38.4 142.72 142.72 0 0 0 -15.136 28.8A64 64 0 0 1 256 192zm40.96 89.44a112 112 0 1 1 142.08 173.12 112 112 0 0 1 -142.08 -173.12zM288 352v32h160v-32H288z\"]\n};\nvar vsExpandAll = {\n prefix: \"vs\",\n iconName: \"expand-all\",\n icon: [512, 512, [], \"f000\", \"M288 288H128v32h160V288zm-64 96V224H192v160h32zM160 96l32 -32h224l32 32v224l-32 32h-64v64l-32 32H96l-32 -32V192l32 -32h64V96zm32 64h128l32 32v128h64V96H192v64zm128 32H96v224h224V192z\"]\n};\nvar vsExport = {\n prefix: \"vs\",\n iconName: \"export\",\n icon: [512, 512, [], \"f000\", \"M418.752 224l-76.48 -76.736 22.464 -22.528L480 240l-115.264 115.264 -22.496 -22.528 76.256 -76.224V256H96V224h322.752zM32 128h32v224H32V128z\"]\n};\nvar vsExtensions = {\n prefix: \"vs\",\n iconName: \"extensions\",\n icon: [512, 512, [], \"f000\", \"M288 32L320 0h160L512 32V192l-32 32H320L288 192V32zm32 0V192h160V32H320zM0 320V128l32 -32H192L224 128v160H384l32 32v160L384 512H32L0 480V320zm192 -32V128H32v160H192zM192 320H32v160H192V320zm32 160H384V320h-160v160z\"]\n};\nvar vsEyeClosed = {\n prefix: \"vs\",\n iconName: \"eye-closed\",\n icon: [512, 512, [], \"f000\", \"M256 64c-48 0 -89.6 12.8 -124.8 38.4l25.6 22.4C185.6 105.6 217.6 96 256 96c105.6 0 192 86.4 192 192h32c0 -124.8 -99.2 -224 -224 -224zM32 96l51.2 48C51.2 182.4 32 233.6 32 288h32c0 -48 16 -89.6 44.8 -121.6l70.4 64C166.4 246.4 160 265.6 160 288c0 54.4 41.6 96 96 96 25.6 0 48 -9.6 64 -25.6l96 89.6 22.4 -22.4 -384 -352L32 96zm169.6 156.8l92.8 86.4c-9.6 6.4 -22.4 12.8 -38.4 12.8 -35.2 0 -64 -28.8 -64 -64 0 -12.8 3.2 -25.6 9.6 -35.2zM352 304l-32 -28.8c-6.4 -25.6 -28.8 -48 -57.6 -51.2l-32 -28.8c9.6 -3.2 16 -3.2 25.6 -3.2 54.4 0 96 41.6 96 96v16z\"]\n};\nvar vsEye = {\n prefix: \"vs\",\n iconName: \"eye\",\n icon: [512, 512, [], \"f000\", \"M32 320c0 -124.8 99.2 -224 224 -224s224 99.2 224 224h-32c0 -105.6 -86.4 -192 -192 -192s-192 86.4 -192 192H32zm128 0c0 -54.4 41.6 -96 96 -96s96 41.6 96 96 -41.6 96 -96 96 -96 -41.6 -96 -96zm32 0c0 35.2 28.8 64 64 64s64 -28.8 64 -64 -28.8 -64 -64 -64 -64 28.8 -64 64z\"]\n};\nvar vsFeedback = {\n prefix: \"vs\",\n iconName: \"feedback\",\n icon: [512, 512, [], \"f000\", \"M241.568 322.496c14.72 5.824 28.16 13.568 40.256 23.2 12.096 9.6 22.432 20.8 31.04 33.472a154.528 154.528 0 0 1 27.136 86.848V480H312v-14.016a124.608 124.608 0 0 0 -36.96 -89.024 129.728 129.728 0 0 0 -40.032 -26.88 124.736 124.736 0 0 0 -49.024 -10.08A124.608 124.608 0 0 0 96.96 376.96a129.92 129.92 0 0 0 -26.88 40.032c-6.592 15.168 -9.92 31.52 -10.08 48.992V480H32v-14.016a151.168 151.168 0 0 1 27.136 -86.816 157.376 157.376 0 0 1 71.328 -56.64 95.808 95.808 0 0 1 -17.76 -15.776 100.992 100.992 0 0 1 -13.344 -19.264 94.144 94.144 0 0 1 -8.32 -21.856 107.04 107.04 0 0 1 -3.04 -23.648c0 -13.536 2.56 -26.24 7.68 -38.048a99.04 99.04 0 0 1 52.032 -52.064 98.144 98.144 0 0 1 76.352 -0.224 99.04 99.04 0 0 1 52.064 52.064 98.144 98.144 0 0 1 5.024 61.696c-1.92 7.584 -4.736 14.88 -8.512 21.888a112.192 112.192 0 0 1 -13.344 19.456c-5.12 5.984 -11.04 11.2 -17.728 15.744zM185.984 312c9.632 0 18.688 -1.824 27.136 -5.44a70.208 70.208 0 0 0 37.184 -37.216c3.808 -8.608 5.696 -17.728 5.696 -27.328a68.416 68.416 0 0 0 -20.576 -49.216 76.256 76.256 0 0 0 -22.304 -15.104 65.536 65.536 0 0 0 -27.136 -5.696c-9.6 0 -18.656 1.824 -27.104 5.44a70.976 70.976 0 0 0 -37.44 37.44c-3.616 8.448 -5.44 17.504 -5.44 27.136 0 9.6 1.824 18.656 5.44 27.104 3.68 8.448 8.64 15.904 14.912 22.304a69.376 69.376 0 0 0 49.664 20.576zM480 32v224h-56l-84 84V256H312v-28h56v44.416l44.416 -44.416h39.584v-168h-280v50.304a232.16 232.16 0 0 0 -14.016 2.208 83.84 83.84 0 0 0 -13.984 3.936V32H480z\"]\n};\nvar vsFileBinary = {\n prefix: \"vs\",\n iconName: \"file-binary\",\n icon: [512, 512, [], \"f000\", \"M338.24 36.48l104.96 105.6 4.8 11.52v310.4l-16 16h-352l-16 -16v-416l16 -16h247.04l11.2 4.48zM96 64v384h320V160l-96 -96H96zm46.72 129.664c0 41.184 14.656 61.76 43.968 61.76 14.624 0 25.824 -5.536 33.6 -16.64 7.872 -11.136 11.776 -27.104 11.776 -47.968C232.064 148.928 217.76 128 189.12 128c-15.072 0 -26.592 5.6 -34.56 16.832 -7.904 11.2 -11.84 27.456 -11.84 48.832zm27.584 -0.704c0 -29.504 5.856 -44.256 17.6 -44.256 11.008 0 16.512 14.336 16.512 42.976s-5.632 42.976 -16.864 42.976c-11.52 0 -17.28 -13.888 -17.28 -41.696zm101.984 60.352h77.92v-21.504h-25.344V128l-53.28 10.752v21.984l26.24 -5.664v76.736h-25.536v21.504zm-42.784 160H151.552v-21.504h25.536V315.072l-26.24 5.664v-21.984L204.16 288v103.808h25.344v21.472zm33.12 -61.792c0 41.184 14.656 61.76 44 61.76 14.624 0 25.824 -5.536 33.6 -16.64 7.84 -11.136 11.776 -27.104 11.776 -47.968 0 -41.888 -14.336 -62.816 -42.976 -62.816 -15.04 0 -26.56 5.6 -34.56 16.832 -7.872 11.2 -11.84 27.456 -11.84 48.832zm27.584 -0.704c0 -29.504 5.888 -44.256 17.6 -44.256 11.008 0 16.512 14.336 16.512 42.976s-5.6 42.976 -16.832 42.976c-11.52 0 -17.28 -13.888 -17.28 -41.696z\"]\n};\nvar vsFileCode = {\n prefix: \"vs\",\n iconName: \"file-code\",\n icon: [512, 512, [], \"f000\", \"M338.24 36.48l104.96 105.6 4.8 11.52v310.4l-16 16h-352l-16 -16v-416l16 -16h247.04l11.2 4.48zM320 160h96l-96 -96v96zM96 64v384h320V192H304L288 176V64H96zm65.984 241.056l58.144 -58.496L197.44 224 128 293.728v22.624l69.472 69.568 22.624 -22.624 -58.112 -58.24zM281.6 246.848l22.4 -22.688 70.048 69.6v22.688L304 385.984l-22.56 -22.688 58.592 -58.24L281.6 246.848z\"]\n};\nvar vsFileMedia = {\n prefix: \"vs\",\n iconName: \"file-media\",\n icon: [512, 512, [], \"f000\", \"M64 64h192v112l16 16H384v32h32V153.6l-4.8 -11.52 -104.96 -105.6L295.04 32H48l-16 16v416l16 16H160v-32H64V64zm224 0l96 96H288V64zm176 192h-256l-16 16v192l16 16h256l16 -16v-192l-16 -16zM448 288v128l-52.16 -51.2h-22.72l-37.12 37.44 -68.16 -68.16h-22.72L224 355.2V288h224zm-89.6 136.64l25.92 -25.92L433.6 448h-51.84l-23.36 -23.36zM224 448v-47.68l32 -32L336.64 448H224zm176 -112a16 16 0 1 0 0 -32 16 16 0 0 0 0 32z\"]\n};\nvar vsFilePdf = {\n prefix: \"vs\",\n iconName: \"file-pdf\",\n icon: [512, 512, [], \"f000\", \"M443.2 142.08l-104.96 -105.6 -11.2 -4.48H80l-16 16V224h32V64h192v112l16 16H416v32h32V153.6l-4.8 -11.52zM320 160V64l96 96h-96zM80 256l-16 16v192l16 16h352l16 -16v-192l-16 -16h-352zM416 416v32H96V288h320v128zm-256 -32h-10.24v32H128v-96h33.92c24 0 36.16 11.52 36.16 32a30.08 30.08 0 0 1 -10.24 23.04A42.56 42.56 0 0 1 160 384zm-1.92 -46.4h-8.32v29.76h8.32c11.52 0 17.28 -5.12 17.28 -15.04 0 -9.92 -5.76 -14.72 -17.28 -14.72zM288 402.56a47.36 47.36 0 0 0 14.08 -35.84c0 -32 -16.96 -46.72 -51.2 -46.72H216.96v96h33.92A51.2 51.2 0 0 0 288 402.56zm-49.6 -4.16v-60.8h10.56a30.08 30.08 0 0 1 22.4 8 29.12 29.12 0 0 1 8 21.44 32 32 0 0 1 -8 23.04 30.08 30.08 0 0 1 -22.08 8.32h-10.88zm142.4 -19.52h-31.04V416h-21.76v-96h55.68v17.6h-33.92v23.68h31.04v17.6z\"]\n};\nvar vsFileSubmodule = {\n prefix: \"vs\",\n iconName: \"file-submodule\",\n icon: [512, 512, [], \"f000\", \"M64 352h32V223.68H64V352zm32 -160.32V176l16 -16h141.76l13.76 8 13.76 24h182.72l16 16v256l-16 16h-352l-16 -16V384H48l-16 -16v-288l16 -16h141.44l14.08 8 13.76 24h182.72l16 16V192l-32 -0.96V128H208l-13.76 -8L180.48 96H64v95.68h32zm162.24 24.32L244.48 192H128v96h100.8l13.12 -23.68L256 256h192V224H272l-13.76 -8zM238.4 320H128v128h320V288H265.6l-13.12 23.68 -14.08 8.32z\"]\n};\nvar vsFileSymlinkDirectory = {\n prefix: \"vs\",\n iconName: \"file-symlink-directory\",\n icon: [512, 512, [], \"f000\", \"M246.72 96h217.28l16.32 16v320l-16 16h-416l-16 -16v-352l16 -16h160l11.2 4.8 27.2 27.2zm200.96 320v-48.32l0.32 -128v-48H246.4l-27.52 27.52 -11.2 4.8H64v192h383.68zm-208 -256h208l0.32 -31.68H240l-11.52 -4.8 -27.2 -27.2H64v96h136.96l27.52 -27.52 11.2 -4.8zm73.28 130.24L269.44 246.4l23.68 -22.08 71.04 71.04v22.72l-73.28 70.72 -22.4 -23.04 44.8 -43.2H269.44a64 64 0 0 0 -43.2 19.52A57.6 57.6 0 0 0 209.28 384h-32a88.32 88.32 0 0 1 25.92 -64 96 96 0 0 1 64 -29.76h45.76z\"]\n};\nvar vsFileSymlinkFile = {\n prefix: \"vs\",\n iconName: \"file-symlink-file\",\n icon: [512, 512, [], \"f000\", \"M338.24 36.48l104.96 105.6 4.8 11.52v310.4l-16 16H320v-32h96V192H304L288 176V64H96v128H64V48l16 -16h247.04l11.2 4.48zM320 160h96l-96 -96v96zM272 224h-224l-16 16v224l16 16h224l16 -16v-224L272 224zM256 448H64V256h192v192zM224 304v96H192v-57.376l-84.672 84.704 -22.656 -22.656L169.376 320H112.96V288H208l16 16z\"]\n};\nvar vsFileZip = {\n prefix: \"vs\",\n iconName: \"file-zip\",\n icon: [512, 512, [], \"f000\", \"M80 32h352l16 16v160l-4.8 11.2 -27.2 27.52v217.28l-16 16h-320l-16 -16v-416l16 -16zM192 64H160v64h32V64zm0 384h128V245.76l-27.2 -27.2L288 207.04V64H224v80l-16 16H192v32H160V160h-16L128 144V64H96v384h64v-32h32v32zm0 -64v32h32v-32H192zm0 -32v32H160v-32h32zm0 -32h32v32H192v-32zm0 -32v32H160V288h32zm0 -32h32v32H192V256zm0 -32v32H160V224h32zm0 0h32V192H192v32zm196.8 4.8l27.2 -27.52V64h-96v136.64l27.2 27.2 4.8 11.2V448h32V240l4.8 -11.2z\"]\n};\nvar vsFile = {\n prefix: \"vs\",\n iconName: \"file\",\n icon: [512, 512, [], \"f000\", \"M438.72 137.28l-96 -96L320 32H128L96 64v384l32 32h288l32 -32V160l-9.28 -22.72zM416 448H128V64h160v128h128v256zm-96 -288V64l96 96h-96z\"]\n};\nvar vsFiles = {\n prefix: \"vs\",\n iconName: \"files\",\n icon: [512, 512, [], \"f000\", \"M373.333 0h-192L149.333 32V128H53.333L21.333 160v321.493L53.333 512h257.493L341.333 481.493V384h100.267l27.733 -30.507V96L373.333 0zm0 45.227l50.773 50.773H373.333V45.227zm-64 434.773h-256v-320H149.333v193.493L181.333 384h128v96zm128 -128h-256v-320H341.333V128h96v224z\"]\n};\nvar vsFilterFilled = {\n prefix: \"vs\",\n iconName: \"filter-filled\",\n icon: [512, 512, [], \"f000\", \"M480 64v53.44l-160 152.288V448H192V269.728l-160 -152.32V64h448z\"]\n};\nvar vsFilter = {\n prefix: \"vs\",\n iconName: \"filter\",\n icon: [512, 512, [], \"f000\", \"M480 64v53.44l-160 152.288V448H192V269.728l-160 -152.32V64h448zM224 256v160h64V256l160 -152.32V96H64v7.68L224 256z\"]\n};\nvar vsFlame = {\n prefix: \"vs\",\n iconName: \"flame\",\n icon: [512, 512, [], \"f000\", \"M292.16 480l-16.96 -24.64a59.2 59.2 0 0 0 -8.96 -81.28 112.32 112.32 0 0 1 -38.08 -64c-49.92 71.36 -24 110.72 0 145.6l-17.6 24.32A140.8 140.8 0 0 1 96 334.72S89.28 265.6 168.96 198.08c0 0 90.24 -83.52 58.88 -145.28L250.56 32a210.24 210.24 0 0 1 83.52 222.08 82.24 82.24 0 0 0 17.92 -25.92l27.84 -2.24c2.24 3.84 58.88 93.76 28.48 169.6A151.04 151.04 0 0 1 292.16 480zm-64 -222.4l27.84 12.48a96 96 0 0 0 29.44 79.36 84.48 84.48 0 0 1 32 89.6A103.712 103.712 0 0 0 377.6 384a155.84 155.84 0 0 0 -13.12 -116.16 59.2 59.2 0 0 1 -58.88 27.52l-11.2 -21.76a169.92 169.92 0 0 0 -28.48 -185.6C261.44 155.84 192 218.56 189.76 222.08 123.52 278.4 128 330.56 128 332.8a111.04 111.04 0 0 0 50.88 100.48C160 388.48 160 334.72 229.12 257.6h-0.96z\"]\n};\nvar vsFoldDown = {\n prefix: \"vs\",\n iconName: \"fold-down\",\n icon: [512, 512, [], \"f000\", \"M454.624 54.624L432 32l-192 192 -192 -192 -22.624 22.624 203.296 203.328h22.656l203.296 -203.328zm0 192L432 224l-192 192 -192 -192 -22.624 22.624 203.296 203.328h22.656l203.296 -203.328z\"]\n};\nvar vsFoldUp = {\n prefix: \"vs\",\n iconName: \"fold-up\",\n icon: [512, 512, [], \"f000\", \"M32 236.8l22.4 22.4 192 -192 192 192 22.4 -22.4L259.2 32h-22.4L32 236.8zm0 192l22.4 22.4 192 -192 192 192 22.4 -22.4L259.2 224h-22.4L32 428.8z\"]\n};\nvar vsFold = {\n prefix: \"vs\",\n iconName: \"fold\",\n icon: [512, 512, [], \"f000\", \"M382.464 76.192L255.232 203.424 128 76.192 108.16 96l137.152 137.12h19.808L402.24 96l-19.776 -19.808zM124.928 448l130.304 -130.304L385.504 448l19.84 -19.808L265.088 288h-19.808l-140.192 140.192 19.808 19.808z\"]\n};\nvar vsFolderActive = {\n prefix: \"vs\",\n iconName: \"folder-active\",\n icon: [512, 512, [], \"f000\", \"M246.72 96h217.28l16.32 16v144.224A159.904 159.904 0 0 0 448 237.312V191.68H246.08l-27.52 27.52 -11.2 4.8H63.68v192H227.2c2.24 11.136 5.664 21.824 10.112 32H48.32l-16 -16v-352l16 -16h160l11.2 4.8 27.2 27.2zm-7.04 64h208l0.32 -31.68H240l-11.52 -4.8 -27.2 -27.2H64v96h136.96l27.52 -27.52 11.2 -4.8zm73.216 117.568a128 128 0 1 1 142.208 212.864 128 128 0 0 1 -142.208 -212.864zm68.16 159.68l76.384 -101.824 -25.6 -19.2 -66.464 88.608 -41.632 -33.312 -20 24.96 54.528 43.648 22.816 -2.88z\"]\n};\nvar vsFolderLibrary = {\n prefix: \"vs\",\n iconName: \"folder-library\",\n icon: [512, 512, [], \"f000\", \"M246.72 96h217.28l16.32 16V224H448V191.68H246.08l-27.52 27.52 -11.2 4.8H63.68v192H224v32H48.32l-16 -16v-352l16 -16h160l11.2 4.8 27.2 27.2zm-7.04 64h208l0.32 -31.68H240l-11.52 -4.8 -27.2 -27.2H64v96h136.96l27.52 -27.52 11.2 -4.8zM256 256h32v192H256zm64 0h32v192h-32zm64.128 11.264l30.08 -10.944 65.664 180.416 -30.08 10.944z\"]\n};\nvar vsFolderOpened = {\n prefix: \"vs\",\n iconName: \"folder-opened\",\n icon: [512, 512, [], \"f000\", \"M48 448h352l15.36 -11.84 84.16 -224 -15.36 -20.16H448V112l-16 -16H246.72l-27.52 -27.2L208 64h-160l-16 16v352l16 16zM64 96h137.28l27.52 27.2 11.2 4.8H416v64H272l-11.2 4.8 -27.52 27.2H112l-15.04 10.88 -32 98.56L64 96zm324.16 320H70.08l53.44 -160H240l11.2 -4.8 27.52 -27.2h185.28l-75.84 192z\"]\n};\nvar vsFolder = {\n prefix: \"vs\",\n iconName: \"folder\",\n icon: [512, 512, [], \"f000\", \"M464 96H246.72l-27.2 -27.2L208.32 64h-160l-16 16v352l16 16h416l16 -16v-320L464 96zm-16.32 271.68V416h-384V224h143.68l11.2 -4.8 27.52 -27.52H448v48l-0.32 128zm0 -207.68h-208l-11.2 4.8 -27.52 27.52H64v-96h137.28l27.2 27.2 11.52 4.8H448l-0.32 31.68z\"]\n};\nvar vsGear = {\n prefix: \"vs\",\n iconName: \"gear\",\n icon: [512, 512, [], \"f000\", \"M291.2 140.8L275.2 64H236.8l-16 76.8 -22.4 9.6 -64 -41.6 -28.8 25.6 41.6 64 -6.4 22.4 -76.8 16v38.4l76.8 16 9.6 25.6 -41.6 64 25.6 25.6 64 -41.6 25.6 9.6 12.8 73.6h38.4l16 -76.8 25.6 -9.6 64 41.6 25.6 -25.6 -41.6 -64 9.6 -25.6 73.6 -12.8V236.8l-76.8 -16 -9.6 -25.6 41.6 -64 -25.6 -25.6 -64 41.6 -22.4 -6.4zM300.8 32l16 76.8L384 67.2l64 64 -44.8 67.2 76.8 12.8v89.6l-76.8 16L448 384l-64 64 -67.2 -44.8 -16 76.8H211.2l-16 -76.8L128 444.8l-64 -64 44.8 -67.2L32 300.8V211.2l76.8 -16L67.2 128l64 -64 67.2 44.8 12.8 -76.8h89.6zm19.2 224c0 35.2 -28.8 64 -64 64s-64 -28.8 -64 -64 28.8 -64 64 -64 64 28.8 64 64zM256 288c19.2 0 32 -12.8 32 -32s-12.8 -32 -32 -32 -32 12.8 -32 32 12.8 32 32 32z\"]\n};\nvar vsGift = {\n prefix: \"vs\",\n iconName: \"gift\",\n icon: [512, 512, [], \"f000\", \"M432 128h-51.2c3.2 -12.8 3.2 -25.6 3.2 -38.4 -3.2 -9.6 -6.4 -19.2 -12.8 -28.8 -6.4 -9.6 -12.8 -16 -22.4 -19.2 -9.6 -3.2 -19.2 -9.6 -28.8 -9.6 -9.6 0 -19.2 0 -28.8 6.4 -22.4 6.4 -38.4 22.4 -51.2 41.6 -12.8 -19.2 -28.8 -35.2 -51.2 -41.6 -9.6 -3.2 -19.2 -6.4 -28.8 -6.4 -9.6 0 -19.2 3.2 -28.8 9.6 -9.6 3.2 -16 9.6 -22.4 19.2 -6.4 6.4 -9.6 19.2 -12.8 28.8 0 12.8 0 25.6 3.2 38.4H48l-16 16v288l16 16h384l16 -16v-288l-16 -16zM224 416H64V160h160v256zm0 -288H128v-6.4c-3.2 -9.6 -3.2 -16 -3.2 -25.6 3.2 -6.4 3.2 -12.8 9.6 -16 3.2 -6.4 9.6 -9.6 16 -12.8 3.2 -3.2 9.6 -3.2 16 -3.2s12.8 0 19.2 3.2c9.6 3.2 19.2 9.6 25.6 19.2 6.4 9.6 12.8 19.2 12.8 32V128zm32 -9.6c0 -12.8 6.4 -22.4 12.8 -32 6.4 -9.6 16 -16 25.6 -19.2 6.4 -3.2 12.8 -3.2 19.2 -3.2 6.4 0 12.8 0 19.2 3.2 6.4 3.2 9.6 6.4 16 12.8 3.2 3.2 3.2 9.6 6.4 16 0 9.6 0 16 -3.2 25.6 0 3.2 0 3.2 -3.2 6.4H256v-9.6zm160 297.6H256V160h160v256z\"]\n};\nvar vsGistSecret = {\n prefix: \"vs\",\n iconName: \"gist-secret\",\n icon: [512, 512, [], \"f000\", \"M96 448h128v29.12l2.88 2.88H80l-16 -16v-416l16 -16h247.04l11.2 4.48 104.96 105.6 4.8 11.52v81.28a99.2 99.2 0 0 0 -32 -30.08V192H304L288 176V64H96v384zm320 -288l-96 -96v96h96zm16 128v32h32l16 16v128l-16 16h-192l-16 -16v-128l16 -16h32V288a64 64 0 0 1 128 0zm-86.624 -22.624A32 32 0 0 0 336 288v32h64V288a32 32 0 0 0 -54.624 -22.624zM288 352v96h160v-96H288z\"]\n};\nvar vsGist = {\n prefix: \"vs\",\n iconName: \"gist\",\n icon: [512, 512, [], \"f000\", \"M338.24 36.48l104.96 105.6 4.8 11.52v310.4l-16 16h-352l-16 -16v-416l16 -16h247.04l11.2 4.48zM320 160h96l-96 -96v96zM96 64v384h320V192H304L288 176V64H96zm65.984 241.056l58.144 -58.496L197.44 224 128 293.728v22.624l69.472 69.568 22.624 -22.624 -58.112 -58.24zM281.6 246.848l22.4 -22.688 70.048 69.6v22.688L304 385.984l-22.56 -22.688 58.592 -58.24L281.6 246.848z\"]\n};\nvar vsGitCommit = {\n prefix: \"vs\",\n iconName: \"git-commit\",\n icon: [512, 512, [], \"f000\", \"M351.328 160a109.44 109.44 0 0 0 -64 -32V0h-32v128a112 112 0 0 0 -5.76 220.48h5.76v128h32v-128a98.56 98.56 0 0 0 26.88 -7.36 109.44 109.44 0 0 0 50.24 -41.28 110.72 110.72 0 0 0 -13.12 -139.84zm-22.4 135.68a80.32 80.32 0 0 1 -101.088 9.92 80 80 0 0 1 -29.44 -35.84 79.68 79.68 0 0 1 58.24 -109.12 87.04 87.04 0 0 1 15.68 0 80 80 0 0 1 81.28 80 80.32 80.32 0 0 1 -25.6 56l0.96 -0.96z\"]\n};\nvar vsGitCompare = {\n prefix: \"vs\",\n iconName: \"git-compare\",\n icon: [512, 512, [], \"f000\", \"M236.448 415.68l-40.64 -40.64 21.44 -22.4 68.16 68.16v22.4l-68.16 68.16 -22.72 -22.72L235.168 448h-59.2a79.68 79.68 0 0 1 -80 -80V190.4a82.88 82.88 0 0 1 -40.64 -21.76 80.64 80.64 0 0 1 -17.28 -87.36A80 80 0 0 1 111.968 32a78.4 78.4 0 0 1 32 6.08 79.36 79.36 0 0 1 43.2 43.2c4.256 10.144 6.304 21.056 6.08 32a80 80 0 0 1 -64 78.4v176a48 48 0 0 0 48 48h59.2zm-149.76 -264a48 48 0 0 0 66.56 -66.56 49.6 49.6 0 0 0 -21.76 -17.92 47.68 47.68 0 0 0 -27.52 -2.56 47.68 47.68 0 0 0 -37.76 37.76 47.68 47.68 0 0 0 2.56 27.52c3.744 8.864 9.952 16.416 17.92 21.76zm330.56 201.6c15.36 3.136 29.504 10.72 40.64 21.76a80.32 80.32 0 0 1 9.92 101.088 80 80 0 1 1 -111.04 -110.976c8.608 -5.824 18.272 -9.856 28.48 -11.84V175.68a48 48 0 0 0 -48 -48h-59.2l40.64 40.64 -22.72 22.72 -68.16 -68.16v-22.4l68.16 -68.16 22.72 22.72 -40.64 40.64h59.2a79.68 79.68 0 0 1 80 80v177.6zm-11.232 126.176a48 48 0 0 0 35.2 -74.304 49.6 49.6 0 0 0 -21.76 -17.92 47.68 47.68 0 0 0 -27.488 -2.56 47.68 47.68 0 0 0 -37.76 37.76 47.68 47.68 0 0 0 2.56 27.52 48 48 0 0 0 49.248 29.504z\"]\n};\nvar vsGitMerge = {\n prefix: \"vs\",\n iconName: \"git-merge\",\n icon: [512, 512, [], \"f000\", \"M424.736 247.36a80.32 80.32 0 0 0 -101.088 -9.92 80 80 0 0 0 -29.472 35.84 71.36 71.36 0 0 0 -4.16 14.08 144.64 144.64 0 0 1 -128 -128 71.36 71.36 0 0 0 14.08 -4.16 80 80 0 0 0 49.28 -73.92 78.4 78.4 0 0 0 -6.08 -32A79.36 79.36 0 0 0 176.096 6.08a78.4 78.4 0 0 0 -32 -6.08 80 80 0 0 0 -73.92 49.28 80.64 80.64 0 0 0 17.28 87.36c11.2 10.976 25.28 18.528 40.64 21.76v163.2a77.152 77.152 0 0 0 -28.48 11.84 80 80 0 1 0 111.04 110.976 80 80 0 0 0 13.44 -44.384 78.4 78.4 0 0 0 -6.08 -32 79.36 79.36 0 0 0 -57.92 -47.68v-76.8a176.64 176.64 0 0 0 64 55.36 180.8 180.8 0 0 0 66.88 19.2 80 80 0 0 0 158.4 -15.68 80.32 80.32 0 0 0 -24.64 -55.04zm-262.4 108.16c8.832 3.744 16.384 9.984 21.76 17.92a48 48 0 0 1 -66.56 66.56 49.6 49.6 0 0 1 -17.92 -21.76 47.68 47.68 0 0 1 -2.56 -27.52 47.68 47.68 0 0 1 37.76 -37.76 47.68 47.68 0 0 1 27.52 2.56zM144.096 128a48 48 0 0 1 -44.48 -29.76 47.68 47.68 0 0 1 -2.56 -27.52 47.68 47.68 0 0 1 37.76 -37.76 47.68 47.68 0 0 1 27.52 2.56A48 48 0 0 1 144.096 128zm257.92 209.92a48 48 0 0 1 -78.4 -15.68 47.68 47.68 0 0 1 -2.56 -27.52 47.68 47.68 0 0 1 37.76 -37.76 47.68 47.68 0 0 1 27.52 2.56 47.968 47.968 0 0 1 15.68 78.4z\"]\n};\nvar vsGitPullRequestClosed = {\n prefix: \"vs\",\n iconName: \"git-pull-request-closed\",\n icon: [512, 512, [], \"f000\", \"M179.712 157.696a79.584 79.584 0 0 1 -35.808 29.504c-4.736 1.92 -14.656 4.416 -14.656 4.416v160.256a80.32 80.32 0 0 1 50.528 33.984c8.736 13.184 13.408 28.64 13.408 44.416 0.256 10.976 -1.824 21.888 -6.08 32A79.52 79.52 0 0 1 112 511.488a79.36 79.36 0 0 1 -44.416 -13.44A79.552 79.552 0 0 1 33.6 416c3.04 -15.552 10.592 -29.824 21.76 -41.056 11.168 -10.976 25.28 -18.528 40.608 -21.76V190.368a83.2 83.2 0 0 1 -40.608 -21.76 80.096 80.096 0 0 1 -21.76 -41.056 79.584 79.584 0 0 1 33.92 -82.08A79.68 79.68 0 0 1 112 32a80.128 80.128 0 0 1 57.824 23.328 79.776 79.776 0 0 1 23.328 57.92c0.064 15.808 -4.608 31.264 -13.44 44.448zm-24.192 251.552a48 48 0 0 0 -17.664 -18.528 46.4 46.4 0 0 0 -24.64 -6.72 47.84 47.84 0 0 0 -47.04 57.28 47.776 47.776 0 0 0 37.76 37.728c9.216 1.856 18.752 0.96 27.52 -2.56 8.832 -3.744 16.384 -9.984 21.76 -17.92 4.8 -7.232 7.52 -15.68 7.968 -24.32a48.32 48.32 0 0 0 -5.664 -24.96zM86.656 151.712c7.904 5.152 17.152 8 26.56 8 8.672 0 17.216 -2.4 24.64 -6.752a48.448 48.448 0 0 0 23.328 -43.52 48.416 48.416 0 0 0 -8 -24.32 49.632 49.632 0 0 0 -21.76 -17.888 47.68 47.68 0 0 0 -27.52 -2.56 47.808 47.808 0 0 0 -37.728 37.76c-1.856 9.216 -0.96 18.752 2.56 27.52 3.744 8.832 9.984 16.384 17.92 21.76zm330.528 201.472c15.36 3.104 29.504 10.72 40.608 21.76 14.912 15.04 23.328 35.424 23.2 56.512 0.064 15.776 -4.608 31.264 -13.44 44.416a80 80 0 0 1 -123.136 12.288 80 80 0 0 1 12.224 -123.136 76.48 76.48 0 0 1 28.48 -11.84V239.648h32.064v113.536zm17.824 112.256a47.776 47.776 0 0 0 6.112 -60.416 49.632 49.632 0 0 0 -21.76 -17.92 47.68 47.68 0 0 0 -27.52 -2.56 47.776 47.776 0 0 0 -37.728 37.76 47.68 47.68 0 0 0 2.56 27.52 47.904 47.904 0 0 0 78.336 15.68zM374.016 108.8L320 162.816l22.624 22.624 54.016 -54.016 53.984 54.016 22.624 -22.624L419.296 108.8l54.016 -53.984 -22.656 -22.624 -53.984 53.984 -54.016 -53.984 -22.624 22.624L374.016 108.8z\"]\n};\nvar vsGitPullRequestCreate = {\n prefix: \"vs\",\n iconName: \"git-pull-request-create\",\n icon: [512, 512, [], \"f000\", \"M179.712 157.696a79.584 79.584 0 0 1 -35.808 29.504c-4.736 1.92 -14.656 4.416 -14.656 4.416v160.256a80.32 80.32 0 0 1 50.528 33.984c8.736 13.184 13.408 28.64 13.408 44.416 0.256 10.976 -1.824 21.888 -6.08 32A79.52 79.52 0 0 1 112 511.488a79.424 79.424 0 0 1 -44.416 -13.408A79.584 79.584 0 0 1 33.6 416c3.04 -15.552 10.592 -29.824 21.76 -41.056 11.168 -10.976 25.28 -18.528 40.608 -21.76V190.368a83.2 83.2 0 0 1 -40.608 -21.76 80.096 80.096 0 0 1 -21.76 -41.056 79.584 79.584 0 0 1 33.92 -82.08A79.68 79.68 0 0 1 112 32a80.128 80.128 0 0 1 57.824 23.328 79.776 79.776 0 0 1 23.328 57.92c0.064 15.808 -4.608 31.296 -13.44 44.448zm-24.192 251.552a48 48 0 0 0 -17.664 -18.528 46.4 46.4 0 0 0 -24.64 -6.72 47.84 47.84 0 0 0 -47.04 57.28 47.776 47.776 0 0 0 37.76 37.728c9.216 1.856 18.752 0.96 27.52 -2.56 8.832 -3.744 16.384 -9.984 21.76 -17.92 4.8 -7.232 7.52 -15.68 7.968 -24.32a48.32 48.32 0 0 0 -5.664 -24.96zM86.656 151.712c7.904 5.152 17.152 8 26.56 8 8.672 0 17.216 -2.4 24.64 -6.752a48.448 48.448 0 0 0 23.328 -43.488 48.416 48.416 0 0 0 -8 -24.32 49.632 49.632 0 0 0 -21.76 -17.92 47.68 47.68 0 0 0 -27.52 -2.56 47.808 47.808 0 0 0 -37.728 37.76c-1.856 9.216 -0.96 18.752 2.56 27.52 3.744 8.832 9.984 16.384 17.92 21.76zM417.184 224h-32.064V175.68a48 48 0 0 0 -48 -48H277.984l40.608 40.64 -22.72 22.688L227.744 122.88v-22.4l68.16 -68.16 22.72 22.752 -40.608 40.64h59.2a79.488 79.488 0 0 1 73.984 49.312c4 9.664 6.048 20.096 5.984 30.624V224zM416 512h-32v-96H288v-32h96V288h32v96h96v32h-96v96z\"]\n};\nvar vsGitPullRequestDraft = {\n prefix: \"vs\",\n iconName: \"git-pull-request-draft\",\n icon: [512, 512, [], \"f000\", \"M143.904 187.2a79.872 79.872 0 0 0 49.216 -73.92 79.776 79.776 0 0 0 -49.216 -75.2A80.128 80.128 0 0 0 111.968 32a79.68 79.68 0 0 0 -44.416 13.44A79.584 79.584 0 0 0 33.6 127.584c3.04 15.552 10.592 29.824 21.76 41.056a83.2 83.2 0 0 0 40.608 21.76v162.816c-15.36 3.232 -29.44 10.784 -40.608 21.76 -11.168 11.2 -18.72 25.504 -21.76 41.056a79.552 79.552 0 0 0 33.984 82.08 79.36 79.36 0 0 0 44.416 13.408 78.08 78.08 0 0 0 32 -6.08 79.52 79.52 0 0 0 49.216 -75.168 80.32 80.32 0 0 0 -63.936 -78.4V191.648s9.92 -2.496 14.656 -4.416zm-6.048 203.52a48 48 0 0 1 15.36 67.84 49.632 49.632 0 0 1 -21.76 17.888 47.744 47.744 0 0 1 -27.52 2.56 47.584 47.584 0 0 1 -37.76 -37.76 47.68 47.68 0 0 1 2.56 -27.52c3.744 -8.832 9.984 -16.384 17.92 -21.76a47.68 47.68 0 0 1 26.56 -8c8.672 -0.096 17.216 2.24 24.64 6.752zm-24.64 -231.04a48.64 48.64 0 0 1 -26.56 -8 49.632 49.632 0 0 1 -17.92 -21.76 47.712 47.712 0 0 1 -2.56 -27.52 47.552 47.552 0 0 1 37.76 -37.728 47.68 47.68 0 0 1 27.52 2.56c8.832 3.744 16.384 9.984 21.76 17.92A47.68 47.68 0 0 1 155.52 134.4a48.64 48.64 0 0 1 -17.664 18.528c-7.424 4.352 -15.968 6.72 -24.64 6.72zm368.512 272.32a80 80 0 1 1 -160 0 80 80 0 0 1 160 0zm-80 48a48 48 0 1 0 0 -96 48 48 0 0 0 0 96z\"]\n};\nvar vsGitPullRequest = {\n prefix: \"vs\",\n iconName: \"git-pull-request\",\n icon: [512, 512, [], \"f000\", \"M179.712 157.696a79.584 79.584 0 0 1 -35.808 29.504c-4.736 1.92 -14.656 4.416 -14.656 4.416v160.256a80.32 80.32 0 0 1 50.528 33.984c8.736 13.184 13.408 28.64 13.408 44.416 0.256 10.976 -1.824 21.888 -6.08 32A79.52 79.52 0 0 1 112 511.488a79.424 79.424 0 0 1 -44.416 -13.408A79.584 79.584 0 0 1 33.6 416c3.04 -15.552 10.592 -29.824 21.76 -41.056 11.168 -10.976 25.28 -18.528 40.608 -21.76V190.368a83.2 83.2 0 0 1 -40.608 -21.76 80.096 80.096 0 0 1 -21.76 -41.056 79.584 79.584 0 0 1 33.92 -82.08A79.68 79.68 0 0 1 112 32a80.128 80.128 0 0 1 57.824 23.328 79.776 79.776 0 0 1 23.328 57.92c0.064 15.808 -4.608 31.296 -13.44 44.448zm-24.192 251.552a48 48 0 0 0 -17.664 -18.528 46.4 46.4 0 0 0 -24.64 -6.72 47.84 47.84 0 0 0 -47.04 57.28 47.776 47.776 0 0 0 37.76 37.728c9.216 1.856 18.752 0.96 27.52 -2.56 8.832 -3.744 16.384 -9.984 21.76 -17.92 4.8 -7.232 7.52 -15.68 7.968 -24.32a48.32 48.32 0 0 0 -5.664 -24.96zM86.656 151.712c7.904 5.152 17.152 8 26.56 8 8.672 0 17.216 -2.4 24.64 -6.752a48.448 48.448 0 0 0 23.328 -43.488 48.416 48.416 0 0 0 -8 -24.32 49.632 49.632 0 0 0 -21.76 -17.92 47.68 47.68 0 0 0 -27.52 -2.56 47.808 47.808 0 0 0 -37.728 37.76c-1.856 9.216 -0.96 18.752 2.56 27.52 3.744 8.832 9.984 16.384 17.92 21.76zm330.528 201.472c15.36 3.104 29.504 10.72 40.608 21.76 14.912 15.04 23.328 35.424 23.2 56.512 0.064 15.776 -4.608 31.264 -13.44 44.416a79.968 79.968 0 0 1 -145.024 -28.768 80 80 0 0 1 34.144 -82.08c8.544 -5.856 18.272 -9.856 28.448 -11.84V175.648a48 48 0 0 0 -48 -47.968H277.984l40.608 40.64 -22.72 22.688L227.744 122.88v-22.4l68.16 -68.16 22.72 22.752 -40.608 40.64h59.2a79.488 79.488 0 0 1 73.984 49.312c4 9.664 6.048 20.096 5.984 30.624v177.536zm17.824 112.288a47.776 47.776 0 0 0 6.112 -60.48 49.664 49.664 0 0 0 -21.76 -17.888 47.68 47.68 0 0 0 -27.52 -2.56 47.776 47.776 0 0 0 -37.728 37.76 47.68 47.68 0 0 0 2.56 27.52 47.872 47.872 0 0 0 78.336 15.68z\"]\n};\nvar vsGithubAction = {\n prefix: \"vs\",\n iconName: \"github-action\",\n icon: [512, 512, [], \"f000\", \"M97.28 320h82.56l20.8 32H81.28l-16 -16v-288l16 -16h384l16 16v152.64l-32 -56V64h-352v256zm177.28 32l-45.12 111.04h70.4L480 278.4 456.64 224h-52.16l26.24 -46.72L404.16 128H312.32l-29.44 18.88 -72.96 160L239.04 352h35.52zm37.76 -192h91.84l-59.84 96h112.32l-184.32 186.88L326.4 320H239.04l73.28 -160zM222.4 224H129.28V192H236.8l-14.4 32zm-28.8 64H129.28V256H208l-14.4 32z\"]\n};\nvar vsGithubAlt = {\n prefix: \"vs\",\n iconName: \"github-alt\",\n icon: [512, 512, [], \"f000\", \"M448.747 112.149c19.413 23.296 29.099 50.475 29.099 81.536 0 112.576 -64.043 145.579 -124.224 155.285 7.765 13.589 9.707 29.12 9.707 44.651v79.573c0 9.707 -5.824 15.531 -13.589 15.531a15.317 15.317 0 0 1 -15.531 -15.531v-79.573a53.269 53.269 0 0 0 -15.531 -44.651l9.707 -25.237c60.181 -7.765 122.304 -27.179 122.304 -131.989 0 -25.237 -9.707 -48.533 -27.179 -67.947l-3.883 -15.509a86.187 86.187 0 0 0 1.92 -58.24c-9.685 1.92 -29.099 5.824 -62.08 29.12l-11.669 1.92a283.883 283.883 0 0 0 -139.733 0l-11.669 -1.92C161.493 57.813 142.08 51.989 132.352 51.989c-5.824 19.413 -5.824 40.747 1.92 58.24l-3.861 15.509c-19.413 19.413 -29.12 44.651 -29.12 67.947 0 102.869 58.24 124.224 122.283 131.989l7.765 25.237c-11.648 11.648 -17.472 27.179 -15.531 42.709v81.515a15.317 15.317 0 0 1 -15.531 15.531 15.317 15.317 0 0 1 -15.531 -15.531V430.507c-64.043 13.589 -89.28 -19.413 -108.693 -44.629 -9.707 -11.648 -17.472 -21.355 -27.179 -23.296 -1.92 -1.941 -7.765 -9.707 -5.824 -17.472 1.941 -7.765 9.707 -13.589 17.493 -9.707 19.413 3.883 31.04 19.413 42.667 33.003 17.493 23.296 34.965 44.629 87.36 33.003v-7.765c-1.92 -15.531 1.941 -31.061 9.707 -44.651 -58.24 -11.648 -126.165 -44.651 -126.165 -155.285 0 -31.061 9.707 -58.24 29.12 -81.536 -5.824 -27.157 -3.883 -56.277 5.824 -79.573l9.707 -7.765C122.645 22.891 149.824 17.067 206.08 51.989a291.691 291.691 0 0 1 141.696 0C402.155 15.104 431.275 20.907 435.157 22.869l9.707 7.765c9.707 27.179 11.648 54.357 3.883 81.515z\"]\n};\nvar vsGithubInverted = {\n prefix: \"vs\",\n iconName: \"github-inverted\",\n icon: [512, 512, [], \"f000\", \"M255.232 0A255.264 255.264 0 0 0 0 255.232c0 112.704 73.6 208.224 173.792 242.688 12.544 1.568 17.216 -6.272 17.216 -12.544v-43.84c-70.432 15.68 -86.08 -34.432 -86.08 -34.432 -10.976 -29.76 -28.192 -37.6 -28.192 -37.6 -23.488 -15.648 1.536 -15.648 1.536 -15.648 25.056 1.568 39.168 26.624 39.168 26.624 23.488 39.136 59.488 28.16 73.6 21.92 1.536 -17.216 9.376 -28.16 15.648 -34.432 -56.384 -6.272 -115.872 -28.192 -115.872 -126.848 0 -28.16 9.376 -50.112 26.624 -68.896 -1.6 -4.704 -10.976 -31.296 3.136 -65.76 0 0 21.92 -6.272 70.432 26.624 20.352 -6.272 42.304 -7.84 64.224 -7.84s43.84 3.136 64.192 7.84c48.544 -32.864 70.464 -26.624 70.464 -26.624 14.08 34.464 4.672 61.056 3.104 67.328a101.12 101.12 0 0 1 26.624 68.896c0 98.656 -59.52 119.008 -115.84 125.28 9.376 7.808 17.216 23.456 17.216 46.944v70.464c0 6.272 4.672 14.08 17.216 12.544A255.488 255.488 0 0 0 512 255.232C510.432 114.304 396.16 0 255.232 0z\"]\n};\nvar vsGithub = {\n prefix: \"vs\",\n iconName: \"github\",\n icon: [512, 512, [], \"f000\", \"M256 0a256 256 0 1 0 0 512 256 256 0 0 0 0 -512zm67.477 464.704h-1.984a10.944 10.944 0 0 1 -8.149 -2.987 10.944 10.944 0 0 1 -2.987 -7.936v-29.995c0.128 -9.963 0.213 -20.053 0.213 -30.208a78.784 78.784 0 0 0 -3.221 -21.931 39.083 39.083 0 0 0 -11.563 -18.667 170.965 170.965 0 0 0 43.477 -10.048 86.421 86.421 0 0 0 31.275 -20.565c8.683 -9.109 15.147 -20.117 18.88 -32.128a144.427 144.427 0 0 0 6.4 -45.44 88.277 88.277 0 0 0 -5.547 -31.488 83.029 83.029 0 0 0 -16.96 -27.392 59.947 59.947 0 0 0 3.456 -12.416c0.704 -4.267 1.067 -8.576 1.067 -12.885 0 -5.547 -0.64 -11.093 -1.92 -16.491a113.259 113.259 0 0 0 -4.715 -16.277 6.251 6.251 0 0 0 -2.368 -0.427h-2.347c-4.907 0.043 -9.728 0.853 -14.379 2.368a113.92 113.92 0 0 0 -14.997 5.547 138.731 138.731 0 0 0 -14.101 7.317c-4.587 2.709 -8.64 5.312 -12.224 7.723a204.331 204.331 0 0 0 -109.717 0 288.149 288.149 0 0 0 -12.203 -7.723 128.469 128.469 0 0 0 -14.336 -7.296 96.341 96.341 0 0 0 -15.04 -5.568 46.997 46.997 0 0 0 -14.123 -2.368h-2.347a6.187 6.187 0 0 0 -2.347 0.427 124.672 124.672 0 0 0 -4.907 16.277c-1.152 5.419 -1.707 10.944 -1.728 16.491 0 4.309 0.363 8.619 1.088 12.885 0.704 4.245 1.835 8.405 3.413 12.416A82.944 82.944 0 0 0 121.643 213.333a88.363 88.363 0 0 0 -5.611 31.488 146.581 146.581 0 0 0 6.229 45.227c3.861 12.011 10.304 23.04 18.859 32.341 8.853 9.003 19.52 16 31.275 20.565 13.931 5.333 28.523 8.747 43.371 10.155a38.997 38.997 0 0 0 -9.643 13.504 63.787 63.787 0 0 0 -4.267 15.872 58.752 58.752 0 0 1 -25.067 5.76 38.144 38.144 0 0 1 -22.72 -6.4 61.952 61.952 0 0 1 -16.043 -17.579 66.133 66.133 0 0 0 -6.229 -8.149 57.451 57.451 0 0 0 -7.936 -7.317 39.275 39.275 0 0 0 -9.216 -5.12 25.6 25.6 0 0 0 -10.261 -2.155c-0.853 0.021 -1.707 0.107 -2.56 0.213a13.845 13.845 0 0 0 -3.456 0.427 8.704 8.704 0 0 0 -2.773 1.28 2.475 2.475 0 0 0 -1.28 2.133 7.04 7.04 0 0 0 2.987 5.163c1.984 1.579 3.627 2.795 4.949 3.648l0.64 0.448c2.837 2.197 5.568 4.565 8.149 7.104 2.389 2.091 4.544 4.459 6.4 7.04 1.92 2.539 3.584 5.248 4.928 8.128 1.557 2.859 3.2 6.144 4.928 9.877 4.011 10.112 11.136 18.667 20.352 24.427 9.664 5.184 20.501 7.765 31.488 7.488 3.712 0 7.445 -0.213 11.136 -0.64 3.669 -0.597 7.317 -1.216 10.987 -1.941v37.184a10.667 10.667 0 0 1 -11.371 11.115h-1.323a219.435 219.435 0 1 1 134.912 0v0.107z\"]\n};\nvar vsGlobe = {\n prefix: \"vs\",\n iconName: \"globe\",\n icon: [512, 512, [], \"f000\", \"M272 32a208 208 0 1 1 0 416 208 208 0 0 1 0 -416zm156.608 128a176.864 176.864 0 0 0 -97.696 -85.632c14.208 26.88 24.48 55.68 30.496 85.632h67.2zm18.624 95.84A163.52 163.52 0 0 0 448 240a174.848 174.848 0 0 0 -6.816 -48h-74.944c1.024 10.592 1.76 21.248 1.76 32a323.648 323.648 0 0 1 -6.592 64h79.776c3.04 -10.528 5.056 -21.28 6.08 -32.16zm-113.12 0l0.192 -1.632A289.28 289.28 0 0 0 336 224a287.808 287.808 0 0 0 -2.432 -32H210.432A282.24 282.24 0 0 0 208 224a287.36 287.36 0 0 0 7.456 64h113.088c2.464 -10.624 4.32 -21.344 5.568 -32.16zM327.968 160a287.168 287.168 0 0 0 -40.16 -95.04C282.56 64.512 277.312 64 272 64a115.84 115.84 0 0 0 -9.984 0.48l-5.824 0.48L256 65.28A287.04 287.04 0 0 0 216.032 160h111.936zM182.592 160a318.688 318.688 0 0 1 30.912 -85.792A176.864 176.864 0 0 0 115.392 160h67.2zM102.816 192A175.36 175.36 0 0 0 96 240 175.36 175.36 0 0 0 102.816 288h79.776A320.512 320.512 0 0 1 176 224c0 -10.752 0.736 -21.408 1.76 -32H102.816zm88.128 128h-75.52a176.48 176.48 0 0 0 122.208 92.576A320.736 320.736 0 0 1 190.944 320zM272 404.608A286.144 286.144 0 0 0 319.296 320H224.704A286.176 286.176 0 0 0 272 404.608zM353.056 320a320.768 320.768 0 0 1 -46.688 92.576A176.544 176.544 0 0 0 428.576 320h-75.52z\"]\n};\nvar vsGoToFile = {\n prefix: \"vs\",\n iconName: \"go-to-file\",\n icon: [512, 512, [], \"f000\", \"M192 189.248l65.92 -65.92v-22.656L189.28 32l-22.624 22.624 1.376 1.376 8 8 32 32h-96a80 80 0 0 0 0 160H128V224h-16a48 48 0 1 1 0 -96h96L166.624 169.376 189.248 192 192 189.248zM352 64H266.496l-32 -32H384l22.72 9.28 96 96L512 160v288l-32 32H192l-32 -32V208l32 27.104V448h288V192h-128V64zm32 0v96h96l-96 -96z\"]\n};\nvar vsGrabber = {\n prefix: \"vs\",\n iconName: \"grabber\",\n icon: [512, 512, [], \"f000\", \"M480 192H32v32h448V192zm0 96H32v32h448V288z\"]\n};\nvar vsGraphLeft = {\n prefix: \"vs\",\n iconName: \"graph-left\",\n icon: [512, 512, [], \"f000\", \"M67.808 128L96 156.192l-19.808 19.808L22.88 122.656v-19.776L76.16 49.536l19.84 19.808L69.344 96H480v32H67.808zM128 465.472V174.56L144 160h64l16 14.56v290.88L208 480h-64l-16 -14.528zm64 -14.56V189.088H160v261.824h32zm64 -49.12V174.208L272 160h64l16 14.208v227.584l-16 14.208h-64l-16 -14.208zm64 -14.24V188.48H288v199.104h32zm64 -213.824v164.576l16 13.696h64l16 -13.696V173.728L464 160h-64l-16 13.728zm64 13.696v137.152h-32V187.424h32z\"]\n};\nvar vsGraphLine = {\n prefix: \"vs\",\n iconName: \"graph-line\",\n icon: [512, 512, [], \"f000\", \"M480 416v32H48l-16 -16V0h32v416h416zm-64 -313.376L251.328 267.328h-22.656L176 214.624l-116.672 116.704 -22.656 -22.656 128 -128h22.656L240 233.376l164.672 -164.704h22.624l64 64 -22.624 22.656L416 102.624z\"]\n};\nvar vsGraphScatter = {\n prefix: \"vs\",\n iconName: \"graph-scatter\",\n icon: [512, 512, [], \"f000\", \"M480 416v32H48l-16 -16V0h32v416h416zM160 64h64v64H160zm224 -32h64v64h-64zM256 160h64v64H256zM160 288h64v64H160zm224 -32h64v64h-64z\"]\n};\nvar vsGraph = {\n prefix: \"vs\",\n iconName: \"graph\",\n icon: [512, 512, [], \"f000\", \"M48 448H480v-32H64V0H32v432l16 16zM96 368v-256l16 -16h64l16 16v256l-16 16h-64l-16 -16zm64 -16V128H128v224h32zm192 -304v320l16 16h64l16 -16v-320l-16 -16h-64l-16 16zm64 16v288h-32V64h32zm-192 304v-192l16 -16h64l16 16v192l-16 16h-64l-16 -16zm64 -16V192H256v160h32z\"]\n};\nvar vsGripper = {\n prefix: \"vs\",\n iconName: \"gripper\",\n icon: [512, 512, [], \"f000\", \"M160 96h64v64H160zm0 128h64v64H160zm0 128h64v64H160zm128 -256h64v64H288zm0 128h64v64H288zm0 128h64v64H288z\"]\n};\nvar vsGroupByRefType = {\n prefix: \"vs\",\n iconName: \"group-by-ref-type\",\n icon: [512, 512, [], \"f000\", \"M48 32h64v32H64v384h48v32h-64l-16 -16v-416l16 -16zm192 192h-64L160 208v-64l16 -16h64l16 16v64l-16 16zM192 192h32V160H192v32zm240 32h-96l-16 -16v-96l16 -16h96l16 16v96l-16 16zM352 192h64V128h-64v64zm-112 192h-64l-16 -16v-64l16 -16h64l16 16v64l-16 16zM192 352h32v-32H192v32zm240 64h-96l-16 -16v-96l16 -16h96l16 16v96l-16 16zM352 384h64v-64h-64v64zm-32 -64H256v32h64v-32zm0 -160H256v32h64V160z\"]\n};\nvar vsHeart = {\n prefix: \"vs\",\n iconName: \"heart\",\n icon: [512, 512, [], \"f000\", \"M476.16 152.96a111.648 111.648 0 0 0 -11.84 -28.8 103.68 103.68 0 0 0 -19.2 -25.28 120.96 120.96 0 0 0 -38.72 -25.92 119.68 119.68 0 0 0 -90.88 0 128 128 0 0 0 -37.12 24l-1.6 1.92 -20.8 20.8 -20.8 -20.8 -1.6 -1.92a128 128 0 0 0 -37.12 -24 119.68 119.68 0 0 0 -90.88 0 120.96 120.96 0 0 0 -38.72 25.92 113.6 113.6 0 0 0 -31.04 54.08 120 120 0 0 0 -3.84 32c0 10.144 1.28 20.256 3.84 30.08a128 128 0 0 0 11.52 28.48 121.6 121.6 0 0 0 19.52 25.28L256 457.92l189.12 -189.12c7.584 -7.456 14.08 -16 19.2 -25.28A114.496 114.496 0 0 0 480 184.96a119.904 119.904 0 0 0 -3.84 -32zm-32 52.16a86.08 86.08 0 0 1 -22.08 38.72l-166.72 166.4 -166.72 -166.4a92.8 92.8 0 0 1 -14.08 -18.24 96 96 0 0 1 -8.64 -20.8 104 104 0 0 1 -2.56 -22.08A107.52 107.52 0 0 1 65.92 160a89.6 89.6 0 0 1 8.64 -20.8c3.84 -6.72 8.576 -12.8 14.08 -18.24a93.12 93.12 0 0 1 28.48 -19.2 89.6 89.6 0 0 1 66.56 0c10.56 4.384 20.096 10.816 28.16 18.88l43.52 43.84 43.52 -43.84a87.04 87.04 0 0 1 28.16 -18.88 89.6 89.6 0 0 1 66.56 0c10.592 4.576 20.256 11.104 28.48 19.2 5.568 5.28 10.24 11.424 13.76 18.24a86.08 86.08 0 0 1 11.2 42.88 83.2 83.2 0 0 1 -1.92 23.04h-0.96z\"]\n};\nvar vsHistory = {\n prefix: \"vs\",\n iconName: \"history\",\n icon: [512, 512, [], \"f000\", \"M432.224 394.368a224 224 0 0 0 2.08 -273.92A224 224 0 0 0 64 140.576V64H32v112l16 16H160V160H89.952a192.256 192.256 0 1 1 -4.32 184.64l-28.384 14.784a224 224 0 0 0 374.976 34.944zm-107.552 -31.04l22.656 -22.624L256 249.344V128H224v128l4.672 11.328 96 96z\"]\n};\nvar vsHome = {\n prefix: \"vs\",\n iconName: \"home\",\n icon: [512, 512, [], \"f000\", \"M267.52 43.84l203.52 185.6 -22.72 22.72L416 222.848v208.832l-16 16h-96l-16 -16v-112H224v112l-16 16h-96l-16 -16V223.104L64 252.16l-22.72 -22.72 203.2 -185.6h23.04zM128 194.016v221.664h64v-112l16 -16h96l16 16v112h64V193.824L256 77.76 128 194.016z\"]\n};\nvar vsHorizontalRule = {\n prefix: \"vs\",\n iconName: \"horizontal-rule\",\n icon: [512, 512, [], \"f000\", \"M205.824 320h26.336V128h-26.336v83.52h-83.52V128H96v192h26.336V236.608h83.52V320zm181.376 0h28.8l-40.96 -84.16c4.192 -1.856 8.32 -4.288 12.448 -7.36a53.312 53.312 0 0 0 18.72 -25.504c2.048 -5.472 3.072 -11.648 3.072 -18.56a56.64 56.64 0 0 0 -2.624 -17.824 52.608 52.608 0 0 0 -7.04 -14.272 48.128 48.128 0 0 0 -9.92 -10.912 59.648 59.648 0 0 0 -23.584 -11.936A46.272 46.272 0 0 0 355.2 128H276.48v192h26.368V240.576h46.944L387.2 320zm-21.792 -106.24a27.968 27.968 0 0 1 -9.376 1.76H302.816V153.184h53.216a27.84 27.84 0 0 1 18.432 7.68 30.592 30.592 0 0 1 9.792 23.584c0 5.376 -0.928 10.048 -2.784 13.984a29.12 29.12 0 0 1 -16.096 15.328zM416 384H96v32h320v-32z\"]\n};\nvar vsHubot = {\n prefix: \"vs\",\n iconName: \"hubot\",\n icon: [512, 512, [], \"f000\", \"M271.36 128h128l16 16v64.96h16.64l16 16V256l-16 16h-16.64v96l-16 16H299.52l-80 88.32L192 460.8V384H112l-16 -20.48V272h-16L64 256v-31.04l16 -16H96V139.52L112.96 128h128V91.52A32 32 0 0 1 224 64a32 32 0 0 1 64 0 32 32 0 0 1 -16.64 26.56V128zM384 256V160H128v187.52l80 4.48H224v70.08l57.6 -65.28 11.2 -4.8H384V256zm-67.84 16.32a86.72 86.72 0 0 1 -43.84 23.68v-0.32a86.72 86.72 0 0 1 -77.44 -23.68l-22.4 22.72c10.88 10.88 23.84 19.456 38.08 25.28 14.4 6.016 29.824 9.152 45.44 9.28a118.4 118.4 0 0 0 82.56 -34.24l-22.4 -22.72zM207.68 208h-32v32h32v-32zm96 0h32v32h-32v-32z\"]\n};\nvar vsInbox = {\n prefix: \"vs\",\n iconName: \"inbox\",\n icon: [512, 512, [], \"f000\", \"M48 448h416l16 -16V288l-88.64 -245.12 -15.04 -10.88H136.64l-15.04 10.56L32 279.68v152.32l16 16zM448 416H64v-95.36h81.6l23.68 40 13.76 7.68h146.24l14.08 -8.32 22.08 -39.36H448V416zm-0.704 -127.36H355.84l-13.76 8.32 -22.08 39.36H192.32l-24 -40 -13.76 -7.68H64V288l83.84 -224h216.96l82.496 224.64z\"]\n};\nvar vsInfo = {\n prefix: \"vs\",\n iconName: \"info\",\n icon: [512, 512, [], \"f000\", \"M274.176 32.992A217.6 217.6 0 0 1 408.32 97.6a225.92 225.92 0 0 1 14.72 300.48 219.2 219.2 0 0 1 -274.56 55.68 224 224 0 0 1 -99.84 -112 227.84 227.84 0 0 1 -7.36 -150.72 224 224 0 0 1 88.64 -121.28 217.6 217.6 0 0 1 144.256 -36.768zM289.28 444.16a188.48 188.48 0 0 0 109.12 -66.24 194.24 194.24 0 0 0 -12.8 -257.92 186.24 186.24 0 0 0 -237.76 -23.68 193.92 193.92 0 0 0 16 329.28 185.92 185.92 0 0 0 125.44 18.56zM236 192h40V160h-40v32zm40 32v128h-40V224h40z\"]\n};\nvar vsInspect = {\n prefix: \"vs\",\n iconName: \"inspect\",\n icon: [512, 512, [], \"f000\", \"M32 96l32 -32h384l32 32v192h-32V96H64v256h160v32H64l-32 -32V96zm470.624 310.624L288 192v301.248l86.624 -86.624h128zM320 416V269.248l105.376 105.376h-64L320 416z\"]\n};\nvar vsIssueDraft = {\n prefix: \"vs\",\n iconName: \"issue-draft\",\n icon: [512, 512, [], \"f000\", \"undefined\"]\n};\nvar vsIssueReopened = {\n prefix: \"vs\",\n iconName: \"issue-reopened\",\n icon: [512, 512, [], \"f000\", \"M168.96 180.992L64 224.192l-21.12 -8.32L0 112.192l29.44 -12.16 25.92 62.4a207.36 207.36 0 0 1 399.36 61.76h-32a175.36 175.36 0 0 0 -340.48 -40.96l74.24 -32 12.48 29.76zm283.52 85.76l42.88 103.36 -29.44 14.08 -26.24 -64a207.68 207.68 0 0 1 -400 -64h32v-16a175.68 175.68 0 0 0 340.48 60.48l-72 29.76 -12.48 -29.44 104 -43.2 20.8 8.96z\"]\n};\nvar vsIssues = {\n prefix: \"vs\",\n iconName: \"issues\",\n icon: [512, 512, [], \"f000\", \"M240 32a208 208 0 1 0 0 416 208 208 0 0 0 0 -416zm0 384a176 176 0 1 1 0 -352 176 176 0 0 1 0 352z\"]\n};\nvar vsItalic = {\n prefix: \"vs\",\n iconName: \"italic\",\n icon: [512, 512, [], \"f000\", \"M288.032 434.976l-3.104 10.4H128l3.936 -10.4c15.744 -0.384 26.144 -1.696 31.232 -3.936 8.224 -3.2 14.336 -7.616 18.24 -13.216 6.208 -8.832 12.608 -24.576 19.168 -47.264l66.368 -230.08c5.632 -19.104 8.416 -33.536 8.416 -43.296a20.576 20.576 0 0 0 -3.648 -12.384 21.856 21.856 0 0 0 -11.232 -7.584c-4.896 -1.888 -14.528 -2.816 -28.992 -2.816L234.88 64h147.36l-3.072 10.4c-12 -0.192 -20.928 1.12 -26.72 3.936a43.456 43.456 0 0 0 -19.424 16.032c-4.288 6.944 -9.92 22.304 -16.864 46.144l-66.112 230.08c-5.984 21.152 -8.96 34.656 -8.96 40.48 0 4.672 1.088 8.704 3.36 12.096 2.432 3.2 6.176 5.696 11.232 7.584 5.248 1.696 16.032 3.104 32.352 4.224z\"]\n};\nvar vsJersey = {\n prefix: \"vs\",\n iconName: \"jersey\",\n icon: [512, 512, [], \"f000\", \"M381.12 455.04H129.92l-16 -16V225.92H68.8l-15.36 -12.16L32 128l10.56 -19.2L178.88 64l20.48 10.24a86.4 86.4 0 0 0 6.72 14.08c2.272 3.296 4.864 6.4 7.68 9.28 5.376 5.408 11.808 9.664 18.88 12.48a58.24 58.24 0 0 0 45.76 0 55.68 55.68 0 0 0 18.88 -12.48c2.88 -3.04 5.536 -6.24 8 -9.6l4.8 -9.28a38.72 38.72 0 0 0 1.6 -4.48l20.48 -10.24 136.32 45.44L480 128l-21.12 85.12 -15.68 12.16h-46.08v213.12l-16 16.64zm-235.2 -32h219.2V209.92l16 -16h48.64l14.72 -58.56 -108.8 -36.48a36.224 36.224 0 0 1 -3.84 6.72c-3.52 5.152 -7.456 9.984 -11.84 14.4a88 88 0 0 1 -29.12 19.52 91.2 91.2 0 0 1 -71.04 0A93.44 93.44 0 0 1 192 120a69.44 69.44 0 0 1 -11.52 -14.08l-4.16 -7.04 -109.76 36.48 14.72 58.56h48.64l16 16v213.12z\"]\n};\nvar vsJson = {\n prefix: \"vs\",\n iconName: \"json\",\n icon: [512, 512, [], \"f000\", \"M192 95.488V64h-2.88c-10.016 0 -19.712 1.984 -29.088 5.92a74.56 74.56 0 0 0 -24.8 16.96 71.36 71.36 0 0 0 -15.776 24.096v0.032a113.344 113.344 0 0 0 -6.336 26.56v0.064a194.56 194.56 0 0 0 -0.768 27.616c0.384 9.28 0.576 18.56 0.576 27.808 0 6.496 -1.28 12.576 -3.744 18.304v0.032a48.128 48.128 0 0 1 -24.48 25.184 44.032 44.032 0 0 1 -17.856 3.68H64v31.488h2.88c6.24 0 12.16 1.28 17.792 3.872l0.032 0.032c5.696 2.496 10.528 5.888 14.56 10.176l0.064 0.064c4.16 4.16 7.456 9.12 9.824 14.88l0.032 0.064c2.496 5.76 3.744 11.776 3.744 18.112 0 9.28 -0.192 18.56 -0.576 27.808 -0.384 9.472 -0.128 18.72 0.768 27.84v0.032c1.056 9.056 3.168 17.856 6.304 26.368v0.032c3.392 8.736 8.672 16.768 15.808 24.096 7.136 7.36 15.424 13.024 24.8 16.96 9.376 3.936 19.072 5.92 29.12 5.92H192v-31.488h-2.88c-6.4 0 -12.384 -1.216 -18.016 -3.68a51.616 51.616 0 0 1 -14.624 -10.24 53.088 53.088 0 0 1 -9.888 -14.944c-2.368 -5.76 -3.52 -11.84 -3.52 -18.336 0 -7.296 0.096 -14.496 0.352 -21.504 0.256 -7.296 0.256 -14.4 0 -21.28a148.448 148.448 0 0 0 -1.76 -20.48 85.824 85.824 0 0 0 -5.376 -19.488A73.088 73.088 0 0 0 112.704 256a73.088 73.088 0 0 0 23.616 -30.56c2.56 -6.144 4.32 -12.576 5.376 -19.264 1.056 -6.72 1.632 -13.536 1.76 -20.48 0.256 -7.04 0.256 -14.144 0 -21.312 -0.256 -7.168 -0.384 -14.4 -0.384 -21.696a47.04 47.04 0 0 1 28.064 -43.328 42.56 42.56 0 0 1 18.016 -3.872H192zm128 321.024V448h2.88c10.016 0 19.712 -1.984 29.088 -5.92 9.376 -3.936 17.664 -9.6 24.8 -16.96 7.136 -7.36 12.416 -15.36 15.776 -24.096v-0.032c3.2 -8.512 5.28 -17.376 6.336 -26.56v-0.064c0.896 -8.96 1.152 -18.144 0.768 -27.616 -0.384 -9.28 -0.576 -18.56 -0.576 -27.808 0 -6.496 1.28 -12.576 3.744 -18.304v-0.032a48.064 48.064 0 0 1 24.48 -25.184 44.16 44.16 0 0 1 17.856 -3.68H448v-31.488h-2.88c-6.272 0 -12.192 -1.28 -17.824 -3.872l-0.032 -0.032a44.032 44.032 0 0 1 -14.56 -10.176l-0.064 -0.064a45.28 45.28 0 0 1 -9.824 -14.88v-0.064a44.96 44.96 0 0 1 -3.776 -18.112c0 -9.28 0.192 -18.56 0.576 -27.808a197.568 197.568 0 0 0 -0.768 -27.84v-0.032a113.184 113.184 0 0 0 -6.304 -26.368v-0.032a71.36 71.36 0 0 0 -15.808 -24.096 74.592 74.592 0 0 0 -24.8 -16.96 74.4 74.4 0 0 0 -29.12 -5.92H320v31.488h2.88c6.4 0 12.384 1.216 17.984 3.68 5.568 2.624 10.432 6.016 14.624 10.24 4.064 4.288 7.36 9.28 9.888 14.944 2.368 5.76 3.52 11.84 3.52 18.336 0 7.296 -0.096 14.464 -0.352 21.504 -0.256 7.296 -0.256 14.4 0 21.28 0.128 7.104 0.704 13.92 1.76 20.48 1.056 6.848 2.848 13.312 5.376 19.488a73.12 73.12 0 0 0 23.616 30.56 73.12 73.12 0 0 0 -23.616 30.56 86.048 86.048 0 0 0 -5.376 19.264c-1.056 6.72 -1.632 13.536 -1.76 20.48a292.8 292.8 0 0 0 0 21.312c0.256 7.168 0.384 14.4 0.384 21.696a47.072 47.072 0 0 1 -28.064 43.328 42.56 42.56 0 0 1 -18.016 3.872H320z\"]\n};\nvar vsKebabVertical = {\n prefix: \"vs\",\n iconName: \"kebab-vertical\",\n icon: [512, 512, [], \"f000\", \"M238.208 442.624a32 32 0 1 0 35.552 -53.216 32 32 0 0 0 -35.52 53.184zM256 288a32 32 0 1 1 0 -64 32 32 0 0 1 0 64zm0 -160a32 32 0 1 1 0 -64 32 32 0 0 1 0 64z\"]\n};\nvar vsKey = {\n prefix: \"vs\",\n iconName: \"key\",\n icon: [512, 512, [], \"f000\", \"M363.232 34.912a144.896 144.896 0 0 1 110.08 101.12c6.88 23.168 7.904 47.68 2.976 71.36a146.656 146.656 0 0 1 -141.984 115.2c-14.016 0 -27.968 -2.016 -41.376 -6.08l-25.6 30.016 -12.128 5.6H224v48l-16 16H160v48l-16 16h-96l-16 -16v-73.824l4.672 -11.296L195.84 219.84a142.848 142.848 0 0 1 -6.4 -44.96 144.896 144.896 0 0 1 173.792 -140zm42.176 230.4a114.176 114.176 0 0 0 39.648 -64.16l0.128 0.16A113.376 113.376 0 0 0 311.04 66.56a114.432 114.432 0 0 0 -89.6 108.8c-0.32 14.592 2.24 29.056 7.648 42.56l-3.52 17.376L64 396.928v51.2h64v-48l16 -16H192v-48l16 -16h39.84l28.032 -32.512 17.952 -4.48a111.04 111.04 0 0 0 40.608 7.616 114.176 114.176 0 0 0 70.976 -25.44zm-26.816 -87.424a32 32 0 1 0 -53.184 -35.52 32 32 0 0 0 53.184 35.52z\"]\n};\nvar vsLaw = {\n prefix: \"vs\",\n iconName: \"law\",\n icon: [512, 512, [], \"f000\", \"M468.16 224L416 96h32V64H288V32H256v32H96v32h32L76.16 224H64v32h4.8c4.992 15.936 15.136 29.76 28.8 39.36a79.04 79.04 0 0 0 92.8 0A78.08 78.08 0 0 0 219.52 256H224V224h-14.4L156.16 96H256v256H192l-12.48 5.76 -64 80.32 12.48 25.92h288l12.48 -25.92 -64 -80.32L352 352H288V96h100.16l-53.44 128H320v32h4.8a79.36 79.36 0 0 0 150.72 0H480V224h-11.84zM167.04 272.32a48.64 48.64 0 0 1 -23.04 6.08 46.4 46.4 0 0 1 -22.72 -6.08A47.04 47.04 0 0 1 104 256h80a48.64 48.64 0 0 1 -16.96 16.32zM175.04 224h-64l32 -76.8 32 76.8zm169.28 160L384 432H160L199.68 384h144.64zm56.96 -236.16l32 76.8h-64l32 -76.8zm21.76 125.12a45.12 45.12 0 0 1 -23.04 6.08 43.2 43.2 0 0 1 -22.72 -6.08 49.6 49.6 0 0 1 -17.28 -16.96h80a43.84 43.84 0 0 1 -16.96 16.96z\"]\n};\nvar vsLayersActive = {\n prefix: \"vs\",\n iconName: \"layers-active\",\n icon: [512, 512, [], \"f000\", \"M261.92 34.656l-17.856 0.128 -189.088 129.184 0.128 26.496L244.16 317.28l17.6 0.128 194.944 -126.816 0.096 -26.752 -194.88 -129.184zm-169.376 142.4l160.672 -109.76 165.632 109.76 -165.632 107.776 -160.672 -107.776zm151.648 220.224L57.376 272h57.44l138.4 92.8 142.688 -92.8h58.656l-25.6 16.64a128.064 128.064 0 0 0 -134.72 87.648l-32.416 21.12 -17.632 -0.128zm43.936 24.832l-34.88 22.72L114.784 352H57.376l186.816 125.28 17.6 0.128 32.64 -21.216a127.616 127.616 0 0 1 -6.304 -34.08zm74.528 -85.92a96 96 0 1 1 106.656 159.584 96 96 0 0 1 -106.656 -159.584zm54.336 122.144l57.28 -76.384 -25.6 -19.2 -47.36 63.168 -28.032 -22.4 -19.968 24.96 40.896 32.736 22.784 -2.88z\"]\n};\nvar vsLayersDot = {\n prefix: \"vs\",\n iconName: \"layers-dot\",\n icon: [512, 512, [], \"f000\", \"M261.92 34.656l-17.856 0.128 -189.088 129.184 0.128 26.496L244.16 317.28l17.6 0.128 194.944 -126.816 0.096 -26.752 -194.88 -129.184zm-169.376 142.4l160.672 -109.76 165.632 109.76 -165.632 107.776 -160.672 -107.776zm151.648 220.224L57.376 272h57.44l138.4 92.8 142.688 -92.8h58.656l-25.6 16.64a128.064 128.064 0 0 0 -134.72 87.648l-32.416 21.12 -17.632 -0.128zm43.936 24.832l-34.88 22.72L114.784 352H57.376l186.816 125.28 17.6 0.128 32.64 -21.216a127.616 127.616 0 0 1 -6.304 -34.08z\"]\n};\nvar vsLayers = {\n prefix: \"vs\",\n iconName: \"layers\",\n icon: [512, 512, [], \"f000\", \"M244.064 34.784l17.856 -0.128 194.912 129.184 -0.096 26.752L261.824 317.44l-17.632 -0.128 -189.12 -126.816 -0.096 -26.496 189.12 -129.184zm9.152 32.512l-160.672 109.76 160.672 107.776 165.632 -107.776 -165.632 -109.76zM57.376 272l186.816 125.28 17.6 0.128L454.592 272h-58.656l-142.688 92.8 -138.4 -92.8H57.376zm186.816 205.28L57.376 352h57.44l138.4 92.8 142.688 -92.8h58.656l-192.736 125.44 -17.632 -0.16z\"]\n};\nvar vsLibrary = {\n prefix: \"vs\",\n iconName: \"library\",\n icon: [512, 512, [], \"f000\", \"M160 80l16 -16h64l16 16v352l-16 16h-64l-16 -16v-352zM192 96v320h32V96H192zm101.472 11.04l9.568 -20.512 60.16 -21.888 20.48 9.568 120.384 330.752 -9.568 20.512 -60.128 21.888 -20.48 -9.568L293.44 107.04zm35.52 4.096l109.44 300.672 30.08 -10.912 -109.44 -300.704 -30.08 10.944zM32 80l16 -16h64l16 16v352l-16 16h-64l-16 -16v-352zM64 96v320h32V96H64z\"]\n};\nvar vsLightbulbAutofix = {\n prefix: \"vs\",\n iconName: \"lightbulb-autofix\",\n icon: [512, 512, [], \"f000\", \"M384 288a96 96 0 1 0 0 192 96 96 0 0 0 0 -192zm41.92 160L384 416l-41.6 32 16 -48.96 -38.4 -26.56h47.04L384 320l17.28 52.48H448l-38.4 26.56 16.32 48.96zm-68.48 -189.28A127.328 127.328 0 0 0 265.216 336H205.088v70.432c0 2.592 0.896 4.8 2.88 6.784a9.28 9.28 0 0 0 6.816 2.88h45.216c2.848 11.136 7.136 21.696 12.672 31.424 -2.112 0.32 -4.288 0.48 -6.496 0.48H214.784a41.12 41.12 0 0 1 -29.504 -12.128 41.696 41.696 0 0 1 -12.16 -29.44v-51.2c0 -15.328 -2.944 -29.472 -8.768 -42.528a113.792 113.792 0 0 0 -24.832 -35.648 150.048 150.048 0 0 1 -32.192 -45.984A133.984 133.984 0 0 1 96 176a141.824 141.824 0 0 1 19.712 -72.64c6.304 -10.752 13.824 -20.48 22.56 -29.248a147.2 147.2 0 0 1 29.152 -22.464c10.816 -6.272 22.4 -11.136 34.688 -14.528a142.4 142.4 0 0 1 38.4 -5.12 143.232 143.232 0 0 1 72.832 19.648 143.2 143.2 0 0 1 51.904 51.712 142.016 142.016 0 0 1 19.712 72.64c0 19.744 -3.744 38.112 -11.296 55.072a145.184 145.184 0 0 1 -16.192 27.648z\"]\n};\nvar vsLightbulb = {\n prefix: \"vs\",\n iconName: \"lightbulb\",\n icon: [512, 512, [], \"f000\", \"M373.44 277.056a117.152 117.152 0 0 0 -24.992 35.648 104.96 104.96 0 0 0 -8.576 42.528v51.2a41.728 41.728 0 0 1 -25.408 38.304 41.024 41.024 0 0 1 -16.288 3.264H246.784a41.12 41.12 0 0 1 -29.504 -12.128 41.696 41.696 0 0 1 -12.16 -29.44v-51.2c0 -15.328 -2.944 -29.472 -8.768 -42.528a113.792 113.792 0 0 0 -24.832 -35.648 150.048 150.048 0 0 1 -32.192 -45.984A133.984 133.984 0 0 1 128 176a141.824 141.824 0 0 1 19.712 -72.64c6.304 -10.752 13.824 -20.48 22.56 -29.248a147.2 147.2 0 0 1 29.152 -22.464c10.816 -6.272 22.4 -11.136 34.688 -14.528a142.4 142.4 0 0 1 38.4 -5.12 143.232 143.232 0 0 1 72.832 19.648 143.2 143.2 0 0 1 51.904 51.712 142.016 142.016 0 0 1 19.712 72.64c0 19.744 -3.744 38.112 -11.296 55.072a150.08 150.08 0 0 1 -32.192 45.984zM307.936 336H237.088v70.432c0 2.592 0.896 4.8 2.88 6.784a9.28 9.28 0 0 0 6.816 2.88h51.392a9.248 9.248 0 0 0 6.816 -2.88 9.152 9.152 0 0 0 2.88 -6.784V336z\"]\n};\nvar vsLinkExternal = {\n prefix: \"vs\",\n iconName: \"link-external\",\n icon: [512, 512, [], \"f000\", \"M48 32H192v32H64v384h384v-128h32v144l-16 16h-416l-16 -16v-416l16 -16zm432 16V256h-32V86.624L231.776 302.88l-22.624 -22.656L425.376 64H256V32h208l16 16z\"]\n};\nvar vsLink = {\n prefix: \"vs\",\n iconName: \"link\",\n icon: [512, 512, [], \"f000\", \"M140.8 96h98.72a108.8 108.8 0 0 1 108.8 108.8v6.56A108.8 108.8 0 0 1 239.52 320H224V288h15.52A76.8 76.8 0 0 0 316.16 211.52V204.8A76.8 76.8 0 0 0 239.68 128H140.8A76.8 76.8 0 0 0 64 204.8v6.56A76.608 76.608 0 0 0 128 286.72v32a108.8 108.8 0 0 1 -96 -107.2V204.8A108.96 108.96 0 0 1 140.8 96zM384 225.28v-32a108.8 108.8 0 0 1 96 107.52v6.56A108.96 108.96 0 0 1 371.36 416h-98.88A108.8 108.8 0 0 1 163.84 307.52V300.8A108.8 108.8 0 0 1 272.48 192H288v32h-15.52A76.8 76.8 0 0 0 195.84 300.8v6.56A76.8 76.8 0 0 0 272.48 384h98.88A76.8 76.8 0 0 0 448 307.52V300.8a76.608 76.608 0 0 0 -64 -75.52z\"]\n};\nvar vsListFilter = {\n prefix: \"vs\",\n iconName: \"list-filter\",\n icon: [512, 512, [], \"f000\", \"M192 384v-32h128v32H192zM128 224h256v32H128V224zm320 -128v32H64V96h384z\"]\n};\nvar vsListFlat = {\n prefix: \"vs\",\n iconName: \"list-flat\",\n icon: [512, 512, [], \"f000\", \"M64 320V288h384v32H64zm0 -128h384v32H64V192zm384 -96v32H64V96h384zM64 384v32h384v-32H64z\"]\n};\nvar vsListOrdered = {\n prefix: \"vs\",\n iconName: \"list-ordered\",\n icon: [512, 512, [], \"f000\", \"M73.184 74.432L86.144 64h21.664v96h-22.656V89.344l-11.968 8.992v-23.904zM160 96h320v32H160V96zm0 128h320v32H160V224zm320 128H160v32h320v-32zM119.744 244.032l0.928 -1.248 2.08 -2.88a26.88 26.88 0 0 0 4.992 -16.224c0 -3.84 -0.64 -7.68 -1.824 -11.328a27.136 27.136 0 0 0 -15.744 -16.928 35.936 35.936 0 0 0 -14.464 -2.624 35.008 35.008 0 0 0 -14.656 2.784 27.744 27.744 0 0 0 -15.328 16.704A33.216 33.216 0 0 0 64 222.624v1.6h25.92v-1.6a9.6 9.6 0 0 1 1.472 -5.024 5.568 5.568 0 0 1 1.824 -1.728 6.08 6.08 0 0 1 5.504 0 6.016 6.016 0 0 1 1.792 1.92 7.68 7.68 0 0 1 0.992 2.592 14.24 14.24 0 0 1 -1.152 9.28 41.888 41.888 0 0 1 -3.84 5.824l-32 36.416 -0.384 0.416v17.28h63.616v-22.4h-28.8l20.8 -23.168zm-1.184 122.144c1.472 1.024 2.752 2.24 3.84 3.648a26.912 26.912 0 0 1 5.344 17.6c0 3.424 -0.544 6.816 -1.6 10.048a25.344 25.344 0 0 1 -15.584 16 41.216 41.216 0 0 1 -15.36 2.528c-3.68 0 -7.36 -0.512 -10.912 -1.568a30.08 30.08 0 0 1 -8.256 -3.936 24.032 24.032 0 0 1 -5.824 -5.664 34.016 34.016 0 0 1 -3.712 -6.4A33.216 33.216 0 0 1 64 386.496v-1.568h26.048v1.568c0 0.864 0.096 1.76 0.288 2.624a6.624 6.624 0 0 0 0.96 2.368 4.48 4.48 0 0 0 1.696 1.664 6.4 6.4 0 0 0 5.024 0.256 5.088 5.088 0 0 0 1.792 -1.248 7.04 7.04 0 0 0 1.344 -2.4 13.344 13.344 0 0 0 0.544 -4.032 15.456 15.456 0 0 0 -0.704 -5.216 6.4 6.4 0 0 0 -1.632 -2.56 4.416 4.416 0 0 0 -1.92 -0.928 17.184 17.184 0 0 0 -2.464 -0.224h-5.152v-20.64h5.376a7.712 7.712 0 0 0 2.208 -0.352 5.248 5.248 0 0 0 2.08 -1.088 5.6 5.6 0 0 0 1.536 -2.144 9.152 9.152 0 0 0 0.672 -3.872 8.96 8.96 0 0 0 -0.512 -3.2 5.312 5.312 0 0 0 -3.104 -3.168 6.4 6.4 0 0 0 -4.992 0.224 5.248 5.248 0 0 0 -1.76 1.696 11.008 11.008 0 0 0 -1.28 4.992v1.568H64v-1.568a31.584 31.584 0 0 1 5.76 -17.408 25.6 25.6 0 0 1 5.728 -5.952 27.84 27.84 0 0 1 8.384 -4.256c3.648 -1.152 7.488 -1.696 11.328 -1.632 3.712 -0.032 7.392 0.32 11.008 1.152 2.944 0.672 5.76 1.76 8.416 3.2a24.224 24.224 0 0 1 10.24 10.176 23.36 23.36 0 0 1 2.88 11.104 25.92 25.92 0 0 1 -5.344 16.896 17.984 17.984 0 0 1 -3.84 3.648z\"]\n};\nvar vsListSelection = {\n prefix: \"vs\",\n iconName: \"list-selection\",\n icon: [512, 512, [], \"f000\", \"M32 384v-32h288v32H32zm0 -160h448v32H32V224zm352 -128v32H32V96h352z\"]\n};\nvar vsListTree = {\n prefix: \"vs\",\n iconName: \"list-tree\",\n icon: [512, 512, [], \"f000\", \"M448 96v32H64V96h384zm-32 96v32H192V192h224zm0 96v32H160V288h256zm0 96v32H160v-32h256zM160 128h32v288H160z\"]\n};\nvar vsListUnordered = {\n prefix: \"vs\",\n iconName: \"list-unordered\",\n icon: [512, 512, [], \"f000\", \"M64 96H32v32h32V96zm0 96H32v32h32V192zM32 288h32v32H32V288zm32 96H32v32h32v-32zm64 -288h352v32H128V96zm352 96H128v32h352V192zM128 288h352v32H128V288zm352 96H128v32h352v-32z\"]\n};\nvar vsLiveShare = {\n prefix: \"vs\",\n iconName: \"live-share\",\n icon: [512, 512, [], \"f000\", \"M293.013 36.139L323.797 21.333l171.285 134.997v29.611l-171.285 129.536 -30.784 -14.805v-59.221h-12.587c-86.613 -0.427 -143.147 2.219 -226.347 110.144l-32.725 -10.517a175.573 175.573 0 0 1 5.781 -48.107 235.221 235.221 0 0 1 83.627 -144.917 241.899 241.899 0 0 1 160.043 -54.336h22.187v-57.6zm38.485 168.896v59.221l121.088 -91.328 -120.491 -96.96v56.832h-61.013A198.379 198.379 0 0 0 123.093 188.757a222.805 222.805 0 0 0 -51.221 87.936c71.488 -68.544 132.053 -71.659 209.024 -71.659h50.624zm-163.136 125.781a91.947 91.947 0 1 1 102.144 152.875 91.947 91.947 0 0 1 -102.144 -152.875zm20.373 122.197a55.211 55.211 0 1 0 61.397 -91.776 55.211 55.211 0 0 0 -61.397 91.776z\"]\n};\nvar vsLoading = {\n prefix: \"vs\",\n iconName: \"loading\",\n icon: [512, 512, [], \"f000\", \"M445.344 224A192.064 192.064 0 0 0 66.656 224H34.272a224.064 224.064 0 0 1 443.456 0h-32.384z\"]\n};\nvar vsLocation = {\n prefix: \"vs\",\n iconName: \"location\",\n icon: [512, 512, [], \"f000\", \"M346.624 86.016A129.792 129.792 0 0 0 256.64 48h-1.28a129.792 129.792 0 0 0 -128 128c-0.416 24 6.336 47.584 19.392 67.744L247.488 448h17.056l100.704 -204.256c13.088 -20.16 19.84 -43.744 19.392 -67.744a129.792 129.792 0 0 0 -38.016 -89.984zM253.6 80l2.624 0.32 2.368 -0.32a98.4 98.4 0 0 1 94.112 97.184 87.68 87.68 0 0 1 -14.944 50.176l-0.64 1.088 -0.544 1.12L256 392.928l-80.544 -163.2 -0.544 -1.248 -0.64 -1.088a87.68 87.68 0 0 1 -14.944 -50.176A98.368 98.368 0 0 1 253.568 80zm19.584 69.408a32 32 0 1 0 -35.584 53.216 32 32 0 0 0 35.584 -53.216zM219.84 122.784a64 64 0 1 1 71.04 106.432 64 64 0 0 1 -71.04 -106.432z\"]\n};\nvar vsLock = {\n prefix: \"vs\",\n iconName: \"lock\",\n icon: [512, 512, [], \"f000\", \"M416 224h-32V160a128 128 0 1 0 -256 0v64H96L64 256v192l32 32h320l32 -32V256l-32 -32zM160 160a96 96 0 1 1 192 0v64H160V160zm256 288H96V256h320v192z\"]\n};\nvar vsMagnet = {\n prefix: \"vs\",\n iconName: \"magnet\",\n icon: [512, 512, [], \"f000\", \"M256 48c-124.8 0 -224 99.2 -224 224v160l32 32h96l32 -32v-160c0 -35.2 28.8 -64 64 -64s64 28.8 64 64v160l32 32h96l32 -32v-160c0 -124.8 -99.2 -224 -224 -224zm-96 384H64v-96h96v96zm288 0h-96v-96h96v96zm-96 -128v-32c0 -54.4 -41.6 -96 -96 -96 -51.2 0 -92.8 41.6 -96 89.6v38.4H64v-32c0 -105.6 86.4 -192 192 -192s192 86.4 192 192v32h-96z\"]\n};\nvar vsMailRead = {\n prefix: \"vs\",\n iconName: \"mail-read\",\n icon: [512, 512, [], \"f000\", \"M264 50.24h-16.32L32 177.92v254.08l16 16h416l16 -16V177.92L264 50.24zM256 82.56l180.16 106.24 -43.84 50.88H119.68L77.76 188.8 256 82.56zM448 416H64V221.44L99.52 265.6l12.48 6.08h288l12.48 -6.08L448 221.44V416z\"]\n};\nvar vsMail = {\n prefix: \"vs\",\n iconName: \"mail\",\n icon: [512, 512, [], \"f000\", \"M32 112l16 -16h416l16 16v288l-16 16h-416l-16 -16v-288zm32 33.12V384h384V145.152L265.92 284.8H246.4L64 145.12zM416.96 128H95.04L256 251.808 416.96 128z\"]\n};\nvar vsMarkdown = {\n prefix: \"vs\",\n iconName: \"markdown\",\n icon: [512, 512, [], \"f000\", \"M203.04 160h67.2v209.056H223.776l1.76 -169.92 -56.768 169.92H130.304l-57.76 -169.92c1.28 20.608 1.92 169.92 1.92 169.92H32V160h68.992s48.896 143.776 50.464 153.824L203.04 160zm214.72 115.744v-112H355.52v112H293.312l93.344 93.312L480 275.744h-62.24z\"]\n};\nvar vsMegaphone = {\n prefix: \"vs\",\n iconName: \"megaphone\",\n icon: [512, 512, [], \"f000\", \"M64 216.64l394.56 -109.76 21.44 16.96v275.2l-21.44 16.96 -194.848 -51.04a69.12 69.12 0 1 1 -133.696 -35.04L64 312.64l-13.44 -16.96V233.6L64 216.64zm96.192 121.184a36.16 36.16 0 0 0 -1.28 7.744 37.44 37.44 0 0 0 73.216 11.104l-71.936 -18.848zM82.56 282.24L448 378.56V144L82.56 247.04v35.2z\"]\n};\nvar vsMention = {\n prefix: \"vs\",\n iconName: \"mention\",\n icon: [512, 512, [], \"f000\", \"M334.88 395.52a176.512 176.512 0 0 1 -97.696 23.552 136.384 136.384 0 0 1 -146.24 -145.376 172.192 172.192 0 0 1 172.512 -178.272c76.064 0 141.216 44 141.216 128.192 0 69.824 -41.344 117.12 -92.8 117.12 -21.632 0 -35.2 -8.768 -36.032 -29.344a64.384 64.384 0 0 1 -56.192 29.216c-31.008 0 -52.128 -20.64 -52.128 -61.536 0 -56.416 36.736 -108.8 83.84 -108.8a42.048 42.048 0 0 1 45.664 29.76l6.752 -25.888h28.8L307.2 276.672c-7.232 29.312 -4.16 38.88 10.944 38.88 31.488 0 58.656 -38.72 58.656 -90.4 0 -66.176 -46.24 -104.48 -115.52 -104.48 -84.576 0 -139.968 68.224 -140.224 153.152a110.176 110.176 0 0 0 117.952 118.944c31.136 1.28 62.08 -5.728 89.6 -20.288l6.272 23.04zM198.944 276.448c0 25.216 9.824 38.592 29.216 38.592 24.256 0 44.16 -19.2 53.856 -58.592C292.352 215.872 283.2 195.2 254.08 195.2c-33.28 0 -55.136 42.848 -55.136 81.248z\"]\n};\nvar vsMenu = {\n prefix: \"vs\",\n iconName: \"menu\",\n icon: [512, 512, [], \"f000\", \"M512 160H0V128h512v32zm0 256H0v-32h512v32zm0 -128.256H0V256h512v31.744z\"]\n};\nvar vsMerge = {\n prefix: \"vs\",\n iconName: \"merge\",\n icon: [512, 512, [], \"f000\", \"M336 148.672L267.328 80h-22.624L176 148.672l22.624 22.624L233.6 136.352V168.96h-0.64v14.592l0.8 0.032 0.192 10.208c0.128 5.984 0.64 12.128 1.6 18.368 0.96 6.24 2.208 12.48 3.744 18.752 1.536 6.24 3.648 12.928 6.4 20.064 4.96 12.128 10.976 23.104 18.08 32.992 7.072 9.888 14.72 19.136 22.88 27.744 8.16 8.64 16.256 17.12 24.32 25.504 8 8.384 15.296 17.312 21.792 26.816 6.496 9.504 11.776 19.872 15.808 31.136 4 11.232 6.016 24.16 6.016 38.816v28.288H400v-28.288a191.712 191.712 0 0 0 -5.312 -44.48 148.416 148.416 0 0 0 -13.664 -35.2 188 188 0 0 0 -19.328 -28.704c-7.104 -8.64 -14.496 -16.864 -22.176 -24.768 -7.68 -7.872 -15.072 -15.744 -22.176 -23.616a204.48 204.48 0 0 1 -19.328 -25.12 121.408 121.408 0 0 1 -13.856 -29.248 117.632 117.632 0 0 1 -5.12 -36.16V168.96h-0.032v-32l34.368 34.368 22.624 -22.656zM225.344 311.712a262.08 262.08 0 0 0 10.528 -11.808 193.92 193.92 0 0 1 -19.84 -36.8L215.808 262.4a232.32 232.32 0 0 1 -3.04 -8.416c-5.44 8.192 -11.488 15.936 -18.08 23.232 -7.104 7.872 -14.496 15.744 -22.176 23.616 -7.68 7.904 -15.04 16.128 -22.176 24.768 -7.072 8.64 -13.536 18.176 -19.328 28.672a148.576 148.576 0 0 0 -13.664 35.264 191.84 191.84 0 0 0 -5.312 44.448v28.288h45.44v-28.288c0 -14.624 1.984 -27.584 6.016 -38.816 4 -11.264 9.28 -21.632 15.776 -31.136 6.496 -9.504 13.76 -18.432 21.824 -26.816 8.032 -8.384 16.128 -16.864 24.32 -25.504z\"]\n};\nvar vsMilestone = {\n prefix: \"vs\",\n iconName: \"milestone\",\n icon: [512, 512, [], \"f000\", \"M256 32H224v64H48l-16 16v128l16 16H224v224h32V256h143.68l10.88 -4.16 69.76 -64v-23.68l-69.76 -64L400 96H256V32zm137.28 192H64V128h329.28l52.16 48L393.28 224zM160 160h160v32H160V160z\"]\n};\nvar vsMirror = {\n prefix: \"vs\",\n iconName: \"mirror\",\n icon: [512, 512, [], \"f000\", \"M274.24 32l198.4 128 7.36 12.16v294.4l-24.32 13.44L256 352l-199.68 128 -24.32 -13.44v-294.4L39.36 160l198.4 -128h36.48zm-1.92 292.16L448 437.44V180.8l-175.68 -112V160h-32V68.16L64 181.44v256l176.32 -113.92v0.64h32zm28.8 -152.96l22.72 -22.4 79.04 79.36v22.72l-78.72 78.72 -22.4 -22.4L352.64 256h-192L211.2 307.2l-22.4 22.4 -78.72 -78.72v-22.72l79.36 -79.36 22.4 22.4L159.36 224h194.56L301.12 171.2z\"]\n};\nvar vsMortarBoard = {\n prefix: \"vs\",\n iconName: \"mortar-board\",\n icon: [512, 512, [], \"f000\", \"M480 181.12L261.76 96h-11.52L32 181.12V384h32V224l73.92 28.8a139.2 139.2 0 0 0 -25.28 79.36c-0.32 3.52 -0.32 7.04 0 10.56v3.52l8.96 12.8L248.96 416h13.12l126.08 -57.92 8.96 -12.8v-14.08a140.48 140.48 0 0 0 -24.96 -79.04L480 210.24v-29.12zm-112.64 149.76v2.24L256 384l-112 -51.2a4.16 4.16 0 0 1 0 -1.92 110.08 110.08 0 0 1 24 -67.84l82.56 32h11.52l81.92 -32a108.8 108.8 0 0 1 23.36 67.84zM256 264L80.64 195.84 256 128l175.36 68.48L256 264z\"]\n};\nvar vsMove = {\n prefix: \"vs\",\n iconName: \"move\",\n icon: [512, 512, [], \"f000\", \"M327.424 342.624L272 398.08V288h-32v110.08l-55.424 -55.456 -22.624 22.624L244.672 448h22.656l82.72 -82.752 -22.624 -22.624zM161.952 114.752l22.624 22.624L240 81.92V192h32V81.92l55.424 55.456 22.624 -22.624L267.328 32h-22.656L161.952 114.752zm-8.576 53.824L97.92 224H208v32H97.92l55.456 55.424 -22.624 22.624L48 251.328v-22.656l82.752 -82.72 22.624 22.624zM304 224h110.08l-55.456 -55.424 22.624 -22.624L464 228.672v22.656l-82.752 82.72 -22.624 -22.624L414.08 256H304V224z\"]\n};\nvar vsMultipleWindows = {\n prefix: \"vs\",\n iconName: \"multiple-windows\",\n icon: [512, 512, [], \"f000\", \"M192 48l16 -16h256l16 16v224l-16 16H384V256h64V128H224v32H192V48zM224 64v32h224V64H224zM48 224l-16 16v224l16 16h256l16 -16v-224L304 224h-256zM64 288V256h224v32H64zm0 32h224v128H64v-128z\"]\n};\nvar vsMute = {\n prefix: \"vs\",\n iconName: \"mute\",\n icon: [512, 512, [], \"f000\", \"M48 160h89.28l123.52 -122.56 27.2 11.2v416l-27.2 10.56L137.28 352H48l-16 -16v-160l16 -16zm107.2 165.44L256 425.92V87.36L155.2 187.2 144 192H64v128h80l11.2 5.44zm300.192 -131.456l22.624 22.624L422.624 272l55.392 55.424 -22.624 22.624L400 294.624l-55.424 55.424 -22.624 -22.624L377.376 272 321.92 216.64l22.624 -22.624 55.456 55.36 55.392 -55.392z\"]\n};\nvar vsNewFile = {\n prefix: \"vs\",\n iconName: \"new-file\",\n icon: [512, 512, [], \"f000\", \"M304 35.2l108.8 112 3.2 12.8v64h-32V192H256V64H96v352h128v32H80l-16 -16v-384l16 -16h214.4l9.6 3.2zM288 64v96h92.8L288 64zm128 448h-32v-96H288v-32h96V288h32v96h96v32h-96v96z\"]\n};\nvar vsNewFolder = {\n prefix: \"vs\",\n iconName: \"new-folder\",\n icon: [512, 512, [], \"f000\", \"M464 64H246.72l-27.2 -27.2L208.32 32h-160l-16 16v352l16 16H224v-32H63.68V192h143.68l11.2 -4.8 27.52 -27.52H448v48l-0.032 16.32h32.352V80L464 64zm-16.32 64h-208l-11.2 4.8 -27.52 27.52H64v-96h137.28l27.2 27.2 11.52 4.8H448l-0.32 31.68zM416 512h-32v-96H288v-32h96V288h32v96h96v32h-96v96z\"]\n};\nvar vsNoNewline = {\n prefix: \"vs\",\n iconName: \"no-newline\",\n icon: [512, 512, [], \"f000\", \"M74.656 176.192a96 96 0 1 1 106.688 159.648 96 96 0 0 1 -106.688 -159.68zm85.664 24.864A63.552 63.552 0 0 0 64 256.288c0.128 11.296 3.264 22.336 9.056 32.032L160.32 201.056zM95.68 310.944A63.552 63.552 0 0 0 192 255.712a63.616 63.616 0 0 0 -9.056 -32.032L95.68 310.944zM448 160v63.488a16 16 0 0 1 -16 16H299.744L352 187.232l-22.624 -22.624 -67.872 67.872 -13.536 13.536v18.176l81.408 81.408 22.624 -22.624 -51.52 -51.488h131.52a48 48 0 0 0 48 -48V160h-32z\"]\n};\nvar vsNote = {\n prefix: \"vs\",\n iconName: \"note\",\n icon: [512, 512, [], \"f000\", \"M48 64h416l16 16v320l-16 16h-416l-16 -16v-320l16 -16zM64 96v288h384V96H64zm64 64h256v32H128V160zm192 64H128v32h192V224zM128 288h128v32H128V288z\"]\n};\nvar vsNotebookTemplate = {\n prefix: \"vs\",\n iconName: \"notebook-template\",\n icon: [512, 512, [], \"f000\", \"M32 160H0V128h32v32zm0 64H0V192h32v32zm0 64H0V256h32v32zm0 64H0v-32h32v32zm0 64H0v-32h32v32zm0 32v32H0v-32h32zm0 32h32v32H32v-32zm64 0h32v32H96v-32zM32 32H0V0h32v32zm64 0H64V0h32v32zm32 -32h32v32H128V0zm96 32H192V0h32v32zm64 0H256V0h32v32zm64 0h-32V0h32v32zm0 32V32h32v32h-32zm32 64h-32V96h32v32zM32 96H0V64h32v32zm128 96l32 -32h224l32 32v288l-32 32H192l-32 -32V192zm32 0v288h224V192H192zm288 32h32v64h-32V224zm0 96h32v64h-32v-64zm0 96h32v64h-32v-64zM224 256h160v32H224z\"]\n};\nvar vsNotebook = {\n prefix: \"vs\",\n iconName: \"notebook\",\n icon: [512, 512, [], \"f000\", \"M64 64l32 -32h288l32 32v384l-32 32H96l-32 -32V64zm32 0v384h288V64H96zm32 64l32 -32h160l32 32v32l-32 32H160L128 160V128zm32 0v32h160V128H160zm320 32h-32v64h32V160zm-32 96h32v64h-32V256zm32 96h-32v64h32v-64z\"]\n};\nvar vsOctoface = {\n prefix: \"vs\",\n iconName: \"octoface\",\n icon: [512, 512, [], \"f000\", \"M443.616 181.536c3.616 -8.96 15.36 -44.544 -3.648 -92.704 0 0 -29.408 -9.216 -96.32 36.416 -28 -7.84 -57.984 -8.96 -87.648 -8.96 -29.696 0 -59.648 1.12 -87.648 8.96 -66.912 -45.92 -96.32 -36.416 -96.32 -36.416 -19.04 48.16 -7.264 83.744 -3.616 92.704C45.696 205.856 32 237.216 32 275.296c0 144.224 93.248 176.704 223.424 176.704 130.24 0 224.576 -32.48 224.576 -176.672 0 -38.08 -13.728 -69.44 -36.384 -93.792zM256 424.576c-92.416 0 -167.424 -4.224 -167.424 -93.824 0 -21.28 10.624 -41.44 28.544 -57.952 29.952 -27.424 81.184 -12.864 138.88 -12.864 57.952 0 108.64 -14.56 138.88 12.864 18.208 16.512 28.576 36.416 28.576 57.952 0 89.312 -75.072 93.792 -167.456 93.792zM185.728 284.256c-18.496 0 -33.6 22.4 -33.6 49.824 0 27.456 15.104 50.112 33.6 50.112 18.464 0 33.6 -22.4 33.6 -50.112 0 -27.712 -15.136 -49.824 -33.6 -49.824zm140.544 0c-18.464 0 -33.6 22.112 -33.6 49.824s15.136 50.112 33.6 50.112c18.496 0 33.6 -22.4 33.6 -50.112 0 -27.712 -14.816 -49.824 -33.6 -49.824z\"]\n};\nvar vsOpenPreview = {\n prefix: \"vs\",\n iconName: \"open-preview\",\n icon: [512, 512, [], \"f000\", \"M96 32h352l32 32v169.6a102.72 102.72 0 0 0 -32 -9.6V64H288v348.16L252.16 448H96l-32 -32V64l32 -32zm0 384h160V64H96v352zm332.128 -159.936a80.96 80.96 0 0 0 -38.08 11.136h-0.96a80.32 80.32 0 0 0 -25.568 112.96L288 455.36l22.72 22.72 75.2 -75.52c10.4 7.04 22.4 11.456 34.88 12.8a79.04 79.04 0 0 0 36.48 -4.16 80.32 80.32 0 0 0 32 -20.16 78.72 78.72 0 0 0 18.56 -32 84.16 84.16 0 0 0 2.24 -36.8 80.96 80.96 0 0 0 -43.2 -57.92 80.96 80.96 0 0 0 -38.752 -8.256zm7.68 127.744a48 48 0 0 1 -31.328 -7.808 49.6 49.6 0 0 1 -17.92 -21.76 47.68 47.68 0 0 1 -2.56 -27.52 47.68 47.68 0 0 1 37.76 -37.76 47.68 47.68 0 0 1 27.52 2.56c8.832 3.744 16.384 9.952 21.76 17.92a48 48 0 0 1 -35.2 74.368z\"]\n};\nvar vsOrganization = {\n prefix: \"vs\",\n iconName: \"organization\",\n icon: [512, 512, [], \"f000\", \"M291.552 149.216A64 64 0 1 1 220.48 42.784a64 64 0 0 1 71.104 106.432zm-17.76 -79.808A32 32 0 1 0 238.208 122.56a32 32 0 0 0 35.584 -53.12zm83.52 0.96a47.808 47.808 0 0 1 60.64 6.016 48.416 48.416 0 0 1 -15.584 78.72 47.744 47.744 0 0 1 -52.32 -10.432 48.384 48.384 0 0 1 7.296 -74.272zm15.36 51.52a15.968 15.968 0 1 0 22.56 -22.656 16.288 16.288 0 0 0 -11.232 -4.8 15.968 15.968 0 0 0 -16 16.096 16.32 16.32 0 0 0 4.672 11.392zM102.08 399.584H160v32.16H102.08a38.304 38.304 0 0 1 -26.944 -11.424 38.72 38.72 0 0 1 -11.136 -27.2v-57.92a31.904 31.904 0 0 1 -22.72 -10.624A32.224 32.224 0 0 1 32 301.056V231.232c0.096 -15.104 6.08 -29.536 16.64 -40.256 10.528 -10.592 24.768 -16.64 39.68 -16.736H147.2a93.184 93.184 0 0 0 -17.6 32.192H88.32a25.536 25.536 0 0 0 -17.28 7.424 24.864 24.864 0 0 0 -7.04 17.376v71.424h32v90.432a6.464 6.464 0 0 0 1.6 4.832 7.68 7.68 0 0 0 4.48 1.6zm233.6 -208.576a56.48 56.48 0 0 0 -40 -16.736H216.32a56.48 56.48 0 0 0 -39.68 16.736c-10.56 10.72 -16.544 25.152 -16.64 40.256v101.696a33.92 33.92 0 0 0 9.28 23.488 32 32 0 0 0 22.72 10.624v74.336a38.464 38.464 0 0 0 11.2 27.36c5.76 5.376 13.024 8.864 20.8 9.984h64a36.8 36.8 0 0 0 32 -37.344V367.04a31.904 31.904 0 0 0 22.72 -10.624 32.192 32.192 0 0 0 9.28 -23.488V231.232a57.6 57.6 0 0 0 -16.32 -40.256zM320 334.528H288v106.88a6.464 6.464 0 0 1 -1.92 4.48 5.44 5.44 0 0 1 -4.48 1.92H230.08a6.72 6.72 0 0 1 -6.4 -6.4v-106.88H192V231.232c0 -6.496 2.528 -12.736 7.04 -17.376a25.536 25.536 0 0 1 17.28 -7.424h79.36a24.896 24.896 0 0 1 22.56 15.36 23.936 23.936 0 0 1 1.76 9.44v103.296zm89.92 97.184H352v-32.16h57.6a7.68 7.68 0 0 0 4.48 -1.6 6.4 6.4 0 0 0 1.92 -4.864V302.656h32V231.232a24.864 24.864 0 0 0 -7.04 -17.376 25.536 25.536 0 0 0 -17.28 -7.424h-41.28a93.12 93.12 0 0 0 -17.6 -32.192h58.88a56.64 56.64 0 0 1 39.68 16.736c10.56 10.72 16.544 25.152 16.64 40.256v69.824c0 8.736 -3.296 17.12 -9.248 23.456 -5.952 6.368 -14.08 10.176 -22.752 10.656v57.92c0 10.208 -4 19.968 -11.136 27.2a38.304 38.304 0 0 1 -26.944 11.424zM128 62.24a47.808 47.808 0 0 0 -44.352 29.824A48.544 48.544 0 0 0 94.08 144.64 47.904 47.904 0 0 0 176 110.528c0 -12.8 -5.056 -25.088 -14.08 -34.144A47.872 47.872 0 0 0 128 62.24zm0 64.384a15.968 15.968 0 0 1 -16 -16.096 16.128 16.128 0 0 1 16 -16.096 16.288 16.288 0 0 1 16 16.096 16.128 16.128 0 0 1 -16 16.096z\"]\n};\nvar vsOutput = {\n prefix: \"vs\",\n iconName: \"output\",\n icon: [512, 512, [], \"f000\", \"M416 0v32L448 64v416L416 512h-320L64 480V64l32 -32V0H128v32h64V0h32v32h64V0H320v32h64V0h32zm-320 480h320V64h-320v416zM160 128h192v32h-192V128zm192 128h-192v32h192V256zm-192 128h192v32h-192V384z\"]\n};\nvar vsPackage = {\n prefix: \"vs\",\n iconName: \"package\",\n icon: [512, 512, [], \"f000\", \"M275.52 96l183.68 48.96L480 160v215.68l-11.84 15.36 -196.16 54.08 -196.48 -54.08 -11.52 -15.36V160l19.52 -15.04L266.88 96h8.64zm-2.88 32l-128 32 17.6 6.4 109.76 28.8 96 -25.92 30.4 -9.28 -125.76 -32zM96 363.52l160 43.84V224L96 181.12v182.4zM288 224v183.36l160 -43.84V180.16l-64.64 17.696V280l-32 8.32V206.624L288 224z\"]\n};\nvar vsPaintcan = {\n prefix: \"vs\",\n iconName: \"paintcan\",\n icon: [512, 512, [], \"f000\", \"M465.28 377.952l-36.48 -99.84v-1.92l-157.12 -157.12v-39.68a53.12 53.12 0 0 0 -3.52 -18.56 47.36 47.36 0 0 0 -26.56 -25.6 45.44 45.44 0 0 0 -18.56 -3.2 47.04 47.04 0 0 0 -47.36 47.36v104.32l-97.92 96a48.64 48.64 0 0 0 0 67.84l116.16 116.16c4.48 4.512 9.824 8.096 15.68 10.56a48.96 48.96 0 0 0 36.48 0 48.32 48.32 0 0 0 15.68 -10.56l157.76 -157.44 -21.12 70.4a38.08 38.08 0 0 0 0 14.72c1.056 4.864 3.136 9.472 6.08 13.44 3.136 3.872 6.912 7.136 11.2 9.6 4.48 2.24 9.408 3.52 14.4 3.84a32 32 0 0 0 15.36 -2.88 36.48 36.48 0 0 0 12.48 -9.28 31.36 31.36 0 0 0 7.04 -14.08c1.024 -4.64 1.12 -9.408 0.32 -14.08zm-256 -298.56a14.72 14.72 0 0 1 0 -6.4 16.64 16.64 0 0 1 3.84 -5.44 20.48 20.48 0 0 1 5.76 -3.2 16 16 0 0 1 6.72 0 16 16 0 0 1 10.24 4.8 16 16 0 0 1 3.84 10.56v40.32l-32 32 1.6 -72.64zm32 363.2a11.52 11.52 0 0 1 -5.12 3.52 15.04 15.04 0 0 1 -12.16 0 11.552 11.552 0 0 1 -5.12 -3.52l-116.16 -115.84a16 16 0 0 1 0 -22.72l139.2 -139.2v91.2a23.68 23.68 0 0 0 -7.68 17.6 24 24 0 1 0 37.44 -17.6v-90.56l123.2 123.84 -153.6 153.28z\"]\n};\nvar vsPassFilled = {\n prefix: \"vs\",\n iconName: \"pass-filled\",\n icon: [512, 512, [], \"f000\", \"M256 480A224 224 0 1 0 256 32a224 224 0 0 0 0 448zm-32.64 -132.16h-22.72L128 275.2l22.72 -22.72 61.44 61.44 134.4 -134.72 22.72 22.72 -145.92 145.92z\"]\n};\nvar vsPass = {\n prefix: \"vs\",\n iconName: \"pass\",\n icon: [512, 512, [], \"f000\", \"M200.64 347.84h22.72l145.92 -145.92 -22.72 -22.72 -134.4 134.72 -61.44 -61.44L128 275.2l72.64 72.64zM275.2 32c51.2 3.2 99.2 28.8 134.4 64 41.6 44.8 64 99.2 64 163.2 0 51.2 -19.2 99.2 -51.2 140.8 -32 38.4 -76.8 67.2 -128 76.8 -51.2 9.6 -102.4 3.2 -147.2 -22.4 -44.8 -25.6 -80 -64 -99.2 -112C28.8 294.4 25.6 240 41.6 192c16 -51.2 44.8 -92.8 89.6 -121.6C172.8 41.6 224 28.8 275.2 32zm16 412.8c41.6 -9.6 80 -32 108.8 -67.2 25.6 -35.2 41.6 -76.8 38.4 -121.6 0 -51.2 -19.2 -102.4 -54.4 -137.6 -32 -32 -70.4 -51.2 -115.2 -54.4 -41.6 -3.2 -86.4 6.4 -121.6 32 -35.2 25.6 -60.8 60.8 -73.6 105.6 -12.8 41.6 -12.8 86.4 6.4 128 19.2 41.6 48 73.6 86.4 96 38.4 22.4 83.2 28.8 124.8 19.2z\"]\n};\nvar vsPersonAdd = {\n prefix: \"vs\",\n iconName: \"person-add\",\n icon: [512, 512, [], \"f000\", \"M416 320h-32v64h-64v32h64v64h32v-64h64v-32h-64v-64zM273.792 69.408a32 32 0 1 0 -35.584 53.216 32 32 0 0 0 35.584 -53.216zm-53.344 -26.624A64 64 0 1 1 291.52 149.216a64 64 0 0 1 -71.04 -106.432zM216.64 175.68h78.72A56.64 56.64 0 0 1 352 232.32V256h-32v-23.68a24.32 24.32 0 0 0 -24.64 -24.64H216.64a24.32 24.32 0 0 0 -24.64 24.64V320h32v105.92a6.4 6.4 0 0 0 6.4 6.4H256v32.64h-25.6a38.4 38.4 0 0 1 -38.4 -38.4V352a33.92 33.92 0 0 1 -32 -35.2V232.32a56.64 56.64 0 0 1 56.64 -56.64z\"]\n};\nvar vsPerson = {\n prefix: \"vs\",\n iconName: \"person\",\n icon: [512, 512, [], \"f000\", \"M256 64a32 32 0 1 1 0 64 32 32 0 0 1 0 -64zm0 -32a64 64 0 1 0 0 128 64 64 0 0 0 0 -128zm39.36 143.68H216.64A56.64 56.64 0 0 0 160 232.32V316.8A33.92 33.92 0 0 0 192 352v74.56a38.4 38.4 0 0 0 38.4 38.4h51.2a38.4 38.4 0 0 0 38.4 -39.68V352a33.92 33.92 0 0 0 32 -35.2V232.32a56.64 56.64 0 0 0 -56.64 -56.64zM192 320V232.32a24.32 24.32 0 0 1 24.64 -24.64h78.72a24.32 24.32 0 0 1 24.64 24.64V320H288v105.92a6.4 6.4 0 0 1 -6.4 6.4H230.4a6.4 6.4 0 0 1 -6.4 -6.4V320H192z\"]\n};\nvar vsPieChart = {\n prefix: \"vs\",\n iconName: \"pie-chart\",\n icon: [512, 512, [], \"f000\", \"M320 192h124.8A160.192 160.192 0 0 0 320 67.2V192zm0 -157.344A192.16 192.16 0 0 1 480 224H288V32c10.88 0 21.6 0.896 32 2.656zM224 256l32 32h156.8A160.064 160.064 0 0 1 96 256a160.064 160.064 0 0 1 128 -156.8V256zm32 192a192.064 192.064 0 0 0 192 -192H256V64a192.064 192.064 0 0 0 0 384z\"]\n};\nvar vsPin = {\n prefix: \"vs\",\n iconName: \"pin\",\n icon: [512, 512, [], \"f000\", \"M448 160v224h-8.896c-12.992 0 -24.896 -2.752 -35.744 -8.256A80.896 80.896 0 0 1 375.36 352H283.84a110.816 110.816 0 0 1 -17.472 26.496 117.92 117.92 0 0 1 -23.52 20.256c-8.64 5.664 -18.08 9.92 -28.224 12.736a124 124 0 0 1 -31.52 4.512h-16V288H64l-32 -16L64 256h103.104V128h16c10.848 0 21.248 1.504 31.264 4.48 9.984 3.008 19.424 7.264 28.256 12.8A108.928 108.928 0 0 1 283.84 192h91.488a81.92 81.92 0 0 1 28 -23.488c10.816 -5.504 22.72 -8.32 35.744 -8.512H448zm-24.896 34.752a39.104 39.104 0 0 0 -10.24 4.992 47.712 47.712 0 0 0 -13.76 14.752L393.12 224H261.856l-3.744 -10.752a78.624 78.624 0 0 0 -22.752 -33.504C224.864 170.592 205.664 162.88 192 160v224c13.664 -2.816 32.864 -10.56 43.36 -19.744 10.496 -9.184 18.08 -20.352 22.72 -33.504L261.888 320h131.264l5.76 9.504c1.824 3.008 3.904 5.664 6.24 8 2.336 2.336 4.896 4.576 7.744 6.72 2.816 2.208 6.24 3.84 10.24 5.024V194.752z\"]\n};\nvar vsPinnedDirty = {\n prefix: \"vs\",\n iconName: \"pinned-dirty\",\n icon: [512, 512, [], \"f000\", \"M128 64h224v8.896c0 12.992 -2.752 24.896 -8.256 35.744 -5.504 10.848 -13.44 20.16 -23.744 28v91.52c9.824 4.64 18.656 10.496 26.496 17.472a118.4 118.4 0 0 1 17.28 19.136 157.44 157.44 0 0 0 -28.672 13.184l-0.224 0.128 -0.96 0.576a78.592 78.592 0 0 0 -35.168 -24.768L288 250.144V118.88l9.504 -5.76c3.008 -1.824 5.664 -3.904 8 -6.24a72.96 72.96 0 0 0 6.72 -7.744 30.976 30.976 0 0 0 5.024 -10.24H162.752c1.344 4 3.008 7.424 4.992 10.24a47.808 47.808 0 0 0 14.752 13.76L192 118.88v131.264l-10.752 3.744c-13.152 4.672 -24.32 12.256 -33.504 22.752C138.592 287.136 130.88 306.336 128 320h160.064a160.8 160.8 0 0 0 -15.392 24.896H256V448l-16 32 -16 -32v-103.104H96v-16c0 -10.848 1.504 -21.248 4.48 -31.264 3.008 -9.984 7.264 -19.424 12.8 -28.256A108.928 108.928 0 0 1 160 228.16V136.64a81.952 81.952 0 0 1 -23.488 -28A80.16 80.16 0 0 1 128 72.896V64zm239.52 269.12a93.568 93.568 0 0 1 22.976 -9.664c8.192 -2.304 16.704 -3.456 25.504 -3.456s17.312 1.152 25.504 3.456a94.592 94.592 0 0 1 42.272 24.736 94.592 94.592 0 0 1 24.768 42.304c2.304 8.192 3.456 16.704 3.456 25.504s-1.152 17.312 -3.456 25.504a94.496 94.496 0 0 1 -24.768 42.368 96.416 96.416 0 0 1 -42.272 24.768c-8.192 2.24 -16.704 3.36 -25.504 3.36s-17.312 -1.12 -25.504 -3.36a97.184 97.184 0 0 1 -42.368 -24.768 97.184 97.184 0 0 1 -24.736 -42.368A95.808 95.808 0 0 1 320 416c0 -8.8 1.12 -17.312 3.36 -25.504a96.416 96.416 0 0 1 28.256 -45.6c4.928 -4.48 10.24 -8.384 15.904 -11.776z\"]\n};\nvar vsPinned = {\n prefix: \"vs\",\n iconName: \"pinned\",\n icon: [512, 512, [], \"f000\", \"M128 64h224v8.896c0 12.992 -2.752 24.896 -8.256 35.744 -5.504 10.848 -13.44 20.16 -23.744 28v91.52c9.824 4.64 18.656 10.496 26.496 17.472 7.84 7.008 14.592 14.848 20.256 23.52 5.664 8.64 9.92 18.08 12.736 28.224 2.848 10.176 4.352 20.672 4.512 31.52v16H256V448l-16 32 -16 -32v-103.104H96v-16c0 -10.848 1.504 -21.248 4.48 -31.264 3.008 -9.984 7.264 -19.424 12.8 -28.256A108.928 108.928 0 0 1 160 228.16V136.64a81.952 81.952 0 0 1 -23.488 -28A80.16 80.16 0 0 1 128 72.896V64zm34.752 24.896c1.344 4 3.008 7.424 4.992 10.24a47.808 47.808 0 0 0 14.752 13.76L192 118.88v131.264l-10.752 3.744c-13.152 4.672 -24.32 12.256 -33.504 22.752C138.592 287.136 130.88 306.336 128 320h224c-2.816 -13.664 -10.56 -32.864 -19.744 -43.36a78.592 78.592 0 0 0 -33.504 -22.72L288 250.112V118.88l9.504 -5.76c3.008 -1.824 5.664 -3.904 8 -6.24a72.96 72.96 0 0 0 6.72 -7.744 30.976 30.976 0 0 0 5.024 -10.24H162.752z\"]\n};\nvar vsPlayCircle = {\n prefix: \"vs\",\n iconName: \"play-circle\",\n icon: [512, 512, [], \"f000\", \"M275.2 32c51.2 3.2 99.2 28.8 134.4 64 41.6 44.8 64 99.2 64 163.2 0 51.2 -19.2 99.2 -51.2 140.8 -32 38.4 -76.8 67.2 -128 76.8 -51.2 9.6 -102.4 3.2 -147.2 -22.4 -44.8 -25.6 -80 -64 -99.2 -112C28.8 294.4 25.6 240 41.6 192c16 -51.2 44.8 -92.8 89.6 -121.6C172.8 41.6 224 28.8 275.2 32zm16 412.8c41.6 -9.6 80 -32 108.8 -67.2 25.6 -35.2 41.6 -76.8 38.4 -121.6 0 -51.2 -19.2 -102.4 -54.4 -137.6 -32 -32 -70.4 -51.2 -115.2 -54.4 -41.6 -3.2 -86.4 6.4 -121.6 32 -35.2 25.6 -60.8 60.8 -73.6 105.6 -12.8 41.6 -12.8 86.4 6.4 128 19.2 41.6 48 73.6 86.4 96 38.4 22.4 83.2 28.8 124.8 19.2zM192 160l24.864 -13.312 144 96v26.624l-144 96L192 352V160zm32 29.888v132.224L323.168 256 224 189.888z\"]\n};\nvar vsPlay = {\n prefix: \"vs\",\n iconName: \"play\",\n icon: [512, 512, [], \"f000\", \"M120.96 64L96 77.12v384l24.96 13.44 288 -192V256l-288 -192zM128 431.36V107.2l243.2 162.24L128 431.36z\"]\n};\nvar vsPlug = {\n prefix: \"vs\",\n iconName: \"plug\",\n icon: [512, 512, [], \"f000\", \"M224 32H192v96H144l-16 16V256a128 128 0 0 0 112 127.008V480h32v-96.992A128 128 0 0 0 384 256V144l-16 -16H320V32H288v96H224V32zm99.872 291.872A96 96 0 0 1 160 256V160h192v96a96 96 0 0 1 -28.128 67.872z\"]\n};\nvar vsPreserveCase = {\n prefix: \"vs\",\n iconName: \"preserve-case\",\n icon: [512, 512, [], \"f000\", \"M273.088 398.944H237.952l-28.704 -75.936h-114.88l-27.04 75.936H32L135.936 128h32.864l104.32 270.944zm-74.24 -104.48L156.32 179.008a110.528 110.528 0 0 1 -4.16 -18.144h-0.736c-1.28 7.68 -2.72 13.76 -4.352 18.144L104.928 294.464h93.92zm114.304 104.48V128h77.12c23.424 0 41.984 5.76 55.712 17.184 13.76 11.488 20.608 26.4 20.608 44.8 0 15.36 -4.16 28.704 -12.48 40.064 -8.32 11.328 -19.776 19.392 -34.4 24.16v0.768c18.272 2.144 32.896 9.056 43.84 20.8 10.976 11.584 16.448 26.688 16.448 45.344 0 23.168 -8.32 41.92 -24.96 56.32 -16.608 14.336 -37.568 21.504 -62.912 21.504H313.152zm31.744 -242.24v87.488h32.512c17.376 0 31.04 -4.16 40.992 -12.48 9.952 -8.416 14.912 -20.256 14.912 -35.52 0 -26.304 -17.28 -39.456 -51.936 -39.456h-36.48zm0 116.032v97.504h43.072c18.656 0 33.088 -4.416 43.296 -13.248 10.304 -8.8 15.488 -20.896 15.488 -36.256 0 -32 -21.792 -48 -65.376 -48h-36.48z\"]\n};\nvar vsPreview = {\n prefix: \"vs\",\n iconName: \"preview\",\n icon: [512, 512, [], \"f000\", \"M64 64h384l32 32v320l-32 32H64l-32 -32V96l32 -32zm0 352h384V96H64v320zm352 -288H96v96h320V128zm-32 64H128V160h256v32zm-96 192h128V256H288v128zm32 -96h64v64h-64V288zM224 256H96v32h128V256zm-128 96h128v32H96v-32z\"]\n};\nvar vsPrimitiveSquare = {\n prefix: \"vs\",\n iconName: \"primitive-square\",\n icon: [512, 512, [], \"f000\", \"M112 128l16 -16h256l16 16v256l-16 16H128l-16 -16V128zm32 16v224h224v-224h-224z\"]\n};\nvar vsProject = {\n prefix: \"vs\",\n iconName: \"project\",\n icon: [512, 512, [], \"f000\", \"M48 32h416l16 16v416l-16 16h-416l-16 -16v-416l16 -16zM64 448h384V64H64v384zM96 96h64v320H96V96zm192 0H224v192h64V96zm64 0h64v256h-64V96z\"]\n};\nvar vsPulse = {\n prefix: \"vs\",\n iconName: \"pulse\",\n icon: [512, 512, [], \"f000\", \"M377.6 288L320 96H288L229.056 308.48 191.68 150.08h-31.04L123.2 288H32v31.68h103.36l15.68 -11.84 23.68 -86.4L210.88 384h32.96l59.84 -225.28 46.72 149.76 15.36 11.52H480V288h-102.4z\"]\n};\nvar vsQuestion = {\n prefix: \"vs\",\n iconName: \"question\",\n icon: [512, 512, [], \"f000\", \"M240 32a208 208 0 1 0 0 416 208 208 0 0 0 0 -416zm0 384a176 176 0 1 1 0 -352 176 176 0 0 1 0 352zm49.6 -269.44a58.88 58.88 0 0 0 -19.52 -13.44A72 72 0 0 0 240.96 128a69.12 69.12 0 0 0 -28.16 5.44c-7.648 3.2 -14.4 8.128 -19.84 14.4a60.48 60.48 0 0 0 -12.16 19.84 96 96 0 0 0 -4.8 23.04h39.36a26.88 26.88 0 0 1 16.192 -23.712 23.04 23.04 0 0 1 9.728 -1.568 27.52 27.52 0 0 1 8.64 0 20.48 20.48 0 0 1 7.04 4.48 19.2 19.2 0 0 1 5.12 7.04 23.36 23.36 0 0 1 1.92 9.6c0 5.536 -1.184 10.976 -3.52 16a76.8 76.8 0 0 1 -8.64 14.72l-11.2 13.44c-3.84 4.16 -7.68 8.64 -11.2 13.12a74.56 74.56 0 0 0 -8.64 14.4 37.76 37.76 0 0 0 -3.2 16v21.12H256v-15.68a30.08 30.08 0 0 1 3.52 -13.44 98.88 98.88 0 0 1 8.96 -13.12l11.52 -14.08a137.28 137.28 0 0 0 11.52 -15.36 82.88 82.88 0 0 0 8.96 -17.6 61.12 61.12 0 0 0 3.52 -20.48 69.76 69.76 0 0 0 -3.2 -21.44 48.64 48.64 0 0 0 -11.2 -17.6zM217.6 314.56h37.44V352H217.6V314.56z\"]\n};\nvar vsQuote = {\n prefix: \"vs\",\n iconName: \"quote\",\n icon: [512, 512, [], \"f000\", \"M229.12 112C151.36 161.92 113.6 213.44 113.6 299.52c5.12 -1.6 9.6 -1.6 14.08 -1.6 40.64 0 80 27.52 80 77.12 0 51.52 -32.96 83.52 -80 83.52 -60.8 0 -95.68 -48.64 -95.68 -136 0 -121.6 56 -208.96 160.64 -269.44L229.12 112zm224 0c-77.76 49.92 -115.52 101.44 -115.52 187.52 5.12 -1.6 9.6 -1.6 14.08 -1.6 40.64 0 80 27.52 80 77.12 0 51.52 -32.96 83.52 -80 83.52 -60.48 0 -95.36 -48.64 -95.36 -136 0 -121.6 56 -208.96 160.64 -269.44l36.48 58.88h-0.32z\"]\n};\nvar vsRadioTower = {\n prefix: \"vs\",\n iconName: \"radio-tower\",\n icon: [512, 512, [], \"f000\", \"M95.936 178.56a177.6 177.6 0 0 1 51.84 -124.16l-22.72 -22.4a206.4 206.4 0 0 0 0 293.12l22.72 -22.4a177.6 177.6 0 0 1 -51.84 -124.16zm33.92 0a141.44 141.44 0 0 0 42.24 101.44l22.72 -22.72a104.64 104.64 0 0 1 -24.32 -35.84 110.4 110.4 0 0 1 0 -85.44 103.04 103.04 0 0 1 24.32 -36.16l-22.72 -22.72a142.72 142.72 0 0 0 -42.24 101.44zm244.8 102.72l-22.72 -22.72c10.56 -10.24 18.88 -22.528 24.32 -36.16a110.368 110.368 0 0 0 0 -85.44 103.04 103.04 0 0 0 -24.32 -36.16l22.72 -22.4a142.976 142.976 0 0 1 0 202.88zM418.176 32l-22.72 22.72a173.76 173.76 0 0 1 0 247.68l22.72 22.72a206.4 206.4 0 0 0 0 -293.12zM319.776 173.76a48 48 0 0 1 -7.84 31.36 64 64 0 0 1 -8.64 7.36l110.08 247.36 -29.44 12.8 -24.64 -55.36h-177.28l-24.64 55.36 -29.44 -12.8 110.08 -247.36a48.64 48.64 0 0 1 -10.56 -52.16 49.6 49.6 0 0 1 17.92 -21.76 48 48 0 0 1 74.4 35.2zm-51.04 -10.88a16.64 16.64 0 0 0 -8 4.48 16.64 16.64 0 0 0 -3.52 7.04 15.36 15.36 0 0 0 0 9.28c1.28 2.88 3.264 5.44 5.76 7.36a17.28 17.28 0 0 0 8.96 2.56 16.32 16.32 0 0 0 16 -16 17.28 17.28 0 0 0 -2.56 -8.96 18.56 18.56 0 0 0 -7.36 -5.76 15.36 15.36 0 0 0 -9.28 0zm7.36 65.6h-8.64l-27.84 62.08h64l-27.52 -62.08zm70.4 158.08l-28.48 -64h-92.16l-28.48 64h149.12z\"]\n};\nvar vsReactions = {\n prefix: \"vs\",\n iconName: \"reactions\",\n icon: [512, 512, [], \"f000\", \"M384 240c0 5.408 -0.32 10.752 -0.864 16h32.16A176 176 0 1 0 256 415.296v-32.16A144 144 0 1 1 384 240zM176 224a32 32 0 1 0 0 -64 32 32 0 0 0 0 64zm64 80c22.784 0 43.36 -9.536 57.92 -24.832l22.624 22.656A111.68 111.68 0 0 1 240 336a111.68 111.68 0 0 1 -81.76 -35.456l22.624 -22.656A79.808 79.808 0 0 0 240 304zm64 -80a32 32 0 1 0 0 -64 32 32 0 0 0 0 64zm80 96h32v64h64v32h-64v64h-32v-64h-64v-32h64v-64z\"]\n};\nvar vsRecordKeys = {\n prefix: \"vs\",\n iconName: \"record-keys\",\n icon: [512, 512, [], \"f000\", \"M448 96H96a32 32 0 0 0 -32 32v224a32 32 0 0 0 32 32h352a32 32 0 0 0 32 -32V128a32 32 0 0 0 -32 -32zm0 256H96V128h352v224zm-96 -192h-32v32h32V160zm-32 64H288v32h32V224zm64 -64h32v32h-32V160zm32 128h-32v32h32V288zM192 288h160v32H192V288zm224 -64h-64v32h64V224zM256 160h32v32H256V160zm0 64H224v32h32V224zM128 288h32v32H128V288zm0 -128h32v32H128V160zm96 0H192v32h32V160zM128 224h64v32H128V224z\"]\n};\nvar vsRecord = {\n prefix: \"vs\",\n iconName: \"record\",\n icon: [512, 512, [], \"f000\", \"M256 320a64 64 0 1 0 0 -128 64 64 0 0 0 0 128zm19.2 -288c51.2 3.2 99.2 28.8 134.4 64 41.6 44.8 64 99.2 64 163.2 0 51.2 -19.2 99.2 -51.2 140.8 -32 38.4 -76.8 67.2 -128 76.8 -51.2 9.6 -102.4 3.2 -147.2 -22.4 -44.8 -25.6 -80 -64 -99.2 -112C28.8 294.4 25.6 240 41.6 192c16 -51.2 44.8 -92.8 89.6 -121.6C172.8 41.6 224 28.8 275.2 32zm16 412.8c41.6 -9.6 80 -32 108.8 -67.2 25.6 -35.2 41.6 -76.8 38.4 -121.6 0 -51.2 -19.2 -102.4 -54.4 -137.6 -32 -32 -70.4 -51.2 -115.2 -54.4 -41.6 -3.2 -86.4 6.4 -121.6 32 -35.2 25.6 -60.8 60.8 -73.6 105.6 -12.8 41.6 -12.8 86.4 6.4 128 19.2 41.6 48 73.6 86.4 96 38.4 22.4 83.2 28.8 124.8 19.2z\"]\n};\nvar vsRedo = {\n prefix: \"vs\",\n iconName: \"redo\",\n icon: [512, 512, [], \"f000\", \"M400 64v112L384 192H272V160h80.672l-30.112 -30.112a113.664 113.664 0 1 0 -160.736 160.736l166.304 166.336 -23.04 23.04 -166.336 -166.336A146.24 146.24 0 0 1 345.6 106.848l22.4 22.4V64h32z\"]\n};\nvar vsReferences = {\n prefix: \"vs\",\n iconName: \"references\",\n icon: [512, 512, [], \"f000\", \"M236.907 97.301l-73.173 73.109 -24.192 -23.893 44.16 -44.373h-102.4a51.2 51.2 0 1 0 0 102.4h18.987v34.133h-18.773a85.333 85.333 0 0 1 0 -170.475h102.4L139.52 24.107 163.733 0l73.173 73.216v24.107zM354.56 512h-204.8l-17.067 -17.067V222.123l17.067 -17.067h204.8l17.067 17.067V494.933l-17.067 17.067zm-187.733 -34.133h170.667V239.189h-170.667V477.867zm119.467 -443.691h204.8l17.067 17.067v272.768l-17.067 17.067h-85.333v-34.133h68.267V68.267h-170.667v102.123h-34.133V51.221l17.067 -17.067zm17.067 238.635h-102.4v34.133h102.4v-34.133zm-102.4 68.267h102.4v34.133h-102.4v-34.133zm102.4 68.267h-102.4v34.133h102.4v-34.133zm34.133 -307.2h102.4v34.133h-102.4v-34.133zm102.4 136.533h-34.133v34.133h34.133v-34.133zm-71.211 -67.755v-0.512h71.211v34.133h-37.589l-33.621 -33.621z\"]\n};\nvar vsRefresh = {\n prefix: \"vs\",\n iconName: \"refresh\",\n icon: [512, 512, [], \"f000\", \"M149.792 96H64V64h112l16 16V192H160V128a160 160 0 1 0 144.96 -24.352l9.664 -30.528A192 192 0 1 1 149.792 96z\"]\n};\nvar vsRegex = {\n prefix: \"vs\",\n iconName: \"regex\",\n icon: [512, 512, [], \"f000\", \"M320.384 64h31.232v99.616l81.92 -49.824 15.552 28.32L367.04 192l82.048 49.888 -15.52 28.32 -81.952 -49.824V320h-31.232V220.384l-81.92 49.824 -15.552 -28.32L304.96 192 222.912 142.112l15.52 -28.32 81.952 49.824V64zM64 320h128v128H64v-128z\"]\n};\nvar vsRemoteExplorer = {\n prefix: \"vs\",\n iconName: \"remote-explorer\",\n icon: [512, 512, [], \"f000\", \"M28.672 45.333h433.323l16.683 16.661v183.445a166.933 166.933 0 0 0 -33.344 -19.456V78.677H45.333V378.667h166.677a166.677 166.677 0 0 0 33.323 100.011H112v-33.344h100.011v-33.344H28.672l-16.683 -16.64V61.973l16.683 -16.661zM378.667 245.333a133.333 133.333 0 1 0 0 266.667 133.333 133.333 0 0 0 0 -266.667zm0 233.344a100.011 100.011 0 1 1 0 -200.043 100.011 100.011 0 0 1 0 200.043zm55.531 -66.816L388.267 365.931 434.197 320l13.803 13.781 -32.128 32.149L448 398.059l-13.803 13.803zM320 367.915l32.128 32.149L320 432.192l13.803 13.803 45.931 -45.931 -45.931 -45.931 -13.803 13.781z\"]\n};\nvar vsRemote = {\n prefix: \"vs\",\n iconName: \"remote\",\n icon: [512, 512, [], \"f000\", \"M412.928 306.24L285.696 179.072l127.232 -127.232 -19.808 -19.84L256 169.152v19.808l137.12 137.12 19.84 -19.776zM96 179.84l130.304 130.24L96 440.416l19.808 19.776L256 320v-19.808L115.808 160 96 179.808z\"]\n};\nvar vsRemove = {\n prefix: \"vs\",\n iconName: \"remove\",\n icon: [512, 512, [], \"f000\", \"M480 256H32V224h448v32z\"]\n};\nvar vsReplaceAll = {\n prefix: \"vs\",\n iconName: \"replace-all\",\n icon: [512, 512, [], \"f000\", \"M371.2 85.664c4.704 -9.92 11.392 -14.88 20.032 -14.88 7.936 0 14.08 3.776 18.336 11.296 4.288 7.552 6.432 17.824 6.432 30.912 0 14.176 -2.496 25.536 -7.52 34.144 -4.992 8.576 -11.68 12.864 -20.064 12.864 -7.584 0 -13.312 -4 -17.184 -11.968h-0.256v9.92H352V32h18.976v53.664h0.256zm-0.512 35.2a24.96 24.96 0 0 0 3.424 13.632c2.272 3.616 5.216 5.408 8.768 5.408 4.352 0 7.68 -2.304 10.048 -6.912 2.4 -4.64 3.616 -11.2 3.616 -19.68 0 -7.04 -1.12 -12.48 -3.328 -16.448 -2.144 -3.968 -5.248 -5.984 -9.28 -5.984 -3.84 0 -7.008 1.984 -9.504 5.92a28.352 28.352 0 0 0 -3.744 15.36v8.704zM131.84 246.24L64 178.176l21.184 -21.184 32.192 32v-48.32A44.48 44.48 0 0 1 161.76 96H236.8v28.96H161.76a15.68 15.68 0 0 0 -14.976 15.776l0.224 48 30.368 -30.208 20.992 20.992 -66.56 66.72zM299.392 157.76H320V103.04C320 77.056 309.92 64 289.792 64c-4.32 0 -9.12 0.768 -14.4 2.336a46.208 46.208 0 0 0 -12.416 5.344v21.28c7.584 -6.496 15.584 -9.728 24 -9.728 8.352 0 12.544 4.992 12.544 15.008l-19.2 3.296c-16.192 2.752 -24.32 12.992 -24.32 30.752 0 8.416 1.952 15.136 5.856 20.192A19.52 19.52 0 0 0 278.08 160c9.28 0 16.288 -5.12 21.024 -15.36h0.288v13.12zm0.128 -43.36v6.176a24 24 0 0 1 -3.84 13.952 11.776 11.776 0 0 1 -10.016 5.44 8.832 8.832 0 0 1 -7.04 -3.04 12.16 12.16 0 0 1 -2.56 -7.936c0 -7.104 3.52 -11.232 10.624 -12.448l12.8 -2.144zM224 413.76h-20.608v-13.12h-0.288c-4.736 10.24 -11.744 15.36 -21.024 15.36a19.52 19.52 0 0 1 -16.224 -7.52c-3.904 -5.056 -5.856 -11.776 -5.856 -20.16 0 -17.792 8.128 -28.032 24.32 -30.784l19.2 -3.296c0 -10.016 -4.16 -15.04 -12.544 -15.04 -8.416 0 -16.416 3.264 -24 9.76v-21.28c3.04 -2.016 7.168 -3.808 12.416 -5.344 5.28 -1.568 10.08 -2.336 14.4 -2.336 20.16 0 30.208 13.024 30.208 39.04v54.72zm-20.48 -37.184v-6.176l-12.8 2.176c-7.104 1.184 -10.656 5.312 -10.656 12.416 0 3.2 0.864 5.856 2.56 7.936a8.832 8.832 0 0 0 7.04 3.04 11.776 11.776 0 0 0 9.984 -5.44c2.56 -3.712 3.84 -8.32 3.84 -13.952zM296.384 416c10.272 0 18.176 -1.856 23.616 -5.536v-22.72a28.8 28.8 0 0 1 -17.664 6.624 19.808 19.808 0 0 1 -16 -6.88c-3.84 -4.64 -5.792 -11.04 -5.792 -19.136 0 -8.32 2.016 -14.848 6.048 -19.584a20.608 20.608 0 0 1 16.512 -7.136c6.208 0 11.84 2.208 16.896 6.624v-23.968c-4.128 -2.88 -10.816 -4.288 -20.032 -4.288 -13.344 0 -24.032 4.48 -32.032 13.504 -7.968 8.96 -11.936 21.184 -11.936 36.736 0 13.44 3.712 24.448 11.168 32.96 7.424 8.544 17.184 12.8 29.216 12.8zM64 288l32 -32h288l32 32v160l-32 32H96l-32 -32V288zm32 0v160h288V288H96zm96 -64l32 -32h224l32 32v160l-32 32V224H192z\"]\n};\nvar vsReplace = {\n prefix: \"vs\",\n iconName: \"replace\",\n icon: [512, 512, [], \"f000\", \"M103.072 119.648l72.352 72.608L246.4 121.088l-22.4 -22.4 -32.384 32.224 -0.256 -51.2a16.736 16.736 0 0 1 16 -16.832H256V32H207.36A47.424 47.424 0 0 0 160 79.648V131.2L125.664 97.056l-22.592 22.592zm213.44 57.408h0.32c5.856 9.952 14.432 14.944 25.792 14.944 12.576 0 22.592 -5.376 30.08 -16.096 7.552 -10.72 11.296 -24.96 11.296 -42.656 0 -16.352 -3.2 -29.216 -9.632 -38.624 -6.432 -9.44 -15.616 -14.144 -27.52 -14.144 -12.96 0 -22.976 6.208 -30.016 18.592h-0.32V32H288v157.408h28.48v-12.352zm-0.48 -33.952v-10.88c0 -7.936 1.856 -14.336 5.6 -19.232a17.28 17.28 0 0 1 14.24 -7.36 15.68 15.68 0 0 1 13.952 7.456c3.328 4.928 4.96 11.776 4.96 20.576 0 10.56 -1.792 18.784 -5.408 24.576a16.768 16.768 0 0 1 -15.04 8.64 15.84 15.84 0 0 1 -13.152 -6.752 27.296 27.296 0 0 1 -5.12 -17.024zM288 408.608c-8.192 4.928 -20 7.392 -35.456 7.392 -18.016 0 -32.64 -5.696 -43.808 -17.056 -11.168 -11.36 -16.736 -26.016 -16.736 -43.968 0 -20.736 5.952 -37.056 17.92 -48.96 11.968 -12.032 28 -18.016 48 -18.016 13.856 0 23.872 1.92 30.08 5.728v31.936a40.32 40.32 0 0 0 -25.344 -8.832c-10.4 0 -18.656 3.2 -24.768 9.536 -6.08 6.272 -9.056 14.976 -9.056 26.112 0 10.816 2.88 19.296 8.704 25.504 5.824 6.112 13.792 9.184 23.968 9.184 9.024 0 17.856 -2.944 26.496 -8.832v30.272zM128 224L96 256v192l32 32h224l32 -32V256l-32 -32H128zm0 32h224v192H128V256z\"]\n};\nvar vsReply = {\n prefix: \"vs\",\n iconName: \"reply\",\n icon: [512, 512, [], \"f000\", \"M201.792 68.672l-128.64 128.64v22.656l128.64 128.64 22.656 -22.624L121.824 223.36H182.08c90.016 0 147.36 19.36 182.56 55.328 35.264 36 51.68 92.064 51.68 173.472v11.2h32v-11.2c0 -84.672 -16.864 -151.04 -60.8 -195.872C343.52 211.36 275.744 191.36 182.08 191.36H124.384l100.064 -100.032 -22.656 -22.656z\"]\n};\nvar vsRepoClone = {\n prefix: \"vs\",\n iconName: \"repo-clone\",\n icon: [512, 512, [], \"f000\", \"M416 320H128V64h128V32H119.68a60.8 60.8 0 0 0 -21.44 4.16 53.12 53.12 0 0 0 -18.24 13.12 55.36 55.36 0 0 0 -11.84 18.88 53.76 53.76 0 0 0 -4.16 19.84v304a56 56 0 0 0 34.24 51.84 60.8 60.8 0 0 0 21.44 4.16H128v-32h-8.32a23.04 23.04 0 0 1 -9.28 -1.92 24.96 24.96 0 0 1 -12.8 -12.8 29.76 29.76 0 0 1 0 -9.28v-16a29.76 29.76 0 0 1 0 -9.28 24.96 24.96 0 0 1 12.8 -12.8 23.04 23.04 0 0 1 9.28 -1.92H416v64H288v32h144l16 -16V288h-32v32zM192 96H160v32h32V96zM160 160h32v32H160V160zm0 64h32v32H160V224zm8.96 256H160v-96h96v96h-8.96L208 431.68 168.96 480zM320 32h144l16 16v192l-16 16H384v32h-32V256h-32a32 32 0 0 1 -32 -32V64a32 32 0 0 1 32 -32zm16 192h16V192h-16a16 16 0 0 0 0 32zM384 224h64V192h-64v32zm-32 -64h96V64h-96v96z\"]\n};\nvar vsRepoForcePush = {\n prefix: \"vs\",\n iconName: \"repo-force-push\",\n icon: [512, 512, [], \"f000\", \"M119.68 32h312.32l16 16v384l-16 16H320v-32h96v-64h-96v-32h96V64H128v256h96v32H119.68a23.68 23.68 0 0 0 -23.68 24v16a23.68 23.68 0 0 0 23.68 24H224v32H119.68A55.68 55.68 0 0 1 64 392v-304A55.68 55.68 0 0 1 119.68 32zm51.2 154.56l22.72 22.4L256 146.56v46.4L172.16 276.8l22.72 22.4 61.44 -61.44V480h32V234.496l64.96 64.704 22.4 -22.4L288 188.8V145.216l64 63.744 22.4 -22.4L284.16 96h-22.72L170.88 186.56z\"]\n};\nvar vsRepoForked = {\n prefix: \"vs\",\n iconName: \"repo-forked\",\n icon: [512, 512, [], \"f000\", \"M448 128a64 64 0 1 0 -79.04 62.08V224a15.36 15.36 0 0 1 -8.64 14.08L271.68 284.16l-88.32 -44.8A15.68 15.68 0 0 1 174.72 224V190.08a64 64 0 1 0 -32 0V224a48.32 48.32 0 0 0 26.24 42.88L256 311.68v42.24a64 64 0 1 0 32 0V311.68l86.4 -43.52A47.68 47.68 0 0 0 400.64 224V189.44A64 64 0 0 0 448 128zM128 128a32 32 0 1 1 64 0 32 32 0 0 1 -64 0zm175.04 288a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zM384 160a32 32 0 1 1 0 -64 32 32 0 0 1 0 64z\"]\n};\nvar vsRepoPull = {\n prefix: \"vs\",\n iconName: \"repo-pull\",\n icon: [512, 512, [], \"f000\", \"M416 48V96h-32V64H96v256h320v112l-16 16H256v-32h128v-64H87.52a23.04 23.04 0 0 0 -9.12 1.92 23.68 23.68 0 0 0 -12.8 12.8 29.76 29.76 0 0 0 -1.6 9.28v16a29.76 29.76 0 0 0 1.6 9.28 23.68 23.68 0 0 0 12.8 12.8c2.912 1.28 6.08 1.92 9.28 1.92H96v32h-8.32a60.8 60.8 0 0 1 -21.44 -4.16 56.64 56.64 0 0 1 -30.08 -30.4 54.4 54.4 0 0 1 -4.16 -21.44v-304a54.4 54.4 0 0 1 4.16 -19.84 56.64 56.64 0 0 1 30.08 -32A60.8 60.8 0 0 1 87.68 32h312.32l16 16zM64 325.44V87.936v237.504zM160 96H128v32h32V96zm0 64H128v32h32V160zM128 224h32v32H128V224zm258.24 -115.52l-22.4 22.72 61.44 61.44H224v32h204.48l-64.64 64.96 22.4 22.4 90.56 -90.24v-22.72l-90.56 -90.56zM176 431.68L136.96 480H128v-96h96v96h-8.96L176 431.68z\"]\n};\nvar vsRepoPush = {\n prefix: \"vs\",\n iconName: \"repo-push\",\n icon: [512, 512, [], \"f000\", \"M432 32H119.68A55.68 55.68 0 0 0 64 88v304A55.68 55.68 0 0 0 119.68 448H224v-32H119.68a23.68 23.68 0 0 1 -23.68 -24v-16a23.68 23.68 0 0 1 23.68 -24H224v-32H128V64h288v256h-96v32h96v64h-96v32h112l16 -16v-384l-16 -16zM96 87.36a24 24 0 0 0 0 0.64v237.44zM192 96H160v32h32V96zm-19.84 180.8l22.72 22.4 61.44 -61.44V480h32V234.496l64.96 64.704 22.4 -22.4 -90.24 -90.56h-22.72L172.16 276.8zM160 160h32v32H160V160z\"]\n};\nvar vsRepo = {\n prefix: \"vs\",\n iconName: \"repo\",\n icon: [512, 512, [], \"f000\", \"M448 320V48l-16 -16H119.68a60.8 60.8 0 0 0 -21.44 4.16 56.64 56.64 0 0 0 -30.08 32 54.4 54.4 0 0 0 -4.16 19.84v304a54.4 54.4 0 0 0 4.16 21.44c5.664 13.664 16.48 24.576 30.08 30.4a60.8 60.8 0 0 0 21.44 4.16H128v-32h-8.32a23.04 23.04 0 0 1 -9.28 -1.92 23.68 23.68 0 0 1 -12.8 -12.8 29.76 29.76 0 0 1 -1.6 -9.28v-16a29.76 29.76 0 0 1 1.6 -9.28 23.68 23.68 0 0 1 12.8 -12.8 23.04 23.04 0 0 1 9.152 -1.92H416v64H288v32h144l16 -16V320zM128 320V64h288v256H128zm32 -224h32v32H160V96zm0 64h32v32H160V160zm32 64H160v32h32V224zm16 207.68L168.96 480H160v-96h96v96h-8.96L208 431.68z\"]\n};\nvar vsReport = {\n prefix: \"vs\",\n iconName: \"report\",\n icon: [512, 512, [], \"f000\", \"M48 32h416l16 16v320l-16 16H246.624l-91.296 91.328L128 464V384H48l-16 -16v-320l16 -16zm192 320H448V64H64v288h80l16 16v57.376l68.672 -68.704L240 352zm0 -256h32v160h-32V96zm0 224h32V288h-32v32z\"]\n};\nvar vsRequestChanges = {\n prefix: \"vs\",\n iconName: \"request-changes\",\n icon: [512, 512, [], \"f000\", \"M464 32h-416l-16 16v320l16 16H128v80l27.328 11.328L246.624 384H464l16 -16v-320l-16 -16zM448 352H240l-11.328 4.672L160 425.376V368l-16 -16H64V64h384v288zm-128 -32H192V287.328h128V320zM240 96h32v64h64v32h-64v64h-32V192h-64V160h64V96z\"]\n};\nvar vsRocket = {\n prefix: \"vs\",\n iconName: \"rocket\",\n icon: [512, 512, [], \"f000\", \"M463.712 32c-115.136 0.128 -212.928 63.456 -282.72 128H48l-16 16v96l4.704 11.328 31.712 31.712 0.032 0.288 128 128 0.288 0.032 31.968 31.968L240 480h96l16 -16v-132.928c64.608 -69.696 127.872 -167.456 127.744 -283.072l-16.032 -16zM64 192h84.576a762.496 762.496 0 0 0 -71.2 86.72L64 265.408V192zm182.4 256l-13.44 -13.536a754.88 754.88 0 0 0 86.88 -70.912V448H246.4zm-36.576 -36.608L100.352 301.984C132.096 256 268.128 75.36 447.296 64.512c-10.432 179.584 -191.584 315.296 -237.472 346.88zM128 480v-32H64v-64H32v96h96zm215.936 -245.344a48 48 0 1 0 -79.872 -53.312 48 48 0 0 0 79.84 53.312z\"]\n};\nvar vsRootFolderOpened = {\n prefix: \"vs\",\n iconName: \"root-folder-opened\",\n icon: [512, 512, [], \"f000\", \"M32 200.224V80l16 -16h160l11.2 4.8 27.52 27.2h185.28l16 16V192h36.16l15.36 20.16 -84.16 224 -15.36 11.84H279.776a175.36 175.36 0 0 0 21.024 -32h87.36l75.84 -192H279.776a177.088 177.088 0 0 0 -23.04 -23.168l4.064 -4.032L272 192H416V128H240l-11.2 -4.8L201.28 96H64l0.32 83.008c-11.552 5.888 -22.4 13.024 -32.32 21.216zM192 336a48 48 0 1 1 -96 0 48 48 0 0 1 96 0zm64 0a112 112 0 1 1 -224 0 112 112 0 0 1 224 0zM144 416a80 80 0 1 0 0 -160 80 80 0 0 0 0 160z\"]\n};\nvar vsRootFolder = {\n prefix: \"vs\",\n iconName: \"root-folder\",\n icon: [512, 512, [], \"f000\", \"M246.72 96h217.28l16.32 16v320l-16 16H279.776a175.36 175.36 0 0 0 21.024 -32h146.88v-48.32l0.32 -128v-48H246.08l-0.544 0.544a175.808 175.808 0 0 0 -28.192 -16.256l11.136 -11.168 11.2 -4.8h208l0.32 -31.68H240l-11.52 -4.8 -27.2 -27.2H64V179.2a174.4 174.4 0 0 0 -31.68 20.768V80l16 -16h160l11.2 4.8 27.2 27.2zM192 336a48 48 0 1 1 -96 0 48 48 0 0 1 96 0zm64 0a112 112 0 1 1 -224 0 112 112 0 0 1 224 0zM144 416a80 80 0 1 0 0 -160 80 80 0 0 0 0 160z\"]\n};\nvar vsRss = {\n prefix: \"vs\",\n iconName: \"rss\",\n icon: [512, 512, [], \"f000\", \"M160 416H96v-64c35.52 0 64 28.48 64 64zM96 96v32a288 288 0 0 1 288 288h32C416 239.36 272.64 96 96 96zm0 128v32c88 0 160 72 160 160h32c0 -105.92 -86.08 -192 -192 -192z\"]\n};\nvar vsRuby = {\n prefix: \"vs\",\n iconName: \"ruby\",\n icon: [512, 512, [], \"f000\", \"M32 230.08l212.48 212.48h23.04L480 230.08v-23.04l-106.24 -106.24 -11.52 -4.8H149.76l-11.52 4.8L32 207.04v23.04zm224 177.92L66.56 218.56 156.48 128h199.04l89.92 90.56L256 408zm0 -247.36h86.08l57.92 57.92 -144 140.8V160.64z\"]\n};\nvar vsRunAbove = {\n prefix: \"vs\",\n iconName: \"run-above\",\n icon: [512, 512, [], \"f000\", \"M56.64 32.32L32 45.44v384l24.96 13.44 288 -192v-26.56l-288.32 -192zM64 399.68V75.52l243.2 162.24L64 399.68zM388.8 256h22.72l80 80 -22.72 22.72L416 305.92V480h-32V305.6l-52.8 52.8 -22.4 -22.4 80 -80z\"]\n};\nvar vsRunAll = {\n prefix: \"vs\",\n iconName: \"run-all\",\n icon: [512, 512, [], \"f000\", \"M88.96 64L64 77.12v384l24.96 13.44 288 -192V256l-288 -192zM96 431.36V107.2l243.2 162.24L96 431.36zm96 38.496l280.96 -187.296V256L192 68.704V107.2l243.2 162.24L192 431.36v38.496z\"]\n};\nvar vsRunBelow = {\n prefix: \"vs\",\n iconName: \"run-below\",\n icon: [512, 512, [], \"f000\", \"M57.6 32.32l-24.96 13.12v384l24.96 13.44 288 -192v-26.56l-288 -192zm7.04 367.36V75.52l243.2 162.24 -243.2 161.92zM411.2 480h-22.72l-80 -80 22.72 -22.72L384 430.08V256h32v174.4l52.8 -52.8 22.72 22.72L411.2 480z\"]\n};\nvar vsRunErrors = {\n prefix: \"vs\",\n iconName: \"run-errors\",\n icon: [512, 512, [], \"f000\", \"M160 77.12L184.96 64l288 192v26.56L288 405.856v-38.4l147.2 -98.016L192 107.2V224H160V77.12zm-4.096 172.736c-27.2 -1.696 -54.56 5.088 -76.896 20.512 -24.096 15.52 -39.456 37.888 -47.968 64.96 -8.608 25.92 -6.816 55.04 3.392 80.576a120.768 120.768 0 0 0 53.056 59.936c24.192 13.824 51.712 17.184 78.944 12.096 27.552 -5.184 51.52 -20.64 68.576 -41.12l0.16 -0.192c16.928 -21.984 27.264 -47.648 27.264 -75.264a124.224 124.224 0 0 0 -34.112 -87.04l-0.192 -0.16c-18.72 -18.72 -44.416 -32.576 -72.224 -34.304zM94.432 293.856c16.384 -11.936 37.504 -16.544 57.344 -15.04h0.032c20.992 1.536 39.04 10.496 54.304 25.728 16.512 16.512 25.696 40.768 25.696 65.216v0.448c1.504 20.768 -5.856 40.32 -18.112 57.248 -13.632 16.576 -31.776 27.2 -51.52 31.712a80.384 80.384 0 0 1 -58.56 -9.024c-18.304 -10.656 -32 -25.856 -41.216 -45.76 -8.96 -19.424 -9.024 -40.48 -2.912 -60.32v-0.128a91.68 91.68 0 0 1 34.944 -50.08zm49.728 58.56L105.344 311.936l-20.416 20.384 39.04 40.64 -39.04 40.64 20.416 20.384L144.16 393.6l38.816 40.448 20.416 -20.384 -39.008 -40.64 39.008 -40.64 -20.416 -20.384 -38.816 40.416z\"]\n};\nvar vsSaveAll = {\n prefix: \"vs\",\n iconName: \"save-all\",\n icon: [512, 512, [], \"f000\", \"M475.2 84.8l-48 -48L416 32H143.36l-16 16V128H48l-16 16v320l16 16h320l16 -16V384h80l16 -16V96l-4.8 -11.2zM352 448H64V160h32v98.24h192V160h25.28L352 198.72V448zM192 224V160h64v64H192zm256 128h-64V192l-4.8 -11.2 -48 -48L320 128H160V64h249.92l38.72 38.72L448 352z\"]\n};\nvar vsSaveAs = {\n prefix: \"vs\",\n iconName: \"save-as\",\n icon: [512, 512, [], \"f000\", \"M353.28 42.56L406.72 96l9.28 22.72v10.56h-16l-16 16v-26.56l-53.44 -53.44H320v128H128v-128H64v320h96l-16 32H64l-32 -32v-320l32 -32h266.56l22.72 9.28zM224 160h64V64H224v96zm208 0L480 208l-0.64 22.08 -176 176 -4.16 3.84 -11.84 11.84 -3.2 2.88 -96 48 -21.44 -21.44 48 -96 2.88 -3.2 11.84 -11.84 3.84 -4.16 176 -176h22.72zm-199.04 231.68l-16.64 32 33.28 -15.36 -16.64 -16.64zm22.08 -32.96l25.28 25.28 164.8 -164.8 -25.28 -25.28 -164.8 164.8z\"]\n};\nvar vsSave = {\n prefix: \"vs\",\n iconName: \"save\",\n icon: [512, 512, [], \"f000\", \"M427.296 36.672l48 48L480 96v368l-16 16h-416l-16 -16v-416l16 -16H416l11.296 4.672zM64 64v384h384V102.656L409.376 64H352v128H128V64H64zm192 0v96h64V64H256z\"]\n};\nvar vsScreenFull = {\n prefix: \"vs\",\n iconName: \"screen-full\",\n icon: [512, 512, [], \"f000\", \"M96 384h320V128H96v256zm64 -192h192v128H160V192zM64 192H32V80l16 -16H160v32H64v96zm416 -112V192h-32V96h-96V64h112l16 16zM448 320h32v112l-16 16H352v-32h96v-96zM64 416h96v32H48l-16 -16V320h32v96z\"]\n};\nvar vsScreenNormal = {\n prefix: \"vs\",\n iconName: \"screen-normal\",\n icon: [512, 512, [], \"f000\", \"M112 128H32V96h64V32h32v80l-16 16zM416 96V32h-32v80l16 16H480V96h-64zm-32 304V480h32v-64h64v-32h-80l-16 16zM32 384v32h64v64h32v-80l-16 -16H32zm352 -48l-16 16h-224l-16 -16v-160l16 -16h224l16 16v160zM320 224H192v64h128V224z\"]\n};\nvar vsSearchStop = {\n prefix: \"vs\",\n iconName: \"search-stop\",\n icon: [512, 512, [], \"f000\", \"M183.616 106.176a144 144 0 0 0 -28.064 163.936A143.36 143.36 0 0 0 195.2 320a147.84 147.84 0 0 0 -3.2 32v5.44c-5.12 -3.52 -10.24 -7.04 -15.04 -10.88L56 464 32 442.88l121.6 -118.08a176 176 0 1 1 307.84 -116.8c0 8.576 -0.64 17.12 -1.92 25.6a167.424 167.424 0 0 0 -30.08 -21.76V208a144 144 0 0 0 -245.824 -101.824zm97.28 139.392a128 128 0 1 1 142.208 212.864 128 128 0 0 1 -142.208 -212.864zm3.2 174.304A96 96 0 0 0 352 448a96 96 0 0 0 55.68 -17.6L273.6 296.32A96 96 0 0 0 256 352a96 96 0 0 0 28.128 67.872zm12.224 -146.24l134.08 134.048A96 96 0 0 0 448 352a96 96 0 0 0 -96 -96 96 96 0 0 0 -55.68 17.6z\"]\n};\nvar vsSearch = {\n prefix: \"vs\",\n iconName: \"search\",\n icon: [512, 512, [], \"f000\", \"M325.333 0a176 176 0 0 0 -131.84 292.693L21.333 488.107l23.893 21.333 171.733 -194.56A176.021 176.021 0 1 0 325.333 0.213V0zm0 320a144 144 0 1 1 0 -288 144 144 0 0 1 0 288z\"]\n};\nvar vsServerEnvironment = {\n prefix: \"vs\",\n iconName: \"server-environment\",\n icon: [512, 512, [], \"f000\", \"M192 96h128v32H192V96zm0 192h128v32H192V288zm0 64h128v32H192v-32zm292.48 160H27.52l40 -160H128V64a30.4 30.4 0 0 1 2.496 -12.256c1.664 -3.84 3.936 -7.232 6.752 -10.24a29.504 29.504 0 0 1 10.24 -7.008A32.32 32.32 0 0 1 160 32h192a30.4 30.4 0 0 1 12.256 2.496c3.84 1.664 7.232 3.936 10.24 6.752a29.504 29.504 0 0 1 7.008 10.24c1.664 4 2.496 8.192 2.496 12.512v288h60.48l40 160zM160 416h192V64H160v352zm283.52 64l-24 -96H384v64H128v-64H92.48l-24 96h375.04z\"]\n};\nvar vsServerProcess = {\n prefix: \"vs\",\n iconName: \"server-process\",\n icon: [512, 512, [], \"f000\", \"M48 64h416l16 16V288h-32V192H64v224h224v32H48l-16 -16v-352l16 -16zM64 160h384V96H64v64zm160 224v-35.008a52.256 52.256 0 0 1 -15.008 -8.48l-30.24 17.248 -16 -27.52 29.984 -17.504a50.24 50.24 0 0 1 0 -17.504l-29.984 -17.472 16 -27.52 30.24 17.28c4.832 -3.84 9.856 -6.688 15.008 -8.512V224h32v35.008a47.36 47.36 0 0 1 15.008 8.48l30.24 -17.248 16 27.52 -29.984 17.504a50.24 50.24 0 0 1 0 17.472l29.984 17.504 -16 27.52 -30.24 -17.28a57.824 57.824 0 0 1 -15.008 8.512V384H224zm-8 -80c0 6.656 2.336 12.32 7.008 16.992a23.136 23.136 0 0 0 16.992 7.008 23.136 23.136 0 0 0 16.992 -7.008 23.136 23.136 0 0 0 7.008 -16.992 23.136 23.136 0 0 0 -7.008 -16.992 23.136 23.136 0 0 0 -16.992 -7.008 23.136 23.136 0 0 0 -16.992 7.008 23.136 23.136 0 0 0 -7.008 16.992zm170.688 176v-35.008a52.288 52.288 0 0 1 -15.008 -8.48l-30.24 17.248 -16 -27.52 30.016 -17.504a50.304 50.304 0 0 1 0 -17.504l-30.016 -17.472 16 -27.52 30.24 17.28c4.832 -3.84 9.856 -6.688 15.04 -8.512V320h32v35.008a47.552 47.552 0 0 1 14.976 8.48l30.24 -17.248 16 27.52 -29.984 17.504a49.984 49.984 0 0 1 0 17.472l29.984 17.504 -16 27.52 -30.24 -17.28a57.792 57.792 0 0 1 -15.008 8.512V480h-32zm-8 -80c0 6.656 2.336 12.32 7.008 16.992a23.136 23.136 0 0 0 16.992 7.008 23.136 23.136 0 0 0 16.992 -7.008 23.136 23.136 0 0 0 7.04 -16.992 23.136 23.136 0 0 0 -7.04 -16.992 23.136 23.136 0 0 0 -16.96 -7.008 23.136 23.136 0 0 0 -17.024 7.008 23.136 23.136 0 0 0 -7.008 16.992z\"]\n};\nvar vsServer = {\n prefix: \"vs\",\n iconName: \"server\",\n icon: [512, 512, [], \"f000\", \"M80 160L64 144v-96l16 -16h352l16 16v96l-16 16h-352zM320 64H288v32H256V64H224v32H192V64H160v32H128V64H96v64h320V64h-64v32h-32V64zm-240 256L64 304v-96l16 -16h352l16 16v96l-16 16h-352zM192 224H160v32H128V224H96v64h320V224h-64v32h-32V224H288v32H256V224H224v32H192V224zm240 256l16 -16v-96l-16 -16h-352l-16 16v96l16 16h352zM96 448v-64h32v32h32v-32h32v32h32v-32h32v32h32v-32h32v32h32v-32h64v64H96z\"]\n};\nvar vsSettingsGear = {\n prefix: \"vs\",\n iconName: \"settings-gear\",\n icon: [512, 512, [], \"f000\", \"M423.467 186.667l88.533 17.707v103.253l-88.533 17.707 50.133 75.093 -73.173 73.173 -75.093 -50.133 -17.707 88.533H204.373l-17.707 -88.533 -75.093 50.133 -73.173 -73.173 50.133 -75.093L0 307.627V204.373l88.533 -17.707L38.4 111.573 111.573 38.4l75.093 50.133L204.373 0h103.253l17.707 88.533 75.093 -50.133 73.173 73.173 -50.133 75.093zm-33.493 108.16l85.333 -17.28v-42.667l-85.333 -17.28 -11.52 -27.733 48.853 -73.173 -30.507 -30.507 -73.173 48.853 -27.733 -11.52 -17.28 -85.333h-42.667l-17.28 85.333 -27.733 11.52 -73.173 -48.853 -30.507 30.507L136.107 189.867l-11.52 27.733 -85.333 17.28v42.667l85.333 17.28 11.52 27.733 -48.853 73.173 30.507 30.507 73.173 -48.853 27.733 11.52 17.28 85.333h42.667l17.28 -85.333 27.733 -11.52 73.173 48.853 30.507 -30.507 -48.853 -73.173 11.52 -27.733zm-174.635 -99.669A73.173 73.173 0 0 1 256 182.827 73.387 73.387 0 0 1 329.173 256a73.173 73.173 0 1 1 -113.835 -60.843zm20.395 91.179c5.995 4.011 13.056 6.144 20.267 6.144A36.267 36.267 0 0 0 292.48 256a36.48 36.48 0 1 0 -56.747 30.336z\"]\n};\nvar vsSettings = {\n prefix: \"vs\",\n iconName: \"settings\",\n icon: [512, 512, [], \"f000\", \"M112 64h-32v160h32V64zm195.2 160H204.8L192 206.4v-32L204.8 160h102.4l12.8 16v32l-12.8 16zm-160 96H44.8L32 304v-32l12.8 -16h102.4l12.8 16v32l-12.8 16zm124.8 -256h-32v64h32V64zm-32 192h32v192h-32V256zm-128 96h-32v96h32v-96zm252.8 0h102.08l12.8 -16v-30.4l-12.8 -16H364.8l-12.8 16v30.4l12.8 16zm67.2 -288h-32v192h32V64zm-32 320h32v64h-32v-64z\"]\n};\nvar vsShield = {\n prefix: \"vs\",\n iconName: \"shield\",\n icon: [512, 512, [], \"f000\", \"M263.872 470.816a889.344 889.344 0 0 1 -48.16 -30.496c-16.032 -10.88 -31.456 -22.624 -46.208 -35.2 -14.656 -12.64 -28.416 -26.24 -41.216 -40.768 -12.8 -14.56 -24.096 -30.4 -33.6 -47.296a249.6 249.6 0 0 1 -22.4 -54.08A225.312 225.312 0 0 1 64 201.6V99.2l16 -16c10.656 0 20.992 -0.352 31.04 -1.152 9.472 -0.736 18.912 -2.112 28.224 -4.096 9.088 -1.984 17.984 -4.736 26.624 -8.192 9.088 -3.776 17.824 -8.352 26.112 -13.664a154.56 154.56 0 0 1 37.888 -18.08 153.6 153.6 0 0 1 64 -4.544 128.576 128.576 0 0 1 39.584 12.256c6.368 3.104 12.544 6.528 18.56 10.304 8.32 5.344 17.12 9.92 26.272 13.696 8.64 3.488 17.504 6.208 26.592 8.192 9.312 1.984 18.784 3.392 28.288 4.128 9.952 0.768 20.288 1.12 30.944 1.12l16 16v102.4a225.376 225.376 0 0 1 -8.192 61.408 249.728 249.728 0 0 1 -22.4 54.08 280.032 280.032 0 0 1 -33.6 47.296c-12.8 14.464 -26.528 28.064 -41.152 40.64a510.08 510.08 0 0 1 -46.336 35.2 918.72 918.72 0 0 1 -48.32 30.592h-16.256zM96 114.88V201.6c-0.128 17.76 2.24 35.52 7.04 52.64a214.4 214.4 0 0 0 19.52 47.136c8.416 14.944 18.4 28.96 29.76 41.856 11.84 13.344 24.512 25.92 38.016 37.568 13.824 11.776 28.256 22.784 43.264 32.96 12.8 8.544 25.6 16.736 38.4 24.608 12.8 -7.744 25.6 -15.936 38.4 -24.576 15.04 -10.208 29.536 -21.216 43.36 -32.992 13.472 -11.648 26.144 -24.192 37.952 -37.504a249.6 249.6 0 0 0 29.76 -41.856c8.352 -14.88 14.912 -30.72 19.52 -47.136 4.8 -17.184 7.136 -34.88 7.04 -52.704V114.88c-5.088 0 -10.016 -0.384 -14.88 -0.736l-2.528 -0.192a254.4 254.4 0 0 1 -32.576 -4.704 195.584 195.584 0 0 1 -63.232 -26.048 165.312 165.312 0 0 0 -15.424 -8.64 99.936 99.936 0 0 0 -30.176 -9.28 117.952 117.952 0 0 0 -49.856 3.392c-10.624 3.456 -20.768 8.32 -30.08 14.464 -9.984 6.4 -20.48 11.904 -31.456 16.416a204.8 204.8 0 0 1 -32 9.824c-10.72 2.24 -21.6 3.84 -32.544 4.672 -5.568 0.32 -11.36 0.64 -17.28 0.832zm194.08 137.6a48 48 0 1 0 -36.16 0L240 336h64l-13.92 -83.52z\"]\n};\nvar vsSignIn = {\n prefix: \"vs\",\n iconName: \"sign-in\",\n icon: [512, 512, [], \"f000\", \"M352.64 120.64l0.32 -0.32 31.68 31.68V80l-16 -16h-288l-16.32 16v15.776L64 96v329.28l11.52 14.72 160 55.04L256 480v-32h112.64l16 -16v-72l-32 32V416H256V150.72l-10.56 -14.72L129.152 96h223.488v24.64zM224 456.96l-128 -42.88V119.04l128 42.88v295.04zm98.88 -216h159.04v32h-157.76l50.88 51.2 -22.72 22.4 -79.04 -78.72v-22.72l79.68 -79.36 22.4 22.4 -52.48 52.8z\"]\n};\nvar vsSignOut = {\n prefix: \"vs\",\n iconName: \"sign-out\",\n icon: [512, 512, [], \"f000\", \"M352.64 120.64v49.92l32 -31.68V80l-16 -16h-288l-16 16v15.552L64 96v329.28l11.52 14.72 160 55.04L256 480v-32h112.64l16 -16v-57.92l-32 -32V416H256V150.72l-10.56 -14.72L129.152 96h223.488v24.64zM224 456.96l-128 -42.88V119.04l128 42.88v295.04zm208.64 -185.6H273.6v-32h157.76l-51.2 -51.2 22.72 -22.4 79.04 78.72v22.72l-79.68 79.36 -22.4 -22.4 52.8 -52.8z\"]\n};\nvar vsSmiley = {\n prefix: \"vs\",\n iconName: \"smiley\",\n icon: [512, 512, [], \"f000\", \"M131.552 69.76a224 224 0 1 1 248.896 372.48A224 224 0 0 1 131.52 69.76zm17.792 345.888a192 192 0 1 0 213.312 -319.296 192 192 0 0 0 -213.312 319.296zM208 224a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zm160 0a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zM256 352a96 96 0 0 1 -84.8 -50.56l-27.84 15.36a128 128 0 0 0 227.84 -5.12l-28.8 -13.76A96 96 0 0 1 256 352z\"]\n};\nvar vsSortPrecedence = {\n prefix: \"vs\",\n iconName: \"sort-precedence\",\n icon: [512, 512, [], \"f000\", \"M224 64L192 96v96h32V96h224v78.496l6.624 -5.12 25.376 25.376V96l-32 -32H224zm32 64h64v64H256V128zM160 288H96v64h64V288zM64 224L32 256v160l32 32h224l32 -32V256L288 224H64zm0 192V256h224v160H64zm192 -96H192v64h64v-64zm160 -192h-32v123.648l-37.824 -37.824 -22.624 22.624 65.12 65.152h22.656l65.12 -65.152 -22.624 -22.624L416 251.648V128z\"]\n};\nvar vsSourceControl = {\n prefix: \"vs\",\n iconName: \"source-control\",\n icon: [512, 512, [], \"f000\", \"M448.149 175.403A79.744 79.744 0 0 0 320.96 110.933a79.723 79.723 0 0 0 24.661 140.437 63.744 63.744 0 0 1 -56.917 35.627h-63.787a95.061 95.061 0 0 0 -63.765 24.853V157.867a79.723 79.723 0 1 0 -31.872 0v194.496a80.555 80.555 0 1 0 38.741 2.112 63.787 63.787 0 0 1 56.917 -35.563h63.787a95.659 95.659 0 0 0 90.091 -64.832 79.701 79.701 0 0 0 69.333 -78.656zM97.387 79.744a47.829 47.829 0 1 1 95.659 0 47.829 47.829 0 0 1 -95.659 0zm95.659 350.741a47.829 47.829 0 1 1 -95.659 0 47.829 47.829 0 0 1 95.659 0zm175.381 -207.253a47.829 47.829 0 1 1 0 -95.68 47.829 47.829 0 0 1 0 95.68z\"]\n};\nvar vsSplitHorizontal = {\n prefix: \"vs\",\n iconName: \"split-horizontal\",\n icon: [512, 512, [], \"f000\", \"M448 32H96L64 64v352l32 32h352l32 -32V64l-32 -32zM256 416H96V64h160v352zm192 0H288V64h160v352z\"]\n};\nvar vsSplitVertical = {\n prefix: \"vs\",\n iconName: \"split-vertical\",\n icon: [512, 512, [], \"f000\", \"M448 32H96L64 64v352l32 32h352l32 -32V64l-32 -32zm0 384H96V256h352v160zm0 -192H96V64h352v160z\"]\n};\nvar vsSquirrel = {\n prefix: \"vs\",\n iconName: \"squirrel\",\n icon: [512, 512, [], \"f000\", \"M177.856 84.544a118.336 118.336 0 0 0 -3.936 -0.32A47.04 47.04 0 0 0 127.968 48.64v41.824a156.736 156.736 0 0 0 -95.776 114.784v12.48c14.688 26.752 60.992 36.16 68.928 37.76 0.864 0.192 1.28 0.288 1.12 0.288 -77.408 10.24 -70.08 71.968 -70.08 71.968a32 32 0 0 0 32 29.76c8.704 -0.608 17.216 -2.56 25.28 -5.76h65.92a96 96 0 0 0 -11.52 32h-10.24a81.6 81.6 0 0 0 -69.44 80.896 13.44 13.44 0 0 0 12.48 15.36h213.664a120.32 120.32 0 0 0 125.728 -133.056 116.768 116.768 0 0 0 -24 -66.88l-3.52 -4.48c-13.76 -17.6 -21.76 -29.088 -17.6 -41.248 4.16 -12.16 11.68 -12.8 11.68 -12.8s5.92 -0.96 14.56 2.88c7.04 4.096 14.72 7.04 22.72 8.64a50.56 50.56 0 0 0 55.552 -28.96c3.04 -6.656 4.576 -13.92 4.576 -21.248 0.192 -22.976 -10.56 -46.56 -23.2 -66.816a159.936 159.936 0 0 0 -49.728 -50.24 127.936 127.936 0 0 0 -84.448 -12.8 97.568 97.568 0 0 0 -53.44 28.48 113.92 113.92 0 0 0 -24.928 43.488 139.456 139.456 0 0 0 -20.352 -23.904v-5.088A47.04 47.04 0 0 0 177.856 48.64v35.904zm169.728 279.648c3.552 23.712 7.04 58.272 -27.744 78.144 -9.472 3.296 -19.456 5.12 -29.536 5.344H102.88a32 32 0 0 1 29.44 -32h40.928v-15.968a57.28 57.28 0 0 1 52.896 -58.4l-20.032 -28.384c-7.552 2.144 -14.816 4.896 -18.464 7.456H84.96a24.128 24.128 0 0 0 -8.448 2.24c-4.416 1.76 -8.768 3.488 -12.672 0.96 -6.4 -4.16 3.52 -35.84 32.32 -35.84h32c15.68 0 18.24 -17.28 18.24 -17.28l8.96 -36.128a108.448 108.448 0 0 1 -91.2 -29.76 108.448 108.448 0 0 1 100.48 -85.056l2.656 0.064c8.32 0.256 13.92 0.448 24.832 5.376 29.76 13.44 68.768 79.008 68.768 79.008l1.92 2.88h5.44v-2.24c-1.92 -14.176 -0.64 -46.848 3.712 -60.48 4.384 -13.568 11.744 -26.048 21.536 -36.48a75.168 75.168 0 0 1 41.6 -21.088 84.448 84.448 0 0 1 59.52 9.28c14.72 9.088 27.2 21.44 36.448 36.064 9.248 14.624 15.232 26.752 17.12 43.968 -0.032 0.64 0 1.504 0.064 2.592 0.224 4.576 0.64 12.48 -4.096 17.504 -4.064 4.32 -14.336 7.36 -21.44 5.76a50.24 50.24 0 0 1 -14.4 -5.76 42.56 42.56 0 0 0 -36.448 -4.16 45.44 45.44 0 0 0 -30.08 32 74.176 74.176 0 0 0 20.48 71.616l3.52 4.48c11.104 13.888 17.472 30.912 18.24 48.64a95.968 95.968 0 0 1 -9.792 45.6 86.656 86.656 0 0 0 -14.848 -41.728l-11.84 11.776zM135.68 160a16 16 0 1 0 0 32 16 16 0 0 0 0 -32z\"]\n};\nvar vsStarEmpty = {\n prefix: \"vs\",\n iconName: \"star-empty\",\n icon: [512, 512, [], \"f000\", \"M307.04 200.064L256 32 204.96 200.064H32l139.936 108.8L120 480 256 374.24 392 480l-51.936 -171.136L480 200.064H307.04zm-231.904 15.04H215.04L256 80.224 215.04 215.104H75.136zm113.184 88l-41.824 137.76 41.824 -137.76zm248.544 -88H296.96h139.904zm-280 28.8h75.712L256 166.848l23.424 77.12h75.744l-61.28 47.68 23.392 77.088L256 321.024l-61.28 47.68 23.392 -77.12 -61.28 -47.68z\"]\n};\nvar vsStarFull = {\n prefix: \"vs\",\n iconName: \"star-full\",\n icon: [512, 512, [], \"f000\", \"M307.04 200.064L256 32 204.96 200.064H32l139.936 108.8L120 480 256 374.24 392 480l-51.936 -171.136L480 200.064H307.04z\"]\n};\nvar vsStarHalf = {\n prefix: \"vs\",\n iconName: \"star-half\",\n icon: [512, 512, [], \"f000\", \"M204.96 200.064L256 32l51.04 168.064H480l-139.936 108.8L392 480 256 374.24 120 480l51.936 -171.136L32 200.064h172.96zM256 321.024l61.28 47.68 -23.392 -77.12 61.28 -47.68H279.424L256 166.848v154.24zm0 -240.8zm180.864 134.88H296.96h139.904z\"]\n};\nvar vsStopCircle = {\n prefix: \"vs\",\n iconName: \"stop-circle\",\n icon: [512, 512, [], \"f000\", \"M192 192h128v128H192zm83.2 -160c51.2 3.2 99.2 28.8 134.4 64 41.6 44.8 64 99.2 64 163.2 0 51.2 -19.2 99.2 -51.2 140.8 -32 38.4 -76.8 67.2 -128 76.8 -51.2 9.6 -102.4 3.2 -147.2 -22.4 -44.8 -25.6 -80 -64 -99.2 -112C28.8 294.4 25.6 240 41.6 192c16 -51.2 44.8 -92.8 89.6 -121.6C172.8 41.6 224 28.8 275.2 32zm16 412.8c41.6 -9.6 80 -32 108.8 -67.2 25.6 -35.2 41.6 -76.8 38.4 -121.6 0 -51.2 -19.2 -102.4 -54.4 -137.6 -32 -32 -70.4 -51.2 -115.2 -54.4 -41.6 -3.2 -86.4 6.4 -121.6 32 -35.2 25.6 -60.8 60.8 -73.6 105.6 -12.8 41.6 -12.8 86.4 6.4 128 19.2 41.6 48 73.6 86.4 96 38.4 22.4 83.2 28.8 124.8 19.2z\"]\n};\nvar vsSymbolArray = {\n prefix: \"vs\",\n iconName: \"symbol-array\",\n icon: [512, 512, [], \"f000\", \"M48 64l-16 16v352l16 16H128v-32H64V96h64V64H48zm416 384l16 -16v-352l-16 -16H384v32h64v320h-64v32h80z\"]\n};\nvar vsSymbolBoolean = {\n prefix: \"vs\",\n iconName: \"symbol-boolean\",\n icon: [512, 512, [], \"f000\", \"M32 112l16 -16h416l16 16v288l-16 16h-416l-16 -16v-288zM448 128H256v111.776h-16l-114.368 -0.16 66.88 -66.88 -22.624 -22.624 -94.56 94.56v22.656l94.56 94.56 22.624 -22.624 -67.648 -67.648 127.872 0.16H256v-31.552l125.024 0.16 -67.648 -67.648 22.624 -22.624 94.592 94.56v22.656L336 361.888l-22.624 -22.624 66.88 -66.88L256 272.224V384h192V128z\"]\n};\nvar vsSymbolClass = {\n prefix: \"vs\",\n iconName: \"symbol-class\",\n icon: [512, 512, [], \"f000\", \"M362.88 310.72h22.72l85.44 -85.44v-22.72L428.16 160h-22.4l-58.24 57.92h-160V177.92l59.52 -59.2V96l-64 -64H160L32 160v22.72l64 64h22.72l36.48 -36.8v185.28l16 16H320v16.64l42.56 42.88h22.72l85.44 -85.44v-22.72L427.84 320h-22.4l-59.52 59.2h-160v-128H320v15.36l42.88 44.16zm54.08 -116.8l20.16 20.16 -64 64 -20.16 -20.16 64 -64zm0 160l20.16 20.16 -64 64 -20.16 -20.16 64 -64zM107.2 212.8l-41.28 -41.6 105.28 -105.28 41.6 41.28 -105.6 105.6z\"]\n};\nvar vsSymbolColor = {\n prefix: \"vs\",\n iconName: \"symbol-color\",\n icon: [512, 512, [], \"f000\", \"M256 32.096a224 224 0 0 0 -224 224v13.76c2.88 48.32 61.12 57.28 96 22.4a59.84 59.84 0 0 1 84.48 84.48c-35.2 37.12 -25.28 98.24 25.6 102.4h19.2a224 224 0 1 0 0 -448l-1.28 0.96zm0 416h-16.64a18.56 18.56 0 0 1 -11.52 -4.48 17.92 17.92 0 0 1 -4.8 -9.6 39.68 39.68 0 0 1 11.2 -34.56 91.84 91.84 0 0 0 0 -128 91.84 91.84 0 0 0 -129.92 0 32 32 0 0 1 -28.8 10.88 13.12 13.12 0 0 1 -7.04 -3.84 13.44 13.44 0 0 1 -3.2 -9.28v-11.84a192 192 0 1 1 192 192l-1.28 -1.28zM288 127.904a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zm96 224.224a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zm-224 -160a32 32 0 1 0 0 -64 32 32 0 0 0 0 64zm224 -32a32 32 0 1 1 -64 0 32 32 0 0 1 64 0zM416 256a32 32 0 1 1 -64 0 32 32 0 0 1 64 0z\"]\n};\nvar vsSymbolConstant = {\n prefix: \"vs\",\n iconName: \"symbol-constant\",\n icon: [512, 512, [], \"f000\", \"M128 192h256v32H128V192zm256 96H128v32h256V288zM32 128l32 -32h384l32 32v256l-32 32H64l-32 -32V128zm32 0v256h384V128H64z\"]\n};\nvar vsSymbolEnumMember = {\n prefix: \"vs\",\n iconName: \"symbol-enum-member\",\n icon: [512, 512, [], \"f000\", \"M224 96l32 -32h192l32 32v160l-32 32h-128V256h128V96H256v96H224V96zm64 192V256L256 224H64L32 256v160l32 32h192l32 -32V288zM256 256v160H64V256h192zm45.248 -32L288 210.752V192h128v32H301.248zM288 128h128v32H288V128zm-64 192H96v32h128v-32z\"]\n};\nvar vsSymbolEnum = {\n prefix: \"vs\",\n iconName: \"symbol-enum\",\n icon: [512, 512, [], \"f000\", \"M448 64H256L224 96v96h32V96h192v160h-128v32h128l32 -32V96l-32 -32zM288 192h128v32H301.12L288 210.88V192zM224 224H64L32 256v160l32 32h192l32 -32V256L256 224H224zm32 192H64V256h192v160zM96 288h128v32H96V288zm0 64h128v32H96v-32zm192 -224h128v32H288V128z\"]\n};\nvar vsSymbolEvent = {\n prefix: \"vs\",\n iconName: \"symbol-event\",\n icon: [512, 512, [], \"f000\", \"M237.248 49.92L265.984 32h105.408l26.176 50.4L327.552 192h56.992l23.04 54.24L179.776 480l-51.264 -37.216L195.808 320H156.736L128 273.92l109.248 -224zM248.96 288L156.8 457.76 384.576 224H265.984l105.408 -160H265.984L156.736 288H248.96z\"]\n};\nvar vsSymbolField = {\n prefix: \"vs\",\n iconName: \"symbol-field\",\n icon: [512, 512, [], \"f000\", \"M462.4 144l-160 -80h-28.8l-224 112 -17.6 28.48v144l17.6 28.8 160 80h28.8l224 -112 17.6 -28.8v-144l-17.6 -28.48zm-256 276.48l-144 -72V229.44l144 64v127.04zm16 -153.6L73.28 199.36l213.12 -106.88 149.44 74.88 -213.44 99.52zm224 49.6l-208 104V294.72l208 -96v117.76z\"]\n};\nvar vsSymbolFile = {\n prefix: \"vs\",\n iconName: \"symbol-file\",\n icon: [512, 512, [], \"f000\", \"M443.2 142.08l-104.96 -105.6 -11.2 -4.48H80l-16 16v416l16 16h352l16 -16V153.6l-4.8 -11.52zM416 160h-96V64l96 96zM96 448V64h192v112l16 16H416v256H96z\"]\n};\nvar vsSymbolInterface = {\n prefix: \"vs\",\n iconName: \"symbol-interface\",\n icon: [512, 512, [], \"f000\", \"M367.872 128a111.68 111.68 0 0 0 -110.72 96h-99.2a64 64 0 1 0 0 32h99.2a112 112 0 1 0 110.72 -128zm0 192a80 80 0 1 1 0 -160 80 80 0 0 1 0 160z\"]\n};\nvar vsSymbolKey = {\n prefix: \"vs\",\n iconName: \"symbol-key\",\n icon: [512, 512, [], \"f000\", \"M231.136 349.856c10.432 6.144 22.368 9.28 34.464 9.024a69.088 69.088 0 0 0 56.128 -26.944 105.312 105.312 0 0 0 20.928 -67.616 92.352 92.352 0 0 0 -18.432 -60.064 63.68 63.68 0 0 0 -52.288 -23.456 73.408 73.408 0 0 0 -48.736 18.144V111.2h-31.712V355.2h31.84v-11.008c2.432 2.112 5.056 4 7.808 5.664zM251.2 214.4c5.952 -2.528 12.416 -3.616 18.88 -3.2a34.56 34.56 0 0 1 28.672 13.696c8.224 11.616 12.224 25.664 11.424 39.84a79.52 79.52 0 0 1 -12.8 47.488 36.256 36.256 0 0 1 -30.72 16.256 39.168 39.168 0 0 1 -31.232 -13.344A48.704 48.704 0 0 1 223.2 281.6v-19.2a55.104 55.104 0 0 1 12.576 -36.64c4.16 -4.928 9.472 -8.832 15.424 -11.36zM105.248 181.6a96.96 96.96 0 0 0 -29.984 5.184 82.88 82.88 0 0 0 -25.6 12.8l-3.2 2.464v38.4l13.536 -11.488a67.2 67.2 0 0 1 43.712 -18.304 24.256 24.256 0 0 1 21.152 9.024c4.8 7.424 7.36 16.096 7.392 24.928L92.8 250.4a83.2 83.2 0 0 0 -44.096 18.4 52.8 52.8 0 0 0 -0.704 74.752 55.584 55.584 0 0 0 40.096 14.528 62.72 62.72 0 0 0 35.424 -10.624c3.264 -2.176 6.304 -4.64 9.152 -7.328v14.208h30.112V246.88a70.176 70.176 0 0 0 -15.008 -48 53.984 53.984 0 0 0 -42.528 -17.28zm27.424 97.312c0.64 13.376 -3.84 26.528 -12.512 36.736a39.072 39.072 0 0 1 -30.56 13.504 26.624 26.624 0 0 1 -19.456 -6.4 26.656 26.656 0 0 1 0 -34.912c8.992 -5.568 19.2 -8.864 29.76 -9.6l32.64 -4.736 0.128 5.408zm266.016 74.144c9.824 4.16 20.48 6.176 31.136 5.824 15.84 0.384 31.456 -3.648 45.12 -11.68l3.936 -2.4 0.416 -0.224V307.68l-14.272 10.24c-10.112 7.168 -22.272 10.88 -34.688 10.528A41.6 41.6 0 0 1 396.8 313.6a63.2 63.2 0 0 1 -12.8 -41.984 64.32 64.32 0 0 1 14.496 -44.192A45.824 45.824 0 0 1 435.2 211.2a57.6 57.6 0 0 1 31.072 8.928l13.76 8.48V191.04l-5.44 -2.336a92.8 92.8 0 0 0 -37.44 -7.904 80.64 80.64 0 0 0 -61.728 26.144 92.8 92.8 0 0 0 -23.904 65.568c-0.896 22.624 6.72 44.8 21.44 62.048 7.104 7.968 15.904 14.272 25.728 18.496z\"]\n};\nvar vsSymbolKeyword = {\n prefix: \"vs\",\n iconName: \"symbol-keyword\",\n icon: [512, 512, [], \"f000\", \"M480 128h-160V96h160v32zm-32 96h-64v32h64V224zm-128 0H32v32h288V224zm64 192H32v32h352v-32zm-160 -96H32v32h192v-32zm256 0h-160v32h160v-32zM256 64v96H32V64h224zM224 96H64v32h160V96z\"]\n};\nvar vsSymbolMethod = {\n prefix: \"vs\",\n iconName: \"symbol-method\",\n icon: [512, 512, [], \"f000\", \"M432.32 128l-160 -96h-32l-160 96 -15.68 27.52v192l15.68 27.2 160 96h32l160 -96 15.68 -27.2v-192L432.32 128zm-192 305.92l-144 -86.4V182.4l144 78.4v173.12zM104.64 150.4l151.68 -90.88 151.68 90.88 -151.68 82.88L104.64 150.4zm311.68 197.12l-144 86.4V260.8l144 -78.4v165.12z\"]\n};\nvar vsSymbolMisc = {\n prefix: \"vs\",\n iconName: \"symbol-misc\",\n icon: [512, 512, [], \"f000\", \"M128 64h256v128c10.912 1.12 21.664 3.584 32 7.36V32H96v271.36l32 -56V64zm68.48 256L160 256 128 312 105.28 352 32 480h256l-73.28 -128 -18.24 -32zm-109.44 128l55.04 -96L160 320l17.92 32 55.04 96H87.04zm218.752 -205.12a112 112 0 1 1 124.416 186.24 112 112 0 0 1 -124.416 -186.24zm17.76 159.648a80 80 0 1 0 88.896 -133.024 80 80 0 0 0 -88.896 133.024z\"]\n};\nvar vsSymbolNamespace = {\n prefix: \"vs\",\n iconName: \"symbol-namespace\",\n icon: [512, 512, [], \"f000\", \"M192 95.488V64h-2.88c-10.016 0 -19.712 1.984 -29.088 5.92a74.56 74.56 0 0 0 -24.8 16.96 71.36 71.36 0 0 0 -15.776 24.096v0.032a113.344 113.344 0 0 0 -6.336 26.56v0.064a194.56 194.56 0 0 0 -0.768 27.616c0.384 9.28 0.576 18.56 0.576 27.808 0 6.496 -1.28 12.576 -3.744 18.304v0.032a48.128 48.128 0 0 1 -24.48 25.184 44.032 44.032 0 0 1 -17.856 3.68H64v31.488h2.88c6.24 0 12.16 1.28 17.792 3.872l0.032 0.032c5.696 2.496 10.528 5.888 14.56 10.176l0.064 0.064c4.16 4.16 7.456 9.12 9.824 14.88l0.032 0.064c2.496 5.76 3.744 11.776 3.744 18.112 0 9.28 -0.192 18.56 -0.576 27.808 -0.384 9.472 -0.128 18.72 0.768 27.84v0.032c1.056 9.056 3.168 17.856 6.304 26.368v0.032c3.392 8.736 8.672 16.768 15.808 24.096 7.136 7.36 15.424 13.024 24.8 16.96 9.376 3.936 19.072 5.92 29.12 5.92H192v-31.488h-2.88c-6.368 0 -12.384 -1.216 -17.984 -3.68a51.616 51.616 0 0 1 -14.624 -10.24 53.088 53.088 0 0 1 -9.888 -14.944c-2.368 -5.76 -3.52 -11.84 -3.52 -18.336 0 -7.296 0.096 -14.496 0.352 -21.504 0.256 -7.296 0.256 -14.4 0 -21.28a148.448 148.448 0 0 0 -1.76 -20.48 85.824 85.824 0 0 0 -5.376 -19.488A73.088 73.088 0 0 0 112.704 256a73.088 73.088 0 0 0 23.616 -30.56c2.56 -6.144 4.32 -12.576 5.376 -19.264 1.056 -6.72 1.632 -13.536 1.76 -20.48 0.256 -7.04 0.256 -14.144 0 -21.312 -0.256 -7.168 -0.384 -14.4 -0.384 -21.696a47.04 47.04 0 0 1 28.064 -43.328 42.56 42.56 0 0 1 18.016 -3.872H192zm128 321.024V448h2.88c10.016 0 19.712 -1.984 29.088 -5.92 9.376 -3.936 17.664 -9.6 24.8 -16.96 7.136 -7.36 12.416 -15.36 15.776 -24.096v-0.032c3.2 -8.512 5.28 -17.376 6.336 -26.56v-0.064c0.896 -8.96 1.152 -18.144 0.768 -27.616 -0.384 -9.28 -0.576 -18.56 -0.576 -27.808 0 -6.496 1.28 -12.576 3.744 -18.304v-0.032a48.128 48.128 0 0 1 24.48 -25.184c5.632 -2.464 11.584 -3.68 17.856 -3.68H448v-31.488h-2.88c-6.24 0 -12.16 -1.28 -17.792 -3.872l-0.032 -0.032a44.032 44.032 0 0 1 -14.56 -10.176l-0.064 -0.064a45.248 45.248 0 0 1 -9.824 -14.88l-0.032 -0.064a44.96 44.96 0 0 1 -3.744 -18.112c0 -9.28 0.192 -18.56 0.576 -27.808a198.08 198.08 0 0 0 -0.768 -27.84v-0.032a113.344 113.344 0 0 0 -6.304 -26.368v-0.032a71.36 71.36 0 0 0 -15.808 -24.096 74.56 74.56 0 0 0 -24.8 -16.96 74.4 74.4 0 0 0 -29.12 -5.92H320v31.488h2.88c6.4 0 12.352 1.216 17.984 3.68 5.568 2.624 10.432 6.016 14.624 10.24 4.064 4.288 7.36 9.28 9.888 14.944 2.368 5.76 3.52 11.84 3.52 18.336 0 7.296 -0.096 14.464 -0.352 21.504 -0.256 7.296 -0.256 14.4 0 21.28 0.128 7.104 0.704 13.92 1.76 20.48 1.056 6.848 2.848 13.312 5.376 19.488a73.024 73.024 0 0 0 23.616 30.56 73.024 73.024 0 0 0 -23.616 30.56 86.4 86.4 0 0 0 -5.376 19.264c-1.056 6.72 -1.632 13.536 -1.76 20.48 -0.256 7.04 -0.256 14.144 0 21.312 0.256 7.168 0.384 14.4 0.384 21.696a47.04 47.04 0 0 1 -13.44 33.12 46.912 46.912 0 0 1 -14.624 10.208 42.56 42.56 0 0 1 -18.016 3.872H320z\"]\n};\nvar vsSymbolNumeric = {\n prefix: \"vs\",\n iconName: \"symbol-numeric\",\n icon: [512, 512, [], \"f000\", \"M352 32v128h128v32h-128v128h128v32h-128v128h-32v-128H192v128H160v-128H32v-32h128V192H32V160h128V32h32v128h128V32h32zM192 192v128h128V192H192z\"]\n};\nvar vsSymbolOperator = {\n prefix: \"vs\",\n iconName: \"symbol-operator\",\n icon: [512, 512, [], \"f000\", \"M91.936 35.2c10.72 4.352 19.264 12.736 23.84 23.36 2.304 5.44 3.488 11.264 3.424 17.184a42.88 42.88 0 0 1 -19.52 36.32 43.488 43.488 0 0 1 -24.096 7.136A43.36 43.36 0 0 1 32 75.584a43.36 43.36 0 0 1 26.56 -40.192A43.84 43.84 0 0 1 91.936 35.2zm-9.536 56.48a17.632 17.632 0 0 0 10.624 -16 17.536 17.536 0 1 0 -10.624 16zM205.76 35.488L35.52 205.76l21.952 21.984 170.24 -170.24 -21.952 -21.984zM368 288h32v80H480v32h-80V480h-32v-80H288v-32h80V288zm-183.424 16.8l22.624 22.624L150.624 384l56.576 56.576 -22.624 22.624L128 406.624l-56.576 56.576 -22.624 -22.624L105.376 384l-56.576 -56.576 22.624 -22.624L128 361.376l56.576 -56.576zm43.2 -134.24a43.296 43.296 0 0 0 -40.192 -26.56 43.36 43.36 0 0 0 -40.192 26.56 43.584 43.584 0 0 0 40.224 60.64A43.456 43.456 0 0 0 227.776 170.56zm-24.096 23.84a17.696 17.696 0 0 1 -9.248 9.28 17.504 17.504 0 0 1 -19.168 -3.744 16.928 16.928 0 0 1 -3.744 -5.536 17.408 17.408 0 0 1 22.912 -22.88 18.08 18.08 0 0 1 5.536 3.712 17.568 17.568 0 0 1 3.712 19.168zM448 96h-128v32h128V96z\"]\n};\nvar vsSymbolParameter = {\n prefix: \"vs\",\n iconName: \"symbol-parameter\",\n icon: [512, 512, [], \"f000\", \"M352 192h-32v-16a16 16 0 0 0 -16 -16H271.328v176a16 16 0 0 0 16 16h16v32h-96v-32h16a16 16 0 0 0 16 -16V160H208a16 16 0 0 0 -16 16V192H160V128h192v64zm93.248 65.536l-46.784 -46.784 22.624 -22.624 58.112 58.112v22.624l-56.576 56.544 -22.624 -22.624 45.248 -45.248zM113.536 302.784L66.752 256 112 210.752l-22.624 -22.624 -56.576 56.544v22.656l58.112 58.08 22.624 -22.624z\"]\n};\nvar vsSymbolProperty = {\n prefix: \"vs\",\n iconName: \"symbol-property\",\n icon: [512, 512, [], \"f000\", \"M89.824 479.2a56 56 0 0 1 -40.16 -17.792 53.888 53.888 0 0 1 -17.408 -35.2A55.04 55.04 0 0 1 43.52 387.2c38.656 -40.64 114.784 -116.8 170.176 -171.04a136.224 136.224 0 0 1 1.536 -98.496 131.04 131.04 0 0 1 53.28 -63.008 136.288 136.288 0 0 1 129.28 -11.52l19.744 8.576 -91.712 94.432 40.16 40.288 94.208 -92.064 8.544 19.808a137.44 137.44 0 0 1 1.28 105.952 134.336 134.336 0 0 1 -29.536 44.544 136.64 136.64 0 0 1 -23.776 18.592 134.944 134.944 0 0 1 -121.984 14.272c-35.136 35.584 -122.88 123.904 -170.24 168.128a52.16 52.16 0 0 1 -34.688 13.536zm254.016 -417.504a106.24 106.24 0 0 0 -59.168 17.824c-6.816 4.16 -13.184 9.088 -18.912 14.656a106.272 106.272 0 0 0 -21.024 119.456l4.32 9.504 -7.456 7.264c-55.616 54.304 -136.608 135.04 -175.52 176.128a25.76 25.76 0 0 0 4.224 33.6 29.152 29.152 0 0 0 9.536 7.04c3.2 1.408 6.688 2.208 10.208 2.304a22.208 22.208 0 0 0 14.4 -5.792c50.336 -47.008 147.584 -145.248 176.128 -174.08l7.36 -7.424 9.408 4.32a105.152 105.152 0 0 0 103.2 -8.128 106.56 106.56 0 0 0 18.912 -14.848 104.96 104.96 0 0 0 30.848 -75.456c0 -6.88 -0.672 -13.76 -2.048 -20.544L365.76 228 284.128 146.496l80.48 -82.88a105.152 105.152 0 0 0 -20.8 -1.92z\"]\n};\nvar vsSymbolRuler = {\n prefix: \"vs\",\n iconName: \"symbol-ruler\",\n icon: [512, 512, [], \"f000\", \"M128 32L96 64v384l32 32h256l32 -32V64l-32 -32H128zm0 64V64h256v384H128v-32h64v-32H128v-64h128V288H128V224h64V192H128V128h128V96H128z\"]\n};\nvar vsSymbolSnippet = {\n prefix: \"vs\",\n iconName: \"symbol-snippet\",\n icon: [512, 512, [], \"f000\", \"M80 32l-16 16V416h32V64h352v352h32V48l-16 -16h-384zM64 480v-32h32v32H64zm96 -32H128v32h32v-32zm32 0h32v32H192v-32zm96 0H256v32h32v-32zm32 0h32v32h-32v-32zm160 32v-32h-32v32h32zm-96 -32h32v32h-32v-32z\"]\n};\nvar vsSymbolString = {\n prefix: \"vs\",\n iconName: \"symbol-string\",\n icon: [512, 512, [], \"f000\", \"M64 64L32 96v288l32 32h384l32 -32V96l-32 -32H64zm0 320V96h384v288H64zm107.392 -98.24H192V231.04C192 205.056 181.92 192 161.792 192c-4.32 0 -9.12 0.768 -14.4 2.336a46.208 46.208 0 0 0 -12.416 5.344v21.28c7.584 -6.496 15.584 -9.728 24 -9.728 8.352 0 12.544 4.992 12.544 15.008l-19.2 3.296c-16.192 2.752 -24.32 12.992 -24.32 30.752 0 8.416 1.952 15.136 5.856 20.192A19.52 19.52 0 0 0 150.08 288c9.28 0 16.288 -5.12 21.024 -15.36h0.288v13.12zm0.128 -43.36v6.176a24 24 0 0 1 -3.84 13.952 11.776 11.776 0 0 1 -10.016 5.44 8.832 8.832 0 0 1 -7.04 -3.04 12.16 12.16 0 0 1 -2.56 -7.936c0 -7.104 3.52 -11.232 10.624 -12.448l12.8 -2.144zM243.2 276.032h-0.224v9.92H224V160h18.976v53.664h0.256c4.672 -9.92 11.36 -14.88 20 -14.88 7.936 0 14.08 3.776 18.336 11.296 4.288 7.552 6.432 17.824 6.432 30.912 0 14.176 -2.496 25.536 -7.52 34.144C275.52 283.712 268.8 288 260.416 288c-7.584 0 -13.312 -4 -17.184 -11.968zm-0.512 -35.872v8.704a24.96 24.96 0 0 0 3.424 13.632c2.272 3.616 5.216 5.408 8.768 5.408 4.32 0 7.68 -2.304 10.048 -6.912 2.4 -4.64 3.616 -11.2 3.616 -19.68 0 -7.04 -1.12 -12.48 -3.328 -16.448 -2.144 -3.968 -5.248 -5.984 -9.28 -5.984 -3.84 0 -7.008 1.984 -9.536 5.92a28.384 28.384 0 0 0 -3.712 15.36zM360.384 288c10.272 0 18.144 -1.856 23.616 -5.536v-22.72a28.8 28.8 0 0 1 -17.664 6.624 19.808 19.808 0 0 1 -16 -6.88c-3.84 -4.64 -5.792 -11.04 -5.792 -19.136 0 -8.32 2.016 -14.848 6.048 -19.584a20.608 20.608 0 0 1 16.512 -7.136c6.208 0 11.84 2.208 16.896 6.624v-23.968c-4.128 -2.88 -10.816 -4.288 -20.032 -4.288 -13.344 0 -24.032 4.48 -32.032 13.504 -7.968 8.96 -11.936 21.184 -11.936 36.736 0 13.44 3.712 24.448 11.168 32.96 7.424 8.544 17.184 12.8 29.216 12.8z\"]\n};\nvar vsSymbolStructure = {\n prefix: \"vs\",\n iconName: \"symbol-structure\",\n icon: [512, 512, [], \"f000\", \"M64 64L32 96v96l32 32h384l32 -32V96l-32 -32H64zm0 32h384v96H64V96zm-32 224l32 -32h96l32 32v96l-32 32H64l-32 -32v-96zm64 0H64v96h96v-96H96zm224 0l32 -32h96l32 32v96l-32 32h-96l-32 -32v-96zm64 0h-32v96h96v-96h-64z\"]\n};\nvar vsSymbolVariable = {\n prefix: \"vs\",\n iconName: \"symbol-variable\",\n icon: [512, 512, [], \"f000\", \"M64 160h64V128H48l-16 16v256l16 16H128v-32H64V160zm400 -32H384v32h64v224h-64v32h80l16 -16v-256l-16 -16zm-87.68 82.24L384 224v80.32l-9.6 14.4 -144 64h-14.72l-80 -48 -7.68 -13.76v-80l9.6 -14.72 144 -64h14.72l80 48zM160 310.72l48 28.8V296.96L160 268.16v42.56zm18.56 -68.8l46.4 27.84 108.48 -48 -46.4 -27.84 -108.48 48zm62.4 101.44l112 -49.92v-44.8l-112 49.6v45.12z\"]\n};\nvar vsSyncIgnored = {\n prefix: \"vs\",\n iconName: \"sync-ignored\",\n icon: [512, 512, [], \"f000\", \"M174.976 117.984l-24.224 -22.592a192 192 0 0 1 297.12 153.568L486.08 211.2l24 24.32 -66.88 66.24 -24.32 -0.32L352 233.92l24.32 -24.32 39.552 40a160 160 0 0 0 -240.896 -131.616zm145.6 284.448l25.088 23.36a192 192 0 0 1 -281.472 -161.28L24.96 304 0 279.36l66.88 -66.24 24.32 0.32 66.88 67.84 -24.32 24.32 -37.344 -37.76a160 160 0 0 0 224.16 134.592zM35.936 94.368l21.824 -23.424L439.04 426.496l-21.824 23.424z\"]\n};\nvar vsSync = {\n prefix: \"vs\",\n iconName: \"sync\",\n icon: [512, 512, [], \"f000\", \"M64.192 264.544L24.96 304 0 279.36l66.88 -66.24 24.32 0.32 66.88 67.84 -24.32 24.32 -37.344 -37.76a160 160 0 0 0 300.8 63.456l26.016 19.104a192 192 0 0 1 -359.04 -85.856zm351.68 -14.912L376.32 209.6l-24.32 24.32 66.88 67.52 24.32 0.32 66.88 -66.24 -24 -24.32 -38.208 37.76a192 192 0 0 0 -355.52 -93.44l25.92 19.008a160 160 0 0 1 297.6 75.072z\"]\n};\nvar vsTable = {\n prefix: \"vs\",\n iconName: \"table\",\n icon: [512, 512, [], \"f000\", \"M432 64h-384l-16 16v352l16 16h384l16 -16v-352l-16 -16zM64 96h352v32H64V96zm224 128H192V160h96v64zm0 32v64H192V256h96zM64 160h96v64H64V160zm0 96h96v64H64V256zm0 160v-64h96v64H64zm128 0v-64h96v64H192zm224 0h-96v-64h96v64zm0 -96h-96V256h96v64zm-96 -96V160h96v64h-96z\"]\n};\nvar vsTag = {\n prefix: \"vs\",\n iconName: \"tag\",\n icon: [512, 512, [], \"f000\", \"M422.4 64H256.544l-11.296 4.672L32 281.92v22.624L197.856 470.4h22.624l70.88 -70.88A143.36 143.36 0 0 0 500.8 288c0.864 -5.312 1.408 -10.624 1.632 -16a144.16 144.16 0 0 0 -64 -119.68V80l-16 -16zm-16 72.288A144.128 144.128 0 0 0 358.4 128a16 16 0 1 0 0 32 112 112 0 0 1 48 10.816v68.416L280.8 364.8a16.192 16.192 0 0 0 -6.944 6.944l-64.704 64.704 -143.2 -143.232L263.168 96H406.4v40.288zm32 57.344a112 112 0 0 1 32 78.368 110.016 110.016 0 0 1 -1.632 16 111.584 111.584 0 0 1 -153.376 87.52l118.336 -118.336 4.672 -11.328V193.632z\"]\n};\nvar vsTasklist = {\n prefix: \"vs\",\n iconName: \"tasklist\",\n icon: [512, 512, [], \"f000\", \"M114.24 214.368l182.176 -157.952L274.72 32 104.736 179.072l-48.32 -58.624L32 142.144l59.2 70.848 23.04 1.376zM480 160H218.368l73.824 -64H480v64zM192 224h288v64H192V224zm288 128H192v64h288v-64z\"]\n};\nvar vsTelescope = {\n prefix: \"vs\",\n iconName: \"telescope\",\n icon: [512, 512, [], \"f000\", \"M359.68 32l18.88 7.68 67.52 157.76 -7.36 18.88 -105.28 45.12 -18.88 -7.68 -5.44 -13.12L195.2 288l-18.56 -6.08 -5.12 -12.16L89.6 303.68l-18.56 -7.68 -23.04 -53.44 8.96 -18.88 80 -33.92 -5.76 -13.12 7.68 -18.56L252.8 109.12 247.04 96 256 77.44 359.68 32zM80 244.48l11.2 27.2 71.04 -29.12 -11.84 -27.2 -70.4 29.12zm87.68 -67.84l35.52 78.4 96 -40.96 -35.52 -78.08 -96 40.64zM281.28 96l59.52 131.52 73.28 -32.32L357.76 64 279.04 96h2.24zM272 291.2l96.64 156.8h-37.44l-60.16 -96.96v128h-32V314.24L178.56 448h-35.2l54.4 -124.8 74.24 -32z\"]\n};\nvar vsTerminalBash = {\n prefix: \"vs\",\n iconName: \"terminal-bash\",\n icon: [512, 512, [], \"f000\", \"M436.96 113.92L285.376 24a57.12 57.12 0 0 0 -58.24 0L75.616 113.92a60.448 60.448 0 0 0 -29.472 52.096v179.968a60.448 60.448 0 0 0 29.216 52.064l151.552 89.984a57.12 57.12 0 0 0 58.24 0l151.552 -89.984a60.416 60.416 0 0 0 29.216 -52.064V166.016a60.448 60.448 0 0 0 -28.928 -52.064zm-117.408 280.992v12.928a4.768 4.768 0 0 1 -2.24 3.968l-7.648 4.384c-1.216 0.64 -2.24 0 -2.24 -1.696v-12.672a24.96 24.96 0 0 1 -17.44 1.696 2.336 2.336 0 0 1 -0.864 -2.88l2.752 -11.68a4.896 4.896 0 0 1 2.272 -3.072 1.536 1.536 0 0 1 1.216 0 21.184 21.184 0 0 0 15.904 -2.016 21.184 21.184 0 0 0 11.84 -18.144c0 -6.592 -3.584 -9.344 -12.288 -9.376 -11.008 0 -21.152 -2.112 -21.44 -18.368A47.04 47.04 0 0 1 307.2 301.984V288.96a4.704 4.704 0 0 1 2.24 -4.032l7.392 -4.704c1.216 -0.64 2.24 0 2.24 1.728v13.088a24.128 24.128 0 0 1 14.496 -1.76 2.336 2.336 0 0 1 0.96 3.04l-2.592 11.584a4.992 4.992 0 0 1 -2.08 2.88 1.76 1.76 0 0 1 -1.12 0 19.2 19.2 0 0 0 -13.952 2.304 17.568 17.568 0 0 0 -10.592 15.552c0 5.92 3.136 7.744 13.6 7.936 14.016 0 20.064 6.368 20.224 20.448a50.176 50.176 0 0 1 -18.432 37.92zm79.392 -21.76a3.008 3.008 0 0 1 -1.152 2.944l-38.336 23.264a1.088 1.088 0 0 1 -1.28 0.096 1.12 1.12 0 0 1 -0.512 -1.184v-9.92a2.752 2.752 0 0 1 1.76 -2.432l37.728 -22.592a1.12 1.12 0 0 1 1.792 1.12v8.736zm26.464 -221.248L281.984 240.48c-17.888 10.592 -31.04 22.176 -31.04 43.744v176.64c0 12.928 5.28 21.184 13.216 23.712a46.88 46.88 0 0 1 -7.936 0.8c-8.448 0 -16.704 -2.304 -23.936 -6.624L80.704 388.8a49.856 49.856 0 0 1 -24 -42.816V166.016a49.856 49.856 0 0 1 24 -42.88l151.616 -89.92a46.72 46.72 0 0 1 47.648 0l151.552 89.984a49.536 49.536 0 0 1 23.296 34.656c-4.928 -10.688 -16.256 -13.664 -29.44 -5.92h0.064z\"]\n};\nvar vsTerminalCmd = {\n prefix: \"vs\",\n iconName: \"terminal-cmd\",\n icon: [512, 512, [], \"f000\", \"M348 224l64.256 160h-22.752l-64.256 -160h22.752zm-164 19.008c-8.832 0 -16.832 1.312 -24 4a49.344 49.344 0 0 0 -18.496 12c-5.184 5.312 -9.184 11.84 -12 19.52a75.648 75.648 0 0 0 -4.256 26.464c0 9.184 1.28 17.504 3.744 24.992 2.496 7.52 6.272 13.856 11.264 19.008 4.992 5.184 11.072 9.28 18.24 12.256 7.168 3.008 15.36 4.416 24.512 4.256a84.16 84.16 0 0 0 31.744 -6.24l4 15.488a63.936 63.936 0 0 1 -15.744 4.736 140.192 140.192 0 0 1 -24 2.24 83.52 83.52 0 0 1 -29.248 -4.992 70.624 70.624 0 0 1 -23.744 -14.496 60.096 60.096 0 0 1 -15.52 -23.744 102.528 102.528 0 0 1 -5.76 -32.736c0 -11.68 1.92 -22.336 5.76 -32 3.84 -9.664 9.184 -18.016 16 -25.024 6.848 -6.976 15.072 -12.416 24.768 -16.224a86.08 86.08 0 0 1 32 -5.76c9.472 0 17.152 0.736 22.976 2.24 5.856 1.504 10.08 3.008 12.768 4.48l-4.768 15.776a59.2 59.2 0 0 0 -12.992 -4.48 76.352 76.352 0 0 0 -17.248 -1.76zM256 256h32v32H256V256zm0 64h32v32H256v-32zm240 -288H16l-16 16v416l16 16h480l16 -16v-416l-16 -16zM480 448H32V160h448v288zm0 -320H32V64h448v64z\"]\n};\nvar vsTerminalDebian = {\n prefix: \"vs\",\n iconName: \"terminal-debian\",\n icon: [512, 512, [], \"f000\", \"M226.688 0.928a40.832 40.832 0 0 0 -11.36 1.6L211.904 2.08a302.72 302.72 0 0 1 16.448 -1.536c2.4 -0.16 4.8 -0.32 7.168 -0.544a53.44 53.44 0 0 1 -8.832 0.928zm132.064 244.672c3.008 -7.616 5.504 -13.952 5.12 -24.384l-4.256 9.024c4.32 -13.12 3.936 -27.104 3.584 -40.384 -0.16 -5.984 -0.32 -11.84 -0.064 -17.376l-1.728 -0.48c-1.536 -45.152 -40.576 -93.152 -75.328 -109.408 -29.952 -13.824 -76.032 -16.192 -97.344 -5.76a21.024 21.024 0 0 1 6.784 -2.72c3.424 -0.992 6.304 -1.856 4.32 -2.976 -19.2 1.92 -24.896 5.472 -31.136 9.408a61.44 61.44 0 0 1 -20.32 8.736c-3.52 3.392 1.632 2.016 5.792 0.928 4.128 -1.12 7.232 -1.92 -0.128 2.432a54.4 54.4 0 0 1 -9.696 1.6c-8.32 0.8 -15.744 1.536 -30.72 17.024 0.832 1.312 3.52 -0.288 5.376 -1.408 2.304 -1.376 3.392 -2.016 -1.728 4.384C98.24 91.872 56.96 137.92 48.224 153.184l4.576 0.8c-3.2 8 -6.816 14.752 -10.016 20.768 -4.352 8.128 -7.968 14.848 -8.736 21.344a543.04 543.04 0 0 1 -1.984 20.32C29.024 243.808 25.28 277.728 35.84 289.92l-1.28 12.992 1.664 3.52c1.152 2.528 2.272 5.024 3.84 7.36l-2.976 0.256c7.04 22.144 10.816 22.528 15.136 22.944 4.384 0.416 9.312 0.896 18.72 24.224 -2.688 -0.896 -5.44 -1.92 -9.376 -7.232 -0.48 4.064 5.76 16.256 13.12 25.792l-3.104 3.584a28.48 28.48 0 0 0 8.64 9.952c0.736 0.608 1.44 1.152 2.112 1.76 -11.904 -6.496 3.2 13.696 11.872 25.28 2.496 3.328 4.48 5.952 5.088 6.976l2.336 -4.224c-0.32 6.08 4.352 13.856 13.12 24.704l7.328 -0.288c3.008 5.952 14.016 16.704 20.704 17.216l-4.448 5.792c8.128 2.56 10.272 4.32 12.704 6.24 2.56 2.048 5.44 4.352 16.064 8.096l-4.16 -7.36c3.456 3.04 6.144 5.952 8.736 8.704 5.184 5.632 9.92 10.72 19.84 15.392 11.264 3.936 17.152 4.864 23.68 5.888 5.376 0.832 11.2 1.76 20.768 4.48a1082.24 1082.24 0 0 0 -6.944 -0.16c-16.192 -0.384 -33.792 -0.8 -46.176 -5.216 -96.512 -26.144 -184.832 -139.392 -178.368 -256 -0.64 -9.952 -0.32 -20.96 0 -30.752 0.384 -13.504 0.704 -24.832 -1.568 -28.224l1.024 -3.36c5.312 -17.28 11.68 -38.112 23.744 -62.624L27.552 125.44v-0.064c0.384 0.384 3.392 3.424 8.8 -5.76 1.28 -2.88 2.528 -5.824 3.744 -8.832 2.56 -6.08 5.12 -12.256 8.448 -17.92l2.56 -0.64c1.728 -10.08 17.056 -23.808 29.76 -35.2 6.08 -5.472 11.584 -10.432 14.72 -14.176l0.64 4.416C113.312 31.264 141.248 19.552 162.368 10.688c4.864 -2.016 9.312 -3.904 13.248 -5.632 -3.424 3.776 2.144 2.624 9.952 1.024 4.8 -0.96 10.4 -2.144 15.296 -2.432 -1.28 0.736 -2.624 1.408 -3.904 2.08 -2.72 1.44 -5.44 2.816 -8 4.64 8.32 -1.984 11.936 -1.408 15.968 -0.768 3.488 0.576 7.264 1.152 14.592 0.192 -5.568 0.8 -12.288 3.008 -11.2 3.84 7.84 0.928 12.736 -0.064 17.184 -0.96 5.568 -1.088 10.464 -2.08 19.52 0.96L244 8.8c7.52 2.72 13.088 4.384 18.048 5.856 10.016 3.008 17.6 5.28 34.144 14.048a18.56 18.56 0 0 0 7.36 -1.184c3.584 -1.12 6.976 -2.208 15.264 1.184 0.448 0.8 0.704 1.472 0.96 2.112 0.96 2.56 1.728 4.576 14.592 12.256 1.792 -0.704 -3.104 -5.184 -7.04 -8.768l-0.096 -0.128c32.32 17.28 67.456 54.144 78.176 93.568 -6.016 -11.104 -5.184 -5.472 -4.288 0.48 0.576 3.968 1.184 8.096 -0.192 7.52 4.48 12.064 8.16 24.512 10.4 37.376l-0.736 -2.72c-3.264 -11.776 -9.6 -34.592 -20.032 -49.76 -0.384 4.384 -2.944 3.904 -5.28 3.456 -3.36 -0.608 -6.272 -1.152 -1.856 12.576 2.592 3.808 3.072 2.368 3.488 1.088 0.48 -1.504 0.864 -2.752 4.704 5.248 0.064 4.256 1.088 8.512 2.24 13.248 0.704 3.008 1.472 6.24 2.08 9.792 -1.088 -0.192 -2.24 -2.24 -3.392 -4.16 -1.44 -2.432 -2.784 -4.704 -3.744 -3.232 2.432 11.456 6.432 17.44 8 18.304 -0.288 0.64 -0.672 0.64 -1.088 0.672 -0.864 0.064 -1.792 0.096 -1.888 5.344 0.704 13.696 3.264 12.48 5.312 11.552 0.64 -0.288 1.184 -0.544 1.632 -0.32a55.168 55.168 0 0 1 -2.656 7.84c-2.752 7.072 -6.016 15.36 -3.392 26.112a75.392 75.392 0 0 0 -3.392 -9.44 188.672 188.672 0 0 1 -1.472 -3.744c-0.576 4.832 -0.32 8.192 -0.096 11.36 0.416 5.312 0.736 9.984 -3.008 19.84 4.32 -14.144 3.84 -26.912 -0.224 -20.768 0.96 10.976 -3.84 20.544 -8.128 29.056 -3.552 7.104 -6.752 13.44 -5.888 19.264l-5.152 -7.104c-7.616 11.008 -7.04 13.344 -6.464 15.648 0.48 1.92 0.96 3.84 -3.36 10.848 1.632 -2.88 1.312 -3.584 0.992 -4.256 -0.32 -0.768 -0.672 -1.472 1.696 -5.056 -1.6 0.096 -5.44 3.84 -10.112 8.48 -3.936 3.872 -8.48 8.352 -12.864 11.776 -37.504 30.08 -82.272 33.984 -125.632 17.792 0.192 -0.992 -0.192 -2.112 -3.104 -4.096 -36.736 -28.16 -58.464 -52.096 -50.912 -107.52 2.176 -1.632 3.744 -6.176 5.6 -11.584 2.88 -8.416 6.496 -18.88 14.336 -23.84 7.84 -17.312 31.328 -33.28 56.448 -33.664 25.6 -1.408 47.232 13.664 58.112 27.904 -19.776 -18.432 -52.16 -24.032 -79.776 -10.368 -28.224 12.672 -44.96 43.776 -42.528 74.752 0.32 -0.512 0.672 -0.736 0.96 -0.96 0.64 -0.48 1.184 -0.864 1.536 -3.456 -0.864 60.16 64.832 104.256 112.128 82.016l0.576 1.248c12.704 -3.488 15.904 -6.56 20.256 -10.72 2.24 -2.144 4.736 -4.544 8.96 -7.456a14.112 14.112 0 0 1 -2.4 2.72c-2.176 2.144 -4.576 4.48 -1.6 4.544 5.312 -1.376 20.288 -14.88 30.304 -23.872l4.256 -3.808c1.984 -4.288 1.632 -5.664 1.28 -7.072 -0.384 -1.664 -0.8 -3.328 2.432 -9.6l7.328 -3.648c0.96 -2.816 1.984 -5.376 2.944 -7.776zM211.584 321.92a0.576 0.576 0 0 0 -0.16 0.512 3.648 3.648 0 0 0 0.16 -0.512zm-0.16 0.512c0.256 2.208 8.608 8.576 14.88 11.808 16.512 6.08 35.2 6.336 49.888 5.792 -31.776 13.28 -92.448 -13.504 -112.288 -49.024 1.824 0.384 5.376 4.48 9.696 9.504 6.528 7.488 14.784 17.024 21.696 19.36 -6.816 -5.44 -12.064 -12.384 -16.96 -19.52 9.216 10.56 20.384 19.2 32.608 24.928a3.264 3.264 0 0 1 0.32 -2.464l0.16 -0.384zM216.064 7.008a211.584 211.584 0 0 1 -2.4 -0.416c15.104 0.448 13.984 1.44 9.056 2.56 0.576 -0.928 -2.88 -1.504 -6.656 -2.144zM308.16 215.424c1.024 -15.264 -3.008 -10.432 -4.352 -4.608 0.608 0.32 1.152 1.888 1.664 3.424 0.896 2.56 1.728 5.056 2.688 1.184zm-6.752 21.248a53.76 53.76 0 0 1 -10.048 22.496c0.192 -1.952 -1.216 -2.368 -2.656 -2.752 -2.944 -0.832 -5.856 -1.664 5.632 -16.128a35.616 35.616 0 0 1 -4.032 7.744c-3.584 5.888 -6.72 11.008 4.032 4.256l1.056 -1.92a45.76 45.76 0 0 0 6.016 -13.696zm-42.88 39.904c-11.104 -1.696 -21.184 -5.952 -12.704 -6.08 7.072 0.64 14.08 0.64 20.992 -1.056a113.408 113.408 0 0 1 -8.32 7.136zM222.656 9.12l-3.2 0.64 3.008 -0.256 0.192 -0.384zM153.28 282.176l-1.216 5.952c1.504 2.048 2.944 4.16 4.352 6.24 3.84 5.6 7.584 11.136 12.8 15.456a151.36 151.36 0 0 0 -6.848 -11.776c-2.56 -4.16 -5.408 -8.704 -9.12 -15.872zm7.232 -10.208c1.664 3.456 3.328 6.816 5.92 9.664l2.624 7.68 -1.216 -2.016c-3.2 -5.312 -6.4 -10.656 -8.064 -16.768l0.736 1.44zm239.168 -41.024l-1.248 3.136a150.944 150.944 0 0 1 -14.784 47.168c8.352 -15.68 13.76 -32.896 16.032 -50.304zM13.952 109.632zm0.064 0.704c0.256 1.184 1.376 0.896 2.4 0.64 1.92 -0.48 3.648 -0.96 -0.128 7.552 -2.368 1.664 -3.808 2.784 -4.608 3.392l-0.864 0.64a1.6 1.6 0 0 1 0.256 -0.544 19.104 19.104 0 0 0 2.944 -11.68zM3.776 152.32a93.44 93.44 0 0 1 -3.392 13.952 18.816 18.816 0 0 0 -0.16 -4.928c-0.416 -3.36 -0.8 -6.304 4.32 -12.864a128.288 128.288 0 0 0 -0.736 3.84z\"]\n};\nvar vsTerminalLinux = {\n prefix: \"vs\",\n iconName: \"terminal-linux\",\n icon: [512, 512, [], \"f000\", \"M424.992 356.992a26.88 26.88 0 0 1 12 9.504c2.688 4 4.576 8.832 5.76 14.496 0.64 3.328 1.408 6.4 2.24 9.28a56.704 56.704 0 0 0 7.008 15.232c1.504 2.336 3.52 4.896 6.016 7.744 2.144 2.336 4.064 5.344 5.76 8.992a25.376 25.376 0 0 1 2.464 10.496 15.68 15.68 0 0 1 -2.976 9.76 30.208 30.208 0 0 1 -7.52 7.008c-3.84 2.656 -7.84 4.992 -12 7.008 -4.16 1.984 -8.32 4.064 -12.48 6.24a115.968 115.968 0 0 0 -17.76 10.496c-4.992 3.68 -10.016 8.32 -15.008 14.016a90.08 90.08 0 0 1 -20 16.736 47.072 47.072 0 0 1 -12.256 5.504c-4.16 1.152 -8.32 1.92 -12.48 2.24 -9.664 0 -17.664 -1.664 -24 -4.992 -6.336 -3.328 -11.84 -9.408 -16.512 -18.24 -1.344 -2.528 -2.656 -4.096 -4 -4.768a24.768 24.768 0 0 0 -6.496 -1.76L277.44 480c-8.32 -0.64 -16.8 -0.992 -25.472 -0.992a136.96 136.96 0 0 0 -21.504 1.728c-7.328 1.184 -14.592 2.592 -21.76 4.256 -1.472 0.32 -2.976 1.6 -4.48 3.744a54.4 54.4 0 0 1 -6.272 7.264 35.392 35.392 0 0 1 -10.72 7.008 47.2 47.2 0 0 1 -17.76 3.232c-5.504 0 -11.424 -0.576 -17.76 -1.728a58.24 58.24 0 0 1 -16.992 -5.76 114.496 114.496 0 0 0 -30.496 -10.496c-10.016 -1.824 -20.576 -3.52 -31.744 -4.992a108.544 108.544 0 0 1 -11.008 -2.016 24.768 24.768 0 0 1 -9.28 -4.256 22.56 22.56 0 0 1 -6.208 -7.008 24.96 24.96 0 0 1 -2.528 -11.232c0 -5.184 0.672 -10.176 2.016 -15.008 1.344 -4.8 2.08 -9.92 2.24 -15.232 0 -3.68 -0.256 -7.264 -0.736 -10.752a112.96 112.96 0 0 1 -1.024 -11.264c0 -8.48 2.016 -14.72 6.016 -18.752 4 -4 9.824 -7.168 17.504 -9.504a31.68 31.68 0 0 0 9.504 -4.736 72.64 72.64 0 0 0 7.488 -6.496 59.52 59.52 0 0 0 6.496 -7.744c2.016 -2.848 4.256 -5.696 6.752 -8.512a3.648 3.648 0 0 0 0.768 -2.24c0 -2.016 -0.096 -3.936 -0.256 -5.76l-0.512 -6.016c0 -11.328 1.76 -22.72 5.248 -34.24 3.52 -11.52 8.096 -22.72 13.76 -33.76a290.56 290.56 0 0 1 19.008 -31.744c6.976 -10.144 13.92 -19.584 20.736 -28.256a139.2 139.2 0 0 0 21.76 -38.496c4.8 -13.312 7.328 -27.84 7.488 -43.52 0 -6.624 -0.32 -13.216 -0.992 -19.712a195.904 195.904 0 0 1 -0.992 -20c0 -13.344 1.504 -25.344 4.48 -36 3.008 -10.688 7.68 -19.84 14.016 -27.52s14.592 -13.408 24.736 -17.248C239.168 2.4 251.328 0.32 265.472 0c16.864 0 30.272 3.328 40.288 10.016 9.984 6.656 17.664 15.392 22.976 26.24 5.344 10.816 8.768 22.912 10.24 36.256 1.536 13.312 2.368 26.816 2.528 40.48v4.256c0 6.848 0.064 12.928 0.256 18.24a80.864 80.864 0 0 0 7.232 31.264c2.336 5.152 5.824 10.752 10.496 16.736 8 10.528 16.192 21.12 24.512 31.776 8.32 10.656 15.904 21.664 22.72 32.96 6.848 11.36 12.448 23.2 16.768 35.52 4.352 12.352 6.592 25.664 6.752 40a105.6 105.6 0 0 1 -5.248 33.28zm-209.728 -260.48c2.304 0 4.224 0.576 5.76 1.728a11.424 11.424 0 0 1 3.488 4.768 27.2 27.2 0 0 1 1.728 5.984c0.32 2.016 0.512 4.096 0.512 6.272a9.024 9.024 0 0 1 -0.768 4 8.64 8.64 0 0 1 -2.24 2.752l-3.008 2.496a25.472 25.472 0 0 0 -2.976 2.976 13.696 13.696 0 0 1 -4.768 4.512 68.128 68.128 0 0 0 -5.76 3.744 41.92 41.92 0 0 0 -4.992 4.256 8.448 8.448 0 0 0 -2.24 6.24c0 1.504 0.736 2.752 2.24 3.744a22.528 22.528 0 0 1 8.512 9.76c1.664 3.84 3.52 7.584 5.504 11.264 1.984 3.648 4.576 6.72 7.744 9.248 3.168 2.496 8.096 3.744 14.72 3.744h1.536c6.656 -0.32 12.992 -2.08 19.008 -5.248 5.984 -3.168 12 -6.496 17.984 -10.016a20.256 20.256 0 0 1 3.264 -1.472 11.84 11.84 0 0 0 3.232 -1.76l18.24 -14.24a29.632 29.632 0 0 0 0.768 -3.264 88 88 0 0 0 0.512 -3.52 7.552 7.552 0 0 0 -1.28 -4.48 12.8 12.8 0 0 0 -2.976 -3.008 10.88 10.88 0 0 0 -4.256 -1.728 29.088 29.088 0 0 1 -4.48 -1.28 34.656 34.656 0 0 1 -11.264 -4.48 46.624 46.624 0 0 0 -11.008 -4.992c-0.64 -0.192 -1.152 -0.672 -1.504 -1.504a31.456 31.456 0 0 1 -0.992 -3.008 7.36 7.36 0 0 1 -0.256 -3.264 4.032 4.032 0 0 0 -0.256 -2.496c0 -1.984 0.16 -4.064 0.512 -6.24a17.632 17.632 0 0 1 2.24 -6.24 13.344 13.344 0 0 1 4 -4.48 13.152 13.152 0 0 1 6.496 -1.792c5.184 0 8.928 1.92 11.264 5.76 2.336 3.84 3.584 8 3.744 12.48a12.704 12.704 0 0 1 -1.248 5.76 12.128 12.128 0 0 0 -1.28 5.504c0 1.344 0.448 2.24 1.28 2.752a8.32 8.32 0 0 0 3.264 0.992c3.84 0 6.304 -0.896 7.488 -2.72a17.056 17.056 0 0 0 1.984 -8.256c0 -3.84 -0.32 -8.096 -0.96 -12.768a42.24 42.24 0 0 0 -4.032 -12.992 31.008 31.008 0 0 0 -7.744 -10.016 18.368 18.368 0 0 0 -12.256 -3.968c-8.64 0 -14.912 2.144 -18.752 6.496 -3.84 4.32 -5.824 10.816 -5.984 19.488 0 2.496 0.16 4.992 0.48 7.488 0.32 2.528 0.512 5.024 0.512 7.52 0 0.832 -0.096 1.248 -0.256 1.248a6.976 6.976 0 0 1 -1.504 -0.512 136.416 136.416 0 0 1 -2.976 -1.248 24.768 24.768 0 0 0 -3.776 -1.248 16.448 16.448 0 0 0 -6.496 -0.256 32.224 32.224 0 0 1 -4 0.256c-2.336 0 -3.52 -0.416 -3.52 -1.248 0 -2.496 -0.128 -5.664 -0.48 -9.504 -0.32 -3.84 -1.152 -7.68 -2.496 -11.52a31.84 31.84 0 0 0 -4.992 -9.472c-2.016 -2.496 -4.992 -3.84 -8.992 -4a10.336 10.336 0 0 0 -7.264 2.752 28.96 28.96 0 0 0 -5.248 6.496 20.48 20.48 0 0 0 -2.752 8.512 172.8 172.8 0 0 1 -0.992 8 46.688 46.688 0 0 0 2.24 12.992c0.832 2.656 1.76 4.992 2.752 7.008 0.992 1.984 2.176 2.976 3.52 2.976 0.8 0 1.92 -0.576 3.232 -1.728 1.344 -1.184 2.016 -2.24 2.016 -3.264 0 -0.512 -0.256 -0.832 -0.768 -0.992a4.704 4.704 0 0 0 -1.504 -0.256c-1.152 0 -2.176 -0.576 -3.008 -1.76a14.976 14.976 0 0 1 -1.984 -4 164.608 164.608 0 0 1 -1.504 -4.736 18.048 18.048 0 0 1 1.76 -12.736c1.504 -2.688 4.256 -4.096 8.256 -4.256zM160.736 485.76c4 0 7.936 -0.32 11.776 -1.024a31.04 31.04 0 0 0 10.752 -4 19.648 19.648 0 0 0 7.488 -7.744 30.176 30.176 0 0 0 3.008 -12 26.112 26.112 0 0 0 -1.504 -8.736 30.816 30.816 0 0 0 -4.256 -8 88.416 88.416 0 0 0 -6.496 -8.992 88.416 88.416 0 0 1 -6.496 -9.024 2013.76 2013.76 0 0 1 -9.28 -13.76c-2.976 -4.48 -5.984 -9.216 -8.96 -14.24a259.968 259.968 0 0 1 -7.52 -12.992 84.672 84.672 0 0 0 -8.512 -12.736 38.496 38.496 0 0 0 -6.976 -6.752 15.008 15.008 0 0 0 -9.28 -3.008 13.952 13.952 0 0 0 -9.472 3.52 72.32 72.32 0 0 0 -8.256 8.48 103.712 103.712 0 0 1 -9.504 9.76c-3.52 3.168 -8 5.664 -13.504 7.488a23.808 23.808 0 0 0 -9.984 5.504c-2.336 2.336 -3.52 5.92 -3.52 10.752 0 3.328 0.256 6.656 0.768 9.984 0.48 3.328 0.832 6.688 0.992 10.016 0 4.48 -0.64 8.736 -2.016 12.736a37.024 37.024 0 0 0 -1.984 11.744c0 4.512 1.6 7.68 4.736 9.504 3.2 1.856 6.752 3.104 10.752 3.744 5.024 0.864 9.76 1.504 14.272 2.016 4.48 0.512 8.896 1.28 13.248 2.24 4.32 1.024 8.64 2.08 12.992 3.264 4.32 1.152 8.928 3.008 13.76 5.504 0.96 0.48 2.496 1.088 4.48 1.728l6.752 2.24c2.496 0.864 4.832 1.536 7.008 2.016a23.712 23.712 0 0 0 4.736 0.768zm91.52 -30.016c4.672 0 9.664 -0.48 15.008 -1.504a113.28 113.28 0 0 0 31.232 -10.752 82.88 82.88 0 0 0 12.992 -8.224 7.104 7.104 0 0 0 1.024 -1.504 9.76 9.76 0 0 0 0.736 -2.016v-0.256c0.992 -3.648 1.824 -7.68 2.496 -12a276.16 276.16 0 0 0 1.76 -13.248 287.36 287.36 0 0 1 1.76 -13.248c0.64 -4.32 1.248 -8.576 1.728 -12.736 0.672 -4.48 1.504 -8.832 2.496 -12.992 1.024 -4.16 2.336 -8.096 4 -11.776a32.96 32.96 0 0 1 6.752 -9.728 49.28 49.28 0 0 1 11.008 -8v-0.512l-0.256 -0.736a9.28 9.28 0 0 1 1.504 -4.768 44.8 44.8 0 0 1 3.744 -5.248 18.624 18.624 0 0 1 4.768 -4.256 30.272 30.272 0 0 1 5.248 -2.496 314.784 314.784 0 0 0 -3.264 -12 158.016 158.016 0 0 1 -3.008 -12 228.032 228.032 0 0 0 -2.976 -15.232 94.528 94.528 0 0 0 -3.52 -11.52 42.144 42.144 0 0 0 -5.76 -10.24c-2.464 -3.328 -5.568 -7.36 -9.216 -12a38.048 38.048 0 0 1 -3.776 -4.992 17.76 17.76 0 0 1 -1.472 -6.272 70.592 70.592 0 0 0 -1.504 -6.496 303.36 303.36 0 0 0 -7.744 -24 93.12 93.12 0 0 0 -5.504 -12.256 123.84 123.84 0 0 0 -5.504 -9.248c-1.664 -2.496 -3.424 -3.744 -5.248 -3.744 -4 0 -8.768 1.6 -14.272 4.768 -5.472 3.168 -11.328 6.656 -17.472 10.496 -6.176 3.84 -12.16 7.424 -18.016 10.752 -5.824 3.328 -11.072 4.896 -15.744 4.736a22.4 22.4 0 0 1 -13.76 -4.736 71.552 71.552 0 0 1 -11.52 -11.008c-3.488 -4.16 -6.4 -7.744 -8.736 -10.752 -2.336 -3.008 -4.064 -4.672 -5.248 -4.992 -1.312 0 -2.08 0.992 -2.24 2.976a81.92 81.92 0 0 0 -0.256 6.752v4.256c0 1.024 -0.16 1.664 -0.512 2.016 -1.824 3.84 -3.84 7.584 -5.984 11.232 -2.176 3.68 -4.32 7.424 -6.496 11.264a51.552 51.552 0 0 0 -7.008 24.256c0 2.496 0.16 4.992 0.512 7.488 0.32 2.496 1.152 4.928 2.496 7.264l-0.512 0.96a41.92 41.92 0 0 1 -4.256 5.024 34.304 34.304 0 0 0 -4.224 5.248 89.472 89.472 0 0 0 -13.024 29.76c-2.496 10.656 -3.84 21.504 -4 32.48 0 2.848 0.192 5.696 0.512 8.512 0.32 2.848 0.512 5.664 0.512 8.512a16.832 16.832 0 0 1 -0.256 2.752 16.8 16.8 0 0 0 -0.256 2.752 24 24 0 0 1 10.016 3.488c3.84 2.176 8 4.928 12.48 8.256 4.48 3.328 8.768 7.168 12.768 11.52 4 4.32 7.808 8.544 11.488 12.736 3.68 4.16 6.336 8.32 8 12.48 1.664 4.16 2.752 7.584 3.232 10.24a14.208 14.208 0 0 1 -4 10.528 30.56 30.56 0 0 1 -9.984 6.496c2.848 4.992 6.336 9.248 10.496 12.736 4.16 3.52 8.672 6.336 13.504 8.512 4.832 2.176 10.08 3.744 15.744 4.736 5.664 1.024 11.2 1.504 16.512 1.504zm100.256 35.52c3.488 0 6.912 -0.512 10.24 -1.504a52.8 52.8 0 0 0 14.24 -6.496c4.352 -2.848 8.32 -6.336 12 -10.528a98.24 98.24 0 0 1 31.264 -24l8.256 -3.744a69.76 69.76 0 0 0 8.224 -4.256 30.784 30.784 0 0 0 5.28 -4.224 8.192 8.192 0 0 0 2.496 -6.016 9.44 9.44 0 0 0 -0.768 -3.744 18.56 18.56 0 0 0 -2.24 -3.744 164.352 164.352 0 0 1 -6.496 -9.76 63.296 63.296 0 0 1 -4.768 -9.504l-4 -9.984a81.856 81.856 0 0 1 -3.52 -11.264 8.96 8.96 0 0 0 -1.728 -3.232 16.96 16.96 0 0 0 -14.72 -7.52 17.056 17.056 0 0 0 -8.512 2.24l-8.512 4.768a234.72 234.72 0 0 1 -8.992 4.736 20.992 20.992 0 0 1 -9.504 2.24 13.152 13.152 0 0 1 -8.256 -2.464 20.352 20.352 0 0 1 -5.504 -6.752 70.976 70.976 0 0 1 -3.744 -8.256l-3.008 -8.256a40.32 40.32 0 0 1 -4.48 6.016 21.312 21.312 0 0 0 -4 6.496c-2.176 4.992 -3.52 10.56 -4 16.736 -0.832 9.664 -1.92 19.072 -3.264 28.256a150.4 150.4 0 0 1 -6.72 27.52 61.248 61.248 0 0 0 -2.016 8.736 92.16 92.16 0 0 0 -1.024 9.248c0 8.16 2.528 14.912 7.52 20.256 4.992 5.312 11.744 8 20.256 8z\"]\n};\nvar vsTerminalPowershell = {\n prefix: \"vs\",\n iconName: \"terminal-powershell\",\n icon: [512, 512, [], \"f000\", \"M80 32.224l415.968 5.44 13.76 16.032 -58.24 411.904 -18.24 15.648 -416 -5.44 -13.76 -16.064L61.76 47.84l18.24 -15.616zM37.76 444.32l383.936 5.024 53.76 -380.224L91.52 64.096 37.76 444.32zm185.312 -111.68l-4.48 31.712 160 2.112 4.48 -31.68 -160 -2.112zm54.72 -78.624l-117.216 -93.76 -22.144 25.472 84.352 67.584L119.648 318.4l14.88 25.984L277.76 254.016z\"]\n};\nvar vsTerminalTmux = {\n prefix: \"vs\",\n iconName: \"terminal-tmux\",\n icon: [512, 512, [], \"f000\", \"M432 32h-384l-16 16v416l16 16h384l16 -16v-416l-16 -16zM224 240V416H64V64h160v176zm192 176H256V256h160v160zm0 -192H256V64h160v160z\"]\n};\nvar vsTerminalUbuntu = {\n prefix: \"vs\",\n iconName: \"terminal-ubuntu\",\n icon: [512, 512, [], \"f000\", \"M104.32 256A43.84 43.84 0 1 1 16.64 256a43.84 43.84 0 0 1 87.68 0zm249.28 213.12a43.84 43.84 0 1 0 75.968 -43.84 43.84 43.84 0 0 0 -75.968 43.84zm75.84 -382.4a43.84 43.84 0 1 0 -75.84 -43.936 43.84 43.84 0 0 0 75.84 43.936zM281.28 131.2a124.8 124.8 0 0 1 124.48 113.6h64a189.76 189.76 0 0 0 -55.36 -121.6 61.12 61.12 0 0 1 -53.12 -3.84 64.032 64.032 0 0 1 -30.08 -44.16 192 192 0 0 0 -49.28 -6.4 186.56 186.56 0 0 0 -83.52 19.52l32 55.36a126.08 126.08 0 0 1 50.88 -12.48zM156.16 256a125.76 125.76 0 0 1 53.12 -102.4l-32 -54.4A189.76 189.76 0 0 0 99.2 208a61.44 61.44 0 0 1 0 96 189.76 189.76 0 0 0 77.44 108.8l32 -54.4A125.76 125.76 0 0 1 156.16 256zm125.12 125.12a128 128 0 0 1 -52.8 -11.84l-32 55.36c25.92 12.896 54.528 19.584 83.52 19.52 16.64 0 33.216 -2.144 49.28 -6.4a64 64 0 0 1 30.08 -44.16 61.152 61.152 0 0 1 53.12 -3.84 189.76 189.76 0 0 0 55.36 -121.6h-64a125.12 125.12 0 0 1 -122.56 112.96z\"]\n};\nvar vsTerminal = {\n prefix: \"vs\",\n iconName: \"terminal\",\n icon: [512, 512, [], \"f000\", \"M64 32L32 64v384L64 480h384l32 -32V64L448 32H64zM64 448V64h384v384H64zm120.661 -85.547l22.144 22.635 112.213 -111.851v-19.456l-112.213 -112.213 -22.08 22.613 97.92 100.309 -97.984 97.963z\"]\n};\nvar vsTextSize = {\n prefix: \"vs\",\n iconName: \"text-size\",\n icon: [512, 512, [], \"f000\", \"M107.52 224L32 416h42.88l16.32 -47.04h72.32L180.48 416H224L148.8 224H107.52zm-4.8 112.96l24.96 -68.48 24.96 68.48H102.72zM378.24 128h-51.2L224 416h49.92l24 -73.28h107.52l24.64 73.28H480l-101.76 -288zM309.44 304l37.76 -114.88c1.888 -5.92 3.2 -12.032 3.84 -18.24 0.864 6.144 2.048 12.224 3.52 18.24l40 114.88H309.44z\"]\n};\nvar vsThreeBars = {\n prefix: \"vs\",\n iconName: \"three-bars\",\n icon: [512, 512, [], \"f000\", \"M448 160H64V96h384v64zm0 128H64V224h384v64zM64 416h384v-64H64v64z\"]\n};\nvar vsThumbsdown = {\n prefix: \"vs\",\n iconName: \"thumbsdown\",\n icon: [512, 512, [], \"f000\", \"M174.72 451.52a46.72 46.72 0 0 1 -25.92 -8 44.16 44.16 0 0 1 -14.4 -54.08L165.44 320H76.16a43.52 43.52 0 0 1 -37.12 -19.52 43.2 43.2 0 0 1 -2.88 -42.24C57.6 211.84 96 128 108.8 92.8A44.16 44.16 0 0 1 150.08 64h285.76A44.8 44.8 0 0 1 480 108.8v112.32a44.16 44.16 0 0 1 -44.16 44.16h-44.16L204.8 440a45.12 45.12 0 0 1 -30.08 11.52zM150.08 96a12.48 12.48 0 0 0 -11.52 8C125.76 138.88 91.52 214.4 64 271.68a12.48 12.48 0 0 0 0 11.52 11.84 11.84 0 0 0 12.16 4.8h105.6l16.64 21.76v14.72l-34.88 78.08a11.84 11.84 0 0 0 4.16 14.72 12.16 12.16 0 0 0 15.36 0l193.92 -178.88 15.04 -4.16h43.84a12.16 12.16 0 0 0 12.16 -13.12V108.8a12.8 12.8 0 0 0 -12.16 -12.8H150.08z\"]\n};\nvar vsThumbsup = {\n prefix: \"vs\",\n iconName: \"thumbsup\",\n icon: [512, 512, [], \"f000\", \"M337.28 64c9.248 0.032 18.24 2.816 25.92 8a44.16 44.16 0 0 1 14.4 54.08l-31.04 69.44h89.28a43.52 43.52 0 0 1 37.12 19.52 43.2 43.2 0 0 1 2.88 42.24c-21.44 46.4 -59.84 130.24 -72.64 165.44a44.16 44.16 0 0 1 -41.28 28.8H76.16A44.8 44.8 0 0 1 32 406.72V294.4a44.16 44.16 0 0 1 44.16 -44.16h44.16L307.2 75.52a45.12 45.12 0 0 1 30.08 -11.52zm24.64 355.52a12.48 12.48 0 0 0 11.52 -8c12.8 -34.88 47.04 -110.4 74.56 -167.68a12.48 12.48 0 0 0 0 -11.52 11.84 11.84 0 0 0 -12.16 -4.8h-105.6l-16.64 -21.76v-14.72l34.88 -78.08a11.84 11.84 0 0 0 -4.16 -14.72 12.16 12.16 0 0 0 -15.36 0L135.04 277.12l-15.04 4.16H76.16A12.16 12.16 0 0 0 64 294.4v112.32a12.8 12.8 0 0 0 12.16 12.8h285.76z\"]\n};\nvar vsTools = {\n prefix: \"vs\",\n iconName: \"tools\",\n icon: [512, 512, [], \"f000\", \"M472.736 111.52l-24.96 -5.888 -67.456 67.072 -38.208 -38.912 65.792 -69.024 -5.76 -25.344a141.44 141.44 0 0 0 -43.104 -7.296 116.48 116.48 0 0 0 -46.624 8.96 122.368 122.368 0 0 0 -37.952 26.88 119.552 119.552 0 0 0 -28 40.48 126.016 126.016 0 0 0 0 94.912 10730.912 10730.912 0 0 0 -197.536 199.488c-6.72 8.8 -9.92 19.776 -9.088 30.816a44.896 44.896 0 0 0 14.848 30.944c3.968 4.32 8.704 7.904 13.984 10.496 5.44 2.4 11.296 3.776 17.216 4.064 10.112 -0.192 19.808 -4.032 27.328 -10.784 49.536 -46.624 144.448 -142.4 198.368 -198.528 14.624 6.208 30.336 9.408 46.208 9.376a119.552 119.552 0 0 0 85.664 -36.256 124.32 124.32 0 0 0 35.552 -87.36 134.752 134.752 0 0 0 -6.272 -44.096zM93.856 445.696a9.92 9.92 0 0 1 -4.32 2.24 13.984 13.984 0 0 1 -4.768 0 11.072 11.072 0 0 1 -4.608 -1.824 10.752 10.752 0 0 1 -3.648 -3.52c-4.48 -4.576 -8.672 -13.28 -4.48 -18.176 43.84 -46.624 134.112 -137.76 190.56 -193.472 3.2 4.224 6.72 8.256 10.496 12.032 3.776 3.936 7.84 7.584 12.16 10.912 -54.592 56 -143.616 146.048 -191.36 191.808zm355.776 -290.08c0.064 24.48 -9.472 48 -26.624 65.536a91.552 91.552 0 0 1 -128.224 0 95.744 95.744 0 0 1 -20.32 -100.384A87.936 87.936 0 0 1 324.48 69.76a88.32 88.32 0 0 1 34.304 -6.848h8.128L308.768 122.848v22.272l60.64 60.352h21.12l59.104 -58.112v8.256zM103.68 214.016h48.992l22.56 22.944 21.696 -21.568 -21.28 -21.696V192.32l1.824 -52.768 -7.04 -13.984 -91.52 -60.224 -18.912 2.112 -26.592 27.168 -2.112 19.168 58.816 93.376 13.568 6.88zm-30.24 -116.224L147.488 146.56 146.24 182.496H111.808L64.064 106.912l9.376 -9.12zm227.36 222.72l21.568 -21.536 99.392 101.92a47.328 47.328 0 0 1 0 65.248 44.928 44.928 0 0 1 -49.568 10.08 41.92 41.92 0 0 1 -13.984 -10.08l-100.544 -102.496 21.728 -21.696 100.224 102.208a12.864 12.864 0 0 0 4.896 3.36 15.264 15.264 0 0 0 11.488 0 12.896 12.896 0 0 0 4.896 -3.36 13.952 13.952 0 0 0 3.2 -4.896 16.8 16.8 0 0 0 1.152 -5.888 17.504 17.504 0 0 0 -1.12 -5.888 13.952 13.952 0 0 0 -3.2 -4.896L300.8 320.512z\"]\n};\nvar vsTrash = {\n prefix: \"vs\",\n iconName: \"trash\",\n icon: [512, 512, [], \"f000\", \"M320 96h96v32h-32v288l-32 32H128l-32 -32V128H64V96h96V64a32 32 0 0 1 32 -32h96a32 32 0 0 1 32 32v32zM288 64H192v32h96V64zM128 416h224V128H128v288zm64 -256H160v224h32V160zm32 0h32v224H224V160zm64 0h32v224H288V160z\"]\n};\nvar vsTriangleDown = {\n prefix: \"vs\",\n iconName: \"triangle-down\",\n icon: [512, 512, [], \"f000\", \"M64 177.92L77.216 160h358.208l12.576 17.28L267.936 352h-26.464L64 177.92z\"]\n};\nvar vsTriangleLeft = {\n prefix: \"vs\",\n iconName: \"triangle-left\",\n icon: [512, 512, [], \"f000\", \"M334.08 64l17.92 13.216v358.208l-17.28 12.576L160 267.936v-26.464L334.08 64z\"]\n};\nvar vsTriangleRight = {\n prefix: \"vs\",\n iconName: \"triangle-right\",\n icon: [512, 512, [], \"f000\", \"M177.92 448L160 434.784V76.576L177.28 64 352 244.064v26.464L177.92 448z\"]\n};\nvar vsTriangleUp = {\n prefix: \"vs\",\n iconName: \"triangle-up\",\n icon: [512, 512, [], \"f000\", \"M448 334.08l-13.216 17.92H76.576L64 334.72 244.064 160h26.464L448 334.08z\"]\n};\nvar vsTwitter = {\n prefix: \"vs\",\n iconName: \"twitter\",\n icon: [512, 512, [], \"f000\", \"M480 121.088a180.16 180.16 0 0 1 -20.8 25.696 193.856 193.856 0 0 1 -25.152 21.76 174.144 174.144 0 0 1 0.448 12.064c0 18.368 -1.952 36.512 -5.888 54.464a270.944 270.944 0 0 1 -17.088 52.064 270.208 270.208 0 0 1 -40.448 65.28 248.576 248.576 0 0 1 -55.04 48.672 250.72 250.72 0 0 1 -67.04 30.4 272.768 272.768 0 0 1 -76.128 10.528 261.696 261.696 0 0 1 -73.376 -10.4A253.472 253.472 0 0 1 32 400.64a184.384 184.384 0 0 0 136.064 -38.08 90.944 90.944 0 0 1 -72.736 -38.08 92.096 92.096 0 0 1 -13.024 -25.6c2.912 0.448 5.792 0.832 8.64 1.12a89.504 89.504 0 0 0 32.704 -2.848 89.856 89.856 0 0 1 -29.632 -11.584 94.144 94.144 0 0 1 -23.296 -20.256 90.848 90.848 0 0 1 -20.8 -58.304v-1.056c12.864 7.264 26.784 11.136 41.792 11.584a94.176 94.176 0 0 1 -29.952 -33.28 94.56 94.56 0 0 1 -8.096 -20.768 94.24 94.24 0 0 1 0.224 -46.496c2.016 -7.776 5.152 -15.168 9.408 -22.176 11.648 14.432 24.64 27.392 38.912 38.816a262.88 262.88 0 0 0 96.256 48.8 254.88 254.88 0 0 0 54.24 8.416 68.8 68.8 0 0 1 -1.856 -10.4 104.48 104.48 0 0 1 -0.544 -10.592c0 -12.704 2.4 -24.64 7.232 -35.776a92.544 92.544 0 0 1 48.896 -48.896 89.28 89.28 0 0 1 35.744 -7.2 91.072 91.072 0 0 1 67.168 29.088 182.4 182.4 0 0 0 58.176 -22.336 90.08 90.08 0 0 1 -40.256 50.752A182.528 182.528 0 0 0 480 121.12z\"]\n};\nvar vsTypeHierarchySub = {\n prefix: \"vs\",\n iconName: \"type-hierarchy-sub\",\n icon: [512, 512, [], \"f000\", \"M432 352h-55.328L270.016 192H304l16 -16v-128L304 32h-128l-16 16v128l16 16h33.984l-106.656 160H48l-16 16v96l16 16h96l16 -16v-96l-16 -16h-2.176L240 204.8l98.176 147.2H336l-16 16v96l16 16h96l16 -16v-96l-16 -16zM192 160V64h96v96H192zm-64 224v64H64v-64h64zm288 64h-64v-64h64v64z\"]\n};\nvar vsTypeHierarchySuper = {\n prefix: \"vs\",\n iconName: \"type-hierarchy-super\",\n icon: [512, 512, [], \"f000\", \"M432 32h-96l-16 16v96l16 16h2.176L240 307.2 141.824 160H144l16 -16v-96L144 32h-96l-16 16v96l16 16h55.328l106.656 160H176l-16 16v128l16 16h128l16 -16v-128l-16 -16H270.016l106.656 -160H432l16 -16v-96l-16 -16zM64 128V64h64v64H64zm224 224v96H192v-96h96zm128 -224h-64V64h64v64z\"]\n};\nvar vsTypeHierarchy = {\n prefix: \"vs\",\n iconName: \"type-hierarchy\",\n icon: [512, 512, [], \"f000\", \"M432 384h-57.376L320 329.376V208L304 192H256V128h16l16 -16v-64L272 32h-64l-16 16v64l16 16H224v64H176l-16 16v121.376L105.376 384H48l-16 16v64l16 16h64l16 -16v-57.376L182.624 352h114.752L352 406.624V464l16 16h64l16 -16v-64l-16 -16zM224 64h32v32H224V64zM192 224h96v96H192V224zm-96 224H64v-32h32v32zm320 0h-32v-32h32v32z\"]\n};\nvar vsUnfold = {\n prefix: \"vs\",\n iconName: \"unfold\",\n icon: [512, 512, [], \"f000\", \"M240.96 208.32v-128l-32 32 -22.72 -22.72L244.8 32h22.72l58.88 58.56 -22.72 22.4 -32 -32v127.36h-30.72zm0 95.36v128l-32 -32 -22.72 22.72L244.8 480h22.72l58.88 -58.56 -22.72 -22.4 -32 32V303.68h-30.72zM439.36 128L448 160.64l-117.76 93.76L448 351.36 439.36 384h-134.4v-32h96L305.6 274.24H209.28L110.4 352h98.56v32H72.64L64 351.36l117.76 -93.44L64 160.64 72.64 128h136.32v32H110.4l96 77.44h96.32L400.96 160h-96V128h134.4z\"]\n};\nvar vsUngroupByRefType = {\n prefix: \"vs\",\n iconName: \"ungroup-by-ref-type\",\n icon: [512, 512, [], \"f000\", \"M92.8 32L160 99.2l-25.6 22.4L96 83.2V224H64V80L25.6 121.6l-22.4 -22.4L70.4 32h22.4zM96 428.8V288H64v140.8L25.6 390.4l-22.4 22.4L70.4 480h22.4L160 412.8l-22.4 -22.4L96 428.8zM272 224h-64L192 208v-64l16 -16h64l16 16v64l-16 16zM224 192h32V160H224v32zm240 32h-96l-16 -16v-96l16 -16h96l16 16v96l-16 16zM384 192h64V128h-64v64zm-112 192h-64l-16 -16v-64l16 -16h64l16 16v64l-16 16zM224 352h32v-32H224v32zm240 64h-96l-16 -16v-96l16 -16h96l16 16v96l-16 16zM384 384h64v-64h-64v64zm-32 -64H288v32h64v-32zm0 -160H288v32h64V160z\"]\n};\nvar vsUnlock = {\n prefix: \"vs\",\n iconName: \"unlock\",\n icon: [512, 512, [], \"f000\", \"M160 224V160a96 96 0 0 1 186.56 -32h33.408A128.064 128.064 0 0 0 128 160v64H96L64 256v192l32 32h320l32 -32V256l-32 -32H160zm192 32h64v192H96V256h256z\"]\n};\nvar vsUnmute = {\n prefix: \"vs\",\n iconName: \"unmute\",\n icon: [512, 512, [], \"f000\", \"M48 154.56h89.28L260.8 32l27.2 11.2v416l-27.2 10.56 -123.52 -123.2H48l-16 -16v-160l16 -16zM155.2 320L256 420.48V81.92L155.2 181.76l-11.2 4.8H64v128h80l11.2 5.44zM480 250.56a223.04 223.04 0 0 1 -50.496 141.696l-22.784 -22.72A191.2 191.2 0 0 0 448 250.56c0 -44.8 -15.36 -86.048 -41.088 -118.72l22.784 -22.72A223.072 223.072 0 0 1 480 250.56zm-64 0a159.296 159.296 0 0 1 -32.064 96.128l-22.912 -22.912A127.424 127.424 0 0 0 384 250.56a127.36 127.36 0 0 0 -22.816 -72.96l22.912 -22.912c20.032 26.72 31.904 59.904 31.904 95.872zm-64 0c0 18.368 -5.12 35.52 -14.08 50.112l-23.648 -23.616a63.776 63.776 0 0 0 0.16 -52.704l23.648 -23.648c8.832 14.528 13.92 31.616 13.92 49.856z\"]\n};\nvar vsUnverified = {\n prefix: \"vs\",\n iconName: \"unverified\",\n icon: [512, 512, [], \"f000\", \"M245.44 471.04h22.72L323.2 416h76.8l16 -16v-77.44l55.68 -55.04v-22.72l-54.72 -55.04V111.68l-16 -15.68H323.2L268.16 41.28h-22.72L192 96H112.96L96 112v77.76L41.92 244.8v22.72L96 322.56v77.44l16.96 16H192l53.44 55.04zM197.12 384H128V315.84l-3.84 -11.2L75.84 256l47.36 -48.32 4.8 -11.2V128h69.12l11.52 -4.48L256 75.2l49.28 48.32 11.2 4.48H384v68.48l5.44 11.2L438.08 256l-49.6 48.64 -4.48 11.2V384H316.48l-12.16 4.8L256 437.12l-47.36 -48.64 -11.52 -4.48zm46.176 -187.488a30.784 30.784 0 0 0 -4.096 9.312c-0.96 3.488 -1.6 6.88 -1.984 10.144l-0.16 1.376h-28.64l0.096 -1.632c0.576 -10.432 2.848 -19.68 6.784 -27.648 1.664 -3.456 3.744 -6.848 6.176 -10.176 2.592 -3.392 5.76 -6.4 9.408 -8.96 3.808 -2.688 8.16 -4.8 13.088 -6.4A54.72 54.72 0 0 1 261.28 160c8.96 0 16.736 1.472 23.232 4.48 6.4 2.848 11.712 6.72 15.808 11.616 4.064 4.864 7.04 10.432 8.928 16.64 1.856 6.208 2.784 12.608 2.784 19.168 0 6.112 -1.024 11.872 -3.136 17.28 -2.048 5.248 -4.576 10.24 -7.616 14.912 -3.008 4.576 -6.304 8.96 -9.92 13.12 -3.52 4.128 -6.752 8.064 -9.728 11.904a79.04 79.04 0 0 0 -7.36 10.88 20.896 20.896 0 0 0 -2.816 10.176v15.36h-28.416v-17.248c0 -5.376 0.992 -10.336 3.008 -14.848a68.8 68.8 0 0 1 7.68 -12.832c3.072 -4.064 6.4 -8 9.856 -11.776a151.68 151.68 0 0 0 9.568 -11.392c2.976 -3.84 5.44 -7.872 7.296 -12.064a31.488 31.488 0 0 0 2.88 -13.472 33.28 33.28 0 0 0 -1.504 -10.176v-0.032a20.416 20.416 0 0 0 -4.16 -7.776 17.856 17.856 0 0 0 -6.912 -5.056H270.72a22.048 22.048 0 0 0 -9.408 -1.888 20.576 20.576 0 0 0 -10.848 2.656 23.744 23.744 0 0 0 -7.136 6.88zM272 352h-28.416v-28.416H272V352z\"]\n};\nvar vsVariableGroup = {\n prefix: \"vs\",\n iconName: \"variable-group\",\n icon: [512, 512, [], \"f000\", \"M172.384 368.736a12.864 12.864 0 0 1 18.976 -11.744c1.856 0.992 3.52 2.08 5.024 3.264 1.504 1.152 2.816 2.24 4 3.232a5.664 5.664 0 0 0 3.744 1.504c1.664 0 3.84 -1.28 6.496 -3.744 2.656 -2.496 5.6 -5.824 8.736 -10.016 3.2 -4.16 6.432 -8.576 9.76 -13.248 3.328 -4.672 6.4 -9.408 9.28 -14.24l7.232 -12.48c1.984 -3.52 3.424 -6.368 4.256 -8.512a490.56 490.56 0 0 0 -4.256 -16.768 492.288 492.288 0 0 1 -4.256 -16.736 119.04 119.04 0 0 0 -4.256 -13.504 33.28 33.28 0 0 0 -5.984 -10.016 20.992 20.992 0 0 0 -8.512 -5.984 43.968 43.968 0 0 0 -12 -2.24 52.096 52.096 0 0 0 -10.496 0.992v-6.24L246.08 224a75.04 75.04 0 0 1 14.752 23.488c1.664 4.16 3.104 8.416 4.256 12.768 1.184 4.32 2.432 9.056 3.744 14.24 2.496 -3.68 5.6 -8.32 9.28 -14.016a143.68 143.68 0 0 1 12.736 -16.736c4.8 -5.504 9.92 -10.08 15.232 -13.76A32.64 32.64 0 0 1 322.848 224c4.16 0 7.904 1.088 11.232 3.232 3.36 2.176 5.024 5.6 5.024 10.24 0 9.024 -4.512 13.536 -13.504 13.536a19.456 19.456 0 0 1 -9.28 -2.24 19.456 19.456 0 0 0 -9.216 -2.272c-3.2 0 -6.496 1.6 -10.016 4.736a73.6 73.6 0 0 0 -9.984 11.264 304 304 0 0 0 -15.52 23.488l14.272 59.264a49.92 49.92 0 0 0 2.976 11.008 21.408 21.408 0 0 0 3.008 5.472 5.888 5.888 0 0 0 4 2.528 11.84 11.84 0 0 0 6.752 -2.752 68.48 68.48 0 0 0 13.76 -15.04c1.664 -2.464 2.976 -4.8 4 -6.976l5.984 3.008a64.8 64.8 0 0 1 -7.008 11.744 120.8 120.8 0 0 1 -11.232 13.504 108.16 108.16 0 0 1 -12.992 11.52c-4.512 3.328 -8.608 4.896 -12.256 4.736a12.704 12.704 0 0 1 -8.992 -3.264 47.712 47.712 0 0 1 -6.528 -7.488 51.168 51.168 0 0 1 -4.224 -11.52 264.416 264.416 0 0 1 -3.776 -16.224 1093.12 1093.12 0 0 1 -3.232 -17.024 70.784 70.784 0 0 0 -3.52 -13.248l-6.496 12a143.648 143.648 0 0 1 -8.96 14.496c-3.52 5.024 -7.104 10.112 -10.784 15.264a78.72 78.72 0 0 1 -12 13.504c-4.32 3.84 -8.48 7.072 -12.48 9.76A21.12 21.12 0 0 1 189.12 384a17.248 17.248 0 0 1 -11.52 -4.256 14.528 14.528 0 0 1 -5.216 -11.008zm195.52 15.264c8.96 -11.52 15.872 -23.936 20.736 -37.248a123.84 123.84 0 0 0 7.232 -42.24c0 -15.04 -2.4 -29.184 -7.232 -42.528A146.24 146.24 0 0 0 367.84 224h23.488a120.64 120.64 0 0 1 29.504 80.48c0 15.168 -2.336 29.344 -6.976 42.528 -4.672 13.152 -12.16 25.472 -22.528 36.992h-23.488zM120.64 384a107.936 107.936 0 0 1 -22.528 -36.768 127.04 127.04 0 0 1 -6.976 -42.752c0 -30.496 9.824 -57.312 29.504 -80.48h23.232a132.224 132.224 0 0 0 -20.48 37.76 134.56 134.56 0 0 0 -7.264 42.72A125.728 125.728 0 0 0 143.872 384H120.64zM496 32H16l-16 16v416l16 16h480l16 -16v-416l-16 -16zM480 448H32V160h448v288zm0 -320H32V64h448v64z\"]\n};\nvar vsVerified = {\n prefix: \"vs\",\n iconName: \"verified\",\n icon: [512, 512, [], \"f000\", \"M245.44 471.04h22.72L323.2 416h76.8l16 -16v-77.44l55.68 -55.04v-22.72l-54.72 -55.04V111.68l-16 -15.68H323.2L268.16 41.28h-22.72L192 96H112.96L96 112v77.76L41.92 244.8v22.72L96 322.56v77.44l16.96 16H192l53.44 55.04zM197.12 384H128V315.84l-3.84 -11.2L75.84 256l47.36 -48.32 4.8 -11.2V128h69.12l11.52 -4.48L256 75.2l49.28 48.32 11.2 4.48H384v68.48l5.44 11.2L438.08 256l-49.6 48.64 -4.48 11.2V384H316.48l-12.16 4.8L256 437.12l-47.36 -48.64 -11.52 -4.48zm18.24 -48.64h22.72l120.64 -120.64L336 192 226.88 301.44 182.72 257.28 160 280l55.36 55.36z\"]\n};\nvar vsVersions = {\n prefix: \"vs\",\n iconName: \"versions\",\n icon: [512, 512, [], \"f000\", \"M256 96L224 128v256l32 32h192l32 -32V128l-32 -32H256zm192 288H256V128h192v256zM160 288V160h32V128H144l-16 16v224l16 16H192v-32H160V288zM64 256V192h32V160H48l-16 16v160l16 16H96v-32H64V256z\"]\n};\nvar vsVmActive = {\n prefix: \"vs\",\n iconName: \"vm-active\",\n icon: [512, 512, [], \"f000\", \"M48 64h416l16 16v176.096a160.192 160.192 0 0 0 -32 -18.656V96H64v288h160a160 160 0 0 0 32 96H128v-32h96v-32H48l-16 -16v-320l16 -16zm264.896 213.568a128 128 0 1 1 142.208 212.864 128 128 0 0 1 -142.208 -212.864zm68.16 159.68l76.384 -101.824 -25.6 -19.2 -66.464 88.608 -41.632 -33.312 -20 24.96 54.528 43.648 22.816 -2.88z\"]\n};\nvar vsVmConnect = {\n prefix: \"vs\",\n iconName: \"vm-connect\",\n icon: [512, 512, [], \"f000\", \"M48 64h416l16 16v176.096a160.192 160.192 0 0 0 -32 -18.656V96H64v288h160a160 160 0 0 0 32 96H128v-32h96v-32H48l-16 -16v-320l16 -16zM384 256a128 128 0 1 0 0 256 128 128 0 0 0 0 -256zm0 224a96 96 0 1 1 0 -192.032A96 96 0 0 1 384 480zm4.256 -114.08l45.952 45.952 13.792 -13.792 -32.128 -32.16L448 333.792l-13.792 -13.76 -45.952 45.888zm-36.128 34.144L320 367.936l13.792 -13.792 45.952 45.92 -45.952 45.952 -13.792 -13.792 32.128 -32.16z\"]\n};\nvar vsVmOutline = {\n prefix: \"vs\",\n iconName: \"vm-outline\",\n icon: [512, 512, [], \"f000\", \"M48 64h416l16 16v176.096a160.192 160.192 0 0 0 -32 -18.656V96H64v288h160a160 160 0 0 0 32 96H128v-32h96v-32H48l-16 -16v-320l16 -16zM384 256a128 128 0 1 0 0 256 128 128 0 0 0 0 -256zm0 224a96 96 0 1 1 0 -192.032A96 96 0 0 1 384 480z\"]\n};\nvar vsVmRunning = {\n prefix: \"vs\",\n iconName: \"vm-running\",\n icon: [512, 512, [], \"f000\", \"M48 64h416l16 16v176.096a160.192 160.192 0 0 0 -32 -18.656V96H64v288h160a160 160 0 0 0 32 96H128v-32h96v-32H48l-16 -16v-320l16 -16zM384 256c11.744 0 23.072 1.504 34.016 4.48 10.88 3.008 21.056 7.36 30.496 13.024 9.408 5.664 18.016 12.32 25.856 20 7.84 7.68 14.56 16.288 20.16 25.856a128.96 128.96 0 0 1 12.96 98.624c-2.976 10.944 -7.328 21.12 -12.992 30.528a140.224 140.224 0 0 1 -20 25.856c-7.68 7.84 -16.288 14.56 -25.856 20.16a128.928 128.928 0 0 1 -98.624 12.96 121.088 121.088 0 0 1 -30.528 -12.992 140.224 140.224 0 0 1 -25.856 -20 121.856 121.856 0 0 1 -20.16 -25.856 128.864 128.864 0 0 1 -12.96 -98.624c2.976 -10.944 7.328 -21.12 12.992 -30.528 5.664 -9.408 12.32 -18.016 20 -25.856 7.68 -7.84 16.288 -14.56 25.856 -20.16A128.896 128.896 0 0 1 384 256zm64 127.616L352 320v128l96 -64.384z\"]\n};\nvar vsVm = {\n prefix: \"vs\",\n iconName: \"vm\",\n icon: [512, 512, [], \"f000\", \"M464 64h-416l-16 16v320l16 16H224v32H128v32h256v-32H288v-32h176l16 -16v-320l-16 -16zM448 384H64V96h384v288z\"]\n};\nvar vsWand = {\n prefix: \"vs\",\n iconName: \"wand\",\n icon: [512, 512, [], \"f000\", \"M140.16 160h32V128h32V96h-32V64h-32v32h-32v32h32v32zm256 128h-32v32h-32v32h32v32h32v-32h32v-32h-32V288zM448 64V32h-32v32h-32v32h32v32h32V96h32V64h-32zm-94.304 78.144a47.68 47.68 0 0 0 -67.84 0l-239.68 239.68a47.68 47.68 0 0 0 0 67.84c18.88 18.88 49.28 18.88 67.84 0l239.68 -239.68c18.56 -18.56 18.56 -48.96 0 -67.84zm-262.4 284.8c-6.4 6.4 -16.32 6.4 -22.72 0 -6.4 -6.4 -6.4 -16.32 0 -22.72l206.72 -206.72 22.72 22.72 -206.72 206.72zm239.68 -239.68l-10.24 10.24 -22.72 -22.72 10.24 -10.24c6.4 -6.4 16.32 -6.4 22.72 0 6.08 6.4 6.08 16.64 0 22.72z\"]\n};\nvar vsWarning = {\n prefix: \"vs\",\n iconName: \"warning\",\n icon: [512, 512, [], \"f000\", \"M241.92 32h28.16l209.28 392.32 -14.08 23.68H46.08L32 424.32 241.92 32zM256 72.96L72.96 416H438.4L256 72.96zM276 384v-32h-40v32h40zm-40 -64V192h40v128h-40z\"]\n};\nvar vsWatch = {\n prefix: \"vs\",\n iconName: \"watch\",\n icon: [512, 512, [], \"f000\", \"M240 288h64V256H256V176H224v96l16 16zm-64 -170.592A159.936 159.936 0 0 0 96 256a159.936 159.936 0 0 0 80 138.592V464l16 16h128l16 -16v-69.408A159.936 159.936 0 0 0 416 256a159.936 159.936 0 0 0 -80 -138.592V48L320 32H192l-16 16v69.408zM384 256a128 128 0 1 1 -256 0 128 128 0 0 1 256 0z\"]\n};\nvar vsWhitespace = {\n prefix: \"vs\",\n iconName: \"whitespace\",\n icon: [512, 512, [], \"f000\", \"M384 64V32H208a112 112 0 0 0 0 224H256v160H224v32h160v-32h-32V64h32zM256 224H208a80 80 0 1 1 0 -160H256v160zm64 192H288V64h32v352z\"]\n};\nvar vsWholeWord = {\n prefix: \"vs\",\n iconName: \"whole-word\",\n icon: [512, 512, [], \"f000\", \"M32 64h448v32H32V64zm416 64h-32v256h32V128zm-87.296 140.384a75.296 75.296 0 0 0 -11.52 -25.152 55.872 55.872 0 0 0 -19.488 -16.96 58.624 58.624 0 0 0 -27.712 -6.176c-6.336 0 -12.16 0.768 -17.504 2.336a56.32 56.32 0 0 0 -14.496 6.56 55.168 55.168 0 0 0 -11.68 10.176l-5.728 8.256V146.496H224V384h28.576v-18.4l4.032 5.6c2.784 3.264 6.048 6.08 9.728 8.608 3.744 2.496 7.968 4.48 12.736 5.952 4.768 1.472 10.048 2.176 15.936 2.176 11.296 0 21.312 -2.272 29.984 -6.784 8.704 -4.576 15.968 -10.816 21.824 -18.752 5.856 -8 10.272 -17.376 13.248 -28.128 2.976 -10.816 4.48 -22.496 4.48 -35.104a120.192 120.192 0 0 0 -3.84 -30.784zM313.376 248.96c4.832 2.272 9.024 5.632 12.48 10.048 3.488 4.48 6.208 10.016 8.16 16.544 1.632 5.568 2.624 11.872 2.848 18.784l-0.224 4c0 10.464 -1.056 19.84 -3.2 27.808a60.352 60.352 0 0 1 -8.896 19.648c-3.744 5.184 -8.32 9.12 -13.472 11.712 -10.304 5.184 -24.32 5.312 -34.208 0.48a40.448 40.448 0 0 1 -12.576 -9.472 40.736 40.736 0 0 1 -6.976 -11.744s-5.728 -14.304 -5.728 -30.304c0 -16 5.728 -32.064 5.728 -32.064 1.984 -5.664 4.352 -10.176 7.168 -13.76 3.648 -4.576 8.192 -8.288 13.568 -11.04 5.376 -2.752 11.68 -4.128 18.784 -4.128 6.08 0 11.648 1.184 16.544 3.488zM480 416H32v32h448v-32zM90.016 320l-23.296 64.992H32l0.8 -2.304 78.112 -226.752h30.112l79.52 229.056H185.92L161.024 320H90.016zm35.872 -114.496h-0.704l-28.96 88.096h58.912l-29.248 -88.096z\"]\n};\nvar vsWindow = {\n prefix: \"vs\",\n iconName: \"window\",\n icon: [512, 512, [], \"f000\", \"M464 64h-416l-16 16v352l16 16h416l16 -16v-352l-16 -16zM448 416H64V192h384v224zm0 -256H64V96h384v64z\"]\n};\nvar vsWordWrap = {\n prefix: \"vs\",\n iconName: \"word-wrap\",\n icon: [512, 512, [], \"f000\", \"M123.776 110.368a38.72 38.72 0 0 0 -15.136 -10.528c-8.768 -3.552 -19.936 -4.8 -33.76 -2.432a112 112 0 0 0 -22.72 6.656c-2.624 1.12 -5.12 2.464 -7.52 4l-1.376 0.96v33.792l5.376 -4.448c4.8 -3.968 10.432 -7.2 16.864 -9.696 6.272 -2.368 12.8 -3.616 19.328 -3.616 6.016 0 10.56 1.632 13.792 5.024 2.784 3.04 4.384 7.936 4.704 14.592l-30.784 4.608c-7.008 0.96 -13.12 2.752 -18.24 5.312a39.84 39.84 0 0 0 -12.736 9.952c-3.296 4 -5.792 8.64 -7.328 13.632 -3.104 10.56 -2.976 21.76 0.352 32.256a35.072 35.072 0 0 0 20.416 21.44c4.96 2.016 10.496 2.976 16.896 2.976a40 40 0 0 0 31.296 -14.112v11.04h32.224V148.8c0 -8.16 -0.96 -15.488 -2.848 -21.792a45.536 45.536 0 0 0 -8.8 -16.64zm-20.352 60.672v7.552c0 3.808 -0.576 7.392 -1.76 10.912a23.84 23.84 0 0 1 -12.064 14.304 22.208 22.208 0 0 1 -16.384 0.864 14.528 14.528 0 0 1 -4.992 -3.008 12.448 12.448 0 0 1 -3.008 -4.448 15.168 15.168 0 0 1 -1.12 -5.952c0 -2.464 0.32 -4.704 0.768 -6.784a10.56 10.56 0 0 1 2.496 -4.512 13.952 13.952 0 0 1 5.152 -3.488 41.6 41.6 0 0 1 9.76 -2.336l21.152 -3.104zm161.632 -34.144a72.096 72.096 0 0 0 -7.808 -20.992 43.328 43.328 0 0 0 -13.952 -14.688 37.28 37.28 0 0 0 -20.544 -5.536 36.352 36.352 0 0 0 -22.08 7.136 42.56 42.56 0 0 0 -8.448 8.512V32H162.88v199.168h29.376v-8.992c3.936 4.864 9.184 8.512 15.104 10.496 3.136 1.024 6.656 1.504 10.56 1.504 8.16 0 15.456 -1.92 21.664 -5.664 6.144 -3.68 11.36 -8.896 15.552 -15.552a73.28 73.28 0 0 0 9.376 -22.976 123.84 123.84 0 0 0 3.072 -28.352 118.848 118.848 0 0 0 -2.496 -24.736zm-27.52 24.256c0 7.424 -0.64 14.048 -1.92 19.616 -1.152 5.504 -2.88 10.08 -5.088 13.568a20.448 20.448 0 0 1 -7.456 7.584 18.624 18.624 0 0 1 -18.08 0.448 21.856 21.856 0 0 1 -6.72 -5.856 29.6 29.6 0 0 1 -4.544 -9.056A37.984 37.984 0 0 1 192 176v-16.544c0 -5.248 0.64 -10.048 1.92 -14.304 1.152 -4.224 2.784 -7.744 4.992 -10.752a21.376 21.376 0 0 1 7.296 -6.656 18.688 18.688 0 0 1 9.28 -2.272 17.728 17.728 0 0 1 15.872 8.928c2.016 3.168 3.456 6.848 4.576 11.328 0.992 4.576 1.6 9.792 1.6 15.424zM77.024 316.8a29.216 29.216 0 0 1 10.112 -7.648c6.976 -3.2 17.504 -3.36 24.512 -0.576 3.328 1.344 6.528 3.2 10.24 5.888l10.56 8.32V286.24l-3.104 -1.984a61.824 61.824 0 0 0 -28.96 -6.88c-9.856 0 -18.976 1.824 -27.072 5.376 -8 3.52 -14.944 8.64 -20.704 15.2 -5.76 6.72 -10.176 14.496 -12.896 22.944 -2.88 8.704 -4.384 18.24 -4.384 28.64 0 9.248 1.376 17.952 4.16 25.856 2.752 7.968 6.752 15.072 11.936 20.864 5.152 5.92 11.552 10.656 19.104 14.112 7.424 3.328 15.776 4.96 24.896 4.96 7.456 0 13.888 -0.896 19.616 -2.688 5.28 -1.6 10.304 -3.936 14.912 -6.944l2.496 -1.952v-28.448l-6.4 3.04a12.8 12.8 0 0 1 -2.432 0.832c-1.6 0.544 -3.168 1.12 -4.096 1.568 -1.152 0.736 -7.264 2.88 -7.264 2.88 -1.92 0.768 -4.48 1.376 -6.976 1.888a31.264 31.264 0 0 1 -19.168 -1.824 26.464 26.464 0 0 1 -9.792 -7.2 34.816 34.816 0 0 1 -6.56 -12.032 55.296 55.296 0 0 1 -2.432 -16.928c0 -6.72 0.896 -12.768 2.656 -17.92 1.728 -5.056 4.16 -9.408 7.04 -12.8zM448 192h-128V160h144l16 16v192l-16 16H252.128l66.24 66.272 -22.592 22.624 -92.48 -92.448v-22.624l92.48 -92.48L318.4 288l-64 64H448V192z\"]\n};\nvar vsWorkspaceTrusted = {\n prefix: \"vs\",\n iconName: \"workspace-trusted\",\n icon: [512, 512, [], \"f000\", \"M258.208 0c8.384 0 16.64 0.544 24.32 1.824a131.2 131.2 0 0 1 22.304 4.928c7.296 2.208 14.432 4.96 21.568 8.416 6.944 3.296 14.08 7.328 21.216 11.712 12.064 7.68 23.936 13.888 36.032 18.848a241.184 241.184 0 0 0 74.592 16.8c12.992 0.928 26.336 1.472 40.224 1.472v128c0 24.32 -3.104 47.36 -9.312 69.312a287.872 287.872 0 0 1 -25.248 62.176 329.984 329.984 0 0 1 -38.016 55.2 482.912 482.912 0 0 1 -47.744 49.024 562.24 562.24 0 0 1 -54.496 42.4c-19.008 13.184 -38.208 25.44 -57.408 36.576l-7.68 4.576 -7.68 -4.576a866.976 866.976 0 0 1 -57.792 -36.576 498.56 498.56 0 0 1 -54.496 -42.4 482.624 482.624 0 0 1 -47.712 -49.024 350.304 350.304 0 0 1 -38.208 -55.2 312.096 312.096 0 0 1 -25.248 -62.176A252.704 252.704 0 0 1 18.272 192V64c13.92 0 27.264 -0.544 40.256 -1.472a261.12 261.12 0 0 0 38.016 -5.472c12.256 -2.752 24.512 -6.4 36.576 -11.328A210.016 210.016 0 0 0 168.96 27.072C183.04 17.92 197.312 11.168 211.392 6.72A153.28 153.28 0 0 1 258.208 0zm208.064 95.456a306.112 306.112 0 0 1 -71.488 -12.064 254.72 254.72 0 0 1 -65.472 -30.176A136.416 136.416 0 0 0 295.36 37.12 124.32 124.32 0 0 0 258.368 31.808a127.68 127.68 0 0 0 -37.28 5.312 126.272 126.272 0 0 0 -33.856 16.096A253.632 253.632 0 0 1 121.6 83.52c-22.688 6.592 -46.432 10.624 -71.328 12.096v96.544c0 21.216 2.752 41.504 8.256 61.056a274.56 274.56 0 0 0 23.04 55.776 307.328 307.328 0 0 0 34.56 50.304c13.344 15.712 27.584 30.336 42.944 44.224 15.36 13.92 31.456 26.72 48.288 38.592 16.992 11.904 34.016 22.688 51.008 32.544a716.704 716.704 0 0 0 50.848 -32.544 492.448 492.448 0 0 0 48.448 -38.592c15.36 -13.888 29.632 -28.512 42.976 -44.224a307.072 307.072 0 0 0 34.56 -50.304 264.256 264.256 0 0 0 22.688 -55.776 218.048 218.048 0 0 0 8.384 -61.056V95.456zm-88.768 55.232l-14.08 -12.096 -12.992 1.12 -139.52 164.736 -47.52 -67.84 -12.8 -2.176 -14.816 10.592 -2.208 12.8 61.088 87.232 6.944 3.84 14.624 0.896 7.488 -3.264 154.72 -182.88 -0.928 -12.96z\"]\n};\nvar vsWorkspaceUnknown = {\n prefix: \"vs\",\n iconName: \"workspace-unknown\",\n icon: [512, 512, [], \"f000\", \"M258.144 0c8.416 0 16.64 0.544 24.32 1.824a131.2 131.2 0 0 1 22.304 4.928c7.328 2.208 14.464 4.96 21.6 8.416 6.944 3.296 14.08 7.328 21.184 11.712a230.4 230.4 0 0 0 36.032 18.848 241.088 241.088 0 0 0 74.624 16.8c12.96 0.928 26.304 1.472 40.224 1.472v128c0 24.32 -3.104 47.36 -9.344 69.312a287.872 287.872 0 0 1 -25.216 62.176 329.792 329.792 0 0 1 -38.048 55.2 482.624 482.624 0 0 1 -47.712 49.024 562.24 562.24 0 0 1 -54.496 42.4c-19.008 13.184 -38.208 25.44 -57.408 36.576l-7.68 4.576 -7.68 -4.576a866.816 866.816 0 0 1 -57.792 -36.576 498.528 498.528 0 0 1 -54.496 -42.4 482.56 482.56 0 0 1 -47.712 -49.024 350.336 350.336 0 0 1 -38.24 -55.2 312.096 312.096 0 0 1 -25.216 -62.176A252.704 252.704 0 0 1 18.24 192V64c13.888 0 27.232 -0.544 40.224 -1.472a261.12 261.12 0 0 0 38.048 -5.472c12.256 -2.752 24.48 -6.4 36.576 -11.328a210.016 210.016 0 0 0 35.84 -18.656C183.008 17.92 197.248 11.168 211.328 6.72A153.28 153.28 0 0 1 258.144 0zm208.096 95.456a306.144 306.144 0 0 1 -71.488 -12.064 254.72 254.72 0 0 1 -65.472 -30.176 136.448 136.448 0 0 0 -34.016 -16.096A124.32 124.32 0 0 0 258.336 31.808a127.68 127.68 0 0 0 -37.312 5.312 126.272 126.272 0 0 0 -33.824 16.096 253.664 253.664 0 0 1 -65.632 30.336c-22.688 6.592 -46.464 10.624 -71.328 12.096v96.544c0 21.216 2.752 41.504 8.224 61.056a274.56 274.56 0 0 0 23.04 55.776 307.328 307.328 0 0 0 34.56 50.304c13.344 15.712 27.616 30.336 42.976 44.224 15.36 13.92 31.456 26.72 48.288 38.592 16.992 11.904 33.984 22.688 51.008 32.544a716.8 716.8 0 0 0 50.816 -32.544 492.288 492.288 0 0 0 48.48 -38.592c15.36 -13.888 29.6 -28.512 42.976 -44.224a307.488 307.488 0 0 0 34.56 -50.304 264.608 264.608 0 0 0 22.656 -55.776 218.048 218.048 0 0 0 8.416 -61.056V95.456zM301.856 151.04c5.472 5.472 10.048 12.064 13.152 19.392 3.296 7.296 4.96 15.36 4.768 24.128a51.2 51.2 0 0 1 -3.648 20.48 71.68 71.68 0 0 1 -9.344 15.36 89.184 89.184 0 0 1 -11.328 12.256 144.64 144.64 0 0 0 -10.784 10.24 45.472 45.472 0 0 0 -7.68 10.24 22.4 22.4 0 0 0 -2.752 11.136v11.52l-4.192 4.416h-22.88l-4.576 -4.576V274.24c0 -7.68 1.28 -14.4 3.84 -20.288 2.4 -5.664 5.312 -10.976 8.96 -15.552a109.44 109.44 0 0 1 11.712 -12.224c3.84 -3.488 7.328 -6.784 10.624 -10.24 3.104 -3.296 5.824 -6.784 7.84 -10.432a22.624 22.624 0 0 0 2.752 -11.328 30.912 30.912 0 0 0 -2.368 -11.52 31.104 31.104 0 0 0 -6.4 -9.536 30.08 30.08 0 0 0 -42.24 0 28.16 28.16 0 0 0 -6.4 9.536 26.528 26.528 0 0 0 -2.4 11.52L224 198.72h-22.88l-4.192 -4.384c0 -8.416 1.472 -16.448 4.736 -23.936 3.296 -7.328 7.68 -13.92 13.184 -19.392 5.664 -5.664 12.256 -10.24 19.552 -13.344a60.256 60.256 0 0 1 48.096 0c7.328 3.296 13.888 7.68 19.392 13.344zM242.24 308.672l4.576 -4.576h22.848l4.576 4.576v22.848l-4.576 4.576h-22.848l-4.576 -4.576v-22.848z\"]\n};\nvar vsWorkspaceUntrusted = {\n prefix: \"vs\",\n iconName: \"workspace-untrusted\",\n icon: [512, 512, [], \"f000\", \"M258.144 0c8.416 0 16.64 0.544 24.32 1.824a131.2 131.2 0 0 1 22.304 4.928c7.328 2.208 14.464 4.96 21.6 8.416 6.944 3.296 14.08 7.328 21.184 11.712a230.4 230.4 0 0 0 36.032 18.848 241.088 241.088 0 0 0 74.624 16.8c12.96 0.928 26.304 1.472 40.224 1.472v128c0 24.32 -3.104 47.36 -9.344 69.312a287.872 287.872 0 0 1 -25.216 62.176 329.792 329.792 0 0 1 -38.048 55.2 482.624 482.624 0 0 1 -47.712 49.024 562.24 562.24 0 0 1 -54.496 42.4c-19.008 13.184 -38.208 25.44 -57.408 36.576l-7.68 4.576 -7.68 -4.576a866.816 866.816 0 0 1 -57.792 -36.576 498.528 498.528 0 0 1 -54.496 -42.4 482.56 482.56 0 0 1 -47.712 -49.024 350.336 350.336 0 0 1 -38.24 -55.2 312.096 312.096 0 0 1 -25.216 -62.176A252.704 252.704 0 0 1 18.24 192V64c13.888 0 27.232 -0.544 40.224 -1.472a261.12 261.12 0 0 0 38.048 -5.472c12.256 -2.752 24.48 -6.4 36.576 -11.328a210.016 210.016 0 0 0 35.84 -18.656C183.008 17.92 197.248 11.168 211.328 6.72A153.28 153.28 0 0 1 258.144 0zm208.096 95.456a306.144 306.144 0 0 1 -71.488 -12.064 254.72 254.72 0 0 1 -65.472 -30.176 136.448 136.448 0 0 0 -34.016 -16.096A124.32 124.32 0 0 0 258.336 31.808a127.68 127.68 0 0 0 -37.312 5.312 126.272 126.272 0 0 0 -33.824 16.096 253.664 253.664 0 0 1 -65.632 30.336c-22.688 6.592 -46.464 10.624 -71.328 12.096v96.544c0 21.216 2.752 41.504 8.224 61.056a274.56 274.56 0 0 0 23.04 55.776 307.328 307.328 0 0 0 34.56 50.304c13.344 15.712 27.616 30.336 42.976 44.224 15.36 13.92 31.456 26.72 48.288 38.592 16.992 11.904 33.984 22.688 51.008 32.544a716.8 716.8 0 0 0 50.816 -32.544 492.288 492.288 0 0 0 48.48 -38.592c15.36 -13.888 29.6 -28.512 42.976 -44.224a307.488 307.488 0 0 0 34.56 -50.304 264.608 264.608 0 0 0 22.656 -55.776 218.048 218.048 0 0 0 8.416 -61.056V95.456zm-121.056 78.816l-12.8 -12.992h-6.592L262.4 224.736 198.912 161.28h-6.4l-12.992 12.992v6.4l63.456 63.456L179.52 307.52v6.592l12.992 12.8h6.4l63.456 -63.456 63.424 63.456h6.592l12.8 -12.8V307.52L281.728 244.16l63.456 -63.456v-6.4z\"]\n};\nvar vsZoomIn = {\n prefix: \"vs\",\n iconName: \"zoom-in\",\n icon: [512, 512, [], \"f000\", \"M384.864 196.768a176.64 176.64 0 0 1 -40.64 125.056l136.32 136.32 -22.4 22.72 -136.32 -136.64a176.64 176.64 0 1 1 63.04 -147.456zm-174.4 156.416a144.32 144.32 0 0 0 101.76 -42.24l-1.28 0.64a144.32 144.32 0 0 0 43.52 -102.4 144 144 0 1 0 -144 144zm78.08 -128v-32h-64v-64h-32v64h-64v32h64v64h32v-64h64z\"]\n};\nvar vsZoomOut = {\n prefix: \"vs\",\n iconName: \"zoom-out\",\n icon: [512, 512, [], \"f000\", \"M384.864 196.768a176.64 176.64 0 0 1 -40.64 125.056l136.32 136.32 -22.4 22.72 -136.32 -136.64a176.64 176.64 0 1 1 63.04 -147.456zm-174.4 156.416a144.32 144.32 0 0 0 101.76 -42.24l-1.28 0.64a144.32 144.32 0 0 0 43.52 -102.4 144 144 0 1 0 -144 144zm-81.28 -159.36h160v32h-160v-32z\"]\n};\nvar dhArrowToBottom = {\n prefix: \"dh\",\n iconName: \"arrow-to-bottom\",\n icon: [512, 512, [], \"f000\", \"M99.2 224l160 160h22.4l160 -160 -22.4 -22.4L288 332.8V64H256v268.8L124.8 201.6l-25.6 22.4zM96 416h352v32H96z\"]\n};\nvar dhArrowToTop = {\n prefix: \"dh\",\n iconName: \"arrow-to-top\",\n icon: [512, 512, [], \"f000\", \"M444.8 288l-160 -160h-22.4l-160 160 22.4 22.4L256 179.2V448h32V179.2l131.2 131.2 25.6 -22.4zm3.2 -192H96V64h352v32z\"]\n};\nvar dhCheckSquare = {\n prefix: \"dh\",\n iconName: \"check-square\",\n icon: [512, 512, [], \"f000\", \"M425.6 64H86.4l-22.4 22.4v342.4l22.4 19.2h342.4l22.4 -22.4V86.4l-25.6 -22.4zm-188.8 284.8h-22.4L144 278.4l22.4 -22.4 60.8 60.8 134.4 -134.4 22.4 22.4 -147.2 144z\"]\n};\nvar dhChevronDownSquare = {\n prefix: \"dh\",\n iconName: \"chevron-down-square\",\n icon: [512, 512, [], \"f000\", \"M425.6 64H86.4l-22.4 22.4v342.4l22.4 19.2h342.4l22.4 -22.4V86.4l-25.6 -22.4zm-160 275.2h-19.2l-128 -131.2 19.2 -19.2L256 310.4 377.6 192l19.2 19.2 -131.2 128z\"]\n};\nvar dhCircleLargeOutlineNotch = {\n prefix: \"dh\",\n iconName: \"circle-large-outline-notch\",\n icon: [512, 512, [], \"f000\", \"M470.4 195.2c-9.6 -38.4 -28.8 -70.4 -57.6 -99.2 -25.6 -25.6 -57.6 -44.8 -92.8 -57.6v35.2c12.8 3.2 22.4 9.6 32 16l38.4 28.8c12.8 12.8 22.4 25.6 28.8 38.4 9.6 12.8 16 28.8 19.2 44.8 6.4 19.2 9.6 35.2 9.6 54.4 0 16 -3.2 35.2 -6.4 51.2s-9.6 32 -19.2 44.8c-16 28.8 -41.6 51.2 -70.4 70.4 -12.8 9.6 -28.8 16 -44.8 19.2 -16 3.2 -32 6.4 -51.2 6.4 -16 0 -35.2 -3.2 -51.2 -6.4s-32 -9.6 -44.8 -19.2l-38.4 -28.8c-25.6 -25.6 -41.6 -54.4 -51.2 -86.4 -3.2 -16 -6.4 -32 -6.4 -51.2 0 -16 3.2 -35.2 6.4 -51.2s9.6 -32 19.2 -44.8c16 -28.8 41.6 -54.4 70.4 -70.4 9.6 -6.4 22.4 -9.6 32 -16v-32c-16 6.4 -35.2 12.8 -48 22.4 -35.2 19.2 -60.8 44.8 -80 80 -12.8 16 -19.2 35.2 -25.6 51.2C35.2 214.4 32 236.8 32 256c0 19.2 3.2 41.6 6.4 60.8 6.4 16 12.8 35.2 25.6 51.2 9.6 16 22.4 32 35.2 44.8 12.8 16 28.8 25.6 44.8 35.2 16 9.6 35.2 16 54.4 22.4 16 6.4 38.4 9.6 57.6 9.6 19.2 0 41.6 -3.2 60.8 -6.4 19.2 -6.4 35.2 -12.8 54.4 -22.4 32 -19.2 60.8 -48 80 -80 9.6 -16 16 -35.2 22.4 -54.4 3.2 -19.2 6.4 -41.6 6.4 -60.8s-3.2 -41.6 -9.6 -60.8z\"]\n};\nvar dhClock = {\n prefix: \"dh\",\n iconName: \"clock\",\n icon: [512, 512, [], \"f000\", \"M470.4 195.2c-9.6 -38.4 -28.8 -70.4 -57.6 -99.2 -25.6 -25.6 -60.8 -44.8 -96 -54.4C297.6 35.2 275.2 32 256 32c-19.2 0 -41.6 3.2 -60.8 9.6 -16 3.2 -35.2 9.6 -51.2 22.4 -35.2 19.2 -60.8 44.8 -80 80 -12.8 16 -19.2 35.2 -25.6 51.2C35.2 214.4 32 236.8 32 256c0 19.2 3.2 41.6 6.4 60.8 6.4 16 12.8 35.2 25.6 51.2 9.6 16 22.4 32 35.2 44.8 12.8 16 28.8 25.6 44.8 35.2 16 9.6 35.2 16 54.4 22.4 16 6.4 38.4 9.6 57.6 9.6 19.2 0 41.6 -3.2 60.8 -6.4 19.2 -6.4 35.2 -12.8 54.4 -22.4 32 -19.2 60.8 -48 80 -80 9.6 -16 16 -35.2 22.4 -54.4 3.2 -19.2 6.4 -41.6 6.4 -60.8s-3.2 -41.6 -9.6 -60.8zm-115.2 121.6l-115.2 -64V89.6h32v147.2L371.2 288l-16 28.8z\"]\n};\nvar dhExclamation = {\n prefix: \"dh\",\n iconName: \"exclamation\",\n icon: [512, 512, [], \"f000\", \"M275.2 384v-32H236.8v32h38.4zm-38.4 -64V128h38.4v192H236.8z\"]\n};\nvar dhEyeSlash = {\n prefix: \"dh\",\n iconName: \"eye-slash\",\n icon: [512, 512, [], \"f000\", \"M480 256c0 -32 -99.2 -160 -224 -160 -32 0 -64 9.6 -92.8 22.4L70.4 25.6 25.6 70.4 435.2 480l44.8 -44.8 -76.8 -76.8C451.2 320 480 272 480 256zM256 131.2c96 0 176 92.8 188.8 124.8 -6.4 16 -32 48 -67.2 76.8L316.8 272c3.2 -6.4 3.2 -9.6 3.2 -16 0 -35.2 -28.8 -64 -64 -64 -6.4 0 -9.6 0 -16 3.2L192 147.2c19.2 -9.6 41.6 -16 64 -16zm0 249.6C160 380.8 80 288 67.2 256c6.4 -9.6 19.2 -32 41.6 -54.4l-25.6 -25.6C51.2 208 32 243.2 32 256c0 32 99.2 160 224 160 19.2 0 38.4 -3.2 57.6 -9.6l-28.8 -28.8c-9.6 3.2 -19.2 3.2 -28.8 3.2z\"]\n};\nvar dhEye = {\n prefix: \"dh\",\n iconName: \"eye\",\n icon: [512, 512, [], \"f000\", \"M256 96C131.2 96 32 224 32 256s99.2 160 224 160 224 -128 224 -160 -99.2 -160 -224 -160zm0 284.8C160 380.8 80 288 67.2 256 80 227.2 160 131.2 256 131.2S432 224 444.8 256c-12.8 28.8 -92.8 124.8 -188.8 124.8zM256 192c-35.2 0 -64 28.8 -64 64s28.8 64 64 64 64 -28.8 64 -64 -28.8 -64 -64 -64zm0 92.8c-16 0 -28.8 -12.8 -28.8 -28.8s12.8 -28.8 28.8 -28.8 28.8 12.8 28.8 28.8 -12.8 28.8 -28.8 28.8z\"]\n};\nvar dhFileCertificate = {\n prefix: \"dh\",\n iconName: \"file-certificate\",\n icon: [512, 512, [], \"f000\", \"M128 448V64h160v128h128v32h32V160l-9.6 -22.4 -96 -96L320 32H128L96 64v384l32 32h96v-32H128zm192 -384l96 96h-96V64zm60.8 224l19.2 19.2 9.6 9.6H448V352l9.6 9.6 19.2 19.2 -19.2 19.2 -9.6 9.6V448h-38.4l-9.6 9.6 -19.2 19.2 -16 -16 -9.6 -9.6H313.6v-38.4l-9.6 -9.6 -16 -22.4 19.2 -19.2 6.4 -9.6V313.6H352l9.6 -9.6 19.2 -16m6.4 -38.4h-12.8l-32 32H294.4l-12.8 9.6v48l-32 35.2v12.8l32 35.2v48l9.6 9.6h48l32 35.2h12.8l35.2 -35.2h48l9.6 -9.6v-48l35.2 -35.2v-12.8l-32 -35.2V291.2l-9.6 -9.6h-48l-35.2 -32z\"]\n};\nvar dhFileCsv = {\n prefix: \"dh\",\n iconName: \"file-csv\",\n icon: [512, 512, [], \"f000\", \"M444.8 140.8l-105.6 -105.6 -12.8 -3.2H80l-16 16V224h32V64h192v112l16 16H416v32h32V153.6l-3.2 -12.8zM320 160V64l96 96h-96zM80 256l-16 16v192l16 16h352l16 -16v-192l-16 -16h-352zM416 416v32H96V288h320v128zm-217.6 -3.2c-6.4 3.2 -16 3.2 -25.6 3.2 -16 0 -25.6 -3.2 -35.2 -12.8 -9.6 -6.4 -12.8 -19.2 -12.8 -32 0 -16 3.2 -28.8 12.8 -38.4 9.6 -9.6 22.4 -12.8 38.4 -12.8 9.6 0 16 0 22.4 3.2v19.2c-6.4 -3.2 -12.8 -6.4 -22.4 -6.4 -9.6 0 -16 3.2 -22.4 9.6 -6.4 6.4 -9.6 12.8 -9.6 22.4 0 9.6 3.2 16 6.4 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16 -3.2 22.4 -6.4v19.2zm19.2 0v-22.4c3.2 3.2 9.6 6.4 12.8 6.4 3.2 3.2 9.6 3.2 12.8 3.2h6.4c3.2 0 3.2 0 6.4 -3.2l3.2 -3.2v-3.2c0 -3.2 0 -3.2 -3.2 -6.4 3.2 0 0 0 0 -3.2 -3.2 0 -3.2 -3.2 -6.4 -3.2s-6.4 -3.2 -9.6 -3.2c-6.4 -3.2 -12.8 -6.4 -16 -12.8 -3.2 -3.2 -6.4 -9.6 -6.4 -16s0 -9.6 3.2 -12.8c3.2 -3.2 3.2 -6.4 9.6 -9.6 3.2 0 6.4 -3.2 12.8 -3.2h25.6c3.2 0 6.4 0 9.6 3.2v19.2s-3.2 -3.2 -6.4 -3.2 -3.2 0 -6.4 -3.2h-19.2c-3.2 0 -3.2 0 -6.4 3.2l-3.2 3.2v6.4l3.2 3.2s3.2 3.2 6.4 3.2 3.2 3.2 6.4 3.2c3.2 3.2 6.4 3.2 9.6 6.4 3.2 3.2 6.4 3.2 6.4 6.4 3.2 3.2 3.2 6.4 6.4 6.4 0 3.2 3.2 6.4 3.2 9.6 0 6.4 0 9.6 -3.2 12.8 -3.2 3.2 -3.2 6.4 -9.6 9.6 3.2 3.2 0 6.4 -3.2 6.4h-32c-3.2 0 -6.4 -3.2 -12.8 -3.2zm169.6 -92.8l-32 96h-25.6l-32 -96h22.4l19.2 67.2c0 3.2 3.2 6.4 3.2 9.6 0 -3.2 0 -6.4 3.2 -9.6l19.2 -67.2h22.4z\"]\n};\nvar dhFileDownload = {\n prefix: \"dh\",\n iconName: \"file-download\",\n icon: [512, 512, [], \"f000\", \"M438.4 137.6l-96 -96L320 32H128L96 64v384l32 32h288l32 -32V160l-9.6 -22.4zM416 448H128V64h160v128h128v256zm-96 -288V64l96 96h-96zm-134.4 182.4l76.8 76.8h22.4l76.8 -76.8 -25.6 -22.4L288 368V227.2H256v140.8L208 320l-22.4 22.4z\"]\n};\nvar dhFilePrint = {\n prefix: \"dh\",\n iconName: \"file-print\",\n icon: [512, 512, [], \"f000\", \"M444.8 140.8l-105.6 -105.6 -12.8 -3.2H80l-16 16V224h32V64h192v112l16 16H416v32h32V153.6l-3.2 -12.8zM320 160V64l96 96h-96zM16 256l-16 16v192l16 16h480l16 -16v-192l-16 -16H16zM480 416v32H32V288h448m-32 80c0 19.2 -12.8 32 -32 32s-32 -12.8 -32 -32 12.8 -32 32 -32 32 12.8 32 32zm-96 -16H96v32h256v-32z\"]\n};\nvar dhFileSearch = {\n prefix: \"dh\",\n iconName: \"file-search\",\n icon: [512, 512, [], \"f000\", \"M412.8 147.2L304 35.2 294.4 32H80l-16 16v384l16 16H224v-32H96V64h160v128h128v32h32V160l-3.2 -12.8zM288 160V64l92.8 96H288zm224 329.6l-92.8 -92.8c9.6 -16 16 -32 16 -51.2 0 -51.2 -41.6 -89.6 -89.6 -89.6C297.6 256 256 297.6 256 345.6s41.6 89.6 89.6 89.6c19.2 0 38.4 -6.4 51.2 -16l92.8 92.8 22.4 -22.4zm-224 -144c0 -32 25.6 -57.6 57.6 -57.6s57.6 25.6 57.6 57.6 -25.6 57.6 -57.6 57.6S288 377.6 288 345.6z\"]\n};\nvar dhFileSpreadsheet = {\n prefix: \"dh\",\n iconName: \"file-spreadsheet\",\n icon: [512, 512, [], \"f000\", \"M438.4 137.6l-96 -96L320 32H128L96 64v384l32 32h288l32 -32V160l-9.6 -22.4zM416 448H128V64h160v128h128v256zm-96 -288V64l96 96h-96zm64 99.2l-19.2 -19.2H179.2l-19.2 19.2v137.6l19.2 19.2h185.6l19.2 -19.2V259.2zm-150.4 134.4H182.4v-48h51.2v48zm0 -115.2v48H182.4V278.4m115.2 115.2H246.4v-48h48v48zm0 -64H246.4V278.4h48v51.2zm64 64H310.4v-48h48v48zm-51.2 -64V278.4h48v48H310.4z\"]\n};\nvar dhFilterFilled = {\n prefix: \"dh\",\n iconName: \"filter-filled\",\n icon: [512, 512, [], \"f000\", \"M480 64v54.4l-160 153.6V448H192V268.8L32 118.4V64h448z\"]\n};\nvar dhFilterSlash = {\n prefix: \"dh\",\n iconName: \"filter-slash\",\n icon: [512, 512, [], \"f000\", \"M480 118.4V64H108.8L70.4 25.6 25.6 70.4l406.4 406.4 44.8 -44.8L320 275.2v-6.4l160 -150.4zM288 416H224v-86.4l-32 -32V448h128v-22.4l-32 -32v22.4zM140.8 96H448v6.4L294.4 249.6 140.8 96z\"]\n};\nvar dhFreeze = {\n prefix: \"dh\",\n iconName: \"freeze\",\n icon: [512, 512, [], \"f000\", \"M438.4 300.8l-19.2 -28.8 -60.8 35.2L272 256l86.4 -51.2 60.8 35.2 19.2 -28.8 -44.8 -25.6 48 -28.8 -16 -25.6 -48 28.8V108.8h-35.2v67.2L256 227.2V128l60.8 -35.2 -16 -28.8 -44.8 25.6V32H224v57.6L179.2 64l-16 28.8L224 128v99.2L137.6 176V108.8H102.4V160l-48 -28.8 -16 25.6 48 28.8 -44.8 25.6 19.2 28.8 60.8 -35.2L208 256 121.6 307.2 60.8 272l-19.2 28.8 44.8 25.6 -48 28.8 16 25.6 48 -28.8v51.2h35.2v-67.2L224 284.8V384l-60.8 35.2 16 28.8 44.8 -25.6V480h32v-57.6l44.8 25.6 16 -28.8L256 384V284.8l86.4 51.2v67.2h35.2V352l48 28.8 16 -25.6 -48 -28.8z\"]\n};\nvar dhGearFilled = {\n prefix: \"dh\",\n iconName: \"gear-filled\",\n icon: [512, 512, [], \"f000\", \"M480 211.2l-76.8 -12.8L448 131.2l-64 -64 -67.2 41.6L300.8 32H211.2l-12.8 76.8L131.2 64l-64 64 41.6 67.2 -76.8 16v89.6l76.8 12.8L64 380.8l64 64 67.2 -41.6 16 76.8h89.6l16 -76.8L384 448l64 -64 -44.8 -67.2 76.8 -16V211.2zM256 320c-38.4 0 -64 -25.6 -64 -64s25.6 -64 64 -64 64 25.6 64 64 -25.6 64 -64 64z\"]\n};\nvar dhGearsFilled = {\n prefix: \"dh\",\n iconName: \"gears-filled\",\n icon: [512, 512, [], \"f000\", \"M281.6 112l-48 32 -12.8 -57.6H153.6l-16 57.6 -51.2 -32L41.6 160l35.2 48 -60.8 9.6V288l57.6 12.8 -32 51.2 48 48 48 -35.2 12.8 60.8h70.4l12.8 -57.6 51.2 32 48 -48 -32 -51.2 60.8 -12.8V220.8l-64 -12.8 32 -51.2 -48 -44.8zm38.4 32l28.8 6.4 -16 25.6 25.6 25.6 25.6 -16 6.4 28.8h35.2l6.4 -28.8 25.6 16 22.4 -25.6 -16 -25.6 28.8 -6.4V108.8l-28.8 -6.4 16 -22.4 -25.6 -25.6 -25.6 16 -6.4 -28.8h-35.2l-3.2 28.8 -25.6 -16 -25.6 25.6 16 25.6 -28.8 3.2v35.2zm86.4 -41.6c16 0 25.6 9.6 25.6 25.6s-9.6 25.6 -25.6 25.6 -25.6 -9.6 -25.6 -25.6 9.6 -25.6 25.6 -25.6zM320 403.2l28.8 6.4 -16 25.6 25.6 25.6 25.6 -16 6.4 28.8h35.2l6.4 -28.8 25.6 16 25.6 -25.6 -16 -25.6 28.8 -6.4v-35.2l-28.8 -6.4 16 -25.6 -25.6 -25.6 -25.6 16 -6.4 -28.8h-35.2l-6.4 28.8 -25.6 -16 -25.6 25.6 16 25.6 -28.8 6.4v35.2zm86.4 -44.8c16 0 25.6 9.6 25.6 25.6s-9.6 25.6 -25.6 25.6 -25.6 -9.6 -25.6 -25.6c0 -12.8 9.6 -25.6 25.6 -25.6zM220.8 291.2c-19.2 19.2 -48 19.2 -70.4 0 -19.2 -19.2 -19.2 -48 0 -70.4s48 -19.2 70.4 0 19.2 48 0 70.4z\"]\n};\nvar dhGraphLineDown = {\n prefix: \"dh\",\n iconName: \"graph-line-down\",\n icon: [512, 512, [], \"f000\", \"M64 416V0H32v432l16 16H480v-32zm67.2 -291.2l-22.4 22.4 108.8 112 70.4 -64 108.8 124.8H320v32h112l16 -16V224h-32v70.4L288 150.4l-70.4 64z\"]\n};\nvar dhGraphLineUp = {\n prefix: \"dh\",\n iconName: \"graph-line-up\",\n icon: [512, 512, [], \"f000\", \"M64 416V0H32v432l16 16H480v-32zm153.6 -150.4l70.4 64 128 -144V256h32V144l-16 -16H320v32h76.8L288 284.8l-70.4 -64 -108.8 112 22.4 22.4z\"]\n};\nvar dhICursor = {\n prefix: \"dh\",\n iconName: \"i-cursor\",\n icon: [512, 512, [], \"f000\", \"M384 48v-32c-73.6 0 -108.8 19.2 -128 38.4C236.8 35.2 201.6 16 128 16v32c70.4 0 112 19.2 112 48v144H192v32h48V416c0 38.4 -83.2 48 -112 48v32c3.2 0 92.8 0 128 -38.4 35.2 38.4 124.8 38.4 128 38.4v-32c-28.8 0 -112 -9.6 -112 -48V272H320v-32H272V96c0 -28.8 41.6 -48 112 -48z\"]\n};\nvar dhInput = {\n prefix: \"dh\",\n iconName: \"input\",\n icon: [512, 512, [], \"f000\", \"M464 448h-416l-16 -16v-352l16 -16h416l16 16v352l-16 16zM64 416h384V96H64v320zm96 -224h32v128H160zm64 -32v32H128V160l48 16zm0 160v32l-48 -16L128 352v-32z\"]\n};\nvar dhNewCircleLargeFilled = {\n prefix: \"dh\",\n iconName: \"new-circle-large-filled\",\n icon: [512, 512, [], \"f000\", \"M240 0C108.8 0 0 108.8 0 240S108.8 480 240 480 480 371.2 480 240 371.2 0 240 0zM352 256H256v96H224V256H128V224h96V128h32v96h96v32z\"]\n};\nvar dhNewSquareFilled = {\n prefix: \"dh\",\n iconName: \"new-square-filled\",\n icon: [512, 512, [], \"f000\", \"M432 32h-384l-16 16v384l16 16h384l16 -16v-384l-16 -16zM352 256H256v96H224V256H128V224h96V128h32v96h96v32z\"]\n};\nvar dhPanels = {\n prefix: \"dh\",\n iconName: \"panels\",\n icon: [512, 512, [], \"f000\", \"M496 288l16 16v160l-16 16h-192l-16 -16v-160l16 -16h192zm0 -256h-192l-16 16v160l16 16h192l16 -16v-160l-16 -16zM16 32l-16 16v160l16 16h192l16 -16v-160L208 32h-192zm0 256l-16 16v160l16 16h192l16 -16v-160L208 288h-192z\"]\n};\nvar dhPython = {\n prefix: \"dh\",\n iconName: \"python\",\n icon: [512, 512, [], \"f000\", \"M198.4 249.6h99.2s57.6 0 57.6 -54.4V102.4s9.6 -54.4 -99.2 -54.4c-105.6 0 -99.2 44.8 -99.2 44.8v48H256v12.8H115.2s-67.2 -6.4 -67.2 99.2c0 105.6 57.6 102.4 57.6 102.4h35.2V307.2s-3.2 -57.6 57.6 -57.6zm3.2 -131.2c-9.6 0 -19.2 -9.6 -19.2 -19.2s6.4 -19.2 19.2 -19.2c9.6 0 19.2 9.6 19.2 19.2s-9.6 19.2 -19.2 19.2zm208 35.2h-35.2v48s3.2 57.6 -57.6 57.6H217.6S160 259.2 160 313.6v92.8s-12.8 54.4 99.2 54.4c105.6 0 99.2 -44.8 99.2 -44.8v-48H259.2v-12.8h140.8s67.2 6.4 67.2 -99.2 -57.6 -102.4 -57.6 -102.4zm-96 236.8c9.6 0 19.2 9.6 19.2 19.2s-9.6 19.2 -19.2 19.2 -19.2 -9.6 -19.2 -19.2 9.6 -19.2 19.2 -19.2z\"]\n};\nvar dhRefresh = {\n prefix: \"dh\",\n iconName: \"refresh\",\n icon: [512, 512, [], \"f000\", \"M313.6 73.6l-9.6 32c83.2 25.6 131.2 118.4 102.4 201.6 -19.2 64 -80 108.8 -150.4 108.8 -89.6 0 -160 -70.4 -160 -160 0 -51.2 22.4 -96 64 -128v64h32V80L176 64H64v32h86.4c-76.8 51.2 -108.8 150.4 -70.4 236.8C112 403.2 179.2 448 256 448c105.6 0 192 -86.4 192 -192 0 -83.2 -54.4 -156.8 -134.4 -182.4z\"]\n};\nvar dhRemoveSquareFilled = {\n prefix: \"dh\",\n iconName: \"remove-square-filled\",\n icon: [512, 512, [], \"f000\", \"M432 32h-384l-16 16v384l16 16h384l16 -16v-384l-16 -16zM352 256H128V224h224v32z\"]\n};\nvar dhShapes = {\n prefix: \"dh\",\n iconName: \"shapes\",\n icon: [512, 512, [], \"f000\", \"M195.2 320L160 256 128 313.6 105.6 352 32 480h256l-73.6 -128 -19.2 -32zm112 -76.8c51.2 -35.2 121.6 -22.4 156.8 28.8s22.4 121.6 -28.8 156.8c0 0 -3.2 0 -3.2 3.2 -51.2 32 -121.6 19.2 -153.6 -32 -35.2 -54.4 -22.4 -121.6 28.8 -156.8zM96 32v192h192V32H96z\"]\n};\nvar dhShareFilled = {\n prefix: \"dh\",\n iconName: \"share-filled\",\n icon: [512, 512, [], \"f000\", \"M400 320c-25.6 0 -51.2 12.8 -64 35.2L188.8 288c3.2 -3.2 3.2 -9.6 3.2 -16 0 -9.6 -3.2 -16 -3.2 -22.4l150.4 -83.2c16 16 35.2 25.6 60.8 25.6C444.8 192 480 156.8 480 112S444.8 32 400 32 320 67.2 320 112c0 9.6 3.2 16 3.2 22.4L172.8 220.8C156.8 201.6 137.6 192 112 192 67.2 192 32 227.2 32 272S67.2 352 112 352c25.6 0 51.2 -12.8 64 -35.2l144 64c0 6.4 -3.2 12.8 -3.2 16 0 44.8 35.2 80 80 80s80 -35.2 80 -80 -32 -76.8 -76.8 -76.8z\"]\n};\nvar dhShare = {\n prefix: \"dh\",\n iconName: \"share\",\n icon: [512, 512, [], \"f000\", \"M400 320c-25.6 0 -51.2 12.8 -64 35.2L188.8 288c3.2 -3.2 3.2 -9.6 3.2 -16 0 -9.6 -3.2 -16 -3.2 -22.4l150.4 -83.2c16 16 35.2 25.6 60.8 25.6C444.8 192 480 156.8 480 112S444.8 32 400 32 320 67.2 320 112c0 9.6 3.2 16 3.2 22.4L172.8 220.8C156.8 201.6 137.6 192 112 192 67.2 192 32 227.2 32 272S67.2 352 112 352c25.6 0 51.2 -12.8 64 -35.2l144 64c0 6.4 -3.2 12.8 -3.2 16 0 44.8 35.2 80 80 80s80 -35.2 80 -80 -32 -76.8 -76.8 -76.8zm0 -256c25.6 0 48 22.4 48 48S425.6 160 400 160 352 137.6 352 112 374.4 64 400 64zm-288 256C86.4 320 64 297.6 64 272S86.4 224 112 224 160 246.4 160 272 137.6 320 112 320zm288 128c-25.6 0 -48 -22.4 -48 -48s22.4 -48 48 -48 48 22.4 48 48 -22.4 48 -48 48z\"]\n};\nvar dhSortAlphaDown = {\n prefix: \"dh\",\n iconName: \"sort-alpha-down\",\n icon: [512, 512, [], \"f000\", \"M236.8 368L156.8 448h-22.4l-80 -80 22.4 -22.4L128 396.8V64h32v332.8l51.2 -51.2 25.6 22.4zM371.2 224l-6.4 -28.8H316.8l-9.6 28.8H256l54.4 -160h60.8l51.2 160h-51.2zm-32 -124.8c0 3.2 -3.2 3.2 -3.2 9.6s-3.2 19.2 -12.8 51.2h32l-9.6 -44.8c-3.2 -6.4 -6.4 -9.6 -6.4 -16zm-6.4 310.4h73.6V448H272v-32l73.6 -89.6H275.2V288h128v32l-70.4 89.6z\"]\n};\nvar dhSortAlphaUp = {\n prefix: \"dh\",\n iconName: \"sort-alpha-up\",\n icon: [512, 512, [], \"f000\", \"M51.2 144L131.2 64h22.4l80 80 -22.4 22.4L160 115.2V448H128V115.2L76.8 166.4l-25.6 -22.4zm320 304l-6.4 -28.8H316.8l-9.6 28.8H256l54.4 -160h60.8l51.2 160h-51.2zm-32 -124.8c0 3.2 -3.2 3.2 -3.2 9.6 0 6.4 -3.2 19.2 -12.8 51.2h32l-9.6 -44.8c-3.2 -6.4 -6.4 -9.6 -6.4 -16zm-6.4 -137.6h73.6V224H272V192l73.6 -89.6H275.2V64h128v32l-70.4 89.6z\"]\n};\nvar dhSortAmountDown = {\n prefix: \"dh\",\n iconName: \"sort-amount-down\",\n icon: [512, 512, [], \"f000\", \"M204.8 368L124.8 448h-22.4L22.4 368l22.4 -22.4L96 396.8V64h32v332.8l51.2 -51.2 25.6 22.4zM256 64h256v64H256zm0 105.6h192v64H256zm0 108.8h128v64H256zM256 384h64v64H256z\"]\n};\nvar dhSortDown = {\n prefix: \"dh\",\n iconName: \"sort-down\",\n icon: [512, 512, [], \"f000\", \"M128 288l-12.8 25.6 128 118.4h25.6l128 -118.4L384 288H128z\"]\n};\nvar dhSortUp = {\n prefix: \"dh\",\n iconName: \"sort-up\",\n icon: [512, 512, [], \"f000\", \"M128 224l-12.8 -25.6 128 -118.4h25.6l128 118.4 -12.8 25.6H128z\"]\n};\nvar dhSort = {\n prefix: \"dh\",\n iconName: \"sort\",\n icon: [512, 512, [], \"f000\", \"M128 224l-12.8 -25.6 128 -118.4h25.6l128 118.4 -12.8 25.6H128zm0 64l-12.8 25.6 128 118.4h25.6l128 -118.4L384 288H128z\"]\n};\nvar dhSplitBoth = {\n prefix: \"dh\",\n iconName: \"split-both\",\n icon: [512, 512, [], \"f000\", \"M448 32H96L64 64v352l32 32h352l32 -32V64l-32 -32zM96 64h160v160H96V64zm0 352V256h160v160H96zm352 0H288V256h160v160zm0 -192H288V64h160v160z\"]\n};\nvar dhSquareFilled = {\n prefix: \"dh\",\n iconName: \"square-filled\",\n icon: [512, 512, [], \"f000\", \"M432 32h-384l-16 16v384l16 16h384l16 -16v-384l-16 -16z\"]\n};\nvar dhStickyNoteFilled = {\n prefix: \"dh\",\n iconName: \"sticky-note-filled\",\n icon: [512, 512, [], \"f000\", \"M288 288h160V48l-16 -16h-384l-16 16v384l16 16H288V288zm32 28.8V448l128 -131.2h-128z\"]\n};\nvar dhTable = {\n prefix: \"dh\",\n iconName: \"table\",\n icon: [512, 512, [], \"f000\", \"M432 64h-384l-16 16v352l16 16h384l16 -16v-352l-16 -16zM160 416H64v-64h96v64zm0 -96H64V256h96v64zm0 -96H64V160h96v64zm128 192H192v-64h96v64zm0 -96H192V256h96v64zm0 -96H192V160h96v64zm128 192h-96v-64h96v64zm0 -96h-96V256h96v64zm0 -96h-96V160h96v64z\"]\n};\nvar dhTrashUndo = {\n prefix: \"dh\",\n iconName: \"trash-undo\",\n icon: [512, 512, [], \"f000\", \"M320 96h96v32h-32v288l-32 32H128l-32 -32V128H64V96h96V64c0 -19.2 12.8 -32 32 -32h96c19.2 0 32 12.8 32 32v32zM288 64H192v32h96V64zM128 416h224V128H128v288zm112 -64L160 272v-22.4l80 -80 22.4 22.4 -51.2 54.4H320v32H211.2l51.2 51.2 -22.4 22.4z\"]\n};\nvar dhTriangleDownSquare = {\n prefix: \"dh\",\n iconName: \"triangle-down-square\",\n icon: [512, 512, [], \"f000\", \"M425.6 64H86.4l-22.4 22.4v342.4l22.4 19.2h342.4l22.4 -22.4V86.4l-25.6 -22.4zm-160 288h-22.4L99.2 208l9.6 -16h291.2l9.6 12.8L265.6 352z\"]\n};\nvar dhTruck = {\n prefix: \"dh\",\n iconName: \"truck\",\n icon: [512, 512, [], \"f000\", \"M480 384V256l-64 -64 -64 -64h-32V64H32v352h35.2c6.4 35.2 38.4 64 76.8 64s70.4 -28.8 76.8 -64H320c6.4 35.2 38.4 64 76.8 64s70.4 -28.8 76.8 -64H512v-32h-32zm-291.2 32c-6.4 19.2 -25.6 32 -44.8 32s-38.4 -12.8 -44.8 -32c-3.2 -6.4 -3.2 -9.6 -3.2 -16 0 -25.6 22.4 -48 48 -48s48 22.4 48 48c0 6.4 0 9.6 -3.2 16zm147.2 -140.8l-12.8 -12.8v-96l22.4 -6.4 96 96 -9.6 19.2h-96zm108.8 140.8c-6.4 19.2 -25.6 32 -44.8 32s-38.4 -12.8 -44.8 -32c-3.2 -6.4 -3.2 -9.6 -3.2 -16 0 -25.6 22.4 -48 48 -48s48 22.4 48 48c0 6.4 0 9.6 -3.2 16z\"]\n};\nvar dhUnlink = {\n prefix: \"dh\",\n iconName: \"unlink\",\n icon: [512, 512, [], \"f000\", \"M32 211.2v-6.4C32 144 80 96 140.8 96h99.2c12.8 0 25.6 3.2 38.4 6.4l-25.6 25.6H140.8C99.2 128 64 163.2 64 204.8v6.4c0 28.8 16 54.4 38.4 67.2l-22.4 22.4C51.2 281.6 32 249.6 32 211.2zM403.2 6.4l-38.4 38.4 -67.2 67.2 -22.4 25.6 -150.4 147.2 -25.6 25.6 -54.4 54.4 -38.4 38.4L51.2 448 448 51.2 403.2 6.4zM384 192v32c38.4 6.4 64 38.4 64 76.8v6.4c0 41.6 -35.2 76.8 -76.8 76.8H272c-32 0 -60.8 -22.4 -73.6 -51.2l-25.6 25.6c19.2 35.2 54.4 60.8 96 60.8h99.2c60.8 0 108.8 -48 108.8 -108.8v-9.6C480 246.4 438.4 198.4 384 192zM246.4 288l-22.4 19.2v12.8h16c60.8 0 108.8 -48 108.8 -108.8v-6.4c0 -6.4 0 -12.8 -3.2 -19.2l-32 32c0 38.4 -32 67.2 -67.2 70.4z\"]\n};\nvar dhUserIncognito = {\n prefix: \"dh\",\n iconName: \"user-incognito\",\n icon: [512, 512, [], \"f000\", \"M348.8 278.4C371.2 256 384 227.2 384 192c0 -22.4 -6.4 -44.8 -19.2 -64H416V96H96v32h51.2c-12.8 19.2 -19.2 41.6 -19.2 64 0 35.2 12.8 64 35.2 86.4 -57.6 32 -99.2 92.8 -99.2 166.4 0 16 86.4 35.2 192 35.2s192 -19.2 192 -35.2c0 -73.6 -38.4 -134.4 -99.2 -166.4zM160 192c0 -25.6 9.6 -48 25.6 -64h144c12.8 16 22.4 38.4 22.4 64 0 28.8 -12.8 54.4 -35.2 73.6 -19.2 12.8 -38.4 22.4 -60.8 22.4s-41.6 -9.6 -57.6 -22.4C176 246.4 160 220.8 160 192zm96 252.8c-76.8 0 -131.2 -9.6 -153.6 -16 6.4 -57.6 41.6 -102.4 92.8 -121.6 19.2 6.4 38.4 12.8 60.8 12.8s41.6 -6.4 60.8 -16c51.2 19.2 86.4 67.2 92.8 121.6 -22.4 9.6 -76.8 19.2 -153.6 19.2zM169.6 76.8c16 3.2 160 3.2 176 0 19.2 -3.2 -19.2 -48 -25.6 -60.8C310.4 6.4 275.2 32 256 32 236.8 32 201.6 6.4 195.2 16c-9.6 12.8 -48 57.6 -25.6 60.8zm67.2 128h32c6.4 9.6 16 19.2 28.8 19.2 16 0 32 -12.8 32 -32s-12.8 -32 -32 -32c-9.6 0 -19.2 6.4 -25.6 16h-32c-6.4 -12.8 -16 -19.2 -28.8 -19.2 -16 0 -32 12.8 -32 32s12.8 32 32 32c12.8 0 22.4 -6.4 25.6 -16z\"]\n};\nvar dhUser = {\n prefix: \"dh\",\n iconName: \"user\",\n icon: [512, 512, [], \"f000\", \"M348.8 278.4C371.2 256 384 227.2 384 192c0 -70.4 -57.6 -128 -128 -128S128 121.6 128 192c0 35.2 12.8 64 35.2 86.4 -57.6 32 -99.2 92.8 -99.2 166.4 0 16 86.4 35.2 192 35.2s192 -19.2 192 -35.2c0 -73.6 -38.4 -134.4 -99.2 -166.4zM160 192c0 -51.2 41.6 -96 96 -96s96 41.6 96 96c0 28.8 -12.8 54.4 -35.2 73.6 -19.2 12.8 -38.4 22.4 -60.8 22.4s-41.6 -9.6 -57.6 -22.4C176 246.4 160 220.8 160 192zm96 252.8c-76.8 0 -131.2 -9.6 -153.6 -16 6.4 -57.6 41.6 -102.4 92.8 -121.6 19.2 6.4 38.4 12.8 60.8 12.8s41.6 -6.4 60.8 -16c51.2 19.2 86.4 67.2 92.8 121.6 -22.4 9.6 -76.8 19.2 -153.6 19.2z\"]\n};\nvar dhWarningCircleFilled = {\n prefix: \"dh\",\n iconName: \"warning-circle-filled\",\n icon: [512, 512, [], \"f000\", \"M470.4 195.2c-9.6 -38.4 -28.8 -70.4 -57.6 -99.2 -25.6 -25.6 -60.8 -44.8 -96 -54.4C297.6 35.2 275.2 32 256 32c-19.2 0 -41.6 3.2 -60.8 9.6 -16 3.2 -35.2 9.6 -51.2 22.4 -35.2 19.2 -60.8 44.8 -80 80 -12.8 16 -19.2 35.2 -25.6 51.2C35.2 214.4 32 236.8 32 256c0 19.2 3.2 41.6 6.4 60.8 6.4 16 12.8 35.2 25.6 51.2 9.6 16 22.4 32 35.2 44.8 12.8 16 28.8 25.6 44.8 35.2 16 9.6 35.2 16 54.4 22.4 16 6.4 38.4 9.6 57.6 9.6 19.2 0 41.6 -3.2 60.8 -6.4 19.2 -6.4 35.2 -12.8 54.4 -22.4 32 -19.2 60.8 -48 80 -80 9.6 -16 16 -35.2 22.4 -54.4 3.2 -19.2 6.4 -41.6 6.4 -60.8s-3.2 -41.6 -9.6 -60.8zM275.2 352H236.8v-32h38.4v32zm0 -64H236.8V160h38.4v128z\"]\n};\nvar dhWarningFilled = {\n prefix: \"dh\",\n iconName: \"warning-filled\",\n icon: [512, 512, [], \"f000\", \"M268.8 32h-25.6L32 425.6l12.8 22.4h419.2l12.8 -22.4L268.8 32zm6.4 352H236.8v-32h38.4v32zm0 -64H236.8V192h38.4v128z\"]\n};\nvar _iconsCache = {\n vsAccount:vsAccount,\n vsActivateBreakpoints:vsActivateBreakpoints,\n vsAdd:vsAdd,\n vsArchive:vsArchive,\n vsArrowBoth:vsArrowBoth,\n vsArrowDown:vsArrowDown,\n vsArrowLeft:vsArrowLeft,\n vsArrowRight:vsArrowRight,\n vsArrowSmallDown:vsArrowSmallDown,\n vsArrowSmallLeft:vsArrowSmallLeft,\n vsArrowSmallRight:vsArrowSmallRight,\n vsArrowSmallUp:vsArrowSmallUp,\n vsArrowSwap:vsArrowSwap,\n vsArrowUp:vsArrowUp,\n vsAzure:vsAzure,\n vsBeakerStop:vsBeakerStop,\n vsBeaker:vsBeaker,\n vsBellDot:vsBellDot,\n vsBell:vsBell,\n vsBold:vsBold,\n vsBook:vsBook,\n vsBookmark:vsBookmark,\n vsBracketDot:vsBracketDot,\n vsBracketError:vsBracketError,\n vsBriefcase:vsBriefcase,\n vsBroadcast:vsBroadcast,\n vsBrowser:vsBrowser,\n vsBug:vsBug,\n vsCalendar:vsCalendar,\n vsCallIncoming:vsCallIncoming,\n vsCallOutgoing:vsCallOutgoing,\n vsCaseSensitive:vsCaseSensitive,\n vsCheckAll:vsCheckAll,\n vsCheck:vsCheck,\n vsChecklist:vsChecklist,\n vsChevronDown:vsChevronDown,\n vsChevronLeft:vsChevronLeft,\n vsChevronRight:vsChevronRight,\n vsChevronUp:vsChevronUp,\n vsChromeClose:vsChromeClose,\n vsChromeMaximize:vsChromeMaximize,\n vsChromeMinimize:vsChromeMinimize,\n vsChromeRestore:vsChromeRestore,\n vsCircleFilled:vsCircleFilled,\n vsCircleLargeFilled:vsCircleLargeFilled,\n vsCircleLargeOutline:vsCircleLargeOutline,\n vsCircleOutline:vsCircleOutline,\n vsCircleSlash:vsCircleSlash,\n vsCircuitBoard:vsCircuitBoard,\n vsClearAll:vsClearAll,\n vsClippy:vsClippy,\n vsCloseAll:vsCloseAll,\n vsClose:vsClose,\n vsCloudDownload:vsCloudDownload,\n vsCloudUpload:vsCloudUpload,\n vsCloud:vsCloud,\n vsCode:vsCode,\n vsCollapseAll:vsCollapseAll,\n vsColorMode:vsColorMode,\n vsCombine:vsCombine,\n vsCommentDiscussion:vsCommentDiscussion,\n vsComment:vsComment,\n vsCompassActive:vsCompassActive,\n vsCompassDot:vsCompassDot,\n vsCompass:vsCompass,\n vsCopy:vsCopy,\n vsCreditCard:vsCreditCard,\n vsDash:vsDash,\n vsDashboard:vsDashboard,\n vsDatabase:vsDatabase,\n vsDebugAll:vsDebugAll,\n vsDebugAltSmall:vsDebugAltSmall,\n vsDebugAlt:vsDebugAlt,\n vsDebugBreakpointConditionalUnverified:vsDebugBreakpointConditionalUnverified,\n vsDebugBreakpointConditional:vsDebugBreakpointConditional,\n vsDebugBreakpointDataUnverified:vsDebugBreakpointDataUnverified,\n vsDebugBreakpointData:vsDebugBreakpointData,\n vsDebugBreakpointFunctionUnverified:vsDebugBreakpointFunctionUnverified,\n vsDebugBreakpointFunction:vsDebugBreakpointFunction,\n vsDebugBreakpointLogUnverified:vsDebugBreakpointLogUnverified,\n vsDebugBreakpointLog:vsDebugBreakpointLog,\n vsDebugBreakpointUnsupported:vsDebugBreakpointUnsupported,\n vsDebugConsole:vsDebugConsole,\n vsDebugContinueSmall:vsDebugContinueSmall,\n vsDebugContinue:vsDebugContinue,\n vsDebugCoverage:vsDebugCoverage,\n vsDebugDisconnect:vsDebugDisconnect,\n vsDebugLineByLine:vsDebugLineByLine,\n vsDebugPause:vsDebugPause,\n vsDebugRerun:vsDebugRerun,\n vsDebugRestartFrame:vsDebugRestartFrame,\n vsDebugRestart:vsDebugRestart,\n vsDebugReverseContinue:vsDebugReverseContinue,\n vsDebugStackframeActive:vsDebugStackframeActive,\n vsDebugStackframeDot:vsDebugStackframeDot,\n vsDebugStackframe:vsDebugStackframe,\n vsDebugStart:vsDebugStart,\n vsDebugStepBack:vsDebugStepBack,\n vsDebugStepInto:vsDebugStepInto,\n vsDebugStepOut:vsDebugStepOut,\n vsDebugStepOver:vsDebugStepOver,\n vsDebugStop:vsDebugStop,\n vsDebug:vsDebug,\n vsDesktopDownload:vsDesktopDownload,\n vsDeviceCameraVideo:vsDeviceCameraVideo,\n vsDeviceCamera:vsDeviceCamera,\n vsDeviceMobile:vsDeviceMobile,\n vsDiffAdded:vsDiffAdded,\n vsDiffIgnored:vsDiffIgnored,\n vsDiffModified:vsDiffModified,\n vsDiffRemoved:vsDiffRemoved,\n vsDiffRenamed:vsDiffRenamed,\n vsDiff:vsDiff,\n vsDiscard:vsDiscard,\n vsEdit:vsEdit,\n vsEditorLayout:vsEditorLayout,\n vsEllipsis:vsEllipsis,\n vsEmptyWindow:vsEmptyWindow,\n vsError:vsError,\n vsExclude:vsExclude,\n vsExpandAll:vsExpandAll,\n vsExport:vsExport,\n vsExtensions:vsExtensions,\n vsEyeClosed:vsEyeClosed,\n vsEye:vsEye,\n vsFeedback:vsFeedback,\n vsFileBinary:vsFileBinary,\n vsFileCode:vsFileCode,\n vsFileMedia:vsFileMedia,\n vsFilePdf:vsFilePdf,\n vsFileSubmodule:vsFileSubmodule,\n vsFileSymlinkDirectory:vsFileSymlinkDirectory,\n vsFileSymlinkFile:vsFileSymlinkFile,\n vsFileZip:vsFileZip,\n vsFile:vsFile,\n vsFiles:vsFiles,\n vsFilterFilled:vsFilterFilled,\n vsFilter:vsFilter,\n vsFlame:vsFlame,\n vsFoldDown:vsFoldDown,\n vsFoldUp:vsFoldUp,\n vsFold:vsFold,\n vsFolderActive:vsFolderActive,\n vsFolderLibrary:vsFolderLibrary,\n vsFolderOpened:vsFolderOpened,\n vsFolder:vsFolder,\n vsGear:vsGear,\n vsGift:vsGift,\n vsGistSecret:vsGistSecret,\n vsGist:vsGist,\n vsGitCommit:vsGitCommit,\n vsGitCompare:vsGitCompare,\n vsGitMerge:vsGitMerge,\n vsGitPullRequestClosed:vsGitPullRequestClosed,\n vsGitPullRequestCreate:vsGitPullRequestCreate,\n vsGitPullRequestDraft:vsGitPullRequestDraft,\n vsGitPullRequest:vsGitPullRequest,\n vsGithubAction:vsGithubAction,\n vsGithubAlt:vsGithubAlt,\n vsGithubInverted:vsGithubInverted,\n vsGithub:vsGithub,\n vsGlobe:vsGlobe,\n vsGoToFile:vsGoToFile,\n vsGrabber:vsGrabber,\n vsGraphLeft:vsGraphLeft,\n vsGraphLine:vsGraphLine,\n vsGraphScatter:vsGraphScatter,\n vsGraph:vsGraph,\n vsGripper:vsGripper,\n vsGroupByRefType:vsGroupByRefType,\n vsHeart:vsHeart,\n vsHistory:vsHistory,\n vsHome:vsHome,\n vsHorizontalRule:vsHorizontalRule,\n vsHubot:vsHubot,\n vsInbox:vsInbox,\n vsInfo:vsInfo,\n vsInspect:vsInspect,\n vsIssueDraft:vsIssueDraft,\n vsIssueReopened:vsIssueReopened,\n vsIssues:vsIssues,\n vsItalic:vsItalic,\n vsJersey:vsJersey,\n vsJson:vsJson,\n vsKebabVertical:vsKebabVertical,\n vsKey:vsKey,\n vsLaw:vsLaw,\n vsLayersActive:vsLayersActive,\n vsLayersDot:vsLayersDot,\n vsLayers:vsLayers,\n vsLibrary:vsLibrary,\n vsLightbulbAutofix:vsLightbulbAutofix,\n vsLightbulb:vsLightbulb,\n vsLinkExternal:vsLinkExternal,\n vsLink:vsLink,\n vsListFilter:vsListFilter,\n vsListFlat:vsListFlat,\n vsListOrdered:vsListOrdered,\n vsListSelection:vsListSelection,\n vsListTree:vsListTree,\n vsListUnordered:vsListUnordered,\n vsLiveShare:vsLiveShare,\n vsLoading:vsLoading,\n vsLocation:vsLocation,\n vsLock:vsLock,\n vsMagnet:vsMagnet,\n vsMailRead:vsMailRead,\n vsMail:vsMail,\n vsMarkdown:vsMarkdown,\n vsMegaphone:vsMegaphone,\n vsMention:vsMention,\n vsMenu:vsMenu,\n vsMerge:vsMerge,\n vsMilestone:vsMilestone,\n vsMirror:vsMirror,\n vsMortarBoard:vsMortarBoard,\n vsMove:vsMove,\n vsMultipleWindows:vsMultipleWindows,\n vsMute:vsMute,\n vsNewFile:vsNewFile,\n vsNewFolder:vsNewFolder,\n vsNoNewline:vsNoNewline,\n vsNote:vsNote,\n vsNotebookTemplate:vsNotebookTemplate,\n vsNotebook:vsNotebook,\n vsOctoface:vsOctoface,\n vsOpenPreview:vsOpenPreview,\n vsOrganization:vsOrganization,\n vsOutput:vsOutput,\n vsPackage:vsPackage,\n vsPaintcan:vsPaintcan,\n vsPassFilled:vsPassFilled,\n vsPass:vsPass,\n vsPersonAdd:vsPersonAdd,\n vsPerson:vsPerson,\n vsPieChart:vsPieChart,\n vsPin:vsPin,\n vsPinnedDirty:vsPinnedDirty,\n vsPinned:vsPinned,\n vsPlayCircle:vsPlayCircle,\n vsPlay:vsPlay,\n vsPlug:vsPlug,\n vsPreserveCase:vsPreserveCase,\n vsPreview:vsPreview,\n vsPrimitiveSquare:vsPrimitiveSquare,\n vsProject:vsProject,\n vsPulse:vsPulse,\n vsQuestion:vsQuestion,\n vsQuote:vsQuote,\n vsRadioTower:vsRadioTower,\n vsReactions:vsReactions,\n vsRecordKeys:vsRecordKeys,\n vsRecord:vsRecord,\n vsRedo:vsRedo,\n vsReferences:vsReferences,\n vsRefresh:vsRefresh,\n vsRegex:vsRegex,\n vsRemoteExplorer:vsRemoteExplorer,\n vsRemote:vsRemote,\n vsRemove:vsRemove,\n vsReplaceAll:vsReplaceAll,\n vsReplace:vsReplace,\n vsReply:vsReply,\n vsRepoClone:vsRepoClone,\n vsRepoForcePush:vsRepoForcePush,\n vsRepoForked:vsRepoForked,\n vsRepoPull:vsRepoPull,\n vsRepoPush:vsRepoPush,\n vsRepo:vsRepo,\n vsReport:vsReport,\n vsRequestChanges:vsRequestChanges,\n vsRocket:vsRocket,\n vsRootFolderOpened:vsRootFolderOpened,\n vsRootFolder:vsRootFolder,\n vsRss:vsRss,\n vsRuby:vsRuby,\n vsRunAbove:vsRunAbove,\n vsRunAll:vsRunAll,\n vsRunBelow:vsRunBelow,\n vsRunErrors:vsRunErrors,\n vsSaveAll:vsSaveAll,\n vsSaveAs:vsSaveAs,\n vsSave:vsSave,\n vsScreenFull:vsScreenFull,\n vsScreenNormal:vsScreenNormal,\n vsSearchStop:vsSearchStop,\n vsSearch:vsSearch,\n vsServerEnvironment:vsServerEnvironment,\n vsServerProcess:vsServerProcess,\n vsServer:vsServer,\n vsSettingsGear:vsSettingsGear,\n vsSettings:vsSettings,\n vsShield:vsShield,\n vsSignIn:vsSignIn,\n vsSignOut:vsSignOut,\n vsSmiley:vsSmiley,\n vsSortPrecedence:vsSortPrecedence,\n vsSourceControl:vsSourceControl,\n vsSplitHorizontal:vsSplitHorizontal,\n vsSplitVertical:vsSplitVertical,\n vsSquirrel:vsSquirrel,\n vsStarEmpty:vsStarEmpty,\n vsStarFull:vsStarFull,\n vsStarHalf:vsStarHalf,\n vsStopCircle:vsStopCircle,\n vsSymbolArray:vsSymbolArray,\n vsSymbolBoolean:vsSymbolBoolean,\n vsSymbolClass:vsSymbolClass,\n vsSymbolColor:vsSymbolColor,\n vsSymbolConstant:vsSymbolConstant,\n vsSymbolEnumMember:vsSymbolEnumMember,\n vsSymbolEnum:vsSymbolEnum,\n vsSymbolEvent:vsSymbolEvent,\n vsSymbolField:vsSymbolField,\n vsSymbolFile:vsSymbolFile,\n vsSymbolInterface:vsSymbolInterface,\n vsSymbolKey:vsSymbolKey,\n vsSymbolKeyword:vsSymbolKeyword,\n vsSymbolMethod:vsSymbolMethod,\n vsSymbolMisc:vsSymbolMisc,\n vsSymbolNamespace:vsSymbolNamespace,\n vsSymbolNumeric:vsSymbolNumeric,\n vsSymbolOperator:vsSymbolOperator,\n vsSymbolParameter:vsSymbolParameter,\n vsSymbolProperty:vsSymbolProperty,\n vsSymbolRuler:vsSymbolRuler,\n vsSymbolSnippet:vsSymbolSnippet,\n vsSymbolString:vsSymbolString,\n vsSymbolStructure:vsSymbolStructure,\n vsSymbolVariable:vsSymbolVariable,\n vsSyncIgnored:vsSyncIgnored,\n vsSync:vsSync,\n vsTable:vsTable,\n vsTag:vsTag,\n vsTasklist:vsTasklist,\n vsTelescope:vsTelescope,\n vsTerminalBash:vsTerminalBash,\n vsTerminalCmd:vsTerminalCmd,\n vsTerminalDebian:vsTerminalDebian,\n vsTerminalLinux:vsTerminalLinux,\n vsTerminalPowershell:vsTerminalPowershell,\n vsTerminalTmux:vsTerminalTmux,\n vsTerminalUbuntu:vsTerminalUbuntu,\n vsTerminal:vsTerminal,\n vsTextSize:vsTextSize,\n vsThreeBars:vsThreeBars,\n vsThumbsdown:vsThumbsdown,\n vsThumbsup:vsThumbsup,\n vsTools:vsTools,\n vsTrash:vsTrash,\n vsTriangleDown:vsTriangleDown,\n vsTriangleLeft:vsTriangleLeft,\n vsTriangleRight:vsTriangleRight,\n vsTriangleUp:vsTriangleUp,\n vsTwitter:vsTwitter,\n vsTypeHierarchySub:vsTypeHierarchySub,\n vsTypeHierarchySuper:vsTypeHierarchySuper,\n vsTypeHierarchy:vsTypeHierarchy,\n vsUnfold:vsUnfold,\n vsUngroupByRefType:vsUngroupByRefType,\n vsUnlock:vsUnlock,\n vsUnmute:vsUnmute,\n vsUnverified:vsUnverified,\n vsVariableGroup:vsVariableGroup,\n vsVerified:vsVerified,\n vsVersions:vsVersions,\n vsVmActive:vsVmActive,\n vsVmConnect:vsVmConnect,\n vsVmOutline:vsVmOutline,\n vsVmRunning:vsVmRunning,\n vsVm:vsVm,\n vsWand:vsWand,\n vsWarning:vsWarning,\n vsWatch:vsWatch,\n vsWhitespace:vsWhitespace,\n vsWholeWord:vsWholeWord,\n vsWindow:vsWindow,\n vsWordWrap:vsWordWrap,\n vsWorkspaceTrusted:vsWorkspaceTrusted,\n vsWorkspaceUnknown:vsWorkspaceUnknown,\n vsWorkspaceUntrusted:vsWorkspaceUntrusted,\n vsZoomIn:vsZoomIn,\n vsZoomOut:vsZoomOut,\n dhArrowToBottom:dhArrowToBottom,\n dhArrowToTop:dhArrowToTop,\n dhCheckSquare:dhCheckSquare,\n dhChevronDownSquare:dhChevronDownSquare,\n dhCircleLargeOutlineNotch:dhCircleLargeOutlineNotch,\n dhClock:dhClock,\n dhExclamation:dhExclamation,\n dhEyeSlash:dhEyeSlash,\n dhEye:dhEye,\n dhFileCertificate:dhFileCertificate,\n dhFileCsv:dhFileCsv,\n dhFileDownload:dhFileDownload,\n dhFilePrint:dhFilePrint,\n dhFileSearch:dhFileSearch,\n dhFileSpreadsheet:dhFileSpreadsheet,\n dhFilterFilled:dhFilterFilled,\n dhFilterSlash:dhFilterSlash,\n dhFreeze:dhFreeze,\n dhGearFilled:dhGearFilled,\n dhGearsFilled:dhGearsFilled,\n dhGraphLineDown:dhGraphLineDown,\n dhGraphLineUp:dhGraphLineUp,\n dhICursor:dhICursor,\n dhInput:dhInput,\n dhNewCircleLargeFilled:dhNewCircleLargeFilled,\n dhNewSquareFilled:dhNewSquareFilled,\n dhPanels:dhPanels,\n dhPython:dhPython,\n dhRefresh:dhRefresh,\n dhRemoveSquareFilled:dhRemoveSquareFilled,\n dhShapes:dhShapes,\n dhShareFilled:dhShareFilled,\n dhShare:dhShare,\n dhSortAlphaDown:dhSortAlphaDown,\n dhSortAlphaUp:dhSortAlphaUp,\n dhSortAmountDown:dhSortAmountDown,\n dhSortDown:dhSortDown,\n dhSortUp:dhSortUp,\n dhSort:dhSort,\n dhSplitBoth:dhSplitBoth,\n dhSquareFilled:dhSquareFilled,\n dhStickyNoteFilled:dhStickyNoteFilled,\n dhTable:dhTable,\n dhTrashUndo:dhTrashUndo,\n dhTriangleDownSquare:dhTriangleDownSquare,\n dhTruck:dhTruck,\n dhUnlink:dhUnlink,\n dhUserIncognito:dhUserIncognito,\n dhUser:dhUser,\n dhWarningCircleFilled:dhWarningCircleFilled,\n dhWarningFilled:dhWarningFilled,\n};\n\nexport { _iconsCache as dh, prefix, vsAccount, vsActivateBreakpoints, vsAdd, vsArchive, vsArrowBoth, vsArrowDown, vsArrowLeft, vsArrowRight, vsArrowSmallDown, vsArrowSmallLeft, vsArrowSmallRight, vsArrowSmallUp, vsArrowSwap, vsArrowUp, vsAzure, vsBeakerStop, vsBeaker, vsBellDot, vsBell, vsBold, vsBook, vsBookmark, vsBracketDot, vsBracketError, vsBriefcase, vsBroadcast, vsBrowser, vsBug, vsCalendar, vsCallIncoming, vsCallOutgoing, vsCaseSensitive, vsCheckAll, vsCheck, vsChecklist, vsChevronDown, vsChevronLeft, vsChevronRight, vsChevronUp, vsChromeClose, vsChromeMaximize, vsChromeMinimize, vsChromeRestore, vsCircleFilled, vsCircleLargeFilled, vsCircleLargeOutline, vsCircleOutline, vsCircleSlash, vsCircuitBoard, vsClearAll, vsClippy, vsCloseAll, vsClose, vsCloudDownload, vsCloudUpload, vsCloud, vsCode, vsCollapseAll, vsColorMode, vsCombine, vsCommentDiscussion, vsComment, vsCompassActive, vsCompassDot, vsCompass, vsCopy, vsCreditCard, vsDash, vsDashboard, vsDatabase, vsDebugAll, vsDebugAltSmall, vsDebugAlt, vsDebugBreakpointConditionalUnverified, vsDebugBreakpointConditional, vsDebugBreakpointDataUnverified, vsDebugBreakpointData, vsDebugBreakpointFunctionUnverified, vsDebugBreakpointFunction, vsDebugBreakpointLogUnverified, vsDebugBreakpointLog, vsDebugBreakpointUnsupported, vsDebugConsole, vsDebugContinueSmall, vsDebugContinue, vsDebugCoverage, vsDebugDisconnect, vsDebugLineByLine, vsDebugPause, vsDebugRerun, vsDebugRestartFrame, vsDebugRestart, vsDebugReverseContinue, vsDebugStackframeActive, vsDebugStackframeDot, vsDebugStackframe, vsDebugStart, vsDebugStepBack, vsDebugStepInto, vsDebugStepOut, vsDebugStepOver, vsDebugStop, vsDebug, vsDesktopDownload, vsDeviceCameraVideo, vsDeviceCamera, vsDeviceMobile, vsDiffAdded, vsDiffIgnored, vsDiffModified, vsDiffRemoved, vsDiffRenamed, vsDiff, vsDiscard, vsEdit, vsEditorLayout, vsEllipsis, vsEmptyWindow, vsError, vsExclude, vsExpandAll, vsExport, vsExtensions, vsEyeClosed, vsEye, vsFeedback, vsFileBinary, vsFileCode, vsFileMedia, vsFilePdf, vsFileSubmodule, vsFileSymlinkDirectory, vsFileSymlinkFile, vsFileZip, vsFile, vsFiles, vsFilterFilled, vsFilter, vsFlame, vsFoldDown, vsFoldUp, vsFold, vsFolderActive, vsFolderLibrary, vsFolderOpened, vsFolder, vsGear, vsGift, vsGistSecret, vsGist, vsGitCommit, vsGitCompare, vsGitMerge, vsGitPullRequestClosed, vsGitPullRequestCreate, vsGitPullRequestDraft, vsGitPullRequest, vsGithubAction, vsGithubAlt, vsGithubInverted, vsGithub, vsGlobe, vsGoToFile, vsGrabber, vsGraphLeft, vsGraphLine, vsGraphScatter, vsGraph, vsGripper, vsGroupByRefType, vsHeart, vsHistory, vsHome, vsHorizontalRule, vsHubot, vsInbox, vsInfo, vsInspect, vsIssueDraft, vsIssueReopened, vsIssues, vsItalic, vsJersey, vsJson, vsKebabVertical, vsKey, vsLaw, vsLayersActive, vsLayersDot, vsLayers, vsLibrary, vsLightbulbAutofix, vsLightbulb, vsLinkExternal, vsLink, vsListFilter, vsListFlat, vsListOrdered, vsListSelection, vsListTree, vsListUnordered, vsLiveShare, vsLoading, vsLocation, vsLock, vsMagnet, vsMailRead, vsMail, vsMarkdown, vsMegaphone, vsMention, vsMenu, vsMerge, vsMilestone, vsMirror, vsMortarBoard, vsMove, vsMultipleWindows, vsMute, vsNewFile, vsNewFolder, vsNoNewline, vsNote, vsNotebookTemplate, vsNotebook, vsOctoface, vsOpenPreview, vsOrganization, vsOutput, vsPackage, vsPaintcan, vsPassFilled, vsPass, vsPersonAdd, vsPerson, vsPieChart, vsPin, vsPinnedDirty, vsPinned, vsPlayCircle, vsPlay, vsPlug, vsPreserveCase, vsPreview, vsPrimitiveSquare, vsProject, vsPulse, vsQuestion, vsQuote, vsRadioTower, vsReactions, vsRecordKeys, vsRecord, vsRedo, vsReferences, vsRefresh, vsRegex, vsRemoteExplorer, vsRemote, vsRemove, vsReplaceAll, vsReplace, vsReply, vsRepoClone, vsRepoForcePush, vsRepoForked, vsRepoPull, vsRepoPush, vsRepo, vsReport, vsRequestChanges, vsRocket, vsRootFolderOpened, vsRootFolder, vsRss, vsRuby, vsRunAbove, vsRunAll, vsRunBelow, vsRunErrors, vsSaveAll, vsSaveAs, vsSave, vsScreenFull, vsScreenNormal, vsSearchStop, vsSearch, vsServerEnvironment, vsServerProcess, vsServer, vsSettingsGear, vsSettings, vsShield, vsSignIn, vsSignOut, vsSmiley, vsSortPrecedence, vsSourceControl, vsSplitHorizontal, vsSplitVertical, vsSquirrel, vsStarEmpty, vsStarFull, vsStarHalf, vsStopCircle, vsSymbolArray, vsSymbolBoolean, vsSymbolClass, vsSymbolColor, vsSymbolConstant, vsSymbolEnumMember, vsSymbolEnum, vsSymbolEvent, vsSymbolField, vsSymbolFile, vsSymbolInterface, vsSymbolKey, vsSymbolKeyword, vsSymbolMethod, vsSymbolMisc, vsSymbolNamespace, vsSymbolNumeric, vsSymbolOperator, vsSymbolParameter, vsSymbolProperty, vsSymbolRuler, vsSymbolSnippet, vsSymbolString, vsSymbolStructure, vsSymbolVariable, vsSyncIgnored, vsSync, vsTable, vsTag, vsTasklist, vsTelescope, vsTerminalBash, vsTerminalCmd, vsTerminalDebian, vsTerminalLinux, vsTerminalPowershell, vsTerminalTmux, vsTerminalUbuntu, vsTerminal, vsTextSize, vsThreeBars, vsThumbsdown, vsThumbsup, vsTools, vsTrash, vsTriangleDown, vsTriangleLeft, vsTriangleRight, vsTriangleUp, vsTwitter, vsTypeHierarchySub, vsTypeHierarchySuper, vsTypeHierarchy, vsUnfold, vsUngroupByRefType, vsUnlock, vsUnmute, vsUnverified, vsVariableGroup, vsVerified, vsVersions, vsVmActive, vsVmConnect, vsVmOutline, vsVmRunning, vsVm, vsWand, vsWarning, vsWatch, vsWhitespace, vsWholeWord, vsWindow, vsWordWrap, vsWorkspaceTrusted, vsWorkspaceUnknown, vsWorkspaceUntrusted, vsZoomIn, vsZoomOut, dhArrowToBottom, dhArrowToTop, dhCheckSquare, dhChevronDownSquare, dhCircleLargeOutlineNotch, dhClock, dhExclamation, dhEyeSlash, dhEye, dhFileCertificate, dhFileCsv, dhFileDownload, dhFilePrint, dhFileSearch, dhFileSpreadsheet, dhFilterFilled, dhFilterSlash, dhFreeze, dhGearFilled, dhGearsFilled, dhGraphLineDown, dhGraphLineUp, dhICursor, dhInput, dhNewCircleLargeFilled, dhNewSquareFilled, dhPanels, dhPython, dhRefresh, dhRemoveSquareFilled, dhShapes, dhShareFilled, dhShare, dhSortAlphaDown, dhSortAlphaUp, dhSortAmountDown, dhSortDown, dhSortUp, dhSort, dhSplitBoth, dhSquareFilled, dhStickyNoteFilled, dhTable, dhTrashUndo, dhTriangleDownSquare, dhTruck, dhUnlink, dhUserIncognito, dhUser, dhWarningCircleFilled, dhWarningFilled, };\n","import ThemeExport from './ThemeExport.module.scss';\n\n// Note that TypeScript does not know what keys exist on ThemeExport.module.scss\n// It only knows it's an object with strings for keys and values\nexport default Object.freeze({\n transitionMs: 150,\n transitionMidMs: 200,\n transitionLongMs: 300,\n transitionSlowMs: 1000,\n ...ThemeExport,\n});\n","import React from 'react';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsCircleLargeOutline, vsLoading } from '@deephaven/icons';\nimport './LoadingSpinner.scss';\n\ntype LoadingSpinnerProps = {\n className?: string;\n};\n\nconst LoadingSpinner = ({\n className = '',\n}: LoadingSpinnerProps): JSX.Element => (\n <div className={classNames('loading-spinner fa-layers', className)}>\n <FontAwesomeIcon icon={vsCircleLargeOutline} className=\"text-white-50\" />\n <FontAwesomeIcon icon={vsLoading} className=\"text-primary\" spin />\n </div>\n);\n\nexport default LoadingSpinner;\n","import React from 'react';\nimport { CSSTransition } from 'react-transition-group';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsWarning } from '@deephaven/icons';\nimport ThemeExport from './ThemeExport';\nimport LoadingSpinner from './LoadingSpinner';\nimport './LoadingOverlay.scss';\n\ntype LoadingOverlayProps = {\n isLoaded: boolean;\n isLoading: boolean;\n errorMessage: string | null;\n};\n\n/**\n * A loading overlay that handles displaying a loading spinner or an error message\n */\nconst LoadingOverlay = ({\n isLoaded = false,\n isLoading = true,\n errorMessage = null,\n}: LoadingOverlayProps): JSX.Element => (\n <CSSTransition\n in={!!errorMessage || !isLoaded || isLoading}\n timeout={ThemeExport.transitionMs}\n classNames={isLoaded ? 'fade' : ''}\n mountOnEnter\n unmountOnExit\n >\n <div className=\"fill-parent-absolute\">\n <div\n className={classNames(\n 'iris-panel-message-overlay',\n 'fill-parent-absolute',\n { 'iris-panel-scrim-background': isLoaded }\n )}\n >\n <div className=\"message-content\">\n <div className=\"message-icon\">\n {isLoading && <LoadingSpinner />}\n {!isLoading && errorMessage && <FontAwesomeIcon icon={vsWarning} />}\n </div>\n <div className=\"message-text\">{errorMessage}</div>\n </div>\n </div>\n </div>\n </CSSTransition>\n);\n\nexport default LoadingOverlay;\n","export const SILENT = -1;\nexport const ERROR = 0;\nexport const WARN = 1;\nexport const INFO = 2;\nexport const DEBUG = 3;\nexport const DEBUG2 = 4;\n\nexport default Object.freeze({\n SILENT,\n ERROR,\n WARN,\n INFO,\n DEBUG,\n DEBUG2,\n});\n","/* eslint no-console: \"off\" */\nimport { ERROR, WARN, INFO, DEBUG, DEBUG2 } from './LoggerLevel';\n\nconst silent = () => {};\n\nclass Logger {\n constructor(name, level) {\n this.name = name;\n this.prefix = name ? `[${name}]` : ``;\n\n this.setLogLevel(level);\n }\n\n setLogLevel(level) {\n this.level = level;\n\n this.error =\n ERROR <= level ? console.error.bind(console, this.prefix) : silent;\n this.warn =\n WARN <= level ? console.warn.bind(console, this.prefix) : silent;\n this.log = INFO <= level ? console.log.bind(console, this.prefix) : silent;\n this.info = this.log;\n this.debug =\n DEBUG <= level ? console.debug.bind(console, this.prefix) : silent;\n this.debug2 =\n DEBUG2 <= level ? console.debug.bind(console, this.prefix) : silent;\n }\n}\n\nexport default Logger;\n","import Logger from './Logger';\nimport LoggerLevel, { DEBUG2, INFO, SILENT } from './LoggerLevel';\n\n/**\n * Get the default log level to use.\n * production mode defaults to INFO.\n * development mode defaults to DEBUG2 (most verbose).\n * test mode defaults to SILENT.\n * Override by setting environment variable `process.env.DEEPHAVEN_LOG_LEVEL`\n * @returns {number} The default log level to use\n */\nfunction getDefaultLevel() {\n let envValue = '';\n try {\n envValue = process.env.DEEPHAVEN_LOG_LEVEL;\n } catch {\n // no-op. Environment without process defined\n }\n if (envValue && LoggerLevel[envValue]) {\n return LoggerLevel[envValue];\n }\n const envLevel = parseInt(envValue ?? '', 10);\n if (!Number.isNaN(envLevel)) {\n return envLevel;\n }\n\n try {\n if (process.env.NODE_ENV === 'test') {\n return SILENT;\n }\n if (process.env.NODE_ENV === 'development') {\n return DEBUG2;\n }\n } catch {\n // no-op. Environment without process defined\n }\n\n return INFO;\n}\n\nclass DefaultLogger extends Logger {\n constructor(level = getDefaultLevel()) {\n super(null, level);\n\n this.modules = {};\n }\n\n module(name) {\n if (!this.modules[name]) {\n this.modules[name] = new Logger(name, this.level);\n }\n\n return this.modules[name];\n }\n\n setLogLevel(level) {\n super.setLogLevel(level);\n\n if (!this.modules) {\n return;\n }\n\n const keys = Object.keys(this.modules);\n for (let i = 0; i < keys.length; i += 1) {\n this.modules[keys[i]].setLogLevel(level);\n }\n }\n}\n\nexport default DefaultLogger;\n","/* eslint-disable no-console */\nimport { EventTarget, Event } from 'event-target-shim';\nimport Log from './Log';\n\nexport enum LOG_PROXY_TYPE {\n DEBUG = 'D',\n LOG = 'L',\n WARN = 'W',\n ERROR = 'E',\n UNCAUGHT_ERROR = 'U',\n}\n\n// We need to cast our CustomEvent so it's happy with event-target-shim\ntype CustomEventType = EventTarget.EventData<\n Record<string, Event>,\n 'standard',\n 'CustomEvent'\n>;\n\nfunction makeEvent(type: LOG_PROXY_TYPE, detail: unknown): CustomEventType {\n return new CustomEvent(type, {\n detail,\n }) as CustomEventType;\n}\n\nexport class LogProxy {\n private isEnabled = false;\n\n private debug: (...data: unknown[]) => void;\n\n private log: (...data: unknown[]) => void;\n\n private warn: (...data: unknown[]) => void;\n\n private error: (...data: unknown[]) => void;\n\n private eventTarget: EventTarget;\n\n private handleUncaughtError = (event: ErrorEvent) => {\n const messages: string[] = [];\n if (event.error) {\n messages.push(event.error as string);\n }\n if (event.message) {\n messages.push(event.message);\n }\n this.eventTarget.dispatchEvent(\n makeEvent(LOG_PROXY_TYPE.UNCAUGHT_ERROR, messages)\n );\n };\n\n constructor() {\n this.debug = console.debug;\n this.log = console.log;\n this.warn = console.warn;\n this.error = console.error;\n this.eventTarget = new EventTarget();\n }\n\n enable(): void {\n if (this.isEnabled) {\n return;\n }\n\n console.debug = (...args: unknown[]): void => {\n this.eventTarget.dispatchEvent(makeEvent(LOG_PROXY_TYPE.DEBUG, args));\n this.debug.apply(console, args);\n };\n\n console.log = (...args: unknown[]): void => {\n this.eventTarget.dispatchEvent(makeEvent(LOG_PROXY_TYPE.LOG, args));\n this.log.apply(console, args);\n };\n\n console.warn = (...args: unknown[]): void => {\n this.eventTarget.dispatchEvent(makeEvent(LOG_PROXY_TYPE.WARN, args));\n this.warn.apply(console, args);\n };\n\n console.error = (...args: unknown[]): void => {\n this.eventTarget.dispatchEvent(makeEvent(LOG_PROXY_TYPE.ERROR, args));\n this.error.apply(console, args);\n };\n\n window.addEventListener('error', this.handleUncaughtError);\n\n // This forces logger to update its reference to the overriding functions instead of the original\n Log.setLogLevel(Log.level);\n this.isEnabled = true;\n }\n\n disable(): void {\n if (!this.isEnabled) {\n return;\n }\n console.debug = this.debug;\n console.log = this.log;\n console.warn = this.warn;\n console.error = this.error;\n window.removeEventListener('error', this.handleUncaughtError);\n Log.setLogLevel(Log.level);\n this.isEnabled = false;\n }\n\n addEventListener(\n type: LOG_PROXY_TYPE,\n listener: (event: CustomEvent<unknown[]>) => void\n ): void {\n // The cast as EventListener is a dumb TypeScript issue\n this.eventTarget.addEventListener(type, listener as EventListener);\n }\n\n removeEventListener(\n type: LOG_PROXY_TYPE,\n listener: (event: CustomEvent<unknown[]>) => void\n ): void {\n this.eventTarget.removeEventListener(type, listener as EventListener);\n }\n}\n\nexport default LogProxy;\n","import DefaultLogger from './DefaultLogger';\n\nconst Log = new DefaultLogger();\nexport default Log;\n","class CanceledPromiseError extends Error {\n isCanceled = true;\n}\n\nexport default CanceledPromiseError;\n","const TABLE_PREFIX = 'table_';\n\nconst COLUMN_PREFIX = 'column_';\n\n// From io.deephaven.db.tables.utils.DBNameValidator#DB_RESERVED_VARIABLE_NAMES\nconst DB_RESERVED_VARIABLE_NAMES = new Set(['in', 'not', 'i', 'ii', 'k']);\n\n// From javax.lang.model.SourceVersion#keywords\nconst JAVA_KEYWORDS = new Set([\n 'abstract',\n 'continue',\n 'for',\n 'new',\n 'switch',\n 'assert',\n 'default',\n 'if',\n 'package',\n 'synchronized',\n 'boolean',\n 'do',\n 'goto',\n 'private',\n 'this',\n 'break',\n 'double',\n 'implements',\n 'protected',\n 'throw',\n 'byte',\n 'else',\n 'import',\n 'public',\n 'throws',\n 'case',\n 'enum',\n 'instanceof',\n 'return',\n 'transient',\n 'catch',\n 'extends',\n 'int',\n 'short',\n 'try',\n 'char',\n 'final',\n 'interface',\n 'static',\n 'void',\n 'class',\n 'finally',\n 'long',\n 'strictfp',\n 'volatile',\n 'const',\n 'float',\n 'native',\n 'super',\n 'while',\n 'null',\n 'true',\n 'false',\n]);\n\n// From io.deephaven.db.tables.utils.DBNameValidator#STERILE_TABLE_AND_NAMESPACE_REGEX\nconst STERILE_TABLE_AND_NAMESPACE_REGEX = /[^a-zA-Z0-9_$+@-]/g;\n\n// From io.deephaven.db.tables.utils.DBNameValidator#STERILE_COLUMN_AND_QUERY_REGEX\nconst STERILE_COLUMN_AND_QUERY_REGEX = /[^A-Za-z0-9_$]/g;\n\n/**\n * Similar to DBNameValidator.java, this class has utilities for validating and legalizing\n * Table and Column names.\n */\nclass DbNameValidator {\n static legalize = (\n name: string,\n prefix: string,\n regex: RegExp,\n checkReserved: boolean,\n i: number\n ): string => {\n // Replace all dashes and spaces with underscores\n let legalName = name.trim().replace(/[- ]/g, '_');\n\n // Add prefix to reserved names\n if (\n checkReserved &&\n (DB_RESERVED_VARIABLE_NAMES.has(legalName) ||\n JAVA_KEYWORDS.has(legalName))\n ) {\n legalName = prefix + legalName;\n }\n\n // Remove illegal characters\n legalName = legalName.replace(regex, '');\n\n // Check if the name ended up blank\n if (!legalName) {\n legalName = prefix + i;\n }\n\n // If name starts with a number, append prefix to the front\n if (!Number.isNaN(Number(legalName.charAt(0)))) {\n legalName = prefix + legalName;\n }\n\n return legalName;\n };\n\n static legalizeTableName = (name: string): string =>\n DbNameValidator.legalize(\n name,\n TABLE_PREFIX,\n STERILE_TABLE_AND_NAMESPACE_REGEX,\n false,\n 0\n );\n\n static legalizeColumnNames = (headers: string[]): string[] => {\n const legalHeaders: string[] = [];\n headers.forEach((header, i) => {\n let legalHeader = DbNameValidator.legalizeColumnName(header, i);\n\n // Check if the name is already in use\n if (legalHeaders.includes(legalHeader)) {\n legalHeader = COLUMN_PREFIX + i;\n }\n\n legalHeaders.push(legalHeader);\n });\n return legalHeaders;\n };\n\n static legalizeColumnName = (header: string, i = 0): string =>\n // Replace all dashes and spaces with underscores\n DbNameValidator.legalize(\n header,\n COLUMN_PREFIX,\n STERILE_COLUMN_AND_QUERY_REGEX,\n true,\n i\n );\n\n static isValidTableName = (name: string): boolean =>\n DbNameValidator.legalizeTableName(name) === name;\n\n static isValidColumnName = (name: string): boolean =>\n DbNameValidator.legalizeColumnName(name) === name;\n}\n\nexport default DbNameValidator;\n","/**\n * Find the first element that matches the given className\n * by testing the element itself and traversing up\n * through its ancestors in the DOM tree.\n *\n * @param {Element} element Starting element\n * @param {string} className Class name without the '.'\n * @returns DOM element matching the given class or null if not found\n */\n\nexport function getClosestByClassName(\n element: Element | null,\n className: string\n): Element | null {\n if (!element) {\n return null;\n }\n return element.closest(`.${className}`);\n}\n\nexport default { getClosestByClassName };\n","import type { Event, EventTarget } from 'event-target-shim';\n\n/**\n * A CustomEvent extension which combines the browser CustomEvent and event-target-shim's Event types for type safety\n * CustomEvent does not have a generic type and augmenting the dom types seemed like not the best idea\n */\nexport class EventShimCustomEvent<T extends string, D = unknown>\n extends CustomEvent<D>\n implements Event<T> {\n // The fields declared are so TS plays nicely w/ event-target-shim and the browser CustomEvent\n // They don't actually do anything other than tell TS to not complain that they aren't set in the constructor\n // If declare is removed, then the properties are initialized to undefined which breaks this class\n // This will be the default for tsc and babel at some point\n // https://github.com/babel/babel/issues/12128#issuecomment-702119272\n declare type: T;\n\n declare target: EventTarget | null;\n\n declare srcElement: EventTarget | null;\n\n declare currentTarget: EventTarget | null;\n\n declare composedPath: () => EventTarget[];\n\n // eslint-disable-next-line @typescript-eslint/no-useless-constructor\n constructor(typeArg: T, eventInitDict?: CustomEventInit<D>) {\n super(typeArg, eventInitDict);\n }\n}\n\n/**\n * Converts an event map into one using EventShimCustomEvent's so the event type only needs to be specified once\n * Takes an event map such as EventSourceEventMap from https://github.com/mysticatea/event-target-shim/blob/HEAD/docs/reference.md#example-3\n * This lets us specify the EventMap as just { onEvent: Event } rather than { onEvent: Event<'onEvent'> }\n */\nexport type CustomEventMap<M extends Record<string, Event | CustomEvent>> = {\n [T in keyof M]: T extends string\n ? M[T] extends CustomEvent<infer D>\n ? EventShimCustomEvent<T, D>\n : M[T] extends Event\n ? Event<T>\n : never\n : never;\n};\n","class TimeoutError extends Error {\n isTimeout = true;\n}\n\nexport default TimeoutError;\n","import CanceledPromiseError from './CanceledPromiseError';\nimport TimeoutError from './TimeoutError';\n\nexport interface CancelablePromise<T> extends Promise<T> {\n cancel: () => void;\n}\n\nexport class PromiseUtils {\n /**\n * Creates a promise that can be canceled by calling the `cancel` function\n * Pass an optional `cleanupFunc` to perform actions on the resolved item after promise is cancelled.\n * @param promise The item to resolve\n * @param cleanup Function to cleanup the resolved item after cancelation. Called after both this promise is cancelled and the wrapped item was resolved (order does not matter).\n */\n static makeCancelable<T>(\n promise: Promise<T> | T,\n cleanup?: (val: T) => void | null\n ): CancelablePromise<T> {\n let hasCanceled = false;\n let resolved: T | undefined;\n\n const wrappedPromise = new Promise((resolve, reject) => {\n Promise.resolve(promise).then(\n val => {\n if (hasCanceled) {\n if (cleanup) {\n cleanup(val);\n }\n reject(new CanceledPromiseError());\n } else {\n resolved = val;\n resolve(val);\n }\n },\n error =>\n hasCanceled ? reject(new CanceledPromiseError()) : reject(error)\n );\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (wrappedPromise as any).cancel = () => {\n hasCanceled = true;\n\n if (resolved != null && cleanup) {\n cleanup(resolved);\n }\n };\n\n return wrappedPromise as CancelablePromise<T>;\n }\n\n static isCanceled(error: unknown): boolean {\n return error instanceof CanceledPromiseError;\n }\n\n static isTimedOut(error: unknown): boolean {\n return error instanceof TimeoutError;\n }\n}\n","import { PromiseUtils, CancelablePromise } from './PromiseUtils';\n\n/**\n * Helper class for managing pending promises.\n * IDS-6391 When cancel is called, it calls cancel on ALL promises, including ones that have already resolved.\n * This behaviour may change when IDS-6806 is implemented.\n */\nclass Pending {\n pending: Array<CancelablePromise<unknown>> = [];\n\n resolved: Array<CancelablePromise<unknown>> = [];\n\n /**\n * Begins tracking a promise. After the promise has resolved, it's removed from tracking.\n * @param item Item to track.\n * @param cleanup The cleanup function to use when the promise is cancelled\n * @returns CancelablePromise Returns a cancelable promise.\n */\n add<T>(\n item: Promise<T> | T,\n cleanup?: (val: T) => void | null\n ): CancelablePromise<T> {\n const promise = PromiseUtils.makeCancelable(item, cleanup);\n this.pending.push(promise);\n promise.then(\n () => {\n this.resolve(promise);\n },\n () => {\n this.resolve(promise);\n }\n );\n return promise;\n }\n\n /**\n * Remove a promise from tracking.\n * @param promise Promise to stop tracking\n */\n remove(promise: CancelablePromise<unknown>): void {\n for (let i = 0; i < this.pending.length; i += 1) {\n if (this.pending[i] === promise) {\n this.pending.splice(i, 1);\n return;\n }\n }\n }\n\n resolve(promise: CancelablePromise<unknown>): void {\n this.remove(promise);\n this.resolved.push(promise);\n }\n\n /**\n * Cancel all pending promises and remove them from tracking.\n */\n cancel(): void {\n const allPromises = [...this.pending, ...this.resolved];\n for (let i = 0; i < allPromises.length; i += 1) {\n allPromises[i].cancel();\n }\n this.pending = [];\n this.resolved = [];\n }\n}\n\nexport default Pending;\n","// A number pair representing [start, end].\nexport type Range = [number, number];\n\nclass RangeUtils {\n static isValidRange(range: Range): boolean {\n return (\n range != null &&\n range.length === 2 &&\n Number.isInteger(range[0]) &&\n Number.isInteger(range[1]) &&\n range[0] <= range[1]\n );\n }\n\n static validateRange(range: Range): void {\n if (!RangeUtils.isValidRange(range)) {\n throw new Error(`Invalid range! ${range}`);\n }\n }\n\n static isSelected(selectedRanges: Range[], index: number): boolean {\n for (let i = 0; i < selectedRanges.length; i += 1) {\n const range = selectedRanges[i];\n const start = range[0];\n const end = range[1];\n if (start <= index && index <= end) {\n return true;\n }\n }\n\n return false;\n }\n\n static selectRange(selectedRanges: Range[], range: Range): Range[] {\n let [start, end] = range;\n const ranges = [...selectedRanges];\n\n // Need to consolidate the range with previous ranges\n for (let i = ranges.length - 1; i >= 0; i -= 1) {\n const selectedRange = ranges[i];\n const selectedStart = selectedRange[0];\n const selectedEnd = selectedRange[1];\n\n if (selectedStart <= start && end <= selectedEnd) {\n // Already contained within a range\n return ranges;\n }\n\n if (start <= selectedEnd && selectedStart <= end) {\n // Overlaps the previous range, remove this range and update the new range\n start = Math.min(start, selectedStart);\n end = Math.max(end, selectedEnd);\n ranges.splice(i, 1);\n }\n }\n\n ranges.push([start, end]);\n\n return ranges;\n }\n\n static deselectRange(selectedRanges: Range[], range: Range): Range[] {\n const [start, end] = range;\n const ranges = [...selectedRanges];\n // Need to consolidate the range with previous ranges\n for (let i = ranges.length - 1; i >= 0; i -= 1) {\n const selectedRange = ranges[i];\n const selectedStart = selectedRange[0];\n const selectedEnd = selectedRange[1];\n\n if (end < selectedStart || selectedEnd < start) {\n // Outside of the selected range\n } else if (selectedStart < start && end < selectedEnd) {\n // Contained within the range, split the range\n ranges[i] = [selectedStart, start - 1];\n ranges.splice(i + 1, 0, [end + 1, selectedEnd]);\n break;\n } else if (start <= selectedStart && selectedEnd <= end) {\n // Entire range should be deselected, remove from selected ranges\n ranges.splice(i, 1);\n } else if (selectedStart < start) {\n // Overlaps end of the previous range, update the end\n ranges[i] = [selectedStart, start - 1];\n } else {\n // Overlaps the start of the previous range, update the start\n ranges[i] = [end + 1, selectedEnd];\n }\n }\n return ranges;\n }\n\n /**\n * Count the sum total of items in the ranges provided\n *\n * @param ranges The ranges to count\n */\n static count(ranges: Range[]): number {\n return ranges.reduce((sum, range) => sum + (range[1] - range[0] + 1), 0);\n }\n}\n\nexport default RangeUtils;\n","class TextUtils {\n /**\n * Joins a list of strings with a comma, keeping the oxford comma and adding \"and\" as appropriate.\n * Eg.\n * One\n * One and Two\n * One, Two, and Three\n * @param items The items to join in a list\n * @param conjunction Conjunction to use between the last two items\n */\n static join(items: string[] | null, conjunction = 'and'): string {\n if (items == null || items.length === 0) {\n return '';\n }\n\n if (items.length === 1) {\n return items[0];\n }\n\n if (items.length === 2) {\n return `${items[0]} ${conjunction} ${items[1]}`;\n }\n\n const itemText = items.slice(0, items.length - 1).join(', ');\n const lastItem = items[items.length - 1];\n return `${itemText}, ${conjunction} ${lastItem}`;\n }\n\n /**\n * Converts text to lower case, handling null if necessary and returning an empty string\n * @param text The text to convert to lower case\n * @param isNullAllowed True if a null string should return an empty string from this function. If false an error is thrown if null is passed in.\n */\n static toLower(text: string | null, isNullAllowed = true): string {\n if (text == null) {\n if (isNullAllowed) {\n return '';\n }\n\n throw new Error('Null string passed in to TextUtils.toLower');\n }\n\n return text.toLowerCase();\n }\n\n /**\n *\n * @param a The string to sort\n * @param b Second string to sort\n * @param isAscending Whether to sort ascending or descending\n */\n static sort(a: string, b: string, isAscending = true): number {\n if (a < b) {\n return isAscending ? -1 : 1;\n }\n if (a > b) {\n return isAscending ? 1 : -1;\n }\n return 0;\n }\n}\n\nexport default TextUtils;\n","type TimeInSeconds = number;\nexport type TimeString = `${string}:${string}:${string}`;\n\nclass TimeUtils {\n static TIME_PATTERN = '([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]';\n\n static TIME_ZONES = Object.freeze([\n { label: 'Tokyo UTC+9 No DST', value: 'Asia/Tokyo' },\n { label: 'Seoul UTC+9 No DST', value: 'Asia/Seoul' },\n { label: 'Hong Kong UTC+8 No DST', value: 'Asia/Hong_Kong' },\n { label: 'Singapore UTC+8 No DST', value: 'Asia/Singapore' },\n { label: 'Kolkata UTC+5:30 No DST', value: 'Asia/Kolkata' },\n { label: 'Berlin UTC+1', value: 'Europe/Berlin' },\n { label: 'UTC UTC±0 No DST', value: 'UTC' },\n { label: 'London UTC±0', value: 'Europe/London' },\n { label: 'Sao Paulo UTC-2', value: 'America/Sao_Paulo' },\n { label: 'Newfoundland UTC-3:30', value: 'America/St_Johns' },\n { label: 'Halifax UTC-4', value: 'America/Halifax' },\n { label: 'New York UTC−5', value: 'America/New_York' },\n { label: 'Chicago UTC-6', value: 'America/Chicago' },\n { label: 'Denver UTC-7', value: 'America/Denver' },\n { label: 'Los Angeles UTC-8', value: 'America/Los_Angeles' },\n { label: 'Anchorage UTC-9', value: 'America/Anchorage' },\n { label: 'Honolulu UTC-10 No DST', value: 'Pacific/Honolulu' },\n { label: 'Zurich UTC+1', value: 'Europe/Zurich' },\n { label: 'Amsterdam UTC+1', value: 'Europe/Amsterdam' },\n { label: 'Taipei UTC+8 No DST', value: 'Asia/Taipei' },\n { label: 'Sydney UTC+10', value: 'Australia/Sydney' },\n ]);\n\n /**\n * Pretty prints a time in seconds as a format like \"1h 3m 23s\", \"32s\"\n * Seconds are padded after 60s, has elapsed to reduce width changes\n * Minutes aren't paded, as thats a slower change\n * @param time in seconds\n */\n static formatElapsedTime(time: unknown): string {\n if (typeof time !== 'number' || !Number.isInteger(time)) {\n throw new Error(\n `${time} is not a number that can be expressed as a formatted time`\n );\n }\n\n const hours = Math.floor(time / 3600);\n const mins = Math.floor((time % 3600) / 60);\n const seconds = time % 60;\n\n return (\n `${hours > 0 ? `${hours}h ` : ''}` +\n `${mins > 0 || hours > 0 ? `${mins}m ` : ''}` +\n `${time >= 60 ? `${seconds}s`.padStart(3, '0') : `${seconds}s`}`\n );\n }\n\n /**\n * Format the time into hh:mm:ss format, eg. '12:34:56'\n * @param timeInSeconds in seconds\n */\n static formatTime(timeInSeconds: unknown): string {\n if (\n typeof timeInSeconds !== 'number' ||\n !Number.isInteger(timeInSeconds) ||\n timeInSeconds < 0\n ) {\n throw new Error(\n `${timeInSeconds} is not a number that can be expressed as a formatted time`\n );\n }\n\n const hours = String(Math.floor(timeInSeconds / (60 * 60))).padStart(\n 2,\n '0'\n );\n\n const divisorForMinutes = timeInSeconds % (60 * 60);\n const minutes = String(Math.floor(divisorForMinutes / 60)).padStart(2, '0');\n\n const divisorForSeconds = divisorForMinutes % 60;\n const seconds = String(Math.ceil(divisorForSeconds)).padStart(2, '0');\n\n return `${hours}:${minutes}:${seconds}`;\n }\n\n static isTimeString(s: string): s is TimeString {\n return new RegExp(TimeUtils.TIME_PATTERN).test(s);\n }\n\n /**\n * Parse time in seconds from the provided time string\n * @param timeString Time string in hh:mm:ss format\n */\n static parseTime(timeString: unknown): TimeInSeconds {\n if (!timeString || typeof timeString !== 'string') {\n throw new Error(`${timeString} is not a valid string`);\n }\n\n const components = timeString.split(':');\n\n if (components.length !== 3) {\n throw new Error(`${timeString} is not a time string that can be parsed`);\n }\n\n return (\n Number(components[0]) * 60 * 60 +\n Number(components[1]) * 60 +\n Number(components[2])\n );\n }\n}\n\nexport default TimeUtils;\n","class InvalidMetadataError extends Error {\n isInvalidMetadata = true;\n}\n\nexport default InvalidMetadataError;\n","class ValidationError extends Error {\n isInvalid = true;\n}\n\nexport default ValidationError;\n","import { IconDefinition } from '@deephaven/icons';\nimport React from 'react';\nimport type { Shortcut } from '../shortcuts';\n\nexport type ResolvableContextAction =\n | ContextAction\n | Promise<ContextAction[]>\n | (() => Promise<ContextAction[]> | ContextAction[] | ContextAction);\n\nexport type MenuItem = ContextAction | Promise<ContextAction[]>;\n\nexport interface ContextAction {\n title?: string;\n description?: string;\n action?(event?: KeyboardEvent): void;\n actions?: ResolvableContextAction[];\n icon?: IconDefinition | React.ReactElement;\n iconColor?: string;\n shortcut?: Shortcut;\n isGlobal?: boolean;\n group?: number;\n order?: number;\n disabled?: boolean;\n menuElement?: React.ReactElement;\n iconOutline?: boolean;\n}\n\nexport interface ContextActionEvent extends MouseEvent {\n contextActions: ResolvableContextAction[];\n}\n\nclass ContextActionUtils {\n static actionsDisabled = false;\n\n static disableAllActions(): void {\n ContextActionUtils.actionsDisabled = true;\n }\n\n static enableAllActions(): void {\n ContextActionUtils.actionsDisabled = false;\n }\n\n static isContextActionEvent(e: MouseEvent): e is ContextActionEvent {\n return Array.isArray((e as ContextActionEvent).contextActions);\n }\n\n /**\n * Compare two action items. Useful in Array.sort\n * @param a First context action to compare\n * @param b Second context action to compare\n */\n static compareActions(a: ContextAction, b: ContextAction): number {\n if (a.group !== b.group) {\n return (a.group || 0) > (b.group || 0) ? 1 : -1;\n }\n\n if (a.order !== b.order) {\n return (a.order || 0) > (b.order || 0) ? 1 : -1;\n }\n\n if (a.title !== b.title) {\n return (a.title || '') > (b.title || '') ? 1 : -1;\n }\n\n if (a !== b) {\n return a > b ? 1 : -1;\n }\n\n return 0;\n }\n\n /**\n *\n * @param actions The array of actions to sort\n */\n static sortActions(actions: ContextAction[]): ContextAction[] {\n if (!actions || !Array.isArray(actions)) {\n return [];\n }\n\n const sortedActions = actions.slice();\n sortedActions.sort(ContextActionUtils.compareActions);\n return sortedActions;\n }\n\n static isMacPlatform(): boolean {\n const { platform } = window.navigator;\n return platform.startsWith('Mac');\n }\n\n /**\n * Retrieve the preferred modifier key based on the current platform\n */\n static getModifierKey(): 'metaKey' | 'ctrlKey' {\n if (ContextActionUtils.isMacPlatform()) {\n return 'metaKey';\n }\n\n return 'ctrlKey';\n }\n\n /**\n * Returns true if the modifier key for the current platform is down for the event (Ctrl for windows/linux, Command (meta) for mac)\n * @param event The event to get the meta key status from\n */\n static isModifierKeyDown(\n event: KeyboardEvent | MouseEvent | React.KeyboardEvent | React.MouseEvent\n ): boolean {\n const modifierKey = ContextActionUtils.getModifierKey();\n return event[modifierKey];\n }\n\n /**\n * Copy the passed in text to the clipboard.\n * @param text The text to copy\n * @returns Promise Resolved on success, rejected on failure\n */\n static async copyToClipboard(text: string): Promise<void> {\n try {\n const permissions = await navigator.permissions.query({\n name: 'clipboard-write' as PermissionName,\n });\n if (permissions.state !== 'granted' && permissions.state !== 'prompt') {\n throw new Error('Invalid permissions for clipboard-write');\n }\n } catch (e) {\n // Fallback if we can't get permissions for some reason\n ContextActionUtils.copyToClipboardExecCommand(text);\n return;\n }\n\n await navigator.clipboard.writeText(text);\n }\n\n /**\n * Copy the passed in text to the clipboard using the `execCommand` functionality\n * Throws on error/failure\n * @param text The text to copy\n */\n static copyToClipboardExecCommand(text: string): void {\n const oldFocus = document.activeElement;\n const textArea = document.createElement('textarea');\n textArea.value = text;\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n\n if (!document.execCommand('copy')) {\n throw new Error('Unable to execute copy command');\n }\n\n document.body.removeChild(textArea);\n\n if (oldFocus instanceof HTMLElement) {\n oldFocus.focus();\n }\n }\n\n /**\n * Returns the menu items for the provided context actions, or empty array if none found.\n * @param actionsParam The actions to get menu items for\n * @param includePromises Whether or not to include promises in the returned menu items\n */\n static getMenuItems(\n actionsParam: ResolvableContextAction | ResolvableContextAction[],\n includePromises?: true\n ): MenuItem[];\n\n // If ignoring promises, then the return type is narrowed\n static getMenuItems(\n actionsParam: ResolvableContextAction | ResolvableContextAction[],\n includePromises: false\n ): ContextAction[];\n\n static getMenuItems(\n actionsParam: ResolvableContextAction | ResolvableContextAction[],\n includePromises = true\n ): MenuItem[] {\n let menuItems: MenuItem[] = [];\n let actions = actionsParam;\n if (!Array.isArray(actions)) {\n actions = [actions];\n }\n\n for (let i = 0; i < actions.length; i += 1) {\n const action = actions[i];\n let newMenuItems:\n | ContextAction\n | ContextAction[]\n | Promise<ContextAction[]>;\n if (typeof action === 'function') {\n newMenuItems = action();\n } else {\n newMenuItems = action;\n }\n\n if (newMenuItems != null) {\n if (newMenuItems instanceof Promise) {\n if (includePromises) {\n menuItems.push(newMenuItems);\n }\n } else if (Array.isArray(newMenuItems)) {\n menuItems = menuItems.concat(newMenuItems);\n } else {\n menuItems.push(newMenuItems);\n }\n }\n }\n\n menuItems = menuItems.filter(\n action =>\n (action as ContextAction).title ||\n (action as Promise<ContextAction[]>).then ||\n (action as ContextAction).menuElement\n );\n\n return menuItems;\n }\n\n /**\n * Returns the index of the next menu item in a list that doesn't have a disabled=true prop\n * @param startIndex the starting position for the iteration\n * @param delta the direction of travel, -1 or 1\n * @param menuItems an array of menuItems\n */\n static getNextMenuItem(\n startIndex: number,\n delta: -1 | 1,\n menuItems: MenuItem[]\n ): number {\n let firstIndex = startIndex;\n if (firstIndex < 0 && delta < 0) {\n // if menu index is -1 and delta -1 manually set start point\n firstIndex = menuItems.length;\n }\n // find the next non disabled menu option, iterating the list only once\n for (let i = 1; i < menuItems.length + 1; i += 1) {\n const menuIndex =\n (firstIndex + delta * i + menuItems.length) % menuItems.length;\n const item = menuItems[menuIndex];\n if (!(item instanceof Promise) && item.disabled !== true) {\n return menuIndex;\n }\n }\n return startIndex;\n }\n}\n\nexport default ContextActionUtils;\n","import React from 'react';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsChevronRight, IconDefinition } from '@deephaven/icons';\nimport type { ContextAction } from './ContextActionUtils';\n\ninterface ContextMenuItemProps {\n children?: React.ReactNode;\n closeMenu(closeAll: boolean): void;\n isKeyboardSelected?: boolean;\n isMouseSelected?: boolean;\n menuItem: ContextAction;\n onMenuItemClick(item: ContextAction, e: React.MouseEvent): void;\n onMenuItemMouseMove(item: ContextAction, e: React.MouseEvent): void;\n onMenuItemContextMenu(item: ContextAction, e: React.MouseEvent): void;\n}\n\nconst ContextMenuItem = React.forwardRef<HTMLDivElement, ContextMenuItemProps>(\n (props: ContextMenuItemProps, ref) => {\n function handleMenuItemClick(e: React.MouseEvent) {\n const { menuItem, onMenuItemClick } = props;\n onMenuItemClick(menuItem, e);\n }\n\n function handleMenuItemMouseMove(e: React.MouseEvent) {\n const { menuItem, onMenuItemMouseMove } = props;\n onMenuItemMouseMove(menuItem, e);\n }\n\n function handleMenuItemContextMenu(e: React.MouseEvent) {\n const { menuItem, onMenuItemContextMenu } = props;\n onMenuItemContextMenu(menuItem, e);\n }\n\n function renderCustomMenuElement(\n element: React.ReactElement,\n iconElement: IconDefinition | React.ReactElement | null,\n displayShortcut: string | undefined\n ): JSX.Element {\n // Don't pass forwardedProps if menuElement is a native DOM node\n if (typeof element.type === 'string') {\n return element;\n }\n const {\n closeMenu,\n menuItem,\n isKeyboardSelected,\n isMouseSelected,\n } = props;\n const forwardedProps = {\n menuItem,\n closeMenu,\n isKeyboardSelected,\n isMouseSelected,\n iconElement,\n displayShortcut,\n };\n return React.cloneElement(element, {\n forwardedProps,\n });\n }\n\n const { children, menuItem, isKeyboardSelected, isMouseSelected } = props;\n\n const displayShortcut = menuItem.shortcut?.getDisplayText();\n let icon: IconDefinition | React.ReactElement | null = null;\n if (menuItem.icon) {\n const menuItemIcon = menuItem.icon;\n if (React.isValidElement(menuItemIcon)) {\n icon = menuItemIcon;\n } else {\n let style: React.CSSProperties | undefined;\n if (menuItem.iconColor && !menuItem.disabled) {\n style = { color: menuItem.iconColor };\n }\n icon = <FontAwesomeIcon icon={menuItemIcon} style={style} />;\n }\n }\n\n let subMenuIndicator = null;\n const isSubMenuActive = !!children;\n if (menuItem.actions) {\n subMenuIndicator = <FontAwesomeIcon icon={vsChevronRight} />;\n }\n let content = null;\n if (menuItem.menuElement) {\n content = (\n <div className=\"custom-menu-item\" onMouseMove={handleMenuItemMouseMove}>\n {renderCustomMenuElement(menuItem.menuElement, icon, displayShortcut)}\n </div>\n );\n } else {\n const menuItemDisabled = menuItem.disabled;\n const iconHasOutline = menuItem.iconOutline;\n content = (\n <button\n type=\"button\"\n className={classNames(\n 'btn-context-menu',\n { disabled: menuItemDisabled },\n {\n active: (isSubMenuActive || isMouseSelected) && !menuItemDisabled,\n },\n { 'keyboard-active': isKeyboardSelected && !menuItemDisabled }\n )}\n onClick={handleMenuItemClick}\n onMouseMove={handleMenuItemMouseMove}\n onContextMenu={handleMenuItemContextMenu}\n title={menuItem.description || ''}\n >\n <div className=\"btn-context-menu-wrapper\">\n <span className={classNames('icon', { outline: iconHasOutline })}>\n {icon}\n </span>\n <span className=\"title\">{menuItem.title}</span>\n {displayShortcut && (\n <span className=\"shortcut\">{displayShortcut}</span>\n )}\n {subMenuIndicator && (\n <span\n className={classNames('submenu-indicator', {\n disabled: menuItemDisabled,\n })}\n >\n {subMenuIndicator}\n </span>\n )}\n </div>\n </button>\n );\n }\n\n return (\n <div className=\"context-menu-item\" ref={ref}>\n {children}\n {content}\n </div>\n );\n }\n);\n\nContextMenuItem.displayName = 'ContextMenuItem';\n\nContextMenuItem.defaultProps = {\n children: null,\n isKeyboardSelected: false,\n isMouseSelected: false,\n};\n\nexport default ContextMenuItem;\n","import React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport Log from '@deephaven/log';\nimport { PromiseUtils, CancelablePromise } from '@deephaven/utils';\nimport ContextActionUtils, {\n ContextAction,\n ResolvableContextAction,\n} from './ContextActionUtils';\nimport ContextMenuItem from './ContextMenuItem';\nimport LoadingSpinner from '../LoadingSpinner';\n\nconst log = Log.module('ContextMenu');\n\ninterface ContextMenuProps {\n top: number;\n left: number;\n updatePosition(top: number, left: number): void;\n // only submenus will have these, defaults to 0 otherwise\n // represents the width height of the parent menu item\n subMenuParentWidth: number;\n subMenuParentHeight: number;\n actions: ResolvableContextAction[];\n closeMenu(closeAll: boolean): void;\n onMenuClosed(menu: ContextMenu): void;\n onMenuOpened(menu: ContextMenu): void;\n options: {\n doNotVerifyPosition?: boolean;\n separateKeyboardMouse?: boolean;\n initialKeyboardIndex?: number;\n };\n menuStyle: React.CSSProperties;\n}\n\ninterface ContextMenuState {\n menuItems: ContextAction[];\n pendingItems: CancelablePromise<ContextAction[]>[];\n activeSubMenu: number | null;\n hasOverflow: boolean;\n subMenuTop: number | null;\n subMenuLeft: number | null;\n subMenuParentWidth: number;\n subMenuParentHeight: number;\n keyboardIndex: number;\n mouseIndex: number;\n}\n\n/** Do not use this class directly. Use ContextMenuRoot and ContextActions instead. */\nclass ContextMenu extends PureComponent<ContextMenuProps, ContextMenuState> {\n static defaultProps = {\n subMenuParentWidth: 0,\n subMenuParentHeight: 0,\n closeMenu(): void {\n // no-op\n },\n onMenuOpened(): void {\n // no-op\n },\n onMenuClosed(): void {\n // no-op\n },\n options: {},\n menuStyle: {},\n };\n\n static handleContextMenu(e: React.MouseEvent): void {\n if (e.metaKey) {\n return;\n }\n\n e.stopPropagation();\n e.preventDefault();\n }\n\n constructor(props: ContextMenuProps) {\n super(props);\n\n this.handleBlur = this.handleBlur.bind(this);\n this.handleCloseSubMenu = this.handleCloseSubMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleMenuItemClick = this.handleMenuItemClick.bind(this);\n this.handleMenuItemContextMenu = this.handleMenuItemContextMenu.bind(this);\n this.handleMenuItemMouseMove = this.handleMenuItemMouseMove.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleWindowResize = this.handleWindowResize.bind(this);\n\n this.container = React.createRef();\n this.oldFocus = document.activeElement;\n this.activeSubMenuRef = React.createRef();\n this.subMenuTimer = 0;\n this.rAF = 0;\n\n this.initialPosition = { top: props.top, left: props.left };\n\n this.state = {\n menuItems: [],\n pendingItems: [],\n activeSubMenu: null,\n hasOverflow: false,\n subMenuTop: null,\n subMenuLeft: null,\n subMenuParentWidth: 0,\n subMenuParentHeight: 0,\n keyboardIndex: -1,\n mouseIndex: -1,\n };\n }\n\n componentDidMount(): void {\n this.initMenu();\n\n this.verifyPosition();\n\n window.addEventListener('resize', this.handleWindowResize);\n\n // rAF is needed to wait for a submenus popper to be created before\n // attempting to set focus, however on a quick mount/unmount when\n // mousing past an item, the submenu could be unmounted before the\n // async rAF finishes, so it is cancelled in willUnmount()\n this.rAF = window.requestAnimationFrame(() => {\n this.container.current?.focus();\n\n const { onMenuOpened } = this.props;\n onMenuOpened(this);\n });\n }\n\n componentDidUpdate(\n prevProps: ContextMenuProps,\n prevState: ContextMenuState\n ): void {\n const { actions } = this.props;\n const { activeSubMenu } = this.state;\n\n if (activeSubMenu !== prevState.activeSubMenu) {\n if (activeSubMenu == null) {\n // close sub menu, refocus parent menu\n this.container.current?.focus();\n } else {\n // open sub menu, set its initial position\n this.setActiveSubMenuPosition();\n }\n }\n\n if (prevProps.actions !== actions) {\n this.initMenu();\n\n if (!this.container.current?.contains(document.activeElement)) {\n this.container.current?.focus();\n }\n }\n\n this.verifyPosition();\n }\n\n componentWillUnmount(): void {\n this.cancelPromises();\n window.removeEventListener('resize', this.handleWindowResize);\n cancelAnimationFrame(this.rAF);\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n oldFocus: Element | null;\n\n activeSubMenuRef: React.RefObject<HTMLDivElement>;\n\n subMenuTimer: number;\n\n rAF: number;\n\n initialPosition: { top: number; left: number };\n\n getKeyboardIndex(): number {\n const { options } = this.props;\n if (options.separateKeyboardMouse) {\n const { keyboardIndex } = this.state;\n return keyboardIndex;\n }\n\n return this.getMouseIndex();\n }\n\n setKeyboardIndex(index: number): void {\n const { options } = this.props;\n if (options.separateKeyboardMouse) {\n this.setState({ keyboardIndex: index });\n } else {\n this.setMouseIndex(index);\n }\n }\n\n getMouseIndex(): number {\n const { mouseIndex } = this.state;\n return mouseIndex;\n }\n\n setMouseIndex(index: number): void {\n this.setState({ mouseIndex: index });\n }\n\n initMenu(): void {\n // cancel any pending close and promises\n this.cancelPromises();\n cancelAnimationFrame(this.rAF);\n\n const { options } = this.props;\n let keyboardIndex = options.initialKeyboardIndex;\n if (keyboardIndex === undefined) {\n keyboardIndex = -1;\n }\n\n const { actions } = this.props;\n const menuItems = ContextActionUtils.getMenuItems(actions);\n const nonPromiseItems: ContextAction[] = [];\n for (let i = menuItems.length - 1; i >= 0; i -= 1) {\n const menuItem = menuItems[i];\n if (menuItem instanceof Promise) {\n this.initMenuPromise(menuItem as Promise<ContextAction[]>);\n } else {\n nonPromiseItems.push(menuItem as ContextAction);\n }\n }\n\n this.setState({\n mouseIndex: -1,\n keyboardIndex,\n activeSubMenu: null,\n menuItems: ContextActionUtils.sortActions(nonPromiseItems),\n });\n }\n\n initMenuPromise(promise: Promise<ContextAction[]>): void {\n // make all promises cancellable\n const cancellablePromise = PromiseUtils.makeCancelable(promise);\n\n this.setState(state => ({\n pendingItems: state.pendingItems.concat(cancellablePromise),\n }));\n\n cancellablePromise.then(\n resolvedMenuItems => {\n this.setState(state => {\n const index = state.pendingItems.indexOf(cancellablePromise);\n if (index >= 0) {\n const pendingItems = state.pendingItems.slice();\n pendingItems.splice(index, 1);\n\n return {\n menuItems: ContextActionUtils.sortActions(\n state.menuItems.concat(resolvedMenuItems)\n ),\n pendingItems,\n };\n }\n // This item is stale, don't update the menu\n return null;\n });\n },\n error => {\n if (PromiseUtils.isCanceled(error)) {\n return; // Canceled promise is ignored\n }\n\n // remove failed item from pending list\n this.setState(state => {\n const index = state.pendingItems.indexOf(cancellablePromise);\n if (index >= 0) {\n const pendingItems = state.pendingItems.slice();\n pendingItems.splice(index, 1);\n return {\n pendingItems,\n };\n }\n return null;\n });\n\n // Log the error\n log.error(error);\n }\n );\n }\n\n cancelPromises(): void {\n const { pendingItems } = this.state;\n pendingItems.map(item => item.cancel());\n }\n\n /**\n * Sets the unverfied start position of a submenu. Submenu then self-verfies\n * its own position and potentially reports back a new position.\n */\n setActiveSubMenuPosition(): void {\n if (this.activeSubMenuRef.current === null) return;\n const parentRect = this.activeSubMenuRef.current.getBoundingClientRect();\n\n // intentionally rect.right, we want the sub menu to start at the right edge of the current menu\n this.setState({\n subMenuTop: parentRect.top,\n subMenuLeft: parentRect.right,\n subMenuParentHeight: parentRect.height,\n subMenuParentWidth: parentRect.width,\n });\n }\n\n /**\n * Verifies the position of this menu in relation to the parent to make sure it's on screen.\n * Will update the top left state (updatePosition) if necessary (causing a re-render)\n * By default it tries to top-align with parent, at the right side of the parent.\n * Because we aren't a native context menu and can't escape window bounds, we also do\n * somethings to better fit on screen, such as the \"nudge\" offset position, and further\n * allow overflow scrolling for large menus in a small window.\n */\n verifyPosition(): void {\n const {\n options,\n updatePosition,\n subMenuParentWidth,\n subMenuParentHeight,\n top: oldTop,\n left: oldLeft,\n } = this.props;\n\n if (!this.container.current || options.doNotVerifyPosition) {\n return;\n }\n\n // initial position is used rather than current position,\n // as the number of menu items can change (actions can bubble)\n // and menu should always be positioned relative to spawn point\n let { top, left } = this.initialPosition;\n const {\n width,\n height,\n } = this.container.current?.getBoundingClientRect() ?? {\n width: 0,\n height: 0,\n };\n const hasOverflow =\n (this.container.current?.scrollHeight ?? 0) > window.innerHeight;\n\n if (height === 0 || width === 0) {\n // We don't have a height or width yet, don't bother doing anything\n return;\n }\n\n // does it fit below?\n if (top + height > window.innerHeight) {\n // can it be flipped to above? include offset if submenu (defaults to 0 if not submenu)\n if (top - height - subMenuParentHeight > 0) {\n // flip like a native menu would\n top -= height - subMenuParentHeight;\n } else {\n // still doesnt fit? okay, position at bottom edge\n top = window.innerHeight - height;\n }\n }\n\n if (left + width > window.innerWidth) {\n // less picky about left right positioning, just keep it going off to right\n left = left - width - subMenuParentWidth;\n }\n\n if (oldLeft !== left || oldTop !== top) {\n // parent owns positioning as single source of truth, ask to update props\n this.setState({ hasOverflow });\n updatePosition(top, left);\n }\n }\n\n // since window resize doesn't trigger blur, listen and close the menu\n handleWindowResize(): void {\n if (!this.container.current) {\n return;\n }\n this.closeMenu(true);\n }\n\n handleBlur(e: React.FocusEvent<HTMLDivElement>): void {\n if (!this.container.current) {\n log.warn('Container is null!');\n return;\n }\n\n if (!this.container.current.contains(e.relatedTarget as Node)) {\n let element: HTMLElement | null = e.relatedTarget as HTMLElement;\n let isContextMenuChild = false;\n while (element && !isContextMenuChild) {\n isContextMenuChild = element.hasAttribute('data-dh-context-menu');\n element = element.parentElement;\n }\n\n if (!isContextMenuChild) {\n // close all submenus on blur\n this.closeMenu(true);\n }\n }\n }\n\n /** Returns whether the specified key should remove the menu. Depends on the side the parent is on. */\n isEscapeKey(key: string): boolean {\n const { left } = this.props;\n return (\n key === 'Escape' ||\n (left < 0 && key === 'ArrowRight') ||\n key === 'ArrowLeft'\n );\n }\n\n handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>): void {\n const { menuItems } = this.state;\n const oldFocus = this.getKeyboardIndex();\n let newFocus: number | null = oldFocus;\n let openSubMenu = false;\n\n if (e.key === 'Enter' || e.key === ' ') {\n if (oldFocus >= 0 && oldFocus < menuItems.length) {\n this.handleMenuItemClick(\n menuItems[oldFocus],\n (e as React.SyntheticEvent) as React.MouseEvent\n );\n }\n return;\n }\n\n if (e.key === 'ArrowRight') {\n if (oldFocus >= 0 && oldFocus <= menuItems.length) {\n openSubMenu = true;\n } else {\n newFocus = 0;\n }\n } else if (this.isEscapeKey(e.key)) {\n newFocus = null;\n } else if (e.key === 'ArrowUp' || (e.shiftKey && e.key === 'Tab')) {\n newFocus = ContextActionUtils.getNextMenuItem(newFocus, -1, menuItems);\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n newFocus = ContextActionUtils.getNextMenuItem(newFocus, 1, menuItems);\n }\n\n if (openSubMenu) {\n this.openSubMenu(oldFocus);\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n if (oldFocus !== newFocus) {\n if (newFocus !== null) {\n this.setKeyboardIndex(newFocus);\n } else {\n this.closeMenu();\n if (this.oldFocus instanceof HTMLElement) {\n this.oldFocus.focus();\n }\n }\n\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n openSubMenu(index: number): void {\n const { menuItems, activeSubMenu } = this.state;\n const newSubMenu = menuItems[index].actions ? index : null;\n if (activeSubMenu === newSubMenu) return;\n this.setState({\n activeSubMenu: newSubMenu,\n subMenuTop: null,\n subMenuLeft: null,\n });\n }\n\n closeMenu(closeAll = false): void {\n const { closeMenu, onMenuClosed } = this.props;\n cancelAnimationFrame(this.rAF);\n this.rAF = window.requestAnimationFrame(() => {\n closeMenu(closeAll);\n onMenuClosed(this);\n });\n }\n\n closeSubMenu(): void {\n this.setState({\n activeSubMenu: null,\n });\n }\n\n handleCloseSubMenu(closeAllMenus: boolean): void {\n if (closeAllMenus) {\n this.closeMenu(true);\n } else {\n this.closeSubMenu();\n }\n }\n\n handleMenuItemClick(menuItem: ContextAction, e: React.MouseEvent): void {\n e.preventDefault();\n e.stopPropagation();\n\n const { menuItems } = this.state;\n if (menuItem != null && !menuItem.disabled) {\n if (menuItem.actions != null) {\n this.openSubMenu(menuItems.indexOf(menuItem));\n } else if (menuItem.action != null) {\n menuItem.action();\n this.closeMenu(true);\n }\n }\n }\n\n handleMenuItemContextMenu(\n menuItem: ContextAction,\n e: React.MouseEvent\n ): void {\n if (e.metaKey) {\n return;\n }\n\n this.handleMenuItemClick(menuItem, e);\n }\n\n handleMenuItemMouseMove(menuItem: ContextAction): void {\n const { menuItems } = this.state;\n const focusIndex = menuItems.indexOf(menuItem);\n this.setMouseIndex(focusIndex);\n\n if (\n focusIndex >= 0 &&\n focusIndex < menuItems.length &&\n !menuItem.disabled\n ) {\n this.openSubMenu(focusIndex);\n }\n }\n\n handleMouseLeave(): void {\n this.setMouseIndex(-1);\n }\n\n render(): JSX.Element {\n const menuItemElements = [];\n const { top, left } = this.props;\n const {\n activeSubMenu,\n hasOverflow,\n keyboardIndex,\n menuItems,\n mouseIndex,\n pendingItems,\n subMenuTop,\n subMenuLeft,\n subMenuParentWidth,\n subMenuParentHeight,\n } = this.state;\n for (let i = 0; i < menuItems.length; i += 1) {\n const menuItem = menuItems[i];\n\n if (i > 0 && menuItem.group !== menuItems[i - 1].group) {\n menuItemElements.push(<hr key={`${i}.separator`} />);\n }\n\n const menuItemElement = (\n <ContextMenuItem\n key={i}\n ref={activeSubMenu === i ? this.activeSubMenuRef : null}\n isKeyboardSelected={keyboardIndex === i}\n isMouseSelected={mouseIndex === i}\n menuItem={menuItem}\n closeMenu={this.handleCloseSubMenu}\n onMenuItemClick={this.handleMenuItemClick}\n onMenuItemMouseMove={this.handleMenuItemMouseMove}\n onMenuItemContextMenu={this.handleMenuItemContextMenu}\n />\n );\n\n menuItemElements.push(menuItemElement);\n }\n\n let pendingElement = null;\n if (pendingItems.length > 0) {\n pendingElement = (\n <div className=\"loading\">\n <LoadingSpinner />\n </div>\n );\n }\n\n const { menuStyle } = this.props;\n\n // don't show submenu until it has an position initialized\n const showSubmenu =\n activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null;\n\n return (\n <>\n <div\n className={classNames(\n { 'has-overflow': hasOverflow },\n 'context-menu-container'\n )}\n style={{ top, left, ...menuStyle }}\n ref={this.container}\n data-dh-context-menu\n onBlur={this.handleBlur}\n onKeyDown={this.handleKeyDown}\n onMouseLeave={this.handleMouseLeave}\n onContextMenu={ContextMenu.handleContextMenu}\n role=\"menuitem\"\n tabIndex={0}\n >\n {menuItemElements}\n {pendingElement}\n </div>\n {showSubmenu &&\n activeSubMenu !== null &&\n subMenuTop !== null &&\n subMenuLeft !== null && (\n <ContextMenu\n key={`sub-${activeSubMenu}`}\n actions={menuItems[activeSubMenu].actions || []}\n closeMenu={this.handleCloseSubMenu}\n top={subMenuTop}\n left={subMenuLeft}\n updatePosition={(verifiedTop, verifiedLeft) => {\n this.setState({\n subMenuTop: verifiedTop,\n subMenuLeft: verifiedLeft,\n });\n }}\n subMenuParentWidth={subMenuParentWidth}\n subMenuParentHeight={subMenuParentHeight}\n />\n )}\n </>\n );\n }\n}\n\nexport default ContextMenu;\n","import React, { Component } from 'react';\nimport classNames from 'classnames';\nimport ContextMenu from './ContextMenu';\nimport ContextActionUtils, { MenuItem } from './ContextActionUtils';\n\ntype ContextMenuRootProps = Record<string, never>;\n\ninterface ContextMenuRootState {\n actions: MenuItem[] | null;\n left: number;\n top: number;\n}\n\n/**\n * Put at your root container, any contextmenu events that are unhandled in the root container will be handled by this\n */\nclass ContextMenuRoot extends Component<\n ContextMenuRootProps,\n ContextMenuRootState\n> {\n constructor(props: ContextMenuRootProps) {\n super(props);\n\n this.handleMenuClose = this.handleMenuClose.bind(this);\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.container = React.createRef();\n this.openMenu = React.createRef();\n\n this.state = {\n actions: null,\n left: 0,\n top: 0,\n };\n }\n\n componentDidMount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.addEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n }\n }\n\n componentWillUnmount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.removeEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n }\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n openMenu: React.RefObject<ContextMenu>;\n\n handleContextMenu(e: MouseEvent): void {\n if (!ContextActionUtils.isContextActionEvent(e)) {\n return;\n }\n\n if (!this.container.current) {\n return;\n }\n\n if (e.metaKey || e.ctrlKey) {\n // debug escape hatch to native menu\n return;\n }\n\n const contextActions = ContextActionUtils.getMenuItems(e.contextActions);\n\n const parentRect = this.container.current.getBoundingClientRect();\n const top = e.clientY - parentRect.top;\n const left = e.clientX - parentRect.left;\n\n if (contextActions.length === 0) {\n // This code path seems to only exist for Chrome on Mac\n // Mac appears to trigger contextmenu events on mousedown vs. mouseup on Windows\n // Mouseup on Windows triggers blur before contextmenu which effectively does what this path does\n if (e.target === this.container.current) {\n // re-emit right clicks that hit the context-root blocking layer\n e.preventDefault();\n\n // Set actions to null removes the menu\n // That allows a new menu to be opened on a different element so initial position is set properly\n // Otherwise the instance of this menu may be reused\n // A new contextmenu event is triggered on the element at the location the user clicked on the blocking layer\n this.setState({ actions: null }, () => {\n const element = document.elementFromPoint(left, top); // x y\n\n const mouseEvent = new MouseEvent('contextmenu', {\n clientX: e.clientX,\n clientY: e.clientY,\n bubbles: true,\n cancelable: true,\n });\n\n element?.dispatchEvent(mouseEvent);\n });\n return;\n }\n\n // target was a menu item\n return;\n }\n\n // new clicks, set actions\n e.preventDefault();\n this.setState({\n actions: contextActions,\n top,\n left,\n });\n }\n\n handleMenuClose(menu: ContextMenu): void {\n if (menu === this.openMenu.current) {\n this.setState({ actions: null });\n }\n }\n\n render(): JSX.Element {\n let menu = null;\n const { actions, top, left } = this.state;\n if (actions) {\n menu = (\n <ContextMenu\n ref={this.openMenu}\n actions={actions}\n onMenuClosed={this.handleMenuClose}\n top={top}\n left={left}\n updatePosition={(verifiedTop, verifiedLeft) => {\n this.setState({ top: verifiedTop, left: verifiedLeft });\n }}\n />\n );\n }\n return (\n <div\n className={classNames('context-menu-root', { active: actions })}\n ref={this.container}\n >\n {menu}\n </div>\n );\n }\n}\n\nexport default ContextMenuRoot;\n","// The Deephaven API script isn't packaged as a module (yet), and is just included in index.html, exported to the global namespace\n// This include file is simply a wrapper so that it behaves like a module, and can be mocked easily for unit tests.\n// https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#using-global-variables\nimport type dhType from './dh.types';\n\ndeclare global {\n // eslint-disable-next-line vars-on-top,no-var\n var dh: dhType;\n}\n\nconst { dh } = globalThis;\n\nexport default dh;\n","import PropTypes from 'prop-types';\n\nconst Column = PropTypes.shape({\n name: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n description: PropTypes.string,\n constituentType: PropTypes.string,\n});\n\nconst FilterCondition = PropTypes.shape({\n not: PropTypes.func.isRequired,\n and: PropTypes.func.isRequired,\n or: PropTypes.func.isRequired,\n});\n\nconst Sort = PropTypes.shape({\n asc: PropTypes.func.isRequired,\n desc: PropTypes.func.isRequired,\n abs: PropTypes.func.isRequired,\n column: Column.isRequired,\n direction: PropTypes.string.isRequired,\n isAbs: PropTypes.bool.isRequired,\n});\n\nconst Table = PropTypes.shape({\n columns: PropTypes.arrayOf(Column).isRequired,\n customColumns: PropTypes.arrayOf(PropTypes.string).isRequired,\n filter: PropTypes.arrayOf(FilterCondition),\n addEventListener: PropTypes.func.isRequired,\n removeEventListener: PropTypes.func.isRequired,\n size: PropTypes.number.isRequired,\n sort: PropTypes.arrayOf(PropTypes.any),\n copy: PropTypes.func.isRequired,\n applyFilter: PropTypes.func.isRequired,\n applySort: PropTypes.func.isRequired,\n applyCustomColumns: PropTypes.func.isRequired,\n description: PropTypes.string,\n});\n\nconst TreeTable = PropTypes.shape({\n columns: PropTypes.arrayOf(Column),\n filter: PropTypes.arrayOf(PropTypes.any),\n isExpanded: PropTypes.func.isRequired,\n saveExpandedState: PropTypes.func.isRequired,\n addEventListener: PropTypes.func.isRequired,\n removeEventListener: PropTypes.func.isRequired,\n size: PropTypes.number.isRequired,\n sort: PropTypes.arrayOf(PropTypes.any),\n applyFilter: PropTypes.func.isRequired,\n applySort: PropTypes.func.isRequired,\n});\n\nconst VariableDefinition = PropTypes.shape({\n name: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n});\n\nconst VariableChanges = PropTypes.shape({\n created: PropTypes.arrayOf(VariableDefinition).isRequired,\n updated: PropTypes.arrayOf(VariableDefinition).isRequired,\n removed: PropTypes.arrayOf(VariableDefinition).isRequired,\n});\n\nconst RollupConfig = PropTypes.shape({\n groupingColumns: PropTypes.arrayOf(PropTypes.string),\n aggregations: PropTypes.shape({}),\n includeConstituents: PropTypes.bool,\n includeOriginalColumns: PropTypes.bool,\n includeDescriptions: PropTypes.bool,\n});\n\nconst IdeSession = PropTypes.shape({\n addEventListener: PropTypes.func.isRequired,\n removeEventListener: PropTypes.func.isRequired,\n onLogMessage: PropTypes.func,\n getTable: PropTypes.func.isRequired,\n runCode: PropTypes.func.isRequired,\n});\n\nconst DhPropTypes = Object.freeze({\n Column,\n FilterCondition,\n IdeSession,\n RollupConfig,\n Sort,\n Table,\n TreeTable,\n VariableChanges,\n VariableDefinition,\n});\n\nexport default DhPropTypes;\n","import dh from '@deephaven/jsapi-shim';\nimport type { DateWrapper } from '@deephaven/jsapi-shim';\n\ninterface DateParts<T> {\n year: T;\n month: T;\n date: T;\n hours: T;\n minutes: T;\n seconds: T;\n nanos: T;\n}\n\nclass DateUtils {\n static FULL_DATE_FORMAT = 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS';\n\n static months = [\n 'january',\n 'february',\n 'march',\n 'april',\n 'may',\n 'june',\n 'july',\n 'august',\n 'september',\n 'october',\n 'november',\n 'december',\n ];\n\n /**\n *\n * @param timeZone The time zone to parse this time in. E.g. America/New_York\n * @param year The year for the date\n * @param month The month, starting at 0\n * @param day The day, starting at 1\n * @param hour The hours\n * @param minute The minutes\n * @param second The seconds\n * @param ns The nanoseconds\n */\n static makeDateWrapper(\n timeZone: string,\n year: number,\n month = 0,\n day = 1,\n hour = 0,\n minute = 0,\n second = 0,\n ns = 0\n ): DateWrapper {\n const yearString = `${year}`.padStart(4, '0');\n const monthString = `${month + 1}`.padStart(2, '0');\n const dayString = `${day}`.padStart(2, '0');\n const hourString = `${hour}`.padStart(2, '0');\n const minuteString = `${minute}`.padStart(2, '0');\n const secondString = `${second}`.padStart(2, '0');\n const nanoString = `${ns}`.padStart(9, '0');\n\n const dateString = `${yearString}-${monthString}-${dayString} ${hourString}:${minuteString}:${secondString}.${nanoString}`;\n return dh.i18n.DateTimeFormat.parse(\n DateUtils.FULL_DATE_FORMAT,\n dateString,\n dh.i18n.TimeZone.getTimeZone(timeZone)\n );\n }\n\n /**\n * Takes the string the user entered and returns the next nanos value\n * @param nanoString The nano string to get the next one of\n * @returns The value of the next nanos\n */\n static getNextNanos(nanoString: string): number {\n const sigNanos = parseInt(nanoString, 10);\n // Get the zeroes needed for padding before adding one so we handle overflow properly.\n const zeros = '0'.repeat(9 - nanoString.length);\n const nextNanoString = `${sigNanos + 1}${zeros}`;\n return parseInt(nextNanoString, 10);\n }\n\n /**\n * @param components The string components that were parsed from the original string\n * @param values The values that were parsed from the components\n * @param timeZone The time zone to parse the date in. E.g. America/New_York\n * @returns Returns the DateWrapper for the next date, or null if a full date was passed in\n */\n static getNextDate(\n components: DateParts<string>,\n values: DateParts<number>,\n timeZone: string\n ): DateWrapper | null {\n let { year, month, date, hours, minutes, seconds, nanos } = values;\n\n if (components.nanos != null) {\n if (components.nanos.length === 9) {\n // They want an exact match\n return null;\n }\n nanos = DateUtils.getNextNanos(components.nanos);\n if (nanos > 999999999) {\n // There's an overflow, add it to the seconds manually\n seconds += 1;\n nanos = 0;\n }\n } else if (components.seconds != null) {\n seconds += 1;\n } else if (components.minutes != null) {\n minutes += 1;\n } else if (components.hours != null) {\n hours += 1;\n } else if (components.date != null) {\n date += 1;\n } else if (components.month != null) {\n month += 1;\n } else {\n year += 1;\n }\n\n // Use the JS date to handle overflow rather than doing our own logic\n // Because handling leap years and stuff is a pain\n // Still need to add nanos after, and the overflow from that is already added to seconds above\n const jsDate = new Date(year, month, date, hours, minutes, seconds);\n return DateUtils.makeDateWrapper(\n timeZone,\n jsDate.getFullYear(),\n jsDate.getMonth(),\n jsDate.getDate(),\n jsDate.getHours(),\n jsDate.getMinutes(),\n jsDate.getSeconds(),\n nanos\n );\n }\n\n /**\n * Get the JS month value for the provided string.\n * Matches digits or a month name (eg. '1', '01', 'jan', 'january' should all work)\n * @param monthString The string to parse to a JS month value\n * @returns number The JS month value, which starts at 0 for january, or NaN if nothing could be parsed\n */\n static parseMonth(monthString: string): number {\n const month = parseInt(monthString, 10);\n if (!Number.isNaN(month)) {\n if (month >= 1 && month <= 12) {\n return month - 1;\n }\n return NaN;\n }\n\n const cleanMonthString = monthString.trim().toLowerCase();\n if (cleanMonthString.length >= 3) {\n for (let i = 0; i < DateUtils.months.length; i += 1) {\n if (DateUtils.months[i].startsWith(cleanMonthString)) {\n return i;\n }\n }\n }\n\n return NaN;\n }\n\n /**\n * Parse a date object out of the provided string segments.\n * Also using `parseMonth` to get month names like Aug/August rather than\n * simply doing `parseInt`.\n * @param yearString The year part of the string\n * @param monthString The month part of the string\n * @param dayString The day part of the string\n * @param hourString The hour part of the string\n * @param minuteString The minute part of the string\n * @param secondString The second part of the string\n * @param nanoString The milli part of the string\n */\n static parseDateValues(\n yearString: string,\n monthString: string,\n dayString: string,\n hourString: string,\n minuteString: string,\n secondString: string,\n nanoString: string\n ): DateParts<number> | null {\n const year = parseInt(yearString, 10);\n const month = monthString != null ? this.parseMonth(monthString) : 0;\n const date = dayString != null ? parseInt(dayString, 10) : 1;\n const hours = hourString != null ? parseInt(hourString, 10) : 0;\n const minutes = minuteString != null ? parseInt(minuteString, 10) : 0;\n const seconds = secondString != null ? parseInt(secondString, 10) : 0;\n const nanos =\n nanoString != null ? parseInt(nanoString.padEnd(9, '0'), 10) : 0;\n if (\n Number.isNaN(year) ||\n Number.isNaN(month) ||\n Number.isNaN(date) ||\n Number.isNaN(hours) ||\n Number.isNaN(minutes) ||\n Number.isNaN(seconds) ||\n Number.isNaN(nanos)\n ) {\n return null;\n }\n\n return { year, month, date, hours, minutes, seconds, nanos };\n }\n\n /**\n * Parse out a date time string into it's string components.\n * Anything that is not captured in the string will be undefined.\n *\n * @param dateTimeString The date time string to parse\n * @returns Containing the date time components\n */\n static parseDateTimeString(dateTimeString: string): DateParts<string> {\n const regex = /\\s*(\\d{4})([-./]([\\da-z]+))?([-./](\\d{1,2}))?([tT\\s](\\d{2})([:](\\d{2}))?([:](\\d{2}))?([.](\\d{1,9}))?)?(.*)/;\n const result = regex.exec(dateTimeString);\n if (result == null) {\n throw new Error(`Unexpected date string: ${dateTimeString}`);\n }\n\n const [\n ,\n year,\n ,\n month,\n ,\n date,\n ,\n hours,\n ,\n minutes,\n ,\n seconds,\n ,\n nanos,\n overflow,\n ] = result;\n if (overflow != null && overflow.length > 0) {\n throw new Error(\n `Unexpected characters after date string '${dateTimeString}': ${overflow}`\n );\n }\n\n return { year, month, date, hours, minutes, seconds, nanos };\n }\n\n /**\n * Parses the date range provided from a string of text.\n * @param text The string to parse the date from. Can be a keyword like \"today\", or in the format \"2018-08-04\"\n * @param timeZone The time zone to parse this range in. E.g. America/New_York\n * @returns A tuple with the start and end value/null for that date range, or both null\n */\n static parseDateRange(\n text: string,\n timeZone: string\n ): [DateWrapper, DateWrapper | null] | [null, null] {\n const cleanText = text.trim().toLowerCase();\n if (cleanText.length === 0) {\n throw new Error('Cannot parse date range from empty string');\n }\n\n if (cleanText === 'null') {\n return [null, null];\n }\n\n if (cleanText === 'today') {\n const now = new Date(Date.now());\n const startDate = DateUtils.makeDateWrapper(\n timeZone,\n now.getFullYear(),\n now.getMonth(),\n now.getDate()\n );\n const endDate = DateUtils.makeDateWrapper(\n timeZone,\n now.getFullYear(),\n now.getMonth(),\n now.getDate() + 1\n );\n return [startDate, endDate];\n }\n\n if (cleanText === 'yesterday') {\n const now = new Date(Date.now());\n const startDate = DateUtils.makeDateWrapper(\n timeZone,\n now.getFullYear(),\n now.getMonth(),\n now.getDate() - 1\n );\n const endDate = DateUtils.makeDateWrapper(\n timeZone,\n now.getFullYear(),\n now.getMonth(),\n now.getDate()\n );\n return [startDate, endDate];\n }\n\n if (cleanText === 'now') {\n const now = new Date(Date.now());\n const date = dh.DateWrapper.ofJsDate(now);\n return [date, null];\n }\n\n const components = DateUtils.parseDateTimeString(cleanText);\n if (\n components.year == null &&\n components.month == null &&\n components.date == null\n ) {\n throw new Error(`Unable to extract year, month, or day ${cleanText}`);\n }\n\n const values = DateUtils.parseDateValues(\n components.year,\n components.month,\n components.date,\n components.hours,\n components.minutes,\n components.seconds,\n components.nanos\n );\n\n if (values == null) {\n throw new Error(`Unable to extract date values from ${components}`);\n }\n\n const startDate = DateUtils.makeDateWrapper(\n timeZone,\n values.year,\n values.month,\n values.date,\n values.hours,\n values.minutes,\n values.seconds,\n values.nanos\n );\n\n const endDate = DateUtils.getNextDate(components, values, timeZone);\n return [startDate, endDate];\n }\n\n /**\n * Gets the Js Date object from the provided DateWrapper.\n * In unit test, DateWrapper is just a number provided in millis, so handles that case.\n * @param dateWrapper The DateWrapper object, or time in millis\n */\n static getJsDate(dateWrapper: DateWrapper | number): Date {\n if (typeof dateWrapper === 'number') {\n return new Date(dateWrapper);\n }\n return dateWrapper.asDate();\n }\n}\n\nexport default DateUtils;\n","/** Different filter conditions user can select */\nexport class FilterType {\n static readonly eq = 'eq';\n\n static readonly eqIgnoreCase = 'eqIgnoreCase';\n\n static readonly notEq = 'notEq';\n\n static readonly notEqIgnoreCase = 'notEqIgnoreCase';\n\n static readonly greaterThan = 'greaterThan';\n\n static readonly greaterThanOrEqualTo = 'greaterThanOrEqualTo';\n\n static readonly lessThan = 'lessThan';\n\n static readonly lessThanOrEqualTo = 'lessThanOrEqualTo';\n\n static readonly in = 'in';\n\n static readonly inIgnoreCase = 'inIgnoreCase';\n\n static readonly notIn = 'notIn';\n\n static readonly notInIgnoreCase = 'notInIgnoreCase';\n\n static readonly isTrue = 'isTrue';\n\n static readonly isFalse = 'isFalse';\n\n static readonly isNull = 'isNull';\n\n static readonly invoke = 'invoke';\n\n static readonly contains = 'contains';\n\n static readonly notContains = 'notContains';\n\n static readonly startsWith = 'startsWith';\n\n static readonly endsWith = 'endsWith';\n\n static readonly containsAny = 'containsAny';\n}\n\nexport type FilterTypeValue = typeof FilterType[Exclude<\n keyof typeof FilterType,\n 'prototype'\n>];\n","export class FilterOperator {\n static readonly not = 'not';\n\n static readonly and = 'and';\n\n static readonly or = 'or';\n}\n\nexport type FilterOperatorValue = typeof FilterOperator[Exclude<\n keyof typeof FilterOperator,\n 'prototype'\n>];\n","import Log from '@deephaven/log';\nimport dh, {\n Column,\n FilterCondition,\n FilterValue,\n LongWrapper,\n RemoverFn,\n Sort,\n Table,\n TreeTable,\n} from '@deephaven/jsapi-shim';\nimport {\n CancelablePromise,\n PromiseUtils,\n TextUtils,\n TimeoutError,\n} from '@deephaven/utils';\nimport DateUtils from './DateUtils';\nimport {\n FilterType,\n FilterOperator,\n FilterTypeValue,\n FilterOperatorValue,\n} from './filters';\nimport type { AdvancedFilterCreatorFilterItemState } from './AdvancedFilterCreatorFilterItem';\n\nconst log = Log.module('TableUtils');\n\ntype Values<T> = T[keyof T];\nexport type DataType = Values<typeof TableUtils.dataType>;\nexport type SortDirection = Values<typeof TableUtils.sortDirection>;\n\n/** Utility class to provide some functions for working with tables */\nclass TableUtils {\n static dataType = {\n BOOLEAN: 'boolean',\n CHAR: 'char',\n DATETIME: 'datetime',\n DECIMAL: 'decimal',\n INT: 'int',\n STRING: 'string',\n } as const;\n\n static sortDirection = {\n ascending: 'ASC',\n descending: 'DESC',\n reverse: 'REVERSE',\n none: null,\n } as const;\n\n static REVERSE_TYPE = Object.freeze({\n NONE: 'none',\n PRE_SORT: 'pre-sort',\n POST_SORT: 'post-sort',\n } as const);\n\n // Regex looking for a negative or positive integer or decimal number\n static NUMBER_REGEX = /^-?\\d+(\\.\\d+)?$/;\n\n static getSortIndex(sort: Sort[], columnIndex: number): number | null {\n for (let i = 0; i < sort.length; i += 1) {\n const s = sort[i];\n if (s.column?.index === columnIndex) {\n return i;\n }\n }\n\n return null;\n }\n\n /**\n * @param tableSort The sorts from the table to get the sort from\n * @param columnIndex The index of the column to get the sort for\n * @return The sort for the column, or null if it's not sorted\n */\n static getSortForColumn(tableSort: Sort[], columnIndex: number): Sort | null {\n const sortIndex = TableUtils.getSortIndex(tableSort, columnIndex);\n if (sortIndex != null) {\n return tableSort[sortIndex];\n }\n return null;\n }\n\n static getFilterText(filter: FilterCondition): string | null {\n if (filter) {\n return filter.toString();\n }\n return null;\n }\n\n /** Return the valid filter types for the column */\n static getFilterTypes(columnType: string): FilterType[] {\n if (TableUtils.isBooleanType(columnType)) {\n return [FilterType.isTrue, FilterType.isFalse, FilterType.isNull];\n }\n // TODO (DH-11799): In Bard (and beyond), we should use the same types as numbers\n // It should just work after the merge for DH-11040: https://gitlab.eng.illumon.com/illumon/iris/merge_requests/5801\n // In Powell though, just support equals/not equals\n if (TableUtils.isCharType(columnType)) {\n return [FilterType.eq, FilterType.notEq];\n }\n if (\n TableUtils.isNumberType(columnType) ||\n TableUtils.isDateType(columnType)\n ) {\n return [\n FilterType.eq,\n FilterType.notEq,\n FilterType.greaterThan,\n FilterType.greaterThanOrEqualTo,\n FilterType.lessThan,\n FilterType.lessThanOrEqualTo,\n ];\n }\n if (TableUtils.isTextType(columnType)) {\n return [\n FilterType.eq,\n FilterType.eqIgnoreCase,\n FilterType.notEq,\n FilterType.notEqIgnoreCase,\n FilterType.contains,\n FilterType.notContains,\n FilterType.startsWith,\n FilterType.endsWith,\n ];\n }\n return [];\n }\n\n static getNextSort(table: Table, columnIndex: number): Sort | null {\n if (\n !table ||\n !table.columns ||\n columnIndex < 0 ||\n columnIndex >= table.columns.length\n ) {\n return null;\n }\n\n const sort = TableUtils.getSortForColumn(table.sort, columnIndex);\n if (sort === null) {\n return table.columns[columnIndex].sort().asc();\n }\n if (sort.direction === TableUtils.sortDirection.ascending) {\n return sort.desc();\n }\n return null;\n }\n\n static makeColumnSort(\n table: Table,\n columnIndex: number,\n direction: SortDirection,\n isAbs: boolean\n ): Sort | null {\n if (\n !table ||\n !table.columns ||\n columnIndex < 0 ||\n columnIndex >= table.columns.length\n ) {\n return null;\n }\n\n if (direction === TableUtils.sortDirection.none) {\n return null;\n }\n\n let sort = table.columns[columnIndex].sort();\n\n switch (direction) {\n case TableUtils.sortDirection.ascending:\n sort = sort.asc();\n break;\n case TableUtils.sortDirection.descending:\n sort = sort.desc();\n break;\n default:\n break;\n }\n if (isAbs) {\n sort = sort.abs();\n }\n return sort;\n }\n\n /**\n * Toggles the sort for the specified column\n * @param sorts The current sorts from IrisGrid.state\n * @param table The table to apply the sort to\n * @param columnIndex The column index to apply the sort to\n * @param addToExisting Add this sort to the existing sort\n */\n static toggleSortForColumn(\n sorts: Sort[],\n table: Table,\n columnIndex: number,\n addToExisting = false\n ): Sort[] {\n if (!table || columnIndex < 0 || columnIndex >= table.columns.length) {\n return [];\n }\n\n const newSort = TableUtils.getNextSort(table, columnIndex);\n\n return TableUtils.setSortForColumn(\n sorts,\n columnIndex,\n newSort,\n addToExisting\n );\n }\n\n static sortColumn(\n table: Table,\n modelColumn: number,\n direction: SortDirection,\n isAbs: boolean,\n addToExisting: boolean\n ): Sort[] {\n if (!table || modelColumn < 0 || modelColumn >= table.columns.length) {\n return [];\n }\n\n const newSort = TableUtils.makeColumnSort(\n table,\n modelColumn,\n direction,\n isAbs\n );\n\n return TableUtils.setSortForColumn(\n table.sort,\n modelColumn,\n newSort,\n addToExisting\n );\n }\n\n /**\n * Sets the sort for the given column *and* removes any reverses\n * @param tableSort The current sorts from IrisGrid.state\n * @param columnIndex The column index to apply the sort to\n * @param sort The sort object to add\n * @param addToExisting Add this sort to the existing sort\n * @returns Returns the modified array of sorts - removing reverses\n */\n static setSortForColumn(\n tableSort: Sort[],\n columnIndex: number,\n sort: Sort | null,\n addToExisting = false\n ): Sort[] {\n const sortIndex = TableUtils.getSortIndex(tableSort, columnIndex);\n let sorts: Sort[] = [];\n if (addToExisting) {\n sorts = sorts.concat(\n tableSort.filter(\n ({ direction }) => direction !== TableUtils.sortDirection.reverse\n )\n );\n if (sortIndex !== null) {\n sorts.splice(sortIndex, 1);\n }\n }\n\n if (sort !== null) {\n sorts.push(sort);\n }\n\n return sorts;\n }\n\n static getNormalizedType(columnType: string): DataType | null {\n switch (columnType) {\n case 'boolean':\n case 'java.lang.Boolean':\n case TableUtils.dataType.BOOLEAN:\n return TableUtils.dataType.BOOLEAN;\n case 'char':\n case 'java.lang.Character':\n case TableUtils.dataType.CHAR:\n return TableUtils.dataType.CHAR;\n case 'java.lang.String':\n case TableUtils.dataType.STRING:\n return TableUtils.dataType.STRING;\n case 'io.deephaven.db.tables.utils.DBDateTime':\n case 'io.deephaven.time.DateTime':\n case 'com.illumon.iris.db.tables.utils.DBDateTime':\n case TableUtils.dataType.DATETIME:\n return TableUtils.dataType.DATETIME;\n case 'double':\n case 'java.lang.Double':\n case 'float':\n case 'java.lang.Float':\n case TableUtils.dataType.DECIMAL:\n return TableUtils.dataType.DECIMAL;\n case 'int':\n case 'java.lang.Integer':\n case 'long':\n case 'java.lang.Long':\n case 'short':\n case 'java.lang.Short':\n case 'byte':\n case 'java.lang.Byte':\n case TableUtils.dataType.INT:\n return TableUtils.dataType.INT;\n default:\n return null;\n }\n }\n\n static isLongType(columnType: string): boolean {\n switch (columnType) {\n case 'long':\n case 'java.lang.Long':\n return true;\n default:\n return false;\n }\n }\n\n static isDateType(columnType: string): boolean {\n switch (columnType) {\n case 'io.deephaven.db.tables.utils.DBDateTime':\n case 'io.deephaven.time.DateTime':\n case 'com.illumon.iris.db.tables.utils.DBDateTime':\n return true;\n default:\n return false;\n }\n }\n\n static isNumberType(columnType: string): boolean {\n return (\n TableUtils.isIntegerType(columnType) ||\n TableUtils.isDecimalType(columnType)\n );\n }\n\n static isIntegerType(columnType: string): boolean {\n switch (columnType) {\n case 'int':\n case 'java.lang.Integer':\n case 'java.math.BigInteger':\n case 'long':\n case 'java.lang.Long':\n case 'short':\n case 'java.lang.Short':\n case 'byte':\n case 'java.lang.Byte':\n return true;\n default:\n return false;\n }\n }\n\n static isDecimalType(columnType: string): boolean {\n switch (columnType) {\n case 'double':\n case 'java.lang.Double':\n case 'java.math.BigDecimal':\n case 'float':\n case 'java.lang.Float':\n return true;\n default:\n return false;\n }\n }\n\n static isBooleanType(columnType: string): boolean {\n switch (columnType) {\n case 'boolean':\n case 'java.lang.Boolean':\n return true;\n default:\n return false;\n }\n }\n\n static isCharType(columnType: string): boolean {\n switch (columnType) {\n case 'char':\n case 'java.lang.Character':\n return true;\n default:\n return false;\n }\n }\n\n static isTextType(columnType: string): boolean {\n switch (columnType) {\n case 'char':\n case 'java.lang.Character':\n case 'java.lang.String':\n return true;\n default:\n return false;\n }\n }\n\n /**\n * Get base column type\n * @param columnType Column type\n * @returns Element type for array columns, original type for non-array columns\n */\n static getBaseType(columnType: string): string {\n return columnType.split('[]')[0];\n }\n\n /**\n * Check if the column types are compatible\n * @param type1 Column type to check\n * @param type2 Column type to check\n * @returns True, if types are compatible\n */\n static isCompatibleType(type1: string, type2: string): boolean {\n return (\n TableUtils.getNormalizedType(type1) ===\n TableUtils.getNormalizedType(type2)\n );\n }\n\n /**\n * Create filter with the provided column and text. Handles multiple filters joined with && or ||\n * @param column The column to set the filter on\n * @param text The text string to create the filter from\n * @param timeZone The time zone to make this value in if it is a date type. E.g. America/New_York\n * @returns Returns the created filter, null if text could not be parsed\n */\n static makeQuickFilter(\n column: Column,\n text: string,\n timeZone: string\n ): FilterCondition | null {\n const orComponents = text.split('||');\n let orFilter = null;\n for (let i = 0; i < orComponents.length; i += 1) {\n const orComponent = orComponents[i];\n const andComponents = orComponent.split('&&');\n let andFilter = null;\n for (let j = 0; j < andComponents.length; j += 1) {\n const andComponent = andComponents[j].trim();\n if (andComponent.length > 0) {\n const filter = TableUtils.makeQuickFilterFromComponent(\n column,\n andComponent,\n timeZone\n );\n if (filter) {\n if (andFilter) {\n andFilter = andFilter.and(filter);\n } else {\n andFilter = filter;\n }\n } else {\n throw new Error(`Unable to parse quick filter from text ${text}`);\n }\n }\n }\n\n if (orFilter && andFilter) {\n orFilter = orFilter.or(andFilter);\n } else {\n orFilter = andFilter;\n }\n }\n\n return orFilter;\n }\n\n /**\n * Create filter with the provided column and text of one component (no multiple conditions)\n * @param column The column to set the filter on\n * @param text The text string to create the filter from\n * @param timeZone The time zone to make this filter in if it is a date type. E.g. America/New_York\n * @returns Returns the created filter, null if text could not be parsed\n */\n static makeQuickFilterFromComponent(\n column: Column,\n text: string,\n timeZone: string\n ): FilterCondition | null {\n const { type } = column;\n if (TableUtils.isNumberType(type)) {\n return this.makeQuickNumberFilter(column, text);\n }\n if (TableUtils.isBooleanType(type)) {\n return this.makeQuickBooleanFilter(column, text);\n }\n if (TableUtils.isDateType(type)) {\n return this.makeQuickDateFilter(column, text, timeZone);\n }\n if (TableUtils.isCharType(type)) {\n return this.makeQuickCharFilter(column, text);\n }\n return this.makeQuickTextFilter(column, text);\n }\n\n static makeQuickNumberFilter(\n column: Column,\n text: string\n ): FilterCondition | null {\n if (text == null) {\n return null;\n }\n\n const columnFilter = column.filter();\n let filter = null;\n\n const regex = /\\s*(>=|<=|=>|=<|>|<|!=|=|!)?(\\s*-\\s*)?(\\s*\\d*(?:,\\d{3})*(?:\\.\\d*)?\\s*)?(null|nan|infinity|inf|\\u221E)?(.*)/i;\n const result = regex.exec(text);\n\n let operation = null;\n let negativeSign = null;\n let value = null;\n let abnormalValue = null; // includes nan, null and infinity(positive & negative)\n let overflow = null;\n\n if (result !== null && result.length > 3) {\n [, operation, negativeSign, value, abnormalValue, overflow] = result;\n }\n\n if (overflow != null && overflow.trim().length > 0) {\n // Some bad characters after the number, bail out!\n return null;\n }\n\n if (operation == null) {\n operation = '=';\n }\n\n if (abnormalValue != null) {\n if (!(operation === '=' || operation === '!' || operation === '!=')) {\n // only equal and not equal operations are supported for abnormal value filter\n return null;\n }\n abnormalValue = abnormalValue.trim().toLowerCase();\n switch (abnormalValue) {\n case 'null':\n filter = columnFilter.isNull();\n break;\n case 'nan':\n filter = dh.FilterCondition.invoke('isNaN', columnFilter);\n break;\n case 'infinity':\n case 'inf':\n case '\\u221E':\n if (negativeSign != null) {\n filter = dh.FilterCondition.invoke('isInf', columnFilter).and(\n columnFilter.lessThan(dh.FilterValue.ofNumber(0))\n );\n } else {\n filter = dh.FilterCondition.invoke('isInf', columnFilter).and(\n columnFilter.greaterThan(dh.FilterValue.ofNumber(0))\n );\n }\n break;\n default:\n break;\n }\n if (filter !== null && (operation === '!' || operation === '!=')) {\n filter = filter.not();\n }\n return filter;\n }\n\n if (value == null) {\n return null;\n }\n\n value = TableUtils.removeCommas(value);\n if (TableUtils.isLongType(column.type)) {\n try {\n value = dh.FilterValue.ofNumber(\n dh.LongWrapper.ofString(`${negativeSign != null ? '-' : ''}${value}`)\n );\n } catch (error) {\n log.warn('Unable to create long filter', error);\n return null;\n }\n } else {\n value = parseFloat(value);\n if (value == null || Number.isNaN(value)) {\n return null;\n }\n\n value = dh.FilterValue.ofNumber(negativeSign != null ? 0 - value : value);\n }\n\n filter = column.filter();\n\n return TableUtils.makeRangeFilterWithOperation(filter, operation, value);\n }\n\n static makeQuickTextFilter(\n column: Column,\n text: string | null\n ): FilterCondition | null {\n if (text == null) {\n return null;\n }\n\n const cleanText = `${text}`.trim();\n const regex = /^(!~|!=|~|=|!)?(.*)/;\n const result = regex.exec(cleanText);\n\n let operation = null;\n let value = null;\n if (result !== null && result.length > 2) {\n [, operation, value] = result;\n if (value != null) {\n value = value.trim();\n }\n }\n\n if (value == null || value.length === 0) {\n return null;\n }\n\n if (operation == null) {\n operation = '=';\n }\n\n const filter = column.filter();\n if (value.toLowerCase() === 'null') {\n // Null is a special case!\n switch (operation) {\n case '=':\n return filter.isNull();\n case '!=':\n case '!':\n return filter.isNull().not();\n default:\n return null;\n }\n }\n\n let prefix = null;\n let suffix = null;\n if (value.startsWith('*')) {\n prefix = '*';\n value = value.substring(1);\n } else if (value.endsWith('*') && !value.endsWith('\\\\*')) {\n suffix = '*';\n value = value.substring(0, value.length - 1);\n }\n\n value = value.replace('\\\\', '');\n\n switch (operation) {\n case '~': {\n return filter\n .isNull()\n .not()\n .and(\n filter.invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E.*`)\n )\n );\n }\n case '!~':\n return filter\n .isNull()\n .or(\n filter\n .invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E.*`)\n )\n .not()\n );\n case '!=':\n if (prefix === '*') {\n // Does not end with\n return filter\n .isNull()\n .or(\n filter\n .invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E$`)\n )\n .not()\n );\n }\n if (suffix === '*') {\n // Does not start with\n return filter\n .isNull()\n .or(\n filter\n .invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i)^\\\\Q${value}\\\\E.*`)\n )\n .not()\n );\n }\n return filter.notEqIgnoreCase(\n dh.FilterValue.ofString(value.toLowerCase())\n );\n\n case '=':\n if (prefix === '*') {\n // Ends with\n return filter\n .isNull()\n .not()\n .and(\n filter.invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E$`)\n )\n );\n }\n if (suffix === '*') {\n // Starts with\n return filter\n .isNull()\n .not()\n .and(\n filter.invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i)^\\\\Q${value}\\\\E.*`)\n )\n );\n }\n return filter.eqIgnoreCase(\n dh.FilterValue.ofString(value.toLowerCase())\n );\n\n default:\n break;\n }\n\n return null;\n }\n\n static makeQuickBooleanFilter(\n column: Column,\n text: string\n ): FilterCondition | null {\n if (text == null) {\n return null;\n }\n\n const regex = /^(!=|=|!)?(.*)/;\n const result = regex.exec(`${text}`.trim());\n if (result === null) {\n return null;\n }\n const [, operation, value] = result;\n const notEqual = operation === '!' || operation === '!=';\n const cleanValue = value.trim().toLowerCase();\n\n let filter: FilterCondition | FilterValue = column.filter();\n\n try {\n const boolValue = TableUtils.makeBooleanValue(cleanValue);\n if (boolValue) {\n filter = filter.isTrue();\n } else if (boolValue === null) {\n filter = filter.isNull();\n } else {\n filter = filter.isFalse();\n }\n\n return notEqual ? filter.not() : filter;\n } catch (e) {\n return null;\n }\n }\n\n /**\n * Builds a date filter parsed from the text string which may or may not include an operator.\n * @param column The column to build the filter from, with or without a leading operator.\n * @param text The date string text to parse.\n * @param timeZone The time zone to make this filter in if it is a date type. E.g. America/New_York\n */\n static makeQuickDateFilter(\n column: Column,\n text: string,\n timeZone: string\n ): FilterCondition {\n const cleanText = text.trim();\n const regex = /\\s*(>=|<=|=>|=<|>|<|!=|!|=)?(.*)/;\n const result = regex.exec(cleanText);\n if (result == null || result.length <= 2) {\n throw new Error(`Unable to parse date filter: ${text}`);\n }\n\n let operation = null;\n let dateText = null;\n\n [, operation, dateText] = result;\n\n let filterOperation: FilterTypeValue = FilterType.eq;\n switch (operation) {\n case '<':\n filterOperation = FilterType.lessThan;\n break;\n case '<=':\n case '=<':\n filterOperation = FilterType.lessThanOrEqualTo;\n break;\n case '>':\n filterOperation = FilterType.greaterThan;\n break;\n case '>=':\n case '=>':\n filterOperation = FilterType.greaterThanOrEqualTo;\n break;\n case '!=':\n case '!':\n filterOperation = FilterType.notEq;\n break;\n case '=':\n case '==':\n default:\n filterOperation = FilterType.eq;\n break;\n }\n\n return TableUtils.makeQuickDateFilterWithOperation(\n column,\n dateText,\n filterOperation,\n timeZone\n );\n }\n\n /**\n * Builds a date filter parsed from the text string with the provided filter.\n * @param column The column to build the filter from.\n * @param text The date string text to parse, without an operator.\n * @param operation The filter operation to use.\n * @param timeZone The time zone to make this filter with. E.g. America/New_York\n */\n static makeQuickDateFilterWithOperation(\n column: Column,\n text: string,\n operation: FilterTypeValue = FilterType.eq,\n timeZone: string\n ): FilterCondition {\n if (column == null) {\n throw new Error('Column is null');\n }\n\n const [startDate, endDate] = DateUtils.parseDateRange(text, timeZone);\n\n const startValue =\n startDate != null ? dh.FilterValue.ofNumber(startDate) : null;\n const endValue = endDate != null ? dh.FilterValue.ofNumber(endDate) : null;\n\n const filter = column.filter();\n if (startValue == null) {\n return operation === FilterType.notEq\n ? filter.isNull().not()\n : filter.isNull();\n }\n\n switch (operation) {\n case FilterType.eq: {\n if (endValue != null) {\n const startFilter = filter.greaterThanOrEqualTo(startValue);\n const endFilter = filter.lessThan(endValue);\n return startFilter.and(endFilter);\n }\n return filter.eq(startValue);\n }\n case FilterType.lessThan: {\n return filter.lessThan(startValue);\n }\n case FilterType.lessThanOrEqualTo: {\n if (endValue != null) {\n return filter.lessThan(endValue);\n }\n return filter.lessThanOrEqualTo(startValue);\n }\n case FilterType.greaterThan: {\n if (endValue != null) {\n return filter.greaterThanOrEqualTo(endValue);\n }\n return filter.greaterThan(startValue);\n }\n case FilterType.greaterThanOrEqualTo:\n return filter.greaterThanOrEqualTo(startValue);\n case FilterType.notEq: {\n if (endValue != null) {\n const startFilter = filter.lessThan(startValue);\n const endFilter = filter.greaterThanOrEqualTo(endValue);\n return startFilter.or(endFilter);\n }\n return filter.notEq(startValue);\n }\n\n default:\n throw new Error(`Invalid operator: ${operation}`);\n }\n }\n\n static makeQuickCharFilter(\n column: Column,\n text: string\n ): FilterCondition | null {\n if (text == null) {\n return null;\n }\n\n const cleanText = `${text}`.trim();\n const regex = /^(!=|=|!)?(null|.)?(.*)/;\n const result = regex.exec(cleanText);\n\n let operation = null;\n let value = null;\n let overflow = null;\n if (result !== null && result.length > 3) {\n [, operation, value, overflow] = result;\n }\n if (overflow != null && overflow.trim().length > 0) {\n // Some bad characters after the number, bail out!\n return null;\n }\n\n if (value == null || value.length === 0) {\n return null;\n }\n\n if (operation == null) {\n operation = '=';\n }\n\n const filter = column.filter();\n if (value.toLowerCase() === 'null') {\n // Null is a special case!\n switch (operation) {\n case '=':\n return filter.isNull();\n case '!=':\n case '!':\n return filter.isNull().not();\n default:\n return null;\n }\n }\n\n return TableUtils.makeRangeFilterWithOperation(\n filter,\n operation,\n dh.FilterValue.ofString(value)\n );\n }\n\n /**\n * @param filter The column filter to apply the range operation to\n * @param operation The range operation to run\n * @param value The value to use for the operation\n * @returns The condition with the specified operation\n */\n static makeRangeFilterWithOperation(\n filter: FilterValue,\n operation: string,\n value: FilterValue\n ): FilterCondition | null {\n switch (operation) {\n case '=':\n return filter.eq(value);\n case '<':\n return filter.lessThan(value);\n case '<=':\n case '=<':\n return filter.lessThanOrEqualTo(value);\n case '>':\n return filter.greaterThan(value);\n case '>=':\n case '=>':\n return filter.greaterThanOrEqualTo(value);\n case '!=':\n case '!':\n return filter.notEq(value);\n default:\n return null;\n }\n }\n\n /**\n * Wraps a table promise in a cancelable promise that will close the table if the promise is cancelled.\n * Use in a component that loads a table, and call cancel when unmounting.\n * @param table The table promise to wrap\n */\n static makeCancelableTablePromise(\n table: Promise<Table> | Table\n ): CancelablePromise<Table> {\n return PromiseUtils.makeCancelable(table, resolved => {\n resolved.close();\n });\n }\n\n /**\n * Make a cancelable promise for a one-shot table event with a timeout.\n * @param table Table to listen for events on\n * @param eventName Event to listen for\n * @param timeout Event timeout in milliseconds, defaults to 0\n * @param matcher Optional function to determine if the promise can be resolved or stays pending\n * @returns Resolves with the event data\n */\n static makeCancelableTableEventPromise(\n table: Table | TreeTable,\n eventName: string,\n timeout = 0,\n matcher: ((event: CustomEvent) => boolean) | null = null\n ): CancelablePromise<CustomEvent> {\n let eventCleanup: RemoverFn;\n let timeoutId: ReturnType<typeof setTimeout>;\n let isPending = true;\n const wrappedPromise = new Promise((resolve, reject) => {\n timeoutId = setTimeout(() => {\n eventCleanup();\n isPending = false;\n reject(new TimeoutError(`Event \"${eventName}\" timed out.`));\n }, timeout);\n eventCleanup = table.addEventListener(eventName, event => {\n if (matcher != null && !matcher(event)) {\n log.debug2('Event triggered, but matcher returned false.');\n return;\n }\n log.debug2('Event triggered, resolving.');\n eventCleanup();\n clearTimeout(timeoutId);\n isPending = false;\n resolve(event);\n });\n }) as CancelablePromise<CustomEvent>;\n wrappedPromise.cancel = () => {\n if (isPending) {\n log.debug2('Pending promise cleanup.');\n eventCleanup();\n clearTimeout(timeoutId);\n isPending = false;\n return;\n }\n log.debug2('Ignoring non-pending promise cancel.');\n };\n return wrappedPromise;\n }\n\n static makeAdvancedFilter(\n column: Column,\n options: {\n filterItems: AdvancedFilterCreatorFilterItemState[];\n filterOperators: FilterOperatorValue[];\n invertSelection: boolean;\n selectedValues: string[];\n },\n timeZone: string\n ): FilterCondition | null {\n const {\n filterItems,\n filterOperators,\n invertSelection,\n selectedValues,\n } = options;\n let filter = null;\n for (let i = 0; i < filterItems.length; i += 1) {\n const filterItem = filterItems[i];\n const { selectedType, value } = filterItem;\n if (\n selectedType != null &&\n selectedType.length > 0 &&\n value != null &&\n value.length > 0\n ) {\n try {\n const newFilter = TableUtils.makeAdvancedValueFilter(\n column,\n selectedType,\n value,\n timeZone\n );\n if (newFilter != null) {\n if (i === 0) {\n filter = newFilter;\n } else if (filter !== null && i - 1 < filterOperators.length) {\n const filterOperator = filterOperators[i - 1];\n if (filterOperator === FilterOperator.and) {\n filter = filter.and(newFilter);\n } else if (filterOperator === FilterOperator.or) {\n filter = filter.or(newFilter);\n } else {\n log.error(\n 'Unexpected filter operator',\n filterOperator,\n newFilter\n );\n filter = null;\n break;\n }\n }\n } else {\n log.debug2('Empty filter ignored for', selectedType, value);\n }\n } catch (err) {\n log.error('Unable to create filter', err);\n filter = null;\n break;\n }\n }\n }\n\n const selectValueFilter = TableUtils.makeSelectValueFilter(\n column,\n selectedValues,\n invertSelection\n );\n if (selectValueFilter != null) {\n if (filter != null) {\n filter = filter.and(selectValueFilter);\n } else {\n filter = selectValueFilter;\n }\n }\n return filter;\n }\n\n static removeCommas(value: string): string {\n return value.replace(/[\\s|,]/g, '');\n }\n\n /**\n * @param columnType The column type to make the filter value from.\n * @param value The value to make the filter value from.\n * @returns The FilterValue item for this column/value combination\n */\n static makeFilterValue(columnType: string, value: string): FilterValue {\n const type = TableUtils.getBaseType(columnType);\n if (TableUtils.isTextType(type)) {\n return dh.FilterValue.ofString(value);\n }\n if (TableUtils.isLongType(type)) {\n return dh.FilterValue.ofNumber(\n dh.LongWrapper.ofString(TableUtils.removeCommas(value))\n );\n }\n\n return dh.FilterValue.ofNumber(TableUtils.removeCommas(value));\n }\n\n /**\n * Takes a value and converts it to an `dh.FilterValue`\n *\n * @param columnType The column type to make the filter value from.\n * @param value The value to actually set\n * @returns The FilterValue item for this column/value combination\n */\n static makeFilterRawValue(\n columnType: string,\n rawValue: unknown\n ): FilterValue {\n if (TableUtils.isTextType(columnType)) {\n return dh.FilterValue.ofString(rawValue);\n }\n\n if (TableUtils.isBooleanType(columnType)) {\n return dh.FilterValue.ofBoolean(rawValue);\n }\n\n return dh.FilterValue.ofNumber(rawValue);\n }\n\n /**\n * Converts a string value to a value appropriate for the column\n * @param columnType The column type to make the value for\n * @param text The string value to make a type for\n * @param timeZone The time zone to make this value in if it is a date type. E.g. America/New_York\n */\n static makeValue(\n columnType: string,\n text: string,\n timeZone: string\n ): string | number | boolean | LongWrapper | null {\n if (text == null || text === 'null') {\n return null;\n }\n if (TableUtils.isTextType(columnType)) {\n return text;\n }\n if (TableUtils.isLongType(columnType)) {\n return dh.LongWrapper.ofString(TableUtils.removeCommas(text));\n }\n if (TableUtils.isBooleanType(columnType)) {\n return TableUtils.makeBooleanValue(text, true);\n }\n if (TableUtils.isDateType(columnType)) {\n const [date] = DateUtils.parseDateRange(text, timeZone);\n return date;\n }\n\n if (TableUtils.isNumberType(columnType)) {\n return TableUtils.makeNumberValue(text);\n }\n\n log.error('Unexpected column type', columnType);\n return null;\n }\n\n static makeBooleanValue(text: string, allowEmpty = false): boolean | null {\n if (text === '' && allowEmpty) {\n return null;\n }\n\n switch (text?.toLowerCase()) {\n case 'null':\n return null;\n case '0':\n case 'f':\n case 'fa':\n case 'fal':\n case 'fals':\n case 'false':\n case 'n':\n case 'no':\n return false;\n case '1':\n case 't':\n case 'tr':\n case 'tru':\n case 'true':\n case 'y':\n case 'ye':\n case 'yes':\n return true;\n default:\n throw new Error(`Invalid boolean '${text}'`);\n }\n }\n\n static makeNumberValue(text: string): number | null {\n if (text == null || text === 'null' || text === '') {\n return null;\n }\n\n const cleanText = text.toLowerCase().trim();\n if (cleanText === '∞' || cleanText === 'infinity' || cleanText === 'inf') {\n return Number.POSITIVE_INFINITY;\n }\n if (\n cleanText === '-∞' ||\n cleanText === '-infinity' ||\n cleanText === '-inf'\n ) {\n return Number.NEGATIVE_INFINITY;\n }\n\n const numberText = TableUtils.removeCommas(cleanText);\n if (TableUtils.NUMBER_REGEX.test(numberText)) {\n return parseFloat(numberText);\n }\n\n throw new Error(`Invalid number '${text}'`);\n }\n\n static makeAdvancedValueFilter(\n column: Column,\n operation: FilterTypeValue,\n value: string,\n timeZone: string\n ): FilterCondition {\n if (TableUtils.isDateType(column.type)) {\n return TableUtils.makeQuickDateFilterWithOperation(\n column,\n value,\n operation,\n timeZone\n );\n }\n\n const filterValue = TableUtils.makeFilterValue(column.type, value);\n const filter = column.filter();\n switch (operation) {\n case FilterType.eq:\n return filter.eq(filterValue);\n case FilterType.eqIgnoreCase:\n return filter.eqIgnoreCase(filterValue);\n case FilterType.notEq:\n return filter.notEq(filterValue);\n case FilterType.notEqIgnoreCase:\n return filter.notEqIgnoreCase(filterValue);\n case FilterType.greaterThan:\n return filter.greaterThan(filterValue);\n case FilterType.greaterThanOrEqualTo:\n return filter.greaterThanOrEqualTo(filterValue);\n case FilterType.lessThan:\n return filter.lessThan(filterValue);\n case FilterType.lessThanOrEqualTo:\n return filter.lessThanOrEqualTo(filterValue);\n case FilterType.isTrue:\n return filter.isTrue();\n case FilterType.isFalse:\n return filter.isFalse();\n case FilterType.isNull:\n return filter.isNull();\n case FilterType.contains:\n return filter\n .isNull()\n .not()\n .and(\n filter.invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E.*`)\n )\n );\n case FilterType.notContains:\n return filter\n .isNull()\n .or(\n filter\n .invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E.*`)\n )\n .not()\n );\n case FilterType.startsWith:\n return filter\n .isNull()\n .not()\n .and(\n filter.invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i)^\\\\Q${value}\\\\E.*`)\n )\n );\n case FilterType.endsWith:\n return filter\n .isNull()\n .not()\n .and(\n filter.invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${value}\\\\E$`)\n )\n );\n case FilterType.in:\n case FilterType.inIgnoreCase:\n case FilterType.notIn:\n case FilterType.notInIgnoreCase:\n case FilterType.invoke:\n default:\n throw new Error(`Unexpected filter operation: ${operation}`);\n }\n }\n\n /**\n * Create a filter using the selected items\n * Has a flag for invertSelection as we start from a \"Select All\" state and a user just deselects items.\n * Since there may be millions of distinct items, it's easier to build an inverse filter.\n * @param column The column to set the filter on\n * @param selectedValues The values that are selected\n * @param invertSelection Invert the selection (eg. All items are selected, then you deselect items)\n * @returns Returns a `in` or `notIn` FilterCondition as necessary, or null if no filtering should be applied (everything selected)\n */\n static makeSelectValueFilter(\n column: Column,\n selectedValues: string[],\n invertSelection: boolean\n ): FilterCondition | null {\n if (selectedValues.length === 0) {\n if (invertSelection) {\n // No filter means select everything\n return null;\n }\n\n // KLUDGE: Return a conflicting filter to show no results.\n // Could recognize this situation at a higher or lower level and pause updates on the\n // table, but this situation should be rare and that wouldn't be much gains for some added complexity\n let value = null;\n\n if (TableUtils.isTextType(column.type)) {\n // Use 'a' so that it can work for String or Character types\n value = dh.FilterValue.ofString('a');\n } else if (TableUtils.isBooleanType(column.type)) {\n value = dh.FilterValue.ofBoolean(true);\n } else if (TableUtils.isDateType(column.type)) {\n value = dh.FilterValue.ofNumber(dh.DateWrapper.ofJsDate(new Date()));\n } else {\n value = dh.FilterValue.ofNumber(0);\n }\n\n const eqFilter = column.filter().eq(value);\n const notEqFilter = column.filter().notEq(value);\n return eqFilter.and(notEqFilter);\n }\n\n const values = [];\n let isNullSelected = false;\n for (let i = 0; i < selectedValues.length; i += 1) {\n const value = selectedValues[i];\n if (value == null) {\n isNullSelected = true;\n } else if (TableUtils.isTextType(column.type)) {\n values.push(\n dh.FilterValue.ofString(\n typeof value === 'number' ? String.fromCharCode(value) : value\n )\n );\n } else if (TableUtils.isBooleanType(column.type)) {\n values.push(dh.FilterValue.ofBoolean(!!value));\n } else {\n values.push(dh.FilterValue.ofNumber(value));\n }\n }\n\n if (isNullSelected) {\n if (values.length > 0) {\n if (invertSelection) {\n return column\n .filter()\n .isNull()\n .not()\n .and(column.filter().notIn(values));\n }\n return column.filter().isNull().or(column.filter().in(values));\n }\n if (invertSelection) {\n return column.filter().isNull().not();\n }\n\n return column.filter().isNull();\n }\n\n if (invertSelection) {\n return column.filter().notIn(values);\n }\n\n return column.filter().in(values);\n }\n\n static isTreeTable(table: unknown): table is TreeTable {\n return (\n table != null &&\n (table as TreeTable).expand !== undefined &&\n (table as TreeTable).collapse !== undefined\n );\n }\n\n /**\n * Copies the provided array, sorts by column name case insensitive, and returns the sorted array.\n * @param columns The columns to sort\n * @param isAscending Whether to sort ascending\n */\n static sortColumns(columns: Column[], isAscending = true): Column[] {\n return [...columns].sort((a, b) => {\n const aName = a.name.toUpperCase();\n const bName = b.name.toUpperCase();\n return TextUtils.sort(aName, bName, isAscending);\n });\n }\n}\n\nexport default TableUtils;\n","/* eslint class-methods-use-this: \"off\" */\n/**\n * Default column data formatter. Just interpolates the value as a string and returns.\n * Extend this class and register with TableUtils to make use of it.\n */\n\nexport type TableColumnFormatType =\n | 'type-global'\n | 'type-context-preset'\n | 'type-context-custom';\n\nexport type TableColumnFormat = {\n label: string;\n formatString: string;\n type: TableColumnFormatType;\n};\n\nexport class TableColumnFormatter<T = unknown> {\n static TYPE_GLOBAL: TableColumnFormatType = 'type-global';\n\n static TYPE_CONTEXT_PRESET: TableColumnFormatType = 'type-context-preset';\n\n static TYPE_CONTEXT_CUSTOM: TableColumnFormatType = 'type-context-custom';\n\n /**\n * Validates format object\n * @param format Format object\n * @returns true for valid object\n */\n static isValid(format: TableColumnFormat): boolean {\n return true;\n }\n\n /**\n * Check if the given formats match\n * @param formatA format object to check\n * @param formatB format object to check\n * @returns True if the formats match\n */\n static isSameFormat(\n formatA?: TableColumnFormat,\n formatB?: TableColumnFormat\n ): boolean {\n throw new Error('isSameFormat not implemented');\n }\n\n /**\n * Create and return a Format object\n * @param label The label of the format object\n * @param formatString Format string to use for the format\n * @param type The type of column to use for this format\n * @returns A format object\n */\n static makeFormat(\n label: string,\n formatString: string,\n type: TableColumnFormatType\n ): TableColumnFormat {\n return { label, formatString, type };\n }\n\n /**\n * @param value The value to format\n * @param format Optional format object with value transformation options\n * @returns String the formatted text string of the value passed in.\n */\n format(value: T, format?: TableColumnFormat): string {\n return '';\n }\n}\n\nexport default TableColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport TableColumnFormatter from './TableColumnFormatter';\n\nclass DefaultColumnFormatter extends TableColumnFormatter {\n format(value: unknown): string {\n return `${value}`;\n }\n}\n\nexport default DefaultColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport TableColumnFormatter from './TableColumnFormatter';\n\n/** Column formatter for chars */\nclass BooleanColumnFormatter extends TableColumnFormatter<boolean | number> {\n format(value: boolean | number): string {\n switch (value) {\n case 1:\n case true:\n return 'true';\n case 0:\n case false:\n return 'false';\n default:\n return '';\n }\n }\n}\n\nexport default BooleanColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport TableColumnFormatter from './TableColumnFormatter';\n\n/** Column formatter for chars */\nclass CharColumnFormatter extends TableColumnFormatter<number> {\n format(value: number): string {\n return String.fromCharCode(value);\n }\n}\n\nexport default CharColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\nimport dh, { DateWrapper, TimeZone } from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport TableColumnFormatter, {\n TableColumnFormat,\n} from './TableColumnFormatter';\n\nconst log = Log.module('DateTimeColumnFormatter');\n\nexport type DateTimeColumnFormatterOptions = {\n // Time zone\n timeZone?: string;\n\n // Show time zone in DateTime values\n showTimeZone?: boolean;\n\n // Show 'T' separator in DateTime values\n showTSeparator?: boolean;\n\n // DateTime format to use if columnFormats for DateTime isn't set\n defaultDateTimeFormatString?: string;\n};\n\nexport class DateTimeColumnFormatter extends TableColumnFormatter<\n Date | DateWrapper | number\n> {\n /**\n * Validates format object\n * @param format Format object\n * @returns true for valid object\n */\n static isValid(format: TableColumnFormat): boolean {\n try {\n dh.i18n.DateTimeFormat.format(format.formatString, new Date());\n return true;\n } catch (e) {\n return false;\n }\n }\n\n static makeFormat(\n label: string,\n formatString: string,\n type = TableColumnFormatter.TYPE_CONTEXT_PRESET\n ): TableColumnFormat {\n return {\n label,\n formatString,\n type,\n };\n }\n\n /**\n * Check if the given formats match\n * @param formatA format object to check\n * @param formatB format object to check\n * @returns True if the formats match\n */\n static isSameFormat(\n formatA?: TableColumnFormat,\n formatB?: TableColumnFormat\n ): boolean {\n return (\n formatA === formatB ||\n (formatA != null &&\n formatB != null &&\n formatA.type === formatB.type &&\n formatA.formatString === formatB.formatString)\n );\n }\n\n static DEFAULT_DATETIME_FORMAT_STRING = 'yyyy-MM-dd HH:mm:ss.SSS';\n\n static DEFAULT_TIME_ZONE_ID = 'America/New_York';\n\n static makeGlobalFormatStringMap(\n showTimeZone: boolean,\n showTSeparator: boolean\n ): Map<string, string> {\n const separator = showTSeparator ? `'T'` : ' ';\n const tz = showTimeZone ? ' z' : '';\n return new Map([\n ['yyyy-MM-dd HH:mm:ss', `yyyy-MM-dd${separator}HH:mm:ss${tz}`],\n ['yyyy-MM-dd HH:mm:ss.SSS', `yyyy-MM-dd${separator}HH:mm:ss.SSS${tz}`],\n [\n 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS',\n `yyyy-MM-dd${separator}HH:mm:ss.SSSSSSSSS${tz}`,\n ],\n ]);\n }\n\n static getGlobalFormats(\n showTimeZone: boolean,\n showTSeparator: boolean\n ): string[] {\n const formatStringMap = DateTimeColumnFormatter.makeGlobalFormatStringMap(\n showTimeZone,\n showTSeparator\n );\n return [...formatStringMap.keys()];\n }\n\n static makeFormatStringMap(\n showTimeZone?: boolean,\n showTSeparator?: boolean\n ): Map<string, string> {\n const separator = showTSeparator ? `'T'` : ' ';\n const tz = showTimeZone ? ' z' : '';\n return new Map([\n ['yyyy-MM-dd', `yyyy-MM-dd${tz}`],\n ['MM-dd-yyyy', `MM-dd-yyyy${tz}`],\n ['HH:mm:ss', `HH:mm:ss${tz}`],\n ['HH:mm:ss.SSS', `HH:mm:ss.SSS${tz}`],\n ['HH:mm:ss.SSSSSSSSS', `HH:mm:ss.SSSSSSSSS${tz}`],\n ['yyyy-MM-dd HH:mm:ss', `yyyy-MM-dd${separator}HH:mm:ss${tz}`],\n ['yyyy-MM-dd HH:mm:ss.SSS', `yyyy-MM-dd${separator}HH:mm:ss.SSS${tz}`],\n [\n 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS',\n `yyyy-MM-dd${separator}HH:mm:ss.SSSSSSSSS${tz}`,\n ],\n ]);\n }\n\n static getFormats(\n showTimeZone?: boolean,\n showTSeparator?: boolean\n ): string[] {\n const formatStringMap = DateTimeColumnFormatter.makeFormatStringMap(\n showTimeZone,\n showTSeparator\n );\n return [...formatStringMap.keys()];\n }\n\n dhTimeZone: TimeZone;\n\n defaultDateTimeFormatString: string;\n\n showTimeZone: boolean;\n\n showTSeparator: boolean;\n\n formatStringMap: Map<string, string>;\n\n constructor({\n timeZone: timeZoneParam = '',\n showTimeZone = true,\n showTSeparator = false,\n defaultDateTimeFormatString = DateTimeColumnFormatter.DEFAULT_DATETIME_FORMAT_STRING,\n }: DateTimeColumnFormatterOptions = {}) {\n super();\n\n const timeZone =\n timeZoneParam || DateTimeColumnFormatter.DEFAULT_TIME_ZONE_ID;\n\n try {\n this.dhTimeZone = dh.i18n.TimeZone.getTimeZone(timeZone);\n } catch (e) {\n log.error('Unsupported time zone id', timeZone);\n this.dhTimeZone = dh.i18n.TimeZone.getTimeZone(\n DateTimeColumnFormatter.DEFAULT_TIME_ZONE_ID\n );\n }\n\n this.defaultDateTimeFormatString = defaultDateTimeFormatString;\n this.showTimeZone = showTimeZone;\n this.showTSeparator = showTSeparator;\n this.formatStringMap = DateTimeColumnFormatter.makeFormatStringMap(\n showTimeZone,\n showTSeparator\n );\n }\n\n getEffectiveFormatString(baseFormatString: string): string {\n return this.formatStringMap.get(baseFormatString) || baseFormatString;\n }\n\n format(\n value: Date | DateWrapper | number,\n format?: TableColumnFormat\n ): string {\n const baseFormatString =\n (format && format.formatString) || this.defaultDateTimeFormatString;\n const formatString = this.getEffectiveFormatString(baseFormatString);\n try {\n return dh.i18n.DateTimeFormat.format(\n formatString,\n value,\n this.dhTimeZone\n );\n } catch (e) {\n log.error('Invalid format arguments');\n }\n return '';\n }\n}\n\nexport default DateTimeColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport TableColumnFormatter, {\n TableColumnFormat,\n} from './TableColumnFormatter';\n\nconst log = Log.module('DecimalColumnFormatter');\n\nexport type DecimalColumnFormat = TableColumnFormat & {\n multiplier?: number;\n};\n\nexport type DecimalColumnFormatterOptions = {\n // Default format string to use. Defaults to DecimalColumnFormatter.DEFAULT_FORMAT_STRING\n defaultFormatString?: string;\n};\n\nexport class DecimalColumnFormatter extends TableColumnFormatter<number> {\n /**\n * Validates format object\n * @param format Format object\n * @returns true for valid object\n */\n static isValid(format: TableColumnFormat): boolean {\n try {\n dh.i18n.NumberFormat.format(format.formatString, 0);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n /**\n * Create a DecimalColumnFormat object with the parameters specified\n * @param label Label for the format\n * @param formatString Format string for the format\n * @param multiplier Optional multiplier for the formatter\n * @param type Type of format created\n * @returns DecimalColumnFormat object\n */\n static makeFormat(\n label: string,\n formatString: string,\n type = TableColumnFormatter.TYPE_CONTEXT_PRESET,\n multiplier?: number\n ): DecimalColumnFormat {\n return {\n label,\n type,\n formatString,\n multiplier,\n };\n }\n\n /**\n * Convenient function to create a DecimalFormatObject with Preset type set\n * @param label Label for this format object\n * @param formatString Format string to use\n * @param multiplier Multiplier to use\n * @returns DecimalColumnFormat object\n */\n static makePresetFormat(\n label: string,\n formatString = '',\n multiplier?: number\n ): DecimalColumnFormat {\n return DecimalColumnFormatter.makeFormat(\n label,\n formatString,\n TableColumnFormatter.TYPE_CONTEXT_PRESET,\n multiplier\n );\n }\n\n /**\n * Convenient function to create a DecimalFormatObject with a default 'Custom Format' label and Custom type\n * @param formatString Format string to use\n * @param multiplier Multiplier to use\n * @returns DecimalColumnFormat object\n */\n static makeCustomFormat(\n formatString = '',\n multiplier?: number\n ): DecimalColumnFormat {\n return DecimalColumnFormatter.makeFormat(\n 'Custom Format',\n formatString,\n TableColumnFormatter.TYPE_CONTEXT_CUSTOM,\n multiplier\n );\n }\n\n static DEFAULT_FORMAT_STRING = '###,##0.0000';\n\n static FORMAT_PERCENT = DecimalColumnFormatter.makePresetFormat(\n 'Percent',\n '##0.00%'\n );\n\n static FORMAT_BASIS_POINTS = DecimalColumnFormatter.makePresetFormat(\n 'Basis Points',\n '###,##0 bp',\n 10000\n );\n\n static FORMAT_MILLIONS = DecimalColumnFormatter.makePresetFormat(\n 'Millions',\n '###,##0.000 mm',\n 0.000001\n );\n\n static FORMAT_ROUND = DecimalColumnFormatter.makePresetFormat(\n 'Round',\n '###,##0'\n );\n\n static FORMAT_ROUND_TWO_DECIMALS = DecimalColumnFormatter.makePresetFormat(\n '0.00',\n '###,##0.00'\n );\n\n static FORMAT_ROUND_FOUR_DECIMALS = DecimalColumnFormatter.makePresetFormat(\n '0.0000',\n '###,##0.0000'\n );\n\n /**\n * Check if the given formats match\n * @param formatA format object to check\n * @param formatB format object to check\n * @returns True if the formats match\n */\n static isSameFormat(\n formatA?: DecimalColumnFormat,\n formatB?: DecimalColumnFormat\n ): boolean {\n return (\n formatA === formatB ||\n (formatA != null &&\n formatB != null &&\n formatA.type === formatB.type &&\n formatA.formatString === formatB.formatString &&\n formatA.multiplier === formatB.multiplier)\n );\n }\n\n defaultFormatString: string;\n\n constructor({\n defaultFormatString = DecimalColumnFormatter.DEFAULT_FORMAT_STRING,\n }: DecimalColumnFormatterOptions = {}) {\n super();\n\n this.defaultFormatString = defaultFormatString;\n }\n\n /**\n * Format a value with the provided format object\n * @param valueParam Value to format\n * @param format Format object\n * @returns Formatted string\n */\n format(valueParam: number, format?: DecimalColumnFormat): string {\n const formatString =\n (format && format.formatString) || this.defaultFormatString;\n const value =\n format && format.multiplier ? valueParam * format.multiplier : valueParam;\n try {\n return dh.i18n.NumberFormat.format(formatString, value);\n } catch (e) {\n log.error('Invalid format arguments');\n }\n return '';\n }\n}\n\nexport default DecimalColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport TableColumnFormatter, {\n TableColumnFormat,\n} from './TableColumnFormatter';\n\nconst log = Log.module('IntegerColumnFormatter');\n\nexport type IntegerColumnFormat = TableColumnFormat & {\n multiplier?: number;\n};\n\nexport type IntegerColumnFormatterOptions = {\n // Default format string to use. Defaults to IntegerColumnFormatter.DEFAULT_FORMAT_STRING\n defaultFormatString?: string;\n};\n\n/** Column formatter for integers/whole numbers */\nexport class IntegerColumnFormatter extends TableColumnFormatter<number> {\n /**\n * Validates format object\n * @param format Format object\n * @returns true for valid object\n */\n static isValid(format: IntegerColumnFormat): boolean {\n try {\n dh.i18n.NumberFormat.format(format.formatString, 0);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n /**\n * Create an IntegerColumnFormat object with the parameters specified\n * @param label Label for the format\n * @param formatString Format string for the format\n * @param multiplier Optional multiplier for the formatter\n * @param type Type of format created\n * @returns IntegerColumnFormat object\n */\n static makeFormat(\n label: string,\n formatString: string,\n type = TableColumnFormatter.TYPE_CONTEXT_PRESET,\n multiplier?: number\n ): IntegerColumnFormat {\n return {\n label,\n type,\n formatString,\n multiplier,\n };\n }\n\n /**\n * Convenient function to create a IntegerFormatObject with Preset type set\n * @param label Label for this format object\n * @param formatString Format string to use\n * @param multiplier Multiplier to use\n * @returns IntegerColumnFormat object\n */\n static makePresetFormat(\n label: string,\n formatString = '',\n multiplier?: number\n ): IntegerColumnFormat {\n return IntegerColumnFormatter.makeFormat(\n label,\n formatString,\n TableColumnFormatter.TYPE_CONTEXT_PRESET,\n multiplier\n );\n }\n\n /**\n * Convenient function to create a IntegerFormatObject with a default 'Custom Format' label and Custom type\n * @param formatString Format string to use\n * @param multiplier Multiplier to use\n * @returns IntegerColumnFormat object\n */\n static makeCustomFormat(\n formatString = '',\n multiplier?: number\n ): IntegerColumnFormat {\n return IntegerColumnFormatter.makeFormat(\n 'Custom Format',\n formatString,\n TableColumnFormatter.TYPE_CONTEXT_CUSTOM,\n multiplier\n );\n }\n\n /**\n * Check if the given formats match\n * @param formatA format object to check\n * @param formatB format object to check\n * @returns True if the formats match\n */\n static isSameFormat(\n formatA?: IntegerColumnFormat,\n formatB?: IntegerColumnFormat\n ): boolean {\n return (\n formatA === formatB ||\n (formatA != null &&\n formatB != null &&\n formatA.type === formatB.type &&\n formatA.formatString === formatB.formatString &&\n formatA.multiplier === formatB.multiplier)\n );\n }\n\n static DEFAULT_FORMAT_STRING = '###,##0';\n\n static FORMAT_MILLIONS = IntegerColumnFormatter.makePresetFormat(\n 'Millions',\n '###,##0.000 mm',\n 0.000001\n );\n\n defaultFormatString: string;\n\n constructor({\n defaultFormatString = IntegerColumnFormatter.DEFAULT_FORMAT_STRING,\n }: IntegerColumnFormatterOptions = {}) {\n super();\n\n this.defaultFormatString = defaultFormatString;\n }\n\n /**\n * Format a value with the provided format object\n * @param valueParam Value to format\n * @param format Format object\n * @returns Formatted string\n */\n format(valueParam: number, format?: IntegerColumnFormat): string {\n const formatString =\n (format && format.formatString) || this.defaultFormatString;\n const value =\n format && format.multiplier ? valueParam * format.multiplier : valueParam;\n try {\n return dh.i18n.NumberFormat.format(formatString, value);\n } catch (e) {\n log.error('Invalid format arguments');\n }\n return '';\n }\n}\n\nexport default IntegerColumnFormatter;\n","/* eslint class-methods-use-this: \"off\" */\nimport TableColumnFormatter from './TableColumnFormatter';\n\n/** Column formatter for strings */\nclass StringColumnFormatter extends TableColumnFormatter<string> {\n format(value: string): string {\n return value;\n }\n}\n\nexport default StringColumnFormatter;\n","import { Log } from '@deephaven/log';\nimport TableUtils, { DataType } from './TableUtils';\nimport {\n BooleanColumnFormatter,\n CharColumnFormatter,\n DateTimeColumnFormatter,\n DecimalColumnFormatter,\n DefaultColumnFormatter,\n IntegerColumnFormatter,\n TableColumnFormat,\n TableColumnFormatter,\n} from './formatters';\nimport StringColumnFormatter from './formatters/StringColumnFormatter';\n\nconst log = Log.module('Formatter');\n\ntype ColumnName = string;\n\nexport interface FormattingRule {\n columnType: string;\n columnName: string;\n format: TableColumnFormat;\n}\n\nclass Formatter {\n /**\n * Converts FormattingRule[] to Map\n * @param columnFormattingRules Array or column formatting rules\n * @returns Map of columnName-to-format Maps indexed by normalized dataType\n */\n static makeColumnFormatMap(\n columnFormattingRules: FormattingRule[]\n ): Map<DataType, Map<ColumnName, TableColumnFormat>> {\n if (columnFormattingRules == null) {\n return new Map();\n }\n return columnFormattingRules.reduce((map, next) => {\n const dataType = TableUtils.getNormalizedType(next.columnType);\n if (dataType === null) {\n return map;\n }\n\n if (!map.has(dataType)) {\n map.set(dataType, new Map());\n }\n const formatMap = map.get(dataType);\n formatMap?.set(next.columnName, next.format);\n return map;\n }, new Map<DataType, Map<ColumnName, TableColumnFormat>>());\n }\n\n /**\n * Creates a column formatting rule\n * @param columnType Normalized data type\n * @param columnName Column name\n * @param format Format object\n */\n static makeColumnFormattingRule(\n columnType: DataType,\n columnName: string,\n format: TableColumnFormat\n ): FormattingRule {\n return {\n columnType,\n columnName,\n format,\n };\n }\n\n /**\n * @param columnFormattingRules Optional array of column formatting rules\n * @param dateTimeOptions Optional object with DateTime configuration\n * @param decimalFormatOptions Optional object with Decimal configuration\n * @param integerFormatOptions Optional object with Integer configuration\n */\n constructor(\n columnFormattingRules: FormattingRule[] = [],\n dateTimeOptions?: ConstructorParameters<typeof DateTimeColumnFormatter>[0],\n decimalFormatOptions?: ConstructorParameters<\n typeof DecimalColumnFormatter\n >[0],\n integerFormatOptions?: ConstructorParameters<\n typeof IntegerColumnFormatter\n >[0]\n ) {\n // Formatting order:\n // - columnFormatMap[type][name]\n // - typeFormatterMap[type]\n // - defaultColumnFormatter\n\n this.defaultColumnFormatter = new DefaultColumnFormatter();\n\n // Default formatters by data type\n this.typeFormatterMap = new Map<DataType, TableColumnFormatter>([\n [TableUtils.dataType.BOOLEAN, new BooleanColumnFormatter()],\n [TableUtils.dataType.CHAR, new CharColumnFormatter()],\n [\n TableUtils.dataType.DATETIME,\n new DateTimeColumnFormatter(dateTimeOptions),\n ],\n [\n TableUtils.dataType.DECIMAL,\n new DecimalColumnFormatter(decimalFormatOptions),\n ],\n [\n TableUtils.dataType.INT,\n new IntegerColumnFormatter(integerFormatOptions),\n ],\n [TableUtils.dataType.STRING, new StringColumnFormatter()],\n ]);\n\n // Formats indexed by data type and column name\n this.columnFormatMap = Formatter.makeColumnFormatMap(columnFormattingRules);\n }\n\n defaultColumnFormatter: TableColumnFormatter;\n\n typeFormatterMap: Map<DataType, TableColumnFormatter>;\n\n columnFormatMap: Map<DataType, Map<string, TableColumnFormat>>;\n\n /**\n * Gets columnFormatMap indexed by name for a given column type, creates new Map entry if necessary\n * @param columnType column type\n * @param createIfNecessary create new entry if true\n * @returns Map of format strings indexed by column name or undefined if it doesn't exist\n */\n getColumnFormatMapForType(\n columnType: string,\n createIfNecessary = false\n ): Map<string, TableColumnFormat> | undefined {\n const dataType = TableUtils.getNormalizedType(columnType);\n if (dataType === null) {\n log.warn(`Unknown columnType ${columnType}`);\n return undefined;\n }\n\n if (createIfNecessary && !this.columnFormatMap.has(dataType)) {\n this.columnFormatMap.set(dataType, new Map());\n }\n return this.columnFormatMap.get(dataType);\n }\n\n /**\n * Gets a column format object for a given column type and name\n * @param columnType column type\n * @param columnName column name\n * @returns format object or null for Default\n */\n getColumnFormat(\n columnType: string,\n columnName: string\n ): TableColumnFormat | null {\n const columnFormatMap = this.getColumnFormatMapForType(columnType);\n return columnFormatMap?.get(columnName) ?? null;\n }\n\n getColumnTypeFormatter(columnType: string): TableColumnFormatter {\n const dataType = TableUtils.getNormalizedType(columnType);\n let columnTypeFormatter = this.defaultColumnFormatter;\n if (dataType) {\n columnTypeFormatter =\n this.typeFormatterMap.get(dataType) ?? columnTypeFormatter;\n }\n return columnTypeFormatter;\n }\n\n /**\n * Gets formatted string for a given value, column type and name\n * @param value Value to format\n * @param columnType Column type used to determine the formatting settings\n * @param columnName Column name used to determine the formatting settings\n * @param formatOverride Format object passed to the formatter in place of the format defined in columnFormatMap\n */\n getFormattedString(\n value: unknown,\n columnType: string,\n columnName = '',\n formatOverride?: TableColumnFormat\n ): string {\n if (value == null) {\n return '';\n }\n\n const formatter = this.getColumnTypeFormatter(columnType);\n const format =\n formatOverride || this.getColumnFormat(columnType, columnName);\n\n return formatter.format(value, format ?? undefined);\n }\n\n /**\n * Gets the timeZone name\n * @returns The time zone name E.g. America/New_York\n */\n get timeZone(): string {\n const formatter = this.typeFormatterMap.get(\n TableUtils.dataType.DATETIME\n ) as DateTimeColumnFormatter;\n return formatter?.dhTimeZone?.id;\n }\n}\n\nexport default Formatter;\n","export class AssertionError extends Error {\n isAssertionFailed = true;\n}\n\nexport default AssertionError;\n","import AssertionError from './AssertionError';\n\nexport function assertIsDefined<T>(val: T): asserts val is NonNullable<T> {\n if (val === undefined || val === null) {\n throw new AssertionError(\n `Expected 'val' to be defined, but received ${val}`\n );\n }\n}\n\nexport default assertIsDefined;\n","export class PasteError extends Error {\n isPasteError = true;\n}\n\nexport default PasteError;\n","import GridRange from './GridRange';\nimport { ModelIndex } from './GridMetrics';\nimport GridModel from './GridModel';\nimport { AssertionError } from './errors';\n\nexport function isEditableGridModel(\n model: GridModel\n): model is EditableGridModel {\n return (model as EditableGridModel)?.isEditable !== undefined;\n}\n\nexport function assertIsEditableGridModel(\n model: GridModel\n): asserts model is EditableGridModel {\n if (!isEditableGridModel(model)) {\n throw new AssertionError(\n `Expected 'model' to be editable, but received ${model}`\n );\n }\n}\n\n/**\n * Edit operation when applying multiple edits\n */\nexport type EditOperation = {\n /** Column to set the value for */\n column: ModelIndex;\n\n /** Row to set the value for */\n row: ModelIndex;\n\n /** Text value to set */\n text: string;\n\n /** @deprecated use `column` instead */\n x?: ModelIndex;\n /** @deprecated use `row` instead */\n y?: ModelIndex;\n};\n\n/**\n * Model for an editable grid\n */\nexport interface EditableGridModel extends GridModel {\n isEditable: boolean;\n\n /**\n * Check if a given range is editable\n * @param range The range to check if it is editable\n * @returns True if the range is editable\n */\n isEditableRange(range: GridRange): boolean;\n\n /**\n * Get the edit text for a cell as a string\n * @param column Column to get\n * @param row Row to get\n * @returns The value to use for editing\n */\n editValueForCell(column: ModelIndex, row: ModelIndex): string;\n\n /**\n * Set value in an editable table\n * @param column Column to set\n * @param row Row to set\n * @param value The value to set\n * @returns A promise that resolves successfully when the operation is complete, or rejects if there's an error\n */\n setValueForCell(\n column: ModelIndex,\n row: ModelIndex,\n value: string\n ): Promise<void>;\n\n /**\n * Set value in an editable table\n * @param ranges The ranges to set\n * @param value The value to set\n * @returns A promise that resolves successfully when the operation is complete, or rejects if there's an error\n */\n setValueForRanges(ranges: GridRange[], value: string): Promise<void>;\n\n /**\n * Apply edits to the model\n * @param edits Edits to apply to the model\n * @returns A promise that resolves successfully when the operation is complete or rejects if there's an error\n */\n setValues(edits: EditOperation[]): Promise<void>;\n\n /**\n * Check if a text value is a valid edit for a cell\n * @param column Column to check\n * @param row Row to check\n * @param value Value to check if it's a valid value or not\n * @returns True if it's a valid value, false otherwise\n */\n isValidForCell(column: ModelIndex, row: ModelIndex, value: string): boolean;\n}\n\nexport default EditableGridModel;\n","import GridModel from './GridModel';\nimport { ModelIndex } from './GridMetrics';\n\nexport function isExpandableGridModel(\n model: GridModel\n): model is ExpandableGridModel {\n return (model as ExpandableGridModel)?.hasExpandableRows !== undefined;\n}\n\n/**\n * Expandable grid model. Allows for a grid with rows that can expand (e.g. A Tree Table)\n */\nexport interface ExpandableGridModel extends GridModel {\n /** Whether the grid has rows that can be expanded */\n hasExpandableRows: boolean;\n\n /**\n * @param row Row to check\n * @returns True if the row is expandable\n */\n isRowExpandable(row: ModelIndex): boolean;\n\n /**\n * @param row Row to check\n * @returns True if the row is currently expanded\n */\n isRowExpanded(row: ModelIndex): boolean;\n\n /**\n * Change the expanded status of an expandable row\n * @param row Row to expand\n * @param isExpanded True to expand the row, false to collapse\n */\n setRowExpanded(row: ModelIndex, isExpanded: boolean): void;\n\n /**\n * Get the depth of a row (ie. How indented the row should be)\n * @param row Row to check\n * @returns Depth of the row\n */\n depthForRow(row: ModelIndex): number;\n}\n\nexport default ExpandableGridModel;\n","export type GridRangeIndex = number | null;\ntype LeftIndex = GridRangeIndex;\ntype RightIndex = GridRangeIndex;\ntype TopIndex = GridRangeIndex;\ntype BottomIndex = GridRangeIndex;\n\nexport type GridCell = { column: number; row: number };\n\nexport interface BoundedGridRange extends GridRange {\n startColumn: number;\n startRow: number;\n endColumn: number;\n endRow: number;\n}\n\n// Also exported via GridRange.SELECTION_DIRECTION\nexport enum SELECTION_DIRECTION {\n DOWN = 'DOWN',\n UP = 'UP',\n LEFT = 'LEFT',\n RIGHT = 'RIGHT',\n}\n\nexport class GridRange {\n startColumn: GridRangeIndex;\n\n startRow: GridRangeIndex;\n\n endColumn: GridRangeIndex;\n\n endRow: GridRangeIndex;\n\n static SELECTION_DIRECTION = SELECTION_DIRECTION;\n\n /**\n * Returns a normalized array of indexes ensuring left <= right and top <= bottom\n * @param startColumn Start column index\n * @param startRow Start row index\n * @param endColumn End column index\n * @param endRow End row index\n * @returns Array containing normalized indexes [left, top, right, bottom]\n */\n static normalize(\n startColumn: GridRangeIndex,\n startRow: GridRangeIndex,\n endColumn: GridRangeIndex,\n endRow: GridRangeIndex\n ): [LeftIndex, TopIndex, RightIndex, BottomIndex] {\n let left = startColumn;\n let top = startRow;\n let right = endColumn;\n let bottom = endRow;\n\n if (left != null && right != null && right < left) {\n left = right;\n right = startColumn;\n }\n\n if (top != null && bottom != null && bottom < top) {\n top = bottom;\n bottom = startRow;\n }\n\n return [left, top, right, bottom];\n }\n\n /**\n * Makes a GridRange ensuring startColumn <= endColumn, startRow <= endRow\n * @param startColumn Start column index\n * @param startRow Start row index\n * @param endColumn End column index\n * @param endRow End row index\n * @returns Normalized GridRange\n */\n static makeNormalized(\n startColumn: GridRangeIndex,\n startRow: GridRangeIndex,\n endColumn: GridRangeIndex,\n endRow: GridRangeIndex\n ): GridRange {\n return new GridRange(\n ...GridRange.normalize(startColumn, startRow, endColumn, endRow)\n );\n }\n\n /**\n * Creates a GridRange representing a single cell\n * @param column Column index\n * @param row Row index\n * @returns GridRange representing the cell\n */\n static makeCell(column: GridRangeIndex, row: GridRangeIndex): GridRange {\n return new GridRange(column, row, column, row);\n }\n\n /**\n * Creates a GridRange representing an infinite length column\n * @param column Column index\n * @returns GridRange representing the column\n */\n static makeColumn(column: GridRangeIndex): GridRange {\n return new GridRange(column, null, column, null);\n }\n\n /**\n * Creates a GridRange representing an infinite length row\n * @param row Row index\n * @returns GridRange representing the row\n */\n static makeRow(row: GridRangeIndex): GridRange {\n return new GridRange(null, row, null, row);\n }\n\n /**\n * Returns the minimum value between 2 range indexes or null if at least 1 is null\n * @param index1 First grid range index\n * @param index2 Second grid range index\n * @returns Minimum index or null if either index is null\n */\n static minOrNull(\n index1: GridRangeIndex,\n index2: GridRangeIndex\n ): number | null {\n if (index1 == null || index2 == null) {\n return null;\n }\n\n return Math.min(index1, index2);\n }\n\n /**\n * Returns the maximum value between 2 range indexes or null if at least 1 is null\n * @param index1 First grid range index\n * @param index2 Second grid range index\n * @returns Maximum index or null if either index is null\n */\n static maxOrNull(\n index1: GridRangeIndex,\n index2: GridRangeIndex\n ): number | null {\n if (index1 == null || index2 == null) {\n return null;\n }\n\n return Math.max(index1, index2);\n }\n\n /**\n * Consolidate the passed in ranges to the minimum set, merging overlapping ranges.\n * @param ranges The ranges to consolidate\n * @returns Consolidated ranges\n */\n static consolidate(ranges: GridRange[]): GridRange[] {\n const result = ranges.slice();\n\n let wasModified = true;\n while (wasModified) {\n wasModified = false;\n for (let i = 0; i < result.length && !wasModified; i += 1) {\n const range = result[i];\n for (let j = result.length - 1; j > i; j -= 1) {\n const other = result[j];\n\n // If one contains the other, we can just keep the bigger one\n if (range.contains(other)) {\n result.splice(j, 1);\n } else if (other.contains(range)) {\n wasModified = true;\n result[i] = other;\n result.splice(j, 1);\n break;\n } else if (\n range.startRow === other.startRow &&\n range.endRow === other.endRow\n ) {\n if (range.touches(other)) {\n // If the start/end rows match, and columns touch, consolidate\n const { startRow, endRow } = range;\n const startColumn = GridRange.minOrNull(\n range.startColumn,\n other.startColumn\n );\n const endColumn = GridRange.maxOrNull(\n range.endColumn,\n other.endColumn\n );\n\n wasModified = true;\n result[i] = new GridRange(\n startColumn,\n startRow,\n endColumn,\n endRow\n );\n result.splice(j, 1);\n break;\n }\n } else if (\n range.startColumn === other.startColumn &&\n range.endColumn === other.endColumn\n ) {\n if (range.touches(other)) {\n // If the start/end rows match, and columns touch, consolidate\n const { startColumn, endColumn } = range;\n const startRow = GridRange.minOrNull(\n range.startRow,\n other.startRow\n );\n const endRow = GridRange.maxOrNull(range.endRow, other.endRow);\n\n wasModified = true;\n result[i] = new GridRange(\n startColumn,\n startRow,\n endColumn,\n endRow\n );\n result.splice(j, 1);\n break;\n }\n }\n }\n }\n }\n\n return result;\n }\n\n /**\n * Checks if the 1-D ranges between 2 index pairs overlap or are continuous.\n * For example ranges [0, 1] and [2, 3] are continuous and will return true.\n * [0, 1] and [1, 3] overlap and return true.\n * [0, 1] and [3, 4] do not overlap and have a gap so this will return false.\n * @param start1 Start of 1st range\n * @param end1 End of 1st range\n * @param start2 Start of 2nd range\n * @param end2 End of 2nd range\n * @returns True if the ranges overlap or touch, else false\n */\n static isAxisRangeTouching(\n start1: GridRangeIndex,\n end1: GridRangeIndex,\n start2: GridRangeIndex,\n end2: GridRangeIndex\n ): boolean {\n if (start1 == null) {\n if (end1 == null) {\n return true;\n }\n\n if (start2 == null) {\n return true;\n }\n\n return start2 <= end1 + 1;\n }\n\n if (end1 == null) {\n if (end2 == null) {\n return true;\n }\n\n return end2 >= start1 - 1;\n }\n\n if (start2 == null) {\n if (end2 == null) {\n return true;\n }\n\n return start1 <= end2 + 1;\n }\n\n if (end2 == null) {\n return end1 >= start2 - 1;\n }\n\n if (start2 >= start1 - 1) {\n return start2 <= end1 + 1;\n }\n\n return end2 >= start1 - 1;\n }\n\n /**\n * Checks if 2 arrays of ranges are the same ranges\n * @param ranges1 First array of ranges\n * @param ranges2 Second array of ranges\n * @returns True if the arrays contain the same ranges in the same order\n */\n static rangeArraysEqual(ranges1: GridRange[], ranges2: GridRange[]): boolean {\n if (ranges1 === ranges2) {\n return true;\n }\n\n if (\n ranges1 == null ||\n ranges2 == null ||\n ranges1.length !== ranges2.length\n ) {\n return false;\n }\n\n for (let i = 0; i < ranges1.length; i += 1) {\n if (!ranges1[i].equals(ranges2[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Get the intersection (overlapping area) of two ranges\n * @param range One range to check for the intersection\n * @param otherRange The other range to check for the intersection\n * @returns Intersection of the two ranges. If they do not intersect, returns `null`.\n */\n static intersection(\n range: GridRange,\n otherRange: GridRange\n ): GridRange | null {\n if (range.equals(otherRange)) {\n return range;\n }\n\n let { startColumn, startRow, endColumn, endRow } = range;\n startColumn =\n startColumn != null && otherRange.startColumn != null\n ? Math.max(startColumn, otherRange.startColumn)\n : startColumn ?? otherRange.startColumn;\n endColumn =\n endColumn != null && otherRange.endColumn != null\n ? Math.min(endColumn, otherRange.endColumn)\n : endColumn ?? otherRange.endColumn;\n startRow =\n startRow != null && otherRange.startRow != null\n ? Math.max(startRow, otherRange.startRow)\n : startRow ?? otherRange.startRow;\n endRow =\n endRow != null && otherRange.endRow != null\n ? Math.min(endRow, otherRange.endRow)\n : endRow ?? otherRange.endRow;\n\n if (\n (startColumn != null && startColumn > (endColumn ?? -1)) ||\n (startRow != null && startRow > (endRow ?? -1))\n ) {\n return null;\n }\n\n return new GridRange(startColumn, startRow, endColumn, endRow);\n }\n\n /**\n * Subtracts 1 range from another\n * @param range The range to be subtracted from\n * @param subtractRange The range to subtract from within this range\n * @returns The ranges needed to represent the remaining\n */\n static subtractFromRange(\n range: GridRange,\n subtractRange: GridRange\n ): GridRange[] {\n const result = [];\n\n // Make it a little easier by finding only the part the subtraction range intersects\n const subtract = GridRange.intersection(range, subtractRange);\n if (subtract == null) {\n return [range];\n }\n\n // Go through each of the quadrants for deselection, there can be up to 4\n // Top quadrant (above the subtracted area)\n if (\n subtract.startRow != null &&\n (range.startRow == null || range.startRow < subtract.startRow)\n ) {\n result.push(\n new GridRange(\n range.startColumn,\n range.startRow,\n range.endColumn,\n subtract.startRow - 1\n )\n );\n }\n\n // middle left\n if (\n subtract.startColumn != null &&\n (range.startColumn == null || range.startColumn < subtract.startColumn)\n ) {\n result.push(\n new GridRange(\n range.startColumn,\n subtract.startRow,\n subtract.startColumn - 1,\n subtract.endRow\n )\n );\n }\n\n // middle right\n if (\n subtract.endColumn != null &&\n (range.endColumn == null || range.endColumn > subtract.endColumn)\n ) {\n result.push(\n new GridRange(\n subtract.endColumn + 1,\n subtract.startRow,\n range.endColumn,\n subtract.endRow\n )\n );\n }\n\n // Bottom quadrant\n if (\n subtract.endRow != null &&\n (range.endRow == null || range.endRow > subtract.endRow)\n ) {\n result.push(\n new GridRange(\n range.startColumn,\n subtract.endRow + 1,\n range.endColumn,\n range.endRow\n )\n );\n }\n\n return result;\n }\n\n /**\n * Subtract a range from multiple ranges\n * @param ranges The ranges to be subtracted from\n * @param subtractRange The range to subtract from within these ranges\n * @returns The ranges needed to represent the remaining\n */\n static subtractFromRanges(\n ranges: GridRange[],\n subtractRange: GridRange\n ): GridRange[] {\n const result: GridRange[] = [];\n for (let i = 0; i < ranges.length; i += 1) {\n result.push(...GridRange.subtractFromRange(ranges[i], subtractRange));\n }\n\n return result;\n }\n\n /**\n * Subtract multiple ranges from multiple ranges\n * @param ranges The ranges to be subtracted from\n * @param subtractRanges The ranges to subtract from within these ranges\n * @returns The ranges needed to represent the remaining\n */\n static subtractRangesFromRanges(\n ranges: GridRange[],\n subtractRanges: GridRange[]\n ): GridRange[] {\n if (!subtractRanges || subtractRanges.length === 0) {\n return ranges;\n }\n\n let result = [...ranges];\n for (let i = 0; i < subtractRanges.length; i += 1) {\n result = GridRange.subtractFromRanges(result, subtractRanges[i]);\n }\n\n return result;\n }\n\n /**\n * Test if a given range is bounded (all values are non-null)\n * @param range The range to test\n * @returns True if this range is bounded, false otherwise\n */\n static isBounded(range: GridRange): range is BoundedGridRange {\n return (\n range.startRow != null &&\n range.startColumn != null &&\n range.endRow != null &&\n range.endColumn != null\n );\n }\n\n /**\n * Converts any GridRange passed in that is a full row or column selection to be bound\n * to the `columnCount` and `rowCount` passed in\n *\n * @param range The range to get the bounded range of\n * @param columnCount The number of columns\n * @param rowCount The number of rows\n * @returns The passed in GridRange with any null values filled in\n */\n static boundedRange(\n range: GridRange,\n columnCount: number,\n rowCount: number\n ): GridRange {\n if (GridRange.isBounded(range)) {\n return range;\n }\n\n return new GridRange(\n range.startColumn ?? 0,\n range.startRow ?? 0,\n range.endColumn ?? columnCount - 1,\n range.endRow ?? rowCount - 1\n );\n }\n\n /**\n * Converts the GridRanges passed in to be bound to the `columnCount` and `rowCount` passed in\n *\n * @param ranges The ranges to get the bounded ranges of\n * @param columnCount The number of columns\n * @param rowCount The number of rows\n * @returns The passed in GridRange with any null values filled in\n */\n static boundedRanges(\n ranges: GridRange[],\n columnCount: number,\n rowCount: number\n ): GridRange[] {\n return ranges.map(r => GridRange.boundedRange(r, columnCount, rowCount));\n }\n\n /**\n * Offsets a GridRange by the specified amount in the x and y directions\n *\n * @param range The range to offset\n * @param columnOffset The number of columns to offset\n * @param rowOffset The number of rows to offset\n * @returns The new grid range offset from the original\n */\n static offset(\n range: GridRange,\n columnOffset: number,\n rowOffset: number\n ): GridRange {\n return new GridRange(\n range.startColumn != null ? range.startColumn + columnOffset : null,\n range.startRow != null ? range.startRow + rowOffset : null,\n range.endColumn != null ? range.endColumn + columnOffset : null,\n range.endRow != null ? range.endRow + rowOffset : null\n );\n }\n\n /**\n * Get the next cell given the selected ranges and the current cell\n * @param ranges The selected bounded ranges within the grid\n * @param column The cursor column, or null if none focused\n * @param row The cursor row, or null if none focused\n * @param direction The direction in which to select next\n * @returns The next cell to focus, or null if there should be no more focus\n */\n static nextCell(\n ranges: GridRange[],\n column: GridRangeIndex = null,\n row: GridRangeIndex = null,\n direction = GridRange.SELECTION_DIRECTION.DOWN\n ): GridCell | null {\n if (ranges.length === 0) {\n return null;\n }\n\n let rangeIndex = -1;\n if (column != null && row != null) {\n rangeIndex = ranges.findIndex(r => r.containsCell(column, row));\n\n if (rangeIndex >= 0) {\n const range = ranges[rangeIndex];\n const nextCell = range.nextCell(column, row, direction);\n if (nextCell != null) {\n return nextCell;\n }\n }\n }\n\n // Otherwise go to the start of the next range (could be same range if only one range)\n switch (direction) {\n case GridRange.SELECTION_DIRECTION.DOWN:\n case GridRange.SELECTION_DIRECTION.RIGHT: {\n const nextRangeIndex =\n rangeIndex < ranges.length - 1 ? rangeIndex + 1 : 0;\n const nextRange = ranges[nextRangeIndex];\n return nextRange.startCell(direction);\n }\n case GridRange.SELECTION_DIRECTION.LEFT:\n case GridRange.SELECTION_DIRECTION.UP: {\n const nextRangeIndex =\n rangeIndex > 0 ? rangeIndex - 1 : ranges.length - 1;\n const nextRange = ranges[nextRangeIndex];\n return nextRange.startCell(direction);\n }\n default:\n throw new Error(`Invalid direction: ${direction}`);\n }\n }\n\n /**\n * Count the number of cells in the provided grid ranges\n * @param ranges The ranges to count the rows of\n * @returns The number of cells in the ranges, or `NaN` if any of the ranges were unbounded\n */\n static cellCount(ranges: GridRange[]): number {\n return ranges.reduce(\n (cellCount, range) =>\n cellCount +\n ((range.endRow ?? NaN) - (range.startRow ?? NaN) + 1) *\n ((range.endColumn ?? NaN) - (range.startColumn ?? NaN) + 1),\n 0\n );\n }\n\n /**\n * Count the number of rows in the provided grid ranges\n * @param ranges The ranges to count the rows of\n * @returns The number of rows in the ranges, or `NaN` if any of the ranges were unbounded\n */\n static rowCount(ranges: GridRange[]): number {\n return ranges.reduce(\n (rowCount, range) =>\n rowCount + (range.endRow ?? NaN) - (range.startRow ?? NaN) + 1,\n 0\n );\n }\n\n /**\n * Count the number of columns in the provided grid ranges\n * @param ranges The ranges to count the columns of\n * @returns The number of columns in the ranges, or `NaN` if any of the ranges were unbounded\n */\n static columnCount(ranges: GridRange[]): number {\n return ranges.reduce(\n (columnCount, range) =>\n columnCount + (range.endColumn ?? NaN) - (range.startColumn ?? NaN) + 1,\n 0\n );\n }\n\n /**\n * Check if the provided ranges contain the provided cell\n * @param ranges The ranges to check\n * @param column The column index\n * @param row The row index\n * @returns True if the cell is within the provided ranges, false otherwise.\n */\n static containsCell(\n ranges: GridRange[],\n column: GridRangeIndex,\n row: GridRangeIndex\n ): boolean {\n for (let i = 0; i < ranges.length; i += 1) {\n const range = ranges[i];\n if (range.containsCell(column, row)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Iterate through each cell in the provided ranges\n * @param ranges The ranges to iterate through\n * @param {(column: number, row: number, index: number) => void} callback The callback to execute. `index` is the index within that range\n * @param {GridRange.SELECTION_DIRECTION} direction The direction to iterate in\n */\n static forEachCell(\n ranges: GridRange[],\n callback: (column: number, row: number, index: number) => void,\n direction = GridRange.SELECTION_DIRECTION.RIGHT\n ): void {\n for (let i = 0; i < ranges.length; i += 1) {\n ranges[i].forEach(callback, direction);\n }\n }\n\n constructor(\n startColumn: GridRangeIndex,\n startRow: GridRangeIndex,\n endColumn: GridRangeIndex,\n endRow: GridRangeIndex\n ) {\n this.startColumn = startColumn;\n this.startRow = startRow;\n this.endColumn = endColumn;\n this.endRow = endRow;\n }\n\n /**\n * Checks if the provided range is equivalent to this range (same start and end column/row indexes)\n * @param other Grid range to check against\n * @returns True if the ranges cover the same area\n */\n equals(other: GridRange): boolean {\n return (\n this.startColumn === other.startColumn &&\n this.startRow === other.startRow &&\n this.endColumn === other.endColumn &&\n this.endRow === other.endRow\n );\n }\n\n /**\n * Checks if this GridRange contains another range\n * @param other The range to check\n * @returns True if this GridRange completely contains `other`\n * */\n contains(other: GridRange): boolean {\n return (\n (this.startColumn == null ||\n (other.startColumn != null && this.startColumn <= other.startColumn)) &&\n (this.startRow == null ||\n (other.startRow != null && this.startRow <= other.startRow)) &&\n (this.endColumn == null ||\n (other.endColumn != null && this.endColumn >= other.endColumn)) &&\n (this.endRow == null ||\n (other.endRow != null && this.endRow >= other.endRow))\n );\n }\n\n /**\n * Check if the provided cell is in this range\n * @param column The column to check\n * @param row The row to check\n * @returns True if this cell is within this range\n */\n containsCell(column: GridRangeIndex, row: GridRangeIndex): boolean {\n if (column == null || row == null) {\n return false;\n }\n\n return (\n (this.startColumn == null || this.startColumn <= column) &&\n (this.endColumn == null || this.endColumn >= column) &&\n (this.startRow == null || this.startRow <= row) &&\n (this.endRow == null || this.endRow >= row)\n );\n }\n\n /**\n * Check if the provided range touches (or overlaps) this GridRange\n * Effectively checks if the 2 ranges could be represented by 1 continuous range\n * @param other The range to check\n * @returns True if this GridRange touches `other`\n * */\n touches(other: GridRange): boolean {\n return (\n GridRange.isAxisRangeTouching(\n this.startRow,\n this.endRow,\n other.startRow,\n other.endRow\n ) &&\n GridRange.isAxisRangeTouching(\n this.startColumn,\n this.endColumn,\n other.startColumn,\n other.endColumn\n )\n );\n }\n\n /**\n * Subtracts a range from this range\n * @param other The range to deselect from within this range\n * @returns The ranges needed to represent the remaining\n */\n subtract(other: GridRange): GridRange[] {\n return GridRange.subtractFromRange(this, other);\n }\n\n /**\n * Get the first cell in this range. Throws if this range is unbounded.\n *\n * @param direction The direction to get the starting cell in. Defaults to DOWN\n * @returns The first cell in this range in the direction specified\n */\n startCell(direction = GridRange.SELECTION_DIRECTION.DOWN): GridCell {\n if (!GridRange.isBounded(this)) {\n throw new Error('Cannot get the startCell of an unbounded range');\n }\n\n switch (direction) {\n case GridRange.SELECTION_DIRECTION.DOWN:\n case GridRange.SELECTION_DIRECTION.RIGHT:\n return { column: this.startColumn, row: this.startRow };\n case GridRange.SELECTION_DIRECTION.LEFT:\n case GridRange.SELECTION_DIRECTION.UP: {\n return { column: this.endColumn, row: this.endRow };\n }\n default:\n throw new Error(`Invalid direction: ${direction}`);\n }\n }\n\n /**\n * Get the next cell in the direction specified. Throws if this range is unbounded.\n * If already at the bounds of the range in that direction, wrap to the next column or row\n * If at the end of the entire range, return null\n * If outside of the range, returns the next cell closest within this range.\n *\n * @param {number} column The cursor column\n * @param {number} row The cursor row\n * @param {SELECTION_DIRECTION} direction The direction to go in\n * @returns {GridCell|null} The next cell in the direction specified, or `null` if at the end of the range\n */\n nextCell(\n column: GridRangeIndex,\n row: GridRangeIndex,\n direction: SELECTION_DIRECTION\n ): GridCell | null {\n if (!GridRange.isBounded(this)) {\n throw new Error('Bounded range required');\n }\n if (column == null || row == null) {\n throw new Error('Require a non-null cursor');\n }\n\n const { startColumn, endColumn, startRow, endRow } = this;\n\n switch (direction) {\n case GridRange.SELECTION_DIRECTION.DOWN:\n if (row < endRow) {\n return { column, row: Math.max(row + 1, startRow) };\n }\n\n if (column < endColumn) {\n return { column: Math.max(column + 1, startColumn), row: startRow };\n }\n break;\n case GridRange.SELECTION_DIRECTION.UP:\n if (row > startRow) {\n return { column, row: Math.min(row - 1, endRow) };\n }\n\n if (column > startColumn) {\n return { column: Math.min(column - 1, endColumn), row: endRow };\n }\n break;\n case GridRange.SELECTION_DIRECTION.RIGHT:\n if (column < endColumn) {\n return { column: Math.max(column + 1, startColumn), row };\n }\n\n if (row < endRow) {\n return { column: startColumn, row: Math.max(row + 1, startRow) };\n }\n break;\n case GridRange.SELECTION_DIRECTION.LEFT:\n if (column > startColumn) {\n return { column: Math.min(column - 1, endColumn), row };\n }\n\n if (row > startRow) {\n return { column: endColumn, row: Math.min(row - 1, endRow) };\n }\n break;\n default:\n throw new Error(`Invalid direction: ${direction}`);\n }\n\n return null;\n }\n\n /**\n * Iterate through each cell in the range\n * @param callback Callback to execute. `index` is the index within this range\n * @param direction The direction to iterate in\n */\n forEach(\n callback: (column: number, row: number, index: number) => void,\n direction = GridRange.SELECTION_DIRECTION.RIGHT\n ): void {\n let i = 0;\n let {\n column: c,\n row: r,\n }: { column?: number; row?: number } = this.startCell(direction);\n while (c != null && r != null) {\n callback(c, r, i);\n i += 1;\n\n ({ column: c, row: r } = this.nextCell(c, r, direction) ?? {});\n }\n }\n}\n\nexport default GridRange;\n","import React from 'react';\nimport GridRange, { GridRangeIndex } from './GridRange';\nimport {\n BoxCoordinates,\n Coordinate,\n CoordinateMap,\n VisibleIndex,\n IndexModelMap,\n ModelIndex,\n ModelSizeMap,\n MoveOperation,\n SizeMap,\n} from './GridMetrics';\nimport type { GridMetrics } from './GridMetrics';\nimport { GridTheme } from './GridTheme';\n\nexport type AxisRange = [start: VisibleIndex, end: VisibleIndex];\n\nexport type GridAxisRange = [start: GridRangeIndex, end: GridRangeIndex];\n\nexport type GridPoint = {\n x: Coordinate;\n y: Coordinate;\n column: GridRangeIndex;\n row: GridRangeIndex;\n};\n\nexport type IndexCallback<T> = (itemIndex: VisibleIndex) => T | undefined;\n\nclass GridUtils {\n // use same constant as chrome source for windows\n // https://github.com/chromium/chromium/blob/973af9d461b6b5dc60208c8d3d66adc27e53da78/ui/events/blink/web_input_event_builders_win.cc#L285\n static PIXELS_PER_LINE = 100 / 3;\n\n /**\n * Get the GridPoint for the coordinates provided\n * @param x The grid x coordinate\n * @param y The grid y coordinate\n * @param metrics The grid metrics\n * @returns The GridPoint including the column/row information\n */\n static getGridPointFromXY(\n x: Coordinate,\n y: Coordinate,\n metrics: GridMetrics\n ): GridPoint {\n const column = GridUtils.getColumnAtX(x, metrics);\n const row = GridUtils.getRowAtY(y, metrics);\n\n return { x, y, row, column };\n }\n\n /**\n * Iterate through each floating item at the start and call a callback, returning the first result\n * @param start The count of floating items at the start\n * @param total The total number of items\n * @param callback Function to call for each item\n * @returns The result from the callback\n */\n static iterateFloatingStart<T>(\n start: number,\n total: number,\n callback: IndexCallback<T>\n ): T | undefined {\n for (let i = 0; i < start && i < total; i += 1) {\n const result = callback(i);\n if (result !== undefined) {\n return result;\n }\n }\n\n return undefined;\n }\n\n /**\n * Iterate through floating items at the end. Iterates in increasing order.\n * @param end The count of floating items at the end\n * @param total The total number of items\n * @param callback Function to call for each item\n * @returns The result from the callback\n */\n static iterateFloatingEnd<T>(\n end: number,\n total: number,\n callback: IndexCallback<T>\n ): T | undefined {\n for (let i = 0; i < end && total - (end - i) >= 0; i += 1) {\n const result = callback(total - (end - i));\n if (result !== undefined) {\n return result;\n }\n }\n\n return undefined;\n }\n\n /**\n * Iterate through all floating items in increasing order, starting with the top items.\n * @param start Count of start floating rows, e.g. floatingTopRowCount\n * @param end Count of end floating rows, e.g. floatingBottomRowCount\n * @param total Total number of items\n * @param callback Callback called for each value, stopping the iterating and returning the value if one is returned\n */\n static iterateFloating<T>(\n start: number,\n end: number,\n total: number,\n callback: IndexCallback<T>\n ): T | undefined {\n const result = GridUtils.iterateFloatingStart(start, total, callback);\n if (result !== undefined) {\n return result;\n }\n return GridUtils.iterateFloatingEnd(end, total, callback);\n }\n\n /**\n * Iterate through all items in one dimension on the grid - first floating, then visible.\n * Call the callback for each item, break if a result is returned and return that result.\n * @param visibleStart Index of the start of the visible viewport\n * @param visibleEnd Index of the end of the visible viewport\n * @param floatingStartCount Number of items floating at the start\n * @param floatingEndCount Number of items floating at the end\n * @param totalCount Total number of items\n * @param callback Callback to call for each item\n * @returns The first result from the callback called, or undefined\n */\n static iterateAllItems<T>(\n visibleStart: VisibleIndex,\n visibleEnd: VisibleIndex,\n floatingStartCount: number,\n floatingEndCount: number,\n totalCount: number,\n callback: IndexCallback<T>\n ): T | undefined {\n const visibleStartIndex = Math.max(visibleStart, floatingStartCount);\n const visibleEndIndex = Math.min(\n visibleEnd,\n totalCount - floatingEndCount - 1\n );\n let result = GridUtils.iterateFloating(\n floatingStartCount,\n floatingEndCount,\n totalCount,\n callback\n );\n if (result !== undefined) {\n return result;\n }\n\n for (let i = visibleStartIndex; i <= visibleEndIndex; i += 1) {\n result = callback(i);\n if (result !== undefined) {\n return result;\n }\n }\n\n return undefined;\n }\n\n /**\n * Check if the coordinate is within the item specified in this dimension\n * @param itemIndex Index of the item to check\n * @param itemCoordinatess Coordinate of all items in this dimension\n * @param itemSizes Size of all items in this dimension\n * @param coordinate The coordinate to check\n * @returns True if the coordinate is within the item specified, false otherwise\n */\n static isInItem(\n itemIndex: VisibleIndex,\n itemCoordinates: CoordinateMap,\n itemSizes: SizeMap,\n coordinate: Coordinate\n ): boolean {\n const itemX = itemCoordinates.get(itemIndex) ?? 0;\n const itemSize = itemSizes.get(itemIndex) ?? 0;\n return itemX <= coordinate && coordinate <= itemX + itemSize;\n }\n\n /**\n * Get the Index of the item at the provided offset\n * @param offset Coordinate of the offset to get the item of\n * @param itemCount The total count of items\n * @param floatingStart Count of floating items at the start\n * @param floatingEnd Count of floating items at the end\n * @param items Index of all items\n * @param itemCoordinates The coordinate of each item\n * @param itemSizes The size of each item\n * @returns The item index, or null if no item matches\n */\n static getItemAtOffset(\n offset: Coordinate,\n itemCount: number,\n floatingStart: number,\n floatingEnd: number,\n items: VisibleIndex[],\n itemCoordinates: CoordinateMap,\n itemSizes: SizeMap\n ): VisibleIndex | null {\n const floatingItem = GridUtils.iterateFloating(\n floatingStart,\n floatingEnd,\n itemCount,\n item => {\n if (GridUtils.isInItem(item, itemCoordinates, itemSizes, offset)) {\n return item;\n }\n return undefined;\n }\n );\n if (floatingItem !== undefined) {\n return floatingItem;\n }\n\n for (let i = 0; i < items.length; i += 1) {\n const item = items[i];\n if (GridUtils.isInItem(item, itemCoordinates, itemSizes, offset)) {\n return item;\n }\n }\n\n return null;\n }\n\n /**\n * Get the index of the column at the specified x coordinate\n * @param x Coordinate to get the item of\n * @param metrics Grid metrics\n * @returns Index of the column at that coordinate, or null if no column matches\n */\n static getColumnAtX(\n x: Coordinate,\n metrics: GridMetrics\n ): VisibleIndex | null {\n const {\n columnCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths,\n gridX,\n } = metrics;\n\n if (x < gridX) {\n return null;\n }\n\n return this.getItemAtOffset(\n x - gridX,\n columnCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths\n );\n }\n\n /**\n * Get the index of the row at the specified y coordinate\n * @param y Coordinate to get the item of\n * @param metrics Grid metrics\n * @returns Index of the row at that coordinate, or null if no row matches\n */\n static getRowAtY(y: Coordinate, metrics: GridMetrics): VisibleIndex | null {\n const {\n floatingTopRowCount,\n floatingBottomRowCount,\n rowCount,\n visibleRows,\n visibleRowYs,\n visibleRowHeights,\n gridY,\n } = metrics;\n\n if (y < gridY) {\n return null;\n }\n\n return this.getItemAtOffset(\n y - gridY,\n rowCount,\n floatingTopRowCount,\n floatingBottomRowCount,\n visibleRows,\n visibleRowYs,\n visibleRowHeights\n );\n }\n\n /**\n * Iterate backward through the visible items until a shown item is hit\n * @param startIndex The index to start from\n * @param modelIndexes The mapping of model indexes\n * @param visibleItems The visible items\n * @param userSizes The user set sizes\n * @returns Index of the next visible item, or null if no more are visible\n */\n static getNextShownItem(\n startIndex: VisibleIndex,\n modelIndexes: IndexModelMap,\n visibleItems: VisibleIndex[],\n userSizes: ModelSizeMap\n ): VisibleIndex | null {\n let visibleItemIndex =\n visibleItems.findIndex(value => value === startIndex) || 0;\n visibleItemIndex -= 1;\n while (visibleItemIndex != null && visibleItemIndex >= 0) {\n const item = visibleItems[visibleItemIndex];\n const modelIndex = modelIndexes.get(item);\n if (modelIndex != null && userSizes.get(modelIndex) !== 0) {\n return item;\n }\n\n visibleItemIndex -= 1;\n }\n\n return null;\n }\n\n /**\n * Iterate backward through the visible columns until a shown column is hit\n * @param columnIndex The column index to start iterating backward from\n * @param metrics The GridMetricCalculator metrics\n * @returns Index of the next visible item, or null if no more are visible\n */\n static getNextShownColumn(\n startIndex: VisibleIndex,\n metrics: GridMetrics\n ): VisibleIndex | null {\n const { modelColumns, visibleColumns, userColumnWidths } = metrics;\n return GridUtils.getNextShownItem(\n startIndex,\n modelColumns,\n visibleColumns,\n userColumnWidths\n );\n }\n\n /**\n * Iterate backward through the visible rows until a shown row is hit\n * @param rowIndex The row index to start iterating backward from\n * @param metrics The GridMetricCalculator metrics\n * @returns Index of the next visible item, or null if no more are visible\n */\n static getNextShownRow(\n startIndex: VisibleIndex,\n metrics: GridMetrics\n ): VisibleIndex | null {\n const { modelRows, visibleRows, userRowHeights } = metrics;\n return GridUtils.getNextShownItem(\n startIndex,\n modelRows,\n visibleRows,\n userRowHeights\n );\n }\n\n /**\n * Gets the column index if the x/y coordinates provided are close enough to the separator, otherwise null\n * @param x Mouse x coordinate\n * @param y Mouse y coordinate\n * @param metrics The grid metrics\n * @param theme The grid theme with potential user overrides\n * @returns Index of the column separator at the coordinates provided, or null if none match\n */\n static getColumnSeparatorIndex(\n x: Coordinate,\n y: Coordinate,\n metrics: GridMetrics,\n theme: GridTheme\n ): VisibleIndex | null {\n const {\n rowHeaderWidth,\n columnHeaderHeight,\n floatingColumns,\n floatingLeftWidth,\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths,\n } = metrics;\n const { allowColumnResize, headerSeparatorHandleSize } = theme;\n\n if (\n columnHeaderHeight < y ||\n !allowColumnResize ||\n headerSeparatorHandleSize <= 0\n ) {\n return null;\n }\n\n const gridX = x - rowHeaderWidth;\n const halfSeparatorSize = headerSeparatorHandleSize * 0.5;\n\n // Iterate through the floating columns first since they're on top\n let isPreviousColumnHidden = false;\n for (let i = floatingColumns.length - 1; i >= 0; i -= 1) {\n const column = floatingColumns[i];\n const columnX = visibleColumnXs.get(column) ?? 0;\n const columnWidth = visibleColumnWidths.get(column) ?? 0;\n const isColumnHidden = columnWidth === 0;\n if (!isPreviousColumnHidden || !isColumnHidden) {\n let midX = columnX + columnWidth;\n if (isColumnHidden) {\n midX += halfSeparatorSize;\n } else if (isPreviousColumnHidden) {\n midX -= halfSeparatorSize;\n }\n\n const minX = midX - halfSeparatorSize;\n const maxX = midX + halfSeparatorSize;\n if (minX <= gridX && gridX <= maxX) {\n return column;\n }\n\n isPreviousColumnHidden = isColumnHidden;\n }\n }\n\n // Iterate backward so that you can reveal hidden columns properly\n isPreviousColumnHidden = false;\n for (let i = visibleColumns.length - 1; i >= 0; i -= 1) {\n const column = visibleColumns[i];\n const columnX = visibleColumnXs.get(column) ?? 0;\n const columnWidth = visibleColumnWidths.get(column) ?? 0;\n const isColumnHidden = columnWidth === 0;\n\n // If this column is under the floating columns \"layer\". Terminate early.\n if (columnX < floatingLeftWidth - columnWidth) {\n return null;\n }\n\n if (!isPreviousColumnHidden || !isColumnHidden) {\n let midX = columnX + columnWidth;\n if (isColumnHidden) {\n midX += halfSeparatorSize;\n } else if (isPreviousColumnHidden) {\n midX -= halfSeparatorSize;\n }\n\n const minX = midX - halfSeparatorSize;\n const maxX = midX + halfSeparatorSize;\n if (minX <= gridX && gridX <= maxX) {\n return column;\n }\n\n isPreviousColumnHidden = isColumnHidden;\n }\n }\n\n return null;\n }\n\n /**\n * Check if the item specified is hidden\n * @param itemIndex Index of the item to check\n * @param visibleSizes Sizes of all visible items\n * @returns True if the item is hidden, false otherwise\n */\n static isItemHidden(itemIndex: VisibleIndex, visibleSizes: SizeMap): boolean {\n return visibleSizes.get(itemIndex) === 0;\n }\n\n /**\n * Check if the column specified is hidden\n * @param columnIndex Index of the column to check\n * @param metrics Grid metrics\n * @returns True if the column is hidden, false otherwise\n */\n static isColumnHidden(\n columnIndex: VisibleIndex,\n metrics: GridMetrics\n ): boolean {\n const { visibleColumnWidths } = metrics;\n return GridUtils.isItemHidden(columnIndex, visibleColumnWidths);\n }\n\n /**\n * Check if the provided row is a floating row\n * @param row The row index to check\n * @param metrics The grid metrics to check against\n * @returns True if it's a floating row, false otherwise\n */\n static isFloatingRow(row: VisibleIndex, metrics: GridMetrics): boolean {\n if (row == null) {\n return false;\n }\n\n const { floatingTopRowCount, floatingBottomRowCount, rowCount } = metrics;\n return (\n row < floatingTopRowCount || row >= rowCount - floatingBottomRowCount\n );\n }\n\n /**\n * Check if the provided column is a floating column\n * @param column The column index to check\n * @param metrics The grid metrics to check against\n * @returns True if it's a floating column, false otherwise\n */\n static isFloatingColumn(column: VisibleIndex, metrics: GridMetrics): boolean {\n if (column == null) {\n return false;\n }\n\n const {\n floatingLeftColumnCount,\n floatingRightColumnCount,\n columnCount,\n } = metrics;\n return (\n column < floatingLeftColumnCount ||\n column >= columnCount - floatingRightColumnCount\n );\n }\n\n /**\n * Get all the items that are hidden under the same Index\n * E.g. If columns are 1, 2, 3, 4, 5, and column 2, 3, 4 are hidden, and we check for item 4, the return will be [2, 3, 4]\n * @param itemIndex Index of the item to start at\n * @param visibleSizes Visible size map\n * @param visibleItems Visible items\n * @returns Array of items that are hidden\n */\n static getHiddenItems(\n itemIndex: VisibleIndex,\n visibleSizes: SizeMap,\n visibleItems: VisibleIndex[]\n ): VisibleIndex[] {\n if (!GridUtils.isItemHidden(itemIndex, visibleSizes)) {\n return [];\n }\n\n const hiddenItems = [itemIndex];\n const visibleItemIndex = visibleItems.findIndex(\n value => value === itemIndex\n );\n for (let i = visibleItemIndex - 1; i >= 0; i -= 1) {\n const item = visibleItems[i];\n if (!GridUtils.isItemHidden(item, visibleSizes)) {\n break;\n }\n\n hiddenItems.push(item);\n }\n\n return hiddenItems;\n }\n\n /**\n * Get all the columns that are hidden under the same Index\n * @param columnIndex Index of the item to start at\n * @param metrics Grid metrics\n * @returns Array of items that are hidden\n */\n static getHiddenColumns(\n columnIndex: VisibleIndex,\n metrics: GridMetrics\n ): VisibleIndex[] {\n const { visibleColumns, visibleColumnWidths } = metrics;\n return GridUtils.getHiddenItems(\n columnIndex,\n visibleColumnWidths,\n visibleColumns\n );\n }\n\n /**\n * Returns the row index if the x/y coordinates provided are close enough to the separator, otherwise null\n * @param x X coordinate to check\n * @param y Y coordinate to check\n * @param metrics The grid metrics\n * @param theme The grid theme\n * @returns Index of the row separator at the coordinates provided, or null if none match\n */\n static getRowSeparatorIndex(\n x: Coordinate,\n y: Coordinate,\n metrics: GridMetrics,\n theme: GridTheme\n ): VisibleIndex | null {\n const {\n rowHeaderWidth,\n columnHeaderHeight,\n visibleRows,\n visibleRowYs,\n visibleRowHeights,\n } = metrics;\n const { allowRowResize, headerSeparatorHandleSize } = theme;\n\n if (\n rowHeaderWidth < x ||\n !allowRowResize ||\n headerSeparatorHandleSize <= 0\n ) {\n return null;\n }\n\n const gridY = y - columnHeaderHeight;\n const halfSeparatorSize = headerSeparatorHandleSize * 0.5;\n\n // Iterate backward so you can reveal hidden rows properly\n let isPreviousRowHidden = false;\n for (let i = visibleRows.length - 1; i >= 0; i -= 1) {\n const row = visibleRows[i];\n const rowY = visibleRowYs.get(row) ?? 0;\n const rowHeight = visibleRowHeights.get(row) ?? 0;\n const isRowHidden = rowHeight === 0;\n if (!isPreviousRowHidden || !isRowHidden) {\n let midY = rowY + rowHeight;\n if (isRowHidden) {\n midY += halfSeparatorSize;\n } else if (isPreviousRowHidden) {\n midY -= halfSeparatorSize;\n }\n\n const minY = midY - halfSeparatorSize;\n const maxY = midY + halfSeparatorSize;\n\n if (minY <= gridY && gridY <= maxY) {\n return row;\n }\n\n isPreviousRowHidden = isRowHidden;\n }\n }\n\n return null;\n }\n\n /**\n * Check if the row specified is hidden\n * @param rowIndex Index of the row to check\n * @param metrics Grid metrics\n * @returns True if the row is hidden, false otherwise\n */\n static isRowHidden(rowIndex: VisibleIndex, metrics: GridMetrics): boolean {\n const { visibleRowHeights } = metrics;\n return GridUtils.isItemHidden(rowIndex, visibleRowHeights);\n }\n\n /**\n * Get all the rows that are hidden under the same Index\n * @param rowIndex Index of the item to start at\n * @param metrics Grid metrics\n * @returns Array of items that are hidden\n */\n static getHiddenRows(\n rowIndex: VisibleIndex,\n metrics: GridMetrics\n ): VisibleIndex[] {\n const { visibleRows, visibleRowHeights } = metrics;\n return GridUtils.getHiddenItems(rowIndex, visibleRowHeights, visibleRows);\n }\n\n /**\n * Set a new order for items in the grid\n * @param from The visible index to move from\n * @param to The visible index to move the itme to\n * @param oldMovedItems The old reordered items\n * @returns The new reordered items\n */\n static moveItem(\n from: VisibleIndex,\n to: VisibleIndex,\n oldMovedItems: MoveOperation[] = []\n ): MoveOperation[] {\n if (from === to) {\n return oldMovedItems;\n }\n\n const movedItems: MoveOperation[] = [...oldMovedItems];\n\n if (\n movedItems.length > 0 &&\n movedItems[movedItems.length - 1].to === from\n ) {\n movedItems[movedItems.length - 1] = {\n ...movedItems[movedItems.length - 1],\n to,\n };\n } else {\n movedItems.push({ from, to });\n }\n\n return movedItems;\n }\n\n /**\n * Retrieve the model index given the currently moved items\n * @param visibleIndex The visible index of the item to get the model index for\n * @param movedItems The moved items\n * @returns The model index of the item\n */\n static getModelIndex(\n visibleIndex: VisibleIndex,\n movedItems: MoveOperation[] = []\n ): ModelIndex {\n let modelIndex = visibleIndex;\n\n for (let i = movedItems.length - 1; i >= 0; i -= 1) {\n const movedItem = movedItems[i];\n if (modelIndex === movedItem.to) {\n ({ from: modelIndex } = movedItem);\n } else if (movedItem.from <= modelIndex && modelIndex < movedItem.to) {\n modelIndex += 1;\n } else if (movedItem.to < modelIndex && modelIndex <= movedItem.from) {\n modelIndex -= 1;\n }\n }\n\n return modelIndex;\n }\n\n /**\n * Translate the provided UI start/end indexes to the model start/end indexes by applying the `movedItems` transformations.\n * Since moved items can split apart a range, multiple pairs of indexes are returned\n *\n * @param start Start item in one dimension\n * @param end End item in one dimension\n * @param movedItems Moved item pairs in this dimension\n * @returns Array of start/end pairs of the indexes after transformations applied.\n */\n static getModelRangeIndexes(\n start: GridRangeIndex,\n end: GridRangeIndex,\n movedItems: MoveOperation[]\n ): GridAxisRange[] {\n if (start == null || end == null) {\n return [[start, end]];\n }\n\n let result: [VisibleIndex, VisibleIndex][] = [[start, end]];\n if (start == null) {\n return result;\n }\n\n // movedItems is built by adding a new item whenever an item in the UI is dragged/moved, transforming a model\n // index to the new UI index. We want to find the model index from the UI index here, so we unwind the\n // transformations applied - the start/end axis range passed in is the current UI range, so we need to apply\n // the transformations starting at the end of the chain backward to find the appropriate model indexes\n for (let i = movedItems.length - 1; i >= 0; i -= 1) {\n const { from, to } = movedItems[i];\n const nextResult: [VisibleIndex, VisibleIndex][] = [];\n for (let j = 0; j < result.length; j += 1) {\n const [currentStart, currentEnd] = result[j];\n const startLength = nextResult.length;\n if (from <= currentStart) {\n // From before\n if (to > currentEnd) {\n // To after\n nextResult.push([currentStart + 1, currentEnd + 1]);\n } else if (to >= currentStart) {\n // To within\n nextResult.push([from, from]);\n nextResult.push([currentStart + 1, currentEnd]);\n }\n } else if (from > currentEnd) {\n // From after\n if (to < currentStart) {\n // To before\n nextResult.push([currentStart - 1, currentEnd - 1]);\n } else if (to <= currentEnd) {\n // To within\n nextResult.push([from, from]);\n nextResult.push([currentStart, currentEnd - 1]);\n }\n } else if (to < currentStart) {\n // From within to before\n nextResult.push([currentStart - 1, from - 1]);\n nextResult.push([from + 1, currentEnd]);\n } else if (to > currentEnd) {\n // From within to after\n nextResult.push([currentStart, from - 1]);\n nextResult.push([from + 1, currentEnd + 1]);\n } else if (from > to) {\n // From within after to within before\n if (to > currentStart) {\n nextResult.push([currentStart, to - 1]);\n }\n nextResult.push([from, from]);\n nextResult.push([to, from - 1]);\n if (from < currentEnd) {\n nextResult.push([from + 1, currentEnd]);\n }\n } else if (from < to) {\n // From within before to within after\n if (from > currentStart) {\n nextResult.push([currentStart, from - 1]);\n }\n nextResult.push([from + 1, to]);\n nextResult.push([from, from]);\n if (from < currentEnd) {\n nextResult.push([to + 1, currentEnd]);\n }\n }\n\n if (startLength === nextResult.length) {\n // No modifications were made, add the original range indexes\n nextResult.push([currentStart, currentEnd]);\n }\n }\n result = nextResult;\n }\n return result;\n }\n\n /**\n * Translate the provided UI range into model range, using the `movedColumns` and `movedRows` to apply the necessary transforms.\n * `movedColumns` and `movedRows` are array of operations done to the UI indexes to re-order items\n *\n * @param uiRange The currently selected UI ranges\n * @param movedColumns The moved column pairs\n * @param movedRows The moved row pairs\n * @returns The model ranges after translation.\n */\n static getModelRange(\n uiRange: GridRange,\n movedColumns: MoveOperation[] = [],\n movedRows: MoveOperation[] = []\n ): GridRange[] {\n const columnRanges = GridUtils.getModelRangeIndexes(\n uiRange.startColumn,\n uiRange.endColumn,\n movedColumns\n );\n const rowRanges = GridUtils.getModelRangeIndexes(\n uiRange.startRow,\n uiRange.endRow,\n movedRows\n );\n const ranges: GridRange[] = [];\n for (let i = 0; i < columnRanges.length; i += 1) {\n const c = columnRanges[i];\n for (let j = 0; j < rowRanges.length; j += 1) {\n const r = rowRanges[j];\n ranges.push(new GridRange(c[0], r[0], c[1], r[1]));\n }\n }\n return ranges;\n }\n\n /**\n * Translate the provided UI range into model ranges, using the `movedColumns` and `movedRows` to apply the necessary transforms.\n * `movedColumns` and `movedRows` are array of operations done to the UI indexes to re-order items\n *\n * @param uiRanges The currently selected UI ranges\n * @param movedColumns The moved column pairs\n * @param movedRows The moved row pairs\n * @returns The model ranges after translation.\n */\n static getModelRanges(\n uiRanges: GridRange[],\n movedColumns: MoveOperation[] = [],\n movedRows: MoveOperation[] = []\n ): GridRange[] {\n const modelRanges = [];\n for (let i = 0; i < uiRanges.length; i += 1) {\n modelRanges.push(\n ...GridUtils.getModelRange(uiRanges[i], movedColumns, movedRows)\n );\n }\n return modelRanges;\n }\n\n /**\n * Retrieve the visible index given the currently moved items\n * @param modelIndex The model index to get the visible index for\n * @param movedItems Moved items\n * @returns The visible index of the item\n */\n static getVisibleIndex(\n modelIndex: ModelIndex,\n movedItems: MoveOperation[] = []\n ): VisibleIndex {\n let visibleIndex = modelIndex;\n\n for (let i = 0; i < movedItems.length; i += 1) {\n const movedItem = movedItems[i];\n if (visibleIndex === movedItem.from) {\n ({ to: visibleIndex } = movedItem);\n } else if (\n movedItem.from < visibleIndex &&\n visibleIndex <= movedItem.to\n ) {\n visibleIndex -= 1;\n } else if (\n movedItem.to <= visibleIndex &&\n visibleIndex < movedItem.from\n ) {\n visibleIndex += 1;\n }\n }\n\n return visibleIndex;\n }\n\n /**\n * Check if the current platform is Mac\n * @returns True if this platform is a Mac, false otherwise\n */\n static isMacPlatform(): boolean {\n const { platform } = window.navigator;\n return platform.startsWith('Mac');\n }\n\n /**\n * Get the modifier key for the current platform\n * @returns The modifier key for the current platform\n */\n static getModifierKey(): 'metaKey' | 'ctrlKey' {\n if (GridUtils.isMacPlatform()) {\n return 'metaKey';\n }\n\n return 'ctrlKey';\n }\n\n /**\n * Check if the modifier key is down for the given event\n * @param event The event to check\n * @returns True if the modifier key is down, false otherwise\n */\n static isModifierKeyDown(\n event: MouseEvent | KeyboardEvent | React.KeyboardEvent | React.MouseEvent\n ): boolean {\n const modifierKey = GridUtils.getModifierKey();\n return event[modifierKey];\n }\n\n /**\n * Check if the user has hidden the specified column\n * @param modelIndex The model index to check\n * @param userColumnWidths The user set column widths\n * @returns True if the user has hidden the column\n */\n static checkColumnHidden(\n modelIndex: ModelIndex,\n userColumnWidths: ModelSizeMap\n ): boolean {\n return userColumnWidths.get(modelIndex) === 0;\n }\n\n /**\n * Check if all the columns specified are hidden\n * @param columns Columns to check\n * @param userColumnWidths The user set column widths\n * @returns True if the user has hidden all of the columns\n */\n static checkAllColumnsHidden(\n columns: ModelIndex[],\n userColumnWidths: ModelSizeMap\n ): boolean {\n if (userColumnWidths.size === 0) {\n return false;\n }\n return columns.every(column => userColumnWidths.get(column) === 0);\n }\n\n /**\n * Get the bounds the mouse needs to be dragged outside of from an initial selection before scrolling occurs.\n * Taking into account any floating rows that may be covering the viewport.\n * @param metrics Grid metrics\n * @param row The row they started dragging in\n * @param column The column they started the drag from\n * @returns Dimensions of the drag area in relation to the canvas they need to drag outside of to start scrolling\n */\n static getScrollDragBounds(\n metrics: GridMetrics,\n row: GridRangeIndex,\n column: GridRangeIndex\n ): BoxCoordinates {\n const {\n gridX,\n gridY,\n width,\n height,\n floatingTopRowCount,\n floatingBottomRowCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n floatingLeftWidth,\n floatingRightWidth,\n floatingTopHeight,\n floatingBottomHeight,\n columnCount,\n rowCount,\n } = metrics;\n let x1 = gridX;\n let y1 = gridY;\n let x2 = width;\n let y2 = height;\n if (column != null) {\n if (column > floatingLeftColumnCount) {\n x1 += floatingLeftWidth;\n }\n if (column < columnCount - floatingRightColumnCount) {\n x2 -= floatingRightWidth;\n }\n }\n\n if (row != null) {\n if (row > floatingTopRowCount) {\n y1 += floatingTopHeight;\n }\n if (row < rowCount - floatingBottomRowCount) {\n y2 -= floatingBottomHeight;\n }\n }\n return { x1, y1, x2, y2 };\n }\n\n /**\n * Converts the delta coordinates from the provided wheel event to pixels\n * Different platforms have different ways of providing the delta so this normalizes it\n * @param wheelEvent The mouse wheel event to get the scrolling delta for\n * @param pageWidth The width of the page that is scrolling\n * @param pageHeight The height of the page that is scrolling\n * @param lineWidth The width of the line scrolling in line mode\n * @param lineHeight The height of the line scrolling in line mode\n * @returns The delta coordinates normalized to pixels\n */\n static getScrollDelta(\n wheelEvent: WheelEvent,\n pageWidth = 1024,\n pageHeight = 768,\n lineWidth = 20,\n lineHeight = 20\n ): { deltaX: number; deltaY: number } {\n let { deltaX, deltaY } = wheelEvent;\n\n // Flip scroll direction if shiftKey is held on windows/linux.\n // On mac, deltaX/Y values are switched at the event level when shiftKey=true.\n // Guard on strictly Y only changing, to ignore trackpad diagonal motion,\n // through that guard may not be necessary, but it is difficult to determine for\n // all platforms/browser/scroll method combos.\n if (\n !GridUtils.isMacPlatform() &&\n wheelEvent.shiftKey &&\n wheelEvent.deltaX === 0 &&\n wheelEvent.deltaY !== 0\n ) {\n deltaX = wheelEvent.deltaY;\n deltaY = wheelEvent.deltaX;\n }\n\n // Normalize other deltaMode values to pixel units\n // deltaMode 0, is already in pixel units\n if (wheelEvent?.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n // Users can set OS to be in deltaMode page\n // scrolly by page units as pixels\n deltaX *= pageWidth;\n deltaY *= pageHeight;\n } else if (wheelEvent?.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n // Firefox reports deltaMode line\n // Normalize distance travelled between browsers\n // but remain ~platform/browser combo consistent\n if (GridUtils.isMacPlatform()) {\n // for mac treat lines as a standard row height\n // on mac, firefox travels less distance then chrome per tick\n deltaX = Math.round(deltaX * lineWidth);\n deltaY = Math.round(deltaY * lineHeight);\n } else {\n // for windows convert to pixels using the same method as chrome\n // chrome goes 100 per 3 lines, and firefox would go 102 per 3 (17 lineheight * 3 lines * 2)\n // make the behaviour the same between as it's close enough\n deltaX = Math.round(deltaX * this.PIXELS_PER_LINE);\n deltaY = Math.round(deltaY * this.PIXELS_PER_LINE);\n }\n }\n\n return { deltaX, deltaY };\n }\n}\n\nexport default GridUtils;\n","import GridModel from './GridModel';\nimport type {\n GridMetrics,\n BoxCoordinates,\n Coordinate,\n CoordinateMap,\n VisibleIndex,\n IndexModelMap,\n ModelIndex,\n ModelSizeMap,\n MoveOperation,\n SizeMap,\n} from './GridMetrics';\nimport GridUtils from './GridUtils';\nimport { GridFont, GridTheme } from './GridTheme';\nimport { isExpandableGridModel } from './ExpandableGridModel';\n\n/* eslint class-methods-use-this: \"off\" */\n/* eslint react/destructuring-assignment: \"off\" */\n\nexport interface GridMetricState {\n // The top/left cell of the scrolled viewport\n left: VisibleIndex;\n top: VisibleIndex;\n\n // The scroll offset within the top/left of the viewport\n leftOffset: Coordinate;\n topOffset: Coordinate;\n\n // Width and height of the total canvas area\n width: number;\n height: number;\n\n // The canvas context\n context: CanvasRenderingContext2D;\n\n // The grid theme\n theme: GridTheme;\n\n // The model used by the grid\n model: GridModel;\n\n // Moved columns/rows in the grid\n movedColumns: MoveOperation[];\n movedRows: MoveOperation[];\n\n // Whether the scrollbars are currently being dragged\n isDraggingHorizontalScrollBar: boolean;\n isDraggingVerticalScrollBar: boolean;\n}\n\n/**\n * Retrieve a value from a map. If the value is not found and no default value is provided, throw.\n * Use when the value _must_ be present\n * @param map The map to get the value from\n * @param key The key to fetch the value for\n * @param defaultValue A default value to set if the key is not present\n * @returns The value set for that key\n */\nexport function getOrThrow<K, V>(\n map: Map<K, V>,\n key: K,\n defaultValue: V | undefined = undefined\n): V {\n const value = map.get(key) ?? defaultValue;\n if (value !== undefined) {\n return value;\n }\n\n throw new Error(`Missing value for key ${key}`);\n}\n\n/**\n * Trim the provided map in place. Trims oldest inserted items down to the target size if the cache size is exceeded.\n * Instead of trimming one item on every tick, we trim half the items so there isn't a cache clear on every new item.\n * @param map The map to trim\n * @param cacheSize The maximum number of elements to cache\n * @param targetSize The number of elements to reduce the cache down to if `cacheSize` is exceeded\n */\nexport function trimMap(\n map: Map<unknown, unknown>,\n cacheSize = GridMetricCalculator.CACHE_SIZE,\n targetSize = Math.floor(cacheSize / 2)\n): void {\n if (map.size > cacheSize) {\n const iter = map.keys();\n while (map.size > targetSize) {\n map.delete(iter.next().value);\n }\n }\n}\n\n/**\n * Get the coordinates of floating items in one dimension.\n * Can be used for getting the y coordinates of floating rows, or x coordinates of floating columns, calculated using the `sizeMap` passed in.\n * @param startCount The number of floating items at the start (ie. `floatingTopRowCount` for rows, `floatingLeftColumnCount` for columns)\n * @param endCount The number of floating items at the end (ie. `floatingBottomRowCount` for rows, `floatingRightColumnCount` for columns)\n * @param totalCount Total number of items in this dimension (ie. `rowCount` for rows, `columnCount` for columns)\n * @param max The max coordinate value (ie. `maxY` for rows, `maxX` for columns)\n * @param sizeMap Map from index to size of item (ie. `rowHeightMap` for rows, `columnWidthMap` for columns)\n */\nexport function getFloatingCoordinates(\n startCount: number,\n endCount: number,\n totalCount: number,\n max: number,\n sizeMap: SizeMap\n): CoordinateMap {\n const coordinates = new Map();\n let x = 0;\n for (let i = 0; i < startCount && i < totalCount; i += 1) {\n coordinates.set(i, x);\n x += getOrThrow(sizeMap, i);\n }\n\n x = max;\n for (let i = 0; i < endCount && totalCount - i - 1 >= 0; i += 1) {\n x -= getOrThrow(sizeMap, totalCount - i - 1);\n coordinates.set(totalCount - i - 1, x);\n }\n return coordinates;\n}\n\n/**\n * Class to calculate all the metrics for drawing a grid.\n * Call getMetrics() with the state to get the full metrics.\n * Override this class and override the individual methods to provide additional functionality.\n */\nclass GridMetricCalculator {\n /** The size of the caches this calculator stores */\n static CACHE_SIZE = 10000;\n\n /** The maximum column width as a percentage of the full grid */\n static MAX_COLUMN_WIDTH = 0.8;\n\n /** User set column widths */\n protected userColumnWidths: ModelSizeMap;\n\n /** User set row heights */\n protected userRowHeights: ModelSizeMap;\n\n /** Calculated column widths based on cell contents */\n protected calculatedColumnWidths: ModelSizeMap;\n\n /** Calculated row heights based on cell contents */\n protected calculatedRowHeights: ModelSizeMap;\n\n /** Cache of fonts to estimated width of one char */\n protected fontWidths: Map<string, number>;\n\n /** Map from visible index to model index for rows (e.g. reversing movedRows operations) */\n protected modelRows: IndexModelMap;\n\n /** Map from visible index to model index for columns (e.g. reversing movedColumns operations) */\n protected modelColumns: IndexModelMap;\n\n /** List of moved row operations. Need to track the previous value so we know if modelRows needs to be cleared. */\n protected movedRows: MoveOperation[];\n\n /** List of moved column operations. Need to track the previous value so we know if modelColumns needs to be cleared. */\n protected movedColumns: MoveOperation[];\n\n constructor({\n userColumnWidths = new Map(),\n userRowHeights = new Map(),\n calculatedColumnWidths = new Map(),\n calculatedRowHeights = new Map(),\n fontWidths = new Map(),\n modelRows = new Map(),\n modelColumns = new Map(),\n movedRows = [],\n movedColumns = [],\n } = {}) {\n this.userColumnWidths = userColumnWidths;\n this.userRowHeights = userRowHeights;\n this.calculatedRowHeights = calculatedRowHeights;\n this.calculatedColumnWidths = calculatedColumnWidths;\n this.fontWidths = fontWidths;\n\n // Need to track the last moved rows/columns array so we know if we need to reset our models cache\n this.modelRows = modelRows;\n this.modelColumns = modelColumns;\n this.movedRows = movedRows;\n this.movedColumns = movedColumns;\n }\n\n /**\n * Get the metrics for the provided metric state\n * @params state The state to get metrics for\n * @returns The full metrics\n */\n getMetrics(state: GridMetricState): GridMetrics {\n const {\n left,\n top,\n leftOffset,\n topOffset,\n width,\n height,\n theme,\n model,\n movedRows,\n movedColumns,\n } = state;\n const {\n rowHeight,\n rowHeaderWidth,\n rowFooterWidth,\n columnWidth,\n columnHeaderHeight,\n minScrollHandleSize,\n scrollBarSize,\n } = theme;\n\n if (movedRows !== this.movedRows) {\n this.movedRows = movedRows;\n this.modelRows.clear();\n }\n\n if (movedColumns !== this.movedColumns) {\n this.movedColumns = movedColumns;\n this.modelColumns.clear();\n }\n\n const {\n columnCount,\n rowCount,\n floatingTopRowCount,\n floatingBottomRowCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n } = model;\n\n // Get some basic metrics\n const firstRow = this.getFirstRow(state);\n const firstColumn = this.getFirstColumn(state);\n\n const gridX = this.getGridX(state);\n const gridY = this.getGridY(state);\n\n const treePaddingX =\n isExpandableGridModel(model) && model.hasExpandableRows\n ? this.calculateTreePaddingX(state)\n : 0;\n const treePaddingY = 0; // We don't support trees on columns (at least not yet)\n\n let visibleRowHeights = this.getVisibleRowHeights(state);\n let visibleColumnWidths = this.getVisibleColumnWidths(\n state,\n firstColumn,\n treePaddingX\n );\n\n // Calculate the metrics for the main grid\n const visibleRows = Array.from(visibleRowHeights.keys());\n const visibleColumns = Array.from(visibleColumnWidths.keys());\n\n // Add the floating row heights/column widths\n // TODO #316: Create an allRowHeights/allColumnWidths maps\n visibleRowHeights = new Map([\n ...visibleRowHeights,\n ...this.getFloatingRowHeights(state),\n ]);\n visibleColumnWidths = new Map([\n ...visibleColumnWidths,\n ...this.getFloatingColumnWidths(state),\n ]);\n\n let visibleColumnXs = this.getVisibleColumnXs(\n visibleColumnWidths,\n visibleColumns,\n leftOffset\n );\n let visibleRowYs = this.getVisibleRowYs(\n visibleRowHeights,\n visibleRows,\n topOffset\n );\n\n const bottom =\n visibleRows.length > 0 ? visibleRows[visibleRows.length - 1] : top;\n const right =\n visibleColumns.length > 0\n ? visibleColumns[visibleColumns.length - 1]\n : left;\n\n const bottomViewport = this.getBottomViewport(\n state,\n visibleRows,\n visibleRowYs,\n visibleRowHeights\n );\n const rightViewport = this.getRightViewport(\n state,\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths\n );\n\n const columnWidthValues = Array.from(visibleColumnWidths.values());\n const rowHeightValues = Array.from(visibleRowHeights.values());\n const maxX = columnWidthValues.reduce((x, w) => x + w, 0) - leftOffset;\n const maxY = rowHeightValues.reduce((y, h) => y + h, 0) - topOffset;\n\n const floatingBottomHeight = this.getFloatingBottomHeight(\n state,\n visibleRowHeights\n );\n\n const lastLeft = this.getLastLeft(\n state,\n null,\n width - gridX - scrollBarSize - rowFooterWidth\n );\n const lastTop = this.getLastTop(\n state,\n null,\n height - gridY - scrollBarSize - floatingBottomHeight\n );\n\n // Calculate some metrics for the scroll bars\n const hasHorizontalBar = lastLeft > 0;\n const hasVerticalBar = lastTop > 0;\n const horizontalBarHeight = hasHorizontalBar ? scrollBarSize : 0;\n const verticalBarWidth = hasVerticalBar ? scrollBarSize : 0;\n const barWidth = width - rowHeaderWidth - verticalBarWidth;\n const barHeight = height - columnHeaderHeight - horizontalBarHeight;\n\n const handleWidth =\n lastLeft > 0\n ? Math.min(\n Math.max(\n minScrollHandleSize,\n barWidth * ((columnCount - lastLeft) / columnCount)\n ),\n barWidth - 1\n )\n : 0;\n const handleHeight =\n lastTop > 0\n ? Math.min(\n Math.max(\n minScrollHandleSize,\n barHeight * ((rowCount - lastTop) / rowCount)\n ),\n barHeight - 1\n )\n : 0;\n\n const leftColumnWidth = getOrThrow(visibleColumnWidths, left, 0);\n const topRowHeight = getOrThrow(visibleRowHeights, top, 0);\n const leftOffsetPercent =\n leftColumnWidth > 0 ? leftOffset / leftColumnWidth : 0;\n const topOffsetPercent = topRowHeight > 0 ? topOffset / topRowHeight : 0;\n const scrollX =\n lastLeft > 0\n ? ((left + leftOffsetPercent) / lastLeft) * (barWidth - handleWidth)\n : 0;\n const scrollY =\n lastTop > 0\n ? ((top + topOffsetPercent) / lastTop) * (barHeight - handleHeight)\n : 0;\n\n // Now add the floating sections positions\n let floatingRows: ModelIndex[] = [];\n if (floatingTopRowCount > 0 || floatingBottomRowCount > 0) {\n floatingRows = [\n ...Array(floatingTopRowCount).keys(),\n ...[...Array(floatingBottomRowCount).keys()].map(i => rowCount - i - 1),\n ];\n visibleRowYs = new Map([\n ...visibleRowYs,\n ...this.getFloatingRowYs(\n state,\n visibleRowHeights,\n Math.floor(height - gridY - horizontalBarHeight)\n ),\n ]);\n }\n\n let floatingColumns: ModelIndex[] = [];\n if (floatingLeftColumnCount > 0 || floatingRightColumnCount > 0) {\n floatingColumns = [\n ...Array(floatingLeftColumnCount).keys(),\n ...[...Array(floatingRightColumnCount).keys()].map(\n i => columnCount - i - 1\n ),\n ];\n visibleColumnXs = new Map([\n ...visibleColumnXs,\n ...this.getFloatingColumnXs(\n state,\n visibleColumnWidths,\n Math.floor(width - gridX - verticalBarWidth)\n ),\n ]);\n }\n\n const allRows = visibleRows.concat(floatingRows);\n const allColumns = visibleColumns.concat(floatingColumns);\n const modelRows = this.getModelRows(allRows, state);\n const modelColumns = this.getModelColumns(allColumns, state);\n\n const visibleRowTreeBoxes = this.getVisibleRowTreeBoxes(\n visibleRowHeights,\n modelRows,\n state\n );\n\n // Calculate the visible viewport based on scroll position and floating sections\n const topVisible = this.getTopVisible(\n state,\n visibleRowYs,\n visibleRowHeights,\n visibleRows\n );\n const leftVisible = this.getLeftVisible(\n state,\n visibleColumnXs,\n visibleColumnWidths,\n visibleColumns\n );\n const bottomVisible =\n lastTop > 0\n ? this.getBottomVisible(\n state,\n visibleRowYs,\n visibleRowHeights,\n visibleRows,\n gridY\n )\n : bottom;\n const rightVisible =\n lastLeft > 0\n ? this.getRightVisible(\n state,\n visibleColumnXs,\n visibleColumnWidths,\n visibleColumns,\n gridX\n )\n : right;\n\n const floatingTopHeight = this.getFloatingTopHeight(\n state,\n visibleRowHeights\n );\n const floatingLeftWidth = this.getFloatingLeftWidth(\n state,\n visibleColumnWidths\n );\n const floatingRightWidth = this.getFloatingRightWidth(\n state,\n visibleColumnWidths\n );\n\n const {\n fontWidths,\n userColumnWidths,\n userRowHeights,\n calculatedRowHeights,\n calculatedColumnWidths,\n } = this;\n\n return {\n // Row/Column metrics from model\n rowHeight,\n rowHeaderWidth,\n rowFooterWidth,\n rowCount,\n columnWidth,\n columnCount,\n columnHeaderHeight,\n\n // Floating row and column counts\n floatingTopRowCount,\n floatingBottomRowCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n\n // The grid offset from the top left\n gridX,\n gridY,\n\n // Index of non-hidden row/columns\n firstRow,\n firstColumn,\n\n // The amount of padding for tree (if applicable)\n treePaddingX,\n treePaddingY,\n\n // What viewport is currently visible, limited by data size\n left,\n top,\n bottom,\n right,\n topOffset,\n leftOffset,\n\n // Bottom and right that are fully visible, not overlapped by scroll bars or anything\n topVisible,\n leftVisible,\n bottomVisible,\n rightVisible,\n\n // Bottom and right of the viewport, not limited by data size\n bottomViewport,\n rightViewport,\n\n // Canvas width/height\n width,\n height,\n\n // Max x/y coordinate of the grid (does not include headers)\n maxX,\n maxY,\n\n // Last valid column/row that can be the left/top of the grid\n lastLeft,\n lastTop,\n\n // Scroll bar metrics\n barHeight,\n barWidth,\n handleHeight,\n handleWidth,\n hasHorizontalBar,\n hasVerticalBar,\n verticalBarWidth,\n horizontalBarHeight,\n\n // The vertical x/y scroll amount\n scrollX,\n scrollY,\n\n // Array of visible rows/columns, by grid index\n visibleRows,\n visibleColumns,\n\n // Array of floating rows/columns, by grid index\n floatingRows,\n floatingColumns,\n\n // Array of all rows/columns, visible and floating, by grid index\n allRows,\n allColumns,\n\n // Map of the height/width of visible rows/columns\n // TODO #316: This should be split into allRowHeights/visibleRowHeights/floatingRowHeights ideally\n visibleRowHeights,\n visibleColumnWidths,\n\n // Floating metrics\n floatingTopHeight,\n floatingBottomHeight,\n floatingLeftWidth,\n floatingRightWidth,\n\n // Map of the X/Y coordinates of the rows/columns, from the top left of the grid\n visibleRowYs,\n visibleColumnXs,\n\n // The boxes user can click on for expanding/collapsing tree rows\n visibleRowTreeBoxes,\n\n // Mapping from visible row indexes to the model row/columns they pull from\n modelRows,\n modelColumns,\n\n // Map of the width of the fonts\n fontWidths,\n\n // Map of user set column/row width/height\n userColumnWidths,\n userRowHeights,\n\n // Map of calculated row/column height/width\n calculatedRowHeights,\n calculatedColumnWidths,\n };\n }\n\n /**\n * The x offset of the grid\n * @param state The current grid state\n * @returns x value of the left side of the first cell\n */\n getGridX(state: GridMetricState): Coordinate {\n const { theme } = state;\n const { rowHeaderWidth } = theme;\n\n return rowHeaderWidth;\n }\n\n /**\n * The y offset of the grid\n * @param state The current grid state\n * @returns y value of the top side of the first cell\n */\n getGridY(state: GridMetricState): Coordinate {\n const { theme } = state;\n const { columnHeaderHeight } = theme;\n\n return columnHeaderHeight;\n }\n\n /**\n * The height of the \"visible\" area (excludes floating areas)\n * @param state The current grid state\n * @param visibleRowHeights All the visible row heights\n * @returns The visible height in pixels\n */\n getVisibleHeight(\n state: GridMetricState,\n visibleRowHeights: SizeMap = this.getFloatingRowHeights(state)\n ): number {\n const { height, theme } = state;\n const { scrollBarSize } = theme;\n const gridY = this.getGridY(state);\n const floatingBottomHeight = this.getFloatingBottomHeight(\n state,\n visibleRowHeights\n );\n const floatingTopHeight = this.getFloatingTopHeight(\n state,\n visibleRowHeights\n );\n\n return (\n height - floatingBottomHeight - floatingTopHeight - gridY - scrollBarSize\n );\n }\n\n /**\n * The width of the \"visible\" area (excludes floating areas)\n * @param state The current grid state\n * @param visibleColumnWidths All the visible column widths\n * @returns The visible width in pixels\n */\n getVisibleWidth(\n state: GridMetricState,\n visibleColumnWidths: SizeMap = this.getFloatingColumnWidths(state)\n ): number {\n const { width, theme } = state;\n const { scrollBarSize, rowFooterWidth } = theme;\n const gridX = this.getGridX(state);\n const floatingRightWidth = this.getFloatingRightWidth(\n state,\n visibleColumnWidths\n );\n const floatingLeftWidth = this.getFloatingLeftWidth(\n state,\n visibleColumnWidths\n );\n\n return (\n width -\n floatingLeftWidth -\n floatingRightWidth -\n gridX -\n scrollBarSize -\n rowFooterWidth\n );\n }\n\n /**\n * Retrieve the index of the first non-hidden item\n * @param itemSizes The size of the items in this dimension\n * @param getModelIndex A function to map from the Index to the ModelIndex\n * @param state The current grid state\n * @returns The first item that is not hidden\n */\n getFirstIndex(\n itemSizes: ModelSizeMap,\n getModelIndex: (\n visibleIndex: VisibleIndex,\n state: GridMetricState\n ) => ModelIndex,\n state: GridMetricState\n ): VisibleIndex {\n // We only need to check at the very most the number of items the user has hidden + 1\n const max = itemSizes.size + 1;\n for (let i = 0; i < max; i += 1) {\n const modelIndex = getModelIndex(i, state);\n if (itemSizes.get(modelIndex) !== 0) {\n return i;\n }\n }\n return 0;\n }\n\n /**\n * Get the first column index that isn't hidden\n * @param state The current grid state\n * @returns The first column that is not hidden\n */\n getFirstColumn(state: GridMetricState): VisibleIndex {\n return this.getFirstIndex(\n this.userColumnWidths,\n this.getModelColumn.bind(this),\n state\n );\n }\n\n /**\n * Get the first row index that isn't hidden\n * @param state The current grid state\n * @returns The first row that is not hidden\n */\n getFirstRow(state: GridMetricState): VisibleIndex {\n return this.getFirstIndex(\n this.userRowHeights,\n this.getModelRow.bind(this),\n state\n );\n }\n\n /**\n * Get the last column that can be the left most column (e.g. scrolled to the right)\n * If no right column is provided, then the last column is used.\n * @param state The current grid state\n * @param right The right-most column to be visible, or null to default to last cell\n * @param visibleWidth The width of the \"visible\" area (excluding floating items)\n * @returns The index of the last left visible column\n */\n getLastLeft(\n state: GridMetricState,\n right: VisibleIndex | null = null,\n visibleWidth: number = this.getVisibleWidth(state)\n ): VisibleIndex {\n const { model } = state;\n const { columnCount } = model;\n\n let lastLeft = columnCount - 1;\n if (right != null) {\n lastLeft = right;\n }\n let x = 0;\n while (lastLeft >= 0) {\n const columnWidth = this.getVisibleColumnWidth(lastLeft, state);\n x += columnWidth;\n\n if (x >= visibleWidth) {\n return Math.min(lastLeft + 1, columnCount - 1);\n }\n\n lastLeft -= 1;\n }\n\n return 0;\n }\n\n /**\n * The last row that can be the top row (e.g. scrolled to the bottom)\n * If no bottom row is provided, then the last row that is not floating is used\n */\n\n /**\n * The last row that can be the top row (e.g. scrolled to the bottom)\n * If no bottom row is provided, then the last row that is not floating is used\n * @param state The current grid state\n * @param bottom The bottom-most row to be visible, or null to default to last cell\n * @param visibleHeight The height of the \"visible\" area (excluding floating items)\n * @returns The index of the last left visible column\n */\n getLastTop(\n state: GridMetricState,\n bottom: VisibleIndex | null = null,\n visibleHeight: number = this.getVisibleHeight(state)\n ): VisibleIndex {\n const { model } = state;\n const { rowCount, floatingBottomRowCount } = model;\n\n let lastTop = Math.max(0, rowCount - floatingBottomRowCount - 1);\n if (bottom != null) {\n lastTop = bottom;\n }\n let y = 0;\n while (lastTop > 0) {\n const rowHeight = this.getVisibleRowHeight(lastTop, state);\n y += rowHeight;\n\n if (y >= visibleHeight) {\n return Math.min(lastTop + 1, rowCount - 1);\n }\n\n lastTop -= 1;\n }\n\n return 0;\n }\n\n /**\n * Retrieve the top row to scroll to so the passed in `topVisible` is completely visible, taking the floating rows into account.\n * The `top` row is at the top underneath any floating rows, whereas `topVisible` is visible below the floating rows.\n * If there are no floating rows, they should be the same value.\n * @param state The grid metric state\n * @param topVisible The top row to be visible\n * @returns The index of the top row to scroll to (under the floating top rows)\n */\n getTopForTopVisible(\n state: GridMetricState,\n topVisible: VisibleIndex\n ): VisibleIndex {\n const floatingTopHeight = this.getFloatingTopHeight(state);\n let top = topVisible;\n let y = 0;\n while (top > 0 && y < floatingTopHeight) {\n top -= 1;\n y += this.getVisibleRowHeight(top, state);\n }\n return top;\n }\n\n /**\n * Retrieve the top row to scroll to so the passed in `bottomVisible` is completely visible\n * at the bottom of the visible viewport, taking the floating rows into account.\n * @param state The grid metric state\n * @param bottomVisible The bottom row to be visible\n * @returns The index of the top row to scroll to (under the floating top rows)\n */\n getTopForBottomVisible(\n state: GridMetricState,\n bottomVisible: VisibleIndex\n ): VisibleIndex {\n const { height } = state;\n const gridY = this.getGridY(state);\n const floatingBottomHeight = this.getFloatingBottomHeight(state);\n const availableHeight = height - gridY - floatingBottomHeight;\n return this.getLastTop(state, bottomVisible, availableHeight);\n }\n\n /**\n * Retrieve the left column to scroll to so the passed in `leftVisible` is completely visible\n * at the left of the visible viewport, taking the floating columns into account.\n * @param state The grid metric state\n * @param leftVisible The left column to be visible\n * @returns The index of the left column to scroll to (under the floating left columns)\n */\n getLeftForLeftVisible(\n state: GridMetricState,\n leftVisible: VisibleIndex\n ): VisibleIndex {\n const floatingLeftWidth = this.getFloatingLeftWidth(state);\n let left = leftVisible;\n let x = 0;\n while (left > 0 && x < floatingLeftWidth) {\n left -= 1;\n x += this.getVisibleColumnWidth(left, state);\n }\n return left;\n }\n\n /**\n * Retrieve the left column to scroll to so the passed in `rightVisible` is completely visible\n * at the right of the visible viewport, taking the floating columns into account.\n * @param state The grid metric state\n * @param rightVisible The right column to be visible\n * @returns The index of the left column to scroll to (under the floating left columns)\n */\n getLeftForRightVisible(\n state: GridMetricState,\n rightVisible: VisibleIndex\n ): VisibleIndex {\n const { width } = state;\n const gridX = this.getGridX(state);\n const floatingRightWidth = this.getFloatingRightWidth(state);\n const availableWidth = width - gridX - floatingRightWidth;\n return this.getLastLeft(state, rightVisible, availableWidth);\n }\n\n /**\n * Retrieve a map of the height of each floating row\n * @param state The grid metric state\n * @returns The heights of all the floating rows\n */\n getFloatingRowHeights(state: GridMetricState): SizeMap {\n const { model } = state;\n const { floatingTopRowCount, floatingBottomRowCount, rowCount } = model;\n\n const rowHeights = new Map();\n for (let i = 0; i < floatingTopRowCount && i < rowCount; i += 1) {\n rowHeights.set(i, this.getVisibleRowHeight(i, state));\n }\n\n for (\n let i = 0;\n i < floatingBottomRowCount && rowCount - i - 1 >= 0;\n i += 1\n ) {\n const row = rowCount - i - 1;\n rowHeights.set(row, this.getVisibleRowHeight(row, state));\n }\n\n return rowHeights;\n }\n\n /**\n * Retrieve a map of the height of all the visible rows (non-floating)\n * @param state The grid metric state\n * @returns The heights of all the visible rows\n */\n getVisibleRowHeights(state: GridMetricState): SizeMap {\n const { top, topOffset, height, model } = state;\n\n let y = 0;\n let row = top;\n const rowHeights = new Map();\n const { rowCount } = model;\n while (y < height + topOffset && row < rowCount) {\n const rowHeight = this.getVisibleRowHeight(row, state);\n rowHeights.set(row, rowHeight);\n y += rowHeight;\n row += 1;\n }\n\n return rowHeights;\n }\n\n /**\n * Retrieve a map of the width of each floating column\n * @param state The grid metric state\n * @param firstColumn The first non-hidden column\n * @param treePaddingX The amount of padding taken up for the tree expansion buttons\n * @returns The widths of all the floating columns\n */\n getFloatingColumnWidths(\n state: GridMetricState,\n firstColumn: VisibleIndex = this.getFirstColumn(state),\n treePaddingX: number = this.calculateTreePaddingX(state)\n ): SizeMap {\n const { model } = state;\n const {\n columnCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n } = model;\n\n const columnWidths = new Map();\n for (let i = 0; i < floatingLeftColumnCount && i < columnCount; i += 1) {\n columnWidths.set(\n i,\n this.getVisibleColumnWidth(i, state, firstColumn, treePaddingX)\n );\n }\n\n for (\n let i = 0;\n i < floatingRightColumnCount && columnCount - i - 1 >= 0;\n i += 1\n ) {\n const column = columnCount - i - 1;\n columnWidths.set(\n column,\n this.getVisibleColumnWidth(column, state, firstColumn, treePaddingX)\n );\n }\n\n return columnWidths;\n }\n\n /**\n * Retrieve a map of the width of all the visible columns (non-floating)\n * @param state The grid metric state\n * @returns The widths of all the visible columns\n */\n getVisibleColumnWidths(\n state: GridMetricState,\n firstColumn: VisibleIndex = this.getFirstColumn(state),\n treePaddingX: number = this.calculateTreePaddingX(state)\n ): SizeMap {\n const { left, leftOffset, width, model } = state;\n\n let x = 0;\n let column = left;\n const columnWidths = new Map();\n const { columnCount } = model;\n while (x < width + leftOffset && column < columnCount) {\n const columnWidth = this.getVisibleColumnWidth(\n column,\n state,\n firstColumn,\n treePaddingX\n );\n columnWidths.set(column, columnWidth);\n x += columnWidth;\n column += 1;\n }\n\n return columnWidths;\n }\n\n /**\n * Retrieve a map of all the floating columns to their x coordinate\n * @param state The grid metric state\n * @param columnWidthMap Map from visible index to column width\n * @param maxX The maximum X size for the grid\n * @returns Map of the x coordinate of all floating columns\n */\n getFloatingColumnXs(\n state: GridMetricState,\n columnWidthMap: SizeMap,\n maxX: Coordinate\n ): CoordinateMap {\n const { model } = state;\n const {\n columnCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n } = model;\n\n return getFloatingCoordinates(\n floatingLeftColumnCount,\n floatingRightColumnCount,\n columnCount,\n maxX,\n columnWidthMap\n );\n }\n\n /**\n * Retrieve a map of all the visible columns to their x coordinate.\n * Starts at leftOffset with the first index in `visibleColumns`, then\n * calculates all the coordinates from there\n * @param visibleColumnWidths Map of visible column index to widths\n * @param visibleColumns All visible columns\n * @param leftOffset The left scroll offset\n * @returns Map of the x coordinate of all visible columns\n */\n getVisibleColumnXs(\n visibleColumnWidths: SizeMap,\n visibleColumns: VisibleIndex[],\n leftOffset: number\n ): CoordinateMap {\n const visibleColumnXs = new Map();\n let x = -leftOffset;\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n visibleColumnXs.set(column, x);\n x += columnWidth;\n }\n\n return visibleColumnXs;\n }\n\n /**\n * Retrieve a map of all the floating rows to their y coordinate\n * @param state The grid metric state\n * @param rowHeightMap Map of visible index to row height\n * @param maxY The maximum Y size for the grid\n * @returns Map of the y coordinate of all floating rows\n */\n getFloatingRowYs(\n state: GridMetricState,\n rowHeightMap: SizeMap,\n maxY: Coordinate\n ): CoordinateMap {\n const { model } = state;\n const { floatingTopRowCount, floatingBottomRowCount, rowCount } = model;\n\n return getFloatingCoordinates(\n floatingTopRowCount,\n floatingBottomRowCount,\n rowCount,\n maxY,\n rowHeightMap\n );\n }\n\n /**\n * Retrieve a map of all the visible rows to their y coordinate.\n * Starts at topOffset with the first index in `visibleRows`, then\n * calculates all the coordinates from there\n * @param visibleRowHeights Map of visible row index to heights\n * @param visibleRows All visible rows\n * @param topOffset The top scroll offset\n * @returns Map of the y coordinate of all visible rows\n */\n getVisibleRowYs(\n visibleRowHeights: SizeMap,\n visibleRows: VisibleIndex[],\n topOffset: number\n ): CoordinateMap {\n const visibleRowYs = new Map();\n let y = -topOffset;\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n const rowHeight = getOrThrow(visibleRowHeights, row);\n visibleRowYs.set(row, y);\n y += rowHeight;\n }\n\n return visibleRowYs;\n }\n\n /**\n * Calculates the tree box click areas that are visible. In relation to the columnX/rowY\n * @param visibleRowHeights Map of visible index to row height\n * @param modelRows Map from visible `Index` to `ModelIndex`\n * @param state The grid metric state\n * @returns Coordinates of tree boxes for each row\n */\n getVisibleRowTreeBoxes(\n visibleRowHeights: SizeMap,\n modelRows: IndexModelMap,\n state: GridMetricState\n ): Map<VisibleIndex, BoxCoordinates> {\n const visibleRowTreeBoxes = new Map();\n const { model, theme } = state;\n const { treeDepthIndent, treeHorizontalPadding } = theme;\n\n if (isExpandableGridModel(model) && model.hasExpandableRows) {\n visibleRowHeights.forEach((rowHeight, row) => {\n const modelRow = getOrThrow(modelRows, row);\n if (model.isRowExpandable(modelRow)) {\n const depth = model.depthForRow(modelRow);\n const x1 = depth * treeDepthIndent + treeHorizontalPadding;\n const x2 = (depth + 1) * treeDepthIndent + treeHorizontalPadding;\n const y1 = 0;\n const y2 = rowHeight;\n visibleRowTreeBoxes.set(row, { x1, y1, x2, y2 });\n }\n });\n }\n\n return visibleRowTreeBoxes;\n }\n\n /**\n * Get the total width of the floating columns on the left\n * @param state The grid metric state\n * @param columnWidths Map of column index to width\n * @returns The total width of the floating left section\n */\n getFloatingLeftWidth(\n state: GridMetricState,\n columnWidths: SizeMap = this.getFloatingColumnWidths(state)\n ): number {\n const { model } = state;\n const { floatingLeftColumnCount } = model;\n let floatingWidth = 0;\n for (let i = 0; i < floatingLeftColumnCount; i += 1) {\n floatingWidth += getOrThrow(columnWidths, i);\n }\n return floatingWidth;\n }\n\n /**\n * Get the total width of the floating columns on the right\n * @param state The grid metric state\n * @param columnWidths Map of column index to width\n * @returns The total width of the floating right section\n */\n getFloatingRightWidth(\n state: GridMetricState,\n columnWidths: SizeMap = this.getFloatingColumnWidths(state)\n ): number {\n const { model } = state;\n const { floatingRightColumnCount, columnCount } = model;\n let floatingWidth = 0;\n for (let i = 0; i < floatingRightColumnCount; i += 1) {\n floatingWidth += getOrThrow(columnWidths, columnCount - i - 1);\n }\n\n return floatingWidth;\n }\n\n /**\n * Get the total height of the floating rows on the top\n * @param state The grid metric state\n * @param rowHeights Map of row index to height\n * @returns The total height of the floating top section\n */\n getFloatingTopHeight(\n state: GridMetricState,\n rowHeights: SizeMap = this.getFloatingRowHeights(state)\n ): number {\n const { model } = state;\n const { floatingTopRowCount } = model;\n let floatingHeight = 0;\n for (let i = 0; i < floatingTopRowCount; i += 1) {\n floatingHeight += getOrThrow(rowHeights, i);\n }\n return floatingHeight;\n }\n\n /**\n * Get the total height of the floating rows on the bottom\n * @param state The grid metric state\n * @param rowHeights Map of row index to height\n * @returns The total height of the floating bottom section\n */\n getFloatingBottomHeight(\n state: GridMetricState,\n rowHeights: SizeMap = this.getFloatingRowHeights(state)\n ): number {\n const { model } = state;\n const { floatingBottomRowCount, rowCount } = model;\n let floatingHeight = 0;\n for (let i = 0; i < floatingBottomRowCount; i += 1) {\n floatingHeight += getOrThrow(rowHeights, rowCount - i - 1);\n }\n return floatingHeight;\n }\n\n /**\n * Retrieve the index of the first fully visible row in the \"visible\" viewport of the grid.\n * E.g. First row visible after the floating rows, provided the visible rows.\n * @param state The grid metric state\n * @param visibleRowYs Map of row index to y coordinate\n * @param visibleRowHeights Map of row index to height\n * @param visibleRows Array of visible row indexes\n * @returns Index of the top visible row\n */\n getTopVisible(\n state: GridMetricState,\n visibleRowYs: CoordinateMap,\n visibleRowHeights: SizeMap,\n visibleRows: VisibleIndex[]\n ): VisibleIndex {\n const floatingHeight = this.getFloatingTopHeight(state, visibleRowHeights);\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n const y = getOrThrow(visibleRowYs, row);\n if (y >= floatingHeight) {\n return row;\n }\n }\n return 0;\n }\n\n /**\n * Retrieve the index of the first fully visible column in the \"visible\" viewport of the grid.\n * E.g. First column visible after the floating columns, provided the visible columns.\n * @param state The grid metric state\n * @param visibleColumnXs Map of column index to x coordinate\n * @param visibleColumnWidths Map of column index to widths\n * @param visibleColumns Array of visible row indexes\n * @returns Index of the left visible column\n */\n getLeftVisible(\n state: GridMetricState,\n visibleColumnXs: CoordinateMap,\n visibleColumnWidths: SizeMap,\n visibleColumns: VisibleIndex[]\n ): VisibleIndex {\n const floatingWidth = this.getFloatingLeftWidth(state, visibleColumnWidths);\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const x = getOrThrow(visibleColumnXs, column);\n if (x >= floatingWidth) {\n return column;\n }\n }\n return 0;\n }\n\n /**\n * Retrieve the index of the last fully visible row in the \"visible\" viewport of the grid.\n * E.g. Last row visible before the bottom floating rows, provided the visible rows.\n * @param state The grid metric state\n * @param visibleRowYs Map of row index to y coordinate\n * @param visibleRowHeights Map of row index to height\n * @param visibleRows Array of visible row indexes\n * @param gridY The starting y coordinate of the grid\n * @returns Index of the bottom visible row\n */\n getBottomVisible(\n state: GridMetricState,\n visibleRowYs: CoordinateMap,\n visibleRowHeights: SizeMap,\n visibleRows: VisibleIndex[],\n gridY: Coordinate\n ): VisibleIndex {\n const { height, theme } = state;\n const { scrollBarSize } = theme;\n const floatingHeight = this.getFloatingBottomHeight(\n state,\n visibleRowHeights\n );\n const visibleHeight = height - gridY - scrollBarSize - floatingHeight;\n for (let i = visibleRows.length - 1; i >= 0; i -= 1) {\n const row = visibleRows[i];\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n if (rowY + rowHeight <= visibleHeight) {\n return row;\n }\n }\n\n return 0;\n }\n\n /**\n * Retrieve the index of the last fully visible column in the \"visible\" viewport of the grid.\n * E.g. Last column visible before the floating columns, provided the visible columns.\n * @param state The grid metric state\n * @param visibleColumnXs Map of column index to x coordinate\n * @param visibleColumnWidths Map of column index to widths\n * @param visibleColumns Array of visible column indexes\n * @returns Index of the right visible column\n */\n getRightVisible(\n state: GridMetricState,\n visibleColumnXs: CoordinateMap,\n visibleColumnWidths: SizeMap,\n visibleColumns: VisibleIndex[],\n gridX: Coordinate\n ): VisibleIndex {\n const { width, theme } = state;\n const { scrollBarSize } = theme;\n const floatingWidth = this.getFloatingRightWidth(\n state,\n visibleColumnWidths\n );\n const visibleWidth = width - gridX - scrollBarSize - floatingWidth;\n for (let i = visibleColumns.length - 1; i >= 0; i -= 1) {\n const column = visibleColumns[i];\n const columnX = getOrThrow(visibleColumnXs, column);\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n if (columnX + columnWidth <= visibleWidth) {\n return column;\n }\n }\n\n return 0;\n }\n\n /**\n * Retrieve the possible bottom of the visible viewport (not limited by data size)\n * @param state The grid metric state\n * @param visibleRows Array of visible row indexes\n * @param visibleRowYs Map of row index to y coordinate\n * @param visibleRowHeights Map of row index to height\n * @returns The index of the bottom viewport possible\n */\n getBottomViewport(\n state: GridMetricState,\n visibleRows: VisibleIndex[],\n visibleRowYs: CoordinateMap,\n visibleRowHeights: SizeMap\n ): VisibleIndex {\n const { height, theme } = state;\n const { rowHeight } = theme;\n\n return this.getLastIndexViewport(\n visibleRows,\n visibleRowYs,\n visibleRowHeights,\n height,\n rowHeight\n );\n }\n\n /**\n * Retrieve the possible right of the visible viewport (not limited by data size)\n * @param state The grid metric state\n * @param visibleColumns Array of visible column indexes\n * @param visibleColumnXs Map of column index to x coordinate\n * @param visibleColumnWidths Map of column index to width\n * @returns The index of the right viewport possible\n */\n getRightViewport(\n state: GridMetricState,\n visibleColumns: VisibleIndex[],\n visibleColumnXs: CoordinateMap,\n visibleColumnWidths: SizeMap\n ): VisibleIndex {\n const { width, theme } = state;\n const { columnWidth } = theme;\n\n return this.getLastIndexViewport(\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths,\n width,\n columnWidth\n );\n }\n\n /**\n * Get the Index of the of the last index visible\n * @param items Array of visible item indexes\n * @param itemXs Map of index to coordinate\n * @param itemSizes Map of index to size\n * @param maxSize Full size of the grid\n * @param defaultItemSize Default size of an item\n * @returns The Index of the last index visible\n */\n getLastIndexViewport(\n items: VisibleIndex[],\n itemXs: CoordinateMap,\n itemSizes: SizeMap,\n maxSize: number,\n defaultItemSize: number\n ): VisibleIndex {\n let lastIndex = 0;\n let dataSize = 0;\n if (items.length > 0) {\n lastIndex = items[items.length - 1];\n dataSize =\n getOrThrow(itemXs, lastIndex) + getOrThrow(itemSizes, lastIndex);\n }\n\n if (dataSize < maxSize) {\n lastIndex += Math.ceil((maxSize - dataSize) / defaultItemSize);\n }\n\n return lastIndex;\n }\n\n /**\n * Get the size from the provided size map of the specified item\n * @param modelIndex The model index to get the size for\n * @param userSizes The user set sizes\n * @param calculateSize Method to calculate the size for this item\n * @returns The size from the provided size map of the specified item\n */\n getVisibleItemSize(\n modelIndex: ModelIndex,\n userSizes: ModelSizeMap,\n calculateSize: () => number\n ): number {\n return userSizes.get(modelIndex) ?? calculateSize();\n }\n\n /**\n * Get the height of the specified row\n * @param row Index of the row to get the height of\n * @param state The grid metric state\n * @returns The height of the row specified\n */\n getVisibleRowHeight(row: VisibleIndex, state: GridMetricState): number {\n const modelRow = this.getModelRow(row, state);\n\n return this.getVisibleItemSize(modelRow, this.userRowHeights, () =>\n this.calculateRowHeight(row, modelRow, state)\n );\n }\n\n /**\n * Get the width of the specified column\n * @param column Index of the column to get the width of\n * @param state The grid metric state\n * @param firstColumn Index of first visible column\n * @param treePaddingX The amount of tree padding to add to the first visible column\n * @returns The width of the column\n */\n getVisibleColumnWidth(\n column: VisibleIndex,\n state: GridMetricState,\n firstColumn: VisibleIndex = this.getFirstColumn(state),\n treePaddingX: number = this.calculateTreePaddingX(state)\n ): number {\n const modelColumn = this.getModelColumn(column, state);\n\n return this.getVisibleItemSize(modelColumn, this.userColumnWidths, () =>\n this.calculateColumnWidth(\n column,\n modelColumn,\n state,\n firstColumn,\n treePaddingX\n )\n );\n }\n\n /**\n * Get a map of ModelIndex to Index\n * @param visibleRows Array of visible row indexes\n * @param state The grid metric state\n * @returns Map of Index to ModelIndex\n */\n getModelRows(\n visibleRows: VisibleIndex[],\n state: GridMetricState\n ): IndexModelMap {\n const modelRows = new Map();\n for (let i = 0; i < visibleRows.length; i += 1) {\n const visibleRow = visibleRows[i];\n const modelRow = this.getModelRow(visibleRow, state);\n modelRows.set(visibleRow, modelRow);\n }\n return modelRows;\n }\n\n /**\n * Get the ModelIndex of the specified row\n * @param visibleRow Index of the row\n * @param state The grid metric state\n * @returns ModelIndex of the row\n */\n getModelRow(visibleRow: VisibleIndex, state: GridMetricState): ModelIndex {\n if (this.modelRows.has(visibleRow)) {\n return getOrThrow(this.modelRows, visibleRow);\n }\n const { movedRows } = state;\n const modelRow = GridUtils.getModelIndex(visibleRow, movedRows);\n this.modelRows.set(visibleRow, modelRow);\n return modelRow;\n }\n\n /**\n * Get a map of Index to ModelIndex. Applies the move operations to get the transformation.\n * @param visibleColumns Array of visible column indexes\n * @param state The grid metric state\n * @returns Map of Index to ModelIndex\n */\n getModelColumns(\n visibleColumns: VisibleIndex[],\n state: GridMetricState\n ): IndexModelMap {\n const modelColumns = new Map();\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const visibleColumn = visibleColumns[i];\n const modelColumn = this.getModelColumn(visibleColumn, state);\n modelColumns.set(visibleColumn, modelColumn);\n }\n return modelColumns;\n }\n\n /**\n * Get the ModelIndex of the specified column\n * @param visibleColumn Index of the column\n * @param state The grid metric state\n * @returns ModelIndex of the column\n */\n getModelColumn(\n visibleColumn: VisibleIndex,\n state: GridMetricState\n ): ModelIndex {\n if (this.modelColumns.has(visibleColumn)) {\n return getOrThrow(this.modelColumns, visibleColumn);\n }\n const { movedColumns } = state;\n const modelColumn = GridUtils.getModelIndex(visibleColumn, movedColumns);\n this.modelColumns.set(visibleColumn, modelColumn);\n return modelColumn;\n }\n\n /**\n * Calculate the height of the row specified.\n * @param row Index of the row to calculate the height for\n * @param modelRow ModelIndex of the row to calculate the height\n * @param state The grid metric state\n * @returns The height of the row\n */\n calculateRowHeight(\n row: VisibleIndex,\n modelRow: ModelIndex,\n state: GridMetricState\n ): number {\n const { theme } = state;\n const { autoSizeRows, rowHeight } = theme;\n if (!autoSizeRows) {\n return rowHeight;\n }\n\n const cachedValue = this.calculatedRowHeights.get(modelRow);\n if (cachedValue != null) {\n return cachedValue;\n }\n\n // Not sure how to accurately get the height of text. For now just return the theme height.\n this.calculatedRowHeights.set(modelRow, Math.ceil(rowHeight));\n trimMap(this.calculatedRowHeights);\n return rowHeight;\n }\n\n /**\n * Calculates the column width based on the provided column model index\n * @param column Index of the column to calculate the width for\n * @param modelColumn ModelIndex of the column to calculate the width\n * @param state The grid metric state\n * @param firstColumn The first visible column\n * @param treePaddingX Tree padding offset for expandable rows\n * @returns The width of the column\n */\n calculateColumnWidth(\n column: VisibleIndex,\n modelColumn: ModelIndex,\n state: GridMetricState,\n firstColumn: VisibleIndex = this.getFirstColumn(state),\n treePaddingX: number = this.calculateTreePaddingX(state)\n ): number {\n const { theme } = state;\n const { autoSizeColumns, minColumnWidth } = theme;\n if (!autoSizeColumns) {\n const { columnWidth } = theme;\n return columnWidth;\n }\n\n const headerWidth = this.calculateColumnHeaderWidth(modelColumn, state);\n const dataWidth = this.calculateColumnDataWidth(modelColumn, state);\n const cachedValue = this.calculatedColumnWidths.get(modelColumn);\n let columnWidth = Math.ceil(Math.max(headerWidth, dataWidth));\n columnWidth = Math.max(minColumnWidth, columnWidth);\n if (cachedValue != null && cachedValue > columnWidth) {\n columnWidth = cachedValue;\n } else {\n this.calculatedColumnWidths.set(modelColumn, columnWidth);\n trimMap(this.calculatedColumnWidths);\n }\n\n if (column === firstColumn) {\n columnWidth += treePaddingX;\n }\n\n return columnWidth;\n }\n\n /**\n * Calculate the width of the specified column's header\n * @param modelColumn ModelIndex of the column to get the header width for\n * @param state The grid metric state\n * @returns The calculated width of the column header\n */\n calculateColumnHeaderWidth(\n modelColumn: ModelIndex,\n state: GridMetricState\n ): number {\n const { model, theme } = state;\n const { headerFont, headerHorizontalPadding } = theme;\n\n const headerText = model.textForColumnHeader(modelColumn);\n if (headerText) {\n const headerFontWidth = this.getWidthForFont(headerFont, state);\n return headerText.length * headerFontWidth + headerHorizontalPadding * 2;\n }\n\n return headerHorizontalPadding * 2;\n }\n\n /**\n * Calculate the width of the specified column's data\n * @param modelColumn ModelIndex of the column to get the data width for\n * @param state The grid metric state\n * @returns The calculated width of the column data\n */\n calculateColumnDataWidth(\n modelColumn: ModelIndex,\n state: GridMetricState\n ): number {\n const { top, height, width, model, theme } = state;\n const { floatingTopRowCount, floatingBottomRowCount, rowCount } = model;\n const {\n font,\n cellHorizontalPadding,\n rowHeight,\n rowHeaderWidth,\n rowFooterWidth,\n scrollBarSize,\n } = theme;\n\n let columnWidth = 0;\n\n const fontWidth = this.getWidthForFont(font, state);\n const rowsPerPage = height / rowHeight;\n const bottom = Math.ceil(top + rowsPerPage);\n GridUtils.iterateAllItems(\n top,\n bottom,\n floatingTopRowCount,\n floatingBottomRowCount,\n rowCount,\n row => {\n const modelRow = this.getModelRow(row, state);\n const text = model.textForCell(modelColumn, modelRow);\n if (text) {\n const cellPadding = cellHorizontalPadding * 2;\n columnWidth = Math.max(\n columnWidth,\n text.length * fontWidth + cellPadding\n );\n }\n }\n );\n\n columnWidth = Math.max(\n Math.min(\n columnWidth,\n (width - rowHeaderWidth - scrollBarSize - rowFooterWidth) *\n GridMetricCalculator.MAX_COLUMN_WIDTH\n ),\n cellHorizontalPadding * 2\n );\n\n return columnWidth;\n }\n\n /**\n * The coordinate for where the tree padding should be drawn\n * @param state The grid metric state\n * @returns The coordinate for tree padding\n */\n calculateTreePaddingX(state: GridMetricState): Coordinate {\n const { top, height, model, theme } = state;\n const { rowHeight, treeDepthIndent } = theme;\n if (!isExpandableGridModel(model) || !model.hasExpandableRows) {\n return 0;\n }\n let treePadding = 0;\n\n const rowsPerPage = height / rowHeight;\n const bottom = Math.ceil(top + rowsPerPage);\n for (let row = top; row <= bottom; row += 1) {\n const modelRow = this.getModelRow(row, state);\n const depth = model.depthForRow(modelRow);\n treePadding = Math.max(treePadding, treeDepthIndent * (depth + 1));\n }\n\n return treePadding;\n }\n\n /**\n * Get the width of the provided font. Exploits the fact that we're\n * using tabular figures so every character is same width\n * @param font The font to get the width for\n * @param state The grid metric state\n * @returns Width of the char `8` for the specified font\n */\n getWidthForFont(font: GridFont, state: GridMetricState): number {\n if (this.fontWidths.has(font)) {\n return getOrThrow(this.fontWidths, font);\n }\n const { context } = state;\n context.font = font;\n const textMetrics = context.measureText('8');\n const { width } = textMetrics;\n\n // context.font changes the string a little bit, e.g. '10px Arial, sans serif' => '10px Arial, \"sans serif\"'\n // Rather than require checking with the correct font def (theme, or context font), just key it to both\n this.fontWidths.set(font, width);\n this.fontWidths.set(context.font, width);\n\n return width;\n }\n\n /**\n * Sets the width for the specified column\n * @param column The column model index to set\n * @param size The size to set it to\n */\n setColumnWidth(column: ModelIndex, size: number): void {\n // Always use a new instance of the map so any consumer of the metrics knows there has been a change\n const userColumnWidths = new Map(this.userColumnWidths);\n userColumnWidths.set(column, Math.ceil(size));\n trimMap(userColumnWidths);\n this.userColumnWidths = userColumnWidths;\n }\n\n /**\n * Resets the column width for the specified column to the calculated width\n * @param column The column model index to reset\n */\n resetColumnWidth(column: ModelIndex): void {\n // Always use a new instance of the map so any consumer of the metrics knows there has been a change\n const userColumnWidths = new Map(this.userColumnWidths);\n userColumnWidths.delete(column);\n this.userColumnWidths = userColumnWidths;\n }\n\n /**\n * Sets the width for the specified row\n * @param row The row model index to set\n * @param size The size to set it to\n */\n setRowHeight(row: ModelIndex, size: number): void {\n // Always use a new instance of the map so any consumer of the metrics knows there has been a change\n const userRowHeights = new Map(this.userRowHeights);\n userRowHeights.set(row, Math.ceil(size));\n trimMap(userRowHeights);\n this.userRowHeights = userRowHeights;\n }\n\n /**\n * Resets the row height for the specified row to the calculated height\n * @param row The row model index to reset\n */\n resetRowHeight(row: ModelIndex): void {\n // Always use a new instance of the map so any consumer of the metrics knows there has been a change\n const userRowHeights = new Map(this.userRowHeights);\n userRowHeights.delete(row);\n this.userRowHeights = userRowHeights;\n this.calculatedRowHeights.delete(row);\n }\n}\n\nexport default GridMetricCalculator;\n","/** A color parsed as CSS color value, eg. '#FF0000' */\nexport type GridColor = string;\n\n/** A nullable color, eg. pass `null` to skip drawing this item */\nexport type NullableGridColor = GridColor | null;\n\n/** One or more colors parsed as CSS color value separated by space, eg. '#FF0000 #00FF00' */\nexport type GridColorWay = string;\n\n/** A font parsed as CSS font value */\nexport type GridFont = string;\n\nexport type GridTheme = {\n // Allow column/row resizing\n allowColumnResize: boolean;\n allowRowResize: boolean;\n\n // Select the full row/column upon selection\n autoSelectRow: boolean;\n autoSelectColumn: boolean;\n\n // Automatically size rows/columns to fit contents\n autoSizeColumns: boolean;\n autoSizeRows: boolean;\n\n // The background color for the whole grid\n backgroundColor: GridColor;\n\n // Color to draw text\n textColor: GridColor;\n\n // Amount of padding within a cell and header\n cellHorizontalPadding: number;\n headerHorizontalPadding: number;\n\n // The font to use in the grid\n font: GridFont;\n\n // Colors to draw grid lines between columns and rows\n gridColumnColor: NullableGridColor;\n gridRowColor: NullableGridColor;\n\n // Colors for drawing the column and row headers\n headerBackgroundColor: GridColor;\n headerSeparatorColor: GridColor;\n headerSeparatorHoverColor: GridColor;\n headerSeparatorHandleSize: number;\n headerHiddenSeparatorSize: number;\n headerHiddenSeparatorHoverColor: GridColor;\n headerColor: GridColor;\n headerFont: GridFont;\n\n // Background color to highlight entire column/row if set\n columnHoverBackgroundColor: NullableGridColor;\n selectedColumnHoverBackgroundColor: NullableGridColor;\n rowHoverBackgroundColor: NullableGridColor;\n selectedRowHoverBackgroundColor: NullableGridColor;\n\n // Background colors to draw for each row, cycling through each value (eg. alternating stripes)\n rowBackgroundColors: GridColorWay;\n\n // Scroll bar look and sizing\n minScrollHandleSize: number;\n scrollBarBackgroundColor: GridColor;\n scrollBarHoverBackgroundColor: GridColor;\n scrollBarCasingColor: GridColor;\n scrollBarCornerColor: GridColor;\n scrollBarColor: GridColor;\n scrollBarHoverColor: GridColor;\n scrollBarActiveColor: GridColor;\n scrollBarSize: number;\n scrollBarHoverSize: number;\n scrollBarCasingWidth: number;\n scrollSnapToColumn: boolean;\n scrollSnapToRow: boolean;\n\n // Look of the current selection\n selectionColor: GridColor;\n selectionOutlineColor: GridColor;\n selectionOutlineCasingColor: GridColor;\n\n // Shadows to draw when representing a hierarchy, eg. when one row is a higher \"depth\" than the row above it\n shadowBlur: number;\n shadowColor: GridColor;\n maxDepth: number; // max depth of the shadowing\n\n // Other tree table metrics\n treeDepthIndent: number;\n treeHorizontalPadding: number;\n treeLineColor: GridColor;\n treeMarkerColor: GridColor;\n treeMarkerHoverColor: GridColor;\n\n // Default row height/column width\n rowHeight: number;\n columnWidth: number;\n minRowHeight: number;\n minColumnWidth: number;\n\n // Default row/column header/footers width/height\n columnHeaderHeight: number;\n rowHeaderWidth: number;\n rowFooterWidth: number;\n\n // When resizing the header, will snap to the auto size of the header within this threshold\n headerResizeSnapThreshold: number;\n headerResizeHiddenSnapThreshold: number;\n\n // Allow moving/reordering columns/rows\n allowColumnReorder: boolean;\n allowRowReorder: boolean;\n\n // The number of pixels to offset a column/row while it is being dragged to move\n reorderOffset: number;\n\n // Colors for the grid in floating sections\n floatingGridColumnColor: NullableGridColor;\n floatingGridRowColor: NullableGridColor;\n\n // Background row colors for grid in the floating sections\n floatingRowBackgroundColors: GridColorWay;\n\n // Divider colors between the floating parts and the grid\n floatingDividerOuterColor: GridColor;\n floatingDividerInnerColor: GridColor;\n};\n\n/**\n * Default theme for a Grid.\n */\nexport default Object.freeze({\n allowColumnResize: true,\n allowRowResize: true,\n autoSelectRow: false, // Select the full row upon selection\n autoSelectColumn: false, // Select the full column upon selection\n autoSizeColumns: true, // Automatically size the columns to fit content\n autoSizeRows: true,\n backgroundColor: '#000000',\n cellHorizontalPadding: 5,\n headerHorizontalPadding: 5,\n font: '12px Arial, sans serif',\n gridColumnColor: '#8f8f8f66',\n gridRowColor: '#8f8f8f66',\n headerBackgroundColor: '#222222',\n headerSeparatorColor: '#000000',\n headerSeparatorHoverColor: '#888888',\n headerSeparatorHandleSize: 5,\n headerHiddenSeparatorSize: 5,\n headerHiddenSeparatorHoverColor: '#8888FF',\n headerColor: '#d5d5d5',\n headerFont: '10px Arial, sans serif',\n columnHoverBackgroundColor: '#444444',\n selectedColumnHoverBackgroundColor: '#494949',\n rowBackgroundColors: '#333333 #222222',\n rowHoverBackgroundColor: '#444444',\n selectedRowHoverBackgroundColor: '#494949',\n minScrollHandleSize: 50,\n scrollBarBackgroundColor: '#111111',\n scrollBarHoverBackgroundColor: '#333333',\n scrollBarCasingColor: '#000000',\n scrollBarCornerColor: '#000000',\n scrollBarColor: '#555555',\n scrollBarHoverColor: '#888888',\n scrollBarActiveColor: '#AAAAAA',\n scrollBarSize: 12,\n scrollBarHoverSize: 16,\n scrollBarCasingWidth: 1,\n scrollSnapToColumn: false,\n scrollSnapToRow: false,\n selectionColor: '#4286f433',\n selectionOutlineColor: '#4286f4',\n selectionOutlineCasingColor: '#222222',\n shadowBlur: 8,\n shadowColor: '#000000',\n textColor: '#ffffff',\n maxDepth: 6,\n treeDepthIndent: 10,\n treeHorizontalPadding: 5,\n treeLineColor: '#888888',\n treeMarkerColor: '#cccccc',\n treeMarkerHoverColor: '#ffffff',\n\n rowHeight: 20,\n columnWidth: 100,\n minRowHeight: 20,\n minColumnWidth: 55,\n columnHeaderHeight: 20,\n rowHeaderWidth: 30,\n rowFooterWidth: 0,\n\n // When resizing the header, will snap to the auto size of the header within this threshold\n headerResizeSnapThreshold: 10,\n headerResizeHiddenSnapThreshold: 8,\n\n allowColumnReorder: true,\n allowRowReorder: true,\n reorderOffset: 2,\n\n // Colors for the grid in floating sections\n floatingGridColumnColor: '#8f8f8f66',\n floatingGridRowColor: '#8f8f8f66',\n\n // Background row colors for grid in the floating sections\n floatingRowBackgroundColors: '#393939 #292929',\n\n // Divider colors between the floating parts and the grid\n floatingDividerOuterColor: '#000000',\n floatingDividerInnerColor: '#cccccc',\n}) as GridTheme;\n","/**\n * Extension of memoizee that clears the entire cache when it's full.\n * This avoids the situation where LRU cache starts thrashing when it fills up.\n * Could look at writing our own memoize with a smarter cache to avoid overhead of\n * LRU queue, but this should be sufficient for now.\n */\nimport memoizee from 'memoizee';\n\n/**\n * @param fn The function to memoize\n * @param options The options to set for memoization\n */\nexport const memoizeClear: typeof memoizee = (fn, options) => {\n let isClearingCache = false;\n const memoizedFn = memoizee(fn, {\n ...options,\n dispose: () => {\n // Need to track when we're clearing because dispose gets called for all items removed\n if (!isClearingCache) {\n isClearingCache = true;\n memoizedFn.clear();\n isClearingCache = false;\n }\n },\n });\n\n return memoizedFn;\n};\n\nexport default memoizeClear;\n","import convert from 'color-convert';\nimport { HEX } from 'color-convert/conversions';\nimport { GridColor } from './GridTheme';\n\n/**\n * Darken the provided colour\n * @param color Color in hex format to convert (with #)\n * @param depth Depth to convert the color to\n * @param maxDepth Maximum depth. Defaults to 6\n * @returns Darkened colour in hex format\n */\nexport function darkenForDepth(\n color: HEX,\n depth: number,\n maxDepth = 6\n): GridColor {\n const lab = convert.hex.lab(color);\n lab[0] = Math.max(lab[0] - (lab[0] / maxDepth) * depth, 0);\n return `#${convert.lab.hex(lab)}`;\n}\n\n/**\n * Convert a hex colour to an rgba with specified alpha\n * @param color Color in hex format to convert (with #)\n * @param alpha Alpha to apply to the color\n * @returns Color with the newly applied alpha in rgba format\n */\nexport function colorWithAlpha(color: HEX, alpha: number): GridColor {\n const [r, g, b] = convert.hex.rgb(color);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nexport default { colorWithAlpha, darkenForDepth };\n","import memoizeClear from './memoizeClear';\nimport GridUtils from './GridUtils';\nimport GridColorUtils from './GridColorUtils';\nimport { isExpandableGridModel } from './ExpandableGridModel';\nimport {\n GridColor,\n GridColorWay,\n GridTheme,\n NullableGridColor,\n} from './GridTheme';\nimport GridModel from './GridModel';\nimport GridRange from './GridRange';\nimport GridMetrics, {\n BoxCoordinates,\n Coordinate,\n VisibleIndex,\n} from './GridMetrics';\nimport { getOrThrow } from './GridMetricCalculator';\nimport { isEditableGridModel } from './EditableGridModel';\n\nexport type EditingCellTextSelectionRange = [start: number, end: number];\n\nexport type EditingCell = {\n // Index of the editing cell\n column: VisibleIndex;\n row: VisibleIndex;\n\n // Selection within the text\n selectionRange?: EditingCellTextSelectionRange;\n\n // The value to use for the edit\n value: string;\n\n // Whether the selection was triggered with a quick edit action (e.g. Start typing with the cell in focus)\n isQuickEdit?: boolean;\n};\n\nexport type GridRenderState = {\n // The top/left cell of the scrolled viewport\n left: VisibleIndex;\n top: VisibleIndex;\n\n // Width and height of the total canvas area\n width: number;\n height: number;\n\n // The canvas context\n context: CanvasRenderingContext2D;\n\n // The grid theme\n theme: GridTheme;\n\n // The model used by the grid\n model: GridModel;\n\n // The grid metrics\n metrics: GridMetrics;\n\n // Location of the mouse on the grid\n mouseX: number | null;\n mouseY: number | null;\n\n // Where the keyboard cursor is located\n cursorColumn: VisibleIndex | null;\n cursorRow: VisibleIndex | null;\n\n // Currently selected ranges\n selectedRanges: GridRange[];\n\n // Currently dragged column/row information\n draggingColumn: VisibleIndex | null;\n draggingColumnOffset: number | null;\n draggingColumnSeparator: VisibleIndex | null;\n draggingRow: VisibleIndex | null;\n draggingRowOffset: number | null;\n draggingRowSeparator: VisibleIndex | null;\n\n // The currently editing cell\n editingCell: EditingCell | null;\n isDraggingHorizontalScrollBar: boolean;\n isDraggingVerticalScrollBar: boolean;\n isDragging: boolean;\n};\n\n/* eslint react/destructuring-assignment: \"off\" */\n/* eslint class-methods-use-this: \"off\" */\n/* eslint no-param-reassign: \"off\" */\n/**\n * A GridRenderer handles rendering the different parts of the grid\n * This default rendering just renders a basic grid. Extend this class and implement\n * your own methods to customize drawing of the grid (eg. Draw icons or special features)\n */\nexport class GridRenderer {\n // Default font width in pixels if it cannot be retrieved from the context\n static DEFAULT_FONT_WIDTH = 10;\n\n // Default radius in pixels for corners for some elements (like the active cell)\n static DEFAULT_EDGE_RADIUS = 2;\n\n // Default width in pixels for the border of the active cell\n static ACTIVE_CELL_BORDER_WIDTH = 2;\n\n /**\n * Truncate a string to the specified length and add ellipses if necessary\n * @param str The string to truncate\n * @param len The length to truncate the string to. If longer than the actual string, just returns the string\n * @returns The truncated string\n */\n static truncate(str: string, len: number): string {\n if (len < str.length) {\n // eslint-disable-next-line prefer-template\n return str.substr(0, len) + '…';\n }\n return str;\n }\n\n /**\n * Uses binary search to truncate a string to fit in the provided width\n * @param context The drawing context to measure the text in\n * @param str The string to get the maximum length it can draw\n * @param width The width to truncate it to\n * @param start The low boundary to start the search\n * @param end The high boundary to start the search\n * @returns The truncated string\n */\n static binaryTruncateToWidth(\n context: CanvasRenderingContext2D,\n str: string,\n width: number,\n start = 0,\n end = str.length\n ): string {\n if (end >= str.length && context.measureText(str).width <= width) {\n // IDS-6069 If the whole string can fit, don't bother checking for truncation\n // The ellipses are actually slightly wider than other chars, and it's possible\n // that the \"truncation\" ends up being slightly longer, which messes up the search\n // algorithm below.\n // Besides, if we already fit, it's just faster to not bother checking other truncations.\n return str;\n }\n let lo = start;\n let hi = Math.min(str.length - 1, end);\n let result = str;\n while (hi >= lo) {\n const mid = Math.ceil((hi + lo) / 2);\n const truncatedStr = GridRenderer.truncate(str, mid);\n if (context.measureText(truncatedStr).width <= width) {\n result = truncatedStr;\n if (lo === mid) {\n break;\n }\n lo = mid;\n } else if (mid === 0) {\n // We already truncated to zero chars and it still doesn't fit, no need to keep looking\n result = truncatedStr;\n break;\n } else {\n hi = mid - 1;\n }\n }\n\n return result;\n }\n\n /**\n * Truncate a string (if necessary) to fit in the specified width.\n * First uses the estimated font width to calculate a lower/upper bound\n * Then uses binary search within those bounds to find the exact max length\n * @param context The drawing context\n * @param str The string to calculate max length for\n * @param width The width to truncate within\n * @param fontWidth The estimated width of each character\n * @returns The truncated string that fits within the width provided\n */\n static truncateToWidth(\n context: CanvasRenderingContext2D,\n str: string,\n width: number,\n fontWidth = GridRenderer.DEFAULT_FONT_WIDTH\n ): string {\n if (width <= 0 || str.length <= 0) {\n return '';\n }\n\n // Estimate the possible low and high boundaries for truncating the text\n // Use the width of the space divided by the estimated width of each character,\n // and take half that as the low (minus 5 just to be extra safe), and double that as the high.\n const lo = Math.min(\n Math.max(0, Math.floor(width / fontWidth / 2) - 5),\n str.length\n );\n const hi = Math.min(Math.ceil((width / fontWidth) * 2), str.length);\n\n return GridRenderer.binaryTruncateToWidth(context, str, width, lo, hi);\n }\n\n /**\n * Draw the grid canvas with the state provided\n * @param state The state of the grid\n */\n drawCanvas(state: GridRenderState): void {\n const { context } = state;\n\n context.save();\n\n this.configureContext(context, state);\n\n this.drawBackground(context, state);\n\n this.drawGrid(context, state);\n\n this.drawHeaders(context, state);\n\n this.drawFooters(context, state);\n\n this.drawDraggingColumn(context, state);\n\n this.drawDraggingRow(context, state);\n\n this.drawScrollBars(context, state);\n\n context.restore();\n }\n\n configureContext(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { theme } = state;\n context.font = theme.font;\n context.textBaseline = 'middle';\n context.lineCap = 'butt';\n }\n\n drawBackground(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { theme, metrics } = state;\n const { width, height } = metrics;\n context.fillStyle = theme.backgroundColor;\n context.fillRect(0, 0, width, height);\n }\n\n drawGrid(context: CanvasRenderingContext2D, state: GridRenderState): void {\n const { metrics, draggingRow, draggingColumn } = state;\n const { gridX, gridY } = metrics;\n\n context.translate(gridX, gridY);\n\n this.drawGridBackground(\n context,\n state,\n draggingRow == null && draggingColumn == null\n );\n\n this.drawCellContents(context, state);\n\n this.drawFloatingRows(context, state);\n\n this.drawFloatingColumns(context, state);\n\n context.translate(-gridX, -gridY);\n }\n\n drawFloatingRows(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { draggingRow, draggingColumn, metrics, theme } = state;\n const {\n floatingTopRowCount,\n floatingBottomRowCount,\n floatingRows,\n rowCount,\n visibleColumns,\n visibleRowYs,\n visibleRowHeights,\n } = metrics;\n\n if (floatingRows.length === 0) {\n return;\n }\n\n if (theme.floatingRowBackgroundColors) {\n this.drawRowStripesForRows(\n context,\n state,\n floatingRows,\n theme.floatingRowBackgroundColors\n );\n }\n\n if (draggingRow == null && draggingColumn == null) {\n this.drawFloatingMouseRowHover(context, state);\n }\n\n this.drawGridLinesForItems(\n context,\n state,\n visibleColumns,\n floatingRows,\n theme.floatingGridColumnColor,\n theme.floatingGridRowColor\n );\n\n this.drawCellBackgroundsForItems(\n context,\n state,\n visibleColumns,\n floatingRows\n );\n\n this.drawFloatingBorders(context, state);\n\n // Draw the floating row selection...\n if (floatingTopRowCount > 0) {\n this.drawSelectedRanges(context, state, {\n top: 0,\n bottom: floatingTopRowCount - 1,\n maxY:\n getOrThrow(visibleRowYs, floatingTopRowCount - 1) +\n getOrThrow(visibleRowHeights, floatingTopRowCount - 1) -\n 0.5,\n });\n }\n if (floatingBottomRowCount > 0) {\n this.drawSelectedRanges(context, state, {\n top: rowCount - floatingBottomRowCount - 1,\n bottom: rowCount - 1,\n minY: getOrThrow(visibleRowYs, rowCount - floatingBottomRowCount) + 0.5,\n maxY:\n getOrThrow(visibleRowYs, rowCount - 1) +\n getOrThrow(visibleRowHeights, rowCount - 1) -\n 0.5,\n });\n }\n\n // Draw the cell content...\n for (let c = 0; c < visibleColumns.length; c += 1) {\n const column = visibleColumns[c];\n for (let r = 0; r < floatingRows.length; r += 1) {\n const row = floatingRows[r];\n this.drawCellContent(context, state, column, row);\n }\n }\n }\n\n drawFloatingColumns(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { draggingRow, draggingColumn, metrics, theme } = state;\n const {\n floatingLeftColumnCount,\n floatingRightColumnCount,\n floatingLeftWidth,\n floatingRightWidth,\n floatingColumns,\n gridX,\n maxX,\n columnCount,\n visibleRows,\n visibleColumnXs,\n visibleColumnWidths,\n width,\n height,\n } = metrics;\n\n if (floatingColumns.length === 0) {\n return;\n }\n\n if (theme.floatingRowBackgroundColors) {\n this.drawRowStripesForRows(\n context,\n state,\n visibleRows,\n theme.floatingRowBackgroundColors,\n 0,\n floatingLeftWidth\n );\n this.drawRowStripesForRows(\n context,\n state,\n visibleRows,\n theme.floatingRowBackgroundColors,\n width - gridX - floatingRightWidth,\n maxX\n );\n }\n\n if (draggingRow == null && draggingColumn == null) {\n this.drawFloatingMouseRowHover(context, state);\n }\n\n // Clip floated column grid lines.\n context.save();\n context.beginPath();\n context.rect(0, 0, floatingLeftWidth, height);\n context.clip();\n\n this.drawGridLinesForItems(\n context,\n state,\n floatingColumns,\n visibleRows,\n theme.floatingGridColumnColor,\n theme.floatingGridRowColor\n );\n\n context.restore();\n\n this.drawCellBackgroundsForItems(\n context,\n state,\n floatingColumns,\n visibleRows\n );\n\n this.drawFloatingBorders(context, state);\n\n // Draw the floating column selection...\n if (floatingLeftColumnCount > 0) {\n this.drawSelectedRanges(context, state, {\n left: 0,\n maxX:\n getOrThrow(visibleColumnXs, floatingLeftColumnCount - 1) +\n getOrThrow(visibleColumnWidths, floatingLeftColumnCount - 1),\n });\n }\n if (floatingRightColumnCount > 0) {\n this.drawSelectedRanges(context, state, {\n left: columnCount - floatingRightColumnCount,\n right: columnCount - 1,\n minX:\n getOrThrow(visibleColumnXs, columnCount - floatingRightColumnCount) +\n 0.5,\n maxX:\n getOrThrow(visibleColumnXs, columnCount - 1) +\n getOrThrow(visibleColumnWidths, columnCount - 1),\n });\n }\n\n // Draw the cell content...\n for (let c = 0; c < floatingColumns.length; c += 1) {\n const column = floatingColumns[c];\n for (let r = 0; r < visibleRows.length; r += 1) {\n const row = visibleRows[r];\n this.drawCellContent(context, state, column, row);\n }\n }\n }\n\n drawFloatingBorders(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { metrics, theme } = state;\n const {\n floatingTopRowCount,\n floatingBottomRowCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n rowCount,\n columnCount,\n visibleRowYs,\n visibleColumnXs,\n visibleRowHeights,\n visibleColumnWidths,\n maxX,\n maxY,\n } = metrics;\n const { floatingDividerOuterColor, floatingDividerInnerColor } = theme;\n\n context.lineWidth = 3;\n context.beginPath();\n context.strokeStyle = floatingDividerOuterColor;\n\n if (floatingTopRowCount > 0) {\n const y =\n getOrThrow(visibleRowYs, floatingTopRowCount - 1) +\n getOrThrow(visibleRowHeights, floatingTopRowCount - 1) +\n 0.5;\n context.moveTo(0.5, y);\n context.lineTo(maxX - 0.5, y);\n }\n\n if (floatingBottomRowCount > 0) {\n const y =\n getOrThrow(visibleRowYs, rowCount - floatingBottomRowCount) - 0.5;\n context.moveTo(0.5, y);\n context.lineTo(maxX - 0.5, y);\n }\n\n if (floatingLeftColumnCount > 0) {\n const x =\n getOrThrow(visibleColumnXs, floatingLeftColumnCount - 1) +\n getOrThrow(visibleColumnWidths, floatingLeftColumnCount - 1) +\n 0.5;\n context.moveTo(x, 0.5);\n context.lineTo(x, maxY - 0.5);\n }\n\n if (floatingRightColumnCount > 0) {\n const x =\n getOrThrow(visibleColumnXs, columnCount - floatingRightColumnCount) -\n 0.5;\n context.moveTo(x, 0.5);\n context.lineTo(x, maxY - 0.5);\n }\n\n context.stroke();\n\n context.beginPath();\n context.lineWidth = 1;\n context.strokeStyle = floatingDividerInnerColor;\n\n if (floatingTopRowCount > 0) {\n const y =\n getOrThrow(visibleRowYs, floatingTopRowCount - 1) +\n getOrThrow(visibleRowHeights, floatingTopRowCount - 1) +\n 0.5;\n context.moveTo(0.5, y);\n context.lineTo(maxX - 0.5, y);\n }\n\n if (floatingBottomRowCount > 0) {\n const y =\n getOrThrow(visibleRowYs, rowCount - floatingBottomRowCount) - 0.5;\n context.moveTo(0.5, y);\n context.lineTo(maxX - 0.5, y);\n }\n\n if (floatingLeftColumnCount > 0) {\n const x =\n getOrThrow(visibleColumnXs, floatingLeftColumnCount - 1) +\n getOrThrow(visibleColumnWidths, floatingLeftColumnCount - 1) +\n 0.5;\n context.moveTo(x, 0.5);\n context.lineTo(x, maxY - 0.5);\n }\n\n if (floatingRightColumnCount > 0) {\n const x =\n getOrThrow(visibleColumnXs, columnCount - floatingRightColumnCount) -\n 0.5;\n context.moveTo(x, 0.5);\n context.lineTo(x, maxY - 0.5);\n }\n\n context.stroke();\n }\n\n drawGridBackground(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n drawHover = false\n ): void {\n this.drawRowStripes(context, state);\n\n if (drawHover) {\n this.drawMouseColumnHover(context, state);\n\n this.drawMouseRowHover(context, state);\n }\n\n this.drawGridLines(context, state);\n\n this.drawCellBackgrounds(context, state);\n\n const { metrics } = state;\n const {\n bottom,\n right,\n floatingBottomRowCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n floatingTopRowCount,\n columnCount,\n rowCount,\n visibleRowHeights,\n visibleRowYs,\n visibleColumnXs,\n visibleColumnWidths,\n width,\n height,\n } = metrics;\n this.drawSelectedRanges(context, state, {\n bottom: Math.min(bottom, rowCount - floatingBottomRowCount - 1),\n right: Math.min(right, columnCount - floatingRightColumnCount - 1),\n minX:\n floatingLeftColumnCount > 0 &&\n visibleColumnXs.has(floatingLeftColumnCount + 1)\n ? getOrThrow(visibleColumnXs, floatingLeftColumnCount + 1)\n : -10,\n minY:\n floatingTopRowCount > 0 && visibleRowYs.has(floatingTopRowCount + 1)\n ? getOrThrow(visibleRowYs, floatingTopRowCount + 1)\n : -10,\n maxX:\n floatingRightColumnCount > 0 &&\n visibleColumnXs.has(columnCount - floatingRightColumnCount - 1)\n ? getOrThrow(\n visibleColumnXs,\n columnCount - floatingRightColumnCount - 1\n ) +\n getOrThrow(\n visibleColumnWidths,\n columnCount - floatingRightColumnCount - 1\n ) -\n 0.5\n : width + 10,\n maxY:\n floatingBottomRowCount > 0 &&\n visibleRowYs.has(rowCount - floatingBottomRowCount - 1)\n ? getOrThrow(visibleRowYs, rowCount - floatingBottomRowCount - 1) +\n getOrThrow(\n visibleRowHeights,\n rowCount - floatingBottomRowCount - 1\n ) -\n 0.5\n : height + 10,\n });\n }\n\n drawRowStripes(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { metrics, theme } = state;\n const { visibleRows } = metrics;\n const { rowBackgroundColors } = theme;\n if (!rowBackgroundColors) {\n return;\n }\n this.drawRowStripesForRows(\n context,\n state,\n visibleRows,\n rowBackgroundColors\n );\n }\n\n drawRowStripesForRows(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n rows: VisibleIndex[],\n rowBackgroundColors: GridColorWay,\n minX = 0,\n maxX = state.metrics.maxX\n ): void {\n const { theme, metrics, model } = state;\n const { maxDepth, shadowBlur, shadowColor } = theme;\n\n const colorSets = this.getCachedBackgroundColors(\n rowBackgroundColors,\n maxDepth\n );\n const { visibleRowYs, visibleRowHeights } = metrics;\n\n // Optimize by grouping together all rows that end up with the same color\n const colorRowMap = new Map();\n const topShadowRows: VisibleIndex[] = []; // Rows that are deeper than the row above them\n const bottomShadowRows: VisibleIndex[] = [];\n const addRowToColorMap = (\n row: VisibleIndex,\n rowAbove?: VisibleIndex\n ): void => {\n const depth = isExpandableGridModel(model) ? model.depthForRow(row) : 0;\n const colorSet = colorSets[row % colorSets.length];\n const color = colorSet[Math.min(depth, colorSet.length - 1)];\n if (!colorRowMap.has(color)) {\n colorRowMap.set(color, []);\n }\n colorRowMap.get(color).push(row);\n if (rowAbove != null) {\n const depthAbove = isExpandableGridModel(model)\n ? model.depthForRow(rowAbove)\n : 0;\n if (depthAbove < depth) {\n topShadowRows.push(row);\n } else if (depthAbove > depth) {\n bottomShadowRows.push(rowAbove);\n }\n }\n };\n\n // Add all the regular row stripes\n for (let i = 0; i < rows.length; i += 1) {\n const row = rows[i];\n const rowAbove = i > 0 ? rows[i - 1] : undefined;\n addRowToColorMap(row, rowAbove);\n }\n\n colorRowMap.forEach((colorRows, color) => {\n context.fillStyle = color;\n\n context.beginPath();\n\n for (let i = 0; i < colorRows.length; i += 1) {\n const row = colorRows[i];\n const y = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n context.rect(minX, y, maxX, rowHeight);\n }\n\n context.fill();\n });\n\n if (topShadowRows.length > 0) {\n context.save();\n\n const startColor = this.getCachedColorWithAlpha(shadowColor, 0.15);\n const endColor = this.getCachedColorWithAlpha(shadowColor, 0);\n const gradient = context.createLinearGradient(0, 0, 0, shadowBlur);\n gradient.addColorStop(0, startColor);\n gradient.addColorStop(1, endColor);\n context.fillStyle = gradient;\n\n for (let i = 0; i < topShadowRows.length; i += 1) {\n const row = topShadowRows[i];\n const y = getOrThrow(visibleRowYs, row);\n // Use a translate so we can reuse the gradient\n context.translate(0, y);\n context.fillRect(minX, 0, maxX, shadowBlur);\n context.translate(0, -y);\n }\n\n context.restore();\n }\n\n if (bottomShadowRows.length > 0) {\n context.save();\n\n const startColor = this.getCachedColorWithAlpha(shadowColor, 0);\n const endColor = this.getCachedColorWithAlpha(shadowColor, 0.15);\n const gradient = context.createLinearGradient(0, 0, 0, shadowBlur);\n gradient.addColorStop(0, startColor);\n gradient.addColorStop(1, endColor);\n context.fillStyle = gradient;\n\n for (let i = 0; i < bottomShadowRows.length; i += 1) {\n const row = bottomShadowRows[i];\n const y = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n const gradientY = y + rowHeight - shadowBlur;\n // Use a translate so we can reuse the gradient\n context.translate(0, gradientY);\n context.fillRect(minX, 0, maxX, shadowBlur);\n context.translate(0, -gradientY);\n }\n\n context.restore();\n }\n }\n\n drawMouseColumnHover(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { mouseX, mouseY, theme, metrics } = state;\n if (mouseX == null || mouseY == null) return;\n\n const mouseColumn = GridUtils.getColumnAtX(mouseX, metrics);\n if (mouseColumn == null || !theme.columnHoverBackgroundColor) {\n return;\n }\n\n const { visibleColumnWidths, visibleColumnXs, maxY } = metrics;\n if (mouseY > maxY) {\n return;\n }\n\n const x = getOrThrow(visibleColumnXs, mouseColumn);\n const columnWidth = getOrThrow(visibleColumnWidths, mouseColumn);\n\n context.fillStyle = theme.columnHoverBackgroundColor;\n context.fillRect(x, 0, columnWidth, maxY);\n }\n\n drawMouseRowHover(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { mouseX, mouseY, theme, metrics } = state;\n if (mouseX == null || mouseY == null) return;\n\n const { maxX } = metrics;\n if (mouseX > maxX || !theme.rowHoverBackgroundColor) {\n return;\n }\n\n const mouseRow = GridUtils.getRowAtY(mouseY, metrics);\n if (mouseRow == null) {\n return;\n }\n\n this.drawMouseRowHoverForRow(context, state, mouseRow);\n }\n\n drawFloatingMouseRowHover(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { mouseX, mouseY, theme, metrics } = state;\n const {\n maxX,\n floatingTopRowCount,\n floatingBottomRowCount,\n rowCount,\n rowFooterWidth,\n } = metrics;\n if (\n mouseX == null ||\n mouseY == null ||\n mouseX > maxX + rowFooterWidth ||\n !theme.rowHoverBackgroundColor\n ) {\n return;\n }\n\n const mouseRow = GridUtils.getRowAtY(mouseY, metrics);\n if (\n mouseRow != null &&\n (mouseRow < floatingTopRowCount ||\n rowCount - floatingBottomRowCount <= mouseRow)\n ) {\n this.drawMouseRowHoverForRow(context, state, mouseRow);\n }\n }\n\n drawMouseRowHoverForRow(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n row: VisibleIndex\n ): void {\n const { metrics, selectedRanges, theme } = state;\n const { visibleRowHeights, visibleRowYs, maxX } = metrics;\n\n const y = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n\n if (theme.rowHoverBackgroundColor) {\n context.fillStyle = theme.rowHoverBackgroundColor;\n }\n for (let i = 0; i < selectedRanges.length; i += 1) {\n const { startRow, endRow } = selectedRanges[i];\n if (\n startRow != null &&\n endRow != null &&\n startRow <= row &&\n endRow >= row\n ) {\n if (theme.selectedRowHoverBackgroundColor) {\n context.fillStyle = theme.selectedRowHoverBackgroundColor;\n }\n break;\n }\n }\n context.fillRect(0, y, maxX, rowHeight);\n }\n\n drawGridLines(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { metrics, theme } = state;\n const { visibleColumns, visibleRows } = metrics;\n\n this.drawGridLinesForItems(\n context,\n state,\n visibleColumns,\n visibleRows,\n theme.gridColumnColor,\n theme.gridRowColor\n );\n }\n\n drawGridLinesForItems(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n columns: VisibleIndex[],\n rows: VisibleIndex[],\n columnColor: NullableGridColor,\n rowColor: NullableGridColor\n ): void {\n if (!columnColor && !rowColor) {\n return;\n }\n\n context.lineWidth = 1;\n context.beginPath();\n\n if (columnColor) {\n context.strokeStyle = columnColor;\n this.drawGridLinesForColumns(context, state, columns);\n }\n if (rowColor) {\n context.strokeStyle = rowColor;\n this.drawGridLinesForRows(context, state, rows);\n }\n\n context.stroke();\n }\n\n drawGridLinesForColumns(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n columns: VisibleIndex[]\n ): void {\n const { metrics } = state;\n const { visibleColumnXs, maxY } = metrics;\n for (let i = 0; i < columns.length; i += 1) {\n const column = columns[i];\n const x = getOrThrow(visibleColumnXs, column) + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, maxY);\n }\n }\n\n drawGridLinesForRows(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n rows: VisibleIndex[]\n ): void {\n const { metrics } = state;\n const { visibleRowYs, maxX: metricsMaxX } = metrics;\n const maxX = metricsMaxX;\n\n // Draw row lines\n for (let i = 0; i < rows.length; i += 1) {\n const row = rows[i];\n const y = getOrThrow(visibleRowYs, row) + 0.5;\n context.moveTo(0.5, y);\n context.lineTo(maxX - 0.5, y);\n }\n }\n\n drawCellBackgrounds(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { metrics } = state;\n const { visibleColumns, visibleRows } = metrics;\n this.drawCellBackgroundsForItems(\n context,\n state,\n visibleColumns,\n visibleRows\n );\n }\n\n drawCellBackgroundsForItems(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n columns: VisibleIndex[],\n rows: VisibleIndex[]\n ): void {\n context.save();\n\n for (let i = 0; i < columns.length; i += 1) {\n const column = columns[i];\n\n for (let j = 0; j < rows.length; j += 1) {\n const row = rows[j];\n const rowAfter = j + 1 < rows.length ? rows[j + 1] : undefined;\n this.drawCellBackground(context, state, column, row, rowAfter);\n }\n }\n\n context.restore();\n }\n\n drawCellBackground(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n column: VisibleIndex,\n row: VisibleIndex,\n rowAfter?: VisibleIndex\n ): void {\n const { metrics, model, theme } = state;\n const {\n firstColumn,\n modelColumns,\n modelRows,\n visibleColumnXs,\n visibleColumnWidths,\n visibleRowYs,\n visibleRowHeights,\n } = metrics;\n const modelRow = getOrThrow(modelRows, row);\n const modelColumn = getOrThrow(modelColumns, column);\n const backgroundColor = model.backgroundColorForCell(\n modelColumn,\n modelRow,\n theme\n );\n const isFirstColumn = column === firstColumn;\n const hasExpandableRows =\n isExpandableGridModel(model) && model.hasExpandableRows;\n\n if (backgroundColor) {\n const x = getOrThrow(visibleColumnXs, column) + 1;\n const y = getOrThrow(visibleRowYs, row) + 1;\n const columnWidth = getOrThrow(visibleColumnWidths, column) - 1;\n const rowHeight = getOrThrow(visibleRowHeights, row) - 1;\n context.fillStyle = backgroundColor;\n context.fillRect(x, y, columnWidth, rowHeight);\n }\n\n if (isFirstColumn && hasExpandableRows) {\n this.drawCellRowTreeDepthLines(context, state, row, rowAfter);\n }\n }\n\n drawCellContents(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { metrics } = state;\n const { visibleColumns } = metrics;\n\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n this.drawColumnCellContents(context, state, column);\n }\n }\n\n drawColumnCellContents(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n column: VisibleIndex\n ): void {\n const { metrics } = state;\n const {\n visibleColumnXs,\n visibleColumnWidths,\n visibleRows,\n height,\n } = metrics;\n const x = getOrThrow(visibleColumnXs, column);\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n\n context.save();\n\n context.beginPath();\n context.rect(x, 0, columnWidth, height);\n context.clip();\n\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n this.drawCellContent(context, state, column, row);\n }\n context.restore();\n }\n\n drawCellContent(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n column: VisibleIndex,\n row: VisibleIndex,\n textOverride?: string\n ): void {\n const { metrics, model, theme } = state;\n const {\n firstColumn,\n fontWidths,\n modelColumns,\n modelRows,\n visibleColumnXs,\n visibleColumnWidths,\n visibleRowYs,\n visibleRowHeights,\n } = metrics;\n const {\n cellHorizontalPadding,\n treeDepthIndent,\n treeHorizontalPadding,\n textColor,\n } = theme;\n const x = getOrThrow(visibleColumnXs, column);\n const y = getOrThrow(visibleRowYs, row);\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n const modelRow = getOrThrow(modelRows, row);\n const modelColumn = getOrThrow(modelColumns, column);\n const text = textOverride ?? model.textForCell(modelColumn, modelRow);\n const isFirstColumn = column === firstColumn;\n\n if (text && rowHeight > 0) {\n const textAlign = model.textAlignForCell(modelColumn, modelRow) || 'left';\n context.textAlign = textAlign;\n\n const color =\n model.colorForCell(modelColumn, modelRow, theme) || textColor;\n context.fillStyle = color;\n\n let treeIndent = 0;\n if (\n isExpandableGridModel(model) &&\n model.hasExpandableRows &&\n isFirstColumn\n ) {\n treeIndent =\n treeDepthIndent * (model.depthForRow(row) + 1) +\n treeHorizontalPadding;\n }\n const textWidth = columnWidth - treeIndent;\n let textX = x + cellHorizontalPadding;\n const textY = y + rowHeight * 0.5;\n if (textAlign === 'right') {\n textX = x + textWidth - cellHorizontalPadding;\n } else if (textAlign === 'center') {\n textX = x + textWidth * 0.5;\n } else {\n textX = x + cellHorizontalPadding;\n }\n textX += treeIndent;\n\n const fontWidth =\n fontWidths.get(context.font) ?? GridRenderer.DEFAULT_FONT_WIDTH;\n const truncatedText = this.getCachedTruncatedString(\n context,\n text,\n textWidth - cellHorizontalPadding * 2,\n fontWidth\n );\n if (truncatedText) {\n context.fillText(truncatedText, textX, textY);\n }\n }\n\n if (\n isFirstColumn &&\n isExpandableGridModel(model) &&\n model.hasExpandableRows\n ) {\n this.drawCellRowTreeMarker(context, state, row);\n }\n }\n\n drawCellRowTreeMarker(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n row: VisibleIndex\n ): void {\n const { metrics, model, mouseX, mouseY, theme } = state;\n const {\n firstColumn,\n gridX,\n gridY,\n visibleColumnXs,\n visibleColumnWidths,\n visibleRowYs,\n visibleRowHeights,\n visibleRowTreeBoxes,\n } = metrics;\n const { treeMarkerColor, treeMarkerHoverColor } = theme;\n const columnX = getOrThrow(visibleColumnXs, firstColumn);\n const columnWidth = getOrThrow(visibleColumnWidths, firstColumn);\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n if (!isExpandableGridModel(model) || !model.isRowExpandable(row)) {\n return;\n }\n\n const treeBox = getOrThrow(visibleRowTreeBoxes, row);\n const color =\n mouseX != null &&\n mouseY != null &&\n mouseX >= gridX + columnX &&\n mouseX <= gridX + columnX + columnWidth &&\n mouseY >= gridY + rowY &&\n mouseY <= gridY + rowY + rowHeight\n ? treeMarkerHoverColor\n : treeMarkerColor;\n\n this.drawTreeMarker(\n context,\n state,\n columnX,\n rowY,\n treeBox,\n color,\n model.isRowExpanded(row)\n );\n }\n\n drawTreeMarker(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n columnX: Coordinate,\n rowY: Coordinate,\n treeBox: BoxCoordinates,\n color: GridColor,\n isExpanded: boolean\n ): void {\n const { x1, y1, x2, y2 } = treeBox;\n const markerText = isExpanded ? '⊟' : '⊞';\n const textX = columnX + (x1 + x2) * 0.5 + 0.5;\n const textY = rowY + (y1 + y2) * 0.5 + 0.5;\n context.fillStyle = color;\n context.textAlign = 'center';\n context.fillText(markerText, textX, textY);\n }\n\n drawCellRowTreeDepthLines(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n row: VisibleIndex,\n rowAfter?: VisibleIndex\n ): void {\n const { metrics, model, theme } = state;\n\n if (!isExpandableGridModel(model)) return;\n\n const depth = model.depthForRow(row);\n if (depth === 0) return;\n\n const {\n firstColumn,\n visibleColumnXs,\n visibleRowYs,\n visibleRowHeights,\n } = metrics;\n const { treeDepthIndent, treeHorizontalPadding, treeLineColor } = theme;\n const columnX = getOrThrow(visibleColumnXs, firstColumn);\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n const depthRowAfter =\n rowAfter !== undefined ? model.depthForRow(rowAfter) : 0;\n const depthDiff = depth > depthRowAfter ? depth - depthRowAfter : 0;\n\n context.strokeStyle = treeLineColor;\n context.lineWidth = 1;\n\n // draw normal depth lines\n if (depth - depthDiff > 0) {\n context.beginPath();\n for (let i = 0; i < depth - depthDiff; i += 1) {\n const lineX =\n columnX +\n i * treeDepthIndent +\n treeDepthIndent * 0.5 +\n treeHorizontalPadding +\n 0.5;\n context.moveTo(lineX, rowY);\n context.lineTo(lineX, rowY + rowHeight);\n }\n context.stroke();\n }\n\n // draw as hockey stick if last row at depth\n if (depthDiff > 0) {\n context.beginPath();\n for (let i = depth - depthDiff; i < depth; i += 1) {\n const lineX =\n columnX +\n i * treeDepthIndent +\n treeDepthIndent * 0.5 +\n treeHorizontalPadding +\n 0.5;\n context.moveTo(lineX, rowY);\n context.lineTo(lineX, rowY + Math.ceil(rowHeight / 2));\n // extra moveTo prevents halfpixel in corner\n context.moveTo(lineX - 0.5, rowY + Math.ceil(rowHeight / 2) + 0.5);\n context.lineTo(\n lineX + treeDepthIndent - 0.5,\n rowY + Math.ceil(rowHeight / 2) + 0.5\n );\n }\n context.stroke();\n }\n }\n\n getCachedTruncatedString = memoizeClear(\n (\n context: CanvasRenderingContext2D,\n text: string,\n width: number,\n fontWidth: number\n ): string => GridRenderer.truncateToWidth(context, text, width, fontWidth),\n { max: 10000 }\n );\n\n getCachedBackgroundColors = memoizeClear(\n (backgroundColors: GridColorWay, maxDepth: number): GridColor[][] =>\n backgroundColors.split(' ').map(color => {\n const colors = [];\n for (let i = 0; i < maxDepth; i += 1) {\n colors.push(GridColorUtils.darkenForDepth(color, i, maxDepth));\n }\n return colors;\n }),\n { max: 1000 }\n );\n\n getCachedColorWithAlpha = memoizeClear(\n (color, alpha) => GridColorUtils.colorWithAlpha(color, alpha),\n { max: 1000 }\n );\n\n drawHeaders(context: CanvasRenderingContext2D, state: GridRenderState): void {\n const { theme } = state;\n\n context.font = theme.headerFont;\n\n this.drawColumnHeaders(context, state);\n\n this.drawRowHeaders(context, state);\n }\n\n drawFooters(context: CanvasRenderingContext2D, state: GridRenderState): void {\n const { theme } = state;\n\n context.font = theme.headerFont;\n\n this.drawRowFooters(context, state);\n }\n\n drawColumnHeaders(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const {\n mouseX,\n mouseY,\n theme,\n metrics,\n draggingColumnSeparator,\n isDragging,\n } = state;\n const {\n columnHeaderHeight,\n floatingColumns,\n gridX,\n width,\n visibleColumns,\n visibleColumnWidths,\n visibleColumnXs,\n floatingLeftColumnCount,\n } = metrics;\n if (columnHeaderHeight <= 0) {\n return;\n }\n\n const {\n headerBackgroundColor,\n headerColor,\n headerHiddenSeparatorSize,\n headerHiddenSeparatorHoverColor,\n headerSeparatorColor,\n headerSeparatorHoverColor,\n } = theme;\n const hiddenSeparatorHeight = columnHeaderHeight * 0.5;\n const hiddenY = columnHeaderHeight * 0.5 - hiddenSeparatorHeight * 0.5;\n const containsFrozenColumns = floatingLeftColumnCount > 0;\n let floatingLeftColumnsWidth = 0;\n\n context.save();\n\n context.beginPath();\n\n // Fill in the background\n context.fillStyle = headerBackgroundColor;\n context.fillRect(0, 0, width, columnHeaderHeight);\n\n context.fillStyle = headerColor;\n\n // Visible columns.\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n const x = getOrThrow(visibleColumnXs, column) + gridX;\n this.drawColumnHeader(context, state, column, x, columnWidth);\n }\n\n if (containsFrozenColumns) {\n floatingLeftColumnsWidth =\n getOrThrow(visibleColumnXs, floatingLeftColumnCount - 1) +\n getOrThrow(visibleColumnWidths, floatingLeftColumnCount - 1);\n\n // Frozen columns' background\n context.fillStyle = headerBackgroundColor;\n context.fillRect(gridX, 0, floatingLeftColumnsWidth, columnHeaderHeight);\n\n // Frozen columns.\n context.fillStyle = headerColor;\n for (let i = 0; i < floatingColumns.length; i += 1) {\n const column = floatingColumns[i];\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n const x = getOrThrow(visibleColumnXs, column) + gridX;\n this.drawColumnHeader(context, state, column, x, columnWidth);\n }\n }\n\n // Draw the separators, visible columns then floating columns.\n if (headerSeparatorColor) {\n context.strokeStyle = headerSeparatorColor;\n context.beginPath();\n const hiddenColumns = [];\n\n // Draw visible column separators.\n let isPreviousColumnHidden = false;\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const columnX = getOrThrow(visibleColumnXs, column);\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n\n if (!(columnX < floatingLeftColumnsWidth - columnWidth)) {\n if (columnWidth > 0) {\n const x = gridX + columnX + columnWidth + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, columnHeaderHeight - 0.5);\n isPreviousColumnHidden = false;\n } else if (!isPreviousColumnHidden) {\n isPreviousColumnHidden = true;\n hiddenColumns.push(column);\n }\n }\n }\n\n // Draw floating column separators.\n isPreviousColumnHidden = false;\n for (let i = 0; i < floatingColumns.length; i += 1) {\n const column = floatingColumns[i];\n const columnX = getOrThrow(visibleColumnXs, column);\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n if (columnWidth > 0) {\n const x = gridX + columnX + columnWidth + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, columnHeaderHeight - 0.5);\n isPreviousColumnHidden = false;\n } else if (!isPreviousColumnHidden) {\n isPreviousColumnHidden = true;\n hiddenColumns.push(column);\n }\n }\n\n // Bottom Border, should be interior to the header height\n context.moveTo(0, columnHeaderHeight - 0.5);\n context.lineTo(width, columnHeaderHeight - 0.5);\n context.stroke();\n\n // Now draw the hidden column separator boxes\n context.beginPath();\n context.fillStyle = headerSeparatorColor;\n for (let i = 0; i < hiddenColumns.length; i += 1) {\n const column = hiddenColumns[i];\n const columnX = getOrThrow(visibleColumnXs, column);\n const columnWidth = getOrThrow(visibleColumnWidths, column);\n const minX =\n gridX + columnX + columnWidth + 0.5 - headerHiddenSeparatorSize * 0.5;\n context.rect(\n minX,\n hiddenY,\n headerHiddenSeparatorSize,\n hiddenSeparatorHeight\n );\n }\n context.fill();\n }\n\n if (headerSeparatorHoverColor) {\n let highlightedSeparator = draggingColumnSeparator;\n\n if (highlightedSeparator == null && mouseX != null && mouseY != null) {\n highlightedSeparator = GridUtils.getColumnSeparatorIndex(\n mouseX,\n mouseY,\n metrics,\n theme\n );\n }\n\n if (\n highlightedSeparator != null &&\n (!isDragging || draggingColumnSeparator != null)\n ) {\n context.strokeStyle = headerSeparatorHoverColor;\n\n const columnX = getOrThrow(visibleColumnXs, highlightedSeparator);\n const columnWidth = getOrThrow(\n visibleColumnWidths,\n highlightedSeparator\n );\n const x = gridX + columnX + columnWidth + 0.5;\n const visibleColumnIndex = visibleColumns.indexOf(highlightedSeparator);\n const nextColumn =\n visibleColumnIndex < visibleColumns.length - 1\n ? visibleColumns[visibleColumnIndex + 1]\n : null;\n const nextColumnWidth =\n nextColumn != null ? visibleColumnWidths.get(nextColumn) : null;\n const isColumnHidden = columnWidth === 0;\n const isNextColumnHidden =\n nextColumnWidth != null && nextColumnWidth === 0;\n if (isColumnHidden) {\n context.strokeStyle = headerHiddenSeparatorHoverColor;\n context.fillStyle = headerHiddenSeparatorHoverColor;\n context.fillRect(\n x,\n hiddenY,\n headerHiddenSeparatorSize * 0.5,\n hiddenSeparatorHeight\n );\n } else if (isNextColumnHidden) {\n context.fillStyle = headerSeparatorHoverColor;\n context.fillRect(\n x - headerHiddenSeparatorSize * 0.5,\n hiddenY,\n headerHiddenSeparatorSize * 0.5,\n hiddenSeparatorHeight\n );\n }\n\n // column seperator hover line\n context.beginPath();\n context.moveTo(x, 0);\n context.lineTo(x, columnHeaderHeight - 1);\n context.stroke();\n }\n }\n\n context.restore();\n }\n\n drawColumnHeader(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n column: VisibleIndex,\n columnX: Coordinate,\n columnWidth: number\n ): void {\n if (columnWidth <= 0) {\n return;\n }\n const { metrics, model, theme } = state;\n const { modelColumns } = metrics;\n const modelColumn = getOrThrow(modelColumns, column);\n let text = model.textForColumnHeader(modelColumn);\n\n const { headerHorizontalPadding } = theme;\n const { columnHeaderHeight, fontWidths } = metrics;\n const fontWidth =\n fontWidths.get(context.font) || GridRenderer.DEFAULT_FONT_WIDTH;\n\n const maxLength = (columnWidth - headerHorizontalPadding * 2) / fontWidth;\n if (maxLength <= 0) {\n return;\n }\n\n context.save();\n\n context.beginPath();\n context.rect(columnX, 0, columnWidth, columnHeaderHeight);\n context.clip();\n\n if (text.length > maxLength) {\n text = `${text.substring(0, maxLength - 1)}…`;\n\n const x = columnX + headerHorizontalPadding;\n const y = columnHeaderHeight * 0.5;\n\n context.textAlign = 'left';\n context.fillText(text, x, y);\n } else {\n const x = columnX + columnWidth * 0.5;\n const y = columnHeaderHeight * 0.5;\n\n context.textAlign = 'center';\n context.fillText(text, x, y);\n }\n\n context.restore();\n }\n\n drawRowHeaders(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { mouseX, mouseY, metrics, theme, draggingRowSeparator } = state;\n const {\n gridY,\n rowHeaderWidth,\n height,\n visibleRows,\n visibleRowHeights,\n visibleRowYs,\n } = metrics;\n if (rowHeaderWidth <= 0) {\n return;\n }\n\n const {\n headerBackgroundColor,\n headerColor,\n headerHiddenSeparatorSize,\n headerHiddenSeparatorHoverColor,\n headerSeparatorColor,\n headerSeparatorHoverColor,\n } = theme;\n const hiddenSeparatorWidth = rowHeaderWidth * 0.5;\n const hiddenX = rowHeaderWidth * 0.5 - hiddenSeparatorWidth * 0.5;\n\n context.save();\n\n context.beginPath();\n\n // Fill in the background\n context.fillStyle = headerBackgroundColor;\n context.fillRect(0, 0, rowHeaderWidth, height);\n\n // Draw the separators\n if (headerSeparatorColor) {\n context.strokeStyle = headerSeparatorColor;\n context.beginPath();\n context.moveTo(0, gridY + 0.5);\n context.lineTo(rowHeaderWidth, gridY + 0.5);\n\n const hiddenRows = [];\n let isPreviousRowHidden = false;\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n if (rowHeight > 0) {\n const y = gridY + rowY + rowHeight + 0.5;\n\n context.moveTo(0, y);\n context.lineTo(rowHeaderWidth, y);\n\n isPreviousRowHidden = false;\n } else if (!isPreviousRowHidden) {\n isPreviousRowHidden = true;\n hiddenRows.push(row);\n }\n }\n\n // border right, interior to the headerWidth\n context.moveTo(rowHeaderWidth - 0.5, 0);\n context.lineTo(rowHeaderWidth - 0.5, height);\n\n context.stroke();\n\n // Draw the hidden column separators\n context.beginPath();\n context.fillStyle = headerSeparatorColor;\n for (let i = 0; i < hiddenRows.length; i += 1) {\n const row = hiddenRows[i];\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n const minY =\n gridY + rowY + rowHeight + 0.5 - headerHiddenSeparatorSize * 0.5;\n context.rect(\n hiddenX,\n minY,\n hiddenSeparatorWidth,\n headerHiddenSeparatorSize\n );\n }\n\n context.fill();\n }\n\n if (headerSeparatorHoverColor) {\n let highlightedSeparator = draggingRowSeparator;\n if (highlightedSeparator == null && mouseX != null && mouseY != null) {\n highlightedSeparator = GridUtils.getRowSeparatorIndex(\n mouseX,\n mouseY,\n metrics,\n theme\n );\n }\n\n if (highlightedSeparator != null) {\n context.strokeStyle = headerSeparatorHoverColor;\n\n const rowY = getOrThrow(visibleRowYs, highlightedSeparator);\n const rowHeight = getOrThrow(visibleRowHeights, highlightedSeparator);\n const y = gridY + rowY + rowHeight + 0.5;\n\n const visibleRowIndex = visibleRows.indexOf(highlightedSeparator);\n const nextRow =\n visibleRowIndex < visibleRows.length - 1\n ? visibleRows[visibleRowIndex + 1]\n : null;\n const nextRowHeight =\n nextRow != null ? visibleRowHeights.get(nextRow) : null;\n const isRowHidden = rowHeight === 0;\n const isNextRowHidden = nextRowHeight != null && nextRowHeight === 0;\n if (isRowHidden) {\n context.strokeStyle = headerHiddenSeparatorHoverColor;\n context.fillStyle = headerHiddenSeparatorHoverColor;\n context.fillRect(\n hiddenX,\n y,\n hiddenSeparatorWidth,\n headerHiddenSeparatorSize * 0.5\n );\n } else if (isNextRowHidden) {\n context.fillStyle = headerSeparatorHoverColor;\n context.fillRect(\n hiddenX,\n y - headerHiddenSeparatorSize * 0.5,\n hiddenSeparatorWidth,\n headerHiddenSeparatorSize * 0.5\n );\n }\n\n context.beginPath();\n context.moveTo(0.5, y);\n context.lineTo(rowHeaderWidth + 0.5, y);\n context.stroke();\n }\n }\n\n // Fill in the text\n context.beginPath();\n context.rect(0, gridY, rowHeaderWidth, height);\n context.clip();\n\n context.fillStyle = headerColor;\n context.textAlign = 'right';\n\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n const rowHeight = getOrThrow(visibleRowHeights, row);\n const y = getOrThrow(visibleRowYs, row) + gridY;\n this.drawRowHeader(context, state, row, y, rowHeight);\n }\n\n context.restore();\n }\n\n drawRowHeader(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n row: VisibleIndex,\n rowY: Coordinate,\n rowHeight: number\n ): void {\n if (rowHeight <= 0) {\n return;\n }\n const { metrics, model, theme } = state;\n const { modelRows, rowHeaderWidth } = metrics;\n const modelRow = getOrThrow(modelRows, row);\n const x = rowHeaderWidth - theme.cellHorizontalPadding;\n const y = rowY + rowHeight * 0.5;\n context.fillText(model.textForRowHeader(modelRow), x, y);\n }\n\n drawRowFooters(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const {\n mouseX,\n mouseY,\n metrics,\n model,\n theme,\n draggingRowSeparator,\n } = state;\n const {\n gridY,\n gridX,\n maxX,\n modelRows,\n rowFooterWidth,\n height,\n verticalBarWidth,\n visibleRows,\n visibleRowHeights,\n visibleRowYs,\n width,\n } = metrics;\n if (rowFooterWidth <= 0) {\n return;\n }\n\n const {\n cellHorizontalPadding,\n headerBackgroundColor,\n headerColor,\n headerHiddenSeparatorSize,\n headerHiddenSeparatorHoverColor,\n headerSeparatorColor,\n headerSeparatorHoverColor,\n } = theme;\n const hiddenSeparatorWidth = rowFooterWidth * 0.5;\n const hiddenX = rowFooterWidth * 0.5 - hiddenSeparatorWidth * 0.5;\n const x = Math.min(gridX + maxX, width - rowFooterWidth - verticalBarWidth);\n\n context.save();\n\n context.beginPath();\n\n // Fill in the background\n context.fillStyle = headerBackgroundColor;\n context.fillRect(x, gridY, rowFooterWidth, height);\n\n // Draw the separators\n if (headerSeparatorColor) {\n context.strokeStyle = headerSeparatorColor;\n context.beginPath();\n context.moveTo(x, gridY + 0.5);\n context.lineTo(rowFooterWidth, gridY + 0.5);\n\n const hiddenRows = [];\n let isPreviousRowHidden = false;\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n if (rowHeight > 0) {\n const y = gridY + rowY + rowHeight + 0.5;\n\n context.moveTo(x + 0.5, y);\n context.lineTo(x + rowFooterWidth - 0.5, y);\n\n isPreviousRowHidden = false;\n } else if (!isPreviousRowHidden) {\n isPreviousRowHidden = true;\n hiddenRows.push(row);\n }\n }\n\n // border left, interior to the headerWidth\n context.moveTo(x + 0.5, gridY);\n context.lineTo(x + 0.5, height);\n\n context.stroke();\n\n // Draw the hidden column separators\n context.beginPath();\n context.fillStyle = headerSeparatorColor;\n for (let i = 0; i < hiddenRows.length; i += 1) {\n const row = hiddenRows[i];\n const rowY = getOrThrow(visibleRowYs, row);\n const rowHeight = getOrThrow(visibleRowHeights, row);\n const minY =\n gridY + rowY + rowHeight + 0.5 - headerHiddenSeparatorSize * 0.5;\n context.rect(\n x + hiddenX,\n minY,\n hiddenSeparatorWidth,\n headerHiddenSeparatorSize\n );\n }\n\n context.fill();\n }\n\n if (headerSeparatorHoverColor) {\n let highlightedSeparator = draggingRowSeparator;\n if (highlightedSeparator == null && mouseX != null && mouseY != null) {\n highlightedSeparator = GridUtils.getRowSeparatorIndex(\n mouseX,\n mouseY,\n metrics,\n theme\n );\n }\n\n if (highlightedSeparator != null) {\n context.strokeStyle = headerSeparatorHoverColor;\n\n const rowY = getOrThrow(visibleRowYs, highlightedSeparator);\n const rowHeight = getOrThrow(visibleRowHeights, highlightedSeparator);\n const y = gridY + rowY + rowHeight + 0.5;\n\n const visibleRowIndex = visibleRows.indexOf(highlightedSeparator);\n const nextRow =\n visibleRowIndex < visibleRows.length - 1\n ? visibleRows[visibleRowIndex + 1]\n : null;\n const nextRowHeight =\n nextRow != null ? visibleRowHeights.get(nextRow) : null;\n const isRowHidden = rowHeight === 0;\n const isNextRowHidden = nextRowHeight != null && nextRowHeight === 0;\n if (isRowHidden) {\n context.strokeStyle = headerHiddenSeparatorHoverColor;\n context.fillStyle = headerHiddenSeparatorHoverColor;\n context.fillRect(\n hiddenX,\n y,\n hiddenSeparatorWidth,\n headerHiddenSeparatorSize * 0.5\n );\n } else if (isNextRowHidden) {\n context.fillStyle = headerSeparatorHoverColor;\n context.fillRect(\n hiddenX,\n y - headerHiddenSeparatorSize * 0.5,\n hiddenSeparatorWidth,\n headerHiddenSeparatorSize * 0.5\n );\n }\n\n context.beginPath();\n context.moveTo(x + 0.5, y);\n context.lineTo(x + rowFooterWidth + 0.5, y);\n context.stroke();\n }\n }\n\n // Fill in the text\n context.beginPath();\n context.rect(x, gridY, rowFooterWidth, height);\n context.clip();\n\n context.fillStyle = headerColor;\n context.textAlign = 'left';\n\n const textX = x + cellHorizontalPadding;\n for (let i = 0; i < visibleRows.length; i += 1) {\n const row = visibleRows[i];\n const rowHeight = getOrThrow(visibleRowHeights, row);\n if (rowHeight > 0) {\n const rowY = getOrThrow(visibleRowYs, row) + gridY;\n const modelRow = getOrThrow(modelRows, row);\n const textY = rowY + rowHeight * 0.5;\n context.fillText(model.textForRowFooter(modelRow), textX, textY);\n }\n }\n\n context.restore();\n }\n\n drawSelectedRanges(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n viewport: {\n left?: VisibleIndex;\n top?: VisibleIndex;\n right?: VisibleIndex;\n bottom?: VisibleIndex;\n minX?: Coordinate;\n minY?: Coordinate;\n maxX?: Coordinate;\n maxY?: Coordinate;\n } = {}\n ): void {\n const {\n cursorColumn: column,\n cursorRow: row,\n draggingRow,\n draggingColumn,\n editingCell,\n metrics,\n model,\n selectedRanges,\n theme,\n } = state;\n const {\n visibleColumnWidths,\n visibleColumnXs,\n visibleRowHeights,\n visibleRowYs,\n width,\n height,\n } = metrics;\n const {\n left = metrics.left,\n top = metrics.top,\n right = metrics.right,\n bottom = metrics.bottom,\n minY = -10,\n maxY = height + 10,\n minX = -10,\n maxX = width + 10,\n } = viewport;\n if (selectedRanges.length === 0) {\n return;\n }\n\n const isCursorVisible =\n isEditableGridModel(model) &&\n model.isEditable &&\n editingCell == null &&\n draggingRow == null &&\n draggingColumn == null &&\n column != null &&\n row != null &&\n visibleColumnXs.has(column) &&\n visibleRowYs.has(row);\n if (isCursorVisible) {\n // Punch a hole out where the active cell is, it gets styled differently.\n const x = getOrThrow(visibleColumnXs, column);\n const y = getOrThrow(visibleRowYs, row);\n const w = getOrThrow(visibleColumnWidths, column);\n const h = getOrThrow(visibleRowHeights, row);\n\n context.save();\n\n context.beginPath();\n\n context.rect(0, 0, width, height);\n context.rect(x, y, w, h);\n\n context.clip('evenodd');\n }\n\n // Draw selection ranges\n context.beginPath();\n for (let i = 0; i < selectedRanges.length; i += 1) {\n const selectedRange = selectedRanges[i];\n const startColumn =\n selectedRange.startColumn !== null ? selectedRange.startColumn : left;\n const startRow =\n selectedRange.startRow !== null ? selectedRange.startRow : top;\n const endColumn =\n selectedRange.endColumn !== null ? selectedRange.endColumn : right;\n const endRow =\n selectedRange.endRow !== null ? selectedRange.endRow : bottom;\n if (\n endRow >= top &&\n bottom >= startRow &&\n endColumn >= left &&\n right >= startColumn\n ) {\n // Need to offset the x/y coordinates so that the line draws nice and crisp\n const x =\n startColumn >= left && visibleColumnXs.has(startColumn)\n ? Math.round(getOrThrow(visibleColumnXs, startColumn)) + 0.5\n : minX;\n const y =\n startRow >= top && visibleRowYs.has(startRow)\n ? Math.max(\n Math.round(getOrThrow(visibleRowYs, startRow)) + 0.5,\n 0.5\n )\n : minY;\n\n const endX =\n endColumn <= right && visibleColumnXs.has(endColumn)\n ? Math.round(\n getOrThrow(visibleColumnXs, endColumn) +\n getOrThrow(visibleColumnWidths, endColumn)\n ) - 0.5\n : maxX;\n const endY =\n endRow <= bottom && visibleRowYs.has(endRow)\n ? Math.round(\n getOrThrow(visibleRowYs, endRow) +\n getOrThrow(visibleRowHeights, endRow)\n ) - 0.5\n : maxY;\n\n context.rect(x, y, endX - x, endY - y);\n }\n\n // draw the inner transparent fill\n context.fillStyle = theme.selectionColor;\n context.fill();\n\n /**\n * draw an \"inner stroke\" that's clipped to just inside of the rects\n * to act as a casing to the outer stroke. 3px width because 1px is outside\n * the rect (but clipped), 1px is \"on\" the rect (technically this pixel is\n * a half pixel clip as well due to rects offset, but we are immediately painting\n * over it), and then the 1px inside (which is the desired pixel).\n */\n context.save();\n context.clip();\n context.strokeStyle = theme.selectionOutlineCasingColor;\n context.lineWidth = 3;\n context.stroke();\n context.restore();\n\n // draw the outerstroke border on top of the inner stroke\n context.strokeStyle = theme.selectionOutlineColor;\n context.lineWidth = 1;\n context.stroke();\n }\n\n if (isCursorVisible && column != null && row != null) {\n context.restore();\n\n this.drawActiveCell(context, state, column, row);\n }\n }\n\n drawActiveCell(\n context: CanvasRenderingContext2D,\n state: GridRenderState,\n column: VisibleIndex,\n row: VisibleIndex,\n borderWidth = GridRenderer.ACTIVE_CELL_BORDER_WIDTH\n ): void {\n const { metrics, theme } = state;\n const {\n visibleColumnWidths,\n visibleColumnXs,\n visibleRowHeights,\n visibleRowYs,\n } = metrics;\n const cellX = getOrThrow(visibleColumnXs, column);\n const cellY = getOrThrow(visibleRowYs, row);\n const cellW = getOrThrow(visibleColumnWidths, column);\n const cellH = getOrThrow(visibleRowHeights, row);\n\n // Now get the outline for the active cell\n let x = cellX - borderWidth * 0.5;\n let y = cellY - borderWidth * 0.5;\n let w = cellW + borderWidth;\n let h = cellH + borderWidth;\n\n // Make sure the outline is interior on the edge\n if (x <= 0) {\n w += x - 1;\n x = 1;\n }\n if (y <= 0) {\n h += y - 1;\n y = 1;\n }\n\n const { lineWidth } = context;\n context.beginPath();\n context.lineWidth = borderWidth;\n context.strokeStyle = theme.selectionOutlineColor;\n this.drawRoundedRect(context, x, y, w, h);\n context.stroke();\n context.lineWidth = lineWidth;\n }\n\n /**\n * Draws a rounded rectangle using the current state of the canvas.\n *\n * @param context The canvas context\n * @param x coordinate of the left side\n * @param y coordinate of the top side\n * @param w width of the rectangle\n * @param h height of the rectangle\n * @param r corner radius of the rectangle\n */\n drawRoundedRect(\n context: CanvasRenderingContext2D,\n x: Coordinate,\n y: Coordinate,\n w: number,\n h: number,\n r = GridRenderer.DEFAULT_EDGE_RADIUS\n ): void {\n context.beginPath();\n context.moveTo(x + r, y);\n context.lineTo(x + w - r, y);\n context.quadraticCurveTo(x + w, y, x + w, y + r);\n context.lineTo(x + w, y + h - r);\n context.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n context.lineTo(x + r, y + h);\n context.quadraticCurveTo(x, y + h, x, y + h - r);\n context.lineTo(x, y + r);\n context.quadraticCurveTo(x, y, x + r, y);\n context.closePath();\n }\n\n drawDraggingColumn(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const {\n draggingColumn,\n draggingColumnOffset,\n metrics,\n mouseX,\n theme,\n } = state;\n if (draggingColumn == null || mouseX == null) {\n return;\n }\n\n const {\n gridX,\n gridY,\n visibleColumnXs,\n visibleColumnWidths,\n height,\n } = metrics;\n const x = getOrThrow(visibleColumnXs, draggingColumn);\n const columnWidth = getOrThrow(visibleColumnWidths, draggingColumn) + 1;\n const {\n backgroundColor,\n font,\n headerFont,\n reorderOffset,\n shadowBlur,\n shadowColor,\n } = theme;\n\n context.save();\n\n context.translate(gridX, 0);\n\n // First, we need to draw over the row stripes where the column is coming from\n context.fillStyle = backgroundColor;\n context.fillRect(x, 0, columnWidth, height);\n\n context.translate(\n mouseX - x - gridX - (draggingColumnOffset ?? 0),\n gridY + reorderOffset\n );\n\n // Then draw the shadow of the moving column\n context.save();\n\n context.shadowColor = shadowColor;\n context.shadowBlur = shadowBlur;\n\n context.fillStyle = backgroundColor;\n context.fillRect(x, -gridY, columnWidth, height);\n\n context.restore();\n\n // Now set the clipping region and pretty much just redraw this column and all it's contents\n context.beginPath();\n context.rect(x, -gridY, columnWidth, height);\n context.clip();\n\n context.font = font;\n\n this.drawGridBackground(context, state);\n\n this.drawColumnCellContents(context, state, draggingColumn);\n\n // Now translate it back up and draw the header\n context.translate(-gridX, -gridY);\n\n context.font = headerFont;\n\n this.drawColumnHeaders(context, state);\n\n context.restore();\n }\n\n drawDraggingRow(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const { draggingRow, draggingRowOffset, metrics, mouseY, theme } = state;\n if (draggingRow == null || mouseY == null) {\n return;\n }\n\n const { gridX, gridY, visibleRowYs, visibleRowHeights, width } = metrics;\n const y = getOrThrow(visibleRowYs, draggingRow);\n const rowHeight = getOrThrow(visibleRowHeights, draggingRow) + 1;\n const {\n backgroundColor,\n font,\n headerFont,\n reorderOffset,\n shadowBlur,\n shadowColor,\n } = theme;\n\n context.save();\n\n context.translate(0, gridY);\n\n // First, we need to draw over the row stripes where the row is coming from\n context.fillStyle = backgroundColor;\n context.fillRect(0, y, width, rowHeight);\n\n context.translate(\n gridX + reorderOffset,\n mouseY - y - gridY - (draggingRowOffset ?? 0)\n );\n\n // Then draw the shadow of the moving row\n context.save();\n\n context.shadowColor = shadowColor;\n context.shadowBlur = shadowBlur;\n\n context.fillStyle = backgroundColor;\n context.fillRect(-gridX, y, width, rowHeight);\n\n context.restore();\n\n // Now set the clipping region and pretty much just redraw this row and all it's contents\n context.beginPath();\n context.rect(-gridX, y, width, rowHeight);\n context.clip();\n\n context.font = font;\n\n this.drawGridBackground(context, state);\n\n this.drawCellContents(context, state);\n\n // Now translate it back up and draw the header\n context.translate(-gridX, -gridY);\n\n context.font = headerFont;\n\n this.drawRowHeaders(context, state);\n\n context.restore();\n }\n\n drawScrollBars(\n context: CanvasRenderingContext2D,\n state: GridRenderState\n ): void {\n const {\n isDraggingHorizontalScrollBar,\n isDraggingVerticalScrollBar,\n isDragging,\n metrics,\n mouseX,\n mouseY,\n theme,\n } = state;\n if (theme.scrollBarSize <= 0) {\n return;\n }\n\n const {\n rowHeaderWidth,\n columnHeaderHeight,\n width,\n height,\n handleHeight,\n handleWidth,\n scrollX,\n scrollY,\n hasHorizontalBar,\n hasVerticalBar,\n barWidth,\n barHeight,\n } = metrics;\n const {\n scrollBarBackgroundColor,\n scrollBarHoverBackgroundColor,\n scrollBarCasingColor,\n scrollBarCornerColor,\n scrollBarColor,\n scrollBarHoverColor,\n scrollBarActiveColor,\n scrollBarSize,\n scrollBarHoverSize,\n scrollBarCasingWidth,\n } = theme;\n\n const isInbounds =\n mouseX != null && mouseY != null && mouseX <= width && mouseY <= height;\n\n const isVerticalBarHover =\n isDraggingVerticalScrollBar ||\n (hasVerticalBar &&\n !isDraggingHorizontalScrollBar &&\n !isDragging &&\n mouseX != null &&\n mouseY != null &&\n mouseX >= width - scrollBarHoverSize &&\n mouseY <= barHeight + columnHeaderHeight &&\n isInbounds);\n\n const isHorizontalBarHover =\n isDraggingHorizontalScrollBar ||\n (hasHorizontalBar &&\n !isDraggingVerticalScrollBar &&\n !isDragging &&\n !isVerticalBarHover && // vert bar gets priorty in overlapped corner hover area\n mouseX != null &&\n mouseY != null &&\n mouseY >= height - scrollBarHoverSize &&\n mouseX <= barWidth - rowHeaderWidth &&\n isInbounds);\n\n const hScrollBarSize = isHorizontalBarHover\n ? scrollBarHoverSize\n : scrollBarSize;\n const vScrollBarSize = isVerticalBarHover\n ? scrollBarHoverSize\n : scrollBarSize;\n\n context.translate(rowHeaderWidth, columnHeaderHeight);\n\n if (hasHorizontalBar && hasVerticalBar) {\n // That little corner in the bottom right\n context.fillStyle = scrollBarCasingColor;\n context.fillRect(\n width - rowHeaderWidth - scrollBarSize,\n height - columnHeaderHeight - scrollBarSize,\n scrollBarSize,\n scrollBarSize\n );\n context.fillStyle = scrollBarCornerColor;\n context.fillRect(\n width - rowHeaderWidth - scrollBarSize + scrollBarCasingWidth,\n height - columnHeaderHeight - scrollBarSize + scrollBarCasingWidth,\n scrollBarSize - scrollBarCasingWidth,\n scrollBarSize - scrollBarCasingWidth\n );\n }\n\n if (hasHorizontalBar) {\n const x = scrollX;\n const y = height - columnHeaderHeight - hScrollBarSize;\n\n // scrollbar casing\n context.fillStyle = scrollBarCasingColor;\n context.fillRect(0, y, barWidth, hScrollBarSize - scrollBarCasingWidth);\n\n // scrollbar track\n context.fillStyle = isHorizontalBarHover\n ? scrollBarHoverBackgroundColor\n : scrollBarBackgroundColor;\n context.fillRect(\n 0,\n y + scrollBarCasingWidth,\n barWidth,\n hScrollBarSize - scrollBarCasingWidth\n );\n\n // scrollbar thumb\n if (isDraggingHorizontalScrollBar) {\n context.fillStyle = scrollBarActiveColor;\n } else if (isHorizontalBarHover) {\n context.fillStyle = scrollBarHoverColor;\n } else {\n context.fillStyle = scrollBarColor;\n }\n\n context.fillRect(\n x,\n y + scrollBarCasingWidth,\n handleWidth,\n hScrollBarSize - scrollBarCasingWidth\n );\n }\n\n if (hasVerticalBar) {\n const x = width - rowHeaderWidth - vScrollBarSize;\n const y = scrollY;\n\n // scrollbar casing\n context.fillStyle = scrollBarCasingColor;\n context.fillRect(x, 0, vScrollBarSize - scrollBarCasingWidth, barHeight);\n\n // scrollbar track\n context.fillStyle = isVerticalBarHover\n ? scrollBarHoverBackgroundColor\n : scrollBarBackgroundColor;\n context.fillRect(\n x + scrollBarCasingWidth,\n 0,\n vScrollBarSize - scrollBarCasingWidth,\n barHeight\n );\n\n // scrollbar thumb\n if (isDraggingVerticalScrollBar) {\n context.fillStyle = scrollBarActiveColor;\n } else if (isVerticalBarHover) {\n context.fillStyle = scrollBarHoverColor;\n } else {\n context.fillStyle = scrollBarColor;\n }\n\n context.fillRect(\n x + scrollBarCasingWidth,\n y,\n vScrollBarSize - scrollBarCasingWidth,\n handleHeight\n );\n }\n\n context.translate(-rowHeaderWidth, -columnHeaderHeight);\n }\n}\n\nexport default GridRenderer;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport { EventHandlerResult } from './EventHandlerResult';\nimport Grid from './Grid';\nimport { GridPoint } from './GridUtils';\n\n/**\n * Some events we listen to are a native mouse event, and others are wrapped with React's SyntheticEvent.\n * The GridMouseHandler shouldn't care though - the properties it accesses should be common on both types of events.\n */\nexport type GridMouseEvent = MouseEvent | React.MouseEvent;\n\nexport type GridMouseHandlerFunctionName =\n | 'onDown'\n | 'onMove'\n | 'onDrag'\n | 'onLeave'\n | 'onClick'\n | 'onContextMenu'\n | 'onDoubleClick'\n | 'onUp'\n | 'onWheel';\n\n/**\n * Define a region in the grid that interacts with the mouse on a grid.\n * Return true from any of the events to indicate they're consumed, and stopPropagation/preventDefault will be called.\n */\nexport class GridMouseHandler {\n order: number;\n\n // What order this mouse handler should trigger in\n // Default to well below any of the GRID mouse handlers 100-1000+\n constructor(order = 5000) {\n this.order = order;\n }\n\n // Cursor to use if this returns true from any function\n cursor: string | null = null;\n\n onDown(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onMove(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onDrag(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onLeave(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onClick(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onContextMenu(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onDoubleClick(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onUp(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n\n onWheel(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n return false;\n }\n}\n\nexport default GridMouseHandler;\n","import { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport { BoxCoordinates } from '../GridMetrics';\nimport GridMouseHandler, { GridMouseEvent } from '../GridMouseHandler';\nimport GridUtils, { GridPoint } from '../GridUtils';\n\nconst DEFAULT_INTERVAL_MS = 100;\n\nclass GridSelectionMouseHandler extends GridMouseHandler {\n private startPoint?: GridPoint;\n\n private hasExtendedFloating = false;\n\n // Timer used when holding a drag past the end of the grid\n private timer?: ReturnType<typeof setTimeout>;\n\n private lastTriggerTime?: number;\n\n private dragBounds?: BoxCoordinates;\n\n onDown(\n gridPoint: GridPoint,\n grid: Grid,\n event: GridMouseEvent\n ): EventHandlerResult {\n const { x, y, column, row } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { gridX, gridY, maxX, maxY } = metrics;\n const gridMouseX = x - gridX;\n const gridMouseY = y - gridY;\n if (\n gridMouseX < 0 ||\n gridMouseY < 0 ||\n (column == null && gridMouseX > maxX) ||\n (row == null && gridMouseY > maxY)\n ) {\n return false;\n }\n\n const isModifierKey = GridUtils.isModifierKeyDown(event);\n const isShiftKey = event.shiftKey;\n if (!isModifierKey) {\n if (isShiftKey) {\n grid.trimSelectedRanges();\n } else {\n grid.clearSelectedRanges();\n }\n }\n\n const theme = grid.getTheme();\n const { autoSelectRow, autoSelectColumn } = theme;\n // If they click a column/row header, don't want to select the whole table if auto select column/row is on\n if (\n (column !== null || !autoSelectColumn) &&\n (row !== null || !autoSelectRow)\n ) {\n grid.focus();\n grid.moveCursorToPosition(\n column,\n row,\n isShiftKey,\n true,\n isShiftKey && isModifierKey\n );\n }\n\n this.startPoint = gridPoint;\n this.hasExtendedFloating = false;\n this.dragBounds = GridUtils.getScrollDragBounds(metrics, row, column);\n\n return true;\n }\n\n onDrag(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.startPoint === undefined) {\n return false;\n }\n\n this.stopTimer();\n\n const { row: startRow, column: startColumn } = this.startPoint;\n const { x, y } = gridPoint;\n let { row, column } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { left, lastLeft, top, lastTop, columnWidth, rowHeight } = metrics;\n const dragBounds = GridUtils.getScrollDragBounds(\n metrics,\n startRow,\n startColumn\n );\n\n // If we're dragging outside of the grid entirely, then we should start scrolling\n let deltaX = 0;\n let deltaY = 0;\n if (left < lastLeft) {\n if (x < dragBounds.x1) {\n deltaX = x - dragBounds.x1;\n } else if (x > dragBounds.x2) {\n deltaX = x - dragBounds.x2;\n }\n }\n if (top < lastTop) {\n if (y < dragBounds.y1) {\n deltaY = y - dragBounds.y1;\n } else if (y > dragBounds.y2) {\n deltaY = y - dragBounds.y2;\n }\n }\n\n if (deltaX !== 0 || deltaY !== 0) {\n // Have it go faster depending on how far out they've dragged\n this.startTimer(\n grid,\n gridPoint,\n deltaX > 0\n ? Math.ceil(deltaX / columnWidth)\n : Math.floor(deltaX / columnWidth),\n deltaY > 0\n ? Math.ceil(deltaY / rowHeight)\n : Math.floor(deltaY / rowHeight)\n );\n } else if (row != null && column != null) {\n const {\n floatingTopRowCount,\n floatingBottomRowCount,\n floatingLeftColumnCount,\n floatingRightColumnCount,\n columnCount,\n rowCount,\n bottom,\n right,\n topVisible,\n bottomVisible,\n leftVisible,\n rightVisible,\n } = metrics;\n // When selection crosses from a floating area to a non floating area, we need to scroll instead of jumping to the floating area\n // So when that happens, just adjust the point to be past the new boundary\n if (!this.hasExtendedFloating) {\n if (\n startRow !== null &&\n startRow < floatingTopRowCount &&\n row >= floatingTopRowCount\n ) {\n // Extending from floating top into the view\n row = floatingTopRowCount;\n this.hasExtendedFloating = true;\n } else if (\n startRow !== null &&\n startRow >= rowCount - floatingBottomRowCount &&\n row < rowCount - floatingBottomRowCount\n ) {\n // Extending from floating bottom into the view\n row = rowCount - floatingBottomRowCount - 1;\n this.hasExtendedFloating = true;\n }\n\n if (\n startColumn !== null &&\n startColumn < floatingLeftColumnCount &&\n column >= floatingLeftColumnCount\n ) {\n // Extending from floating left into the view\n column = floatingLeftColumnCount;\n this.hasExtendedFloating = true;\n } else if (\n startColumn !== null &&\n startColumn >= columnCount - floatingRightColumnCount &&\n column < columnCount - floatingRightColumnCount\n ) {\n // Extending from floating right into the view\n column = columnCount - floatingRightColumnCount - 1;\n this.hasExtendedFloating = true;\n }\n }\n\n // When a selection is dragging from within the main area to over a floating area, scroll.\n if (\n startRow !== null &&\n !GridUtils.isFloatingRow(startRow, metrics) &&\n GridUtils.isFloatingRow(row, metrics)\n ) {\n // Need to scroll\n if (startRow > row && row < top) {\n row = topVisible - 1;\n } else if (startRow < row && row > bottom) {\n row = bottomVisible + 1;\n }\n }\n if (\n startColumn !== null &&\n !GridUtils.isFloatingColumn(startColumn, metrics) &&\n GridUtils.isFloatingColumn(column, metrics)\n ) {\n if (startColumn > column && column < left) {\n column = leftVisible - 1;\n } else if (startColumn < column && column > right) {\n column = rightVisible + 1;\n }\n }\n grid.moveCursorToPosition(column, row, true, true);\n }\n return true;\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.startPoint !== undefined) {\n this.startPoint = undefined;\n this.dragBounds = undefined;\n this.stopTimer();\n grid.commitSelection();\n }\n\n return false;\n }\n\n moveSelection(\n grid: Grid,\n gridPoint: GridPoint,\n deltaX: number,\n deltaY: number\n ): void {\n const { row, column } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { selectionEndRow, selectionEndColumn } = grid.state;\n if (selectionEndRow == null || selectionEndColumn == null) {\n throw new Error('selection not set');\n }\n\n const { rowCount, columnCount } = metrics;\n const minX = deltaX < 0 && column != null ? column : 0;\n const maxX = deltaX > 0 && column != null ? column : columnCount - 1;\n const minY = deltaY < 0 && row != null ? row : 0;\n const maxY = deltaY > 0 && row != null ? row : rowCount - 1;\n grid.moveCursorToPosition(\n Math.min(Math.max(minX, selectionEndColumn + deltaX), maxX),\n Math.min(Math.max(minY, selectionEndRow + deltaY), maxY),\n true\n );\n this.lastTriggerTime = Date.now();\n }\n\n startTimer(\n grid: Grid,\n gridPoint: GridPoint,\n deltaX: number,\n deltaY: number\n ): void {\n this.stopTimer();\n\n const timeout =\n this.lastTriggerTime != null\n ? DEFAULT_INTERVAL_MS -\n Math.min(DEFAULT_INTERVAL_MS, Date.now() - this.lastTriggerTime)\n : 0;\n this.timer = setTimeout(() => {\n this.moveSelection(grid, gridPoint, deltaX, deltaY);\n this.startTimer(grid, gridPoint, deltaX, deltaY);\n }, timeout);\n }\n\n stopTimer(): void {\n if (this.timer !== undefined) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n}\n\nexport default GridSelectionMouseHandler;\n","import Grid from '../Grid';\nimport GridUtils, { GridPoint } from '../GridUtils';\nimport GridMouseHandler from '../GridMouseHandler';\nimport { getOrThrow } from '../GridMetricCalculator';\nimport { EventHandlerResult } from '../EventHandlerResult';\n\nconst SLOPPY_CLICK_DISTANCE = 5;\n\nclass GridColumnMoveMouseHandler extends GridMouseHandler {\n cursor: string | null = null;\n\n private draggingOffset?: number;\n\n private startingGridPoint?: GridPoint;\n\n private sloppyClickThreshold = false;\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const { model } = grid.props;\n const { x, y, column } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('Metrics not set');\n\n const { columnHeaderHeight, rowHeaderWidth, visibleColumnXs } = metrics;\n\n this.startingGridPoint = gridPoint;\n this.sloppyClickThreshold = false;\n this.cursor = null;\n\n if (\n column != null &&\n y <= columnHeaderHeight &&\n model.isColumnMovable(column)\n ) {\n const columnX = getOrThrow(visibleColumnXs, column);\n this.draggingOffset = x - columnX - rowHeaderWidth;\n grid.setState({ draggingColumnOffset: this.draggingOffset });\n }\n return false;\n }\n\n onDrag(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (\n this.draggingOffset === undefined ||\n this.startingGridPoint === undefined\n ) {\n return false;\n }\n\n const { model } = grid.props;\n let { draggingColumn } = grid.state;\n const { mouseX, mouseY, isDragging } = grid.state;\n if (mouseX == null || mouseY == null) {\n return false;\n }\n\n // before considering it a drag, the mouse must have moved a minimum distance\n // this prevents click actions from triggering a drag state\n if (\n (!this.sloppyClickThreshold &&\n Math.abs(this.startingGridPoint.x - mouseX) >= SLOPPY_CLICK_DISTANCE) ||\n Math.abs(this.startingGridPoint.y - mouseY) >= SLOPPY_CLICK_DISTANCE\n ) {\n this.sloppyClickThreshold = true;\n } else if (!this.sloppyClickThreshold && !isDragging) {\n return false;\n }\n\n if (draggingColumn == null) {\n const { column } = grid.getGridPointFromXY(mouseX, mouseY);\n if (column != null && !model.isColumnMovable(column)) {\n return false;\n }\n\n draggingColumn = column;\n\n grid.setState({ draggingColumn, isDragging: true });\n\n if (draggingColumn == null) {\n return false;\n }\n }\n\n this.cursor = 'move';\n const { metrics } = grid;\n if (!metrics) throw new Error('Metrics not set');\n\n const {\n left,\n lastLeft,\n right,\n rightVisible,\n columnCount,\n rowHeaderWidth,\n visibleColumnWidths,\n visibleColumnXs,\n width,\n } = metrics;\n let minX = rowHeaderWidth;\n if (left < draggingColumn) {\n const leftColumn = draggingColumn - 1;\n minX =\n getOrThrow(visibleColumnXs, leftColumn) +\n getOrThrow(visibleColumnWidths, leftColumn) * 0.5 +\n this.draggingOffset +\n rowHeaderWidth;\n }\n\n let maxX = width;\n if (draggingColumn < right) {\n const rightColumn = draggingColumn + 1;\n maxX =\n getOrThrow(visibleColumnXs, rightColumn) +\n getOrThrow(visibleColumnWidths, rightColumn) * 0.5 -\n getOrThrow(visibleColumnWidths, draggingColumn) +\n this.draggingOffset +\n rowHeaderWidth;\n }\n\n let { movedColumns } = grid.state;\n if (\n mouseX < minX &&\n draggingColumn > 0 &&\n model.isColumnMovable(draggingColumn - 1)\n ) {\n movedColumns = GridUtils.moveItem(\n draggingColumn,\n draggingColumn - 1,\n movedColumns\n );\n draggingColumn -= 1;\n } else if (\n maxX < mouseX &&\n draggingColumn < columnCount - 1 &&\n model.isColumnMovable(draggingColumn + 1)\n ) {\n movedColumns = GridUtils.moveItem(\n draggingColumn,\n draggingColumn + 1,\n movedColumns\n );\n draggingColumn += 1;\n }\n grid.setState({ movedColumns, draggingColumn });\n\n const minMoveX =\n rowHeaderWidth + getOrThrow(visibleColumnWidths, left) * 0.5;\n const maxMoveX =\n rowHeaderWidth +\n getOrThrow(visibleColumnXs, rightVisible) +\n getOrThrow(visibleColumnWidths, rightVisible) * 0.5;\n if (mouseX < minMoveX && left > 0) {\n grid.setState({ left: left - 1 });\n } else if (mouseX > maxMoveX && left < lastLeft) {\n grid.setState({ left: left + 1 });\n }\n\n return true;\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n this.cursor = null;\n\n if (this.draggingOffset != null) {\n this.draggingOffset = undefined;\n grid.setState({\n draggingColumnOffset: null,\n draggingColumn: null,\n isDragging: false,\n });\n return true;\n }\n\n return false;\n }\n}\n\nexport default GridColumnMoveMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport { Grid, GridMetricCalculator } from '..';\nimport { EventHandlerResult } from '../EventHandlerResult';\nimport { getOrThrow } from '../GridMetricCalculator';\nimport GridMetrics, { ModelIndex, VisibleIndex } from '../GridMetrics';\nimport GridMouseHandler from '../GridMouseHandler';\nimport { GridPoint } from '../GridUtils';\n\n// The different properties that can be used by implementing classes, whether for rows or columns\nexport type PointProperty = 'x' | 'y';\nexport type UserSizeProperty = 'userRowHeights' | 'userColumnWidths';\nexport type VisibleOffsetProperty = 'visibleRowYs' | 'visibleColumnXs';\nexport type VisibleSizeProperty = 'visibleRowHeights' | 'visibleColumnWidths';\nexport type MarginProperty = 'columnHeaderHeight' | 'rowHeaderWidth';\nexport type CalculatedSizeProperty =\n | 'calculatedRowHeights'\n | 'calculatedColumnWidths';\nexport type ModelIndexesProperty = 'modelRows' | 'modelColumns';\nexport type FirstIndexProperty = 'firstRow' | 'firstColumn';\nexport type TreePaddingProperty = 'treePaddingX' | 'treePaddingY';\n\n/**\n * Abstract class that should be extended for column/row behaviour\n * Override the necessary functions/properties\n */\nabstract class GridSeparatorMouseHandler extends GridMouseHandler {\n // The index where dragging the column separator started\n protected draggingIndex?: VisibleIndex;\n\n // The columns in the order they're being resized\n protected resizingItems: VisibleIndex[] = [];\n\n // Columns that were hidden under the separator when starting a drag\n protected hiddenItems: VisibleIndex[] = [];\n\n // The target width of the columns being resized\n protected targetSizes: Map<ModelIndex, number> = new Map();\n\n protected dragOffset = 0;\n\n // Override/Implement these properties/functions\n abstract hiddenCursor: string;\n\n abstract defaultCursor: string;\n\n abstract pointProperty: PointProperty;\n\n abstract userSizesProperty: UserSizeProperty;\n\n abstract visibleOffsetProperty: VisibleOffsetProperty;\n\n abstract visibleSizesProperty: VisibleSizeProperty;\n\n abstract marginProperty: MarginProperty;\n\n abstract calculatedSizesProperty: CalculatedSizeProperty;\n\n abstract modelIndexesProperty: ModelIndexesProperty;\n\n abstract firstIndexProperty: FirstIndexProperty;\n\n abstract treePaddingProperty: TreePaddingProperty;\n\n abstract getHiddenItems(\n itemIndex: VisibleIndex,\n metrics: GridMetrics\n ): VisibleIndex[];\n\n abstract getNextShownItem(\n itemIndex: VisibleIndex,\n metrics: GridMetrics\n ): VisibleIndex | null;\n\n abstract setSize(\n metricCalculator: GridMetricCalculator,\n modelIndex: ModelIndex,\n size: number\n ): void;\n\n abstract resetSize(\n metricCalculator: GridMetricCalculator,\n modelIndex: ModelIndex\n ): void;\n\n abstract updateSeparator(\n grid: Grid,\n separatorIndex: VisibleIndex | null\n ): void;\n\n abstract getSeparatorIndex(\n gridPoint: GridPoint,\n grid: Grid,\n checkAllowResize?: boolean\n ): VisibleIndex | null;\n // End of overrides\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const separatorIndex = this.getSeparatorIndex(gridPoint, grid);\n if (separatorIndex != null) {\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n this.dragOffset = 0;\n this.draggingIndex = separatorIndex;\n this.resizingItems = [separatorIndex];\n this.hiddenItems = this.getHiddenItems(separatorIndex, metrics).reverse();\n this.targetSizes.clear();\n\n this.addTargetSize(metrics, separatorIndex);\n\n this.updateCursor(metrics, separatorIndex);\n\n this.updateSeparator(grid, separatorIndex);\n\n return true;\n }\n return false;\n }\n\n onMove(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const separatorIndex = this.getSeparatorIndex(gridPoint, grid);\n if (separatorIndex != null) {\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n this.updateCursor(metrics, separatorIndex);\n return true;\n }\n return false;\n }\n\n onDrag(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.draggingIndex == null) {\n return false;\n }\n\n const point = gridPoint[this.pointProperty];\n const { metricCalculator, metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const theme = grid.getTheme();\n\n const visibleOffsets = metrics[this.visibleOffsetProperty];\n const margin = metrics[this.marginProperty];\n const calculatedSizes = metrics[this.calculatedSizesProperty];\n const modelIndexes = metrics[this.modelIndexesProperty];\n const firstIndex = metrics[this.firstIndexProperty];\n const treePadding = metrics[this.treePaddingProperty];\n\n // New sizes are batched and applied after the loop to avoid updating state while calculating next step\n const newSizes: Map<ModelIndex, number | null> = new Map();\n\n // Use a loop as we may need to resize multiple items if they drag quickly\n let resizeIndex: number | null = this.resizingItems[\n this.resizingItems.length - 1\n ];\n while (resizeIndex != null) {\n const itemOffset = getOrThrow(visibleOffsets, resizeIndex);\n const itemSize = point - margin - itemOffset - this.dragOffset;\n const modelIndex = getOrThrow(modelIndexes, resizeIndex);\n const targetSize = this.targetSizes.get(modelIndex);\n const isResizingMultiple = this.resizingItems.length > 1;\n const hiddenIndex = this.hiddenItems.indexOf(resizeIndex);\n let calculatedSize = getOrThrow(calculatedSizes, modelIndex);\n if (resizeIndex === firstIndex) {\n calculatedSize += treePadding;\n }\n let newSize: number | null = itemSize;\n if (\n Math.abs(itemSize - calculatedSize) <= theme.headerResizeSnapThreshold\n ) {\n // Snapping behaviour to \"natural\" width\n newSize = null;\n } else if (\n targetSize !== undefined &&\n itemSize > targetSize &&\n ((isResizingMultiple && hiddenIndex !== 0) || hiddenIndex > 0)\n ) {\n newSize = targetSize;\n } else if (itemSize <= theme.headerResizeHiddenSnapThreshold) {\n // Snapping to hidden item\n newSize = 0;\n }\n\n if (newSize !== calculatedSize) {\n newSizes.set(modelIndex, newSize);\n } else {\n newSizes.set(modelIndex, null);\n }\n\n if (itemSize < -theme.headerResizeSnapThreshold && newSize === 0) {\n if (hiddenIndex >= 0 && isResizingMultiple) {\n this.resizingItems.pop();\n this.removeTargetSize(metrics, resizeIndex);\n resizeIndex = this.resizingItems[this.resizingItems.length - 1];\n this.dragOffset -=\n this.targetSizes.get(getOrThrow(modelIndexes, resizeIndex)) ?? 0;\n } else {\n resizeIndex = this.getNextShownItem(resizeIndex, metrics);\n if (resizeIndex !== null) {\n this.resizingItems.push(resizeIndex);\n this.addTargetSize(metrics, resizeIndex);\n }\n }\n } else if (\n targetSize !== undefined &&\n itemSize > targetSize + theme.headerResizeSnapThreshold &&\n newSize === targetSize\n ) {\n if (hiddenIndex > 0) {\n this.dragOffset += newSize;\n resizeIndex = this.hiddenItems[hiddenIndex - 1];\n this.resizingItems.push(resizeIndex);\n this.addTargetSize(metrics, resizeIndex);\n } else if (isResizingMultiple) {\n this.resizingItems.pop();\n this.removeTargetSize(metrics, resizeIndex);\n resizeIndex = this.resizingItems[this.resizingItems.length - 1];\n } else {\n resizeIndex = null;\n }\n } else {\n resizeIndex = null;\n }\n }\n\n newSizes.forEach((newSize, modelIndex) => {\n if (newSize !== null) {\n this.setSize(metricCalculator, modelIndex, newSize);\n } else {\n this.resetSize(metricCalculator, modelIndex);\n }\n });\n\n this.updateCursor(metrics, this.draggingIndex);\n\n return true;\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.draggingIndex != null) {\n this.draggingIndex = undefined;\n this.resizingItems = [];\n this.hiddenItems = [];\n this.targetSizes.clear();\n\n this.updateSeparator(grid, null);\n }\n\n return false;\n }\n\n onDoubleClick(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const separatorIndex = this.getSeparatorIndex(gridPoint, grid);\n\n if (separatorIndex != null) {\n const { metricCalculator, metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const modelIndexes = metrics[this.modelIndexesProperty];\n const modelIndex = getOrThrow(modelIndexes, separatorIndex);\n\n this.resetSize(metricCalculator, modelIndex);\n\n grid.forceUpdate();\n\n return true;\n }\n return false;\n }\n\n updateCursor(metrics: GridMetrics, itemIndex: VisibleIndex): void {\n const visibleSizes = metrics[this.visibleSizesProperty];\n const itemSize = getOrThrow(visibleSizes, itemIndex);\n if (itemSize === 0) {\n this.cursor = this.hiddenCursor;\n } else {\n this.cursor = this.defaultCursor;\n }\n }\n\n addTargetSize(metrics: GridMetrics, itemIndex: VisibleIndex): void {\n const modelIndexes = metrics[this.modelIndexesProperty];\n const userSizes = metrics[this.userSizesProperty];\n const calculatedSizes = metrics[this.calculatedSizesProperty];\n const treePadding = itemIndex === 0 ? metrics[this.treePaddingProperty] : 0;\n\n const modelIndex = getOrThrow(modelIndexes, itemIndex);\n let targetSize = userSizes.get(modelIndex);\n if (targetSize == null || targetSize === 0) {\n targetSize = getOrThrow(calculatedSizes, modelIndex) + treePadding;\n }\n this.targetSizes.set(modelIndex, targetSize);\n }\n\n removeTargetSize(metrics: GridMetrics, itemIndex: VisibleIndex): void {\n const modelIndexes = metrics[this.modelIndexesProperty];\n const modelIndex = getOrThrow(modelIndexes, itemIndex);\n this.targetSizes.delete(modelIndex);\n }\n}\n\nexport default GridSeparatorMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport Grid from '../Grid';\nimport GridMetricCalculator from '../GridMetricCalculator';\nimport { ModelIndex, VisibleIndex } from '../GridMetrics';\nimport GridUtils, { GridPoint } from '../GridUtils';\nimport GridSeparatorMouseHandler from './GridSeparatorMouseHandler';\n\nclass GridColumnSeparatorMouseHandler extends GridSeparatorMouseHandler {\n static getColumnSeparatorIndex(\n gridPoint: GridPoint,\n grid: Grid,\n checkAllowResize = true\n ): VisibleIndex | null {\n const theme = grid.getTheme();\n if (checkAllowResize && !theme.allowColumnResize) {\n return null;\n }\n\n const { x, y } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n return GridUtils.getColumnSeparatorIndex(x, y, metrics, theme);\n }\n\n hiddenCursor = 'e-resize';\n\n defaultCursor = 'col-resize';\n\n pointProperty = 'x' as const;\n\n userSizesProperty = 'userColumnWidths' as const;\n\n visibleOffsetProperty = 'visibleColumnXs' as const;\n\n visibleSizesProperty = 'visibleColumnWidths' as const;\n\n marginProperty = 'rowHeaderWidth' as const;\n\n calculatedSizesProperty = 'calculatedColumnWidths' as const;\n\n modelIndexesProperty = 'modelColumns' as const;\n\n firstIndexProperty = 'firstColumn' as const;\n\n treePaddingProperty = 'treePaddingX' as const;\n\n getHiddenItems = GridUtils.getHiddenColumns;\n\n getNextShownItem = GridUtils.getNextShownColumn;\n\n setSize(\n metricCalculator: GridMetricCalculator,\n modelIndex: ModelIndex,\n size: number\n ): void {\n metricCalculator.setColumnWidth(modelIndex, size);\n }\n\n resetSize(\n metricCalculator: GridMetricCalculator,\n modelIndex: ModelIndex\n ): void {\n metricCalculator.resetColumnWidth(modelIndex);\n }\n\n updateSeparator(grid: Grid, separatorIndex: VisibleIndex | null): void {\n grid.setState({\n draggingColumnSeparator: separatorIndex,\n isDragging: separatorIndex !== null,\n });\n }\n\n getSeparatorIndex = GridColumnSeparatorMouseHandler.getColumnSeparatorIndex;\n}\n\nexport default GridColumnSeparatorMouseHandler;\n","import { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport { VisibleIndex } from '../GridMetrics';\nimport GridMouseHandler from '../GridMouseHandler';\nimport { GridPoint } from '../GridUtils';\n\n/* eslint class-methods-use-this: \"off\" */\nclass GridHorizontalScrollBarMouseHandler extends GridMouseHandler {\n static getLeftWithOffsetFromRawLeft(\n grid: Grid,\n rawLeft: number\n ): { left: VisibleIndex; leftOffset: number } {\n const theme = grid.getTheme();\n const { metrics, metricCalculator } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n if (theme.scrollSnapToColumn) {\n const left = Math.round(rawLeft);\n const leftOffset = 0;\n\n return { left, leftOffset };\n }\n const left = Math.floor(rawLeft);\n const leftOffsetPercent = rawLeft - left;\n let columnWidth = metrics.visibleColumnWidths.get(left);\n if (columnWidth == null) {\n const metricState = grid.getMetricState();\n columnWidth = metricCalculator.getVisibleColumnWidth(left, metricState);\n }\n const leftOffset = columnWidth * leftOffsetPercent;\n\n return { left, leftOffset };\n }\n\n private dragOffset?: number;\n\n // to trigger pointer event blocking\n cursor = 'default';\n\n isInScrollBar(gridPoint: GridPoint, grid: Grid): boolean {\n const theme = grid.getTheme();\n\n const { scrollBarSize, scrollBarHoverSize } = theme;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { x, y } = gridPoint;\n const { lastLeft, lastTop, rowHeaderWidth, width, height } = metrics;\n const scrollBarWidth = lastTop > 0 ? width - scrollBarSize : width;\n return (\n scrollBarSize > 0 &&\n lastLeft > 0 &&\n y >= height - scrollBarHoverSize &&\n y < height &&\n x > rowHeaderWidth &&\n x < scrollBarWidth\n );\n }\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { x } = gridPoint;\n const {\n barWidth,\n handleWidth,\n lastLeft,\n rowHeaderWidth,\n scrollX,\n } = metrics;\n if (!this.isInScrollBar(gridPoint, grid)) {\n return false;\n }\n\n const mouseBarX = x - rowHeaderWidth;\n if (mouseBarX >= scrollX && mouseBarX <= scrollX + handleWidth) {\n // Grabbed the horizontal handle\n this.dragOffset = mouseBarX - scrollX;\n grid.setState({ isDraggingHorizontalScrollBar: true });\n } else {\n this.dragOffset = 0;\n const rawLeft = Math.min(\n Math.max(0, (mouseBarX / (barWidth - handleWidth)) * lastLeft),\n lastLeft\n );\n\n const {\n left: newLeft,\n leftOffset: newLeftOffset,\n } = GridHorizontalScrollBarMouseHandler.getLeftWithOffsetFromRawLeft(\n grid,\n rawLeft\n );\n grid.setViewState({\n left: newLeft,\n leftOffset: newLeftOffset,\n isDraggingHorizontalScrollBar: true,\n isDragging: true,\n });\n }\n\n return true;\n }\n\n onDrag(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.dragOffset != null) {\n const { x } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { barWidth, handleWidth, lastLeft, rowHeaderWidth } = metrics;\n const mouseBarX = x - rowHeaderWidth;\n\n const rawLeft = Math.min(\n Math.max(\n 0,\n ((mouseBarX - this.dragOffset) / (barWidth - handleWidth)) * lastLeft\n ),\n lastLeft\n );\n\n const {\n left: newLeft,\n leftOffset: newLeftOffset,\n } = GridHorizontalScrollBarMouseHandler.getLeftWithOffsetFromRawLeft(\n grid,\n rawLeft\n );\n grid.setViewState({\n left: newLeft,\n leftOffset: newLeftOffset,\n isDraggingHorizontalScrollBar: true,\n isDragging: true,\n });\n\n return true;\n }\n return false;\n }\n\n onMove(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInScrollBar(gridPoint, grid);\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.dragOffset !== undefined) {\n this.dragOffset = undefined;\n grid.setState({\n isDraggingHorizontalScrollBar: false,\n isDragging: false,\n });\n }\n\n return this.isInScrollBar(gridPoint, grid);\n }\n\n onClick(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInScrollBar(gridPoint, grid);\n }\n}\n\nexport default GridHorizontalScrollBarMouseHandler;\n","import { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport { getOrThrow } from '../GridMetricCalculator';\nimport GridMouseHandler from '../GridMouseHandler';\nimport GridUtils, { GridPoint } from '../GridUtils';\n\nclass GridRowMoveMouseHandler extends GridMouseHandler {\n cursor = 'move';\n\n private draggingOffset?: number;\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const { model } = grid.props;\n const { x, y, row } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { columnHeaderHeight, rowHeaderWidth, visibleRowYs } = metrics;\n\n if (x <= rowHeaderWidth && row !== null && model.isRowMovable(row)) {\n const rowY = getOrThrow(visibleRowYs, row);\n this.draggingOffset = y - rowY - columnHeaderHeight;\n grid.setState({ draggingRowOffset: this.draggingOffset });\n }\n return false;\n }\n\n onDrag(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.draggingOffset == null) {\n return false;\n }\n\n const { model } = grid.props;\n let { draggingRow } = grid.state;\n const { mouseX, mouseY } = grid.state;\n if (mouseX == null || mouseY == null) {\n return false;\n }\n\n if (draggingRow == null) {\n const { row } = grid.getGridPointFromXY(mouseX, mouseY);\n if (row != null && !model.isRowMovable(row)) {\n return false;\n }\n\n draggingRow = row;\n\n grid.setState({ draggingRow, isDragging: true });\n\n if (draggingRow == null) {\n return false;\n }\n }\n\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const {\n top,\n lastTop,\n bottom,\n bottomVisible,\n rowCount,\n columnHeaderHeight,\n visibleRowHeights,\n visibleRowYs,\n height,\n } = metrics;\n let minY = columnHeaderHeight;\n if (top < draggingRow) {\n const topRow = draggingRow - 1;\n minY =\n getOrThrow(visibleRowYs, topRow) +\n getOrThrow(visibleRowHeights, topRow) * 0.5 +\n columnHeaderHeight;\n }\n\n let maxY = height;\n if (draggingRow < bottom) {\n const bottomRow = draggingRow + 1;\n maxY =\n getOrThrow(visibleRowYs, bottomRow) +\n getOrThrow(visibleRowHeights, bottomRow) * 0.5 +\n columnHeaderHeight;\n }\n\n let { movedRows } = grid.state;\n if (\n mouseY < minY &&\n draggingRow > 0 &&\n model.isRowMovable(draggingRow - 1)\n ) {\n movedRows = GridUtils.moveItem(draggingRow, draggingRow - 1, movedRows);\n draggingRow -= 1;\n } else if (\n maxY < mouseY &&\n draggingRow < rowCount - 1 &&\n model.isRowMovable(draggingRow + 1)\n ) {\n movedRows = GridUtils.moveItem(draggingRow, draggingRow + 1, movedRows);\n draggingRow += 1;\n }\n grid.setState({ movedRows, draggingRow });\n\n const minMoveY =\n columnHeaderHeight + getOrThrow(visibleRowHeights, top) * 0.5;\n const maxMoveY =\n columnHeaderHeight +\n getOrThrow(visibleRowYs, bottomVisible) +\n getOrThrow(visibleRowHeights, bottomVisible) * 0.5;\n if (mouseY < minMoveY && top > 0) {\n grid.setState({ top: top - 1 });\n } else if (mouseY > maxMoveY && top < lastTop) {\n grid.setState({ top: top + 1 });\n }\n\n return true;\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.draggingOffset !== undefined) {\n this.draggingOffset = undefined;\n grid.setState({\n draggingRowOffset: null,\n draggingRow: null,\n isDragging: false,\n });\n return true;\n }\n\n return false;\n }\n}\n\nexport default GridRowMoveMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport Grid from '../Grid';\nimport GridMetricCalculator from '../GridMetricCalculator';\nimport { ModelIndex, VisibleIndex } from '../GridMetrics';\nimport GridUtils, { GridPoint } from '../GridUtils';\nimport GridSeparatorMouseHandler from './GridSeparatorMouseHandler';\n\nclass GridRowSeparatorMouseHandler extends GridSeparatorMouseHandler {\n static getRowSeparatorIndex(\n gridPoint: GridPoint,\n grid: Grid,\n checkAllowResize = true\n ): VisibleIndex | null {\n const theme = grid.getTheme();\n if (checkAllowResize && !theme.allowRowResize) {\n return null;\n }\n\n const { x, y } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n return GridUtils.getRowSeparatorIndex(x, y, metrics, theme);\n }\n\n hiddenCursor = 's-resize';\n\n defaultCursor = 'row-resize';\n\n pointProperty = 'y' as const;\n\n userSizesProperty = 'userRowHeights' as const;\n\n visibleOffsetProperty = 'visibleRowYs' as const;\n\n visibleSizesProperty = 'visibleRowHeights' as const;\n\n marginProperty = 'columnHeaderHeight' as const;\n\n calculatedSizesProperty = 'calculatedRowHeights' as const;\n\n modelIndexesProperty = 'modelRows' as const;\n\n firstIndexProperty = 'firstRow' as const;\n\n treePaddingProperty = 'treePaddingY' as const;\n\n getHiddenItems = GridUtils.getHiddenRows;\n\n getNextShownItem = GridUtils.getNextShownRow;\n\n setSize(\n metricCalculator: GridMetricCalculator,\n modelIndex: ModelIndex,\n size: number\n ): void {\n metricCalculator.setRowHeight(modelIndex, size);\n }\n\n resetSize(\n metricCalculator: GridMetricCalculator,\n modelIndex: ModelIndex\n ): void {\n metricCalculator.resetRowHeight(modelIndex);\n }\n\n updateSeparator(grid: Grid, separatorIndex: VisibleIndex | null): void {\n grid.setState({\n draggingRowSeparator: separatorIndex,\n isDragging: separatorIndex !== null,\n });\n }\n\n getSeparatorIndex = GridRowSeparatorMouseHandler.getRowSeparatorIndex;\n}\n\nexport default GridRowSeparatorMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport { getOrThrow } from '../GridMetricCalculator';\nimport GridMouseHandler from '../GridMouseHandler';\nimport { GridPoint } from '../GridUtils';\n\n/**\n * Detect when the tree expand/collapse button is clicked\n */\nclass GridRowTreeMouseHandler extends GridMouseHandler {\n static isInTreeBox(gridPoint: GridPoint, grid: Grid): boolean {\n const { column, row, x, y } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const {\n gridX,\n gridY,\n firstColumn,\n visibleColumnXs,\n visibleColumnWidths,\n visibleRowHeights,\n visibleRowYs,\n visibleRowTreeBoxes,\n } = metrics;\n\n if (\n column === firstColumn &&\n row != null &&\n visibleRowTreeBoxes.get(row) != null &&\n x > gridX &&\n y > gridY\n ) {\n const columnX = getOrThrow(visibleColumnXs, column);\n const width = getOrThrow(visibleColumnWidths, column);\n const rowY = getOrThrow(visibleRowYs, row);\n const height = getOrThrow(visibleRowHeights, row);\n if (\n x >= gridX + columnX &&\n x <= gridX + columnX + width &&\n y >= gridY + rowY &&\n y <= gridY + rowY + height\n ) {\n return true;\n }\n }\n return false;\n }\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return GridRowTreeMouseHandler.isInTreeBox(gridPoint, grid);\n }\n\n onClick(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (GridRowTreeMouseHandler.isInTreeBox(gridPoint, grid)) {\n const { row } = gridPoint;\n if (row !== null) {\n grid.toggleRowExpanded(row);\n return true;\n }\n }\n return false;\n }\n}\n\nexport default GridRowTreeMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport GridMouseHandler from '../GridMouseHandler';\nimport { GridPoint } from '../GridUtils';\n\n/**\n * Used to eat the mouse event in the bottom right corner of the scroll bar\n */\nclass GridScrollBarCornerMouseHandler extends GridMouseHandler {\n isInCorner(gridPoint: GridPoint, grid: Grid): boolean {\n const theme = grid.getTheme();\n const { scrollBarSize } = theme;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { x, y } = gridPoint;\n const { lastLeft, lastTop, width, height } = metrics;\n return (\n scrollBarSize > 0 &&\n lastTop > 0 &&\n lastLeft > 0 &&\n x >= width - scrollBarSize &&\n y >= height - scrollBarSize &&\n x <= width &&\n y <= height\n );\n }\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInCorner(gridPoint, grid);\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInCorner(gridPoint, grid);\n }\n\n onClick(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInCorner(gridPoint, grid);\n }\n}\n\nexport default GridScrollBarCornerMouseHandler;\n","import { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport { VisibleIndex } from '../GridMetrics';\nimport GridMouseHandler from '../GridMouseHandler';\nimport { GridPoint } from '../GridUtils';\n\n/* eslint class-methods-use-this: \"off\" */\nclass GridVerticalScrollBarMouseHandler extends GridMouseHandler {\n static getTopWithOffsetFromRawTop(\n grid: Grid,\n rawTop: number\n ): { top: VisibleIndex; topOffset: number } {\n const theme = grid.getTheme();\n const { metrics, metricCalculator } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n if (theme.scrollSnapToRow) {\n const top = Math.round(rawTop);\n const topOffset = 0;\n\n return { top, topOffset };\n }\n const top = Math.floor(rawTop);\n const topOffsetPercent = rawTop - top;\n let rowHeight = metrics.visibleRowHeights.get(top);\n if (rowHeight == null) {\n const metricState = grid.getMetricState();\n rowHeight = metricCalculator.getVisibleRowHeight(top, metricState);\n }\n const topOffset = rowHeight * topOffsetPercent;\n\n return { top, topOffset };\n }\n\n private dragOffset?: number;\n\n // to trigger pointer event blocking\n cursor = 'default';\n\n isInScrollBar(gridPoint: GridPoint, grid: Grid): boolean {\n const theme = grid.getTheme();\n\n const { scrollBarSize, scrollBarHoverSize } = theme;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { x, y } = gridPoint;\n const { lastLeft, lastTop, columnHeaderHeight, height, width } = metrics;\n const scrollBarHeight = lastLeft > 0 ? height - scrollBarSize : height;\n return (\n scrollBarSize > 0 &&\n lastTop > 0 &&\n x >= width - scrollBarHoverSize &&\n x < width &&\n y > columnHeaderHeight &&\n y < scrollBarHeight\n );\n }\n\n onDown(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { y } = gridPoint;\n const {\n barHeight,\n handleHeight,\n lastTop,\n columnHeaderHeight,\n scrollY,\n } = metrics;\n if (!this.isInScrollBar(gridPoint, grid)) {\n return false;\n }\n\n const mouseBarY = y - columnHeaderHeight;\n if (mouseBarY >= scrollY && mouseBarY <= scrollY + handleHeight) {\n // Grabbed the vertical handle\n this.dragOffset = mouseBarY - scrollY;\n grid.setState({ isDraggingVerticalScrollBar: true });\n } else {\n // clicked elsewhere in bar\n this.dragOffset = 0;\n const rawTop = Math.min(\n Math.max(0, (mouseBarY / (barHeight - handleHeight)) * lastTop),\n lastTop\n );\n\n const {\n top: newTop,\n topOffset: newTopOffset,\n } = GridVerticalScrollBarMouseHandler.getTopWithOffsetFromRawTop(\n grid,\n rawTop\n );\n grid.setViewState({\n top: newTop,\n topOffset: newTopOffset,\n isDraggingVerticalScrollBar: true,\n isDragging: true,\n });\n }\n\n return true;\n }\n\n onMove(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInScrollBar(gridPoint, grid);\n }\n\n onDrag(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.dragOffset != null) {\n const { y } = gridPoint;\n const { metrics } = grid;\n if (!metrics) throw new Error('metrics not set');\n\n const { barHeight, handleHeight, lastTop, columnHeaderHeight } = metrics;\n const mouseBarY = y - columnHeaderHeight;\n\n const rawTop = Math.min(\n Math.max(\n 0,\n ((mouseBarY - this.dragOffset) / (barHeight - handleHeight)) * lastTop\n ),\n lastTop\n );\n\n const {\n top: newTop,\n topOffset: newTopOffset,\n } = GridVerticalScrollBarMouseHandler.getTopWithOffsetFromRawTop(\n grid,\n rawTop\n );\n grid.setViewState({\n top: newTop,\n topOffset: newTopOffset,\n isDraggingVerticalScrollBar: true,\n isDragging: true,\n });\n return true;\n }\n return false;\n }\n\n onUp(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n if (this.dragOffset !== undefined) {\n this.dragOffset = undefined;\n grid.setState({ isDraggingVerticalScrollBar: false, isDragging: false });\n }\n\n return this.isInScrollBar(gridPoint, grid);\n }\n\n onClick(gridPoint: GridPoint, grid: Grid): EventHandlerResult {\n return this.isInScrollBar(gridPoint, grid);\n }\n}\n\nexport default GridVerticalScrollBarMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { isEditableGridModel } from '../EditableGridModel';\nimport { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport GridMouseHandler from '../GridMouseHandler';\nimport GridRange from '../GridRange';\nimport { GridPoint } from '../GridUtils';\n\n/**\n * Handles clicking on a cell to edit it in an editable grid\n */\nclass EditMouseHandler extends GridMouseHandler {\n onDoubleClick({ column, row }: GridPoint, grid: Grid): EventHandlerResult {\n const { model } = grid.props;\n if (\n isEditableGridModel(model) &&\n column != null &&\n row != null &&\n model.isEditableRange(GridRange.makeCell(column, row))\n ) {\n grid.startEditing(column, row);\n return true;\n }\n return false;\n }\n}\n\nexport default EditMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint @typescript-eslint/no-unused-vars: \"off\" */\n/**\n * Handle keys in a grid\n * Return true from any of the events to indicate they're consumed, and stopPropagation/preventDefault will be called.\n */\n\nimport React from 'react';\nimport { EventHandlerResult } from './EventHandlerResult';\nimport type Grid from './Grid';\n\n/**\n * Some events we listen to are a native keyboard event, and others are wrapped with React's SyntheticEvent.\n * The KeyHandler shouldn't care though - the properties it accesses should be common on both types of events.\n */\nexport type GridKeyboardEvent = KeyboardEvent | React.KeyboardEvent;\n\nexport class KeyHandler {\n order: number;\n\n // What order this key handler should trigger in\n // Default to well below any of the GRID key handlers 100-1000+\n constructor(order = 5000) {\n this.order = order;\n }\n\n /**\n * Handle a keydown event on the grid.\n * @param event The keyboard event\n * @param grid The grid component the key press is on\n * @returns Response indicating if the key was consumed\n */\n onDown(event: GridKeyboardEvent, grid: Grid): EventHandlerResult {\n return false;\n }\n}\n\nexport default KeyHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport clamp from 'lodash.clamp';\nimport Grid from '../Grid';\nimport GridRange from '../GridRange';\nimport GridUtils from '../GridUtils';\nimport KeyHandler, { GridKeyboardEvent } from '../KeyHandler';\n\nclass SelectionKeyHandler extends KeyHandler {\n onDown(event: GridKeyboardEvent, grid: Grid): boolean {\n switch (event.key) {\n case 'a':\n if (GridUtils.isModifierKeyDown(event)) {\n grid.selectAll();\n return true;\n }\n break;\n case 'ArrowUp':\n return this.handleArrowMove(0, -1, event, grid);\n case 'ArrowDown':\n return this.handleArrowMove(0, 1, event, grid);\n case 'ArrowRight':\n return this.handleArrowMove(1, 0, event, grid);\n case 'ArrowLeft':\n return this.handleArrowMove(-1, 0, event, grid);\n case 'k': // h/j/k/l keys are grouped together for quick navigation by power users\n case 'PageUp':\n return this.handlePageUp(event, grid);\n case 'j':\n case 'PageDown':\n return this.handlePageDown(event, grid);\n case 'h':\n grid.clearSelectedRanges();\n grid.moveCursorToPosition(0, grid.state.cursorRow);\n return true;\n case 'l': {\n const { model } = grid.props;\n const { columnCount } = model;\n grid.clearSelectedRanges();\n grid.moveCursorToPosition(columnCount - 1, grid.state.cursorRow);\n return true;\n }\n case 'Home':\n if (!event.shiftKey) {\n grid.clearSelectedRanges();\n }\n grid.moveCursorToPosition(\n GridUtils.isModifierKeyDown(event) ? grid.state.cursorColumn : 0,\n GridUtils.isModifierKeyDown(event) ? 0 : grid.state.cursorRow,\n event.shiftKey,\n true,\n true\n );\n return true;\n case 'End': {\n const { model } = grid.props;\n const { columnCount, rowCount } = model;\n if (!event.shiftKey) {\n grid.clearSelectedRanges();\n }\n grid.moveCursorToPosition(\n GridUtils.isModifierKeyDown(event)\n ? grid.state.cursorColumn\n : columnCount - 1,\n GridUtils.isModifierKeyDown(event)\n ? rowCount - 1\n : grid.state.cursorRow,\n event.shiftKey,\n true,\n true\n );\n return true;\n }\n case 'Escape':\n grid.clearSelectedRanges();\n return true;\n case 'Enter':\n if (grid.state.selectedRanges.length > 0) {\n grid.moveCursorInDirection(\n event.shiftKey\n ? GridRange.SELECTION_DIRECTION.UP\n : GridRange.SELECTION_DIRECTION.DOWN\n );\n return true;\n }\n break;\n case 'Tab':\n if (grid.state.selectedRanges.length > 0) {\n grid.moveCursorInDirection(\n event.shiftKey\n ? GridRange.SELECTION_DIRECTION.LEFT\n : GridRange.SELECTION_DIRECTION.RIGHT\n );\n return true;\n }\n break;\n default:\n break;\n }\n return false;\n }\n\n handleArrowMove(\n deltaColumn: number,\n deltaRow: number,\n event: GridKeyboardEvent,\n grid: Grid\n ): boolean {\n const isShiftKey = event.shiftKey;\n const isModifierKey = GridUtils.isModifierKeyDown(event);\n if (isShiftKey) {\n grid.trimSelectedRanges();\n } else {\n grid.clearSelectedRanges();\n }\n\n const {\n cursorRow,\n cursorColumn,\n selectionEndColumn,\n selectionEndRow,\n } = grid.state;\n const column = isShiftKey ? selectionEndColumn : cursorColumn;\n const row = isShiftKey ? selectionEndRow : cursorRow;\n if (isModifierKey) {\n const { model } = grid.props;\n const { columnCount, rowCount } = model;\n const maximizePreviousRange = isModifierKey && isShiftKey;\n let moveToColumn = null;\n let moveToRow = null;\n if (deltaColumn < 0) {\n moveToColumn = 0;\n moveToRow = row;\n } else if (deltaColumn > 0) {\n moveToColumn = columnCount - 1;\n moveToRow = row;\n } else if (deltaRow < 0) {\n moveToColumn = column;\n moveToRow = 0;\n } else if (deltaRow > 0) {\n moveToColumn = column;\n moveToRow = rowCount - 1;\n }\n if (moveToColumn != null && moveToRow != null) {\n grid.moveCursorToPosition(\n moveToColumn,\n moveToRow,\n isShiftKey,\n true,\n maximizePreviousRange\n );\n }\n } else {\n if (!grid.metrics) throw new Error('grid.metrics are not set');\n\n const { theme } = grid.props;\n const { autoSelectRow, autoSelectColumn } = theme;\n if (autoSelectRow && deltaColumn !== 0) {\n const { lastLeft } = grid.metrics;\n let { left } = grid.state;\n\n left = clamp(left + deltaColumn, 0, lastLeft);\n\n grid.moveCursorToPosition(left, cursorRow, isShiftKey, false);\n\n grid.setViewState({ left });\n } else if (autoSelectColumn && deltaRow !== 0) {\n const { lastTop } = grid.metrics;\n let { top } = grid.state;\n\n top = clamp(top + deltaRow, 0, lastTop);\n\n grid.moveCursorToPosition(top, cursorColumn, isShiftKey, false);\n\n grid.setViewState({ top });\n } else {\n grid.moveCursor(deltaColumn, deltaRow, isShiftKey);\n }\n }\n return true;\n }\n\n handlePageUp(e: GridKeyboardEvent, grid: Grid): boolean {\n const isShiftKey = e.shiftKey;\n\n if (isShiftKey) {\n grid.trimSelectedRanges();\n } else {\n grid.clearSelectedRanges();\n }\n\n const { cursorColumn, selectionEndRow } = grid.state;\n const row: number | null = selectionEndRow;\n const column: number | null = cursorColumn;\n if (row == null) {\n return false;\n }\n const metricState = grid.getMetricState();\n const { metricCalculator } = grid;\n const {\n bottomVisible,\n topVisible,\n hasHorizontalBar,\n } = metricCalculator.getMetrics(metricState);\n\n let selectRangeEndPosition = row - (bottomVisible - topVisible);\n selectRangeEndPosition -= hasHorizontalBar ? 0 : 1;\n\n // Don't move beyond the top table row.\n selectRangeEndPosition = Math.max(selectRangeEndPosition, 0);\n const viewportPosition = Math.max(\n selectRangeEndPosition - (row - topVisible),\n 0\n );\n\n grid.moveCursorToPosition(\n column,\n selectRangeEndPosition,\n isShiftKey,\n false\n );\n grid.setViewState({ top: viewportPosition });\n return true;\n }\n\n handlePageDown(e: GridKeyboardEvent, grid: Grid): boolean {\n const isShiftKey = e.shiftKey;\n\n if (isShiftKey) {\n grid.trimSelectedRanges();\n } else {\n grid.clearSelectedRanges();\n }\n\n const { selectionEndRow, cursorColumn } = grid.state;\n const row: number | null = selectionEndRow;\n const column: number | null = cursorColumn;\n if (row === null) {\n return false;\n }\n const metricState = grid.getMetricState();\n const { metricCalculator } = grid;\n const {\n bottomVisible,\n topVisible,\n hasHorizontalBar,\n rowCount,\n lastTop,\n } = metricCalculator.getMetrics(metricState);\n const lastRowIndex = rowCount - 1;\n\n let selectRangeEndPosition = bottomVisible - topVisible + row;\n selectRangeEndPosition += hasHorizontalBar ? 0 : 1;\n\n // Don't move beyond the bottom table row.\n selectRangeEndPosition = Math.min(selectRangeEndPosition, lastRowIndex);\n\n const viewportPosition = Math.min(\n lastTop,\n selectRangeEndPosition - (row - topVisible)\n );\n grid.moveCursorToPosition(\n column,\n selectRangeEndPosition,\n isShiftKey,\n false\n );\n grid.setViewState({ top: viewportPosition });\n\n return true;\n }\n}\n\nexport default SelectionKeyHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { isExpandableGridModel } from '../ExpandableGridModel';\nimport Grid from '../Grid';\nimport GridRange from '../GridRange';\nimport KeyHandler from '../KeyHandler';\n\nclass TreeKeyHandler extends KeyHandler {\n onDown(event: KeyboardEvent, grid: Grid): boolean {\n switch (event.key) {\n case 'Enter':\n case ' ': {\n return this.handleExpandKey(event, grid);\n }\n default:\n break;\n }\n return false;\n }\n\n handleExpandKey(event: KeyboardEvent, grid: Grid): boolean {\n const { selectedRanges } = grid.state;\n if (selectedRanges.length === 1) {\n const range = selectedRanges[0] as GridRange;\n if (\n range.startRow === range.endRow &&\n range.startColumn === range.endColumn\n ) {\n if (!grid.metrics) throw new Error('grid.metrics not set');\n\n const { model } = grid.props;\n const { startRow: row, startColumn: column } = range;\n if (row != null) {\n const modelRow = grid.getModelRow(row);\n if (\n (column === 0 || column == null) &&\n isExpandableGridModel(model) &&\n model.isRowExpandable(modelRow)\n ) {\n grid.toggleRowExpanded(row);\n return true;\n }\n }\n }\n }\n return false;\n }\n}\n\nexport default TreeKeyHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport GridUtils from '../GridUtils';\nimport Grid from '../Grid';\nimport GridRange from '../GridRange';\nimport KeyHandler, { GridKeyboardEvent } from '../KeyHandler';\nimport { isEditableGridModel } from '../EditableGridModel';\nimport { EventHandlerResult } from '../EventHandlerResult';\n\nclass EditKeyHandler extends KeyHandler {\n onDown(event: GridKeyboardEvent, grid: Grid): EventHandlerResult {\n if (GridUtils.isModifierKeyDown(event)) {\n return false;\n }\n\n const { model } = grid.props;\n const { cursorColumn, cursorRow } = grid.state;\n if (\n cursorColumn == null ||\n cursorRow == null ||\n !isEditableGridModel(model) ||\n !model.isEditableRange(GridRange.makeCell(cursorColumn, cursorRow))\n ) {\n return false;\n }\n const column: number | null = cursorColumn;\n const row: number | null = cursorRow;\n if (column == null || row == null) {\n return false;\n }\n\n if (event.key.length === 1) {\n grid.startEditing(column, row, true, [1, 1], event.key);\n return true;\n }\n\n if (event.key === 'F2') {\n grid.startEditing(column, row);\n return true;\n }\n\n if (event.key === 'Backspace') {\n grid.startEditing(column, row, true, undefined, '');\n return true;\n }\n\n if (event.key === 'Delete') {\n grid.setValueForCell(column, row, '');\n return true;\n }\n return false;\n }\n}\n\nexport default EditKeyHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { EventHandlerResult } from '../EventHandlerResult';\nimport Grid from '../Grid';\nimport GridUtils from '../GridUtils';\nimport KeyHandler, { GridKeyboardEvent } from '../KeyHandler';\n\n/**\n * Parse out data from an HTML table. Currently does not support colspan/rowspan\n * @param table HTML Table\n * @returns A two dimensional array with the data found in the table\n */\nexport function parseValueFromTable(table: HTMLTableElement): string[][] {\n const data = [];\n const rows = table.querySelectorAll('tr');\n for (let r = 0; r < rows.length; r += 1) {\n const row = rows[r];\n const cells = row.querySelectorAll('td');\n const rowData = [];\n for (let c = 0; c < cells.length; c += 1) {\n const cell = cells[c];\n rowData.push(cell.textContent?.trim() ?? '');\n }\n data.push(rowData);\n }\n\n return data;\n}\n\n/**\n * Parses out a table of data from HTML elements. Treats each element as one rows.\n * Filters out blank rows.\n * @param rows The elements to parse out\n * @returns A string table of data\n */\nexport function parseValueFromNodes(nodes: NodeListOf<ChildNode>): string[][] {\n const result = [] as string[][];\n nodes.forEach(node => {\n const text = node.textContent ?? '';\n if (text.length > 0) {\n // When Chrome pastes a table from text, it preserves the tab characters\n // In Firefox, it breaks it into a combination of non-breaking spaces and spaces\n result.push(text.split(/\\t|\\u00a0\\u00a0 \\u00a0/));\n }\n });\n\n return result;\n}\n\nexport function parseValueFromElement(\n element: HTMLElement\n): string | string[][] | null {\n // Check first if there's an HTML table element that we can use\n const table = element.querySelector('table');\n if (table != null) {\n return parseValueFromTable(table);\n }\n\n // Otherwise check if there's any text content at all\n const text = element.textContent?.trim() ?? '';\n if (text.length > 0) {\n // If there's text content, try and parse out a table from the child nodes. Each node is a row.\n // If there's only one row and it doesn't contain a tab, then just treat it as a regular value\n const { childNodes } = element;\n const hasTabChar = text.includes('\\t');\n const hasFirefoxTab = text.includes('\\u00a0\\u00a0 \\u00a0');\n if (\n hasTabChar &&\n childNodes.length !== 0 &&\n (childNodes.length === 1 ||\n (childNodes.length > 1 && !childNodes[0].textContent?.includes('\\t')))\n ) {\n // When Chrome pastes a single row, it gets split into multiple child nodes\n // If we check the first child node and it doesn't have a tab character, but the full element text content does, then\n // just parse the text out separated by the tab chars\n return text.split('\\n').map(row => row.split('\\t'));\n }\n if (childNodes.length > 1 || hasFirefoxTab) {\n return parseValueFromNodes(element.childNodes);\n }\n // If there's no tabs or no multiple rows, than just treat it as one value\n return text;\n }\n return null;\n}\n\n/**\n * Handles the paste key combination\n */\nclass PasteKeyHandler extends KeyHandler {\n onDown(event: GridKeyboardEvent, grid: Grid): EventHandlerResult {\n switch (event.key) {\n case 'v':\n if (GridUtils.isModifierKeyDown(event)) {\n // Chrome doesn't allow the paste event on canvas elements\n // Instead, we capture the ctrl+v keydown, then do this to capture the input\n const dummyInput = document.createElement('div');\n document.body.appendChild(dummyInput);\n dummyInput.setAttribute('contenteditable', 'true');\n\n // Give it invisible styling\n dummyInput.setAttribute(\n 'style',\n 'clip-path: \"inset(50%)\"; height: 1px; width: 1px; margin: -1px; overflow: hidden; padding 0; position: absolute;'\n );\n\n const listener = () => {\n dummyInput.removeEventListener('input', listener);\n dummyInput.remove();\n\n grid.focus();\n const value = parseValueFromElement(dummyInput);\n if (value != null) {\n grid.pasteValue(value);\n }\n };\n\n // Listen for the `input` event, when there's a change to the HTML\n // We could also listen to the `paste` event to get the clipboard data, but that's just text data\n // By listening to `input`, we can get a table that's already parsed in HTML, which is easier to consume\n dummyInput.addEventListener('input', listener);\n\n // Focus the element so it receives the paste event\n dummyInput.focus();\n\n // Don't block the paste event from updating our dummy input\n return { preventDefault: false, stopPropagation: true };\n }\n break;\n }\n return false;\n }\n}\n\nexport default PasteKeyHandler;\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { SELECTION_DIRECTION } from './GridRange';\nimport GridUtils from './GridUtils';\nimport './CellInputField.scss';\n\nexport type CellInputFieldProps = {\n selectionRange?: number[];\n className?: string;\n disabled?: boolean;\n isQuickEdit?: boolean;\n value?: string;\n onChange?: (value: string) => void;\n onCancel?: () => void;\n onDone?: (\n value: string,\n options: {\n direction?: SELECTION_DIRECTION | null;\n fillRange?: boolean;\n }\n ) => void;\n onContextMenu?: React.MouseEventHandler<HTMLTextAreaElement>;\n style?: React.CSSProperties;\n};\n\nexport const directionForKey = (\n key: string\n): SELECTION_DIRECTION | undefined => {\n switch (key) {\n case 'ArrowDown':\n return SELECTION_DIRECTION.DOWN;\n case 'ArrowUp':\n return SELECTION_DIRECTION.UP;\n case 'ArrowLeft':\n return SELECTION_DIRECTION.LEFT;\n case 'ArrowRight':\n return SELECTION_DIRECTION.RIGHT;\n default:\n return undefined;\n }\n};\n\nexport const CellInputField = ({\n selectionRange = undefined,\n className = '',\n disabled = false,\n value: propsValue = '',\n isQuickEdit: propsIsQuickEdit = true,\n onChange = () => undefined,\n onCancel = () => undefined,\n onDone = () => undefined,\n onContextMenu = () => undefined,\n style = {},\n}: CellInputFieldProps): JSX.Element => {\n const inputField = useRef<HTMLTextAreaElement>(null);\n // Use a ref for `isCancelled` as we need to know when it's cancelled after it's called by the event handlers as well\n const isCancelled = useRef<boolean>(false);\n const [initialValue] = useState(propsValue);\n const [isChanged, setIsChanged] = useState(false);\n const [isQuickEdit, setIsQuickEdit] = useState(propsIsQuickEdit);\n const [value, setValue] = useState(propsValue);\n\n // Init field selection\n useEffect(() => {\n const { current: field } = inputField;\n if (field == null) {\n return;\n }\n\n field.focus();\n if (selectionRange) {\n field.setSelectionRange(selectionRange[0], selectionRange[1]);\n } else {\n field.setSelectionRange(field.value.length, field.value.length);\n }\n }, [selectionRange]);\n\n const sendUpdate = useCallback(\n (newValue: string) => {\n onChange(newValue);\n },\n [onChange]\n );\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const { value: newValue } = event.target;\n setValue(newValue);\n setIsChanged(true);\n sendUpdate(newValue);\n },\n [sendUpdate, setValue, setIsChanged]\n );\n\n const handleCancel = useCallback(() => {\n isCancelled.current = true;\n if (isChanged) {\n sendUpdate(initialValue);\n }\n\n setIsChanged(false);\n onCancel();\n }, [initialValue, isChanged, onCancel, sendUpdate]);\n\n const handleClick = useCallback(() => {\n setIsQuickEdit(false);\n }, [setIsQuickEdit]);\n\n const handleCommit = useCallback(\n (direction?: SELECTION_DIRECTION | null, fillRange = false) => {\n onDone(value, { direction, fillRange });\n },\n [onDone, value]\n );\n\n const handleBlur = useCallback(() => {\n if (isCancelled.current) {\n return;\n }\n\n handleCommit(null);\n }, [isCancelled, handleCommit]);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n event.stopPropagation();\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n handleCancel();\n break;\n case 'Enter':\n event.preventDefault();\n if (GridUtils.isModifierKeyDown(event)) {\n handleCommit(undefined, true);\n } else if (event.altKey) {\n const newValue = `${value}\\n`;\n setValue(newValue);\n setIsChanged(true);\n sendUpdate(newValue);\n } else {\n handleCommit(\n event.shiftKey ? SELECTION_DIRECTION.UP : SELECTION_DIRECTION.DOWN\n );\n }\n break;\n case 'Tab':\n event.preventDefault();\n handleCommit(\n event.shiftKey\n ? SELECTION_DIRECTION.LEFT\n : SELECTION_DIRECTION.RIGHT\n );\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (isQuickEdit) {\n event.preventDefault();\n handleCommit(directionForKey(event.key));\n }\n break;\n default:\n break;\n }\n },\n [\n handleCancel,\n handleCommit,\n isQuickEdit,\n setValue,\n setIsChanged,\n sendUpdate,\n value,\n ]\n );\n\n const handleContextMenu = useCallback(\n (event: React.MouseEvent<HTMLTextAreaElement, MouseEvent>) => {\n onContextMenu(event);\n },\n [onContextMenu]\n );\n\n return (\n <textarea\n ref={inputField}\n className={classNames('grid-cell-input-field', className)}\n value={value}\n onBlur={handleBlur}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onContextMenu={handleContextMenu}\n onClick={handleClick}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck=\"false\"\n disabled={disabled}\n style={style}\n />\n );\n};\n\nCellInputField.propTypes = {\n selectionRange: PropTypes.arrayOf(PropTypes.number),\n className: PropTypes.string,\n disabled: PropTypes.bool,\n isQuickEdit: PropTypes.bool,\n value: PropTypes.string,\n onChange: PropTypes.func,\n onCancel: PropTypes.func,\n onDone: PropTypes.func,\n onContextMenu: PropTypes.func,\n style: PropTypes.shape({}),\n};\n\nCellInputField.defaultProps = {\n selectionRange: null,\n className: '',\n disabled: false,\n value: '',\n isQuickEdit: true,\n onChange: () => undefined,\n onCancel: () => undefined,\n onDone: () => undefined,\n onContextMenu: () => undefined,\n style: {},\n};\n\nexport default CellInputField;\n","/* eslint react/no-did-update-set-state: \"off\" */\nimport React, { CSSProperties, PureComponent, ReactNode } from 'react';\nimport classNames from 'classnames';\nimport memoize from 'memoize-one';\nimport clamp from 'lodash.clamp';\nimport GridMetricCalculator, { GridMetricState } from './GridMetricCalculator';\nimport GridModel from './GridModel';\nimport GridMouseHandler, {\n GridMouseEvent,\n GridMouseHandlerFunctionName,\n} from './GridMouseHandler';\nimport GridTheme, { GridTheme as GridThemeType } from './GridTheme';\nimport GridRange, { GridRangeIndex, SELECTION_DIRECTION } from './GridRange';\nimport GridRenderer, {\n EditingCell,\n EditingCellTextSelectionRange,\n} from './GridRenderer';\nimport GridUtils, { GridPoint } from './GridUtils';\nimport {\n GridSelectionMouseHandler,\n GridColumnMoveMouseHandler,\n GridColumnSeparatorMouseHandler,\n GridHorizontalScrollBarMouseHandler,\n GridRowMoveMouseHandler,\n GridRowSeparatorMouseHandler,\n GridRowTreeMouseHandler,\n GridScrollBarCornerMouseHandler,\n GridVerticalScrollBarMouseHandler,\n EditMouseHandler,\n} from './mouse-handlers';\nimport './Grid.scss';\nimport KeyHandler, { GridKeyboardEvent } from './KeyHandler';\nimport {\n EditKeyHandler,\n PasteKeyHandler,\n SelectionKeyHandler,\n TreeKeyHandler,\n} from './key-handlers';\nimport CellInputField from './CellInputField';\nimport PasteError from './errors/PasteError';\nimport GridMetrics, {\n Coordinate,\n ModelIndex,\n MoveOperation,\n VisibleIndex,\n} from './GridMetrics';\nimport { isExpandableGridModel } from './ExpandableGridModel';\nimport {\n assertIsEditableGridModel,\n EditOperation,\n isEditableGridModel,\n} from './EditableGridModel';\nimport { EventHandlerResultOptions } from './EventHandlerResult';\nimport { assertIsDefined } from './errors';\n\ntype LegacyCanvasRenderingContext2D = CanvasRenderingContext2D & {\n webkitBackingStorePixelRatio?: number;\n mozBackingStorePixelRatio?: number;\n msBackingStorePixelRatio?: number;\n oBackingStorePixelRatio?: number;\n backingStorePixelRatio?: number;\n};\n\nexport type GridProps = typeof Grid.defaultProps & {\n // Options to set on the canvas\n canvasOptions?: CanvasRenderingContext2DSettings;\n\n // Whether the grid should stick to the bottom or the right once scrolled to the end\n // Only matters with ticking grids\n isStickyBottom?: boolean;\n isStickyRight?: boolean;\n\n // Whether the grid is currently stuck to the bottom or the right\n isStuckToBottom?: boolean;\n isStuckToRight?: boolean;\n\n // Calculate all the metrics required for drawing the grid\n metricCalculator?: GridMetricCalculator;\n\n // The model to pull data from\n model: GridModel;\n\n // Optional key and mouse handlers\n keyHandlers?: KeyHandler[];\n mouseHandlers?: GridMouseHandler[];\n\n // Initial state of moved columns or rows\n movedColumns?: MoveOperation[];\n movedRows?: MoveOperation[];\n\n // Callback for if an error occurs\n onError?: (e: Error) => void;\n\n // Callback when the selection within the grid changes\n onSelectionChanged?: (ranges: GridRange[]) => void;\n\n // Callback when the moved columns or rows have changed\n onMovedColumnsChanged?: (movedColumns: MoveOperation[]) => void;\n onMovedRowsChanged?: (movedRows: MoveOperation[]) => void;\n\n // Callback when a move operation is completed\n onMoveColumnComplete?: (movedColumns: MoveOperation[]) => void;\n onMoveRowComplete?: (movedRows: MoveOperation[]) => void;\n\n // Callback when the viewport has scrolled or changed\n onViewChanged?: (metrics: GridMetrics) => void;\n\n // Renderer for the grid canvas\n renderer?: GridRenderer;\n\n // Optional state override to pass in to the metric and render state\n // Can be used to add custom properties as well\n stateOverride?: Record<string, unknown>;\n\n theme?: GridThemeType;\n};\n\nexport type GridState = {\n // Top/left visible cell in the grid. Note that it's visible row/column index, not the model index (ie. if columns are re-ordered)\n top: VisibleIndex;\n left: VisibleIndex;\n\n // The scroll offset of the top/left cell. 0,0 means the cell is at the top left\n topOffset: number; // Should be less than the height of the row\n leftOffset: number; // Should be less than the width of the column\n\n // current column/row that user is dragging\n draggingColumn: VisibleIndex | null;\n draggingRow: VisibleIndex | null;\n\n // Offset when dragging a column/row\n draggingColumnOffset: number | null;\n draggingRowOffset: number | null;\n\n // When drawing header separators for resizing\n draggingColumnSeparator: VisibleIndex | null;\n draggingRowSeparator: VisibleIndex | null;\n\n // Dragging a scroll bar status\n isDraggingHorizontalScrollBar: boolean;\n isDraggingVerticalScrollBar: boolean;\n\n // Anything is performing a drag, for blocking hover rendering\n isDragging: boolean;\n\n // The coordinates of the mouse. May be outside of the canvas\n mouseX: number | null;\n mouseY: number | null;\n\n // Move operations the user has performed on this grids columns/rows\n movedColumns: MoveOperation[];\n movedRows: MoveOperation[];\n\n // Cursor (highlighted cell) location and active selected range\n cursorRow: VisibleIndex | null;\n cursorColumn: VisibleIndex | null;\n selectionStartRow: VisibleIndex | null;\n selectionStartColumn: VisibleIndex | null;\n selectionEndRow: VisibleIndex | null;\n selectionEndColumn: VisibleIndex | null;\n\n // Currently selected ranges and previously selected ranges\n // Store the previously selected ranges to determine if the new selection should\n // deselect again (if it's the same range)\n selectedRanges: GridRange[];\n lastSelectedRanges: GridRange[];\n\n // The mouse cursor style to use when hovering over the grid element\n cursor: string | null;\n\n // { column: number, row: number, selectionRange: [number, number], value: string | null, isQuickEdit?: boolean }\n // The cell that is currently being edited\n editingCell: EditingCell | null;\n\n // Whether we're stuck to the bottom or the right\n isStuckToBottom: boolean;\n isStuckToRight: boolean;\n};\n\n/**\n * High performance, extendible, themeable grid component.\n * Architectured to be fast and handle billions of rows/columns by default.\n * The base model does not provide support for sorting, filtering, etc.\n * To get that functionality, extend GridModel/GridRenderer, and add onClick/onContextMenu handlers to implement your own sort.\n *\n * Extend GridModel with your own data model to provide the data for the grid.\n * Extend GridTheme to change the appearance if the grid. See GridTheme for all the settable values.\n * Extend GridMetricCalculator to provide different metrics for the grid, such as column sizing, header sizing, etc.\n * Extend GridRenderer to have complete control over the rendering process. Can override just one method such as drawColumnHeader, or override the whole drawCanvas process.\n *\n * Add an onViewChanged callback to page in/out data as user moves around the grid\n * Can also add onClick and onContextMenu handlers to add custom functionality and menus.\n */\nclass Grid extends PureComponent<GridProps, GridState> {\n static defaultProps = {\n canvasOptions: { alpha: false } as CanvasRenderingContext2DSettings,\n isStickyBottom: false,\n isStickyRight: false,\n isStuckToBottom: false,\n isStuckToRight: false,\n keyHandlers: [] as KeyHandler[],\n mouseHandlers: [] as GridMouseHandler[],\n movedColumns: [] as MoveOperation[],\n movedRows: [] as MoveOperation[],\n onError: (): void => undefined,\n onSelectionChanged: (): void => undefined,\n onMovedColumnsChanged: (): void => undefined,\n onMoveColumnComplete: (): void => undefined,\n onMovedRowsChanged: (): void => undefined,\n onMoveRowComplete: (): void => undefined,\n onViewChanged: (): void => undefined,\n stateOverride: {} as Record<string, unknown>,\n theme: {\n autoSelectColumn: false,\n autoSelectRow: false,\n } as GridThemeType,\n };\n\n // use same constant as chrome source for windows\n // https://github.com/chromium/chromium/blob/973af9d461b6b5dc60208c8d3d66adc27e53da78/ui/events/blink/web_input_event_builders_win.cc#L285\n static pixelsPerLine = 100 / 3;\n\n static dragTimeout = 1000;\n\n static getTheme = memoize(userTheme => ({ ...GridTheme, ...userTheme }));\n\n /**\n * On some devices there may be different scaling required for high DPI. Get the scale required for the canvas.\n * @param context The canvas context\n * @returns The scale to use\n */\n static getScale(context: CanvasRenderingContext2D): number {\n const devicePixelRatio = window.devicePixelRatio || 1;\n\n // backingStorePixelRatio is deprecated, but check it just in case\n const legacyContext = context as LegacyCanvasRenderingContext2D;\n const backingStorePixelRatio =\n legacyContext.webkitBackingStorePixelRatio ||\n legacyContext.mozBackingStorePixelRatio ||\n legacyContext.msBackingStorePixelRatio ||\n legacyContext.oBackingStorePixelRatio ||\n legacyContext.backingStorePixelRatio ||\n 1;\n return devicePixelRatio / backingStorePixelRatio;\n }\n\n /**\n * Get the class name from the cursor provided\n * @param cursor The grid cursor to use\n * @returns Class name with the grid-cursor prefix or null if no cursor provided\n */\n static getCursorClassName(cursor: string | null): string | null {\n return cursor ? `grid-cursor-${cursor}` : null;\n }\n\n // Need to disable react/sort-comp so I can put the fields here\n /* eslint-disable react/sort-comp */\n renderer: GridRenderer;\n\n metricCalculator: GridMetricCalculator;\n\n canvas: HTMLCanvasElement | null;\n\n canvasContext: CanvasRenderingContext2D | null;\n\n // We draw the canvas on the next animation frame, keep track of the next one\n animationFrame: number | null;\n\n // Keep track of previous metrics and new metrics for comparison\n prevMetrics: GridMetrics | null;\n\n metrics: GridMetrics | null;\n\n // Track the cursor that is currently added to the document\n // Add to document so that when dragging the cursor stays, even if mouse leaves the canvas\n // Note: on document, not body so that cursor styling can be combined with\n // blocked pointer events that would otherwise prevent cursor styling from showing\n documentCursor: string | null;\n\n dragTimer: ReturnType<typeof setTimeout> | null;\n\n keyHandlers: KeyHandler[];\n\n mouseHandlers: GridMouseHandler[];\n\n /* eslint-enable react/sort-comp */\n\n constructor(props: GridProps) {\n super(props);\n\n this.handleClick = this.handleClick.bind(this);\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleEditCellCancel = this.handleEditCellCancel.bind(this);\n this.handleEditCellChange = this.handleEditCellChange.bind(this);\n this.handleEditCellCommit = this.handleEditCellCommit.bind(this);\n this.handleDoubleClick = this.handleDoubleClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleMouseDown = this.handleMouseDown.bind(this);\n this.handleMouseDrag = this.handleMouseDrag.bind(this);\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleMouseUp = this.handleMouseUp.bind(this);\n this.handleResize = this.handleResize.bind(this);\n this.handleWheel = this.handleWheel.bind(this);\n\n const {\n isStuckToBottom,\n isStuckToRight,\n metricCalculator,\n movedColumns,\n movedRows,\n renderer,\n } = props;\n\n this.renderer = renderer || new GridRenderer();\n this.metricCalculator = metricCalculator || new GridMetricCalculator();\n\n this.canvas = null;\n this.canvasContext = null;\n this.animationFrame = null;\n\n this.prevMetrics = null;\n this.metrics = null;\n\n // Track the cursor that is currently added to the document\n // Add to document so that when dragging the cursor stays, even if mouse leaves the canvas\n // Note: on document, not body so that cursor styling can be combined with\n // blocked pointer events that would otherwise prevent cursor styling from showing\n this.documentCursor = null;\n\n this.dragTimer = null;\n\n // specify handler ordering, such that any extensions can insert handlers in between\n this.keyHandlers = [\n new EditKeyHandler(400),\n new PasteKeyHandler(450),\n new SelectionKeyHandler(500),\n new TreeKeyHandler(900),\n ];\n this.mouseHandlers = [\n new GridRowSeparatorMouseHandler(100),\n new GridColumnSeparatorMouseHandler(200),\n new GridRowMoveMouseHandler(300),\n new GridColumnMoveMouseHandler(400),\n new EditMouseHandler(450),\n new GridVerticalScrollBarMouseHandler(500),\n new GridHorizontalScrollBarMouseHandler(600),\n new GridScrollBarCornerMouseHandler(700),\n new GridRowTreeMouseHandler(800),\n new GridSelectionMouseHandler(900),\n ];\n\n this.state = {\n // Top/left visible cell in the grid. Note that it's visible row/column index, not the model index (ie. if columns are re-ordered)\n top: 0,\n left: 0,\n\n // The scroll offset of the top/left cell. 0,0 means the cell is at the top left\n // Should be less than the width of the column\n topOffset: 0,\n leftOffset: 0,\n\n // current column/row that user is dragging\n draggingColumn: null,\n draggingRow: null,\n\n // Offset when dragging a column/row\n draggingColumnOffset: null,\n draggingRowOffset: null,\n\n // When drawing header separators for resizing\n draggingColumnSeparator: null,\n draggingRowSeparator: null,\n\n isDraggingHorizontalScrollBar: false,\n isDraggingVerticalScrollBar: false,\n\n // Anything is performing a drag, for blocking hover rendering\n isDragging: false,\n\n // The coordinates of the mouse. May be outside of the canvas\n mouseX: null,\n mouseY: null,\n\n // Move operations the user has performed on this grids columns/rows\n movedColumns,\n movedRows,\n\n // Cursor (highlighted cell) location and active selected range\n cursorRow: null,\n cursorColumn: null,\n selectionStartRow: null,\n selectionStartColumn: null,\n selectionEndRow: null,\n selectionEndColumn: null,\n\n // Currently selected ranges and previously selected ranges\n // Store the previously selected ranges to determine if the new selection should\n // deselect again (if it's the same range)\n selectedRanges: [],\n lastSelectedRanges: [],\n\n // The mouse cursor style to use when hovering over the grid element\n cursor: null,\n\n // { column: number, row: number, selectionRange: [number, number], value: string | null, isQuickEdit?: boolean }\n // The cell that is currently being edited\n editingCell: null,\n\n isStuckToBottom,\n isStuckToRight,\n };\n }\n\n componentDidMount(): void {\n this.initContext();\n\n // Need to explicitly add wheel event to canvas so we can preventDefault/avoid passive listener issue\n // Otherwise React attaches listener at doc level and you can't prevent default\n // https://github.com/facebook/react/issues/14856\n this.canvas?.addEventListener('wheel', this.handleWheel, {\n passive: false,\n });\n window.addEventListener('resize', this.handleResize);\n\n this.updateCanvasScale();\n this.updateCanvas();\n }\n\n componentDidUpdate(prevProps: GridProps, prevState: GridState): void {\n const {\n isStickyBottom,\n isStickyRight,\n movedColumns,\n movedRows,\n onMovedColumnsChanged,\n onMoveColumnComplete,\n onMovedRowsChanged,\n onMoveRowComplete,\n } = this.props;\n const {\n isStickyBottom: prevIsStickyBottom,\n isStickyRight: prevIsStickyRight,\n movedColumns: prevPropMovedColumns,\n movedRows: prevPropMovedRows,\n } = prevProps;\n const {\n movedColumns: prevStateMovedColumns,\n movedRows: prevStateMovedRows,\n } = prevState;\n const {\n draggingColumn,\n draggingRow,\n movedColumns: currentStateMovedColumns,\n movedRows: currentStateMovedRows,\n } = this.state;\n\n if (prevPropMovedColumns !== movedColumns) {\n this.setState({ movedColumns });\n }\n\n if (prevPropMovedRows !== movedRows) {\n this.setState({ movedRows });\n }\n\n if (prevStateMovedColumns !== currentStateMovedColumns) {\n onMovedColumnsChanged(currentStateMovedColumns);\n }\n\n if (prevState.draggingColumn != null && draggingColumn == null) {\n onMoveColumnComplete(currentStateMovedColumns);\n }\n\n if (prevStateMovedRows !== currentStateMovedRows) {\n onMovedRowsChanged(currentStateMovedRows);\n }\n\n if (prevState.draggingRow != null && draggingRow == null) {\n onMoveRowComplete(currentStateMovedRows);\n }\n\n if (isStickyBottom !== prevIsStickyBottom) {\n this.setState({ isStuckToBottom: false });\n }\n\n if (isStickyRight !== prevIsStickyRight) {\n this.setState({ isStuckToRight: false });\n }\n\n this.updateMetrics();\n\n this.requestUpdateCanvas();\n\n if (!this.metrics || !this.prevMetrics) {\n return;\n }\n\n const {\n bottomVisible,\n rightVisible,\n rowCount,\n columnCount,\n top,\n left,\n height,\n width,\n } = this.metrics;\n const {\n rowCount: prevRowCount,\n columnCount: prevColumnCount,\n height: prevHeight,\n width: prevWidth,\n } = this.prevMetrics;\n const metricState = this.getMetricState();\n\n if (prevRowCount !== rowCount || height !== prevHeight) {\n const lastTop = this.metricCalculator.getLastTop(metricState);\n const { isStuckToBottom } = this.state;\n if (\n (isStuckToBottom &&\n bottomVisible < rowCount - 1 &&\n bottomVisible > 0) ||\n top > lastTop\n ) {\n this.setState({ top: lastTop });\n }\n }\n\n if (prevColumnCount !== columnCount || width !== prevWidth) {\n const lastLeft = this.metricCalculator.getLastLeft(metricState);\n const { isStuckToRight } = this.state;\n if (\n (isStuckToRight &&\n rightVisible < columnCount - 1 &&\n rightVisible > 0) ||\n left > lastLeft\n ) {\n this.setState({ left: lastLeft });\n }\n }\n\n if (this.validateSelection()) {\n this.checkSelectionChange(prevState);\n }\n }\n\n componentWillUnmount(): void {\n if (this.animationFrame != null) {\n cancelAnimationFrame(this.animationFrame);\n }\n\n this.canvas?.removeEventListener('wheel', this.handleWheel);\n\n window.removeEventListener(\n 'mousemove',\n (this.handleMouseDrag as unknown) as EventListenerOrEventListenerObject,\n true\n );\n window.removeEventListener(\n 'mouseup',\n (this.handleMouseUp as unknown) as EventListenerOrEventListenerObject,\n true\n );\n window.removeEventListener('resize', this.handleResize);\n\n this.stopDragTimer();\n }\n\n getTheme(): GridThemeType {\n const { theme } = this.props;\n return Grid.getTheme(theme);\n }\n\n getGridPointFromEvent(event: GridMouseEvent): GridPoint {\n assertIsDefined(this.canvas);\n\n const rect = this.canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n return this.getGridPointFromXY(x, y);\n }\n\n getGridPointFromXY(x: Coordinate, y: Coordinate): GridPoint {\n if (!this.metrics) throw new Error('metrics must be set');\n\n return GridUtils.getGridPointFromXY(x, y, this.metrics);\n }\n\n getMetricState(state = this.state): GridMetricState {\n const theme = this.getTheme();\n const { model, stateOverride } = this.props;\n if (!this.canvasContext || !this.canvas) {\n throw new Error('Canvas and context must be defined to get metrics');\n }\n const context = this.canvasContext;\n const width = this.canvas.clientWidth;\n const height = this.canvas.clientHeight;\n const {\n left,\n top,\n leftOffset,\n topOffset,\n movedColumns,\n movedRows,\n isDraggingHorizontalScrollBar,\n isDraggingVerticalScrollBar,\n } = state;\n\n return {\n left,\n top,\n leftOffset,\n topOffset,\n width,\n height,\n context,\n theme,\n model,\n movedColumns,\n movedRows,\n isDraggingHorizontalScrollBar,\n isDraggingVerticalScrollBar,\n ...stateOverride,\n };\n }\n\n getCachedKeyHandlers = memoize((keyHandlers: KeyHandler[]) =>\n [...keyHandlers, ...this.keyHandlers].sort((a, b) => a.order - b.order)\n );\n\n getKeyHandlers(): KeyHandler[] {\n const { keyHandlers } = this.props;\n return this.getCachedKeyHandlers(keyHandlers);\n }\n\n getCachedMouseHandlers = memoize((mouseHandlers: GridMouseHandler[]) =>\n [...mouseHandlers, ...this.mouseHandlers].sort((a, b) => a.order - b.order)\n );\n\n getMouseHandlers(): GridMouseHandler[] {\n const { mouseHandlers } = this.props;\n return this.getCachedMouseHandlers(mouseHandlers);\n }\n\n /**\n * Translate from the provided visible index to the model index\n * @param columnIndex The column index to get the model for\n * @returns The model index\n */\n getModelColumn(columnIndex: VisibleIndex): ModelIndex {\n const modelIndex = this.metrics?.modelColumns?.get(columnIndex);\n if (modelIndex === undefined) {\n throw new Error(`Unable to get ModelIndex for column ${columnIndex}`);\n }\n return modelIndex;\n }\n\n /**\n * Translate from the provided visible index to the model index\n * @param rowIndex The row index to get the model for\n * @returns The model index\n */\n getModelRow(rowIndex: VisibleIndex): ModelIndex {\n const modelIndex = this.metrics?.modelRows?.get(rowIndex);\n if (modelIndex === undefined) {\n throw new Error(`Unable to get ModelIndex for row ${rowIndex}`);\n }\n return modelIndex;\n }\n\n /**\n * Toggle a row between expanded and collapsed states\n * @param row The row to toggle expansion for\n */\n toggleRowExpanded(row: VisibleIndex): void {\n const modelRow = this.getModelRow(row);\n const { model } = this.props;\n // We only want to set expansion if the row is expandable\n // If it's not, still move the cursor to that position, as it may be outside of the current viewport and we don't know if it's expandable yet\n if (isExpandableGridModel(model) && model.isRowExpandable(modelRow)) {\n model.setRowExpanded(modelRow, !model.isRowExpanded(modelRow));\n }\n this.clearSelectedRanges();\n this.commitSelection(); // Need to commit before moving in case we're selecting same row again\n this.moveCursorToPosition(0, row);\n this.commitSelection();\n\n this.setState({ isStuckToBottom: false });\n }\n\n /**\n * Allows the selected ranges to be set programatically\n * Will update the cursor and selection start/end based on the new ranges\n * @param gridRanges The new selected ranges to set\n */\n setSelectedRanges(gridRanges: GridRange[]): void {\n const { model } = this.props;\n const { columnCount, rowCount } = model;\n const { cursorRow, cursorColumn, selectedRanges } = this.state;\n this.setState({\n selectedRanges: gridRanges,\n lastSelectedRanges: selectedRanges,\n });\n if (gridRanges.length > 0) {\n const range = GridRange.boundedRange(\n gridRanges[0],\n columnCount,\n rowCount\n );\n let newCursorRow = cursorRow;\n let newCursorColumn = cursorColumn;\n if (!range.containsCell(cursorColumn, cursorRow)) {\n ({ row: newCursorRow, column: newCursorColumn } = range.startCell());\n }\n\n this.setState({\n selectionStartColumn: range.startColumn,\n selectionStartRow: range.startRow,\n selectionEndColumn: range.endColumn,\n selectionEndRow: range.endRow,\n cursorColumn: newCursorColumn,\n cursorRow: newCursorRow,\n });\n }\n }\n\n initContext(): void {\n const { canvas } = this;\n const { canvasOptions } = this.props;\n\n if (!canvas) throw new Error('Canvas not set');\n\n this.canvasContext = canvas.getContext('2d', canvasOptions);\n }\n\n requestUpdateCanvas(): void {\n if (this.animationFrame != null) {\n return;\n }\n\n this.animationFrame = requestAnimationFrame(() => {\n this.animationFrame = null;\n\n if (!this.metrics) throw new Error('Metrics not set');\n\n this.updateCanvas(this.metrics);\n });\n }\n\n updateCanvas(metrics = this.updateMetrics()): void {\n this.updateCanvasScale();\n\n const { onViewChanged } = this.props;\n onViewChanged(metrics);\n\n this.drawCanvas(metrics);\n }\n\n updateCanvasScale(): void {\n const { canvas, canvasContext } = this;\n if (!canvas) throw new Error('canvas not set');\n if (!canvasContext) throw new Error('canvasContext not set');\n if (!canvas.parentElement) throw new Error('Canvas has no parent element');\n\n const scale = Grid.getScale(canvasContext);\n // the parent wrapper has 100% width/height, and is used for determining size\n // we don't want to stretch the canvas to 100%, to avoid fractional pixels.\n // A wrapper element must be used for sizing, and canvas size must be\n // set manually to a floored value in css and a scaled value in width/height\n const { width, height } = canvas.parentElement.getBoundingClientRect();\n canvas.style.width = `${Math.floor(width)}px`;\n canvas.style.height = `${Math.floor(height)}px`;\n canvas.width = Math.floor(width) * scale;\n canvas.height = Math.floor(height) * scale;\n canvasContext.scale(scale, scale);\n }\n\n updateMetrics(state = this.state): GridMetrics {\n this.prevMetrics = this.metrics;\n\n const { metricCalculator } = this;\n const metricState = this.getMetricState(state);\n this.metrics = metricCalculator.getMetrics(metricState);\n\n return this.metrics;\n }\n\n /**\n * Check if the selection state has changed, and call the onSelectionChanged callback if they have\n * @param prevState The previous grid state\n */\n checkSelectionChange(prevState: GridState): void {\n const { selectedRanges: oldSelectedRanges } = prevState;\n const { selectedRanges } = this.state;\n\n if (selectedRanges !== oldSelectedRanges) {\n const { onSelectionChanged } = this.props;\n onSelectionChanged(selectedRanges);\n }\n }\n\n /**\n * Validate the current selection, and reset if it is invalid\n * @returns True if the selection is valid, false if the selection was invalid and has been reset\n */\n validateSelection(): boolean {\n const { model } = this.props;\n const { selectedRanges } = this.state;\n const { columnCount, rowCount } = model;\n\n for (let i = 0; i < selectedRanges.length; i += 1) {\n const range = selectedRanges[i];\n if (\n (range.endColumn != null && range.endColumn >= columnCount) ||\n (range.endRow != null && range.endRow >= rowCount)\n ) {\n // Just clear the selection rather than trying to trim it.\n this.setState({ selectedRanges: [], lastSelectedRanges: [] });\n return false;\n }\n }\n return true;\n }\n\n /**\n * Clears all selected ranges\n */\n clearSelectedRanges(): void {\n const { selectedRanges } = this.state;\n this.setState({ selectedRanges: [], lastSelectedRanges: selectedRanges });\n }\n\n /** Clears all but the last selected range */\n trimSelectedRanges(): void {\n const { selectedRanges } = this.state;\n if (selectedRanges.length > 0) {\n this.setState({\n selectedRanges: selectedRanges.slice(selectedRanges.length - 1),\n });\n }\n }\n\n /**\n * Begin a selection operation at the provided location\n * @param column Column where the selection is beginning\n * @param row Row where the selection is beginning\n */\n beginSelection(column: GridRangeIndex, row: GridRangeIndex): void {\n this.setState({\n selectionStartColumn: column,\n selectionStartRow: row,\n selectionEndColumn: column,\n selectionEndRow: row,\n cursorColumn: column,\n cursorRow: row,\n });\n }\n\n /**\n * Moves the selection to the cell specified\n * @param column The column index to move the cursor to\n * @param row The row index to move the cursor to\n * @param extendSelection Whether to extend the current selection (eg. holding Shift)\n * @param maximizePreviousRange When true, maximize/add to the previous range only, ignoring where the selection was started.\n */\n moveSelection(\n column: GridRangeIndex,\n row: GridRangeIndex,\n extendSelection = false,\n maximizePreviousRange = false\n ): void {\n this.setState(state => {\n const { selectedRanges, selectionStartRow, selectionStartColumn } = state;\n const { theme } = this.props;\n const { autoSelectRow, autoSelectColumn } = theme;\n\n if (extendSelection && selectedRanges.length > 0) {\n const lastSelectedRange = selectedRanges[selectedRanges.length - 1];\n let left = null;\n let top = null;\n let right = null;\n let bottom = null;\n if (maximizePreviousRange) {\n left = autoSelectRow\n ? null\n : Math.min(column ?? 0, lastSelectedRange.startColumn ?? 0);\n top = autoSelectColumn\n ? null\n : Math.min(row ?? 0, lastSelectedRange.startRow ?? 0);\n right = autoSelectRow\n ? null\n : Math.max(column ?? 0, lastSelectedRange.endColumn ?? 0);\n bottom = autoSelectColumn\n ? null\n : Math.max(row ?? 0, lastSelectedRange.endRow ?? 0);\n } else {\n left = lastSelectedRange.startColumn;\n top = lastSelectedRange.startRow;\n\n if (selectionStartColumn != null || selectionStartRow != null) {\n if (!autoSelectRow) {\n left = selectionStartColumn;\n }\n if (!autoSelectColumn) {\n top = selectionStartRow;\n }\n }\n right = autoSelectRow ? null : column;\n bottom = autoSelectColumn ? null : row;\n }\n const selectedRange = GridRange.makeNormalized(\n left,\n top,\n right,\n bottom\n );\n\n if (lastSelectedRange.equals(selectedRange)) {\n return null;\n }\n\n const newRanges = [...selectedRanges];\n newRanges[newRanges.length - 1] = selectedRange;\n return {\n selectedRanges: newRanges,\n selectionEndColumn: column,\n selectionEndRow: row,\n };\n }\n const newRanges = [...selectedRanges];\n const selectedColumn = autoSelectRow ? null : column;\n const selectedRow = autoSelectColumn ? null : row;\n newRanges.push(\n GridRange.makeNormalized(\n selectedColumn,\n selectedRow,\n selectedColumn,\n selectedRow\n )\n );\n return {\n selectedRanges: newRanges,\n selectionEndColumn: column,\n selectionEndRow: row,\n };\n });\n }\n\n /**\n * Commits the last selected range to the selected ranges.\n * First checks if the last range is completely contained within another range, and if it\n * is then it blows those ranges apart.\n * Then it consolidates all the selected ranges, reducing them.\n */\n commitSelection(): void {\n this.setState((state: GridState) => {\n const { theme } = this.props;\n const { autoSelectRow } = theme;\n const {\n selectedRanges,\n lastSelectedRanges,\n cursorRow,\n cursorColumn,\n } = state;\n\n if (\n selectedRanges.length === 1 &&\n (autoSelectRow\n ? GridRange.rowCount(selectedRanges) === 1\n : GridRange.cellCount(selectedRanges) === 1) &&\n GridRange.rangeArraysEqual(selectedRanges, lastSelectedRanges)\n ) {\n // If it's the exact same single selection, then deselect.\n // For if we click on one cell multiple times.\n return {\n selectedRanges: [],\n lastSelectedRanges: [],\n cursorColumn,\n cursorRow,\n };\n }\n\n let newSelectedRanges = selectedRanges.slice();\n if (newSelectedRanges.length > 1) {\n // Check if the latest selection is entirely within a previously selected range\n // If that's the case, then deselect that section instead\n const lastRange = newSelectedRanges[newSelectedRanges.length - 1];\n for (let i = 0; i < newSelectedRanges.length - 1; i += 1) {\n const selectedRange = newSelectedRanges[i];\n if (selectedRange.contains(lastRange)) {\n // We found a match, now remove the two matching ranges, and add back\n // the remainder of the two\n const remainder = selectedRange.subtract(lastRange);\n newSelectedRanges.pop();\n newSelectedRanges.splice(i, 1);\n newSelectedRanges = newSelectedRanges.concat(remainder);\n break;\n }\n }\n\n newSelectedRanges = GridRange.consolidate(newSelectedRanges);\n }\n\n let newCursorColumn = cursorColumn;\n let newCursorRow = cursorRow;\n if (!GridRange.containsCell(newSelectedRanges, cursorColumn, cursorRow)) {\n const { model } = this.props;\n const { columnCount, rowCount } = model;\n const nextCursor = GridRange.nextCell(\n GridRange.boundedRanges(selectedRanges, columnCount, rowCount)\n );\n if (nextCursor != null) {\n ({ column: newCursorColumn, row: newCursorRow } = nextCursor);\n } else {\n newCursorColumn = null;\n newCursorRow = null;\n }\n }\n return {\n cursorRow: newCursorRow,\n cursorColumn: newCursorColumn,\n selectedRanges: newSelectedRanges,\n lastSelectedRanges: selectedRanges,\n };\n });\n }\n\n /**\n * Set the selection to the entire grid\n */\n selectAll(): void {\n const { model, theme } = this.props;\n const { autoSelectRow, autoSelectColumn } = theme;\n\n const top = autoSelectColumn ? null : 0;\n const bottom = autoSelectColumn ? null : model.rowCount - 1;\n const left = autoSelectRow ? null : 0;\n const right = autoSelectRow ? null : model.columnCount - 1;\n this.setSelectedRanges([new GridRange(left, top, right, bottom)]);\n }\n\n /**\n * Move the cursor in relation to the current cursor position\n * @param deltaColumn Number of columns to move the cursor\n * @param deltaRow Number of rows to move the cursor\n * @param extendSelection True if the current selection should be extended, false to start a new selection\n */\n moveCursor(\n deltaColumn: number,\n deltaRow: number,\n extendSelection: boolean\n ): void {\n const {\n cursorRow,\n cursorColumn,\n selectionEndColumn,\n selectionEndRow,\n } = this.state;\n const column = extendSelection ? selectionEndColumn : cursorColumn;\n const row = extendSelection ? selectionEndRow : cursorRow;\n if (row === null || column === null) {\n const { left, top } = this.state;\n this.moveCursorToPosition(left, top, extendSelection);\n } else {\n const { model } = this.props;\n const { columnCount, rowCount } = model;\n\n const left = clamp(column + deltaColumn, 0, columnCount - 1);\n const top = clamp(row + deltaRow, 0, rowCount - 1);\n this.moveCursorToPosition(left, top, extendSelection);\n }\n }\n\n /**\n * Move the cursor in the provided selection direction\n * @param direction The direction to move the cursor in\n */\n moveCursorInDirection(direction = GridRange.SELECTION_DIRECTION.DOWN): void {\n const { model } = this.props;\n const { columnCount, rowCount } = model;\n const { cursorRow, cursorColumn, selectedRanges } = this.state;\n const ranges =\n selectedRanges.length > 0\n ? selectedRanges\n : [GridRange.makeCell(cursorColumn, cursorRow)];\n let nextCursor = null;\n if (ranges.length === 1 && GridRange.cellCount(ranges) === 1) {\n // If we only have one cell selected, we want to update the cursor and we want to update the selected cells\n const gridRange = new GridRange(0, 0, columnCount - 1, rowCount - 1);\n nextCursor =\n gridRange.nextCell(cursorColumn, cursorRow, direction) ??\n gridRange.startCell(direction);\n } else {\n nextCursor = GridRange.nextCell(\n GridRange.boundedRanges(ranges, columnCount, rowCount),\n cursorColumn,\n cursorRow,\n direction\n );\n }\n\n if (nextCursor != null) {\n const { column, row } = nextCursor;\n this.setState({\n cursorColumn: column,\n cursorRow: row,\n });\n\n if (!GridRange.containsCell(selectedRanges, column, row)) {\n this.setState({\n selectedRanges: [GridRange.makeCell(column, row)],\n selectionStartColumn: column,\n selectionStartRow: row,\n selectionEndColumn: column,\n selectionEndRow: row,\n });\n }\n\n this.moveViewToCell(nextCursor.column, nextCursor.row);\n }\n }\n\n /**\n * Move a cursor to the specified position in the grid.\n * @param column The column index to move the cursor to\n * @param row The row index to move the cursor to\n * @param extendSelection Whether to extend the current selection (eg. holding Shift)\n * @param keepCursorInView Whether to move the viewport so that the cursor is in view\n * @param maximizePreviousRange With this and `extendSelection` true, it will maximize/add to the previous range only, ignoring where the selection was started\n */\n moveCursorToPosition(\n column: GridRangeIndex,\n row: GridRangeIndex,\n extendSelection = false,\n keepCursorInView = true,\n maximizePreviousRange = false\n ): void {\n if (!extendSelection) {\n this.beginSelection(column, row);\n }\n\n this.moveSelection(column, row, extendSelection, maximizePreviousRange);\n\n if (keepCursorInView) {\n this.moveViewToCell(column, row);\n }\n }\n\n /**\n * Moves the view to make the specified cell visible\n *\n * @param column The column index to bring into view\n * @param row The row index to bring into view\n */\n moveViewToCell(column: GridRangeIndex, row: GridRangeIndex): void {\n if (!this.metrics) throw new Error('metrics not set');\n\n const { metricCalculator } = this;\n const {\n bottomVisible,\n rightVisible,\n topVisible,\n leftVisible,\n } = this.metrics;\n const metricState = this.getMetricState(this.state);\n let { top, left, topOffset, leftOffset } = this.state;\n\n if (row != null && !GridUtils.isFloatingRow(row, this.metrics)) {\n if (row < topVisible) {\n top = metricCalculator.getTopForTopVisible(metricState, row);\n topOffset = 0;\n } else if (row > bottomVisible) {\n top = metricCalculator.getTopForBottomVisible(metricState, row);\n topOffset = 0;\n }\n }\n\n if (column != null && !GridUtils.isFloatingColumn(column, this.metrics)) {\n if (column < leftVisible) {\n left = metricCalculator.getLeftForLeftVisible(metricState, column);\n leftOffset = 0;\n } else if (column > rightVisible) {\n left = metricCalculator.getLeftForRightVisible(metricState, column);\n leftOffset = 0;\n }\n }\n\n this.setViewState({ top, left, topOffset, leftOffset });\n }\n\n /**\n * Checks the `top` and `left` properties that are set and updates the isStuckToBottom/Right properties\n * Should be called when user interaction occurs\n * @param viewState New state properties to set.\n * @param forceUpdate Whether to force an update.\n */\n setViewState(viewState: Partial<GridState>, forceUpdate = false): void {\n if (!this.metrics) throw new Error('metrics not set');\n\n const { isStickyBottom, isStickyRight } = this.props;\n const { top, left } = viewState;\n const { lastTop, lastLeft } = this.metrics;\n if (top != null) {\n this.setState({ isStuckToBottom: isStickyBottom && top >= lastTop });\n }\n if (left != null) {\n this.setState({ isStuckToRight: isStickyRight && left >= lastLeft });\n }\n\n this.setState(viewState as GridState);\n if (forceUpdate) {\n this.forceUpdate();\n }\n }\n\n /**\n * Start editing the data at the given index\n *\n * @param column The visible column index to start editing\n * @param row The visible row index to start editing\n * @param isQuickEdit If this is a quick edit (the arrow keys can commit)\n * @param selectionRange The tuple [start,end] text selection range of the value to select when editing\n * @param value The value to start with in the edit field. Leave undefined to use the current value.\n */\n startEditing(\n column: VisibleIndex,\n row: VisibleIndex,\n isQuickEdit = false,\n selectionRange?: EditingCellTextSelectionRange,\n value?: string\n ): void {\n const { model } = this.props;\n if (!isEditableGridModel(model)) throw new Error('model is not editable');\n\n const modelColumn = this.getModelColumn(column);\n const modelRow = this.getModelRow(row);\n const cell = {\n column,\n row,\n selectionRange,\n value:\n value !== undefined\n ? value\n : model.editValueForCell(modelColumn, modelRow),\n isQuickEdit,\n };\n\n this.setState({ editingCell: cell, cursorColumn: column, cursorRow: row });\n this.moveViewToCell(column, row);\n }\n\n /**\n * Check if a value is valid for a specific cell\n * @param column Column index of the cell to check\n * @param row Row index of the cell to check\n * @param value Value to check\n * @returns True if the value is valid for the provided cell, false otherwise\n */\n isValidForCell(\n column: VisibleIndex,\n row: VisibleIndex,\n value: string\n ): boolean {\n const { model } = this.props;\n\n const modelColumn = this.getModelColumn(column);\n const modelRow = this.getModelRow(row);\n return (\n isEditableGridModel(model) &&\n model.isValidForCell(modelColumn, modelRow, value)\n );\n }\n\n /**\n * Paste a value with the current selection\n * It first needs to validate that the pasted table is valid for the given selection.\n * Also may update selection if single cells are selected and a table is pasted.\n * @param value Table or a string that is being pasted\n */\n async pasteValue(value: string[][] | string): Promise<void> {\n const { model } = this.props;\n const { movedColumns, movedRows, selectedRanges } = this.state;\n\n try {\n assertIsEditableGridModel(model);\n\n if (\n !model.isEditable ||\n !selectedRanges.every(range => model.isEditableRange(range))\n ) {\n throw new PasteError(\"Can't paste in to read-only area.\");\n }\n\n if (selectedRanges.length <= 0) {\n throw new PasteError('Select an area to paste to.');\n }\n\n if (typeof value === 'string') {\n // Just paste the value into all the selected cells\n const edits: EditOperation[] = [];\n\n const modelRanges = GridUtils.getModelRanges(\n selectedRanges,\n movedColumns,\n movedRows\n );\n GridRange.forEachCell(modelRanges, (column, row) => {\n edits.push({ column, row, text: value });\n });\n await model.setValues(edits);\n return;\n }\n\n // Otherwise it's a table of data\n const tableHeight = value.length;\n const tableWidth = value[0].length;\n const { columnCount, rowCount } = model;\n let ranges = selectedRanges;\n // If each cell is a single selection, we need to update the selection to map to the newly pasted data\n if (\n ranges.every(\n range =>\n GridRange.cellCount([range]) === 1 &&\n (range.startColumn ?? 0) + tableWidth <= columnCount &&\n (range.startRow ?? 0) + tableHeight <= rowCount\n )\n ) {\n // Remap the selected ranges\n ranges = ranges.map(\n range =>\n new GridRange(\n range.startColumn,\n range.startRow,\n (range.startColumn ?? 0) + tableWidth - 1,\n (range.startRow ?? 0) + tableHeight - 1\n )\n );\n this.setSelectedRanges(ranges);\n }\n\n if (\n !ranges.every(\n range =>\n GridRange.rowCount([range]) === tableHeight &&\n GridRange.columnCount([range]) === tableWidth\n )\n ) {\n throw new PasteError('Copy and paste area are not same size.');\n }\n\n const edits: EditOperation[] = [];\n ranges.forEach(range => {\n for (let x = 0; x < tableWidth; x += 1) {\n for (let y = 0; y < tableHeight; y += 1) {\n edits.push({\n column: (range.startColumn ?? 0) + x,\n row: (range.startRow ?? 0) + y,\n text: value[y][x],\n });\n }\n }\n });\n await model.setValues(edits);\n } catch (e) {\n const { onError } = this.props;\n onError(e instanceof Error ? e : new Error(`${e}`));\n }\n }\n\n /**\n * Set a value to a specific cell. If the value is not valid for that cell, do not set it\n * @param column Column index to set the value for\n * @param row Row index to set the value for\n * @param value Value to set at that cell\n * @returns true If the value was valid and attempted to be set, false is it was not valid\n */\n setValueForCell(\n column: VisibleIndex,\n row: VisibleIndex,\n value: string\n ): boolean {\n const { model } = this.props;\n assertIsEditableGridModel(model);\n\n const modelColumn = this.getModelColumn(column);\n const modelRow = this.getModelRow(row);\n if (model.isValidForCell(modelColumn, modelRow, value)) {\n model.setValueForCell(modelColumn, modelRow, value);\n return true;\n }\n return false;\n }\n\n /**\n * Set a value on all the ranges provided\n * @param ranges Ranges to set\n * @param value The value to set on all the ranges\n */\n setValueForRanges(ranges: GridRange[], value: string): void {\n const { model } = this.props;\n const { movedColumns, movedRows } = this.state;\n\n const modelRanges = GridUtils.getModelRanges(\n ranges,\n movedColumns,\n movedRows\n );\n if (isEditableGridModel(model)) {\n model.setValueForRanges(modelRanges, value);\n }\n }\n\n /**\n * Check if a given cell is within the current selection\n * @param row Row to check\n * @param column Column to check\n * @returns True if the cell is in the current selection, false otherwise\n */\n isSelected(row: VisibleIndex, column: VisibleIndex): boolean {\n const { selectedRanges } = this.state;\n\n for (let i = 0; i < selectedRanges.length; i += 1) {\n const selectedRange = selectedRanges[i];\n const rowSelected =\n selectedRange.startRow === null ||\n (selectedRange.startRow <= row && row <= (selectedRange.endRow ?? 0));\n const columnSelected =\n selectedRange.startColumn === null ||\n (selectedRange.startColumn <= column &&\n column <= (selectedRange.endColumn ?? 0));\n if (rowSelected && columnSelected) {\n return true;\n }\n }\n\n return false;\n }\n\n addDocumentCursor(cursor: string | null = null): void {\n if (this.documentCursor === Grid.getCursorClassName(cursor)) return;\n if (this.documentCursor) {\n document.documentElement.classList.remove(this.documentCursor);\n }\n this.documentCursor = Grid.getCursorClassName(cursor);\n if (this.documentCursor) {\n document.documentElement.classList.add(this.documentCursor);\n }\n document.documentElement.classList.add('grid-block-events');\n }\n\n removeDocumentCursor(): void {\n if (this.documentCursor) {\n document.documentElement.classList.remove(this.documentCursor);\n document.documentElement.classList.remove('grid-block-events');\n this.documentCursor = null;\n }\n }\n\n startDragTimer(event: React.MouseEvent): void {\n this.stopDragTimer();\n\n const mouseEvent = new MouseEvent('custom', event.nativeEvent);\n\n this.dragTimer = setTimeout(() => {\n this.handleMouseDrag(mouseEvent);\n }, Grid.dragTimeout);\n }\n\n stopDragTimer(): void {\n if (this.dragTimer) {\n clearTimeout(this.dragTimer);\n this.dragTimer = null;\n }\n }\n\n /**\n * Draw the grid with the metrics provided\n * When scrolling you've have to re-draw the whole canvas. As a consequence, all these drawing methods\n * must be very quick.\n * @param metrics Metrics to use for rendering the grid\n */\n drawCanvas(metrics = this.updateMetrics()): void {\n if (!this.canvas) throw new Error('canvas is not set');\n if (!this.canvasContext) throw new Error('context not set');\n\n const {\n left,\n top,\n cursorColumn,\n cursorRow,\n draggingColumn,\n draggingColumnOffset,\n draggingColumnSeparator,\n draggingRow,\n draggingRowOffset,\n draggingRowSeparator,\n editingCell,\n isDraggingHorizontalScrollBar,\n isDraggingVerticalScrollBar,\n isDragging,\n mouseX,\n mouseY,\n selectedRanges,\n } = this.state;\n const { model, stateOverride } = this.props;\n const { renderer } = this;\n const context = this.canvasContext;\n const theme = this.getTheme();\n const width = this.canvas.clientWidth;\n const height = this.canvas.clientHeight;\n const renderState = {\n left,\n top,\n width,\n height,\n context,\n theme,\n model,\n metrics,\n mouseX,\n mouseY,\n selectedRanges,\n draggingColumn,\n draggingColumnOffset,\n draggingColumnSeparator,\n draggingRow,\n draggingRowOffset,\n draggingRowSeparator,\n editingCell,\n isDraggingHorizontalScrollBar,\n isDraggingVerticalScrollBar,\n isDragging,\n cursorColumn,\n cursorRow,\n ...stateOverride,\n };\n\n context.save();\n\n renderer.drawCanvas(renderState);\n\n context.restore();\n }\n\n /**\n * Set focus to this grid element\n */\n focus(): void {\n this.canvas?.focus();\n }\n\n /**\n * Check if this grid is currently focused\n * @returns True if the active element is this grid\n */\n isFocused(): boolean {\n return document.activeElement === this.canvas;\n }\n\n /**\n * Handle a mouse click event. Pass the event to the registered mouse handlers until one handles it.\n * Focuses the grid after the click.\n * @param event The mouse event\n */\n handleClick(event: React.MouseEvent): void {\n const gridPoint = this.getGridPointFromEvent(event);\n\n const mouseHandlers = this.getMouseHandlers();\n for (let i = 0; i < mouseHandlers.length; i += 1) {\n const mouseHandler = mouseHandlers[i];\n if (mouseHandler.onClick(gridPoint, this, event)) {\n event.stopPropagation();\n event.preventDefault();\n break;\n }\n }\n\n this.canvas?.focus();\n }\n\n /**\n * Handle a mouse context menu event. Pass the event to the registered mouse handlers until one handles it.\n * @param event The mouse event triggering the context menu\n */\n handleContextMenu(event: React.MouseEvent): void {\n const gridPoint = this.getGridPointFromEvent(event);\n\n const mouseHandlers = this.getMouseHandlers();\n for (let i = 0; i < mouseHandlers.length; i += 1) {\n const mouseHandler = mouseHandlers[i];\n if (mouseHandler.onContextMenu(gridPoint, this, event)) {\n event.stopPropagation();\n event.preventDefault();\n break;\n }\n }\n }\n\n /**\n * Handle a key down event from the keyboard. Pass the event to the registered keyboard handlers until one handles it.\n * @param event Keyboard event\n */\n handleKeyDown(event: GridKeyboardEvent): void {\n const keyHandlers = this.getKeyHandlers();\n for (let i = 0; i < keyHandlers.length; i += 1) {\n const keyHandler = keyHandlers[i];\n const result = keyHandler.onDown(event, this);\n if (result) {\n const options = result as EventHandlerResultOptions;\n if (options?.stopPropagation ?? true) event.stopPropagation();\n if (options?.preventDefault ?? true) event.preventDefault();\n break;\n }\n }\n }\n\n /**\n * Notify all of the mouse handlers for this grid of a mouse event.\n * @param functionName The name of the function in the mouse handler to call\n * @param event The mouse event to notify\n * @param updateCoordinates Whether to update the mouse coordinates\n * @param addCursorToDocument Whether to add a cursor overlay or not (for dragging)\n */\n notifyMouseHandlers(\n functionName: GridMouseHandlerFunctionName,\n event: GridMouseEvent,\n updateCoordinates = true,\n addCursorToDocument = false\n ): void {\n const gridPoint = this.getGridPointFromEvent(event);\n const mouseHandlers = this.getMouseHandlers();\n let cursor = null;\n for (let i = 0; i < mouseHandlers.length; i += 1) {\n const mouseHandler = mouseHandlers[i];\n const result =\n mouseHandler[functionName] &&\n mouseHandler[functionName](gridPoint, this, event);\n if (result) {\n if (mouseHandler.cursor != null) {\n ({ cursor } = mouseHandler);\n if (addCursorToDocument) {\n this.addDocumentCursor(cursor);\n }\n }\n\n // result is bool or object, events are stopped by default\n const options = result as EventHandlerResultOptions;\n if (options?.stopPropagation ?? true) event.stopPropagation();\n if (options?.preventDefault ?? true) event.preventDefault();\n break;\n }\n }\n\n this.setState({ cursor });\n\n if (updateCoordinates) {\n const { x, y } = gridPoint;\n this.setState({ mouseX: x, mouseY: y });\n }\n }\n\n handleMouseDown(event: React.MouseEvent): void {\n window.addEventListener('mousemove', this.handleMouseDrag, true);\n window.addEventListener('mouseup', this.handleMouseUp, true);\n\n if (event.button != null && event.button !== 0) {\n return;\n }\n\n this.notifyMouseHandlers('onDown', event);\n\n this.startDragTimer(event);\n }\n\n handleDoubleClick(event: React.MouseEvent): void {\n this.notifyMouseHandlers('onDoubleClick', event);\n }\n\n handleMouseMove(event: React.MouseEvent): void {\n this.notifyMouseHandlers('onMove', event);\n }\n\n handleMouseLeave(event: React.MouseEvent): void {\n this.notifyMouseHandlers('onLeave', event, false);\n this.setState({ mouseX: null, mouseY: null });\n }\n\n handleMouseDrag(event: MouseEvent): void {\n this.setState({ isDragging: true });\n this.notifyMouseHandlers('onDrag', event, true, true);\n\n this.stopDragTimer();\n }\n\n handleMouseUp(event: MouseEvent): void {\n window.removeEventListener('mousemove', this.handleMouseDrag, true);\n window.removeEventListener('mouseup', this.handleMouseUp, true);\n\n if (event.button != null && event.button !== 0) {\n return;\n }\n\n this.notifyMouseHandlers('onUp', event, false);\n\n this.stopDragTimer();\n\n this.removeDocumentCursor();\n }\n\n handleResize(): void {\n /**\n * We need to always redraw the canvas in the same frame as the updateCanvasScale\n * because it clears the canvas by nature of direct dom manipulation. However,\n * We also need to verify the state/metrics, which we currently have no way\n * of doing outside of a full componentDidUpdate() call, so we force the update.\n * Ideally, we could verify state/metrics without the forced update.\n */\n this.updateCanvasScale();\n this.updateCanvas();\n this.forceUpdate();\n }\n\n handleWheel(event: WheelEvent): void {\n this.notifyMouseHandlers('onWheel', event);\n\n if (event.defaultPrevented) {\n return;\n }\n\n const { metricCalculator, metrics } = this;\n const metricState = this.getMetricState();\n\n if (!metrics) throw new Error('metrics not set');\n\n const { lastTop, lastLeft } = metrics;\n let { top, left, topOffset, leftOffset } = metrics;\n\n const theme = this.getTheme();\n\n let { deltaX, deltaY } = GridUtils.getScrollDelta(\n event,\n metrics.barWidth,\n metrics.barHeight,\n metrics.rowHeight,\n metrics.rowHeight\n );\n\n // iterate through each column to determine column width and figure out how far to scroll\n // get column width of next column to scroll to, and subract it from the remaining distance to travel\n while (deltaX !== 0) {\n leftOffset += deltaX;\n deltaX = 0;\n\n // no scrolling needed, at directional edge\n if (\n (leftOffset > 0 && left >= lastLeft) ||\n (leftOffset < 0 && left <= 0)\n ) {\n leftOffset = 0;\n break;\n }\n\n if (leftOffset > 0) {\n // scroll right\n\n // get width of next column\n const columnWidth =\n metrics.visibleColumnWidths.get(left) ??\n metricCalculator.getVisibleColumnWidth(left, metricState);\n\n if (leftOffset >= columnWidth) {\n // remove width from balance and advance by 1 column\n deltaX = leftOffset - columnWidth;\n leftOffset = 0;\n left += 1;\n } else if (theme.scrollSnapToColumn) {\n // if there's still a balance to travel but its less then a column and snapping is on\n leftOffset = 0;\n left += 1;\n }\n } else if (leftOffset < 0) {\n // scroll left\n\n // get width of next column\n const columnWidth =\n metrics.visibleColumnWidths.get(left - 1) ??\n metricCalculator.getVisibleColumnWidth(left - 1, metricState);\n\n if (Math.abs(leftOffset) <= columnWidth && theme.scrollSnapToColumn) {\n // if there's still a balance to travel but its less then a column and snapping is on\n leftOffset = 0;\n left -= 1;\n } else {\n // remove width from balance and advance by 1 column\n deltaX = leftOffset + columnWidth;\n leftOffset = 0;\n left -= 1;\n }\n }\n }\n\n // iterate through each row to determine row height and figure out how far to scroll\n // get row height of next row to scroll to, and subract it from the remaining distance to travel\n while (deltaY !== 0) {\n topOffset += deltaY;\n deltaY = 0;\n\n // no scrolling needed, at directional edge\n if ((topOffset > 0 && top >= lastTop) || (topOffset < 0 && top <= 0)) {\n topOffset = 0;\n break;\n }\n\n if (topOffset > 0) {\n // scroll direction down\n\n // get height of next row\n const rowHeight =\n metrics.visibleRowHeights.get(top) ??\n metricCalculator.getVisibleRowHeight(top, metricState);\n\n if (topOffset >= rowHeight) {\n // remove height from balance and advance by 1 row\n deltaY = topOffset - rowHeight;\n topOffset = 0;\n top += 1;\n } else if (theme.scrollSnapToRow) {\n // if there's still a balance to travel but its less then a row and snapping is on\n topOffset = 0;\n top += 1;\n }\n } else if (topOffset < 0) {\n // scroll direction up\n\n // get height of next row\n const rowHeight =\n metrics.visibleRowHeights.get(top - 1) ??\n metricCalculator.getVisibleRowHeight(top - 1, metricState);\n\n if (Math.abs(topOffset) <= rowHeight && theme.scrollSnapToRow) {\n // if there's still a balance to travel but its less then a row and snapping is on\n topOffset = 0;\n top -= 1;\n } else {\n // remove height from balance and advance by 1 row\n deltaY = topOffset + rowHeight;\n topOffset = 0;\n top -= 1;\n }\n }\n }\n\n this.setViewState({ top, left, leftOffset, topOffset });\n\n event.stopPropagation();\n event.preventDefault();\n }\n\n /**\n * Handle cancelling the cell edit action\n */\n handleEditCellCancel(): void {\n this.setState({ editingCell: null });\n this.focus();\n }\n\n /**\n * Handle a change in the value in an editing cell\n * @param value New value set\n */\n handleEditCellChange(value: string): void {\n this.setState(({ editingCell }) => {\n try {\n assertIsDefined(editingCell);\n\n return {\n editingCell: { ...editingCell, value } as EditingCell,\n };\n } catch (e) {\n // This case should _never_ happen, since the editingCell shouldn't be null if this method is called\n const { onError } = this.props;\n onError(e instanceof Error ? e : new Error(`${e}`));\n return null;\n }\n });\n }\n\n /**\n * Commit an edit for the currently editing cell\n * @param value Value that was committed\n * @param options Options for committing\n */\n handleEditCellCommit(\n value: string,\n {\n direction = SELECTION_DIRECTION.DOWN,\n fillRange = false,\n }: { direction?: SELECTION_DIRECTION | null; fillRange?: boolean } = {}\n ): void {\n const { editingCell, selectedRanges } = this.state;\n if (!editingCell) throw new Error('editingCell not set');\n\n const { column, row } = editingCell;\n if (!this.isValidForCell(column, row, value)) {\n // Don't allow an invalid value to be commited, the editing cell should show an error\n if (direction === null) {\n // If they clicked off of the editing cell, just remove focus\n this.setState({ editingCell: null });\n }\n return;\n }\n\n if (fillRange) {\n this.setValueForRanges(selectedRanges, value);\n } else {\n this.setValueForCell(column, row, value);\n }\n\n if (direction !== null) {\n this.moveCursorInDirection(direction);\n }\n\n this.setState({ editingCell: null });\n\n this.focus();\n }\n\n renderInputField(): ReactNode {\n const { model } = this.props;\n const { editingCell } = this.state;\n const { metrics } = this;\n if (editingCell == null || metrics == null || !isEditableGridModel(model)) {\n return null;\n }\n const { selectionRange, value, isQuickEdit } = editingCell;\n const { column, row } = editingCell;\n const {\n gridX,\n gridY,\n visibleColumnXs,\n visibleRowYs,\n visibleColumnWidths,\n visibleRowHeights,\n } = metrics;\n\n const x = visibleColumnXs.get(column);\n const y = visibleRowYs.get(row);\n const w = visibleColumnWidths.get(column);\n const h = visibleRowHeights.get(row);\n\n // If the cell isn't visible, we still need to display an invisible cell for focus purposes\n const wrapperStyle: CSSProperties =\n x != null && y != null && w != null && h != null\n ? {\n position: 'absolute',\n left: gridX + x,\n top: gridY + y,\n width: w,\n height: h,\n }\n : { opacity: 0 };\n\n const modelColumn = this.getModelColumn(column);\n const modelRow = this.getModelRow(row);\n const inputStyle: CSSProperties | undefined =\n modelColumn != null && modelRow != null\n ? {\n textAlign: model.textAlignForCell(modelColumn, modelRow),\n }\n : undefined;\n const isValid = model.isValidForCell(modelColumn, modelRow, value);\n\n return (\n <div style={wrapperStyle}>\n <CellInputField\n key={`${column},${row}`}\n selectionRange={selectionRange}\n className={classNames({ error: !isValid })}\n onCancel={this.handleEditCellCancel}\n onChange={this.handleEditCellChange}\n onDone={this.handleEditCellCommit}\n isQuickEdit={isQuickEdit}\n style={inputStyle}\n value={value}\n />\n </div>\n );\n }\n\n render(): ReactNode {\n const { cursor } = this.state;\n\n return (\n <>\n <canvas\n className={classNames('grid-canvas', Grid.getCursorClassName(cursor))}\n ref={canvas => {\n this.canvas = canvas;\n }}\n onClick={this.handleClick}\n onContextMenu={this.handleContextMenu}\n onDoubleClick={this.handleDoubleClick}\n onKeyDown={this.handleKeyDown}\n onMouseDown={this.handleMouseDown}\n onMouseMove={this.handleMouseMove}\n onMouseLeave={this.handleMouseLeave}\n tabIndex={0}\n >\n Your browser does not support HTML canvas. Update your browser?\n </canvas>\n {this.renderInputField()}\n </>\n );\n }\n}\n\nexport default Grid;\n","import { EventTarget } from 'event-target-shim';\nimport { ModelIndex } from './GridMetrics';\nimport { GridColor, GridTheme, NullableGridColor } from './GridTheme';\n\n/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\n/**\n * Model for a Grid\n * All of these methods should return very quickly, as they will be called many times in the render cycle.\n * If data needs to be loaded asynchronously, return something immediately, then trigger an event for the table to refresh (Not yet implemented).\n */\nabstract class GridModel extends EventTarget {\n /** Count of rows in the grid */\n abstract get rowCount(): number;\n\n /** Count of columns in the grid */\n abstract get columnCount(): number;\n\n /** Count of rows that are frozen (or 'floating') at the top */\n get floatingTopRowCount(): number {\n return 0;\n }\n\n /** Count of rows that are frozen at the bottom */\n get floatingBottomRowCount(): number {\n return 0;\n }\n\n /** Count of columns that are frozen (or 'floating') at the left */\n get floatingLeftColumnCount(): number {\n return 0;\n }\n\n /** Count of columns that are frozen (or 'floating') at the right */\n get floatingRightColumnCount(): number {\n return 0;\n }\n\n /**\n * Get the text for the specified cell\n * @param column Column to get the text for\n * @param row Row to get the text for\n * @returns Text for the specified cell\n */\n abstract textForCell(column: ModelIndex, row: ModelIndex): string;\n\n /**\n * Get the text alignment for the specified cell\n * @param column Column to get the alignment for\n * @param row Row to get the alignment for\n * @returns Text alignment for the specified cell\n */\n textAlignForCell(column: ModelIndex, row: ModelIndex): CanvasTextAlign {\n return 'left';\n }\n\n /**\n * Get the color for the text in the specified cell\n * @param column Column to get the color for\n * @param row Row to get the color for\n * @param theme Theme applied to the grid\n * @returns Color for the text in the cell\n */\n colorForCell(\n column: ModelIndex,\n row: ModelIndex,\n theme: GridTheme\n ): GridColor {\n return theme.textColor;\n }\n\n /**\n * Get the background color for the cell\n * @param column Column to get the background color for\n * @param row Row to get the background color for\n * @param theme Theme applied to the grid\n * @returns Background color for the cell\n */\n backgroundColorForCell(\n column: ModelIndex,\n row: ModelIndex,\n theme: GridTheme\n ): NullableGridColor {\n return null;\n }\n\n /**\n * Text for the column header\n * @param column Column to get the header for\n * @returns Text to put in the column header\n */\n textForColumnHeader(column: ModelIndex): string {\n return '';\n }\n\n /**\n * Text for the row header\n * @param row Row to get the header for\n * @returns Text to put in the row header\n */\n textForRowHeader(row: ModelIndex): string {\n return '';\n }\n\n /**\n * Text for the row footer\n * @param row Row to get the footer for\n * @returns Text to put in the row footer\n */\n textForRowFooter(row: ModelIndex): string {\n return '';\n }\n\n /**\n * @param column Column to check\n * @returns True if the column is movable\n */\n isColumnMovable(column: ModelIndex): boolean {\n return true;\n }\n\n /**\n * @param row Row to check\n * @returns True if the row is movable\n */\n isRowMovable(row: ModelIndex): boolean {\n return true;\n }\n}\n\nexport default GridModel;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport EditableGridModel, { EditOperation } from './EditableGridModel';\nimport { ModelIndex } from './GridMetrics';\nimport GridModel from './GridModel';\nimport GridRange from './GridRange';\nimport { GridColor, GridTheme } from './GridTheme';\n\n/**\n * Mock model implementing GridModel for testing out grid functionality\n */\nclass MockGridModel extends GridModel implements EditableGridModel {\n protected numRows: number;\n\n protected numColumns: number;\n\n protected floatingTop: number;\n\n protected floatingBottom: number;\n\n protected floatingLeft: number;\n\n protected floatingRight: number;\n\n protected editable: boolean;\n\n protected editedData: string[][];\n\n constructor({\n rowCount = 1000000000,\n columnCount = 100,\n floatingTopRowCount = 0,\n floatingBottomRowCount = 0,\n floatingLeftColumnCount = 0,\n floatingRightColumnCount = 0,\n isEditable = false,\n editedData = [],\n } = {}) {\n super();\n\n this.numRows = rowCount;\n this.numColumns = columnCount;\n this.floatingTop = floatingTopRowCount;\n this.floatingBottom = floatingBottomRowCount;\n this.floatingLeft = floatingLeftColumnCount;\n this.floatingRight = floatingRightColumnCount;\n this.editable = isEditable;\n this.editedData = editedData;\n }\n\n get rowCount(): number {\n return this.numRows;\n }\n\n get columnCount(): number {\n return this.numColumns;\n }\n\n get floatingTopRowCount(): number {\n return this.floatingTop;\n }\n\n get floatingBottomRowCount(): number {\n return this.floatingBottom;\n }\n\n get floatingLeftColumnCount(): number {\n return this.floatingLeft;\n }\n\n get floatingRightColumnCount(): number {\n return this.floatingRight;\n }\n\n get isEditable(): boolean {\n return this.editable;\n }\n\n textForCell(column: ModelIndex, row: ModelIndex): string {\n return this.editedData[column]?.[row] ?? `${column},${row}`;\n }\n\n colorForCell(\n column: ModelIndex,\n row: ModelIndex,\n theme: GridTheme\n ): GridColor {\n return theme.textColor;\n }\n\n textForColumnHeader(column: ModelIndex): string {\n return `${column}`;\n }\n\n textForRowHeader(row: ModelIndex): string {\n return `${row}`;\n }\n\n textForRowFooter(row: ModelIndex): string {\n return `${row}`;\n }\n\n async setValueForCell(\n column: ModelIndex,\n row: ModelIndex,\n value: string\n ): Promise<void> {\n if (this.editedData[column] == null) {\n this.editedData[column] = [];\n }\n this.editedData[column][row] = `${value}`;\n }\n\n async setValueForRanges(ranges: GridRange[], text: string): Promise<void> {\n GridRange.forEachCell(ranges, (x, y) => {\n this.setValueForCell(x, y, text);\n });\n }\n\n async setValues(edits: EditOperation[]): Promise<void> {\n for (let i = 0; i < edits.length; i += 1) {\n const edit = edits[i];\n this.setValueForCell(\n edit.column ?? edit.x,\n edit.row ?? edit.y,\n edit.text\n );\n }\n }\n\n editValueForCell(column: ModelIndex, row: ModelIndex): string {\n return this.textForCell(column, row);\n }\n\n isValidForCell(column: ModelIndex, row: ModelIndex, value: string): boolean {\n return true;\n }\n\n isEditableRange(range: GridRange): boolean {\n return this.isEditable;\n }\n\n delete(ranges: GridRange[]): Promise<void> {\n throw new Error('Method not implemented.');\n }\n}\n\nexport default MockGridModel;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport MockGridModel from './MockGridModel';\nimport memoizeClear from './memoizeClear';\nimport ExpandableGridModel from './ExpandableGridModel';\nimport { ModelIndex } from './GridMetrics';\n\ntype ChildrenTreeMap = Map<ModelIndex, MockTreeGridModel>;\n\n/**\n * A class to mock a tree model so can test out tree models.\n * Whenever a row is expanded, it creates a child model for that row, which can then make a child for those rows, etc.\n */\nclass MockTreeGridModel extends MockGridModel implements ExpandableGridModel {\n static DEFAULT_ROW_COUNT = 1000000000;\n\n static DEFAULT_COLUMN_COUNT = 100;\n\n /** How many rows a child tree should have related to the parent. Eg. if parent has 10000 rows, child will have 100 */\n static DEFAULT_CHILD_ROW_COUNT_FACTOR = 0.01;\n\n static MIN_CHILD_ROW_COUNT = 10;\n\n static MAX_DEPTH = 10;\n\n private children: ChildrenTreeMap;\n\n private childRowCount: number;\n\n private maxDepth: number;\n\n constructor({\n rowCount = MockTreeGridModel.DEFAULT_ROW_COUNT,\n columnCount = MockTreeGridModel.DEFAULT_COLUMN_COUNT,\n children = new Map(),\n childRowCount = Math.ceil(\n Math.max(\n MockTreeGridModel.MIN_CHILD_ROW_COUNT,\n rowCount * MockTreeGridModel.DEFAULT_CHILD_ROW_COUNT_FACTOR\n )\n ),\n maxDepth = MockTreeGridModel.MAX_DEPTH,\n }: {\n children?: ChildrenTreeMap;\n columnCount?: number;\n rowCount?: number;\n childRowCount?: number;\n maxDepth?: number;\n } = {}) {\n super({ rowCount, columnCount });\n\n this.children = children;\n this.childRowCount = childRowCount;\n this.maxDepth = maxDepth;\n }\n\n textForCell(column: ModelIndex, row: ModelIndex): string {\n return this.getCachedTextForCell(this.children, column, row);\n }\n\n textForRowHeader(row: ModelIndex): string {\n return this.getCachedTextForRowHeader(this.children, row);\n }\n\n isRowMovable(row: ModelIndex): boolean {\n return false;\n }\n\n get hasExpandableRows(): boolean {\n return true;\n }\n\n get floatingBottomRowCount(): number {\n return 0;\n }\n\n isRowExpandable(row: ModelIndex): boolean {\n return this.getCachedIsRowExpandable(this.children, row, this.maxDepth);\n }\n\n isRowExpanded(row: ModelIndex): boolean {\n return this.getCachedIsRowExpanded(this.children, row);\n }\n\n setRowExpanded(row: ModelIndex, isExpanded: boolean): void {\n const { key, offsetRow } = this.getCachedModelRowOffset(this.children, row);\n\n // We always set a new map so that our memoize functions work properly\n const children = new Map(this.children);\n if (key != null) {\n const model = this.children.get(key);\n if (model !== undefined) {\n const { rowCount: originalChildRowCount } = model;\n model.setRowExpanded(offsetRow, isExpanded);\n this.numRows += model.rowCount - originalChildRowCount;\n }\n } else if (!isExpanded) {\n const childModel = children.get(offsetRow);\n if (childModel !== undefined) {\n this.numRows -= childModel.rowCount;\n children.delete(offsetRow);\n }\n } else {\n const child = new MockTreeGridModel({\n rowCount: this.childRowCount,\n columnCount: this.numColumns,\n });\n children.set(offsetRow, child);\n this.numRows += child.rowCount;\n }\n\n this.children = children;\n }\n\n depthForRow(row: ModelIndex): number {\n return this.getCachedDepthForRow(this.children, row);\n }\n\n /**\n * Returns the map key and the offsetRow given the provided children and row index.\n * If the returned key is null, then this offset row is within this model.\n * Only returning the key instead of the model so that memoize doesn't cache a bunch of the children models after they've been deleted (collapsed).\n */\n getCachedModelRowOffset = memoizeClear(\n (\n children: ChildrenTreeMap,\n row: ModelIndex\n ): { key: ModelIndex | null; offsetRow: ModelIndex } => {\n let key = null;\n let offsetRow = row;\n // Need to iterate through the map in order... sort it first\n const sortedEntries = [...children].sort((a, b) => a[0] - b[0]);\n for (let i = 0; i < sortedEntries.length; i += 1) {\n const [childRow, childModel] = sortedEntries[i];\n if (offsetRow <= childRow) {\n break;\n }\n const childRowCount = childModel.rowCount;\n if (offsetRow <= childRow + childRowCount) {\n key = childRow;\n offsetRow = offsetRow - childRow - 1;\n break;\n }\n offsetRow -= childRowCount;\n }\n\n return { key, offsetRow };\n }\n );\n\n getCachedTextForRowHeader = memoizeClear(\n (children: ChildrenTreeMap, row: ModelIndex): string => {\n const { key, offsetRow } = this.getCachedModelRowOffset(children, row);\n\n if (key != null) {\n const model = children.get(key);\n if (model !== undefined) {\n return `${key}.${model.textForRowHeader(offsetRow)}`;\n }\n }\n\n return `${offsetRow}`;\n }\n );\n\n getCachedTextForCell = memoizeClear(\n (\n children: ChildrenTreeMap,\n column: ModelIndex,\n row: ModelIndex\n ): string => {\n const { key, offsetRow } = this.getCachedModelRowOffset(children, row);\n\n if (key != null) {\n const model = children.get(key);\n if (model !== undefined) {\n return `${key}.${model.textForCell(column, offsetRow)}`;\n }\n }\n\n return `${column},${offsetRow}`;\n }\n );\n\n getCachedIsRowExpandable = memoizeClear(\n (children: ChildrenTreeMap, row: ModelIndex, maxDepth: number): boolean => {\n const depth = this.getCachedDepthForRow(children, row);\n\n return depth < maxDepth;\n }\n );\n\n getCachedIsRowExpanded = memoizeClear(\n (children: ChildrenTreeMap, row: ModelIndex): boolean => {\n const { key, offsetRow } = this.getCachedModelRowOffset(children, row);\n\n if (key != null) {\n const model = children.get(key);\n if (model !== undefined) {\n return model.isRowExpanded(offsetRow);\n }\n }\n\n return children.has(offsetRow);\n }\n );\n\n getCachedDepthForRow = memoizeClear(\n (children: ChildrenTreeMap, row: ModelIndex): number => {\n const { key, offsetRow } = this.getCachedModelRowOffset(children, row);\n\n if (key != null) {\n const model = children.get(key);\n if (model !== undefined) {\n return model.depthForRow(offsetRow) + 1;\n }\n }\n\n return 0;\n }\n );\n}\n\nexport default MockTreeGridModel;\n","/* eslint class-methods-use-this: \"off\" */\n/* eslint no-unused-vars: \"off\" */\nimport { GridModel } from '@deephaven/grid';\nimport dh from '@deephaven/jsapi-shim';\nimport Formatter from './Formatter';\n\n/**\n * Abstract class that extends the GridModel to have more functionality, like filtering and sorting.\n * For use from IrisGrid.\n * Provides some abstraction from the dh.Table and dh.TreeTable classes, so we can treat them somewhat the same.\n * Note that it still uses dh.Column, dh.FilterCondition, dh.Sort, etc., still. Theoretically should abstract\n * those out as well, so there's no dependency on IrisAPI at all, but it's a lot of work for no real gain at this time.\n */\nclass IrisGridModel extends GridModel {\n static EVENT = Object.freeze({\n UPDATED: 'UPDATED',\n FORMATTER_UPDATED: 'FORMATTER_UPDATED',\n REQUEST_FAILED: 'REQUEST_FAILED',\n COLUMNS_CHANGED: 'COLUMNS_CHANGED',\n TABLE_CHANGED: 'TABLE_CHANGED',\n FILTERS_CHANGED: 'FILTERS_CHANGED',\n SORTS_CHANGED: 'SORTS_CHANGED',\n DISCONNECT: 'DISCONNECT',\n RECONNECT: 'RECONNECT',\n TOTALS_UPDATED: 'TOTALS_UPDATED',\n PENDING_DATA_UPDATED: 'PENDING_DATA_UPDATED',\n });\n\n constructor() {\n super();\n\n this.listenerCount = 0;\n }\n\n addEventListener(...args) {\n super.addEventListener(...args);\n\n this.listenerCount += 1;\n if (this.listenerCount === 1) {\n this.startListening();\n }\n }\n\n removeEventListener(...args) {\n super.removeEventListener(...args);\n\n this.listenerCount -= 1;\n if (this.listenerCount === 0) {\n this.stopListening();\n }\n }\n\n /**\n * Function called when first listener is added.\n * Override for implementation specific behaviour.\n */\n startListening() {}\n\n /**\n * Function called when last listener is removed.\n * Override for implementation specific behaviour.\n */\n stopListening() {}\n\n /**\n * Gets the columns for this model\n * @returns {dh.Column[]} All columns in the model\n */\n get columns() {\n throw new Error('get columns not implemented');\n }\n\n /**\n * Gets the column index for this model\n * @param {String} name The model column name.\n * @returns {Number} The numeric index of the requested column.\n */\n getColumnIndexByName(name) {\n throw new Error('getColumnIndexByName not implemented');\n }\n\n /**\n * Gets the columns for the model before any transformations (such as rollups) are applied.\n * @returns {dh.Column[]} All original columns in the model.\n */\n get originalColumns() {\n return this.columns;\n }\n\n /**\n * Retrieve the grouped columns for this model\n * @returns {dh.Column[]} The columns that are grouped\n */\n get groupedColumns() {\n throw new Error('get groupedColumns not implemented');\n }\n\n /**\n * The description for this model.\n * @returns {String} The description of the model\n */\n get description() {\n throw new Error('get description not implemented');\n }\n\n /**\n * @param {Number} x The model column index\n * @param {Number} y The model row index\n * @returns {dh.Format} The format stored for that cell\n */\n formatForCell(x, y) {\n throw new Error('formatForCell not implemented');\n }\n\n /**\n * @param {Number} x The model column index\n * @param {Number} y The model row index\n * @returns {Any} The value stored for that cell\n */\n valueForCell(x, y) {\n throw new Error('valueForCell not implemented');\n }\n\n /**\n * @returns {FilterCondition[]} The filters set on this model\n */\n get filter() {\n throw new Error('get filter not implemented');\n }\n\n /**\n * @param {FilterCondition[]} filter The filters to set\n */\n set filter(filter) {\n throw new Error('set filter not implemented');\n }\n\n /**\n * @returns {Formatter} The formatter used when formatting data\n */\n get formatter() {\n throw new Error('get formatter not implemented');\n }\n\n /**\n * @param {Formatter} formatter The formatter to set\n */\n set formatter(formatter) {\n throw new Error('set formatter not implemented');\n }\n\n /**\n * @param {Any} value The value to format\n * @param {String} columnType The column type to format\n * @param {String} columnName The column name to format\n */\n displayString(value, columnType, columnName = '') {\n throw new Error('displayString not implemented');\n }\n\n /**\n * @returns {dh.Sort[]} The sorts used on this model\n */\n get sort() {\n throw new Error('get sort not implemented');\n }\n\n /**\n * @param {dh.Sort[]} sort The sorts to use on this model\n */\n set sort(sort) {\n throw new Error('set sort not implemented');\n }\n\n /**\n * @returns {String[]} The custom columns on this model\n */\n get customColumns() {\n throw new Error('get customColumns not implemented');\n }\n\n /**\n * @param {String[]} customColumns The custom columns to use\n */\n set customColumns(customColumns) {\n throw new Error('set customColumns not implemented');\n }\n\n /**\n * @param {String[]} columns The columns to treat as frozen\n */\n updateFrozenColumns(columns) {\n throw new Error('updateFrozenColumns not implemented');\n }\n\n /**\n * @returns {dh.RollupTableConfig} The config to use for rolling up this table\n */\n get rollupConfig() {\n throw new Error('get rollupConfig not implemented');\n }\n\n set rollupConfig(rollupConfig) {\n throw new Error('set rollupConfig not implemented');\n }\n\n /**\n * @returns {dh.TotalsTableConfig} The config to use for the totals table of this model\n */\n get totalsConfig() {\n throw new Error('get totalsConfig not implemented');\n }\n\n set totalsConfig(totalsConfig) {\n throw new Error('set totalsConfig not implemented');\n }\n\n /**\n * @returns {dh.LayoutHints|null} The LayoutHints to use for the columns of this table model\n */\n get layoutHints() {\n return null;\n }\n\n /**\n * @param {Number} index The column index to check\n * @returns {Boolean} Whether the column is one of LayoutHints' frozen columns\n */\n isColumnFrozen(index) {\n return false;\n }\n\n /**\n * @returns {boolean} True if this model requires a filter to be set\n */\n get isFilterRequired() {\n return false;\n }\n\n get isReversible() {\n return true;\n }\n\n /**\n * @returns {boolean} True if this model supports the columnStatistics(column) function\n */\n get isColumnStatisticsAvailable() {\n return false;\n }\n\n /**\n * @returns {boolean} True if this model supports customColumns\n */\n get isCustomColumnsAvailable() {\n return false;\n }\n\n /**\n * @returns {boolean} True if this model supports the export() function\n */\n get isExportAvailable() {\n return false;\n }\n\n /**\n * @returns {boolean} True if this model supports the valuesTable(column) function\n */\n get isValuesTableAvailable() {\n return false;\n }\n\n /**\n * @returns {boolean} True if this model should allow the chart builder\n */\n get isChartBuilderAvailable() {\n return false;\n }\n\n /**\n * @returns {boolean} True if the rollup rows functionality is available\n */\n get isRollupAvailable() {\n return false;\n }\n\n /**\n * @returns {boolean} True if the totals functionality is available\n */\n get isTotalsAvailable() {\n return false;\n }\n\n /**\n * The pending data for this model\n * @returns {Map<number, Map<string, value>>} A map of row index to a map of column name/value pairs\n */\n get pendingDataMap() {\n throw new Error('get pendingDataMap not implemented');\n }\n\n /**\n * Set the pending data for this model\n * @param {Map<number, Map<string, value>>} A map of row index to a map of column name/value pairs\n */\n set pendingDataMap(map) {\n throw new Error('set pendingDataMap not implemented');\n }\n\n /**\n * @returns {number} The count of pending rows to show\n */\n get pendingRowCount() {\n throw new Error('get pendingRowCount not implemented');\n }\n\n /**\n * Set the count of pending rows to show\n * @param {number} count The count of pending rows to show\n */\n set pendingRowCount(count) {\n throw new Error('set pendingRowCount not implemented');\n }\n\n /**\n * Errors for the pending data\n * @returns {Map<number, Error>} Map from row number to the error\n */\n get pendingDataErrors() {\n throw new Error('get pendingDataErrors not implemented');\n }\n\n /**\n * Commit pending data and save all data to the table\n */\n async commitPending() {\n throw new Error('commitPending not implemented');\n }\n\n /**\n * Check if a column is filterable\n * @param columnIndex {number} The column index to check for filterability\n * @returns {boolean} True if the current provided column index is filterable, false otherwise\n */\n isFilterable(columnIndex) {\n return false;\n }\n\n /**\n * Set the indices of the viewport\n * @param {number} top Top of viewport\n * @param {number} bottom Bottom of viewport\n * @param {Iris.Column[]} columns The columns in the viewport. `null` for all columns\n */\n setViewport(top, bottom, columns) {\n throw new Error('setViewport not implemented');\n }\n\n /**\n * Takes a snapshot of the provided ranges\n * @param {GridRange[]} ranges The model ranges to take the snapshot of\n * @returns {unknown[][]} Returns the data in a row/column matrix\n */\n async snapshot(ranges) {\n throw new Error('snapshot not implemented');\n }\n\n /**\n * @param {GridRange[]} ranges The ranges to take a snapshot of\n * @param {boolean} includeHeaders Whether to include the headers in the snapshot or not\n * @param {(unknown, dh.Column, dh.Row) => string} formatValue A function to format a value for a cell. Defaults to model format value.\n * @returns {Promise<string>} A text formatted snapshot of the data for the specified range set\n */\n async textSnapshot(ranges, includeHeaders, formatValue) {\n throw new Error('textSnapshot not implemented');\n }\n\n /**\n * @returns {Promise<dh.Table>} Returns a raw table that is frozen and can be used for exporting data\n */\n async export() {\n throw new Error('export not implemented');\n }\n\n /**\n * @param {dh.Column} column The column to get the distinct values for\n * @returns {Promise<dh.Table>} A table partitioned on the column specified\n */\n async valuesTable(column) {\n throw new Error('getValuesTable not implemented');\n }\n\n /**\n * @param {dh.Column} column The column to get statistics for\n * @returns {Promise<dh.ColumnStatistics>} The column statistics\n */\n async columnStatistics(column) {\n throw new Error('columnStatistics not implemented');\n }\n\n /**\n * Close this model. It can no longer be used after being closed\n */\n close() {}\n\n /**\n * Don't allow any rows to be movable in any IrisGrids by default. Just columns.\n */\n isRowMovable() {\n return false;\n }\n\n /**\n * Delete ranges from an input grid. Will delete the entire row, causing data to shift up\n * @param {GridRange[]} ranges The ranges to delete\n * @returns {Promise<void>} A promise that resolves successfully when the operation is complete or rejects if there's an error\n */\n delete(ranges) {\n throw new Error('delete not implemented');\n }\n}\n\nexport default IrisGridModel;\n","enum AggregationOperation {\n COUNT = 'Count',\n MIN = 'Min',\n MAX = 'Max',\n SUM = 'Sum',\n ABS_SUM = 'AbsSum',\n VAR = 'Var',\n AVG = 'Avg',\n STD = 'Std',\n FIRST = 'First',\n LAST = 'Last',\n SKIP = 'Skip',\n COUNT_DISTINCT = 'CountDistinct',\n DISTINCT = 'Distinct',\n UNIQUE = 'Unique',\n}\n\nexport default AggregationOperation;\n","enum AdvancedSettingsType {\n FILTER_CONTROL_CHANGE_CLEARS_ALL_FILTERS = 'filter-control-change-clears-all-filters',\n LINK_CHANGE_CLEARS_ALL_FILTERS = 'link-change-clears-all-filters',\n}\n\nexport default AdvancedSettingsType;\n","import AdvancedSettingsType from './AdvancedSettingsType';\n\nconst DEFAULTS = Object.freeze([\n [AdvancedSettingsType.FILTER_CONTROL_CHANGE_CLEARS_ALL_FILTERS, false],\n [AdvancedSettingsType.LINK_CHANGE_CLEARS_ALL_FILTERS, false],\n]);\n\nexport default { DEFAULTS };\n","import type { Column } from '@deephaven/jsapi-shim';\nimport TableUtils from '../../TableUtils';\nimport AggregationOperation from './AggregationOperation';\n\n/**\n * Check if an operation requires a rollup/table grouping\n * @param type The operation to check\n * @returns True if this operation applies to the whole table, false if applies to columns\n */\nexport const isRollupOperation = (type: AggregationOperation): boolean => {\n switch (type) {\n // currently no rollup only operations, but there has been in the past\n default:\n return false;\n }\n};\n\n/**\n * Check if an operation is valid against the given column type\n * @param operationType The operation to check\n * @param columnType The column type to check against\n */\nexport const isValidOperation = (\n operationType: AggregationOperation,\n columnType: string\n): boolean => {\n switch (operationType) {\n case AggregationOperation.COUNT:\n case AggregationOperation.FIRST:\n case AggregationOperation.LAST:\n case AggregationOperation.COUNT_DISTINCT:\n case AggregationOperation.DISTINCT:\n case AggregationOperation.UNIQUE:\n return true;\n case AggregationOperation.MIN:\n case AggregationOperation.MAX:\n return (\n TableUtils.isNumberType(columnType) ||\n TableUtils.isDateType(columnType) ||\n TableUtils.isTextType(columnType)\n );\n case AggregationOperation.SUM:\n case AggregationOperation.ABS_SUM:\n case AggregationOperation.VAR:\n case AggregationOperation.AVG:\n case AggregationOperation.STD:\n return TableUtils.isNumberType(columnType);\n case AggregationOperation.SKIP:\n return false;\n // No default case - if AggregationOperation is added, we'll get a compile time error\n }\n};\n\nexport const filterValidColumns = (\n columns: Column[],\n operationType: AggregationOperation\n): Column[] => columns.filter(c => isValidOperation(operationType, c.type));\n\nexport const getOperationColumnNames = (\n columns: Column[],\n operationType: AggregationOperation,\n selected: string[],\n invert: boolean\n): string[] =>\n filterValidColumns(columns, operationType)\n .map(({ name }) => name)\n .filter(name => (selected.includes(name) ? !invert : invert));\n\nexport default {\n isRollupOperation,\n filterValidColumns,\n getOperationColumnNames,\n};\n","import { GridUtils } from '@deephaven/grid';\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport TableUtils from './TableUtils';\nimport DateUtils from './DateUtils';\nimport AdvancedSettings from './sidebar/AdvancedSettings';\nimport AggregationUtils from './sidebar/aggregations/AggregationUtils';\nimport AggregationOperation from './sidebar/aggregations/AggregationOperation';\n\nconst log = Log.module('IrisGridUtils');\n\nclass IrisGridUtils {\n /**\n * Exports the state from Grid component to a JSON stringifiable object\n * @param {IrisGridModel} model The table model to export the Grid state for\n * @param {Object} gridState The state of the Grid to export\n * @returns {Object} An object that can be stringified and imported with {{@link hydrateGridState}}\n */\n static dehydrateGridState(model, gridState) {\n const {\n isStuckToBottom,\n isStuckToRight,\n movedColumns,\n movedRows,\n } = gridState;\n\n const { columns } = model;\n return {\n isStuckToBottom,\n isStuckToRight,\n movedColumns: [...movedColumns]\n .filter(\n ({ to, from }) =>\n to >= 0 && to < columns.length && from >= 0 && from < columns.length\n )\n .map(({ to, from }) => ({\n to: columns[to].name,\n from: columns[from].name,\n })),\n movedRows: [...movedRows],\n };\n }\n\n /**\n * Import a state for Grid that was exported with {{@link dehydrateGridState}}\n * @param {IrisGridModel} model The table model to import the state for\n * @param {Object} gridState The state of the panel that was saved\n * @returns {Object} The gridState props to set on the Grid\n */\n static hydrateGridState(model, gridState, customColumns = []) {\n const {\n isStuckToBottom,\n isStuckToRight,\n movedColumns,\n movedRows,\n } = gridState;\n\n const { columns } = model;\n const customColumnNames = IrisGridUtils.parseCustomColumnNames(\n customColumns\n );\n const columnNames = columns\n .map(({ name }) => name)\n .concat(customColumnNames);\n\n return {\n isStuckToBottom,\n isStuckToRight,\n movedColumns: [...movedColumns]\n .map(({ to, from }) => {\n if (\n (typeof to === 'string' || to instanceof String) &&\n (typeof from === 'string' || from instanceof String)\n ) {\n return {\n to: columnNames.findIndex(name => name === to),\n from: columnNames.findIndex(name => name === from),\n };\n }\n return { to, from };\n })\n .filter(\n ({ to, from }) =>\n to != null &&\n to >= 0 &&\n to < columnNames.length &&\n from != null &&\n from >= 0 &&\n from < columnNames.length\n ),\n movedRows: [...movedRows],\n };\n }\n\n /**\n * Exports the state from IrisGrid to a JSON stringifiable object\n * @param {IrisGridModel} model The table model to export the state for\n * @param {Object} irisGridState The current state of the IrisGrid\n */\n static dehydrateIrisGridState(model, irisGridState) {\n const {\n aggregationSettings = { aggregations: [], showOnTop: false },\n advancedSettings = [],\n advancedFilters,\n customColumnFormatMap,\n isFilterBarShown,\n metrics,\n quickFilters,\n customColumns,\n reverseType,\n rollupConfig = null,\n showSearchBar,\n searchValue,\n selectDistinctColumns,\n selectedSearchColumns,\n sorts,\n invertSearchColumns,\n pendingDataMap = new Map(),\n frozenColumns,\n } = irisGridState;\n const { userColumnWidths, userRowHeights } = metrics;\n\n const { columns } = model;\n return {\n advancedFilters: IrisGridUtils.dehydrateAdvancedFilters(\n columns,\n advancedFilters\n ),\n advancedSettings: [...advancedSettings],\n aggregationSettings,\n customColumnFormatMap: [...customColumnFormatMap],\n isFilterBarShown,\n quickFilters: IrisGridUtils.dehydrateQuickFilters(quickFilters),\n sorts: IrisGridUtils.dehydrateSort(sorts, model),\n userColumnWidths: [...userColumnWidths]\n .filter(\n ([columnIndex]) =>\n columnIndex != null &&\n columnIndex >= 0 &&\n columnIndex < columns.length\n )\n .map(([columnIndex, width]) => [columns[columnIndex].name, width]),\n userRowHeights: [...userRowHeights],\n customColumns: [...customColumns],\n reverseType,\n rollupConfig,\n showSearchBar,\n searchValue,\n selectDistinctColumns: [...selectDistinctColumns],\n selectedSearchColumns,\n invertSearchColumns,\n pendingDataMap: IrisGridUtils.dehydratePendingDataMap(\n columns,\n pendingDataMap\n ),\n frozenColumns,\n };\n }\n\n /**\n * Import a state for IrisGrid that was exported with {{@link dehydrateIrisGridState}}\n * @param {IrisGridModel} model The table model to import the state with\n * @param {Object} irisGridState The saved IrisGrid state\n */\n static hydrateIrisGridState(model, irisGridState) {\n const {\n advancedFilters,\n advancedSettings = [],\n aggregationSettings = { aggregations: [], showOnTop: false },\n customColumnFormatMap,\n isFilterBarShown,\n quickFilters,\n sorts,\n customColumns,\n userColumnWidths,\n userRowHeights,\n reverseType,\n rollupConfig = null,\n showSearchBar,\n searchValue,\n selectDistinctColumns,\n selectedSearchColumns,\n invertSearchColumns = true,\n pendingDataMap = [],\n frozenColumns,\n } = irisGridState;\n const { columns, formatter } = model;\n return {\n advancedFilters: IrisGridUtils.hydrateAdvancedFilters(\n columns,\n advancedFilters,\n formatter.timeZone\n ),\n advancedSettings: new Map([\n ...AdvancedSettings.DEFAULTS,\n ...advancedSettings,\n ]),\n aggregationSettings,\n customColumnFormatMap: new Map(customColumnFormatMap),\n isFilterBarShown,\n quickFilters: IrisGridUtils.hydrateQuickFilters(\n columns,\n quickFilters,\n formatter.timeZone\n ),\n sorts: IrisGridUtils.hydrateSort(columns, sorts),\n userColumnWidths: new Map(\n userColumnWidths\n .map(([column, width]) => {\n if (typeof column === 'string' || column instanceof String) {\n return [columns.findIndex(({ name }) => name === column), width];\n }\n return [column, width];\n })\n .filter(\n ([column]) =>\n column != null && column >= 0 && column < columns.length\n )\n ),\n customColumns,\n userRowHeights: new Map(userRowHeights),\n reverseType,\n rollupConfig,\n showSearchBar,\n searchValue,\n selectDistinctColumns,\n selectedSearchColumns,\n invertSearchColumns,\n pendingDataMap: IrisGridUtils.hydratePendingDataMap(\n columns,\n pendingDataMap\n ),\n frozenColumns,\n };\n }\n\n /**\n * Export the IrisGridPanel state.\n * @param {IrisGridModel} model The table model the state is being dehydrated with\n * @param {Object} irisGridPanelState The current IrisGridPanel state\n * @returns {Object} The dehydrated IrisGridPanel state\n */\n static dehydrateIrisGridPanelState(model, irisGridPanelState) {\n const {\n isSelectingPartition,\n partition,\n partitionColumn,\n } = irisGridPanelState;\n\n return {\n isSelectingPartition,\n partition,\n partitionColumn: partitionColumn ? partitionColumn.name : null,\n };\n }\n\n /**\n * Import the saved IrisGridPanel state.\n * @param {IrisGridModel} model The model the state is being hydrated with\n * @param {Object} irisGridPanelState Exported IrisGridPanel state\n * @returns {Object} The state to apply to the IrisGridPanel\n */\n static hydrateIrisGridPanelState(model, irisGridPanelState) {\n const {\n isSelectingPartition,\n partition,\n partitionColumn,\n } = irisGridPanelState;\n\n const { columns } = model;\n return {\n isSelectingPartition,\n partition,\n partitionColumn:\n partitionColumn != null\n ? IrisGridUtils.getColumnByName(columns, partitionColumn)\n : null,\n };\n }\n\n /**\n * Export the quick filters to JSON striginfiable object\n * @param {AdvancedFilter[]} quickFilters The quick filters to dehydrate\n * @returns {Object} The dehydrated quick filters\n */\n static dehydrateQuickFilters(quickFilters) {\n return [...quickFilters].map(([columnIndex, quickFilter]) => {\n const { text } = quickFilter;\n return [columnIndex, { text }];\n });\n }\n\n /**\n * Import the saved quick filters to apply to the columns. Does not actually apply the filters.\n * @param {dh.Column[]} columns The columns the filters will be applied to\n * @param {Object[]} savedQuickFilters Exported quick filters definitions\n * @param {string} timeZone The time zone to make this value in if it is a date type. E.g. America/New_York\n * @returns {QuickFilter[]} The quick filters to apply to the columns\n */\n static hydrateQuickFilters(columns, savedQuickFilters, timeZone) {\n const importedFilters = savedQuickFilters.map(\n ([columnIndex, quickFilter]) => {\n const { text } = quickFilter;\n\n let filter = null;\n try {\n const column = IrisGridUtils.getColumn(columns, columnIndex);\n if (column != null) {\n filter = TableUtils.makeQuickFilter(column, text, timeZone);\n }\n } catch (error) {\n log.error('hydrateQuickFilters error with', text, error);\n }\n\n return [columnIndex, { text, filter }];\n }\n );\n\n return new Map(importedFilters);\n }\n\n /**\n * Export the advanced filters from the provided columns to JSON striginfiable object\n * @param {dh.Column[]} columns The columns for the filters\n * @param {AdvancedFilter[]} advancedFilters The advanced filters to dehydrate\n * @returns {Object} The dehydrated advanced filters\n */\n static dehydrateAdvancedFilters(columns, advancedFilters) {\n return [...advancedFilters].map(([columnIndex, advancedFilter]) => {\n const options = IrisGridUtils.dehydrateAdvancedFilterOptions(\n IrisGridUtils.getColumn(columns, columnIndex),\n advancedFilter.options\n );\n return [columnIndex, { options }];\n });\n }\n\n /**\n * Import the saved advanced filters to apply to the columns. Does not actually apply the filters.\n * @param {dh.Columns[]} columns The columns the filters will be applied to\n * @param {Object[]} savedAdvancedFilters Exported advanced filters definitions\n * @param {string} timeZone The time zone to make this filter in if it is a date type. E.g. America/New_York\n * @returns {AdvancedFilter[]} The advanced filters to apply to the columns\n */\n static hydrateAdvancedFilters(columns, savedAdvancedFilters, timeZone) {\n const importedFilters = savedAdvancedFilters.map(\n ([columnIndex, advancedFilter]) => {\n const options = IrisGridUtils.hydrateAdvancedFilterOptions(\n IrisGridUtils.getColumn(columns, columnIndex),\n advancedFilter.options\n );\n let filter = null;\n\n try {\n const column = IrisGridUtils.getColumn(columns, columnIndex);\n if (column != null) {\n filter = TableUtils.makeAdvancedFilter(column, options, timeZone);\n }\n } catch (error) {\n log.error('hydrateAdvancedFilters error with', options, error);\n }\n\n return [columnIndex, { options, filter }];\n }\n );\n\n return new Map(importedFilters);\n }\n\n static dehydrateAdvancedFilterOptions(column, options) {\n const { selectedValues, ...otherOptions } = options;\n return {\n selectedValues: selectedValues.map(value =>\n IrisGridUtils.dehydrateValue(value, column?.type)\n ),\n ...otherOptions,\n };\n }\n\n static hydrateAdvancedFilterOptions(column, options) {\n const { selectedValues, ...otherOptions } = options;\n return {\n selectedValues: selectedValues.map(value =>\n IrisGridUtils.hydrateValue(value, column?.type)\n ),\n ...otherOptions,\n };\n }\n\n static dehydratePendingDataMap(columns, pendingDataMap) {\n return [...pendingDataMap].map(([rowIndex, { data }]) => [\n rowIndex,\n {\n data: [...data].map(([c, value]) => [\n columns[c].name,\n IrisGridUtils.dehydrateValue(value, columns[c].type),\n ]),\n },\n ]);\n }\n\n static hydratePendingDataMap(columns, pendingDataMap) {\n const columnMap = new Map();\n const getColumnIndex = columnName => {\n if (!columnMap.has(columnName)) {\n columnMap.set(\n columnName,\n columns.findIndex(({ name }) => name === columnName)\n );\n }\n return columnMap.get(columnName);\n };\n\n return new Map(\n pendingDataMap.map(([rowIndex, { data }]) => [\n rowIndex,\n {\n data: new Map(\n data.map(([columnName, value]) => [\n getColumnIndex(columnName),\n IrisGridUtils.hydrateValue(\n value,\n columns[getColumnIndex(columnName)].type\n ),\n ])\n ),\n },\n ])\n );\n }\n\n /**\n * Dehydrates/serializes a value for storage.\n * @param {Any} value The value to dehydrate\n * @param {String} columnType The column type\n */\n static dehydrateValue(value, columnType) {\n if (TableUtils.isDateType(columnType)) {\n return IrisGridUtils.dehydrateDateTime(value);\n }\n\n if (TableUtils.isLongType(columnType)) {\n return IrisGridUtils.dehydrateLong(value);\n }\n\n return value;\n }\n\n /**\n * Hydrate a value from it's serialized state\n * @param {Any} value The dehydrated value that needs to be hydrated\n * @param {String} columnType The type of column\n */\n static hydrateValue(value, columnType) {\n if (TableUtils.isDateType(columnType)) {\n return IrisGridUtils.hydrateDateTime(value);\n }\n\n if (TableUtils.isLongType(columnType)) {\n return IrisGridUtils.hydrateLong(value);\n }\n\n return value;\n }\n\n static dehydrateDateTime(value) {\n return value != null\n ? dh.i18n.DateTimeFormat.format(DateUtils.FULL_DATE_FORMAT, value)\n : null;\n }\n\n static hydrateDateTime(value) {\n return value != null\n ? dh.i18n.DateTimeFormat.parse(DateUtils.FULL_DATE_FORMAT, value)\n : null;\n }\n\n static dehydrateLong(value) {\n return value != null ? `${value}` : null;\n }\n\n static hydrateLong(value) {\n return value != null ? dh.LongWrapper.ofString(value) : null;\n }\n\n /**\n * Export the sorts from the provided table sorts to JSON stringifiable object\n * @param {dh.Sort[]} sorts The table sorts\n * @returns {Object} The dehydrated sorts\n */\n static dehydrateSort(sorts) {\n return sorts.map(sort => {\n const { column, isAbs, direction } = sort;\n return {\n column: column.index,\n isAbs,\n direction,\n };\n });\n }\n\n /**\n * Import the saved sorts to apply to the table. Does not actually apply the sort.\n * @param {dh.Column[]} columns The columns the sorts will be applied to\n * @param {Object[]} sorts Exported sort definitions\n * @returns {dh.Sort[]} The sorts to apply to the table\n */\n static hydrateSort(columns, sorts) {\n return (\n sorts\n .map(sort => {\n const { column: columnIndex, isAbs, direction } = sort;\n if (direction === TableUtils.sortDirection.reverse) {\n return dh.Table.reverse();\n }\n const column = IrisGridUtils.getColumn(columns, columnIndex);\n if (column != null) {\n let columnSort = column.sort();\n if (isAbs) {\n columnSort = columnSort.abs();\n }\n if (direction === TableUtils.sortDirection.descending) {\n columnSort = columnSort.desc();\n } else {\n columnSort = columnSort.asc();\n }\n return columnSort;\n }\n\n return null;\n })\n // If we can't find the column any more, it's null, filter it out\n // If the item is a reverse sort item, filter it out - it will get applied with the `reverseType` property\n // This should only happen when loading a legacy dashboard\n .filter(\n item =>\n item != null && item.direction !== TableUtils.sortDirection.reverse\n )\n );\n }\n\n /**\n * Pulls just the table settings from the panel state, eg. filters/sorts\n * @param {Object} panelState The dehydrated panel state\n * @returns {Object} A dehydrated table settings object, { partition, partitionColumn, advancedFilters, quickFilters, sorts }\n */\n static extractTableSettings(panelState, inputFilters = []) {\n const { irisGridPanelState, irisGridState } = panelState;\n const { partitionColumn, partition } = irisGridPanelState;\n const { advancedFilters, quickFilters, sorts } = irisGridState;\n\n return {\n advancedFilters,\n inputFilters,\n partition,\n partitionColumn,\n quickFilters,\n sorts,\n };\n }\n\n /**\n * Applies the passed in table settings directly to the provided table\n * @param {dh.Table} table The table to apply the settings to\n * @param {Object} tableSettings Dehydrated table settings extracted with `extractTableSettings`\n * @param {string} timeZone The time zone to make this value in if it is a date type. E.g. America/New_York\n */\n static applyTableSettings(table, tableSettings, timeZone) {\n const { columns } = table;\n const quickFilters = IrisGridUtils.getFiltersFromFilterMap(\n IrisGridUtils.hydrateQuickFilters(\n columns,\n tableSettings.quickFilters,\n timeZone\n )\n );\n const advancedFilters = IrisGridUtils.getFiltersFromFilterMap(\n IrisGridUtils.hydrateAdvancedFilters(\n columns,\n tableSettings.advancedFilters,\n timeZone\n )\n );\n const inputFilters = IrisGridUtils.getFiltersFromInputFilters(\n columns,\n tableSettings.inputFilters,\n timeZone\n );\n const sorts = IrisGridUtils.hydrateSort(columns, tableSettings.sorts);\n\n let filters = [...quickFilters, ...advancedFilters];\n const { partition, partitionColumn: partitionColumnName } = tableSettings;\n if (partition && partitionColumnName) {\n const partitionColumn = IrisGridUtils.getColumnByName(\n columns,\n partitionColumnName\n );\n if (partitionColumn) {\n const partitionFilter = partitionColumn\n .filter()\n .eq(dh.FilterValue.ofString(partition));\n filters = [partitionFilter, ...filters];\n }\n }\n filters = [...inputFilters, ...filters];\n\n table.applyFilter(filters);\n table.applySort(sorts);\n }\n\n static getInputFiltersForColumns(columns, inputFilters = []) {\n return inputFilters.filter(({ name, type }) =>\n columns.find(\n ({ name: columnName, type: columnType }) =>\n columnName === name && columnType === type\n )\n );\n }\n\n static getFiltersFromInputFilters(columns, inputFilters = [], timeZone) {\n return inputFilters\n .map(({ name, type, value }) => {\n const column = columns.find(\n ({ name: columnName, type: columnType }) =>\n columnName === name && columnType === type\n );\n if (column) {\n try {\n return TableUtils.makeQuickFilter(column, value, timeZone);\n } catch (e) {\n // It may be unable to create it because user hasn't completed their input\n log.debug('Unable to create input filter', e);\n }\n }\n\n return null;\n })\n .filter(filter => filter);\n }\n\n static getFiltersFromFilterMap(filterMap) {\n const filters = [];\n\n const keys = Array.from(filterMap.keys());\n for (let i = 0; i < keys.length; i += 1) {\n const key = keys[i];\n const item = filterMap.get(key);\n if (item.filter != null) {\n filters.push(item.filter);\n }\n }\n\n return filters;\n }\n\n /**\n * Get array of hidden column indexes\n * @param {Map} userColumnWidths Map of user column widths\n * @returns {number[]} Array of hidden column indexes\n */\n static getHiddenColumns(userColumnWidths) {\n return [...userColumnWidths.entries()]\n .filter(([, value]) => value === 0)\n .map(([key]) => key);\n }\n\n static parseCustomColumnNames(customColumns) {\n return customColumns.map(customColumn => customColumn.split('=')[0]);\n }\n\n static getRemovedCustomColumnNames(oldCustomColumns, customColumns) {\n const oldCustomColumnsNames = IrisGridUtils.parseCustomColumnNames(\n oldCustomColumns\n );\n const customColumnNames = IrisGridUtils.parseCustomColumnNames(\n customColumns\n );\n return oldCustomColumnsNames.filter(\n oldCustomColumnName => !customColumnNames.includes(oldCustomColumnName)\n );\n }\n\n static removeSortsInColumns(sorts, columnNames) {\n return sorts.filter(sort => !columnNames.includes(sort.column.name));\n }\n\n static removeFiltersInColumns(columns, filters, removedColumnNames) {\n const columnNames = columns.map(({ name }) => name);\n const newFilter = new Map(filters);\n removedColumnNames.forEach(columnName =>\n newFilter.delete(columnNames.indexOf(columnName))\n );\n return newFilter;\n }\n\n static removeColumnFromMovedColumns(\n columns,\n movedColumns,\n removedColumnNames\n ) {\n const columnNames = columns.map(({ name }) => name);\n let newMoves = [...movedColumns];\n for (let i = 0; i < removedColumnNames.length; i += 1) {\n const removedColumnName = removedColumnNames[i];\n let removedColumnIndex = columnNames.findIndex(\n name => name === removedColumnName\n );\n const moves = [];\n for (let j = 0; j < newMoves.length; j += 1) {\n const move = newMoves[j];\n const newMove = { ...move };\n // remove the move if it's a removed column move\n // from-=1 & to-=! if the from/to column is placed after the removed column\n if (removedColumnIndex !== move.from) {\n if (move.from > removedColumnIndex) {\n newMove.from -= 1;\n }\n if (move.to >= removedColumnIndex) {\n newMove.to -= 1;\n }\n if (newMove.from !== newMove.to) {\n moves.push(newMove);\n }\n }\n // get the next index of the removed column after the move\n if (move.from === removedColumnIndex) {\n removedColumnIndex = move.to;\n } else if (\n move.from < removedColumnIndex &&\n removedColumnIndex < move.to\n ) {\n removedColumnIndex -= 1;\n } else if (\n move.to <= removedColumnIndex &&\n removedColumnIndex < move.from\n ) {\n removedColumnIndex += 1;\n }\n }\n newMoves = moves;\n columnNames.splice(\n columnNames.findIndex(name => name === removedColumnName),\n 1\n );\n }\n return newMoves;\n }\n\n static removeColumnsFromSelectDistinctColumns(\n selectDistinctColumns,\n removedColumnNames\n ) {\n return selectDistinctColumns.filter(\n columnName => !removedColumnNames.includes(columnName)\n );\n }\n\n static getVisibleColumnsInRange(\n tableColumns,\n left,\n right,\n movedColumns,\n hiddenColumns\n ) {\n const columns = [];\n for (let i = left; i <= right; i += 1) {\n const modelIndex = GridUtils.getModelIndex(i, movedColumns);\n if (\n modelIndex >= 0 &&\n modelIndex < tableColumns.length &&\n !hiddenColumns.includes(modelIndex)\n ) {\n columns.push(tableColumns[modelIndex]);\n }\n }\n return columns;\n }\n\n static getPrevVisibleColumns(\n tableColumns,\n startIndex,\n count,\n movedColumns,\n hiddenColumns\n ) {\n const columns = [];\n let i = startIndex;\n while (i >= 0 && columns.length < count) {\n const modelIndex = GridUtils.getModelIndex(i, movedColumns);\n if (\n modelIndex >= 0 &&\n modelIndex < tableColumns.length &&\n !hiddenColumns.includes(modelIndex)\n ) {\n columns.unshift(tableColumns[modelIndex]);\n }\n i -= 1;\n }\n return columns;\n }\n\n static getNextVisibleColumns(\n tableColumns,\n startIndex,\n count,\n movedColumns,\n hiddenColumns\n ) {\n const columns = [];\n let i = startIndex;\n while (i < tableColumns.length && columns.length < count) {\n const modelIndex = GridUtils.getModelIndex(i, movedColumns);\n if (\n modelIndex >= 0 &&\n modelIndex < tableColumns.length &&\n !hiddenColumns.includes(modelIndex)\n ) {\n columns.push(tableColumns[modelIndex]);\n }\n i += 1;\n }\n return columns;\n }\n\n static getColumnsToFetch(\n tableColumns,\n viewportColumns,\n alwaysFetchColumnNames\n ) {\n const columnsToFetch = [...viewportColumns];\n alwaysFetchColumnNames.forEach(columnName => {\n const column = tableColumns.find(({ name }) => name === columnName);\n if (column != null && !viewportColumns.includes(column)) {\n columnsToFetch.push(column);\n }\n });\n return columnsToFetch;\n }\n\n static getModelViewportColumns(\n columns,\n left,\n right,\n movedColumns = [],\n hiddenColumns = [],\n alwaysFetchColumnNames = [],\n bufferPages = 0\n ) {\n if (left == null || right == null) {\n return null;\n }\n\n const columnsCenter = IrisGridUtils.getVisibleColumnsInRange(\n columns,\n left,\n right,\n movedColumns,\n hiddenColumns\n );\n const bufferWidth = columnsCenter.length * bufferPages;\n const columnsLeft = IrisGridUtils.getPrevVisibleColumns(\n columns,\n left - 1,\n bufferWidth,\n movedColumns,\n hiddenColumns\n );\n const columnsRight = IrisGridUtils.getNextVisibleColumns(\n columns,\n right + 1,\n bufferWidth,\n movedColumns,\n hiddenColumns\n );\n\n const bufferedColumns = [...columnsLeft, ...columnsCenter, ...columnsRight];\n\n return IrisGridUtils.getColumnsToFetch(\n columns,\n bufferedColumns,\n alwaysFetchColumnNames\n );\n }\n\n /**\n * Get the dh.RangeSet representation of the provided ranges.\n * Ranges are sorted prior to creating the RangeSet. Only the rows are taken into account,\n * RangeSet does not have an option for columns.\n * @param {GridRange[]} ranges The ranges to get the range set for\n * @returns {dh.RangeSet} The rangeset for the provided ranges\n */\n static rangeSetFromRanges(ranges) {\n const rangeSets = ranges\n .slice()\n .sort((a, b) => a.startRow - b.startRow)\n .map(range => {\n const { startRow, endRow } = range;\n return dh.RangeSet.ofRange(startRow, endRow);\n });\n return dh.RangeSet.ofRanges(rangeSets);\n }\n\n /**\n * Validate whether the ranges passed in are valid to take a snapshot from.\n * Multiple selections are valid if all of the selected rows have the same columns selected.\n *\n * @param {GridRange[]} ranges The ranges to validate\n * @returns {boolean} True if the ranges are valid, false otherwise\n */\n static isValidSnapshotRanges(ranges) {\n if (!ranges || ranges.length === 0) {\n return false;\n }\n\n // To verify all the rows selected have the same set of columns selected, build a map with string representations\n // of each range.\n const rangeMap = new Map();\n for (let i = 0; i < ranges.length; i += 1) {\n const range = ranges[i];\n const rowMapIndex = `${range.startRow}:${range.endRow}`;\n const columnMapIndex = `${range.startColumn}:${range.endColumn}`;\n if (!rangeMap.has(rowMapIndex)) {\n rangeMap.set(rowMapIndex, []);\n }\n rangeMap.get(rowMapIndex).push(columnMapIndex);\n }\n\n const keys = [...rangeMap.keys()];\n const matchColumnRanges = rangeMap.get(keys[0]).sort().join(',');\n for (let i = 1; i < keys.length; i += 1) {\n if (rangeMap.get(keys[i]).sort().join(',') !== matchColumnRanges) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Check if the provided value is a valid table index\n * @param {any} value A value to check if it's a valid table index\n */\n static isValidIndex(value) {\n return Number.isInteger(value) && value >= 0;\n }\n\n /**\n * Returns all columns used in any of the ranges provided\n * @param {GridRange[]} ranges The model ranges to get columns for\n * @param {dh.Column[]} allColumns All the columns to pull from\n * @returns {dh.Column[]} The columns selected in the range\n */\n static columnsFromRanges(ranges, allColumns) {\n if (!ranges || ranges.length === 0) {\n return [];\n }\n if (ranges[0].startColumn === null && ranges[0].endColumn === null) {\n // Snapshot of all the columns\n return allColumns;\n }\n\n const columnSet = new Set();\n for (let i = 0; i < ranges.length; i += 1) {\n const range = ranges[i];\n for (\n let c = range.startColumn ?? 0;\n c <= (range.endColumn ?? allColumns.length - 1);\n c += 1\n ) {\n columnSet.add(c);\n }\n }\n return [...columnSet].map(c => allColumns[c]);\n }\n\n /**\n * Transforms an iris data snapshot into a simple data matrix\n * @param {dh.TableData} data The Iris formatted table data\n * @returns {unknown[][]} A matrix of the values of the data\n */\n static snapshotDataToMatrix(data) {\n const { columns, rows } = data;\n const result = [];\n for (let r = 0; r < rows.length; r += 1) {\n const row = rows[r];\n const rowData = [];\n for (let c = 0; c < columns.length; c += 1) {\n const column = columns[c];\n const value = row.get(column);\n rowData.push(value);\n }\n result.push(rowData);\n }\n return result;\n }\n\n /**\n * Hydrate model rollup config\n * @param {Array} originalColumns Original model columns\n * @param {Object} config Dehydrated rollup config\n * @param {Object} aggregationSettings Aggregation settings\n * @returns {Object} Rollup config for the model\n */\n static getModelRollupConfig(originalColumns, config, aggregationSettings) {\n if ((config?.columns?.length ?? 0) === 0) {\n return null;\n }\n\n const {\n columns: groupingColumns = [],\n showConstituents: includeConstituents = true,\n showNonAggregatedColumns = true,\n includeDescriptions = true,\n } = config ?? {};\n const { aggregations = [] } = aggregationSettings ?? {};\n const aggregationColumns = aggregations.map(\n ({ operation, selected, invert }) =>\n AggregationUtils.isRollupOperation(operation)\n ? []\n : AggregationUtils.getOperationColumnNames(\n originalColumns,\n operation,\n selected,\n invert\n )\n );\n\n const aggregationMap = {};\n // Aggregation columns should show first, add them first\n for (let i = 0; i < aggregations.length; i += 1) {\n aggregationMap[aggregations[i].operation] = aggregationColumns[i];\n }\n\n if (showNonAggregatedColumns) {\n // Filter out any column that already has an aggregation or grouping\n const nonAggregatedColumnSet = new Set(\n originalColumns\n .map(c => c.name)\n .filter(name => !groupingColumns.includes(name))\n );\n aggregationColumns.forEach(columns => {\n columns.forEach(name => nonAggregatedColumnSet.delete(name));\n });\n\n if (nonAggregatedColumnSet.size > 0) {\n const existingColumns =\n aggregationMap[AggregationOperation.FIRST] ?? [];\n aggregationMap[AggregationOperation.FIRST] = [\n ...existingColumns,\n ...nonAggregatedColumnSet,\n ];\n }\n }\n\n return {\n groupingColumns,\n includeConstituents,\n includeDescriptions,\n aggregations: aggregationMap,\n };\n }\n\n /**\n * @param {Map} pendingDataMap Map of pending data\n * @returns {Map} A map with the errors in the pending data\n */\n static getPendingErrors(pendingDataMap) {\n pendingDataMap.forEach((row, rowIndex) => {\n if (!IrisGridUtils.isValidIndex(rowIndex)) {\n throw new Error('Invalid rowIndex', rowIndex);\n }\n\n const { data } = row;\n data.forEach((value, columnIndex) => {\n if (!IrisGridUtils.isValidIndex(columnIndex)) {\n throw new Error('Invalid columnIndex', columnIndex);\n }\n });\n });\n }\n\n /**\n * Retrieves a column from the provided array at the index, or `null` and logs an error if it's invalid\n *\n * @param {dh.Columns[]} columns The columns to get the column from\n * @param {Number} columnIndex The column index to get\n */\n static getColumn(columns, columnIndex) {\n if (columnIndex < columns.length) {\n return columns[columnIndex];\n }\n\n log.error('Unable to retrieve column', columnIndex, '>=', columns.length);\n\n return null;\n }\n\n /**\n * Retrieves a column from the provided array matching the name, or `null` and logs an error if not found\n * @param {dh.Column[]} columns The columns to get the column from\n * @param {String} columnName The column name to retrieve\n */\n static getColumnByName(columns, columnName) {\n const column = columns.find(({ name }) => name === columnName);\n if (column == null) {\n log.error(\n 'Unable to retrieve column by name',\n columnName,\n columns.map(({ name }) => name)\n );\n }\n\n return column;\n }\n}\n\nexport default IrisGridUtils;\n","class MissingKeyError extends Error {\n isMissingKey = true;\n\n rowIndex: number;\n\n columnName: string;\n\n constructor(rowIndex: number, columnName: string) {\n super(`${columnName} can't be empty (on pending row ${rowIndex + 1})`);\n this.rowIndex = rowIndex;\n this.columnName = columnName;\n }\n}\n\nexport default MissingKeyError;\n","/* eslint class-methods-use-this: \"off\" */\nimport memoize from 'memoize-one';\nimport throttle from 'lodash.throttle';\nimport { GridRange, memoizeClear } from '@deephaven/grid';\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport { PromiseUtils } from '@deephaven/utils';\nimport TableUtils from './TableUtils';\nimport Formatter from './Formatter';\nimport { TableColumnFormatter } from './formatters';\nimport IrisGridModel from './IrisGridModel';\nimport AggregationOperation from './sidebar/aggregations/AggregationOperation';\nimport IrisGridUtils from './IrisGridUtils';\nimport MissingKeyError from './MissingKeyError';\n\nconst log = Log.module('IrisGridTableModel');\n\nconst SET_VIEWPORT_THROTTLE = 150;\nconst APPLY_VIEWPORT_THROTTLE = 0;\n\n/**\n * Model for a grid showing an iris data table\n */\nclass IrisGridTableModel extends IrisGridModel {\n static ROW_BUFFER_PAGES = 1;\n\n static COLUMN_BUFFER_PAGES = 0;\n\n /**\n * @param {dh.Table} table Iris data table to be used in the model\n * @param {Formatter} formatter The formatter to use when getting formats\n * @param {dh.InputTable} inputTable Iris input table associated with this table\n */\n constructor(table, formatter = new Formatter(), inputTable = null) {\n super();\n\n this.handleTableDisconnect = this.handleTableDisconnect.bind(this);\n this.handleTableReconnect = this.handleTableReconnect.bind(this);\n this.handleTableUpdate = this.handleTableUpdate.bind(this);\n this.handleTotalsUpdate = this.handleTotalsUpdate.bind(this);\n this.handleRequestFailed = this.handleRequestFailed.bind(this);\n this.handleCustomColumnsChanged = this.handleCustomColumnsChanged.bind(\n this\n );\n this.setViewport = throttle(\n this.setViewport.bind(this),\n SET_VIEWPORT_THROTTLE\n );\n this.applyViewport = throttle(\n this.applyViewport.bind(this),\n APPLY_VIEWPORT_THROTTLE,\n { leading: false }\n );\n\n this.irisFormatter = formatter;\n this.inputTable = inputTable;\n this.listenerCount = 0;\n this.subscription = null;\n this.table = table;\n this.viewport = null;\n this.viewportData = null;\n this.formattedStringData = [];\n this.pendingStringData = [];\n this.isSaveInProgress = false;\n\n this.totalsTable = null;\n this.totalsTablePromise = null;\n this.totals = null;\n this.totalsDataMap = null;\n\n // Map from new row index to their values. Only for input tables that can have new rows added.\n // The index of these rows start at 0, and they are appended at the end of the regular table data.\n // These rows can be sparse, so using a map instead of an array.\n this.pendingNewDataMap = new Map();\n this.pendingNewRowCount = 0;\n\n this.userFrozenColumns = null;\n }\n\n close() {\n this.table.close();\n if (this.totalsTable !== null) {\n this.totalsTable.close();\n }\n if (this.totalsTablePromise !== null) {\n this.totalsTablePromise.cancel();\n }\n }\n\n startListening() {\n super.startListening();\n\n this.table.addEventListener(\n dh.Table.EVENT_DISCONNECT,\n this.handleTableDisconnect\n );\n this.table.addEventListener(\n dh.Table.EVENT_RECONNECT,\n this.handleTableReconnect\n );\n this.table.addEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);\n this.table.addEventListener(\n dh.Client.EVENT_REQUEST_FAILED,\n this.handleRequestFailed\n );\n this.table.addEventListener(\n dh.Table.EVENT_CUSTOMCOLUMNSCHANGED,\n this.handleCustomColumnsChanged\n );\n\n if (this.totalsTable != null) {\n this.addTotalsListeners(this.totalsTable);\n }\n\n this.applyViewport();\n }\n\n stopListening() {\n super.stopListening();\n\n this.table.removeEventListener(\n dh.Table.EVENT_DISCONNECT,\n this.handleTableDisconnect\n );\n this.table.removeEventListener(\n dh.Table.EVENT_RECONNECT,\n this.handleTableReconnect\n );\n this.table.removeEventListener(\n dh.Table.EVENT_UPDATED,\n this.handleTableUpdate\n );\n this.table.removeEventListener(\n dh.Client.EVENT_REQUEST_FAILED,\n this.handleRequestFailed\n );\n this.table.removeEventListener(\n dh.Table.EVENT_CUSTOMCOLUMNSCHANGED,\n this.handleCustomColumnsChanged\n );\n\n if (this.totalsTable != null) {\n this.removeTotalsListeners(this.totalsTable);\n }\n\n this.closeSubscription();\n }\n\n addTotalsListeners(totalsTable) {\n totalsTable.addEventListener(\n dh.Table.EVENT_UPDATED,\n this.handleTotalsUpdate\n );\n\n // Totals table only has one row of data\n totalsTable.setViewport(0, 0);\n }\n\n removeTotalsListeners(totalsTable) {\n totalsTable.removeEventListener(\n dh.Table.EVENT_UPDATED,\n this.handleTotalsUpdate\n );\n }\n\n handleTableDisconnect() {\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.DISCONNECT));\n }\n\n handleTableReconnect() {\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.RECONNECT));\n }\n\n handleTableUpdate(event) {\n this.copyViewportData(event.detail);\n\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n }\n\n handleTotalsUpdate(event) {\n this.copyTotalsData(event.detail);\n\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n }\n\n handleRequestFailed(event) {\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.REQUEST_FAILED, event)\n );\n }\n\n handleCustomColumnsChanged() {\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.COLUMNS_CHANGED, {\n detail: this.columns,\n })\n );\n }\n\n get rowCount() {\n return (\n this.table.size +\n (this.totals?.operationOrder?.length ?? 0) +\n this.pendingNewRowCount\n );\n }\n\n get pendingDataErrors() {\n return this.getCachedPendingErrors(\n this.pendingNewDataMap,\n this.columns,\n this.inputTable?.keyColumns.length ?? 0\n );\n }\n\n get pendingDataMap() {\n return this.pendingNewDataMap;\n }\n\n set pendingDataMap(map) {\n if (map === this.pendingNewDataMap) {\n return;\n }\n\n map.forEach((row, rowIndex) => {\n if (!IrisGridUtils.isValidIndex(rowIndex)) {\n throw new Error('Invalid rowIndex', rowIndex);\n }\n\n const { data } = row;\n data.forEach((value, columnIndex) => {\n if (!IrisGridUtils.isValidIndex(columnIndex)) {\n throw new Error('Invalid columnIndex', columnIndex);\n }\n });\n });\n\n this.pendingNewDataMap = map;\n\n this.pendingNewRowCount = Math.max(\n this.pendingNewRowCount,\n this.maxPendingDataRow\n );\n\n this.formattedStringData = [];\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED)\n );\n }\n\n get pendingRowCount() {\n return this.pendingNewRowCount;\n }\n\n set pendingRowCount(count) {\n if (count === this.pendingNewRowCount) {\n return;\n }\n\n this.pendingNewRowCount = Math.max(0, count, this.maxPendingDataRow);\n\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n }\n\n get maxPendingDataRow() {\n return this.pendingNewDataMap.size > 0\n ? Math.max(...this.pendingNewDataMap.keys()) + 1\n : 0;\n }\n\n get columnCount() {\n return this.columns.length;\n }\n\n get floatingBottomRowCount() {\n return this.totals?.showOnTop\n ? 0\n : this.totals?.operationOrder?.length ?? 0;\n }\n\n get floatingTopRowCount() {\n return this.totals?.showOnTop\n ? this.totals?.operationOrder?.length ?? 0\n : 0;\n }\n\n get isExportAvailable() {\n return this.table.freeze != null;\n }\n\n get isColumnStatisticsAvailable() {\n return this.table.getColumnStatistics != null;\n }\n\n get isValuesTableAvailable() {\n return this.table.selectDistinct != null && this.table.copy != null;\n }\n\n get isRollupAvailable() {\n return this.table.rollup != null;\n }\n\n get isSelectDistinctAvailable() {\n return this.table.selectDistinct != null;\n }\n\n get isCustomColumnsAvailable() {\n return this.table.applyCustomColumns != null;\n }\n\n get isChartBuilderAvailable() {\n return true;\n }\n\n get isTotalsAvailable() {\n return this.table.getTotalsTable != null;\n }\n\n get isEditable() {\n return !this.isSaveInProgress && this.inputTable != null;\n }\n\n cacheFormattedValue(x, y, text) {\n if (this.formattedStringData[x] == null) {\n this.formattedStringData[x] = [];\n }\n this.formattedStringData[x][y] = text;\n }\n\n cachePendingValue(x, y, text) {\n if (this.pendingStringData[x] == null) {\n this.pendingStringData[x] = [];\n }\n this.pendingStringData[x][y] = text;\n }\n\n clearPendingValue(x, y) {\n const column = this.pendingStringData[x];\n if (column != null) {\n delete column[y];\n }\n }\n\n textValueForCell(x, y) {\n // First check if there's any pending values we should read from\n if (this.pendingStringData[x]?.[y] !== undefined) {\n return this.pendingStringData[x][y];\n }\n\n // Use a separate cache from memoization just for the strings that are currently displayed\n if (this.formattedStringData[x]?.[y] === undefined) {\n const value = this.valueForCell(x, y);\n if (value == null) {\n return null;\n }\n\n const column = this.totalsColumn(x, y) ?? this.columns[x];\n const hasCustomColumnFormat = this.getCachedCustomColumnFormatFlag(\n this.formatter,\n column.type,\n column.name\n );\n let formatOverride = null;\n if (!hasCustomColumnFormat) {\n const formatForCell = this.formatForCell(x, y);\n if (formatForCell?.formatString != null) {\n formatOverride = formatForCell;\n }\n }\n const text = this.displayString(\n value,\n column.type,\n column.name,\n formatOverride\n );\n this.cacheFormattedValue(x, y, text);\n }\n\n return this.formattedStringData[x][y];\n }\n\n textForCell(x, y) {\n const text = this.textValueForCell(x, y);\n if (text == null && this.isKeyColumn(x)) {\n const pendingRow = this.pendingRow(y);\n if (this.pendingDataMap.has(pendingRow)) {\n // Asterisk to show a value is required for a key column on a row that has some data entered\n return '*';\n }\n }\n return text;\n }\n\n colorForCell(x, y, theme) {\n const data = this.dataForCell(x, y);\n if (data) {\n const { format, value } = data;\n if (value == null || value === '') {\n return theme.nullStringColor;\n }\n if (format && format.color) {\n return format.color;\n }\n\n if (this.isPendingRow(y)) {\n // Data entered in a pending row\n return theme.pendingTextColor;\n }\n\n // Fallback to formatting based on the value/type of the cell\n if (value != null) {\n const column = this.totalsColumn(x, y) ?? this.columns[x];\n if (TableUtils.isDateType(column.type) || column.name === 'Date') {\n return theme.dateColor;\n }\n if (TableUtils.isNumberType(column.type)) {\n if (value > 0) {\n return theme.positiveNumberColor;\n }\n if (value < 0) {\n return theme.negativeNumberColor;\n }\n return theme.zeroNumberColor;\n }\n }\n } else if (this.isPendingRow(y) && this.isKeyColumn(x)) {\n return theme.errorTextColor;\n }\n\n return theme.textColor;\n }\n\n backgroundColorForCell(x, y) {\n return this.formatForCell(x, y)?.backgroundColor;\n }\n\n textAlignForCell(x) {\n const column = this.columns[x];\n const { type } = column;\n\n if (TableUtils.isNumberType(type)) {\n return 'right';\n }\n if (TableUtils.isDateType(type) || column.name === 'Date') {\n return 'center';\n }\n return 'left';\n }\n\n textForColumnHeader(x) {\n const column = this.columns[x];\n return `${column.name}`;\n }\n\n textForRowFooter(y) {\n const totalsRow = this.totalsRow(y);\n if (totalsRow != null) {\n return this.totals.operationOrder[totalsRow];\n }\n return '';\n }\n\n getColumnsWithLayoutHints = memoize(\n (columnMap, frontColumns, backColumns, frozenColumns) => {\n const columns = [...columnMap.values()];\n if (frontColumns.length || backColumns.length || frozenColumns.length) {\n let finalFrontColumns = [];\n let finalBackColumns = [];\n let finalFrozenColumns = [];\n\n if (frontColumns.length) {\n finalFrontColumns = frontColumns\n .map(name => columnMap.get(name))\n .filter(Boolean);\n }\n if (backColumns.length) {\n finalBackColumns = backColumns\n .map(name => columnMap.get(name))\n .filter(Boolean);\n }\n if (frozenColumns.length) {\n finalFrozenColumns = frozenColumns\n .map(name => columnMap.get(name))\n .filter(Boolean);\n }\n\n if (\n finalFrontColumns.length !== frontColumns.length ||\n finalBackColumns.length !== backColumns.length ||\n finalFrozenColumns.length !== frozenColumns.length\n ) {\n throw new Error(\n 'Layout hints are invalid (contain invalid column names)'\n );\n }\n\n const frontColumnSet = new Set(finalFrontColumns);\n const backColumnSet = new Set(finalBackColumns);\n const frozenColumnSet = new Set(finalFrozenColumns);\n const middleColumns = columns.filter(\n col =>\n !frontColumnSet.has(col) &&\n !backColumnSet.has(col) &&\n !frozenColumnSet.has(col)\n );\n\n return [\n ...finalFrozenColumns,\n ...finalFrontColumns,\n ...middleColumns,\n ...finalBackColumns,\n ];\n }\n return columns;\n }\n );\n\n get columns() {\n return this.getColumnsWithLayoutHints(\n this.columnMap,\n this.frontColumns,\n this.backColumns,\n this.frozenColumns\n );\n }\n\n getMemoizedColumnMap = memoize(tableColumns => {\n const columnMap = new Map();\n tableColumns.forEach(col => columnMap.set(col.name, col));\n return columnMap;\n });\n\n get columnMap() {\n return this.getMemoizedColumnMap(this.table.columns);\n }\n\n getMemoizedFrontColumns = memoize(\n layoutHintsFrontColumns => layoutHintsFrontColumns ?? []\n );\n\n get frontColumns() {\n return this.getMemoizedFrontColumns(this.layoutHints?.frontColumns);\n }\n\n getMemoizedBackColumns = memoize(\n layoutHintsBackColumns => layoutHintsBackColumns ?? []\n );\n\n get backColumns() {\n return this.getMemoizedBackColumns(this.layoutHints?.backColumns);\n }\n\n getMemoizedFrozenColumns = memoize(\n (layoutHintsFrozenColumns, userFrozenColumns) =>\n userFrozenColumns ?? layoutHintsFrozenColumns ?? []\n );\n\n get frozenColumns() {\n return this.getMemoizedFrozenColumns(\n this.layoutHints?.frozenColumns,\n this.userFrozenColumns\n );\n }\n\n get layoutHints() {\n return this.table.layoutHints;\n }\n\n get floatingLeftColumnCount() {\n return this.frozenColumns.length;\n }\n\n get groupedColumns() {\n return [];\n }\n\n get description() {\n return this.table.description;\n }\n\n row(y) {\n const totalsRowCount = this.totals?.operationOrder?.length ?? 0;\n const showOnTop = this.totals?.showOnTop ?? false;\n const totalsRow = this.totalsRow(y);\n if (totalsRow != null) {\n const operation = this.totals.operationOrder[totalsRow];\n return this.totalsDataMap?.get(operation) ?? null;\n }\n const pendingRow = this.pendingRow(y);\n if (pendingRow != null) {\n return this.pendingNewDataMap.get(pendingRow) ?? null;\n }\n const offset = this.viewportData?.offset ?? 0;\n const viewportY = (showOnTop ? y - totalsRowCount : y) - offset;\n return this.viewportData?.rows?.[viewportY] ?? null;\n }\n\n /**\n * Retrieve the totals column if this is a totals row, or null otherwise\n * @param {ModelIndex} x Column index to get the totals column from\n * @param {ModelIndex} y Row index to get the totals column from\n * @returns {dh.Column | null}\n */\n totalsColumn(x, y) {\n const totalsRow = this.totalsRow(y);\n if (totalsRow == null) return null;\n\n const operation = this.totals.operationOrder[totalsRow];\n const defaultOperation =\n this.totals?.defaultOperation ?? AggregationOperation.SUM;\n const tableColumn = this.columns[x];\n return this.totalsTable.columns.find(\n column =>\n column.name === `${tableColumn.name}__${operation}` ||\n (operation === defaultOperation && column.name === tableColumn.name)\n );\n }\n\n /**\n * Translate from the row in the model to a row in the totals table.\n * If the row is not a totals row, return null\n * @param {number} y The row in the model to get the totals row for\n * @returns {number|null} The row within the totals table if it's a totals row, null otherwise\n */\n totalsRow(y) {\n const totalsRowCount = this.totals?.operationOrder?.length ?? 0;\n const showOnTop = this.totals?.showOnTop ?? false;\n const totalsRow = showOnTop ? y : y - this.table.size;\n if (totalsRow >= 0 && totalsRow < totalsRowCount) {\n return totalsRow;\n }\n return null;\n }\n\n /**\n * Translate from the row in the model to a pending input row.\n * If the row is not a pending input row, return null\n * @param {number} y The row in the model to get the pending row for\n * @returns {number|null} The row within the pending input rows if it's a pending row, null otherwise\n */\n pendingRow(y) {\n const pendingRow = y - this.floatingTopRowCount - this.table.size;\n if (pendingRow >= 0 && pendingRow < this.pendingNewRowCount) {\n return pendingRow;\n }\n\n return null;\n }\n\n /**\n * Check if a row is a totals table row\n * @param {number} y The row in the model to check if it's a totals table row\n * @returns {boolean} True if the row is a totals row, false if not\n */\n isTotalsRow(y) {\n return this.totalsRow(y) != null;\n }\n\n /**\n * Check if a row is a pending input row\n * @param {number} y The row in the model to check if it's a pending new row\n * @returns {boolean} True if the row is a pending new row, false if not\n */\n isPendingRow(y) {\n return this.pendingRow(y) != null;\n }\n\n dataForCell(x, y) {\n return this.row(y)?.data.get(x);\n }\n\n formatForCell(x, y) {\n return this.dataForCell(x, y)?.format;\n }\n\n valueForCell(x, y) {\n const data = this.dataForCell(x, y);\n if (data) {\n return data.value ?? null;\n }\n return undefined;\n }\n\n copyViewportData(data) {\n if (!data) {\n log.warn('invalid data!');\n return;\n }\n\n this.viewportData = this.extractViewportData(data);\n this.formattedStringData = [];\n }\n\n copyTotalsData(totalsData) {\n if (!totalsData) {\n log.warn('invalid data!');\n return;\n }\n\n const { columns, rows } = totalsData;\n if (rows.length !== 1) {\n log.error(\n 'Unexpected number of rows received for totals table, ignoring update'\n );\n return;\n }\n\n const dataMap = new Map();\n const row = rows[0];\n const defaultOperation =\n this.totals?.defaultOperation ?? AggregationOperation.SUM;\n const operationMap = this.totals?.operationMap;\n for (let c = 0; c < columns.length; c += 1) {\n const column = columns[c];\n const [\n name,\n operation = operationMap?.[name]?.[0] ?? defaultOperation,\n ] = column.name.split('__');\n if (!dataMap.has(operation)) {\n dataMap.set(operation, { data: new Map() });\n }\n const { data: rowData } = dataMap.get(operation);\n const columnIndex = this.columns.findIndex(col => col.name === name);\n rowData.set(columnIndex, {\n value: row.get(column),\n format: row.getFormat(column),\n });\n }\n\n log.debug2('copyTotalsData', dataMap);\n\n this.totalsDataMap = dataMap;\n this.formattedStringData = [];\n }\n\n /**\n * Use this as the canonical column index since things like layoutHints could have\n * changed the column order.\n */\n getColumnIndexByName(name) {\n return this.getColumnIndicesByNameMap(this.columns).get(name);\n }\n\n getColumnIndicesByNameMap = memoize(columns => {\n const indices = new Map();\n columns.forEach(({ name }, i) => indices.set(name, i));\n return indices;\n });\n\n /**\n * Copies all the viewport data into an object that we can reference later.\n * @param {ViewportData} data The data to copy from\n */\n extractViewportData(data) {\n const newData = {\n offset: data.offset,\n rows: [],\n };\n\n const { columns } = data;\n for (let r = 0; r < data.rows.length; r += 1) {\n const row = data.rows[r];\n const newRow = this.extractViewportRow(row, columns);\n newData.rows.push(newRow);\n }\n\n return newData;\n }\n\n extractViewportRow(row, columns) {\n const data = new Map();\n for (let c = 0; c < columns.length; c += 1) {\n const column = columns[c];\n\n data.set(this.getColumnIndexByName(column.name), {\n value: row.get(column),\n format: row.getFormat(column),\n });\n }\n\n return { data };\n }\n\n closeSubscription() {\n log.debug2('closeSubscription', this.subscription);\n if (this.subscription) {\n this.subscription.close();\n this.subscription = null;\n }\n\n this.setViewport.cancel();\n this.applyViewport.cancel();\n }\n\n get filter() {\n return this.table.filter;\n }\n\n set filter(filter) {\n this.closeSubscription();\n this.table.applyFilter(filter);\n this.applyViewport();\n }\n\n get formatter() {\n return this.irisFormatter;\n }\n\n set formatter(formatter) {\n this.irisFormatter = formatter;\n this.formattedStringData = [];\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.FORMATTER_UPDATED));\n }\n\n displayString(value, columnType, columnName = '', formatOverride = null) {\n return this.getCachedFormattedString(\n this.formatter,\n value,\n columnType,\n columnName,\n formatOverride\n );\n }\n\n get sort() {\n return this.table.sort;\n }\n\n set sort(sort) {\n this.closeSubscription();\n this.table.applySort(sort);\n this.applyViewport();\n }\n\n get customColumns() {\n return this.table.customColumns ?? [];\n }\n\n set customColumns(customColumns) {\n this.closeSubscription();\n this.table.applyCustomColumns(customColumns);\n this.applyViewport();\n }\n\n updateFrozenColumns(columns) {\n this.userFrozenColumns = columns;\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.TABLE_CHANGED));\n }\n\n set totalsConfig(totalsConfig) {\n log.debug('set totalsConfig', totalsConfig);\n\n if (totalsConfig === this.totals) {\n // Totals already set, or it will be set when the next model actually gets set\n return;\n }\n\n this.totals = totalsConfig;\n this.formattedStringData = [];\n\n if (this.totalsTablePromise != null) {\n this.totalsTablePromise.cancel();\n }\n\n this.setTotalsTable(null);\n\n if (totalsConfig == null) {\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n return;\n }\n\n this.totalsTablePromise = PromiseUtils.makeCancelable(\n this.table.getTotalsTable(totalsConfig),\n table => table.close()\n );\n this.totalsTablePromise\n .then(totalsTable => {\n this.totalsTablePromise = null;\n this.setTotalsTable(totalsTable);\n })\n .catch(err => {\n if (PromiseUtils.isCanceled(err)) {\n return;\n }\n\n log.error('Unable to set next totalsTable', err);\n this.totalsTablePromise = null;\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.REQUEST_FAILED, { detail: err })\n );\n });\n }\n\n setTotalsTable(totalsTable) {\n log.debug('setTotalsTable', totalsTable);\n\n if (this.totalsTable !== null) {\n if (this.listenerCount > 0) {\n this.removeTotalsListeners(this.totalsTable);\n }\n\n this.totalsTable.close();\n }\n\n this.totalsTable = totalsTable;\n this.totalsDataMap = null;\n\n if (this.listenerCount > 0 && this.totalsTable != null) {\n this.addTotalsListeners(totalsTable);\n }\n }\n\n setViewport(top, bottom, columns) {\n if (bottom < top) {\n log.error('Invalid viewport', top, bottom);\n return;\n }\n\n const { viewport } = this;\n if (\n viewport != null &&\n viewport.top === top &&\n viewport.bottom === bottom &&\n viewport.columns === columns\n ) {\n log.debug2('Ignoring duplicate viewport', viewport);\n return;\n }\n\n this.viewport = {\n top,\n bottom,\n columns,\n };\n log.debug2('setViewport', this.viewport);\n\n this.applyViewport();\n }\n\n /**\n * Applies the current viewport to the underlying table.\n */\n applyViewport() {\n if (!this.viewport) {\n return;\n }\n\n log.debug2('applyViewport', this.viewport);\n const { top, bottom, columns } = this.viewport;\n const [viewportTop, viewportBottom] = this.getCachedViewportRowRange(\n top,\n bottom\n );\n this.applyBufferedViewport(viewportTop, viewportBottom, columns);\n }\n\n applyBufferedViewport(viewportTop, viewportBottom, columns) {\n log.debug2('applyBufferedViewport', viewportTop, viewportBottom, columns);\n if (this.subscription == null) {\n log.debug2('applyBufferedViewport creating new subscription');\n this.subscription = this.table.setViewport(\n viewportTop,\n viewportBottom,\n columns\n );\n } else {\n log.debug2('applyBufferedViewport using existing subscription');\n this.subscription.setViewport(viewportTop, viewportBottom, columns);\n }\n }\n\n async snapshot(ranges, includeHeaders = false, formatValue = value => value) {\n if (this.subscription == null) {\n throw new Error('No subscription available');\n }\n\n const consolidated = GridRange.consolidate(ranges);\n if (!IrisGridUtils.isValidSnapshotRanges(consolidated)) {\n throw new Error('Invalid snapshot ranges', ranges);\n }\n\n // Need to separate out the floating ranges as they're from a different source\n const topFloatingRowsSet = new Set();\n const tableRanges = [];\n const bottomFloatingRowsSet = new Set();\n for (let i = 0; i < consolidated.length; i += 1) {\n const range = consolidated[i];\n\n // Get the rows that are in the top aggregations section\n for (\n let r = range.startRow;\n r <= range.endRow && r < this.floatingTopRowCount;\n r += 1\n ) {\n topFloatingRowsSet.add(r);\n }\n\n // Separate out the range that is part of the actual table (ie. not the floating ranges, not aggregations)\n if (\n range.endRow >= this.floatingTopRowCount &&\n range.startRow <= this.floatingTopRowCount + this.table.size\n ) {\n tableRanges.push(\n new GridRange(\n range.startColumn,\n Math.min(Math.max(0, range.startRow - this.floatingTopRowCount)),\n range.endColumn,\n Math.min(\n Math.max(0, range.endRow - this.floatingTopRowCount),\n this.table.size - this.floatingTopRowCount\n )\n )\n );\n }\n\n // Get the rows that are in the bottom aggregations section\n for (\n let r = Math.max(\n range.startRow,\n this.floatingTopRowCount + this.table.size\n );\n r <= range.endRow &&\n r <\n this.floatingTopRowCount +\n this.table.size +\n this.floatingBottomRowCount;\n r += 1\n ) {\n bottomFloatingRowsSet.add(r);\n }\n }\n\n const columns = IrisGridUtils.columnsFromRanges(consolidated, this.columns);\n const result = [];\n if (includeHeaders) {\n result.push(columns.map(c => c.name));\n }\n const topFloatingRows = [...topFloatingRowsSet].sort();\n for (let i = 0; i < topFloatingRows.length; i += 1) {\n const row = topFloatingRows[i];\n const rowData = columns.map(column =>\n formatValue(\n this.valueForCell(this.getColumnIndexByName(column.name), row),\n column\n )\n );\n if (includeHeaders) {\n rowData.push(this.textForRowFooter(row));\n }\n result.push(rowData);\n }\n\n if (tableRanges.length > 0) {\n const rangeSet = IrisGridUtils.rangeSetFromRanges(tableRanges);\n const snapshot = await this.subscription.snapshot(rangeSet, columns);\n result.push(\n ...snapshot.rows.map(rowData =>\n columns.map(column => formatValue(rowData.get(column), column))\n )\n );\n }\n\n const bottomFloatingRows = [...bottomFloatingRowsSet].sort();\n for (let i = 0; i < bottomFloatingRows.length; i += 1) {\n const row = bottomFloatingRows[i];\n const rowData = columns.map(column =>\n formatValue(\n this.valueForCell(this.getColumnIndexByName(column.name), row),\n column\n )\n );\n if (includeHeaders) {\n rowData.push(this.textForRowFooter(row));\n }\n result.push(rowData);\n }\n\n return result;\n }\n\n /**\n * Get a text snapshot of the provided ranges\n * @param {GridRange[]} ranges The ranges to get the snapshot for\n * @param {boolean} includeHeaders Whether to include the headers in the snapshot or not\n * @param {(unknown, dh.Column) => string} formatValue Function for formatting the raw value into a string\n * @returns {string} A formatted string of all the data, columns separated by `\\t` and rows separated by `\\n`\n */\n async textSnapshot(\n ranges,\n includeHeaders = false,\n formatValue = value => `${value}`\n ) {\n log.debug2('textSnapshot', ranges, includeHeaders);\n\n const data = await this.snapshot(ranges, includeHeaders, formatValue);\n return data.map(row => row.join('\\t')).join('\\n');\n }\n\n get isFilterRequired() {\n return this.table.isUncoalesced;\n }\n\n get hasExpandableRows() {\n return false;\n }\n\n isFilterable(columnIndex) {\n return this.getCachedFilterableColumnSet(this.columns).has(columnIndex);\n }\n\n isRowExpanded(y) {\n const row = this.row(y);\n return row?.isExpanded ?? false;\n }\n\n setRowExpanded(y, isExpanded) {\n this.table.setExpanded(y, isExpanded);\n }\n\n depthForRow(y) {\n const row = this.row(y);\n return (row?.depth ?? 1) - 1;\n }\n\n async valuesTable(column) {\n let table = null;\n try {\n table = await this.table.copy();\n table.applyFilter([]);\n table.applySort([]);\n return table.selectDistinct([column]);\n } finally {\n if (table != null) {\n table.close();\n }\n }\n }\n\n async export() {\n return this.table.freeze();\n }\n\n columnStatistics(column) {\n return this.table.getColumnStatistics(column);\n }\n\n getCachedFilterableColumnSet = memoize(\n columns => new Set(columns.map((_, index) => index))\n );\n\n getCachedFormattedString = memoizeClear(\n (formatter, value, columnType, columnName, formatOverride) =>\n formatter.getFormattedString(\n value,\n columnType,\n columnName,\n formatOverride\n ),\n { max: 10000 }\n );\n\n getCachedCustomColumnFormatFlag = memoizeClear(\n (formatter, columnType, columnName) => {\n const columnFormat = formatter.getColumnFormat(columnType, columnName);\n return (\n columnFormat != null &&\n (columnFormat.type === TableColumnFormatter.TYPE_CONTEXT_PRESET ||\n columnFormat.type === TableColumnFormatter.TYPE_CONTEXT_CUSTOM)\n );\n },\n { max: 10000 }\n );\n\n getCachedViewportRowRange = memoize((top, bottom) => {\n const viewHeight = bottom - top;\n const viewportTop = Math.max(\n 0,\n top - viewHeight * IrisGridTableModel.ROW_BUFFER_PAGES\n );\n const viewportBottom =\n bottom + viewHeight * IrisGridTableModel.ROW_BUFFER_PAGES;\n return [viewportTop, viewportBottom];\n });\n\n getCachedPendingErrors = memoize(\n (pendingDataMap, columns, keyColumnCount) => {\n const map = new Map();\n pendingDataMap.forEach((row, rowIndex) => {\n const { data: rowData } = row;\n for (let i = 0; i < keyColumnCount; i += 1) {\n if (!rowData.has(i)) {\n if (!map.has(rowIndex)) {\n map.set(rowIndex, []);\n }\n map\n .get(rowIndex)\n .push(new MissingKeyError(rowIndex, columns[i].name));\n }\n }\n });\n return map;\n }\n );\n\n isColumnMovable(x) {\n const columnName = this.columns[x].name;\n if (\n this.layoutHints?.frontColumns?.includes(columnName) ||\n this.layoutHints?.backColumns?.includes(columnName) ||\n this.frozenColumns.includes(columnName)\n ) {\n return false;\n }\n return !this.isKeyColumn(x);\n }\n\n isColumnFrozen(x) {\n return this.frozenColumns.includes(this.columns[x].name);\n }\n\n isKeyColumn(x) {\n return x < (this.inputTable?.keyColumns.length ?? 0);\n }\n\n isRowMovable() {\n return false;\n }\n\n isEditableRange(range) {\n return (\n this.inputTable != null &&\n GridRange.isBounded(range) &&\n ((this.isPendingRow(range.startRow) && this.isPendingRow(range.endRow)) ||\n (range.startColumn >= this.inputTable.keyColumns.length &&\n range.endColumn >= this.inputTable.keyColumns.length)) &&\n range.startRow >= this.floatingTopRowCount &&\n range.startRow <\n this.floatingTopRowCount + this.table.size + this.pendingRowCount &&\n range.endRow <\n this.floatingTopRowCount + this.table.size + this.pendingRowCount\n );\n }\n\n isDeletableRange(range) {\n return (\n this.inputTable != null &&\n range.startRow != null &&\n range.endRow != null &&\n range.startRow >= this.floatingTopRowCount &&\n range.startRow <\n this.floatingTopRowCount + this.table.size + this.pendingRowCount &&\n range.endRow <\n this.floatingTopRowCount + this.table.size + this.pendingRowCount\n );\n }\n\n isEditableRanges(ranges) {\n return ranges.every(range => this.isEditableRange(range));\n }\n\n isDeletableRanges(ranges) {\n return ranges.every(range => this.isDeletableRange(range));\n }\n\n /**\n * @returns {GridRange} A range corresponding to the underlying table\n */\n getTableAreaRange() {\n return new GridRange(\n null,\n this.floatingTopRowCount,\n null,\n this.floatingTopRowCount + this.table.size - 1\n );\n }\n\n /**\n * @returns {GridRange} A range corresponding to the pending new rows\n */\n getPendingAreaRange() {\n return new GridRange(\n null,\n this.floatingTopRowCount + this.table.size,\n null,\n this.floatingTopRowCount + this.table.size + this.pendingNewRowCount - 1\n );\n }\n\n /**\n * Set value in an editable table\n * @param {number} x The column to set\n * @param {number} y The row to set\n * @param {string} value The value to set\n * @returns {Promise<void>} A promise that resolves successfully when the operation is complete, or rejects if there's an error\n */\n async setValueForCell(x, y, text) {\n // Cache the value in our pending string cache so that it stays displayed until our edit has been completed\n return this.setValueForRanges([new GridRange(x, y, x, y)], text);\n }\n\n /**\n * Set value in an editable table\n * @param {GridRange[]} ranges The ranges to set\n * @param {string} value The values to set\n * @returns {Promise<void>} A promise that resolves successfully when the operation is complete, or rejects if there's an error\n */\n async setValueForRanges(ranges, text) {\n if (!this.isEditableRanges(ranges)) {\n throw new Error('Uneditable ranges', ranges);\n }\n\n try {\n // Cache the value in our pending string cache so that it stays displayed until our edit has been completed\n const columnSet = new Set();\n\n // Formatted text for each column\n // Since there could be different formatting for each column, but the value will be the same across rows\n const formattedText = [];\n GridRange.forEachCell(ranges, (x, y) => {\n const column = this.columns[x];\n columnSet.add(column);\n if (formattedText[x] === undefined) {\n const value = TableUtils.makeValue(\n column.type,\n text,\n this.formatter.timeZone\n );\n formattedText[x] =\n value != null\n ? this.displayString(value, column.type, column.name)\n : null;\n }\n this.cachePendingValue(x, y, formattedText[x]);\n });\n\n // Take care of updates to the pending new area first, as they can be updated synchronously\n const pendingAreaRange = this.getPendingAreaRange();\n const pendingRanges = ranges\n .map(range => GridRange.intersection(pendingAreaRange, range))\n .filter(range => range != null)\n .map(range =>\n GridRange.offset(\n range,\n 0,\n -(this.floatingTopRowCount + this.table.size)\n )\n );\n if (pendingRanges.length > 0) {\n const newDataMap = new Map(this.pendingNewDataMap);\n GridRange.forEachCell(pendingRanges, (columnIndex, rowIndex) => {\n if (!newDataMap.has(rowIndex)) {\n newDataMap.set(rowIndex, { data: new Map() });\n }\n\n const column = this.columns[columnIndex];\n const row = newDataMap.get(rowIndex);\n const { data: rowData } = row;\n const newRowData = new Map(rowData);\n const value = TableUtils.makeValue(\n column.type,\n text,\n this.formatter.timeZone\n );\n if (value != null) {\n newRowData.set(columnIndex, { value });\n } else {\n newRowData.delete(columnIndex);\n }\n if (newRowData.size > 0) {\n newDataMap.set(rowIndex, { ...row, data: newRowData });\n } else {\n newDataMap.delete(rowIndex);\n }\n });\n this.pendingDataMap = newDataMap;\n }\n\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n\n const tableAreaRange = this.getTableAreaRange();\n const tableRanges = ranges\n .map(range => GridRange.intersection(tableAreaRange, range))\n .filter(range => range != null);\n if (tableRanges.length > 0) {\n // Get a snapshot of the full rows, as we need to write a full row when editing\n const data = await this.snapshot(\n tableRanges.map(\n range => new GridRange(null, range.startRow, null, range.endRow)\n )\n );\n const newRows = data.map(row => {\n const newRow = {};\n for (let c = 0; c < this.columns.length; c += 1) {\n newRow[this.columns[c].name] = row[c];\n }\n\n columnSet.forEach(column => {\n newRow[column.name] = TableUtils.makeValue(\n column.type,\n text,\n this.formatter.timeZone\n );\n });\n return newRow;\n });\n\n const result = await this.inputTable.addRows(newRows);\n\n log.debug(\n 'setValueForRanges(',\n ranges,\n ',',\n text,\n ') set tableRanges',\n tableRanges,\n 'result',\n result\n );\n }\n\n // Add the changes to the formatted cache so it's still displayed until the update event is received\n // The update event could be received on the next tick, after the input rows have been committed,\n // so make sure we don't display stale data\n GridRange.forEachCell(ranges, (x, y) => {\n this.cacheFormattedValue(x, y, formattedText[x]);\n });\n } catch (err) {\n log.error('Unable to set ranges', ranges, text, err);\n } finally {\n GridRange.forEachCell(ranges, (x, y) => {\n this.clearPendingValue(x, y);\n });\n }\n }\n\n async setValues(edits = []) {\n log.debug('setValues(', edits, ')');\n if (\n !edits.every(edit =>\n this.isEditableRange(\n GridRange.makeCell(edit.column ?? edit.x, edit.row ?? edit.y)\n )\n )\n ) {\n throw new Error('Uneditable ranges', edits);\n }\n\n try {\n const newDataMap = new Map(this.pendingNewDataMap);\n\n // Cache the display values\n edits.forEach(edit => {\n const { text } = edit;\n const x = edit.column ?? edit.x;\n const y = edit.row ?? edit.y;\n const column = this.columns[x];\n const value = TableUtils.makeValue(\n column.type,\n text,\n this.formatter.timeZone\n );\n const formattedText =\n value != null\n ? this.displayString(value, column.type, column.name)\n : null;\n this.cachePendingValue(x, y, formattedText);\n\n // Take care of updates to the pending new area as well, as that can be updated synchronously\n const pendingRow = this.pendingRow(y);\n if (pendingRow != null) {\n if (!newDataMap.has(pendingRow)) {\n newDataMap.set(pendingRow, { data: new Map() });\n }\n\n const row = newDataMap.get(pendingRow);\n const { data: rowData } = row;\n const newRowData = new Map(rowData);\n if (value != null) {\n newRowData.set(x, { value });\n } else {\n newRowData.delete(x);\n }\n if (newRowData.size > 0) {\n newDataMap.set(pendingRow, { ...row, data: newRowData });\n } else {\n newDataMap.delete(pendingRow);\n }\n }\n });\n\n this.pendingDataMap = newDataMap;\n\n // Send an update right after setting the pending map so the values are displayed immediately\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n\n // Need to group by row...\n const rowEditMap = edits.reduce((rowMap, edit) => {\n const y = edit.row ?? edit.y;\n if (!rowMap.has(y)) {\n rowMap.set(y, []);\n }\n rowMap.get(y).push(edit);\n return rowMap;\n }, new Map());\n\n const ranges = GridRange.consolidate(\n edits.map(edit =>\n GridRange.makeCell(edit.column ?? edit.x, edit.row ?? edit.y)\n )\n );\n const tableAreaRange = this.getTableAreaRange();\n const tableRanges = ranges\n .map(range => GridRange.intersection(tableAreaRange, range))\n .filter(range => range != null);\n\n if (tableRanges.length > 0) {\n // Get a snapshot of the full rows, as we need to write a full row when editing\n const data = await this.snapshot(\n tableRanges.map(\n range => new GridRange(null, range.startRow, null, range.endRow)\n )\n );\n const newRows = data.map((row, dataIndex) => {\n let rowIndex = null;\n let r = dataIndex;\n for (let i = 0; i < tableRanges.length; i += 1) {\n const range = tableRanges[i];\n const rangeRowCount = GridRange.rowCount([range]);\n if (r < rangeRowCount) {\n rowIndex = range.startRow + r;\n break;\n }\n r -= rangeRowCount;\n }\n\n const newRow = {};\n for (let c = 0; c < this.columns.length; c += 1) {\n newRow[this.columns[c].name] = row[c];\n }\n\n const rowEdits = rowEditMap.get(rowIndex);\n if (rowEdits != null) {\n rowEdits.forEach(edit => {\n const column = this.columns[edit.column ?? edit.x];\n newRow[column.name] = TableUtils.makeValue(\n column.type,\n edit.text,\n this.formatter.timeZone\n );\n });\n }\n return newRow;\n });\n\n log.info('setValues setting tableRanges', tableRanges);\n\n const result = await this.inputTable.addRows(newRows);\n\n log.info('setValues set tableRanges', tableRanges, 'SUCCESS', result);\n }\n\n // We've sent the changes to the server, but have not yet got an update with those changes committed\n // Add the changes to the formatted cache so it's still displayed until the update event is received\n // The update event could be received on the next tick, after the input rows have been committed,\n // so make sure we don't display stale data\n edits.forEach(edit => {\n const { text } = edit;\n const x = edit.column ?? edit.x;\n const y = edit.row ?? edit.y;\n const column = this.columns[x];\n const value = TableUtils.makeValue(\n column.type,\n text,\n this.formatter.timeZone\n );\n const formattedText =\n value != null\n ? this.displayString(value, column.type, column.name)\n : null;\n this.cacheFormattedValue(x, y, formattedText);\n });\n } finally {\n edits.forEach(edit => {\n this.clearPendingValue(edit.column, edit.row);\n });\n }\n }\n\n async commitPending() {\n if (this.pendingNewDataMap.size <= 0) {\n throw new Error('No pending changes to commit');\n }\n\n try {\n this.isSaveInProgress = true;\n\n const newRows = [];\n this.pendingNewDataMap.forEach(row => {\n const newRow = {};\n row.data.forEach(({ value }, columnIndex) => {\n const column = this.columns[columnIndex];\n newRow[column.name] = value;\n });\n newRows.push(newRow);\n });\n const result = await this.inputTable.addRows(newRows);\n\n log.debug('commitPending()', this.pendingNewDataMap, 'result', result);\n\n this.pendingNewDataMap = new Map();\n this.pendingNewDataErrors = new Map();\n this.pendingNewRowCount = Math.max(\n 0,\n (this.viewport?.bottom ?? 0) - this.table.size\n );\n this.formattedStringData = [];\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED)\n );\n\n return result;\n } finally {\n this.isSaveInProgress = false;\n }\n }\n\n editValueForCell(x, y) {\n return this.textValueForCell(x, y);\n }\n\n async delete(ranges) {\n if (!this.isDeletableRanges(ranges)) {\n throw new Error('Undeletable ranges', ranges);\n }\n\n const { keyColumns } = this.inputTable;\n if (keyColumns.length === 0) {\n throw new Error('No key columns to allow deletion');\n }\n\n const pendingAreaRange = this.getPendingAreaRange();\n const pendingRanges = ranges\n .map(range => GridRange.intersection(pendingAreaRange, range))\n .filter(range => range != null)\n .map(range =>\n GridRange.offset(\n range,\n 0,\n -(this.floatingTopRowCount + this.table.size)\n )\n );\n\n if (pendingRanges.length > 0) {\n const newDataMap = new Map(this.pendingNewDataMap);\n for (let i = 0; i < pendingRanges.length; i += 1) {\n const pendingRange = pendingRanges[i];\n for (let r = pendingRange.startRow; r <= pendingRange.endRow; r += 1) {\n newDataMap.delete(r);\n }\n }\n this.pendingNewDataMap = newDataMap;\n\n this.formattedStringData = [];\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED)\n );\n\n this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));\n }\n\n const tableAreaRange = this.getTableAreaRange();\n const tableRanges = ranges\n .map(range => GridRange.intersection(tableAreaRange, range))\n .filter(range => range != null);\n if (tableRanges.length <= 0) {\n return null;\n }\n const [data, deleteTable] = await Promise.all([\n // Need to get the key values of each row\n this.snapshot(\n tableRanges.map(\n range =>\n new GridRange(\n 0,\n range.startRow,\n keyColumns.length - 1,\n range.endRow\n )\n )\n ),\n this.table.copy(),\n ]);\n\n // Now copy the existing table and filter it on the values in the snapshot for the key columns in the input table\n const filters = data.map(row => {\n const columnFilters = [];\n for (let c = 0; c < keyColumns.length; c += 1) {\n const column = keyColumns[c];\n const value = row[c];\n const filterValue = TableUtils.makeFilterRawValue(column.type, value);\n const filter = column.filter().eq(filterValue);\n columnFilters.push(filter);\n }\n return columnFilters.reduce((agg, curr) => (agg ? agg.and(curr) : curr));\n });\n\n const filter = filters.reduce((agg, curr) => (agg ? agg.or(curr) : curr));\n deleteTable.applyFilter([filter]);\n\n const result = await this.inputTable.deleteTable(deleteTable);\n deleteTable.close();\n return result;\n }\n\n isValidForCell(x, y, value) {\n try {\n const column = this.columns[x];\n TableUtils.makeValue(column.type, value, this.formatter.timeZone);\n return true;\n } catch (e) {\n return false;\n }\n }\n}\n\nexport default IrisGridTableModel;\n","/* eslint class-methods-use-this: \"off\" */\nimport memoize from 'memoize-one';\nimport { GridRange } from '@deephaven/grid';\nimport IrisGridTableModel from './IrisGridTableModel';\n\nclass IrisGridTreeTableModel extends IrisGridTableModel {\n applyBufferedViewport(viewportTop, viewportBottom, columns) {\n this.table.setViewport(viewportTop, viewportBottom, columns);\n }\n\n textForCell(x, y) {\n const column = this.columns[x];\n const row = this.row(y);\n if (row != null && column != null) {\n if (!row.hasChildren && column.constituentType != null) {\n const value = this.valueForCell(x, y);\n return value != null\n ? this.displayString(value, column.constituentType, column.name)\n : null;\n }\n }\n\n return super.textForCell(x, y);\n }\n\n extractViewportRow(row, columns) {\n const { isExpanded, hasChildren, depth } = row;\n return {\n ...super.extractViewportRow(row, columns),\n isExpanded,\n hasChildren,\n depth,\n };\n }\n\n async snapshot(ranges, includeHeaders = false, formatValue = value => value) {\n const { columns } = this.viewport;\n const result = [];\n\n if (includeHeaders) {\n result.push(columns.map(c => c.name));\n }\n\n const viewportRange = new GridRange(\n 0,\n this.viewportData.offset,\n columns.length,\n this.viewportData.offset + this.viewportData.rows.length\n );\n\n for (let i = 0; i < ranges.length; i += 1) {\n const intersection = GridRange.intersection(viewportRange, ranges[i]);\n\n for (let r = intersection.startRow; r <= intersection.endRow; r += 1) {\n const resultRow = [];\n const viewportRow = this.viewportData.rows[\n r - this.viewportData.offset\n ];\n for (\n let c = intersection.startColumn;\n c <= intersection.endColumn;\n c += 1\n ) {\n resultRow.push(\n formatValue(viewportRow.data.get(c).value, this.columns[c])\n );\n }\n result.push(resultRow);\n }\n }\n\n return result;\n }\n\n get groupedColumns() {\n return this.table.groupedColumns ?? [];\n }\n\n get hasExpandableRows() {\n return true;\n }\n\n get isChartBuilderAvailable() {\n return false;\n }\n\n get isSelectDistinctAvailable() {\n return false;\n }\n\n get isReversible() {\n return false;\n }\n\n isFilterable(columnIndex) {\n return this.getCachedFilterableColumnSet(\n this.columns,\n this.groupedColumns\n ).has(columnIndex);\n }\n\n isColumnMovable(column) {\n return column >= this.groupedColumns.length;\n }\n\n isRowExpandable(y) {\n const row = this.row(y);\n return row?.hasChildren ?? false;\n }\n\n isRowExpanded(y) {\n const row = this.row(y);\n return row?.isExpanded ?? false;\n }\n\n setRowExpanded(y, isExpanded) {\n this.table.setExpanded(y, isExpanded);\n }\n\n depthForRow(y) {\n const row = this.row(y);\n return (row?.depth ?? 1) - 1;\n }\n\n getCachedFilterableColumnSet = memoize(\n (columns, groupedColumns) =>\n new Set(\n (groupedColumns?.length > 0 ? groupedColumns : columns).map(c1 =>\n columns.findIndex(c2 => c1.name === c2.name)\n )\n )\n );\n}\n\nexport default IrisGridTreeTableModel;\n","/* eslint class-methods-use-this: \"off\" */\nimport deepEqual from 'deep-equal';\nimport Log from '@deephaven/log';\nimport { PromiseUtils } from '@deephaven/utils';\nimport Formatter from './Formatter';\nimport IrisGridTableModel from './IrisGridTableModel';\nimport IrisGridTreeTableModel from './IrisGridTreeTableModel';\nimport IrisGridModel from './IrisGridModel';\nimport TableUtils from './TableUtils';\n\nconst log = Log.module('IrisGridProxyModel');\n\nfunction makeModel(table, formatter, inputTable) {\n if (TableUtils.isTreeTable(table)) {\n return new IrisGridTreeTableModel(table, formatter);\n }\n return new IrisGridTableModel(table, formatter, inputTable);\n}\n\n/**\n * Model which proxies calls to other IrisGridModels.\n * This allows for operations that generate new tables, like rollups.\n */\nclass IrisGridProxyModel extends IrisGridModel {\n /**\n * @param {dh.Table} table Iris data table to be used in the model\n * @param {Formatter} formatter The formatter to use when getting formats\n * @param {dh.InputTable} inputTable Iris input table associated with this table\n */\n constructor(table, formatter = new Formatter(), inputTable = null) {\n super();\n\n this.handleModelEvent = this.handleModelEvent.bind(this);\n\n const model = makeModel(table, formatter, inputTable);\n this.originalModel = model;\n this.model = model;\n this.modelPromise = null;\n this.rollup = null;\n this.selectDistinct = [];\n }\n\n close() {\n this.originalModel.close();\n if (this.model !== this.originalModel) {\n this.model.close();\n }\n if (this.modelPromise != null) {\n this.modelPromise.cancel();\n }\n }\n\n handleModelEvent(event) {\n log.debug2('handleModelEvent', event);\n\n const { detail, type } = event;\n this.dispatchEvent(new CustomEvent(type, { detail }));\n }\n\n setModel(model) {\n log.debug('setModel', model);\n\n const oldModel = this.model;\n if (this.listenerCount > 0) {\n this.removeListeners(oldModel);\n }\n\n if (oldModel !== this.originalModel) {\n oldModel.close();\n }\n\n this.model = model;\n\n if (this.listenerCount > 0) {\n this.addListeners(model);\n }\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.COLUMNS_CHANGED, {\n detail: model.columns,\n })\n );\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.TABLE_CHANGED, {\n detail: model.table,\n })\n );\n }\n\n setNextModel(modelPromise) {\n log.debug2('setNextModel');\n\n if (this.modelPromise) {\n this.modelPromise.cancel();\n }\n\n this.modelPromise = PromiseUtils.makeCancelable(modelPromise, model =>\n model.close()\n );\n this.modelPromise\n .then(model => {\n this.modelPromise = null;\n this.setModel(model);\n })\n .catch(err => {\n if (PromiseUtils.isCanceled(err)) {\n return;\n }\n\n log.error('Unable to set next model', err);\n this.modelPromise = null;\n\n this.dispatchEvent(\n new CustomEvent(IrisGridModel.EVENT.REQUEST_FAILED, { detail: err })\n );\n });\n }\n\n startListening() {\n super.startListening();\n\n this.addListeners(this.model);\n }\n\n stopListening() {\n super.stopListening();\n\n this.removeListeners(this.model);\n }\n\n addListeners(model) {\n const events = Object.keys(IrisGridModel.EVENT);\n for (let i = 0; i < events.length; i += 1) {\n model.addEventListener(events[i], this.handleModelEvent);\n }\n }\n\n removeListeners(model) {\n const events = Object.keys(IrisGridModel.EVENT);\n for (let i = 0; i < events.length; i += 1) {\n model.removeEventListener(events[i], this.handleModelEvent);\n }\n }\n\n get rowCount() {\n return this.model.rowCount;\n }\n\n get columnCount() {\n return this.model.columnCount;\n }\n\n get floatingTopRowCount() {\n return this.model.floatingTopRowCount;\n }\n\n get floatingBottomRowCount() {\n return this.model.floatingBottomRowCount;\n }\n\n get floatingLeftColumnCount() {\n return this.model.floatingLeftColumnCount;\n }\n\n get floatingRightColumnCount() {\n return this.model.floatingRightColumnCount;\n }\n\n textForCell(...args) {\n return this.model.textForCell(...args);\n }\n\n textAlignForCell(...args) {\n return this.model.textAlignForCell(...args);\n }\n\n colorForCell(...args) {\n return this.model.colorForCell(...args);\n }\n\n backgroundColorForCell(...args) {\n return this.model.backgroundColorForCell(...args);\n }\n\n textForColumnHeader(...args) {\n return this.model.textForColumnHeader(...args);\n }\n\n textForRowHeader(...args) {\n return this.model.textForRowHeader(...args);\n }\n\n textForRowFooter(...args) {\n return this.model.textForRowFooter(...args);\n }\n\n isRowMovable(...args) {\n return this.model.isRowMovable(...args);\n }\n\n isColumnMovable(...args) {\n return this.model.isColumnMovable(...args);\n }\n\n isColumnFrozen(...args) {\n return this.model.isColumnFrozen(...args);\n }\n\n get hasExpandableRows() {\n return this.model.hasExpandableRows;\n }\n\n isRowExpandable(...args) {\n return this.model.isRowExpandable(...args);\n }\n\n isRowExpanded(...args) {\n return this.model.isRowExpanded(...args);\n }\n\n setRowExpanded(...args) {\n this.model.setRowExpanded(...args);\n }\n\n depthForRow(...args) {\n return this.model.depthForRow(...args);\n }\n\n get table() {\n return this.model.table;\n }\n\n get isExportAvailable() {\n return this.model.isExportAvailable;\n }\n\n get isColumnStatisticsAvailable() {\n return this.model.isColumnStatisticsAvailable;\n }\n\n get isValuesTableAvailable() {\n return this.model.isValuesTableAvailable;\n }\n\n get isCustomColumnsAvailable() {\n return (\n this.model.isCustomColumnsAvailable &&\n // Disable for selectDistinct tables\n !(this.isSelectDistinctAvailable && this.selectDistinctColumns.length > 0)\n );\n }\n\n get isChartBuilderAvailable() {\n return this.model.isChartBuilderAvailable;\n }\n\n get isRollupAvailable() {\n return (\n (this.originalModel.isRollupAvailable || this.rollup != null) &&\n this.selectDistinct.length === 0\n );\n }\n\n get isSelectDistinctAvailable() {\n return (\n (this.originalModel.isSelectDistinctAvailable ||\n this.selectDistinct.length > 0) &&\n this.rollup == null\n );\n }\n\n get isTotalsAvailable() {\n return this.model.isTotalsAvailable;\n }\n\n get isReversible() {\n return this.model.isReversible;\n }\n\n get columns() {\n return this.model.columns;\n }\n\n get layoutHints() {\n return this.model.layoutHints;\n }\n\n updateFrozenColumns(...args) {\n this.model.updateFrozenColumns(...args);\n }\n\n get originalColumns() {\n return this.originalModel.columns;\n }\n\n get groupedColumns() {\n return this.model.groupedColumns;\n }\n\n get description() {\n return this.model.description;\n }\n\n formatForCell(x, y) {\n return this.model.formatForCell(x, y);\n }\n\n valueForCell(x, y) {\n return this.model.valueForCell(x, y);\n }\n\n get filter() {\n return this.model.filter;\n }\n\n set filter(filter) {\n this.model.filter = filter;\n }\n\n get formatter() {\n return this.model.formatter;\n }\n\n set formatter(formatter) {\n this.model.formatter = formatter;\n }\n\n displayString(...args) {\n return this.model.displayString(...args);\n }\n\n get sort() {\n return this.model.sort;\n }\n\n set sort(sort) {\n this.model.sort = sort;\n }\n\n get customColumns() {\n return this.model.customColumns;\n }\n\n set customColumns(customColumns) {\n this.model.customColumns = customColumns;\n }\n\n get rollupConfig() {\n return this.rollup;\n }\n\n set rollupConfig(rollupConfig) {\n log.debug('set rollupConfig', rollupConfig);\n\n if (!this.isRollupAvailable) {\n throw new Error('Rollup Rows are not available');\n }\n\n // Prevent model update when IrisGridModelUpdater is mounted\n // if rollup is already initialized in IrisGridPanel\n if (deepEqual(rollupConfig, this.rollup)) {\n return;\n }\n\n this.rollup = rollupConfig;\n\n let modelPromise = Promise.resolve(this.originalModel);\n\n if (rollupConfig != null) {\n modelPromise = this.originalModel.table\n .rollup(rollupConfig)\n .then(table => makeModel(table, this.formatter));\n }\n this.setNextModel(modelPromise);\n }\n\n get selectDistinctColumns() {\n return this.selectDistinct;\n }\n\n set selectDistinctColumns(columnNames) {\n log.debug('set selectDistinctColumns', columnNames);\n\n if (!this.isSelectDistinctAvailable) {\n throw new Error('Select distinct is not available');\n }\n\n if (\n columnNames === this.selectDistinctColumns ||\n (columnNames.length === 0 && this.selectDistinctColumns.length === 0)\n ) {\n log.debug('Ignore same selectDistinctColumns', columnNames);\n return;\n }\n\n this.selectDistinct = columnNames;\n\n const selectDistinctColumns = columnNames\n .map(name => this.originalColumns.find(column => column.name === name))\n .filter(column => column != null);\n\n let modelPromise = Promise.resolve(this.originalModel);\n\n if (columnNames.length > 0) {\n modelPromise = this.originalModel.table\n .selectDistinct(selectDistinctColumns)\n .then(table => makeModel(table, this.formatter));\n }\n this.setNextModel(modelPromise);\n }\n\n get totalsConfig() {\n return this.model.totalsConfig;\n }\n\n set totalsConfig(totalsConfig) {\n this.model.totalsConfig = totalsConfig;\n }\n\n get isFilterRequired() {\n return this.model.isFilterRequired;\n }\n\n get isEditable() {\n return this.model.isEditable;\n }\n\n isEditableRange(...args) {\n return this.model.isEditableRange(...args);\n }\n\n isFilterable(...args) {\n return this.model.isFilterable(...args);\n }\n\n setViewport(...args) {\n this.model.setViewport(...args);\n }\n\n async snapshot(...args) {\n return this.model.snapshot(...args);\n }\n\n async textSnapshot(...args) {\n return this.model.textSnapshot(...args);\n }\n\n async export(...args) {\n return this.model.export(...args);\n }\n\n async valuesTable(...args) {\n return this.model.valuesTable(...args);\n }\n\n async columnStatistics(...args) {\n return this.model.columnStatistics(...args);\n }\n\n editValueForCell(...args) {\n return this.model.editValueForCell(...args);\n }\n\n setValueForCell(...args) {\n return this.model.setValueForCell(...args);\n }\n\n setValueForRanges(...args) {\n return this.model.setValueForRanges(...args);\n }\n\n setValues(...args) {\n return this.model.setValues(...args);\n }\n\n isValidForCell(...args) {\n return this.model.isValidForCell(...args);\n }\n\n delete(...args) {\n return this.model.delete(...args);\n }\n\n get pendingDataMap() {\n return this.model.pendingDataMap;\n }\n\n set pendingDataMap(map) {\n this.model.pendingDataMap = map;\n }\n\n get pendingRowCount() {\n return this.model.pendingRowCount;\n }\n\n set pendingRowCount(count) {\n this.model.pendingRowCount = count;\n }\n\n get pendingDataErrors() {\n return this.model.pendingDataErrors;\n }\n\n commitPending(...args) {\n return this.model.commitPending(...args);\n }\n\n getColumnIndexByName(name) {\n return this.model.getColumnIndexByName(name);\n }\n}\n\nexport default IrisGridProxyModel;\n","import Formatter from './Formatter';\nimport IrisGridProxyModel from './IrisGridProxyModel';\n\n/**\n * Factory to create an IrisGridDataModel based on a table or tree table, whatever is passed in.\n */\nclass IrisGridModelFactory {\n /**\n * @param {Table|TreeTable} table The Table or TreeTable object to create the model with\n * @param {Formatter} formatter The formatter to use\n * @returns {Promise<IrisGridModel>} An IrisGridModel that uses the table provided\n */\n static async makeModel(\n table,\n isConsoleTable = false,\n formatter = new Formatter()\n ) {\n if (!isConsoleTable && table.isUncoalesced) {\n table.close();\n throw new Error(\n 'Table is uncoalesced. Tables must contain a where clause when part of persistent queries to be viewable.'\n );\n }\n\n let inputTable = null;\n if (table.hasInputTable) {\n inputTable = await table.inputTable();\n }\n return new IrisGridProxyModel(table, formatter, inputTable);\n }\n}\n\nexport default IrisGridModelFactory;\n","import React from 'react';\nimport './DeephavenSpinner.scss';\nimport classNames from 'classnames';\n\ninterface DeephavenSpinnerProps {\n className?: string;\n show?: boolean;\n}\n\n/**\n * Break apart a generated svg into indivdual svg layers, to allow each to be animated on the GPU\n * CSS animations that reach into the svg are blocking since SVG aren't drawn by the gpu, only animations\n * that are performed on the whole svg remain hardware accelerated.\n */\nconst DeephavenSpinner = ({\n className = '',\n show = true,\n}: DeephavenSpinnerProps): JSX.Element => (\n <div className={classNames('dh-loader', className, { show })}>\n <svg className=\"dh-outer-shape\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <path\n d=\"M82.7429,0L82.7429,41.3714L45.2571,41.3714L45.2571,0L0,0L0,128L45.2571,128L45.2571,86.6286L82.5143,86.6286L82.5143,128L128,128L128,0L82.7429,0ZM41.3714,124.114L4.11429,124.114L4.11429,86.6286L41.3714,86.6286L41.3714,124.114ZM41.3714,82.7429L4.11429,82.7429L4.11429,45.2571L41.3714,45.2571L41.3714,82.7429ZM41.3714,41.3714L4.11429,41.3714L4.11429,4.11429L41.3714,4.11429L41.3714,41.3714ZM45.2571,82.7429L45.2571,45.2571L82.5143,45.2571L82.5143,82.5143L45.2571,82.5143ZM124.114,124.114L86.6286,124.114L86.6286,86.6286L123.886,86.6286L123.886,124.114ZM124.114,82.7429L86.6286,82.7429L86.6286,45.2571L123.886,45.2571L123.886,82.7429ZM86.6286,41.3714L86.6286,4.11429L123.886,4.11429L123.886,41.3714L86.6286,41.3714Z\"\n fill=\"#f0f0ee\"\n />\n </g>\n </svg>\n <svg className=\"dh-loader-tile dh-loader-tile-3\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <g transform=\"translate(63.9589,64.0492) translate(-59.9751,-63.9508)\">\n <rect\n width=\"37.3438\"\n height=\"37.6389\"\n fill=\"#5189e5\"\n transform=\"translate(-21.9838,29.7957) translate(21.9838,15.3027)\"\n />\n </g>\n </g>\n </svg>\n <svg className=\"dh-loader-tile dh-loader-tile-2\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <g transform=\"translate(63.9589,64.0492) translate(-59.9751,-63.9508)\">\n <rect\n width=\"37.2755\"\n height=\"37.4675\"\n fill=\"#5189e5\"\n transform=\"translate(-21.9838,69.7957) translate(22.0822,16.7783)\"\n />\n </g>\n </g>\n </svg>\n <svg className=\"dh-loader-tile dh-loader-tile-5\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <g transform=\"translate(63.9589,64.0492) translate(-59.9751,-63.9508)\">\n <rect\n width=\"37.3512\"\n height=\"41.3781\"\n fill=\"#35618c\"\n transform=\"translate(18.0162,72.7957) translate(23.1643,13.7278)\"\n />\n </g>\n </g>\n </svg>\n <svg className=\"dh-loader-tile dh-loader-tile-6\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <g transform=\"translate(63.9589,64.0492) translate(-59.9751,-63.9508)\">\n <rect\n width=\"37.2483\"\n height=\"37.5869\"\n fill=\"#35618c\"\n transform=\"translate(59.0162,29.7957) translate(23.6379,15.3564)\"\n />\n </g>\n </g>\n </svg>\n <svg className=\"dh-loader-tile dh-loader-tile-7\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <g transform=\"translate(63.9589,64.0492) translate(-59.9751,-63.9508)\">\n <rect\n width=\"37.5664\"\n height=\"41.2747\"\n fill=\"#35618c\"\n transform=\"translate(17.0162,-13.2043) translate(24.2531,13.2043)\"\n />\n </g>\n </g>\n </svg>\n <svg className=\"dh-loader-tile dh-loader-tile-4\" viewBox=\"0 0 182 182\">\n <g transform=\"translate(91,91.0033) translate(-64,-64.0033)\">\n <g transform=\"translate(63.9589,64.0492) translate(-59.9751,-63.9508)\">\n <rect\n width=\"37.2854\"\n height=\"37.3014\"\n fill=\"#5189e5\"\n transform=\"translate(-21.9838,-13.2043) translate(22.0822,17.1792)\"\n />\n </g>\n </g>\n </svg>\n </div>\n);\n\nexport default DeephavenSpinner;\n","/**\n * A component for creating popover dialogs. Only requires child element.\n *\n * <Popper\n * options={popperOptions}\n * className=\"whatever\"\n * onEntered={this.handleEnter}\n * onExited={this.handleExit}\n * closeOnBlur // if you want dialog to self close, on click outside\n * interactive // if popper contents will be interactable\n * isShown={variable} // controls if its shown or not,\n * ref={this.popper} // or via ref and this.popper.show() or this.popper.hide()\n * >\n * <ChildContent />\n * </Popper>\n */\n\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport classNames from 'classnames';\nimport { CSSTransition } from 'react-transition-group';\nimport PopperJs, { PopperOptions, ReferenceObject } from 'popper.js';\nimport PropTypes from 'prop-types';\nimport ThemeExport from '../ThemeExport';\nimport './Popper.scss';\n\ninterface PopperProps {\n options: PopperOptions;\n className: string;\n timeout: number;\n onEntered: () => void;\n onExited: () => void;\n isShown: boolean;\n closeOnBlur: boolean;\n interactive: boolean;\n referenceObject: ReferenceObject | null;\n}\n\ninterface PopperState {\n show: boolean;\n popper: PopperJs | null;\n}\n\nclass Popper extends Component<PopperProps, PopperState> {\n static propTypes = {\n children: PropTypes.node.isRequired,\n options: PropTypes.shape({}),\n className: PropTypes.string,\n timeout: PropTypes.number,\n onEntered: PropTypes.func,\n onExited: PropTypes.func,\n isShown: PropTypes.bool,\n closeOnBlur: PropTypes.bool,\n interactive: PropTypes.bool,\n referenceObject: PropTypes.shape({}),\n };\n\n static defaultProps = {\n options: {},\n className: '',\n timeout: ThemeExport.transitionMs,\n onEntered(): void {\n // no-op\n },\n onExited(): void {\n // no-op\n },\n isShown: false,\n interactive: false,\n closeOnBlur: false,\n referenceObject: null,\n };\n\n constructor(props: PopperProps) {\n super(props);\n\n this.handleEnter = this.handleEnter.bind(this);\n this.handleExit = this.handleExit.bind(this);\n this.handleBlur = this.handleBlur.bind(this);\n this.element = document.createElement('div');\n this.element.className = 'popper-container';\n this.container = React.createRef<HTMLDivElement>();\n\n // cancelAnimationFrame does nothing if the handle isn't recognized\n // requestAnimationFrame provides a non-zero number, so 0 as a default should be safe\n this.rAF = 0;\n\n const { isShown } = this.props;\n\n this.state = {\n show: isShown,\n popper: null,\n };\n }\n\n componentDidUpdate(prevProps: PopperProps): void {\n const { isShown } = this.props;\n\n if (prevProps.isShown !== isShown) {\n if (isShown) {\n cancelAnimationFrame(this.rAF);\n this.rAF = window.requestAnimationFrame(() => {\n this.show();\n });\n } else {\n this.hide();\n }\n }\n }\n\n componentWillUnmount(): void {\n this.destroyPopper(false);\n }\n\n element: HTMLDivElement;\n\n container: React.RefObject<HTMLDivElement>;\n\n // This is the request animation frame handle number\n rAF: number;\n\n /** Goes through an element and it's parents until the first visible element is found */\n getVisibleElement(element: HTMLElement | null): HTMLElement | null {\n if (\n element == null ||\n element.clientHeight > 0 ||\n element.clientWidth > 0\n ) {\n return element;\n }\n\n return this.getVisibleElement(element.parentElement);\n }\n\n initPopper(): void {\n let { popper } = this.state;\n const { closeOnBlur, referenceObject } = this.props;\n\n if (popper) {\n return;\n }\n\n if (this.container.current === null) {\n return;\n }\n\n let { options } = this.props;\n options = {\n placement: 'auto',\n ...options,\n };\n document.body.appendChild(this.element);\n\n let parent = this.getVisibleElement(this.container.current);\n if (parent == null) {\n parent = this.container.current;\n }\n\n popper = new PopperJs(referenceObject || parent, this.element, options);\n popper.scheduleUpdate();\n\n // delayed due to scheduleUpdate\n cancelAnimationFrame(this.rAF);\n this.rAF = window.requestAnimationFrame(() => {\n // for blur on close to work, focus needs to be on or within the popper\n if (closeOnBlur && !this.element.contains(document.activeElement)) {\n // only set focus, if a focus isn't already set within\n const elem = this.element.firstElementChild;\n if (elem instanceof HTMLElement) {\n elem.focus(); // first child of the portal element\n }\n }\n });\n\n this.setState({ popper });\n }\n\n destroyPopper(updateState = true): void {\n cancelAnimationFrame(this.rAF);\n\n const { popper } = this.state;\n if (!popper) {\n return;\n }\n\n popper.destroy();\n\n // If component is exiting and unmounted in\n // the same frame, destroy can be called twice.\n // Check to make sure removeChild isn't called twice.\n if (document.body.contains(this.element)) {\n document.body.removeChild(this.element);\n }\n\n if (updateState) {\n this.setState({ popper: null });\n }\n }\n\n show(): void {\n this.initPopper();\n this.setState({ show: true });\n }\n\n hide(): void {\n this.setState({ show: false });\n }\n\n scheduleUpdate(): void {\n const { popper } = this.state;\n if (popper) popper.scheduleUpdate();\n }\n\n handleBlur(e: React.FocusEvent): void {\n if (!(e.relatedTarget instanceof HTMLElement)) {\n return;\n }\n if (!this.element.contains(e.relatedTarget)) {\n this.hide();\n }\n }\n\n handleEnter(): void {\n const { onEntered } = this.props;\n onEntered(); // trigger any parent component waiting for enter handler\n }\n\n handleExit(): void {\n const { onExited } = this.props;\n const { show } = this.state;\n if (!show) {\n this.destroyPopper();\n }\n onExited(); // trigger any parent component waiting for exited handler\n }\n\n renderContent(): JSX.Element {\n const {\n className,\n children,\n timeout,\n interactive,\n closeOnBlur,\n } = this.props;\n const { show } = this.state;\n\n return (\n <CSSTransition\n in={show}\n timeout={timeout}\n classNames=\"popper-transition\"\n onEntered={this.handleEnter}\n onExited={this.handleExit}\n >\n <div\n onClick={e => {\n // stop click events from escaping popper\n e.stopPropagation();\n }}\n onKeyDown={e => {\n if (e.key === 'Escape') this.hide();\n }}\n className={classNames('popper', { interactive }, className)}\n onBlur={closeOnBlur ? this.handleBlur : undefined}\n tabIndex={closeOnBlur ? -1 : undefined}\n role=\"presentation\"\n >\n <div className=\"popper-content\">\n {children}\n <div className=\"popper-arrow\" x-arrow=\"\" />\n </div>\n </div>\n </CSSTransition>\n );\n }\n\n render(): JSX.Element {\n const { popper } = this.state;\n return (\n <div\n className=\"popper-parent-container\"\n ref={this.container}\n style={{ display: 'none' }}\n >\n {popper && ReactDOM.createPortal(this.renderContent(), this.element)}\n </div>\n );\n }\n}\n\nexport default Popper;\nexport type { PopperOptions, ReferenceObject };\n","import React, { Component } from 'react';\nimport classNames from 'classnames';\nimport Log from '@deephaven/log';\nimport Popper, { PopperOptions, ReferenceObject } from './Popper';\n\nconst log = Log.module('Tooltip');\n\ntype TooltipProps = typeof Tooltip.defaultProps & {\n children: React.ReactNode;\n interactive?: boolean;\n options?: PopperOptions;\n popperClassName?: string;\n reshowTimeout?: number;\n timeout?: number;\n referenceObject?: ReferenceObject | null;\n onExited?: () => void;\n};\ninterface TooltipState {\n isShown: boolean;\n}\n\n/**\n * Component that can be added to an element to automatically display a tooltip.\n * Content is mounted lazily, so don't worry about complex tooltips!\n *\n * Usage:\n * <div className=\"parent-container\">\n * Hover this container to see a tooltip\n * <Tooltip>\n * <div>My tooltip content goes here!</div>\n * </Tooltip>\n * </div>\n */\nclass Tooltip extends Component<TooltipProps, TooltipState> {\n static defaultTimeout = 500;\n\n static defaultReshowTimeout = 100;\n\n static triggerReshowThreshold = 300;\n\n static shownTooltipCount = 0;\n\n static lastHiddenTime = Date.now();\n\n static defaultProps = {\n interactive: false,\n options: {},\n popperClassName: '',\n reshowTimeout: Tooltip.defaultReshowTimeout,\n timeout: Tooltip.defaultTimeout,\n referenceObject: null,\n onExited: (): void => undefined,\n };\n\n static handleHidden(): void {\n Tooltip.shownTooltipCount -= 1;\n\n if (Tooltip.shownTooltipCount === 0) {\n Tooltip.lastHiddenTime = Date.now();\n }\n }\n\n static handleShown(): void {\n Tooltip.shownTooltipCount += 1;\n }\n\n constructor(props: TooltipProps) {\n super(props);\n\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleWindowMouseMove = this.handleWindowMouseMove.bind(this);\n this.handleWheel = this.handleWheel.bind(this);\n this.handleTimeout = this.handleTimeout.bind(this);\n this.handleExited = this.handleExited.bind(this);\n this.stopShowingTooltip = this.stopShowingTooltip.bind(this);\n\n this.container = React.createRef();\n this.popper = React.createRef();\n this.parent = null;\n this.timer = null;\n\n this.state = {\n isShown: false,\n };\n }\n\n componentDidMount(): void {\n this.startListening();\n\n const { timeout } = this.props;\n if (timeout === 0) {\n this.show();\n }\n }\n\n componentDidUpdate(prevProps: TooltipProps, prevState: TooltipState): void {\n const { isShown: oldIsShown } = prevState;\n const { isShown } = this.state;\n\n if (isShown !== oldIsShown) {\n if (isShown) {\n Tooltip.handleShown();\n } else {\n Tooltip.handleHidden();\n }\n }\n }\n\n componentWillUnmount(): void {\n this.stopListening();\n this.stopListeningWindow();\n this.stopTimer();\n\n const { isShown } = this.state;\n\n if (isShown) {\n Tooltip.handleHidden();\n }\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n popper: React.RefObject<Popper>;\n\n parent: HTMLElement | null;\n\n // This is platform dependent of Node/DOM\n // Jest requires Node types\n timer: number | null;\n\n startListening(): void {\n if (!this.container.current || !this.container.current.parentElement) {\n log.error(\"Tooltip doesn't have a container or a parent set!\");\n return;\n }\n\n this.parent = this.container.current.parentElement;\n this.parent.addEventListener('mousemove', this.handleMouseMove);\n this.parent.addEventListener('mouseleave', this.handleMouseLeave);\n this.parent.addEventListener('mousedown', this.stopShowingTooltip);\n }\n\n stopListening(): void {\n if (!this.parent) {\n return;\n }\n\n this.parent.removeEventListener('mousemove', this.handleMouseMove);\n this.parent.removeEventListener('mouseleave', this.handleMouseLeave);\n this.parent.removeEventListener('mousedown', this.stopShowingTooltip);\n }\n\n startListeningWindow(): void {\n window.addEventListener('mousemove', this.handleWindowMouseMove, true);\n window.addEventListener('contextmenu', this.stopShowingTooltip, true);\n window.addEventListener('wheel', this.handleWheel);\n }\n\n stopListeningWindow(): void {\n window.removeEventListener('mousemove', this.handleWindowMouseMove, true);\n window.removeEventListener('contextmenu', this.stopShowingTooltip, true);\n window.removeEventListener('wheel', this.handleWheel);\n }\n\n handleMouseMove(): void {\n this.startTimer();\n }\n\n handleWheel(): void {\n const { isShown } = this.state;\n if (this.popper.current && this.parent && isShown) {\n if (\n !this.popper.current.element.matches(':hover') &&\n !this.parent.matches(':hover')\n ) {\n this.stopTimer();\n this.hide();\n }\n }\n }\n\n handleMouseLeave(): void {\n const { isShown } = this.state;\n this.stopTimer();\n\n const { interactive } = this.props;\n if (!interactive && isShown) {\n this.hide();\n }\n }\n\n handleTimeout(): void {\n this.show();\n }\n\n handleWindowMouseMove(event: MouseEvent): void {\n const mouseX = event.clientX;\n const mouseY = event.clientY;\n const { isShown } = this.state;\n\n if (!this.popper.current || !this.parent) {\n return;\n }\n const popperRect = this.popper.current.element.getBoundingClientRect();\n const parentRect = this.parent.getBoundingClientRect();\n\n if (\n mouseX >= popperRect.left &&\n mouseX <= popperRect.left + popperRect.width &&\n mouseY >= popperRect.top &&\n mouseY <= popperRect.top + popperRect.height\n ) {\n this.handleMouseMove();\n } else if (\n mouseX >= parentRect.left &&\n mouseX <= parentRect.left + parentRect.width &&\n mouseY >= parentRect.top &&\n mouseY <= parentRect.top + parentRect.height\n ) {\n this.handleMouseMove();\n } else if (isShown) {\n this.stopTimer();\n this.hide();\n }\n }\n\n startTimer(): void {\n this.stopTimer();\n\n const { timeout, reshowTimeout } = this.props;\n let timerTimeout = timeout;\n if (\n Tooltip.shownTooltipCount > 0 ||\n Date.now() - Tooltip.lastHiddenTime < Tooltip.triggerReshowThreshold\n ) {\n timerTimeout = reshowTimeout;\n }\n this.timer = window.setTimeout(this.handleTimeout, timerTimeout);\n }\n\n stopTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n\n show(): void {\n const { isShown } = this.state;\n this.stopTimer();\n\n if (!isShown) {\n this.popper.current?.show();\n this.setState({ isShown: true });\n\n const { interactive } = this.props;\n if (interactive) {\n this.startListeningWindow();\n }\n }\n }\n\n hide(): void {\n this.popper.current?.hide();\n this.stopListeningWindow();\n }\n\n update(): void {\n this.popper.current?.scheduleUpdate();\n }\n\n handleExited(): void {\n this.setState({ isShown: false });\n const { onExited } = this.props;\n onExited();\n }\n\n stopShowingTooltip(): void {\n const { isShown } = this.state;\n this.stopTimer();\n if (isShown) {\n this.hide();\n }\n }\n\n render(): JSX.Element {\n const {\n interactive,\n children,\n options,\n referenceObject,\n popperClassName,\n } = this.props;\n const { isShown } = this.state;\n return (\n <div ref={this.container} style={{ display: 'none' }}>\n <Popper\n className={classNames(popperClassName)}\n options={options}\n ref={this.popper}\n onExited={this.handleExited}\n interactive={interactive}\n referenceObject={referenceObject}\n >\n <div className=\"tooltip-content\"> {isShown && children}</div>\n </Popper>\n </div>\n );\n }\n}\n\nexport default Tooltip;\n","import { useEffect, useRef } from 'react';\n\n// From https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state\nexport default function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T>();\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n}\n","import React, { useState, useEffect, useMemo, useCallback } from 'react';\nimport { CSSTransition } from 'react-transition-group';\nimport { usePrevious } from '@deephaven/react-hooks';\nimport ThemeExport from '../ThemeExport';\nimport './Stack.scss';\n\nexport type StackProps = {\n children: React.ReactNode | React.ReactNode[];\n};\n\n/**\n * Pass a full navigation stack of children, and then automatically does a sliding animation when the stack changes.\n * Adding items to the stack will do a \"push\" animation, and removing items from the stack will do a \"pop\" animation.\n */\nexport const Stack = ({ children }: StackProps): JSX.Element => {\n const childrenArray = useMemo(() => React.Children.toArray(children), [\n children,\n ]);\n const prevChildrenArray = usePrevious(childrenArray);\n const [mainView, setMainView] = useState<React.ReactNode>(\n childrenArray[childrenArray.length - 1]\n );\n\n const [pushingView, setPushingView] = useState<React.ReactNode>(null);\n const [poppingView, setPoppingView] = useState<React.ReactNode>(null);\n\n /**\n * To do the animation effect, we just need to set the proper pushing/popping views when the stack changes.\n * `mainView` - The main view of the stack, stationary, filling the container.\n * `pushingView` - A view that's currently being pushed. Slides from off screen right to overtop of `mainView`.\n * `poppingView` - A view that's currently being popped. Slides from overtop of `mainView` to right off screen.\n *\n * When the `pushingView` or `poppingView` is set, that will kick off their animation.\n * Completion of the animation is handled in `pushComplete` or `popComplete`, and then the stack is in an idle state again.\n */\n useEffect(() => {\n if (\n prevChildrenArray === undefined ||\n childrenArray === prevChildrenArray\n ) {\n return;\n }\n const topChild = childrenArray[childrenArray.length - 1];\n if (\n childrenArray.length === prevChildrenArray.length ||\n prevChildrenArray.length === 0 ||\n pushingView !== null ||\n poppingView !== null\n ) {\n // 1) Stack is the same size, we've just mounted, or we're already in an animation - just update the view\n if (pushingView !== null && topChild !== pushingView) {\n // Stack was updated mid animation\n setPushingView(topChild);\n } else if (topChild !== poppingView && topChild !== mainView) {\n // Replace the current view\n setMainView(topChild);\n }\n } else if (childrenArray.length > prevChildrenArray.length) {\n // 2) Stack has grown - start the push animation\n setPushingView(topChild);\n } else if (childrenArray.length < prevChildrenArray.length) {\n // 3) Stack has shrunk - start the pop animation\n setMainView(topChild);\n setPoppingView(prevChildrenArray[prevChildrenArray.length - 1]);\n }\n }, [childrenArray, prevChildrenArray, pushingView, poppingView, mainView]);\n\n const pushComplete = useCallback(() => {\n setMainView(pushingView);\n setPushingView(null);\n }, [pushingView]);\n\n const popComplete = useCallback(() => {\n setPoppingView(null);\n }, []);\n\n return (\n <div className=\"navigation-stack\">\n <div className=\"main-view\">{mainView}</div>\n\n <CSSTransition\n in={poppingView != null}\n timeout={ThemeExport.transitionMidMs}\n classNames=\"slide-right\"\n onEntered={popComplete}\n >\n <>{poppingView && <div className=\"popping-view\">{poppingView}</div>}</>\n </CSSTransition>\n <CSSTransition\n in={pushingView != null}\n timeout={ThemeExport.transitionMidMs}\n classNames=\"slide-left\"\n onEntered={pushComplete}\n >\n <>{pushingView && <div className=\"pushing-view\">{pushingView}</div>}</>\n </CSSTransition>\n </div>\n );\n};\n\nexport default Stack;\n","import React from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsClose, vsChevronLeft } from '@deephaven/icons';\nimport './Page.scss';\n\nexport type PageProps = {\n children: React.ReactNode;\n onBack?: () => void;\n onClose?: () => void;\n title: string;\n};\n\n/**\n * A page view with a back button in the bottom left, a title at the top, and a close button in the top right.\n * Back and close buttons will only appear if `onBack` and/or `onClose` callbacks are set.\n */\nexport const Page = ({\n children,\n onBack,\n onClose,\n title,\n}: PageProps): JSX.Element => (\n <div className=\"navigation-page\">\n <div className=\"navigation-title-bar\">\n <div className=\"navigation-left-buttons\">\n {onBack !== undefined && (\n <button\n className=\"btn btn-link btn-back\"\n type=\"button\"\n onClick={onBack}\n >\n <FontAwesomeIcon icon={vsChevronLeft} />\n Back\n </button>\n )}\n </div>\n <div className=\"navigation-title\">{title}</div>\n <div className=\"navigation-right-buttons\">\n {onClose !== undefined && (\n <button\n className=\"btn btn-link btn-link-icon btn-close px-2 m-1\"\n type=\"button\"\n onClick={onClose}\n >\n <FontAwesomeIcon icon={vsClose} />\n </button>\n )}\n </div>\n </div>\n <div className=\"navigation-content\">{children}</div>\n </div>\n);\n\nexport default Page;\n","import React from 'react';\nimport classNames from 'classnames';\nimport './UISwitch.scss';\n\ntype UISwitchProps = {\n on: boolean;\n onClick: React.MouseEventHandler<HTMLButtonElement>;\n id?: string;\n className?: string;\n isInvalid?: boolean;\n disabled?: boolean;\n};\n\nconst UISwitch = ({\n on,\n id,\n className,\n isInvalid,\n disabled = false,\n onClick,\n}: UISwitchProps): JSX.Element => (\n <button\n type=\"button\"\n className={classNames(\n 'btn',\n 'btn-switch',\n className,\n { active: on },\n { 'is-invalid': isInvalid }\n )}\n id={id}\n onClick={onClick}\n disabled={disabled}\n >\n <div className=\"handle\" />\n </button>\n);\n\nexport default UISwitch;\n","import React, { useMemo } from 'react';\nimport { IconProp } from '@fortawesome/fontawesome-svg-core';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsChevronRight } from '@deephaven/icons';\nimport './MenuItem.scss';\n\nimport UISwitch from '../UISwitch';\n\nexport type MenuItemDef = {\n title: string;\n subtitle?: string;\n icon?: IconProp;\n};\n\nexport type SwitchMenuItemDef = MenuItemDef & {\n isOn: boolean;\n onChange: (isOn: boolean) => void;\n};\n\nfunction isSwitchMenuItemType(item: MenuItemDef): item is SwitchMenuItemDef {\n return (item as SwitchMenuItemDef).isOn !== undefined;\n}\n\nexport type MenuItemProps = {\n item: MenuItemDef;\n onSelect?: () => void;\n};\n\n/**\n * @param props.item The menu item to set. Set a SwitchMenuItemDef to show a switch.\n * @param props.onSelect Called when the menu item is selected\n */\nexport const MenuItem = ({\n item,\n onSelect = () => undefined,\n}: MenuItemProps): JSX.Element => {\n const { icon, subtitle, title } = item;\n const handleSelect = useMemo(() => {\n if (isSwitchMenuItemType(item)) {\n return () => {\n item.onChange(!item.isOn);\n };\n }\n return onSelect;\n }, [item, onSelect]);\n return (\n <div\n className=\"btn btn-navigation-menu-item\"\n onClick={handleSelect}\n onKeyDown={event => {\n if (event.key === 'Enter' || event.key === ' ') {\n handleSelect();\n }\n }}\n tabIndex={0}\n role=\"menuitem\"\n >\n {icon && (\n <div className=\"icon\">\n <FontAwesomeIcon icon={icon} />\n </div>\n )}\n <div className=\"title\">{title}</div>\n {subtitle && <div className=\"shortcut\">{subtitle}</div>}\n <div className=\"accessory\">\n {(isSwitchMenuItemType(item) && (\n <UISwitch\n on={item.isOn}\n onClick={event => {\n event.stopPropagation();\n handleSelect();\n }}\n />\n )) || <FontAwesomeIcon icon={vsChevronRight} />}\n </div>\n </div>\n );\n};\n\nexport default MenuItem;\n","import React from 'react';\nimport MenuItem, { MenuItemDef } from './MenuItem';\nimport './Menu.scss';\n\nexport type MenuSelectCallback = (itemIndex: number) => void;\n\nexport type MenuProps = {\n items: MenuItemDef[];\n onSelect?: MenuSelectCallback;\n};\n\nexport const Menu = ({\n items,\n onSelect = () => undefined,\n}: MenuProps): JSX.Element => (\n <div className=\"navigation-menu-view\">\n <ul className=\"navigation-menu-list\">\n {items.map((item, itemIndex) => (\n <li key={item.title}>\n <MenuItem\n item={item}\n onSelect={() => {\n onSelect(itemIndex);\n }}\n />\n </li>\n ))}\n </ul>\n </div>\n);\n\nexport default Menu;\n","import { Component } from 'react';\nimport Log from '@deephaven/log';\nimport ContextActionUtils from './ContextActionUtils';\nimport type { ContextAction, ContextActionEvent } from './ContextActionUtils';\n\nconst log = Log.module('GlobalContextAction');\n\ninterface GlobalContextActionProps {\n action: ContextAction;\n}\n\nclass GlobalContextAction extends Component<GlobalContextActionProps> {\n constructor(props: GlobalContextActionProps) {\n super(props);\n\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount(): void {\n document.body.addEventListener('contextmenu', this.handleContextMenu);\n document.body.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount(): void {\n document.body.removeEventListener('contextmenu', this.handleContextMenu);\n document.body.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleContextMenu(evt: MouseEvent): void {\n const e = evt as ContextActionEvent;\n if (!e.contextActions) {\n e.contextActions = [];\n }\n\n const { action } = this.props;\n\n if (!action.title && !action.menuElement) {\n return;\n }\n\n if (!e.contextActions) {\n e.contextActions = [];\n }\n\n e.contextActions.push(action);\n\n log.debug(\n 'Received context menu event at global action! Menu items are now: ',\n e.contextActions\n );\n }\n\n handleKeyDown(e: KeyboardEvent): void {\n const { action } = this.props;\n if (\n !ContextActionUtils.actionsDisabled &&\n action.shortcut?.matchesEvent(e)\n ) {\n log.debug('Global hotkey matched!', e);\n\n const result = action.action?.(e);\n\n if (result || result === undefined) {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n }\n\n render(): null {\n return null;\n }\n}\n\nexport default GlobalContextAction;\n","import React, { Component } from 'react';\nimport GlobalContextAction from './GlobalContextAction';\nimport type { ContextAction } from './ContextActionUtils';\n\ninterface GlobalContextActionsProps {\n actions: ContextAction[];\n}\n\nclass GlobalContextActions extends Component<GlobalContextActionsProps> {\n render(): React.ReactNode {\n const { actions } = this.props;\n const actionElements = [];\n for (let i = 0; i < actions.length; i += 1) {\n const action = actions[i];\n const { shortcut } = action;\n if (action.title || action.menuElement || shortcut) {\n const actionElement = (\n <GlobalContextAction\n key={`${action.title}.${shortcut?.id}`}\n action={action}\n />\n );\n actionElements.push(actionElement);\n }\n }\n return actionElements;\n }\n}\n\nexport default GlobalContextActions;\n","/**\n * Just a simple utility class for displaying a popup menu.\n */\nimport React, { Component } from 'react';\nimport Log from '@deephaven/log';\nimport ContextActionUtils from './ContextActionUtils';\nimport type { ContextAction, ContextActionEvent } from './ContextActionUtils';\nimport GlobalContextActions from './GlobalContextActions';\nimport './ContextActions.scss';\n\nconst log = Log.module('ContextActions');\n\ninterface ContextActionsProps {\n actions: ContextAction[] | (() => ContextAction[]);\n ignoreClassNames?: string[];\n}\n\ninterface ContextActionsState {\n globalActions: ContextAction[];\n keyboardActions: ContextAction[];\n}\n\n/**\n * ContextActions that you add onto any component.\n *\n * Usage:\n * let actions = [{\n * title: 'My Action', // Omit the title to hide it from the context menu\n * action: () => { alert('My Action Clicked!') }\n * actions: [] // Submenu of actions\n * icon: faPrint, // Limited to FontAwesome icons for now.\n * iconColor: '#ff0000, // Color to use for the icon\n * shortcut: Shortcut, // Defaults to null\n * isGlobal: false, // Global context action. Defaults to false.\n * group: ContextActions.groups.default, // What group to group the context action with\n * order: null, // Int where to order within group\n * disabled: true // disable action\n * menuElement: null // Custom menu element for displaying in context menu. When null, creates a default menu item based on title\n * }];\n *\n * <div>\n * Right click in this container\n * <ContextActions actions={actions}/>\n * </div>\n *\n * Right clicking the container will then build the context menu, bubbling up until an element with a ContextMenuRoot is on it.\n * You should generally have a ContextMenuRoot on the root node of your document.\n */\nclass ContextActions extends Component<\n ContextActionsProps,\n ContextActionsState\n> {\n /**\n * Group you can assign to context menu actions to group them together.\n * Lower group IDs appear at the top of the list.\n * Groups are separated by a separator item.\n * Items within groups are ordered by their order property, then by their title.\n */\n static groups = {\n default: null,\n high: 100,\n medium: 5000,\n low: 10000,\n global: 100000,\n\n edit: 100,\n };\n\n static triggerMenu(\n element: Element,\n clientX: number,\n clientY: number,\n actions: ContextAction[]\n ): void {\n if (!element || !clientX || !clientY || !actions) {\n return;\n }\n\n const mouseEvent: Partial<ContextActionEvent> = new MouseEvent(\n 'contextmenu',\n {\n clientX,\n clientY,\n bubbles: true,\n cancelable: true,\n }\n );\n mouseEvent.contextActions = actions;\n\n element.dispatchEvent(mouseEvent as ContextActionEvent);\n }\n\n constructor(props: ContextActionsProps) {\n super(props);\n\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n\n this.container = React.createRef();\n\n this.state = { globalActions: [], keyboardActions: [] };\n }\n\n static getDerivedStateFromProps(\n props: ContextActionsProps\n ): ContextActionsState {\n if (!props.actions || !Array.isArray(props.actions)) {\n return { globalActions: [], keyboardActions: [] };\n }\n const globalActions = props.actions.filter(action => action.isGlobal);\n const keyboardActions = props.actions.filter(\n action => !action.isGlobal && action.shortcut != null\n );\n\n return { globalActions, keyboardActions };\n }\n\n componentDidMount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.addEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n this.container.current.parentElement.addEventListener(\n 'keydown',\n this.handleKeyDown\n );\n }\n }\n\n componentWillUnmount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.removeEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n this.container.current.parentElement.removeEventListener(\n 'keydown',\n this.handleKeyDown\n );\n }\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n handleContextMenu(e: MouseEvent): void {\n const { ignoreClassNames = [] } = this.props;\n if (ignoreClassNames.length > 0) {\n let el = e.target as Element | null;\n while (el != null) {\n const { classList } = el;\n const ignoredClassName = ignoreClassNames.find(className =>\n classList.contains(className)\n );\n if (ignoredClassName !== undefined) {\n log.debug2(\n `Contextmenu event ignored based on the target className \"${ignoredClassName}\"`\n );\n return;\n }\n el = el.parentElement;\n }\n }\n if (!ContextActionUtils.isContextActionEvent(e)) {\n (e as ContextActionEvent).contextActions = [];\n }\n\n if (!ContextActionUtils.isContextActionEvent(e)) {\n return;\n }\n\n const { actions } = this.props;\n if (actions) {\n let contextActions = actions;\n if (Array.isArray(contextActions)) {\n contextActions = contextActions.filter(action => !action.isGlobal);\n }\n\n e.contextActions = e.contextActions.concat(contextActions);\n }\n\n log.debug(\n 'Received context menu event! Menu items are now: ',\n e.contextActions\n );\n }\n\n handleKeyDown(e: KeyboardEvent): void {\n const { keyboardActions } = this.state;\n for (let i = 0; i < keyboardActions.length; i += 1) {\n const keyboardAction = keyboardActions[i];\n if (\n !ContextActionUtils.actionsDisabled &&\n keyboardAction.shortcut?.matchesEvent(e)\n ) {\n log.debug('Context hotkey matched!', e);\n\n const result = keyboardAction.action?.(e);\n\n if (result || result === undefined) {\n e.stopPropagation();\n e.preventDefault();\n return;\n }\n\n log.debug2('Matched hotkey returned false, key event not consumed');\n }\n }\n }\n\n render(): JSX.Element {\n const { globalActions } = this.state;\n return (\n <div className=\"context-actions-listener\" ref={this.container}>\n <GlobalContextActions actions={globalActions} />\n </div>\n );\n }\n}\n\nexport default ContextActions;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { IconDefinition } from '@fortawesome/fontawesome-svg-core';\nimport { Tooltip } from './popper';\n\nconst BUTTON_KINDS = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'danger',\n 'inline',\n 'ghost',\n] as const;\ntype ButtonTuple = typeof BUTTON_KINDS;\ntype ButtonKind = ButtonTuple[number];\n\nconst VARIANT_KINDS = ['group-end'] as const;\ntype VariantTuple = typeof VARIANT_KINDS;\ntype VariantKind = VariantTuple[number];\n\ntype ButtonTypes = 'submit' | 'reset' | 'button';\n\ninterface BaseButtonProps extends React.ComponentPropsWithRef<'button'> {\n kind: ButtonKind;\n type?: ButtonTypes;\n variant?: VariantKind;\n tooltip?: string | JSX.Element;\n icon?: IconDefinition | JSX.Element;\n active?: boolean;\n}\n\ntype ButtonWithChildren = BaseButtonProps & {\n children: React.ReactNode;\n};\n\ntype IconOnlyButton = BaseButtonProps & {\n tooltip: string | JSX.Element;\n icon: IconDefinition | JSX.Element;\n children?: undefined;\n};\n\ntype ButtonProps = IconOnlyButton | ButtonWithChildren;\n\nfunction getClassName(kind: ButtonKind, iconOnly: boolean): string {\n switch (kind) {\n case 'primary':\n return 'btn-primary';\n case 'secondary':\n return 'btn-outline-primary';\n case 'tertiary':\n return 'btn-secondary';\n case 'success':\n return 'btn-success';\n case 'danger':\n return 'btn-danger';\n case 'inline':\n return 'btn-inline';\n case 'ghost':\n return classNames('btn-link', {\n 'btn-link-icon': iconOnly,\n 'px-2': iconOnly,\n });\n }\n}\n\nfunction getVariantClasses(kind: VariantKind): string {\n switch (kind) {\n case 'group-end':\n return classNames('pl-2', 'pr-3');\n }\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (props: ButtonProps, ref) => {\n const {\n kind,\n variant,\n type,\n tooltip,\n icon,\n disabled,\n active,\n onClick,\n className,\n style,\n children,\n } = props;\n\n const iconOnly = (icon && !children) as boolean;\n const btnClassName = getClassName(kind, iconOnly);\n\n let variantClassName;\n if (variant) {\n variantClassName = getVariantClasses(variant);\n }\n\n let iconElem: JSX.Element | undefined;\n if (icon) {\n iconElem = React.isValidElement(icon) ? (\n icon\n ) : (\n <FontAwesomeIcon icon={icon as IconDefinition} />\n );\n }\n\n let tooltipElem: JSX.Element | undefined;\n if (tooltip) {\n tooltipElem =\n typeof tooltip === 'string' ? <Tooltip>{tooltip}</Tooltip> : tooltip;\n }\n\n const button = (\n <button\n ref={ref}\n // eslint-disable-next-line react/button-has-type\n type={type}\n className={classNames(\n 'btn',\n btnClassName,\n variantClassName,\n { active },\n className\n )}\n onClick={onClick}\n style={style}\n disabled={disabled}\n >\n {icon && iconElem}\n {children}\n {tooltip && !disabled && tooltipElem}\n </button>\n );\n\n // disabled buttons tooltips need a wrapped element to receive pointer events\n // https://jakearchibald.com/2017/events-and-disabled-form-fields/\n\n return disabled ? (\n <span className=\"btn-disabled-wrapper\">\n {button}\n {tooltip && tooltipElem}\n </span>\n ) : (\n button\n );\n }\n);\n\nButton.displayName = 'Button';\n\nButton.propTypes = {\n kind: PropTypes.oneOf(BUTTON_KINDS).isRequired,\n variant: PropTypes.oneOf(VARIANT_KINDS),\n type: PropTypes.oneOf<ButtonTypes>(['submit', 'reset', 'button']),\n tooltip(props) {\n const { tooltip, icon, children } = props;\n if (!tooltip && icon && !children) {\n return new Error('Tooltip is required for icon only buttons');\n }\n return null;\n },\n icon(props) {\n const { children, icon } = props;\n if (!icon && !children) {\n return new Error('Icon is required if no children are provided');\n }\n\n if (!children && !React.isValidElement(icon) && !icon?.iconName) {\n return new Error(\n 'Icon must be react element or fontawesome IconDefinition'\n );\n }\n\n return null;\n },\n disabled: PropTypes.bool,\n active: PropTypes.bool,\n onClick(props) {\n const { onClick, type } = props;\n if (type === 'button' && typeof onClick !== 'function') {\n return new Error('type button requires an onClick function');\n }\n if (onClick !== undefined && typeof onClick !== 'function') {\n return new Error('onClick must be a function');\n }\n return null;\n },\n children: PropTypes.node,\n className: PropTypes.string,\n style: PropTypes.object,\n};\n\nButton.defaultProps = {\n type: 'button',\n onClick: undefined,\n variant: undefined,\n tooltip: undefined,\n icon: undefined,\n disabled: false,\n active: undefined,\n children: undefined,\n className: undefined,\n style: {},\n};\n\nexport default Button;\n","import React from 'react';\nimport classNames from 'classnames';\nimport { CSSTransition } from 'react-transition-group';\nimport { ThemeExport } from '@deephaven/components';\nimport './IrisGridBottomBar.scss';\n\nexport type IrisGridBottomBarProps = {\n animation?: string;\n children: React.ReactNode;\n onClick?: () => void;\n onEntering?: () => void;\n onEntered?: () => void;\n onExiting?: () => void;\n onExited?: () => void;\n isShown: boolean;\n className?: string;\n};\n\nexport const IrisGridBottomBar = ({\n animation = 'iris-grid-bottom-bar-slide-up',\n children,\n className,\n isShown,\n onClick,\n onEntering,\n onEntered,\n onExiting,\n onExited,\n}: IrisGridBottomBarProps): JSX.Element => (\n <CSSTransition\n in={isShown}\n timeout={ThemeExport.transitionMs}\n classNames={animation}\n onEntering={onEntering}\n onEntered={onEntered}\n onExiting={onExiting}\n onExited={onExited}\n mountOnEnter\n unmountOnExit\n >\n <div\n className={classNames('iris-grid-bottom-bar', className)}\n role=\"presentation\"\n onClick={onClick}\n onKeyPress={onClick}\n >\n {children}\n </div>\n </CSSTransition>\n);\n\nexport default IrisGridBottomBar;\n","import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsPass, vsWarning } from '@deephaven/icons';\nimport { Button, LoadingSpinner } from '@deephaven/components';\nimport { usePrevious } from '@deephaven/react-hooks';\nimport IrisGridBottomBar from './IrisGridBottomBar';\nimport './PendingDataBottomBar.scss';\n\nconst HIDE_TIMEOUT = 3000;\n\nconst MAX_NUMBER_ROWS_SHOWN = 5;\n\nexport type PendingDataBottomBarProps = {\n onSave: () => Promise<void>;\n onDiscard: () => Promise<void>;\n discardTooltip?: string;\n saveTooltip?: string;\n isSaving?: boolean;\n error?: string;\n pendingDataErrors: Map<number, Error[]>;\n pendingDataMap: Map<number, { data: Map<number, { value: unknown }> }>;\n onEntering?: () => void;\n onEntered?: () => void;\n onExiting?: () => void;\n onExited?: () => void;\n};\n\nexport const PendingDataBottomBar = ({\n isSaving = false,\n onSave,\n onDiscard,\n discardTooltip,\n saveTooltip,\n error,\n pendingDataErrors,\n pendingDataMap,\n onEntering,\n onEntered,\n onExiting,\n onExited,\n}: PendingDataBottomBarProps): JSX.Element => {\n const [isSuccessShown, setIsSuccessShown] = useState(false);\n const [wasSuccessShown, setWasSuccessShown] = useState(false);\n const successTimeout = useRef<ReturnType<typeof setTimeout>>();\n const prevIsSaving = usePrevious(isSaving);\n const errorMessage = useMemo(() => {\n if (pendingDataErrors.size === 0) {\n return error;\n }\n if (pendingDataErrors.size <= MAX_NUMBER_ROWS_SHOWN) {\n return `Key can't be empty (on pending row${\n pendingDataErrors.size > 1 ? 's' : ''\n } ${Array.from(pendingDataErrors.keys()).join(', ').trim()})`;\n }\n return `Key can't be empty (on ${pendingDataErrors.size} rows)`;\n }, [error, pendingDataErrors]);\n\n useEffect(() => {\n if (prevIsSaving && !isSaving && errorMessage == null) {\n setIsSuccessShown(true);\n setWasSuccessShown(true);\n successTimeout.current = setTimeout(() => {\n setIsSuccessShown(false);\n }, HIDE_TIMEOUT);\n }\n }, [errorMessage, isSaving, prevIsSaving]);\n\n useEffect(() => {\n if (successTimeout.current && pendingDataMap.size > 0) {\n // A change just occurred while the success message was still being shown, just hide the success message\n clearTimeout(successTimeout.current);\n setIsSuccessShown(false);\n setWasSuccessShown(false);\n }\n }, [pendingDataMap]);\n\n useEffect(\n () => () =>\n successTimeout.current ? clearTimeout(successTimeout.current) : undefined,\n []\n );\n\n const pendingRowCount = pendingDataMap.size;\n let commitIcon;\n if (isSaving) {\n commitIcon = <LoadingSpinner />;\n } else if (wasSuccessShown) {\n commitIcon = vsPass;\n }\n\n return (\n <IrisGridBottomBar\n className=\"pending-data-bottom-bar\"\n isShown={pendingRowCount > 0 || isSuccessShown || errorMessage != null}\n onEntering={onEntering}\n onEntered={onEntered}\n onExiting={onExiting}\n onExited={() => {\n setWasSuccessShown(false);\n if (onExited) {\n onExited();\n }\n }}\n >\n {errorMessage && (\n <div className=\"error-message\">\n <FontAwesomeIcon icon={vsWarning} />\n <span>{`${errorMessage}`}</span>\n </div>\n )}\n {!errorMessage && (\n <div className=\"status-message\">\n {pendingRowCount > 0 && (\n <span>{`${pendingRowCount} row${\n pendingRowCount > 1 ? 's' : ''\n } pending`}</span>\n )}\n </div>\n )}\n <div className=\"buttons-container\">\n {!isSaving && !wasSuccessShown && (\n <Button kind=\"secondary\" onClick={onDiscard} tooltip={discardTooltip}>\n Discard\n </Button>\n )}\n <Button\n kind={wasSuccessShown ? 'success' : 'primary'}\n onClick={onSave}\n icon={commitIcon}\n disabled={isSaving || wasSuccessShown || errorMessage != null}\n tooltip={saveTooltip}\n >\n {isSaving && `Committing...`}\n {!isSaving && wasSuccessShown && `Success`}\n {!isSaving && !wasSuccessShown && `Commit`}\n </Button>\n </div>\n </IrisGridBottomBar>\n );\n};\n\nexport default PendingDataBottomBar;\n","import React, { Component } from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport { CSSTransition } from 'react-transition-group';\nimport {\n ContextActionUtils,\n LoadingSpinner,\n ThemeExport,\n} from '@deephaven/components';\nimport { GridRange, GridUtils } from '@deephaven/grid';\nimport { CanceledPromiseError, PromiseUtils } from '@deephaven/utils';\nimport Log from '@deephaven/log';\nimport IrisGridModel from './IrisGridModel';\nimport IrisGridUtils from './IrisGridUtils';\nimport IrisGridBottomBar from './IrisGridBottomBar';\nimport './IrisGridCopyHandler.scss';\n\nconst log = Log.module('IrisGridCopyHandler');\n\n/**\n * Component for handling copying of data from the Iris Grid.\n * - Prompts if necessary (large amount of rows copied)\n * - Tries to async copy, falls back to showing a \"Click to Copy\" button if that fails\n */\nclass IrisGridCopyHandler extends Component {\n static NO_PROMPT_THRESHOLD = 10000;\n\n static HIDE_TIMEOUT = 3000;\n\n /**\n * Different states for the current copy operation\n */\n static COPY_STATES = {\n // No copy operation in progress\n IDLE: 'IDLE',\n\n // Large copy operation, confirmation required\n CONFIRMATION_REQUIRED: 'CONFIRMATION_REQUIRED',\n\n // Fetch is currently in progress\n FETCH_IN_PROGRESS: 'FETCH_IN_PROGRESS',\n\n // There was an error fetching the data\n FETCH_ERROR: 'FETCH_ERROR',\n\n // Click is required to copy\n CLICK_REQUIRED: 'CLICK_REQUIRED',\n\n // The copy operation is completed and successfully copied to the clipboard\n DONE: 'DONE',\n };\n\n static BUTTON_STATES = {\n COPY: 'COPY',\n FETCH_IN_PROGRESS: 'FETCH_IN_PROGRESS',\n CLICK_TO_COPY: 'CLICK_TO_COPY',\n RETRY: 'RETRY',\n };\n\n static getStatusMessageText(copyState, rowCount) {\n switch (copyState) {\n case IrisGridCopyHandler.COPY_STATES.CONFIRMATION_REQUIRED:\n return `Are you sure you want to copy ${rowCount.toLocaleString()} rows to your clipboard?`;\n case IrisGridCopyHandler.COPY_STATES.CLICK_REQUIRED:\n return `Fetched ${rowCount.toLocaleString()} rows!`;\n case IrisGridCopyHandler.COPY_STATES.FETCH_ERROR:\n return 'Unable to copy data.';\n case IrisGridCopyHandler.COPY_STATES.FETCH_IN_PROGRESS:\n return `Fetching ${rowCount.toLocaleString()} rows for clipboard...`;\n case IrisGridCopyHandler.COPY_STATES.DONE:\n return 'Copied to Clipboard!';\n default:\n return '';\n }\n }\n\n static getCopyButtonText(buttonState) {\n switch (buttonState) {\n case IrisGridCopyHandler.BUTTON_STATES.FETCH_IN_PROGRESS:\n return 'Fetching';\n case IrisGridCopyHandler.BUTTON_STATES.CLICK_TO_COPY:\n return 'Click to Copy';\n case IrisGridCopyHandler.BUTTON_STATES.RETRY:\n return 'Retry';\n default:\n return 'Copy';\n }\n }\n\n constructor(props) {\n super(props);\n\n this.handleBackgroundClick = this.handleBackgroundClick.bind(this);\n this.handleCancelClick = this.handleCancelClick.bind(this);\n this.handleCopyClick = this.handleCopyClick.bind(this);\n this.handleHideTimeout = this.handleHideTimeout.bind(this);\n\n this.textData = null;\n this.hideTimer = null;\n this.fetchPromise = null;\n\n this.state = {\n error: null,\n copyState: IrisGridCopyHandler.COPY_STATES.IDLE,\n buttonState: IrisGridCopyHandler.BUTTON_STATES.COPY,\n isShown: false,\n rowCount: 0,\n };\n }\n\n componentDidMount() {\n const { copyOperation } = this.props;\n if (copyOperation != null) {\n this.startCopy();\n }\n }\n\n componentDidUpdate(prevProps) {\n const { copyOperation } = this.props;\n if (prevProps.copyOperation !== copyOperation) {\n this.startCopy();\n }\n }\n\n componentWillUnmount() {\n this.stopCopy();\n }\n\n startCopy() {\n log.debug2('startCopy');\n\n this.stopCopy();\n\n const { copyOperation } = this.props;\n if (copyOperation == null) {\n log.debug2('No copy operation set, cancelling out');\n this.setState({ isShown: false });\n return;\n }\n\n const { ranges, error } = copyOperation;\n if (error != null) {\n log.debug('Showing copy error', error);\n this.setState({\n isShown: true,\n copyState: IrisGridCopyHandler.COPY_STATES.DONE,\n error,\n });\n this.startHideTimer();\n return;\n }\n\n const rowCount = GridRange.rowCount(ranges);\n\n this.setState({ rowCount, isShown: true, error: null });\n\n if (rowCount > IrisGridCopyHandler.NO_PROMPT_THRESHOLD) {\n this.setState({\n buttonState: IrisGridCopyHandler.BUTTON_STATES.COPY,\n copyState: IrisGridCopyHandler.COPY_STATES.CONFIRMATION_REQUIRED,\n });\n } else {\n this.startFetch();\n }\n }\n\n stopCopy() {\n this.textData = null;\n this.stopFetch();\n this.stopHideTimer();\n }\n\n handleBackgroundClick() {\n log.debug2('handleBackgroundClick');\n\n const { copyState } = this.state;\n if (copyState === IrisGridCopyHandler.COPY_STATES.DONE) {\n this.setState({ isShown: false });\n }\n }\n\n handleCancelClick() {\n log.debug2('handleCancelClick');\n\n this.stopFetch();\n this.setState({ isShown: false });\n }\n\n handleCopyClick() {\n log.debug2('handleCopyClick');\n\n if (this.textData != null) {\n this.copyText(this.textData);\n } else {\n this.startFetch();\n }\n }\n\n handleHideTimeout() {\n log.debug2('handleHideTimeout');\n\n this.stopHideTimer();\n\n this.setState({ isShown: false });\n }\n\n copyText(text) {\n log.debug2('copyText', text);\n\n this.textData = text;\n\n ContextActionUtils.copyToClipboard(text).then(\n () => {\n this.setState({ copyState: IrisGridCopyHandler.COPY_STATES.DONE });\n this.startHideTimer();\n },\n error => {\n log.error('copyText error', error);\n this.setState({\n buttonState: IrisGridCopyHandler.BUTTON_STATES.CLICK_TO_COPY,\n copyState: IrisGridCopyHandler.COPY_STATES.CLICK_REQUIRED,\n });\n }\n );\n }\n\n startFetch() {\n this.stopFetch();\n\n this.setState({\n buttonState: IrisGridCopyHandler.BUTTON_STATES.FETCH_IN_PROGRESS,\n copyState: IrisGridCopyHandler.COPY_STATES.FETCH_IN_PROGRESS,\n });\n\n const { model, copyOperation } = this.props;\n const {\n ranges,\n includeHeaders,\n userColumnWidths,\n movedColumns,\n formatValues,\n } = copyOperation;\n log.debug('startFetch', ranges);\n\n const hiddenColumns = IrisGridUtils.getHiddenColumns(userColumnWidths);\n let modelRanges = GridUtils.getModelRanges(ranges, movedColumns);\n if (hiddenColumns.length > 0) {\n const subtractRanges = hiddenColumns.map(GridRange.makeColumn);\n modelRanges = GridRange.subtractRangesFromRanges(\n modelRanges,\n subtractRanges\n );\n }\n\n // Remove the hidden columns from the snapshot\n const formatValue = formatValues\n ? (value, column) => model.displayString(value, column.type, column.name)\n : value => `${value}`;\n\n this.fetchPromise = PromiseUtils.makeCancelable(\n model.textSnapshot(modelRanges, includeHeaders, formatValue)\n );\n this.fetchPromise\n .then(text => {\n this.fetchPromise = null;\n this.copyText(text);\n })\n .catch(error => {\n if (error instanceof CanceledPromiseError) {\n log.debug('User cancelled copy.');\n } else {\n log.error('Error fetching contents', error);\n this.fetchPromise = null;\n this.setState({\n buttonState: IrisGridCopyHandler.BUTTON_STATES.RETRY,\n copyState: IrisGridCopyHandler.COPY_STATES.FETCH_ERROR,\n });\n }\n });\n }\n\n stopFetch() {\n if (this.fetchPromise) {\n log.debug2('stopFetch');\n this.fetchPromise.cancel();\n this.fetchPromise = null;\n }\n }\n\n startHideTimer() {\n this.stopHideTimer();\n\n this.hideTimer = setTimeout(\n this.handleHideTimeout,\n IrisGridCopyHandler.HIDE_TIMEOUT\n );\n }\n\n stopHideTimer() {\n if (this.hideTimer != null) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n render() {\n const { onEntering, onEntered, onExiting, onExited } = this.props;\n const { buttonState, copyState, isShown, rowCount, error } = this.state;\n\n const animation =\n copyState === IrisGridCopyHandler.COPY_STATES.DONE\n ? 'fade'\n : 'copy-slide-up';\n const copyButtonText = IrisGridCopyHandler.getCopyButtonText(buttonState);\n const statusMessageText =\n error ?? IrisGridCopyHandler.getStatusMessageText(copyState, rowCount);\n const isButtonContainerVisible =\n copyState !== IrisGridCopyHandler.COPY_STATES.DONE;\n const isFetching =\n buttonState === IrisGridCopyHandler.BUTTON_STATES.FETCH_IN_PROGRESS;\n const isDone = copyState === IrisGridCopyHandler.COPY_STATES.DONE;\n\n return (\n <IrisGridBottomBar\n animation={animation}\n isShown={isShown}\n className={classNames('iris-grid-copy-handler', {\n 'copy-done': isDone,\n })}\n onClick={this.handleBackgroundClick}\n onEntering={onEntering}\n onEntered={onEntered}\n onExiting={onExiting}\n onExited={onExited}\n >\n <div className=\"status-message\">\n <span>{statusMessageText}</span>\n </div>\n <CSSTransition\n in={isButtonContainerVisible}\n timeout={ThemeExport.transitionMs}\n classNames=\"fade\"\n mountOnEnter\n unmountOnExit\n >\n <div className=\"buttons-container\">\n <button\n type=\"button\"\n className=\"btn btn-outline-secondary btn-cancel\"\n onClick={this.handleCancelClick}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className={classNames('btn', 'btn-copy', {\n 'btn-primary': !isFetching,\n 'btn-secondary': isFetching,\n 'btn-spinner': isFetching,\n })}\n onClick={this.handleCopyClick}\n disabled={isFetching}\n >\n {isFetching && <LoadingSpinner />}\n {copyButtonText}\n </button>\n </div>\n </CSSTransition>\n </IrisGridBottomBar>\n );\n }\n}\n\nIrisGridCopyHandler.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n copyOperation: PropTypes.shape({\n // ranges are expected to be bounded ranges\n ranges: PropTypes.arrayOf(PropTypes.instanceOf(GridRange)).isRequired,\n movedColumns: PropTypes.arrayOf(\n PropTypes.shape({ to: PropTypes.number, from: PropTypes.number })\n ).isRequired,\n userColumnWidths: PropTypes.instanceOf(Map).isRequired,\n formatValues: PropTypes.bool,\n includeHeaders: PropTypes.bool,\n error: PropTypes.string,\n }),\n onEntering: PropTypes.func,\n onEntered: PropTypes.func,\n onExiting: PropTypes.func,\n onExited: PropTypes.func,\n};\n\nIrisGridCopyHandler.defaultProps = {\n copyOperation: null,\n onEntering: () => {},\n onEntered: () => {},\n onExiting: () => {},\n onExited: () => {},\n};\n\nexport default IrisGridCopyHandler;\n","import React, { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport debounce from 'lodash.debounce';\nimport { vsFilter, dhFilterFilled } from '@deephaven/icons';\nimport './FilterInputField.scss';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\n/**\n * An input field showing a input field and button.\n * Debounces changes.\n */\nclass FilterInputField extends PureComponent {\n constructor(props) {\n super(props);\n\n const { debounceMs } = props;\n\n this.debouncedSendUpdate = debounce(this.sendUpdate.bind(this), debounceMs);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleChange = this.handleChange.bind(this);\n this.handleCommit = this.handleCommit.bind(this);\n this.handleFocus = this.handleFocus.bind(this);\n this.handleBlur = this.handleBlur.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleContextMenu = this.handleContextMenu.bind(this);\n\n this.inputField = null;\n\n const { value } = props;\n this.initialValue = value;\n this.state = {\n isChanged: false,\n value,\n };\n }\n\n componentDidMount() {\n this.inputField.focus();\n }\n\n componentDidUpdate(prevProps) {\n const { debounceMs } = this.props;\n if (prevProps.debounceMs !== debounceMs) {\n this.debouncedSendUpdate.flush();\n this.debouncedSendUpdate = debounce(\n this.sendUpdate.bind(this),\n debounceMs\n );\n }\n }\n\n componentWillUnmount() {\n this.debouncedSendUpdate.cancel();\n }\n\n // clear filters needs to be able to reset the value externally\n // and due to the way this component handles its own debouncing\n // this was easier than moving state up.\n setValue(value) {\n this.initialValue = value;\n this.setState({ value });\n }\n\n focus() {\n this.inputField.focus();\n }\n\n handleChange(event) {\n const { value } = event.target;\n this.setState({ value, isChanged: true });\n\n this.debouncedSendUpdate(value);\n }\n\n handleCancel() {\n this.debouncedSendUpdate.cancel();\n const { initialValue } = this;\n const { isChanged } = this.state;\n if (isChanged) {\n this.sendUpdate(initialValue);\n }\n\n const { onDone } = this.props;\n onDone();\n }\n\n handleCommit(setGridFocus = true, defocusInput = true) {\n this.debouncedSendUpdate.flush();\n\n const { onDone } = this.props;\n onDone(setGridFocus, defocusInput);\n }\n\n handleFocus() {\n this.inputField.select();\n }\n\n handleBlur(event) {\n const { relatedTarget } = event;\n // handleCommit results in a call that steals focus\n if (relatedTarget?.classList.contains('context-menu-container')) {\n // input blurred by calling context-menu\n // don't set grid focus, but do null column focus\n this.handleCommit(false, true);\n } else if (relatedTarget?.classList.contains('advanced-filter-button')) {\n // blurred by clicking an advanced filter button\n // don't set grid focus, maintain focusedFilterBarColumn state\n this.handleCommit(false, false);\n } else {\n // clear both, blurred elsewhere\n this.handleCommit(true, true);\n }\n }\n\n handleTab(backward = false) {\n this.debouncedSendUpdate.flush();\n\n const { onTab } = this.props;\n onTab(backward);\n }\n\n handleKeyDown(event) {\n switch (event.key) {\n case 'Escape':\n event.stopPropagation();\n event.preventDefault();\n this.handleCancel();\n break;\n case 'Enter':\n event.stopPropagation();\n event.preventDefault();\n this.handleCommit();\n break;\n case 'Tab':\n event.stopPropagation();\n event.preventDefault();\n this.handleTab(event.shiftKey);\n break;\n default:\n break;\n }\n }\n\n handleContextMenu(event) {\n const { onContextMenu } = this.props;\n onContextMenu(event);\n }\n\n sendUpdate(value) {\n const { onChange } = this.props;\n onChange(value);\n }\n\n render() {\n const {\n className,\n style,\n isAdvancedFilterSet,\n onAdvancedFiltersTriggered,\n } = this.props;\n const { value } = this.state;\n return (\n <div\n style={style}\n className=\"iris-grid-input-autosized-wrapper\"\n data-value={value} // used by css based autosizer\n >\n <input\n ref={inputField => {\n this.inputField = inputField;\n }}\n className={classNames('iris-grid-input-field', className)}\n type=\"text\"\n value={value}\n onBlur={this.handleBlur}\n onFocus={this.handleFocus}\n onChange={this.handleChange}\n onKeyDown={this.handleKeyDown}\n onContextMenu={this.handleContextMenu}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck=\"false\"\n />\n <div className=\"advanced-filter-button-container\">\n <button\n type=\"button\"\n className={classNames(\n 'btn btn-link btn-link-icon advanced-filter-button',\n {\n 'filter-set': isAdvancedFilterSet,\n }\n )}\n onClick={onAdvancedFiltersTriggered}\n onContextMenu={this.handleContextMenu}\n >\n <div className=\"fa-layers \">\n <FontAwesomeIcon icon={dhFilterFilled} className=\"filter-solid\" />\n <FontAwesomeIcon icon={vsFilter} className=\"filter-light\" />\n </div>\n </button>\n </div>\n </div>\n );\n }\n}\n\nFilterInputField.propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n value: PropTypes.string,\n isAdvancedFilterSet: PropTypes.bool,\n onAdvancedFiltersTriggered: PropTypes.func,\n onChange: PropTypes.func,\n onDone: PropTypes.func,\n onTab: PropTypes.func,\n onContextMenu: PropTypes.func,\n debounceMs: PropTypes.number,\n};\n\nFilterInputField.defaultProps = {\n style: {},\n className: '',\n value: '',\n isAdvancedFilterSet: false,\n onAdvancedFiltersTriggered: () => {},\n onChange: () => {},\n onDone: () => {},\n onTab: () => {},\n onContextMenu: () => {},\n debounceMs: 150,\n};\n\nexport default FilterInputField;\n","/* eslint-disable no-underscore-dangle */\nimport { EventTarget } from 'event-target-shim';\nimport React from 'react';\nimport { Log } from '@deephaven/log';\nimport { CustomEventMap, EventShimCustomEvent } from '@deephaven/utils';\nimport { ContextActionUtils } from '../context-actions';\n\nconst log = Log.module('Shortcut');\n\nexport enum MODIFIER {\n CTRL = 'MODIFIER_CTRL',\n CMD = 'MODIFIER_CMD',\n ALT = 'MODIFIER_ALT',\n OPTION = 'MODIFIER_OPTION',\n SHIFT = 'MODIFIER_SHIFT',\n}\n\n// The value should match the KeyboardEvent.key value\n// This is the value which will be displayed if no display overrides are done in the OS specific getDisplayString methods\nexport enum KEY {\n A = 'A',\n B = 'B',\n C = 'C',\n D = 'D',\n E = 'E',\n F = 'F',\n G = 'G',\n H = 'H',\n I = 'I',\n J = 'J',\n K = 'K',\n L = 'L',\n M = 'M',\n N = 'N',\n O = 'O',\n P = 'P',\n Q = 'Q',\n R = 'R',\n S = 'S',\n T = 'T',\n U = 'U',\n V = 'V',\n W = 'W',\n X = 'X',\n Y = 'Y',\n Z = 'Z',\n ZERO = '0',\n ONE = '1',\n TWO = '2',\n THREE = '3',\n FOUR = '4',\n FIVE = '5',\n SIX = '6',\n SEVEN = '7',\n EIGHT = '8',\n NINE = '9',\n BACKSPACE = 'Backspace',\n ESCAPE = 'Escape',\n ENTER = 'Enter',\n DELETE = 'Delete',\n SLASH = '/',\n QUESTION_MARK = '?',\n BACKSLASH = '\\\\',\n PIPE = '|',\n MINUS = '-',\n UNDERSCORE = '_',\n EQUALS = '=',\n PLUS = '+',\n BACKTICK = '`',\n TILDE = '~',\n COMMA = ',',\n LEFT_CHEVRON = '<',\n PERIOD = '.',\n RIGHT_CHEVRON = '>',\n SEMICOLON = ';',\n COLON = ':',\n SINGLE_QUOTE = \"'\",\n DOUBLE_QUOTE = '\"',\n LEFT_BRACKET = '[',\n RIGHT_BRACKET = ']',\n LEFT_CURLY = '{',\n RIGHT_CURLY = '}',\n F1 = 'F1',\n F2 = 'F2',\n F3 = 'F3',\n F4 = 'F4',\n F5 = 'F5',\n F6 = 'F6',\n F7 = 'F7',\n F8 = 'F8',\n F9 = 'F9',\n F10 = 'F10',\n F11 = 'F11',\n F12 = 'F12',\n}\n\nconst ALLOWED_SINGLE_KEY_SET: Set<KEY> = new Set([\n KEY.ENTER,\n KEY.DELETE,\n KEY.F1,\n KEY.F2,\n KEY.F3,\n KEY.F4,\n KEY.F5,\n KEY.F6,\n KEY.F7,\n KEY.F8,\n KEY.F9,\n KEY.F10,\n KEY.F11,\n KEY.F12,\n]);\n\ntype ShortcutKeys = [...MODIFIER[], KEY];\n\nexport interface KeyState {\n /**\n * This is purposely keyValue and not key to make KeyboardEvents not match the interface\n * KeyboardEvents need some processing to get the actual value\n * Use Shortcut.getKeyStateFromEvent to get the right KeyState from an event\n */\n keyValue: string | null;\n altKey: boolean;\n ctrlKey: boolean;\n metaKey: boolean;\n shiftKey: boolean;\n}\n\nexport interface ValidKeyState extends KeyState {\n keyValue: KEY | null;\n}\n\ntype EventMap = CustomEventMap<{\n onUpdate: CustomEvent<Shortcut>;\n}>;\n\nexport default class Shortcut extends EventTarget<EventMap, 'strict'> {\n readonly id: string; // Unique identifier for the shortcut\n\n readonly name: string; // e.g. Rename, Save, Run Selected\n\n readonly tooltip?: string;\n\n readonly isEditable: boolean;\n\n private readonly defaultKeyState: ValidKeyState;\n\n private keyState: ValidKeyState;\n\n static NULL_KEY_STATE: ValidKeyState = {\n metaKey: false,\n shiftKey: false,\n altKey: false,\n ctrlKey: false,\n keyValue: null,\n };\n\n /**\n * Use to check if a keyCode corresponds to an allowed key for a shortcut\n * @param keyCode The keyCode to check. This should be the charCode of the key\n * @returns Type predicate asserting the key is an allowed KEY\n */\n static isAllowedKey(key: string | null): key is KEY {\n return Object.values(KEY).includes(key as KEY);\n }\n\n /**\n * Checks if a KeyState has a valid key.\n * @param state KeyState with any string as the key\n * @returns True if KeyState is is using an allowed keyCode\n */\n static isValidKeyState(state: KeyState): state is ValidKeyState {\n const { keyValue } = state;\n\n if (keyValue === null) {\n // Null state is valid\n return true;\n }\n\n if (!Shortcut.isMacPlatform && state.metaKey) {\n // MetaKey not allowed in windows\n return false;\n }\n\n if (!Shortcut.isAllowedKey(keyValue)) {\n return false;\n }\n\n const isSingleKey =\n !state.altKey && !state.ctrlKey && !state.metaKey && !state.shiftKey;\n\n return !isSingleKey || ALLOWED_SINGLE_KEY_SET.has(keyValue);\n }\n\n static isMacPlatform = ContextActionUtils.isMacPlatform();\n\n /**\n * Creates a KeyState from a valid array of modifier and key constants\n * @param keys Array of keys in the shortcut. Modifiers first and key last. Should use the MODIFIER and KEY enums\n * @returns KeyState representing the array of constants\n */\n static createKeyState(keys: ShortcutKeys): ValidKeyState {\n const keyState: ValidKeyState = {\n altKey: false,\n ctrlKey: false,\n metaKey: false,\n shiftKey: false,\n keyValue: keys[keys.length - 1] as KEY,\n };\n\n keys.forEach(key => {\n switch (key) {\n case MODIFIER.CTRL:\n keyState.ctrlKey = true;\n break;\n case MODIFIER.ALT:\n case MODIFIER.OPTION:\n keyState.altKey = true;\n break;\n case MODIFIER.CMD:\n keyState.metaKey = true;\n break;\n case MODIFIER.SHIFT:\n keyState.shiftKey = true;\n break;\n default:\n break;\n }\n });\n\n return keyState;\n }\n\n static getKeyStateFromEvent(\n e: React.KeyboardEvent | KeyboardEvent\n ): KeyState {\n const { key: eventKey, keyCode } = e;\n let key = '';\n if (\n eventKey === 'Shift' ||\n eventKey === 'Meta' ||\n eventKey === 'Control' ||\n eventKey === 'Alt'\n ) {\n key = '';\n } else if (\n // This is primarily for Mac which has a symbol keyboard hidden behind the alt key\n // The keyCode still corresponds to the letter keyCode, but the key value will be a symbol\n !Shortcut.isAllowedKey(eventKey) &&\n Shortcut.isAllowedKey(String.fromCharCode(keyCode))\n ) {\n key = String.fromCharCode(keyCode);\n } else {\n key = eventKey;\n }\n\n return {\n keyValue: key,\n altKey: e.altKey,\n ctrlKey: e.ctrlKey,\n metaKey: e.metaKey,\n shiftKey: e.shiftKey,\n };\n }\n\n /**\n * Gets display string for Windows (and Linux + any other non-Mac OS)\n * If the key is not an allowed key, the display will only display the modifiers\n * @param keyState KeyState to get the display for\n * @returns The string to display on Windows/non-Mac OS\n */\n private static getWindowsDisplayText(keyState: KeyState): string {\n let display = '';\n\n if (keyState.ctrlKey) {\n display += 'Ctrl+';\n }\n if (keyState.altKey) {\n display += 'Alt+';\n }\n if (keyState.shiftKey) {\n display += 'Shift+';\n }\n\n if (keyState.keyValue === KEY.ESCAPE) {\n display += 'Esc';\n } else if (keyState.keyValue !== null) {\n display += keyState.keyValue;\n }\n\n return display;\n }\n\n /**\n * Gets display string Mac OS\n * If the key is not an allowed key, the display will only display the modifiers\n * @param keyState KeyState to get the display for\n * @returns The string to display on Mac OS\n */\n private static getMacDisplayText(keyState: KeyState): string {\n let display = '';\n\n if (keyState.ctrlKey) {\n display += '⌃';\n }\n if (keyState.altKey) {\n display += '⌥';\n }\n if (keyState.shiftKey) {\n display += '⇧';\n }\n if (keyState.metaKey) {\n display += '⌘';\n }\n\n switch (keyState.keyValue) {\n case KEY.ENTER:\n display += '⏎';\n break;\n case KEY.ESCAPE:\n display += '⎋';\n break;\n case KEY.BACKSPACE:\n display += '⌫';\n break;\n case KEY.DELETE:\n display += '⌦';\n break;\n case null:\n break;\n default:\n display += keyState.keyValue;\n }\n\n return display;\n }\n\n /**\n * Checks if 2 KeyStates match\n * @param state1 First KeyState to compare\n * @param state2 Second KeyState to compare\n * @returns True if the KeyStates match and have non-null keyValues\n */\n static doKeyStatesMatch(state1: KeyState, state2: KeyState): boolean {\n return (\n state1.keyValue?.toUpperCase() === state2.keyValue?.toUpperCase() &&\n state1.altKey === state2.altKey &&\n state1.ctrlKey === state2.ctrlKey &&\n state1.metaKey === state2.metaKey &&\n state1.shiftKey === state2.shiftKey\n );\n }\n\n /**\n * Gets the display string for the current OS from a KeyState.\n * @param keyState KeyState to get the display for\n * @returns Display string for the current OS\n */\n static getDisplayText(keyState: KeyState): string {\n if (keyState.keyValue === null) {\n return '';\n }\n return Shortcut.isMacPlatform\n ? Shortcut.getMacDisplayText(keyState)\n : Shortcut.getWindowsDisplayText(keyState);\n }\n\n constructor({\n id,\n shortcut,\n macShortcut,\n isEditable = true,\n name,\n tooltip,\n }: {\n id: string;\n shortcut: ShortcutKeys;\n macShortcut: ShortcutKeys;\n isEditable?: boolean;\n name: string;\n tooltip?: string;\n }) {\n super();\n this.id = id;\n this.name = name;\n this.tooltip = tooltip;\n this.isEditable = isEditable;\n\n const isMac = Shortcut.isMacPlatform;\n const activeShortcut = isMac ? macShortcut : shortcut;\n this.defaultKeyState = Shortcut.createKeyState(activeShortcut);\n this.keyState = this.defaultKeyState;\n }\n\n /**\n * Gets the display string for the current OS\n */\n getDisplayText(): string {\n return Shortcut.getDisplayText(this.keyState);\n }\n\n /**\n * Gets the current keyState for the Shortcut\n */\n getKeyState(): ValidKeyState {\n return this.keyState;\n }\n\n /**\n * Sets the KeyState if it is valid\n * @param keyState\n */\n setKeyState(keyState: KeyState): void {\n if (Shortcut.isValidKeyState(keyState)) {\n log.debug2(`Shortcut ${this.id} updated to ${JSON.stringify(keyState)}`);\n this.keyState = keyState;\n this.dispatchEvent(\n new EventShimCustomEvent('onUpdate', { detail: this })\n );\n } else {\n log.debug2(\n `Shortcut ${\n this.id\n } tried to update to invalid keyState ${JSON.stringify(keyState)}`\n );\n }\n }\n\n /**\n * Gets the default key state of the shortcut\n * @returns Default key state\n */\n getDefaultKeyState(): ValidKeyState {\n return this.defaultKeyState;\n }\n\n isDefault(): boolean {\n return Shortcut.doKeyStatesMatch(\n this.getDefaultKeyState(),\n this.getKeyState()\n );\n }\n\n /**\n * Sets the shortcut to have null keyValue\n */\n setToNull(): void {\n this.setKeyState(Shortcut.NULL_KEY_STATE);\n }\n\n isNull(): boolean {\n return Shortcut.doKeyStatesMatch(this.keyState, Shortcut.NULL_KEY_STATE);\n }\n\n /**\n * Sets the shortcut to its default key state\n */\n setToDefault(): void {\n this.setKeyState(this.defaultKeyState);\n }\n\n /**\n * Checks if a KeyState matches the KeyState for the shortcut\n * @param keyState KeyState to check\n * @returns True if the passed KeyState matches the Shortcut's KeyState\n */\n matchesKeyState(keyState: KeyState): boolean {\n return Shortcut.doKeyStatesMatch(keyState, this.keyState);\n }\n\n /**\n * Alias for matchesKeyState\n * @param e KeyboardEvent to check if the Shortcut matches\n * @returns True if the event matches the Shortcut's KeyState\n */\n matchesEvent(e: React.KeyboardEvent | KeyboardEvent): boolean {\n return this.matchesKeyState(Shortcut.getKeyStateFromEvent(e));\n }\n}\n","/* eslint-disable max-classes-per-file */\nimport { EventTarget } from 'event-target-shim';\nimport { Log } from '@deephaven/log';\nimport { CustomEventMap, EventShimCustomEvent } from '@deephaven/utils';\nimport Shortcut, { KeyState } from './Shortcut';\n\nconst log = Log.module('ShortcutRegistry');\n\ntype EventMap = CustomEventMap<{\n onUpdate: CustomEvent<Shortcut>;\n}>;\n\nclass ShortcutRegistry extends EventTarget<EventMap, 'strict'> {\n readonly shortcutMap = new Map<string, Shortcut>();\n\n readonly shortcutsByCategory = new Map<string, Shortcut[]>();\n\n /**\n * Creates a Shortcut and adds it to the registry\n * @param params The constructor params for the {@link Shortcut}\n * @returns The created shortcut or the shortcut in the registry if 1 already exists w/ the same ID\n */\n createAndAdd(params: ConstructorParameters<typeof Shortcut>[0]): Shortcut {\n const shortcut = new Shortcut(params);\n return this.add(shortcut);\n }\n\n /**\n * Adds a shortcut to the registry. Warns and returns existing shortcut if a shortcut with the same ID already exists\n * @param shortcut Shortcut to add to the registry\n * @returns Shortcut passed if it is not in the registry. Shortcut from the registry if one exists for the same ID\n */\n add(shortcut: Shortcut): Shortcut {\n const existingShortcut = this.shortcutMap.get(shortcut.id);\n if (existingShortcut) {\n log.warn(\n `Skipping attempt to add duplicate shortcut ID to registry: ${shortcut.id}`\n );\n return existingShortcut;\n }\n\n log.debug2(`Adding shortcut to registry: ${shortcut.id}`);\n\n shortcut.addEventListener('onUpdate', ({ detail }) =>\n this.dispatchEvent(new EventShimCustomEvent('onUpdate', { detail }))\n );\n\n const category = shortcut.id.split('.')[0];\n\n this.shortcutMap.set(shortcut.id, shortcut);\n if (this.shortcutsByCategory.has(category)) {\n this.shortcutsByCategory.get(category)?.push(shortcut);\n } else {\n this.shortcutsByCategory.set(category, [shortcut]);\n }\n\n return shortcut;\n }\n\n /**\n * Gets a shortcut from the registry from an ID\n * @param id ID of the shortcut\n * @returns The shortcut for that ID if it exists\n */\n get(id: string): Shortcut | undefined {\n return this.shortcutMap.get(id);\n }\n\n /**\n * Gets an array of any registered shortcuts with conflicting key states.\n * Only checks the key states of the current OS (Mac or Windows/Linux)\n * @param keyState\n * @returns Array of conflicting shortcuts. Empty array if none conflict\n */\n getConflictingShortcuts(keyState: KeyState): Shortcut[] {\n return Array.from(this.shortcutMap.values()).filter(\n shortcut => !shortcut.isNull() && shortcut.matchesKeyState(keyState)\n );\n }\n}\n\nconst registry = Object.freeze(new ShortcutRegistry());\n\nexport default registry;\n","import { ShortcutRegistry, MODIFIER, KEY } from '@deephaven/components';\n\nconst TABLE = {\n TOGGLE_QUICK_FILTER: ShortcutRegistry.createAndAdd({\n id: 'TABLE.TOGGLE_QUICK_FILTER',\n name: 'Toggle Quick Filter',\n shortcut: [MODIFIER.CTRL, KEY.F],\n macShortcut: [MODIFIER.CMD, KEY.F],\n }),\n CLEAR_ALL_FILTERS: ShortcutRegistry.createAndAdd({\n id: 'TABLE.CLEAR_ALL_FILTERS',\n name: 'Clear All Table Filters',\n shortcut: [MODIFIER.CTRL, KEY.E],\n macShortcut: [MODIFIER.CMD, KEY.E],\n }),\n CLEAR_FILTERS: ShortcutRegistry.createAndAdd({\n id: 'TABLE.CLEAR_FILTERS',\n name: 'Clear Active Table Filters',\n shortcut: [MODIFIER.CTRL, MODIFIER.SHIFT, KEY.E],\n macShortcut: [MODIFIER.CMD, MODIFIER.SHIFT, KEY.E],\n }),\n REVERSE: ShortcutRegistry.createAndAdd({\n id: 'TABLE.REVERSE',\n name: 'Reverse',\n shortcut: [MODIFIER.CTRL, KEY.I],\n macShortcut: [MODIFIER.CMD, KEY.I],\n }),\n TOGGLE_SEARCH: ShortcutRegistry.createAndAdd({\n id: 'TABLE.TOGGLE_SEARCH',\n name: 'Toggle Search',\n shortcut: [MODIFIER.CTRL, MODIFIER.SHIFT, KEY.F],\n macShortcut: [MODIFIER.CMD, MODIFIER.SHIFT, KEY.F],\n }),\n};\n\nconst INPUT_TABLE = {\n COMMIT: ShortcutRegistry.createAndAdd({\n id: 'INPUT_TABLE.COMMIT',\n name: 'Commit',\n shortcut: [MODIFIER.CTRL, KEY.S],\n macShortcut: [MODIFIER.CMD, KEY.S],\n }),\n DISCARD: ShortcutRegistry.createAndAdd({\n id: 'INPUT_TABLE.DISCARD',\n name: 'Discard',\n shortcut: [MODIFIER.CTRL, MODIFIER.ALT, KEY.S],\n macShortcut: [MODIFIER.CMD, MODIFIER.OPTION, KEY.S],\n }),\n};\n\nconst IRIS_GRID_SHORTCUTS = {\n TABLE,\n INPUT_TABLE,\n};\n\nexport default IRIS_GRID_SHORTCUTS;\n","import { KeyboardEvent } from 'react';\nimport { KeyHandler } from '@deephaven/grid';\nimport { IrisGrid } from '../IrisGrid';\nimport TableUtils from '../TableUtils';\nimport IrisGridShortcuts from '../IrisGridShortcuts';\n\nclass ReverseKeyHandler extends KeyHandler {\n private irisGrid: IrisGrid;\n\n constructor(irisGrid: IrisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n onDown(event: KeyboardEvent): boolean {\n if (IrisGridShortcuts.TABLE.REVERSE.matchesEvent(event)) {\n if (!this.irisGrid.isReversible()) {\n return false;\n }\n const { reverseType } = this.irisGrid.state;\n if (reverseType === TableUtils.REVERSE_TYPE.NONE) {\n this.irisGrid.reverse(TableUtils.REVERSE_TYPE.POST_SORT);\n } else {\n this.irisGrid.reverse(TableUtils.REVERSE_TYPE.NONE);\n }\n return true;\n }\n return false;\n }\n}\n\nexport default ReverseKeyHandler;\n","import { KeyboardEvent } from 'react';\nimport { KeyHandler } from '@deephaven/grid';\nimport { IrisGrid } from '../IrisGrid';\nimport IrisGridShortcuts from '../IrisGridShortcuts';\n\nclass ClearFilterKeyHandler extends KeyHandler {\n private irisGrid: IrisGrid;\n\n constructor(irisGrid: IrisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n onDown(event: KeyboardEvent): boolean {\n if (IrisGridShortcuts.TABLE.CLEAR_FILTERS.matchesEvent(event)) {\n this.irisGrid.clearAllFilters();\n return true;\n }\n return false;\n }\n}\n\nexport default ClearFilterKeyHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { KeyboardEvent } from 'react';\nimport { ContextActionUtils } from '@deephaven/components';\nimport { KeyHandler } from '@deephaven/grid';\nimport { IrisGrid } from '../IrisGrid';\nimport IrisGridUtils from '../IrisGridUtils';\n\nclass CopyKeyHandler extends KeyHandler {\n private irisGrid: IrisGrid;\n\n constructor(irisGrid: IrisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n onDown(event: KeyboardEvent): boolean {\n const { selectedRanges } = this.irisGrid.state;\n if (event.key === 'c' && ContextActionUtils.isModifierKeyDown(event)) {\n if (IrisGridUtils.isValidSnapshotRanges(selectedRanges)) {\n this.irisGrid.copyRanges(selectedRanges);\n } else {\n this.irisGrid.copyRanges(\n selectedRanges,\n false,\n false,\n 'Invalid copy ranges'\n );\n }\n return true;\n }\n return false;\n }\n}\n\nexport default CopyKeyHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { GridMouseHandler } from '@deephaven/grid';\n\n/**\n * Handles interaction with tables when the Linker tool is active\n */\nclass IrisGridColumnSelectMouseHandler extends GridMouseHandler {\n constructor(irisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n this.cursor = null;\n }\n\n isActive() {\n const { isSelectingColumn } = this.irisGrid.props;\n return isSelectingColumn;\n }\n\n isValidColumn(tableColumn) {\n if (tableColumn == null) {\n return false;\n }\n\n const { columnSelectionValidator } = this.irisGrid.props;\n if (columnSelectionValidator) {\n return columnSelectionValidator(tableColumn);\n }\n return true;\n }\n\n updateColumnSelectionStatus() {\n const { columnSelectionValidator } = this.irisGrid.props;\n if (columnSelectionValidator) {\n columnSelectionValidator(null);\n }\n }\n\n getTableColumn(columnIndex) {\n if (columnIndex == null) {\n return null;\n }\n\n const { model } = this.irisGrid.props;\n const modelColumn = this.irisGrid.getModelColumn(columnIndex);\n if (modelColumn == null) {\n return null;\n }\n\n return model.columns[modelColumn];\n }\n\n onMove(gridPoint) {\n if (!this.isActive()) {\n return false;\n }\n\n const { columnAllowedCursor, columnNotAllowedCursor } = this.irisGrid.props;\n const { column } = gridPoint;\n const tableColumn = this.getTableColumn(column);\n\n if (this.isValidColumn(tableColumn)) {\n this.cursor = columnAllowedCursor;\n this.irisGrid.setState({ hoverSelectColumn: column });\n } else {\n this.cursor = columnNotAllowedCursor;\n this.irisGrid.setState({ hoverSelectColumn: null });\n }\n\n return true;\n }\n\n // keeps linker cursor state during wheel event\n onWheel(gridPoint) {\n if (!this.isActive()) {\n return false;\n }\n\n const { columnAllowedCursor, columnNotAllowedCursor } = this.irisGrid.props;\n const { column } = gridPoint;\n const tableColumn = this.getTableColumn(column);\n\n if (this.isValidColumn(tableColumn)) {\n this.cursor = columnAllowedCursor;\n } else {\n this.cursor = columnNotAllowedCursor;\n }\n\n // don't block wheel event from scrolling\n return { preventDefault: false, stopPropagation: false };\n }\n\n onLeave() {\n if (this.isActive()) {\n this.irisGrid.setState({ hoverSelectColumn: null });\n }\n\n this.updateColumnSelectionStatus();\n\n return false;\n }\n\n onDown() {\n return this.isActive();\n }\n\n onClick(gridPoint) {\n if (!this.isActive()) {\n return false;\n }\n\n const { column } = gridPoint;\n const tableColumn = this.getTableColumn(column);\n if (this.isValidColumn(tableColumn)) {\n this.irisGrid.selectColumn(tableColumn);\n }\n\n return true;\n }\n}\n\nexport default IrisGridColumnSelectMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { GridMouseHandler } from '@deephaven/grid';\n\n/**\n * Detects mouse hover over column headers and displays the appropriate tooltip\n */\nclass IrisGridColumnTooltipMouseHandler extends GridMouseHandler {\n constructor(irisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n destroyColumnTooltip() {\n const { shownColumnTooltip } = this.irisGrid.state;\n if (shownColumnTooltip != null) {\n this.irisGrid.setState({ shownColumnTooltip: null });\n }\n }\n\n hideColumnTooltip() {\n const { tooltip } = this.irisGrid;\n if (tooltip) {\n tooltip.stopTimer();\n tooltip.hide();\n }\n }\n\n onDown() {\n this.hideColumnTooltip();\n return false;\n }\n\n onContextMenu() {\n this.hideColumnTooltip();\n return false;\n }\n\n onWheel() {\n this.destroyColumnTooltip();\n }\n\n onMove(gridPoint) {\n const { y, column, row } = gridPoint;\n const { shownColumnTooltip } = this.irisGrid.state;\n const theme = this.irisGrid.getTheme();\n let newTooltip = null;\n if (column !== null && row === null) {\n /**\n * one would expect at y == theme.columnHeaderHeight, row == null\n * however, gridY also == theme.columnHeaderHeight, so row still has a value\n * so this tooltip won't actually show until row is null at columnHeaderHeight - 1\n */\n if (y >= 0 && y <= theme.columnHeaderHeight) {\n newTooltip = column;\n }\n }\n\n if (newTooltip !== shownColumnTooltip) {\n this.irisGrid.setState({ shownColumnTooltip: newTooltip });\n }\n\n return false;\n }\n}\n\nexport default IrisGridColumnTooltipMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { ContextActionUtils } from '@deephaven/components';\nimport { GridMouseHandler } from '@deephaven/grid';\n\n/**\n * Used to handle sorting on column header clicks\n */\nclass IrisGridSortMouseHandler extends GridMouseHandler {\n constructor(irisGrid) {\n super();\n\n this.column = null;\n this.irisGrid = irisGrid;\n }\n\n getColumnFromGridPoint(gridPoint) {\n const { y, column, row } = gridPoint;\n if (column !== null && row === null) {\n const theme = this.irisGrid.getTheme();\n if (y <= theme.columnHeaderHeight) {\n return column;\n }\n }\n\n return null;\n }\n\n // We need to remember where the down started, because the canvas element will trigger a click whereever mouseUp is\n onDown(gridPoint) {\n this.column = this.getColumnFromGridPoint(gridPoint);\n return false;\n }\n\n onClick(gridPoint, grid, event) {\n const column = this.getColumnFromGridPoint(gridPoint);\n if (column != null && column === this.column) {\n const addToExisting = ContextActionUtils.isModifierKeyDown(event);\n this.irisGrid.toggleSort(column, addToExisting);\n return true;\n }\n\n return false;\n }\n}\n\nexport default IrisGridSortMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { GridMouseHandler } from '@deephaven/grid';\n\n/**\n * Trigger quick filters and advanced filters\n */\nclass IrisGridFilterMouseHandler extends GridMouseHandler {\n constructor(irisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n onDown(gridPoint) {\n const { y, column, row } = gridPoint;\n if (column !== null && row === null) {\n const { isFilterBarShown } = this.irisGrid.state;\n const theme = this.irisGrid.getTheme();\n if (\n isFilterBarShown &&\n y > theme.columnHeaderHeight &&\n y <= theme.columnHeaderHeight + theme.filterBarHeight\n ) {\n this.irisGrid.focusFilterBar(column);\n return true;\n }\n }\n\n return false;\n }\n\n onMove(gridPoint) {\n const { y, column } = gridPoint;\n const { isFilterBarShown, hoverAdvancedFilter } = this.irisGrid.state;\n const theme = this.irisGrid.getTheme();\n let newHoverAdvancedFilter = null;\n if (\n isFilterBarShown &&\n column !== null &&\n y >= theme.columnHeaderHeight &&\n y <= theme.columnHeaderHeight + theme.filterBarHeight\n ) {\n newHoverAdvancedFilter = column;\n }\n\n if (newHoverAdvancedFilter !== hoverAdvancedFilter) {\n this.irisGrid.setState({ hoverAdvancedFilter: newHoverAdvancedFilter });\n }\n\n return false;\n }\n\n onLeave(gridPoint) {\n const { column } = gridPoint;\n const { hoverAdvancedFilter } = this.irisGrid.state;\n if (hoverAdvancedFilter !== null && column !== hoverAdvancedFilter) {\n this.irisGrid.setState({ hoverAdvancedFilter: null });\n }\n }\n}\n\nexport default IrisGridFilterMouseHandler;\n","import ShortcutRegistry from './ShortcutRegistry';\nimport { MODIFIER, KEY } from './Shortcut';\n\nconst GLOBAL_SHORTCUTS = {\n COPY: ShortcutRegistry.createAndAdd({\n id: 'GLOBAL.COPY',\n name: 'Copy',\n shortcut: [MODIFIER.CTRL, KEY.C],\n macShortcut: [MODIFIER.CMD, KEY.C],\n isEditable: false,\n }),\n PASTE: ShortcutRegistry.createAndAdd({\n id: 'GLOBAL.PASTE',\n name: 'Paste',\n shortcut: [MODIFIER.CTRL, KEY.V],\n macShortcut: [MODIFIER.CMD, KEY.V],\n isEditable: false,\n }),\n SAVE: ShortcutRegistry.createAndAdd({\n id: 'GLOBAL.SAVE',\n name: 'Save',\n shortcut: [MODIFIER.CTRL, KEY.S],\n macShortcut: [MODIFIER.CMD, KEY.S],\n isEditable: false,\n }),\n SELECT_ALL: ShortcutRegistry.createAndAdd({\n id: 'GLOBAL.SELECT_ALL',\n name: 'Select All',\n shortcut: [MODIFIER.CTRL, KEY.A],\n macShortcut: [MODIFIER.CMD, KEY.A],\n isEditable: false,\n }),\n LINKER: ShortcutRegistry.createAndAdd({\n id: 'GLOBAL.LINKER',\n name: 'Linker',\n shortcut: [MODIFIER.CTRL, KEY.L],\n macShortcut: [MODIFIER.CMD, KEY.L],\n }),\n LINKER_CLOSE: ShortcutRegistry.createAndAdd({\n id: 'GLOBAL.LINKER_CLOSE',\n name: 'Close Linker Overlay',\n shortcut: [KEY.ESCAPE],\n macShortcut: [KEY.ESCAPE],\n isEditable: false,\n }),\n};\n\nexport default GLOBAL_SHORTCUTS;\n","import React, { Component } from 'react';\nimport { Tooltip } from '@deephaven/components';\nimport { DOMUtils } from '@deephaven/utils';\n\nimport './CustomFormatAction.scss';\n\ntype CustomFormatActionProps = typeof CustomFormatAction.defaultProps & {\n forwardedProps: {\n menuItem: {\n title?: string;\n description?: string;\n };\n };\n};\n\n/**\n * Renders menuElement option with custom format input for use in formatting context menus\n *\n * TODO:\n * - capture focus when this menu action is selected via ArrowUp/ArrowDown keys\n * - dynamically update selected menu item when clicking on the input box\n */\nclass CustomFormatAction extends Component<CustomFormatActionProps> {\n static defaultProps = {\n formatString: '',\n forwardedProps: {\n menuItem: {},\n closeMenu(focusInput: boolean): void {\n // no-op\n },\n iconElement: null,\n },\n placeholder: '',\n title: '',\n onChange(value: string | null): void {\n // no-op\n },\n };\n\n constructor(\n props: CustomFormatActionProps = CustomFormatAction.defaultProps\n ) {\n super(props);\n\n this.handleInputChange = this.handleInputChange.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n\n this.inputRef = React.createRef();\n }\n\n inputRef: React.RefObject<HTMLInputElement>;\n\n handleInputChange(): void {\n const { onChange } = this.props;\n if (this.inputRef.current) {\n onChange(this.inputRef.current.value);\n }\n }\n\n closeContextMenu(): void {\n const { forwardedProps } = this.props;\n const { closeMenu } = forwardedProps;\n closeMenu(true);\n }\n\n revertToDefault(): void {\n const { onChange } = this.props;\n onChange(null);\n }\n\n returnFocusToContextMenu(): void {\n const parentContextMenu = DOMUtils.getClosestByClassName(\n this.inputRef.current,\n 'context-menu-container'\n );\n if (parentContextMenu instanceof HTMLElement) {\n parentContextMenu.focus();\n }\n }\n\n handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {\n switch (event.key) {\n case 'Enter':\n event.stopPropagation();\n this.closeContextMenu();\n break;\n case 'Escape':\n event.stopPropagation();\n this.revertToDefault();\n this.closeContextMenu();\n break;\n case 'ArrowRight':\n case 'ArrowLeft':\n event.stopPropagation();\n break;\n case 'ArrowUp':\n case 'ArrowDown':\n this.returnFocusToContextMenu();\n break;\n default:\n event.stopPropagation();\n }\n }\n\n render(): JSX.Element {\n const { formatString, forwardedProps, placeholder, title } = this.props;\n const {\n menuItem: { description },\n iconElement,\n } = forwardedProps;\n return (\n <div className=\"form-group flex-grow mb-0\">\n <div className=\"custom-format-title\">\n <span className=\"icon\">{iconElement}</span>\n <label className=\"title mb-0\" htmlFor=\"custom-format-input\">\n {title}\n {description && <Tooltip>{description}</Tooltip>}\n </label>\n </div>\n <div className=\"pl-2 pr-2 pb-2\">\n <input\n id=\"custom-format-input\"\n className=\"form-control text-right mb-0\"\n type=\"text\"\n defaultValue={formatString}\n ref={this.inputRef}\n placeholder={placeholder}\n onKeyDown={this.handleKeyDown}\n onChange={this.handleInputChange}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck=\"false\"\n />\n </div>\n </div>\n );\n }\n}\n\nexport default CustomFormatAction;\n","import React from 'react';\nimport CustomFormatAction from './CustomFormatAction';\nimport { TableColumnFormatter, TableColumnFormat } from '../formatters';\n\nexport interface FormatContextMenuOption {\n title: string;\n description: string;\n group: number;\n format: TableColumnFormat | null;\n isSelected: boolean;\n}\n\nexport interface CustomFormatOption extends FormatContextMenuOption {\n menuElement: React.ReactElement;\n}\n\nclass FormatContextMenuUtils {\n /**\n * Returns true if default option should be active in the context menu\n * @param selectedFormat selected format object or null\n */\n static isDefaultSelected(selectedFormat: TableColumnFormat): boolean {\n return (\n !selectedFormat ||\n ![\n TableColumnFormatter.TYPE_CONTEXT_CUSTOM,\n TableColumnFormatter.TYPE_CONTEXT_PRESET,\n ].includes(selectedFormat.type)\n );\n }\n\n /**\n * Returns true if custom format option should be active in the context menu\n * @param selectedFormat selected format object or null\n */\n static isCustomSelected(selectedFormat: TableColumnFormat): boolean {\n return (\n selectedFormat &&\n selectedFormat.type === TableColumnFormatter.TYPE_CONTEXT_CUSTOM\n );\n }\n\n /**\n * Creates context menu option\n * @param title Context menu title\n * @param format Format object\n * @param group Context menu group\n * @param isSelected Is current option selected\n */\n static makeOption(\n title: string,\n format: TableColumnFormat | null,\n group: number,\n isSelected: boolean\n ): FormatContextMenuOption {\n return {\n title,\n description: title,\n group,\n format,\n isSelected,\n };\n }\n\n /**\n * Creates context menu option with an input element\n * @param format Format object\n * @param group Context menu group\n * @param placeholder Input element placeholder\n * @param isSelected Is current option selected\n * @param onChange Input element onChange callback\n */\n static makeCustomFormatOption(\n format: TableColumnFormat,\n group: number,\n placeholder: string,\n isSelected: boolean,\n onChange: (value: string | null) => void\n ): CustomFormatOption {\n return {\n title: format.label,\n description: format.label,\n format,\n group,\n isSelected,\n menuElement: (\n <CustomFormatAction\n formatString={format.formatString}\n title={format.label}\n placeholder={placeholder}\n onChange={onChange}\n />\n ),\n };\n }\n}\n\nexport default FormatContextMenuUtils;\n","import { DateTimeColumnFormatter, TableColumnFormat } from '../formatters';\nimport FormatContextMenuUtils, {\n FormatContextMenuOption,\n} from './FormatContextMenuUtils';\nimport TableUtils from '../TableUtils';\nimport type Formatter from '../Formatter';\n\nclass DateTimeFormatContextMenu {\n static dateGroup = 10;\n\n static timeGroup = 20;\n\n static dateTimeGroup = 30;\n\n /**\n * Creates list of formatting options for DateTime context menu\n * @param formatter Formatter instance\n * @param selectedFormat Selected format object, null for no selected format\n * @returns Array of formatting options for the context menu\n */\n static getOptions(\n formatter: Formatter,\n selectedFormat: TableColumnFormat\n ): FormatContextMenuOption[] {\n const currentTime = new Date();\n const formatItems = [\n {\n group: DateTimeFormatContextMenu.dateGroup,\n formatString: 'yyyy-MM-dd',\n },\n {\n group: DateTimeFormatContextMenu.dateGroup,\n formatString: 'MM-dd-yyyy',\n },\n\n {\n group: DateTimeFormatContextMenu.timeGroup,\n formatString: 'HH:mm:ss',\n },\n {\n group: DateTimeFormatContextMenu.timeGroup,\n formatString: 'HH:mm:ss.SSS',\n },\n {\n group: DateTimeFormatContextMenu.timeGroup,\n formatString: 'HH:mm:ss.SSSSSSSSS',\n },\n\n {\n group: DateTimeFormatContextMenu.dateTimeGroup,\n formatString: `yyyy-MM-dd HH:mm:ss`,\n },\n {\n group: DateTimeFormatContextMenu.dateTimeGroup,\n formatString: `yyyy-MM-dd HH:mm:ss.SSS`,\n },\n {\n group: DateTimeFormatContextMenu.dateTimeGroup,\n formatString: `yyyy-MM-dd HH:mm:ss.SSSSSSSSS`,\n },\n ];\n\n const presetFormatOptions = formatItems.map(item => {\n const format = DateTimeColumnFormatter.makeFormat(\n '',\n item.formatString,\n DateTimeColumnFormatter.TYPE_CONTEXT_PRESET\n );\n const title = formatter.getFormattedString(\n currentTime,\n TableUtils.dataType.DATETIME,\n '',\n format\n );\n\n return FormatContextMenuUtils.makeOption(\n title,\n format,\n item.group,\n DateTimeColumnFormatter.isSameFormat(format, selectedFormat)\n );\n });\n\n const defaultOption = FormatContextMenuUtils.makeOption(\n 'Default',\n null,\n DateTimeFormatContextMenu.dateGroup,\n FormatContextMenuUtils.isDefaultSelected(selectedFormat)\n );\n\n return [defaultOption, ...presetFormatOptions];\n }\n}\n\nexport default DateTimeFormatContextMenu;\n","import FormatContextMenuUtils, {\n FormatContextMenuOption,\n} from './FormatContextMenuUtils';\nimport { DecimalColumnFormat, DecimalColumnFormatter } from '../formatters';\n\nclass DecimalFormatContextMenu {\n static defaultGroup = 10;\n\n static presetGroup = 20;\n\n static presetRoundGroup = 30;\n\n static customGroup = 40;\n\n /**\n * Creates list of formatting options for Decimal context menu\n * @param selectedFormat Selected format object, null for no selected format\n * @param onCustomFormatChange Callback to call when the custom format is changed\n * @returns Array of formatting options for the context menu\n */\n static getOptions(\n selectedFormat: DecimalColumnFormat,\n onCustomFormatChange: (value: DecimalColumnFormat | null) => void\n ): FormatContextMenuOption[] {\n const formatItems = [\n {\n format: DecimalColumnFormatter.FORMAT_PERCENT,\n group: DecimalFormatContextMenu.presetGroup,\n },\n {\n format: DecimalColumnFormatter.FORMAT_BASIS_POINTS,\n group: DecimalFormatContextMenu.presetGroup,\n },\n {\n format: DecimalColumnFormatter.FORMAT_MILLIONS,\n group: DecimalFormatContextMenu.presetGroup,\n },\n {\n format: DecimalColumnFormatter.FORMAT_ROUND,\n group: DecimalFormatContextMenu.presetRoundGroup,\n },\n {\n format: DecimalColumnFormatter.FORMAT_ROUND_TWO_DECIMALS,\n group: DecimalFormatContextMenu.presetRoundGroup,\n },\n {\n format: DecimalColumnFormatter.FORMAT_ROUND_FOUR_DECIMALS,\n group: DecimalFormatContextMenu.presetRoundGroup,\n },\n ];\n\n const defaultFormatOption = FormatContextMenuUtils.makeOption(\n 'Default',\n null,\n DecimalFormatContextMenu.defaultGroup,\n FormatContextMenuUtils.isDefaultSelected(selectedFormat)\n );\n\n const presetFormatOptions = formatItems.map(item =>\n FormatContextMenuUtils.makeOption(\n item.format.label,\n item.format,\n item.group,\n DecimalColumnFormatter.isSameFormat(item.format, selectedFormat)\n )\n );\n\n const isCustomSelected = FormatContextMenuUtils.isCustomSelected(\n selectedFormat\n );\n\n const customFormat = isCustomSelected\n ? selectedFormat\n : DecimalColumnFormatter.makeCustomFormat();\n\n const customFormatOption = FormatContextMenuUtils.makeCustomFormatOption(\n customFormat,\n DecimalFormatContextMenu.customGroup,\n DecimalColumnFormatter.DEFAULT_FORMAT_STRING,\n isCustomSelected,\n formatString => {\n if (formatString) {\n const newCustomFormat = DecimalColumnFormatter.makeCustomFormat(\n formatString\n );\n if (DecimalColumnFormatter.isValid(newCustomFormat)) {\n onCustomFormatChange(newCustomFormat);\n }\n } else {\n onCustomFormatChange(null);\n }\n }\n );\n\n return [defaultFormatOption, ...presetFormatOptions, customFormatOption];\n }\n}\n\nexport default DecimalFormatContextMenu;\n","import FormatContextMenuUtils, {\n FormatContextMenuOption,\n} from './FormatContextMenuUtils';\nimport { IntegerColumnFormat, IntegerColumnFormatter } from '../formatters';\n\nclass IntegerFormatContextMenu {\n static defaultGroup = 10;\n\n static presetGroup = 20;\n\n static customGroup = 30;\n\n /**\n * Creates list of formatting options for Integer context menu\n * @param selectedFormat Selected format object, null for no selected format\n * @param onCustomFormatChange Callback to call when the custom format is changed\n * @returns Array of formatting options for the context menu\n */\n static getOptions(\n selectedFormat: IntegerColumnFormat,\n onCustomFormatChange: (value: IntegerColumnFormat | null) => void\n ): FormatContextMenuOption[] {\n const formatItems = [\n {\n format: IntegerColumnFormatter.FORMAT_MILLIONS,\n group: IntegerFormatContextMenu.presetGroup,\n },\n ];\n\n const defaultFormatOption = FormatContextMenuUtils.makeOption(\n 'Default',\n null,\n IntegerFormatContextMenu.defaultGroup,\n FormatContextMenuUtils.isDefaultSelected(selectedFormat)\n );\n\n const presetFormatOptions = formatItems.map(item =>\n FormatContextMenuUtils.makeOption(\n item.format.label,\n item.format,\n item.group,\n IntegerColumnFormatter.isSameFormat(item.format, selectedFormat)\n )\n );\n\n const isCustomSelected = FormatContextMenuUtils.isCustomSelected(\n selectedFormat\n );\n\n const customFormat = isCustomSelected\n ? selectedFormat\n : IntegerColumnFormatter.makeCustomFormat();\n\n const customFormatOption = FormatContextMenuUtils.makeCustomFormatOption(\n customFormat,\n IntegerFormatContextMenu.customGroup,\n IntegerColumnFormatter.DEFAULT_FORMAT_STRING,\n isCustomSelected,\n formatString => {\n if (formatString) {\n const newCustomFormat = IntegerColumnFormatter.makeCustomFormat(\n formatString\n );\n if (IntegerColumnFormatter.isValid(newCustomFormat)) {\n onCustomFormatChange(newCustomFormat);\n }\n } else {\n onCustomFormatChange(null);\n }\n }\n );\n\n return [defaultFormatOption, ...presetFormatOptions, customFormatOption];\n }\n}\n\nexport default IntegerFormatContextMenu;\n","/* eslint class-methods-use-this: \"off\" */\nimport React from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { dhFilterFilled, vsRemove, vsCheck, vsFilter } from '@deephaven/icons';\nimport debounce from 'lodash.debounce';\nimport {\n ContextActions,\n ContextActionUtils,\n GLOBAL_SHORTCUTS,\n} from '@deephaven/components';\nimport { GridMouseHandler } from '@deephaven/grid';\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport {\n DateTimeFormatContextMenu,\n DecimalFormatContextMenu,\n IntegerFormatContextMenu,\n} from '../format-context-menus';\nimport './IrisGridContextMenuHandler.scss';\nimport TableUtils from '../TableUtils';\nimport { TableColumnFormatter, DateTimeColumnFormatter } from '../formatters';\nimport SHORTCUTS from '../IrisGridShortcuts';\n\nconst log = Log.module('IrisGridContextMenuHandler');\n\nconst DEBOUNCE_UPDATE_FORMAT = 150;\nconst CONTEXT_MENU_DATE_FORMAT = 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS';\n\n/**\n * Used to eat the mouse event in the bottom right corner of the scroll bar\n */\nclass IrisGridContextMenuHandler extends GridMouseHandler {\n static GROUP_EDIT = ContextActions.groups.high + 10;\n\n static GROUP_HIDE_COLUMNS = ContextActions.groups.high + 25;\n\n static GROUP_FILTER = ContextActions.groups.high + 50;\n\n static GROUP_SORT = ContextActions.groups.high + 75;\n\n static GROUP_COPY = ContextActions.groups.high + 100;\n\n static GROUP_FORMAT = ContextActions.groups.high + 150;\n\n static COLUMN_SORT_DIRECTION = {\n ascending: 'ASC',\n descending: 'DESC',\n none: null,\n };\n\n /**\n * Get filter condition for quick filter with existed column filter and the new filter to be applied,\n * returns new filter if filters are not additive.\n * if filters are additive, returns filter conditions combined with 'and'.\n * @param {FilterCondition} columnFilter\n * @param {FilterCondition} newColumnFilter\n * @param {boolean} additive\n */\n static getQuickFilterCondition(\n columnFilter,\n newColumnFilter,\n additive = false\n ) {\n if (!additive || !columnFilter) {\n return newColumnFilter;\n }\n return columnFilter.and(newColumnFilter);\n }\n\n /**\n * combines filter text with '&&' if filters are additive\n * @param {String} filterText\n * @param {String} newFilterText\n * @param {boolean} additive\n */\n static getQuickFilterText(filterText, newFilterText, additive = false) {\n return additive && filterText\n ? `${filterText} && ${newFilterText}`\n : newFilterText;\n }\n\n /**\n * Gets an equality filter for the provided numeric value\n * @param {dh.Column} column The column to make the filter for\n * @param {Number} value The value to get the equality filter for\n */\n static getNumberValueEqualsFilter(column, value) {\n const columnFilter = column.filter();\n if (value === Number.POSITIVE_INFINITY) {\n return dh.FilterCondition.invoke('isInf', columnFilter).and(\n columnFilter.greaterThan(dh.FilterValue.ofNumber(0))\n );\n }\n if (value === Number.NEGATIVE_INFINITY) {\n return dh.FilterCondition.invoke('isInf', columnFilter).and(\n columnFilter.lessThan(dh.FilterValue.ofNumber(0))\n );\n }\n if (Number.isNaN(value)) {\n return dh.FilterCondition.invoke('isNaN', columnFilter);\n }\n\n const filterValue = IrisGridContextMenuHandler.getFilterValueForNumberOrChar(\n column.type,\n value\n );\n return columnFilter.eq(filterValue);\n }\n\n static getFilterValueForNumberOrChar(columnType, value) {\n return TableUtils.isCharType(columnType)\n ? dh.FilterValue.ofString(String.fromCharCode(value))\n : dh.FilterValue.ofNumber(value);\n }\n\n constructor(irisGrid) {\n super();\n\n this.debouncedUpdateCustomFormat = debounce(\n irisGrid.handleFormatSelection,\n DEBOUNCE_UPDATE_FORMAT\n );\n\n this.irisGrid = irisGrid;\n }\n\n componentWillUnmount() {\n this.debouncedUpdateCustomFormat.flush();\n }\n\n onContextMenu(gridPoint, grid, event) {\n const { irisGrid } = this;\n const { y, column: columnIndex, row: rowIndex } = gridPoint;\n const modelColumn = irisGrid.getModelColumn(columnIndex);\n const modelRow = irisGrid.getModelRow(rowIndex);\n const { model, canCopy } = irisGrid.props;\n const { columns } = model;\n const value = model.valueForCell(modelColumn, modelRow);\n const valueText = model.textForCell(modelColumn, modelRow);\n const column = columns[modelColumn];\n\n const actions = [];\n\n const {\n metrics,\n isFilterBarShown,\n reverseType,\n quickFilters,\n advancedFilters,\n searchFilter,\n } = irisGrid.state;\n const theme = irisGrid.getTheme();\n const { columnHeaderHeight, gridY } = metrics;\n const {\n filterIconColor,\n filterBarActiveColor,\n contextMenuSortIconColor,\n contextMenuReverseIconColor,\n } = theme;\n const { onContextMenu, settings } = irisGrid.props;\n\n const modelSort = model.sort;\n const columnSort = TableUtils.getSortForColumn(modelSort, modelColumn);\n const hasReverse = reverseType !== TableUtils.REVERSE_TYPE.NONE;\n const dateFilterFormatter = new DateTimeColumnFormatter({\n timeZone: settings.timeZone,\n showTimeZone: false,\n showTSeparator: true,\n defaultDateTimeFormatString: CONTEXT_MENU_DATE_FORMAT,\n });\n const previewFilterFormatter = new DateTimeColumnFormatter({\n timeZone: settings.timeZone,\n showTimeZone: settings.showTimeZone,\n showTSeparator: settings.showTSeparator,\n defaultDateTimeFormatString: CONTEXT_MENU_DATE_FORMAT,\n });\n const isColumnFrozen = model.isColumnFrozen(columnIndex);\n\n if (column != null) {\n const { table } = model;\n actions.push(\n onContextMenu({\n table,\n model,\n value,\n valueText,\n column,\n rowIndex,\n columnIndex,\n modelRow,\n modelColumn,\n })\n );\n }\n\n if (column != null && model.isFilterable(modelColumn)) {\n actions.push({\n title: 'Clear Column Filter',\n group: IrisGridContextMenuHandler.GROUP_FILTER,\n order: 30,\n action: () => {\n this.irisGrid.removeColumnFilter(modelColumn);\n },\n disabled: !(\n quickFilters.has(modelColumn) || advancedFilters.has(modelColumn)\n ),\n });\n }\n\n if (isFilterBarShown ? y <= gridY : y <= columnHeaderHeight) {\n // grid header context menu options\n if (column != null) {\n const { userColumnWidths } = metrics;\n const isColumnHidden = [...userColumnWidths.values()].some(\n columnWidth => columnWidth === 0\n );\n actions.push({\n title: 'Hide Column',\n group: IrisGridContextMenuHandler.GROUP_HIDE_COLUMNS,\n action: () => {\n this.irisGrid.hideColumnByVisibleIndex(columnIndex);\n },\n });\n actions.push({\n title: isColumnFrozen ? 'Unfreeze Column' : 'Freeze Column',\n group: IrisGridContextMenuHandler.GROUP_HIDE_COLUMNS,\n action: () => {\n if (isColumnFrozen) {\n this.irisGrid.unFreezeColumnByColumnName(column.name);\n } else {\n this.irisGrid.freezeColumnByColumnName(column.name);\n }\n },\n order: 10,\n });\n actions.push({\n title: 'Show All Columns',\n group: IrisGridContextMenuHandler.GROUP_HIDE_COLUMNS,\n action: () => {\n this.irisGrid.showAllColumns();\n },\n disabled: !isColumnHidden,\n });\n actions.push({\n title: 'Quick Filters',\n icon: vsRemove,\n iconColor: filterBarActiveColor,\n shortcut: SHORTCUTS.TABLE.TOGGLE_QUICK_FILTER,\n group: IrisGridContextMenuHandler.GROUP_FILTER,\n order: 10,\n action: () => {\n this.irisGrid.toggleFilterBar(columnIndex);\n },\n });\n actions.push({\n title: 'Advanced Filters',\n icon: advancedFilters.get(modelColumn) ? dhFilterFilled : vsFilter,\n iconColor: filterIconColor,\n group: IrisGridContextMenuHandler.GROUP_FILTER,\n order: 20,\n action: () => {\n this.irisGrid.handleAdvancedMenuOpened(columnIndex);\n },\n });\n actions.push({\n title: 'Clear Table Filters',\n group: IrisGridContextMenuHandler.GROUP_FILTER,\n order: 40,\n // this just displays the shortcut, the actual listener is in irisgrid handleKeyDown\n shortcut: SHORTCUTS.TABLE.CLEAR_FILTERS,\n action: () => {\n this.irisGrid.clearAllFilters();\n },\n disabled: !(\n quickFilters.size > 0 ||\n advancedFilters.size > 0 ||\n searchFilter !== null\n ),\n });\n actions.push({\n title: 'Sort by',\n icon: vsRemove,\n iconColor: contextMenuSortIconColor,\n group: IrisGridContextMenuHandler.GROUP_SORT,\n order: 10,\n actions: this.sortByActions(column, modelColumn, columnSort),\n });\n actions.push({\n title: 'Add Additional Sort',\n /**\n * disable conditions:\n * 1. table is sorted only by this column\n * 2. table is only reversed\n * 3. 1 & 2 combined\n * 4. table has no sort\n * reverse is a type of sort, so needs to be accounted for in exclusions\n * */\n disabled:\n (columnSort && modelSort.length === 1) ||\n (hasReverse && modelSort.length === 1) ||\n (columnSort && hasReverse && modelSort.length === 2) ||\n modelSort.length === 0,\n group: IrisGridContextMenuHandler.GROUP_SORT,\n order: 20,\n actions: this.additionalSortActions(column, modelColumn),\n });\n actions.push({\n title: 'Clear Table Sorting',\n disabled:\n // reverse is a type of sort, but special and needs to be exluded despite being part of model.sort\n modelSort.length === 0 || (hasReverse && modelSort.length === 1),\n group: IrisGridContextMenuHandler.GROUP_SORT,\n action: () => {\n this.irisGrid.sortColumn(\n columnIndex,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.none\n );\n },\n order: 30,\n });\n actions.push({\n title:\n reverseType === TableUtils.REVERSE_TYPE.NONE\n ? 'Reverse Table'\n : 'Clear Reverse Table',\n icon: vsRemove,\n iconColor: contextMenuReverseIconColor,\n group: IrisGridContextMenuHandler.GROUP_SORT,\n order: 40,\n disabled: !model.isReversible,\n // this just displays the shortcut, the actual listener is in irisgrid handleKeyDown\n shortcut: SHORTCUTS.TABLE.REVERSE,\n action: () => {\n if (reverseType === TableUtils.REVERSE_TYPE.NONE) {\n this.irisGrid.reverse(TableUtils.REVERSE_TYPE.POST_SORT);\n } else {\n this.irisGrid.reverse(TableUtils.REVERSE_TYPE.NONE);\n }\n },\n });\n actions.push({\n title: 'Copy Column Name',\n group: IrisGridContextMenuHandler.GROUP_COPY,\n action: () => {\n ContextActionUtils.copyToClipboard(\n model.textForColumnHeader(modelColumn)\n ).catch(e => log.error('Unable to copy header', e));\n },\n });\n\n if (TableUtils.isDateType(column.type)) {\n actions.push({\n title: 'Date/Time Format',\n group: IrisGridContextMenuHandler.GROUP_FORMAT,\n actions: this.dateFormatActions(column),\n });\n } else if (TableUtils.isNumberType(column.type)) {\n actions.push({\n title: 'Number Format',\n group: IrisGridContextMenuHandler.GROUP_FORMAT,\n actions: this.numberFormatActions(column),\n });\n }\n }\n } else {\n // grid data area context menu options\n if (column != null && rowIndex != null) {\n if (model.isFilterable(modelColumn)) {\n // cell data area contextmenu options\n const filterMenu = {\n title: 'Filter By Value',\n icon: vsRemove,\n iconColor: filterIconColor,\n group: IrisGridContextMenuHandler.GROUP_FILTER,\n order: 10,\n actions: null,\n };\n\n const andFilterMenu = {\n title: 'Add Filter By Value',\n icon: vsRemove,\n iconColor: filterIconColor,\n group: IrisGridContextMenuHandler.GROUP_FILTER,\n order: 20,\n actions: null,\n disabled: !quickFilters.get(modelColumn),\n };\n\n if (value != null) {\n // Chars get treated like numbers in terms of which filters are available\n if (\n TableUtils.isNumberType(column.type) ||\n TableUtils.isCharType(column.type)\n ) {\n // We want to show the full unformatted value if it's a number, so user knows which value they are matching\n // If it's a Char we just show the char\n const numberValueText = TableUtils.isCharType(column.type)\n ? String.fromCharCode(value)\n : `${value}`;\n filterMenu.actions = this.numberFilterActions(\n column,\n numberValueText,\n value\n );\n andFilterMenu.actions = this.numberFilterActions(\n column,\n numberValueText,\n value,\n quickFilters.get(modelColumn),\n true\n );\n } else if (TableUtils.isBooleanType(column.type)) {\n filterMenu.actions = this.booleanFilterActions(column, valueText);\n andFilterMenu.actions = this.booleanFilterActions(\n column,\n valueText,\n quickFilters.get(modelColumn),\n true\n );\n } else if (TableUtils.isDateType(column.type)) {\n const dateValueText = dateFilterFormatter.format(value);\n const previewValue = previewFilterFormatter.format(value);\n filterMenu.actions = this.dateFilterActions(\n column,\n dateValueText,\n previewValue,\n value\n );\n andFilterMenu.actions = this.dateFilterActions(\n column,\n dateValueText,\n previewValue,\n value,\n quickFilters.get(modelColumn),\n true\n );\n } else {\n filterMenu.actions = this.stringFilterActions(\n column,\n valueText,\n value\n );\n andFilterMenu.actions = this.stringFilterActions(\n column,\n valueText,\n value,\n quickFilters.get(modelColumn),\n true\n );\n }\n } else {\n filterMenu.actions = this.nullFilterActions(column);\n andFilterMenu.actions = this.nullFilterActions(\n column,\n quickFilters.get(modelColumn),\n true\n );\n }\n\n if (filterMenu.actions != null && filterMenu.actions.length > 0) {\n actions.push(filterMenu);\n }\n if (\n andFilterMenu.actions != null &&\n andFilterMenu.actions.length > 0\n ) {\n actions.push(andFilterMenu);\n }\n }\n\n if (canCopy) {\n actions.push({\n title: 'Copy Cell',\n group: IrisGridContextMenuHandler.GROUP_COPY,\n order: 10,\n action: () => {\n irisGrid.copyCell(columnIndex, rowIndex);\n },\n });\n\n actions.push({\n title: 'Copy Cell Unformatted',\n group: IrisGridContextMenuHandler.GROUP_COPY,\n order: 20,\n action: () => {\n irisGrid.copyCell(columnIndex, rowIndex, true);\n },\n });\n }\n }\n\n // data area, including blank space context menu options\n const { selectedRanges } = grid.state;\n if (selectedRanges.length > 0) {\n if (canCopy) {\n actions.push({\n title: 'Copy Selection',\n shortcut: GLOBAL_SHORTCUTS.COPY,\n group: IrisGridContextMenuHandler.GROUP_COPY,\n order: 30,\n action: () => {\n irisGrid.copyRanges(selectedRanges);\n },\n });\n\n actions.push({\n title: 'Copy Selection w/ Headers',\n group: IrisGridContextMenuHandler.GROUP_COPY,\n order: 40,\n action: () => {\n irisGrid.copyRanges(selectedRanges, true);\n },\n });\n }\n\n if (model.isEditable) {\n actions.push({\n title: 'Delete Selected Rows',\n group: IrisGridContextMenuHandler.GROUP_EDIT,\n order: 50,\n action: () => {\n this.irisGrid.deleteRanges(selectedRanges);\n },\n });\n }\n }\n }\n\n if (actions.length === 0) {\n return false;\n }\n\n ContextActions.triggerMenu(\n irisGrid.gridWrapper,\n event.pageX,\n event.pageY,\n actions\n );\n return true;\n }\n\n dateFormatActions(column) {\n const { model } = this.irisGrid.props;\n const { formatter } = model;\n const selectedFormat = formatter.getColumnFormat(column.type, column.name);\n const formatOptions = DateTimeFormatContextMenu.getOptions(\n formatter,\n selectedFormat\n );\n\n const actions = [];\n\n for (let i = 0; i < formatOptions.length; i += 1) {\n const { description, format, group, isSelected, title } = formatOptions[\n i\n ];\n actions.push({\n title,\n description,\n icon: isSelected ? vsCheck : null,\n group,\n order: i,\n action: () => {\n this.irisGrid.handleFormatSelection(\n model.getColumnIndexByName(column.name),\n format\n );\n },\n });\n }\n return actions;\n }\n\n numberFormatActions(column) {\n const { model } = this.irisGrid.props;\n const { formatter } = model;\n const selectedFormat = formatter.getColumnFormat(column.type, column.name);\n let formatOptions;\n\n const columnIndex = model.getColumnIndexByName(column.name);\n if (TableUtils.isDecimalType(column.type)) {\n formatOptions = DecimalFormatContextMenu.getOptions(\n selectedFormat,\n format => {\n this.debouncedUpdateCustomFormat(columnIndex, format);\n }\n );\n } else if (TableUtils.isIntegerType(column.type)) {\n formatOptions = IntegerFormatContextMenu.getOptions(\n selectedFormat,\n format => {\n this.debouncedUpdateCustomFormat(columnIndex, format);\n }\n );\n } else {\n log.error('Invalid column type in numberFormatActions');\n return null;\n }\n\n const actions = [];\n\n for (let i = 0; i < formatOptions.length; i += 1) {\n const { format, isSelected } = formatOptions[i];\n actions.push({\n ...formatOptions[i],\n icon: isSelected ? vsCheck : null,\n order: i,\n action: () => {\n if (\n format &&\n format.type === TableColumnFormatter.TYPE_CONTEXT_CUSTOM\n ) {\n return;\n }\n this.irisGrid.handleFormatSelection(columnIndex, format);\n },\n });\n }\n return actions;\n }\n\n stringFilterActions(\n column,\n valueText,\n value,\n quickFilter = {},\n additive = false\n ) {\n const filterValue = dh.FilterValue.ofString(value);\n const { filter, text: filterText } = quickFilter;\n const actions = [];\n const { model } = this.irisGrid.props;\n const columnIndex = model.getColumnIndexByName(column.name);\n\n actions.push({\n menuElement: (\n <div className=\"iris-grid-filter-menu-item-value\">\n &quot;{valueText}&quot;\n </div>\n ),\n order: 1,\n });\n\n actions.push({\n title: 'text is exactly',\n description: `Show only rows where ${column.name} is ${value} (case sensitive)`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().eq(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `=${valueText}`,\n additive\n )\n );\n },\n order: 10,\n });\n actions.push({\n title: 'text is not exactly',\n description: `Show only rows where ${column.name} is not ${valueText} (case sensitive)`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().notEq(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `!=${valueText}`,\n additive\n )\n );\n },\n order: 20,\n });\n actions.push({\n title: `text contains`,\n description: `Show only rows where ${column.name} contains ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().contains(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `~${valueText}`,\n additive\n )\n );\n },\n order: 30,\n });\n actions.push({\n title: 'text does not contain',\n description: `Show only rows where ${column.name} does not contain ${value}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().contains(filterValue).not(),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `!~${valueText}`,\n additive\n )\n );\n },\n order: 40,\n });\n actions.push({\n title: 'text starts with',\n description: `Show only rows where ${column.name} starts with ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().invoke('startsWith', filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `${valueText}*`,\n additive\n )\n );\n },\n order: 50,\n });\n actions.push({\n title: 'text ends with',\n description: `Show only rows where ${column.name} ends with ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n quickFilter,\n column.filter().invoke('endsWith', filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `*${valueText}`,\n additive\n )\n );\n },\n order: 60,\n });\n return actions;\n }\n\n numberFilterActions(\n column,\n valueText,\n value,\n quickFilter = {},\n additive = false\n ) {\n const filterValue = IrisGridContextMenuHandler.getFilterValueForNumberOrChar(\n column.type,\n value\n );\n const { filter, text: filterText } = quickFilter;\n const actions = [];\n const isFinite =\n value !== Number.POSITIVE_INFINITY &&\n value !== Number.NEGATIVE_INFINITY &&\n !Number.isNaN(value);\n const { model } = this.irisGrid.props;\n const columnIndex = model.getColumnIndexByName(column.name);\n\n actions.push({\n menuElement: (\n <div className=\"iris-grid-filter-menu-item-value\">\n {additive ? ' AND ' : ''}&quot;{valueText}&quot;\n </div>\n ),\n order: 1,\n });\n actions.push({\n title: 'is equal to',\n description: `Show only rows where ${column.name} is ${valueText}`,\n action: () => {\n const valueFilter = IrisGridContextMenuHandler.getNumberValueEqualsFilter(\n column,\n value\n );\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n valueFilter,\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `=${valueText}`,\n additive\n )\n );\n },\n order: 10,\n });\n actions.push({\n title: 'is not equal to',\n description: `Show only rows where ${column.name} is not ${valueText}`,\n action: () => {\n const valueFilter = IrisGridContextMenuHandler.getNumberValueEqualsFilter(\n column,\n value\n ).not();\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n valueFilter,\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `!=${valueText}`,\n additive\n )\n );\n },\n order: 20,\n });\n\n // IDS-6092 Less/greater than filters don't make sense for Infinite/NaN\n // TODO (DH-11799): These char filters should work in Bard, with the merge for DH-11040: https://gitlab.eng.illumon.com/illumon/iris/merge_requests/5801\n // They do not work in Powell though, so disable them.\n if (isFinite && !TableUtils.isCharType(column.type)) {\n actions.push({\n title: 'greater than',\n description: `Show only rows where ${column.name} is greater than ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().greaterThan(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `>${valueText}`,\n additive\n )\n );\n },\n order: 30,\n });\n actions.push({\n title: 'greater than or equal to',\n description: `Show only rows where ${column.name} is greater than or equal to ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().greaterThanOrEqualTo(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `>=${valueText}`,\n additive\n )\n );\n },\n order: 40,\n });\n actions.push({\n title: 'less than',\n description: `Show only rows where ${column.name} is less than ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().lessThan(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `<${valueText}`,\n additive\n )\n );\n },\n order: 50,\n });\n actions.push({\n title: 'less than or equal to',\n description: `Show only rows where ${column.name} is less than or equal to ${valueText}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().lessThanOrEqualTo(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `<=${valueText}`,\n additive\n )\n );\n },\n order: 60,\n });\n }\n return actions;\n }\n\n booleanFilterActions(column, valueText, quickFilter = {}, additive = false) {\n const actions = [];\n const { filter, text: filterText } = quickFilter;\n const { model } = this.irisGrid.props;\n const columnIndex = model.getColumnIndexByName(column.name);\n\n actions.push({\n menuElement: (\n <div className=\"iris-grid-filter-menu-item-value\">\n {additive ? 'AND ' : ''}&quot;{valueText}&quot;\n </div>\n ),\n order: 1,\n });\n actions.push({\n title: 'true',\n description: `Show only rows where ${column.name} is true`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().isTrue(),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n 'true',\n additive\n )\n );\n },\n order: 10,\n });\n actions.push({\n title: 'false',\n description: `Show only rows where ${column.name} is false`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().isFalse(),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n 'false',\n additive\n )\n );\n },\n order: 20,\n });\n actions.push({\n title: 'null',\n description: `Show only rows where ${column.name} is null`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n quickFilter,\n column.filter().isNull(),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n 'null',\n additive\n )\n );\n },\n order: 30,\n });\n\n return actions;\n }\n\n dateFilterActions(\n column,\n valueText,\n previewValue,\n value,\n quickFilter = {},\n additive = false\n ) {\n const filterValue = dh.FilterValue.ofNumber(value);\n const { filter, text: filterText } = quickFilter;\n const { model } = this.irisGrid.props;\n const columnIndex = model.getColumnIndexByName(column.name);\n\n const actions = [];\n\n actions.push({\n menuElement: (\n <div className=\"iris-grid-filter-menu-item-value\">\n {additive ? ' AND ' : ''}&quot;{previewValue}&quot;\n </div>\n ),\n order: 1,\n });\n actions.push({\n title: 'date is',\n description: `Show only rows where ${column.name} is ${previewValue}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().eq(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `=${valueText}`,\n additive\n )\n );\n },\n order: 10,\n });\n actions.push({\n title: 'date is not',\n description: `Show only rows where ${column.name} is not ${previewValue}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().notEq(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `!=${valueText}`,\n additive\n )\n );\n },\n order: 20,\n });\n actions.push({\n title: 'date is before',\n description: `Show only rows where ${column.name} is before ${previewValue}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().lessThan(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `<${valueText}`,\n additive\n )\n );\n },\n order: 30,\n });\n actions.push({\n title: 'date is before or equal',\n description: `Show only rows where ${column.name} is before or equal to ${previewValue}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().lessThanOrEqualTo(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `<=${valueText}`,\n additive\n )\n );\n },\n order: 40,\n });\n actions.push({\n title: 'date is after',\n description: `Show only rows where ${column.name} is greater than ${previewValue}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().greaterThan(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `>${valueText}`,\n additive\n )\n );\n },\n order: 50,\n });\n actions.push({\n title: 'date is after or equal',\n description: `Show only rows where ${column.name} is after or equal to ${previewValue}`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().greaterThanOrEqualTo(filterValue),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n `>=${valueText}`,\n additive\n )\n );\n },\n order: 60,\n });\n return actions;\n }\n\n nullFilterActions(column, quickFilter = {}, additive = false) {\n const { filter, text: filterText } = quickFilter;\n const actions = [];\n const { model } = this.irisGrid.props;\n const columnIndex = model.getColumnIndexByName(column.name);\n\n actions.push({\n menuElement: (\n <div className=\"iris-grid-filter-menu-item-value\">\n {additive ? ' AND ' : ''}&quot;null&quot;\n </div>\n ),\n order: 1,\n });\n actions.push({\n title: 'equals null',\n description: `Show only rows where ${column.name} is null`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().isNull(),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n 'null',\n additive\n )\n );\n },\n order: 10,\n });\n actions.push({\n title: 'not equals null',\n description: `Show only rows where ${column.name} is not null`,\n action: () => {\n this.irisGrid.setQuickFilter(\n columnIndex,\n IrisGridContextMenuHandler.getQuickFilterCondition(\n filter,\n column.filter().isNull().not(),\n additive\n ),\n IrisGridContextMenuHandler.getQuickFilterText(\n filterText,\n '!null',\n additive\n )\n );\n },\n order: 20,\n });\n\n return actions;\n }\n\n sortByActions(column, modelColumn, columnSort) {\n const theme = this.irisGrid.getTheme();\n const { contextMenuSortIconColor } = theme;\n const sortActions = [\n {\n title: `${column.name} Ascending`,\n order: 10,\n action: () => {\n this.irisGrid.sortColumn(\n modelColumn,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.ascending\n );\n },\n icon: this.checkColumnSort(\n columnSort,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.ascending\n )\n ? vsRemove\n : null,\n iconColor: contextMenuSortIconColor,\n },\n {\n title: `${column.name} Descending`,\n order: 20,\n action: () => {\n this.irisGrid.sortColumn(\n modelColumn,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.descending\n );\n },\n icon: this.checkColumnSort(\n columnSort,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.descending\n )\n ? vsRemove\n : null,\n iconColor: contextMenuSortIconColor,\n },\n {\n title: `Remove Sort`,\n order: 50,\n action: () => {\n this.irisGrid.sortColumn(\n modelColumn,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.none,\n false,\n true\n );\n },\n disabled: !columnSort,\n },\n ];\n if (TableUtils.isNumberType(column.type)) {\n sortActions.push({\n title: `ABS(${column.name}) Ascending`,\n order: 30,\n action: () => {\n this.irisGrid.sortColumn(\n modelColumn,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.ascending,\n true\n );\n },\n icon: this.checkColumnSort(\n columnSort,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.ascending,\n true\n )\n ? vsRemove\n : null,\n iconColor: contextMenuSortIconColor,\n });\n sortActions.push({\n title: `ABS(${column.name}) Descending`,\n order: 40,\n action: () => {\n this.irisGrid.sortColumn(\n modelColumn,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.descending,\n true\n );\n },\n icon: this.checkColumnSort(\n columnSort,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.descending,\n true\n )\n ? vsRemove\n : null,\n iconColor: contextMenuSortIconColor,\n });\n }\n return sortActions;\n }\n\n additionalSortActions(column, columnIndex) {\n const theme = this.irisGrid.getTheme();\n const { contextMenuSortIconColor } = theme;\n const additionalSortActions = [\n {\n title: 'Add Sort By',\n menuElement: (\n <div className=\"btn-context-menu menu-title\">\n <span className=\"icon\">\n <FontAwesomeIcon\n icon={vsRemove}\n style={{ color: contextMenuSortIconColor }}\n />\n </span>\n <span className=\"title\">Add Additional Sort</span>\n <span className=\"shortcut\">\n {ContextActionUtils.isMacPlatform() ? '⌘Click' : '^Click'}\n </span>\n </div>\n ),\n order: 1,\n },\n {\n title: `${column.name} Ascending`,\n order: 10,\n action: () => {\n this.irisGrid.sortColumn(\n columnIndex,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.ascending,\n false,\n true\n );\n },\n },\n {\n title: `${column.name} Descending`,\n order: 20,\n action: () => {\n this.irisGrid.sortColumn(\n columnIndex,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.descending,\n false,\n true\n );\n },\n },\n ];\n if (TableUtils.isNumberType(column.type)) {\n additionalSortActions.push({\n title: `ABS(${column.name}) Ascending`,\n order: 30,\n action: () => {\n this.irisGrid.sortColumn(\n columnIndex,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.ascending,\n true,\n true\n );\n },\n });\n additionalSortActions.push({\n title: `ABS(${column.name}) Descending`,\n order: 40,\n action: () => {\n this.irisGrid.sortColumn(\n columnIndex,\n IrisGridContextMenuHandler.COLUMN_SORT_DIRECTION.descending,\n true,\n true\n );\n },\n });\n }\n return additionalSortActions;\n }\n\n checkColumnSort(columnSort, direction = null, isAbs = false) {\n if (!columnSort) {\n return false;\n }\n return columnSort.direction === direction && columnSort.isAbs === isAbs;\n }\n}\n\nexport default IrisGridContextMenuHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { GridMouseHandler } from '@deephaven/grid';\n\n/**\n * Handles sending data selected via double click\n */\nclass IrisGridDataSelectMouseHandler extends GridMouseHandler {\n constructor(irisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n onDoubleClick(gridPoint) {\n const { column, row } = gridPoint;\n if (row == null || column == null) {\n return false;\n }\n\n this.irisGrid.selectData(column, row);\n\n return true;\n }\n}\n\nexport default IrisGridDataSelectMouseHandler;\n","/* eslint class-methods-use-this: \"off\" */\nimport { GridMouseHandler, GridUtils } from '@deephaven/grid';\n\n/**\n * Handles sending data selected via double click\n */\nclass PendingMouseHandler extends GridMouseHandler {\n constructor(irisGrid) {\n super();\n\n this.irisGrid = irisGrid;\n }\n\n onWheel(gridPoint, grid, wheelEvent) {\n const { irisGrid } = this;\n const { model } = irisGrid.props;\n const { metrics, pendingRowCount } = irisGrid.state;\n const { bottom, rowCount, rowHeight } = metrics;\n const { deltaY } = GridUtils.getScrollDelta(wheelEvent);\n if (model.isEditable && bottom >= rowCount - 1 && deltaY > 0) {\n // We add new rows onto the bottom, but we don't consume the event\n irisGrid.setState({\n pendingRowCount: pendingRowCount + Math.ceil(deltaY / rowHeight),\n });\n }\n return false;\n }\n}\n\nexport default PendingMouseHandler;\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePrevious } from '@deephaven/react-hooks';\nimport IrisGridBottomBar from './IrisGridBottomBar';\nimport './PendingDataBottomBar.scss';\n\nconst HIDE_TIMEOUT = 3000;\n\nexport type ToastBottomBarProps = {\n children?: React.ReactNode;\n onEntering?: () => void;\n onEntered?: () => void;\n onExiting?: () => void;\n onExited?: () => void;\n};\n\nexport const ToastBottomBar = ({\n children = null,\n onEntering,\n onEntered,\n onExiting,\n onExited,\n}: ToastBottomBarProps): JSX.Element => {\n const [isShown, setIsShown] = useState(false);\n const timeout = useRef<ReturnType<typeof setTimeout>>();\n const prevChildren = usePrevious(children);\n\n const startTimer = useCallback(() => {\n setIsShown(true);\n if (timeout.current) {\n clearTimeout(timeout.current);\n }\n timeout.current = setTimeout(() => {\n setIsShown(false);\n }, HIDE_TIMEOUT);\n }, [setIsShown, timeout]);\n\n useEffect(() => {\n if (prevChildren !== children && children != null) {\n startTimer();\n }\n }, [children, prevChildren, setIsShown, startTimer]);\n\n useEffect(\n () => () => (timeout.current ? clearTimeout(timeout.current) : undefined),\n []\n );\n\n return (\n <IrisGridBottomBar\n className=\"toast-bottom-bar\"\n isShown={isShown}\n onEntering={onEntering}\n onEntered={onEntered}\n onExiting={onExiting}\n onExited={onExited}\n >\n {children}\n </IrisGridBottomBar>\n );\n};\n\nexport default ToastBottomBar;\n","import { GridMetricCalculator } from '@deephaven/grid';\nimport type { VisibleIndex, GridMetricState, GridTheme } from '@deephaven/grid';\nimport TableUtils from './TableUtils';\nimport type IrisGridModel from './IrisGridModel';\nimport type IrisGridTheme from './IrisGridTheme';\n\nexport interface IrisGridMetricState extends GridMetricState {\n model: IrisGridModel;\n theme: typeof IrisGridTheme & typeof GridTheme;\n isFilterBarShown: boolean;\n advancedFilters: Map<string, unknown>;\n quickFilters: Map<string, unknown>;\n sorts: unknown[];\n reverseType: string;\n}\n\n/* eslint class-methods-use-this: \"off\" */\n/* eslint react/destructuring-assignment: \"off\" */\n/**\n * Class to calculate all the metrics for a grid.\n * Call getMetrics() with the state to get metrics\n */\nclass IrisGridMetricCalculator extends GridMetricCalculator {\n getVisibleColumnWidth(\n column: VisibleIndex,\n state: IrisGridMetricState,\n firstColumn: VisibleIndex = this.getFirstColumn(state),\n treePaddingX = this.calculateTreePaddingX(state)\n ): number {\n const { model } = state;\n const hiddenColumns = model.layoutHints?.hiddenColumns ?? [];\n const modelColumn = this.getModelColumn(column, state);\n\n const existingWidth = this.userColumnWidths.get(modelColumn);\n if (existingWidth !== undefined) {\n return existingWidth;\n }\n if (hiddenColumns.includes(model.columns[modelColumn].name)) {\n return 0;\n }\n return super.getVisibleColumnWidth(\n column,\n state,\n firstColumn,\n treePaddingX\n );\n }\n\n getGridY(state: IrisGridMetricState): number {\n let gridY = super.getGridY(state);\n const {\n isFilterBarShown,\n theme,\n advancedFilters,\n quickFilters,\n sorts,\n reverseType,\n } = state;\n if (isFilterBarShown) {\n gridY += theme.filterBarHeight;\n } else if (\n (quickFilters && quickFilters.size > 0) ||\n (advancedFilters && advancedFilters.size > 0)\n ) {\n gridY += theme.filterBarCollapsedHeight;\n }\n if (reverseType !== TableUtils.REVERSE_TYPE.NONE && sorts.length > 0) {\n gridY += theme.reverseHeaderBarHeight;\n }\n\n return gridY;\n }\n}\n\nexport default IrisGridMetricCalculator;\n","/* eslint-disable no-param-reassign */\nimport React, { useEffect, useMemo } from 'react';\nimport PropTypes from 'prop-types';\nimport dh, { PropTypes as APIPropTypes } from '@deephaven/jsapi-shim';\nimport Formatter from './Formatter';\nimport IrisGridModel from './IrisGridModel';\nimport IrisGridUtils from './IrisGridUtils';\nimport TableUtils from './TableUtils';\n\nconst COLUMN_BUFFER_PAGES = 1;\n\n/**\n * React component to keep IrisGridModel in sync\n */\nconst IrisGridModelUpdater = React.memo(\n ({\n model,\n modelColumns,\n top,\n bottom,\n left,\n right,\n filter,\n formatter,\n reverseType,\n sorts,\n customColumns,\n movedColumns,\n hiddenColumns,\n alwaysFetchColumns,\n rollupConfig,\n totalsConfig,\n selectDistinctColumns,\n pendingRowCount,\n pendingDataMap,\n frozenColumns,\n }) => {\n const columns = useMemo(\n () =>\n IrisGridUtils.getModelViewportColumns(\n modelColumns,\n left,\n right,\n movedColumns,\n hiddenColumns,\n alwaysFetchColumns,\n COLUMN_BUFFER_PAGES\n ),\n [\n modelColumns,\n left,\n right,\n movedColumns,\n hiddenColumns,\n alwaysFetchColumns,\n ]\n );\n\n useEffect(() => {\n model.filter = filter;\n }, [model, filter]);\n useEffect(() => {\n const sortsForModel = [...sorts];\n if (reverseType !== TableUtils.REVERSE_TYPE.NONE) {\n sortsForModel.push(dh.Table.reverse());\n }\n model.sort = sortsForModel;\n }, [model, sorts, reverseType]);\n useEffect(() => {\n model.formatter = formatter;\n }, [model, formatter]);\n useEffect(() => {\n if (model.isCustomColumnsAvailable) {\n model.customColumns = customColumns;\n }\n }, [model, customColumns]);\n useEffect(() => {\n model.setViewport(top, bottom, columns);\n }, [model, top, bottom, columns]);\n useEffect(() => {\n if (model.isRollupAvailable) {\n model.rollupConfig = rollupConfig;\n }\n }, [model, model.isRollupAvailable, rollupConfig]);\n useEffect(() => {\n if (model.isSelectDistinctAvailable) {\n model.selectDistinctColumns = selectDistinctColumns;\n }\n }, [model, selectDistinctColumns]);\n useEffect(() => {\n if (model.isTotalsAvailable) {\n model.totalsConfig = totalsConfig;\n }\n }, [model, model.isTotalsAvailable, totalsConfig]);\n useEffect(() => {\n model.pendingRowCount = pendingRowCount;\n }, [model, pendingRowCount]);\n useEffect(() => {\n model.pendingDataMap = pendingDataMap;\n }, [model, pendingDataMap]);\n useEffect(() => {\n model.updateFrozenColumns(frozenColumns);\n }, [model, frozenColumns]);\n\n return null;\n }\n);\n\nIrisGridModelUpdater.displayName = 'IrisGridModelUpdater';\n\nIrisGridModelUpdater.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n modelColumns: PropTypes.arrayOf(APIPropTypes.Column).isRequired,\n top: PropTypes.number.isRequired,\n bottom: PropTypes.number.isRequired,\n left: PropTypes.number,\n right: PropTypes.number,\n filter: PropTypes.arrayOf(APIPropTypes.FilterCondition).isRequired,\n sorts: PropTypes.arrayOf(APIPropTypes.Sort).isRequired,\n reverseType: PropTypes.oneOf(Object.values(TableUtils.REVERSE_TYPE)),\n customColumns: PropTypes.arrayOf(PropTypes.string).isRequired,\n movedColumns: PropTypes.arrayOf(PropTypes.shape({})).isRequired,\n hiddenColumns: PropTypes.arrayOf(PropTypes.number).isRequired,\n frozenColumns: PropTypes.arrayOf(PropTypes.string),\n alwaysFetchColumns: PropTypes.arrayOf(PropTypes.string).isRequired,\n formatter: PropTypes.instanceOf(Formatter).isRequired,\n rollupConfig: APIPropTypes.RollupConfig,\n totalsConfig: PropTypes.shape({}),\n selectDistinctColumns: PropTypes.arrayOf(PropTypes.string),\n pendingRowCount: PropTypes.number,\n pendingDataMap: PropTypes.instanceOf(Map),\n};\n\nIrisGridModelUpdater.defaultProps = {\n left: null,\n right: null,\n reverseType: TableUtils.REVERSE_TYPE.NONE,\n rollupConfig: null,\n totalsConfig: null,\n selectDistinctColumns: [],\n pendingRowCount: 0,\n pendingDataMap: new Map(),\n frozenColumns: null,\n};\n\nexport default IrisGridModelUpdater;\n","/* eslint react/destructuring-assignment: \"off\" */\n/* eslint class-methods-use-this: \"off\" */\n/* eslint no-param-reassign: \"off\" */\nimport {\n dhSortDown,\n dhSortUp,\n vsTriangleDown,\n vsTriangleRight,\n} from '@deephaven/icons';\nimport { GridRenderer, GridUtils } from '@deephaven/grid';\nimport TableUtils from './TableUtils';\n\nconst ICON_NAMES = Object.freeze({\n SORT_UP: 'sortUp',\n SORT_DOWN: 'sortDown',\n CARET_DOWN: 'caretDown',\n CARET_RIGHT: 'caretRight',\n});\n\nconst ICON_SCALE = 0.03;\n\n/**\n * Handles rendering some of the Iris specific features, such as sorting icons, sort bar display\n * */\nclass IrisGridRenderer extends GridRenderer {\n static isFilterValid(advancedFilter, quickFilter) {\n const isAdvancedFilterValid =\n advancedFilter == null || advancedFilter.filter != null;\n const isQuickFilterValid =\n quickFilter == null || quickFilter.filter != null;\n return isAdvancedFilterValid && isQuickFilterValid;\n }\n\n constructor() {\n super();\n\n this.initIcons();\n }\n\n initIcons() {\n this.icons = {};\n\n this.setIcon(ICON_NAMES.SORT_UP, dhSortUp);\n this.setIcon(ICON_NAMES.SORT_DOWN, dhSortDown);\n this.setIcon(ICON_NAMES.CARET_DOWN, vsTriangleDown);\n this.setIcon(ICON_NAMES.CARET_RIGHT, vsTriangleRight);\n }\n\n setIcon(name, faIcon) {\n this.icons[name] = new Path2D(faIcon.icon[4]);\n }\n\n getIcon(name) {\n return this.icons[name];\n }\n\n getSortIcon(sort) {\n if (!sort) {\n return null;\n }\n if (sort.direction === TableUtils.sortDirection.ascending) {\n return new Path2D(this.getIcon(ICON_NAMES.SORT_UP));\n }\n if (sort.direction === TableUtils.sortDirection.descending) {\n return new Path2D(this.getIcon(ICON_NAMES.SORT_DOWN));\n }\n return null;\n }\n\n drawCanvas(state) {\n super.drawCanvas(state);\n\n this.drawScrim(state);\n }\n\n drawGridLines(context, state) {\n super.drawGridLines(context, state);\n\n this.drawGroupedColumnLine(context, state);\n\n this.drawPendingRowLine(context, state);\n }\n\n drawCellContent(context, state, column, row) {\n const { metrics, model } = state;\n const { modelColumns, modelRows } = metrics;\n const modelRow = modelRows.get(row);\n const modelColumn = modelColumns.get(column);\n const value = model.valueForCell(modelColumn, modelRow);\n if (TableUtils.isTextType(model.columns[modelColumn].type)) {\n if (value === null || value === '') {\n const originalFont = context.font;\n context.font = `italic ${originalFont}`;\n const displayValue = value === null ? 'null' : 'empty';\n super.drawCellContent(context, state, column, row, displayValue);\n context.font = originalFont;\n return;\n }\n }\n super.drawCellContent(context, state, column, row);\n }\n\n drawGroupedColumnLine(context, state) {\n const { metrics, model, theme } = state;\n const { groupedColumns, columns } = model;\n const { maxY, visibleColumnWidths, visibleColumnXs } = metrics;\n if (groupedColumns.length === 0 || !theme.groupedColumnDividerColor) {\n return;\n }\n\n const lastGroupedColumn = groupedColumns[groupedColumns.length - 1];\n const modelIndex = columns.findIndex(\n c => c.name === lastGroupedColumn.name\n );\n const columnX = visibleColumnXs.get(modelIndex);\n const columnWidth = visibleColumnWidths.get(modelIndex);\n if (columnX == null || columnWidth == null) {\n return;\n }\n\n const x = columnX + columnWidth + 0.5;\n\n context.strokeStyle = theme.groupedColumnDividerColor;\n context.lineWidth = 1;\n context.beginPath();\n context.moveTo(x, 0);\n context.lineTo(x, maxY);\n context.stroke();\n }\n\n drawPendingRowLine(context, state) {\n const { metrics, model, theme } = state;\n const { visibleRowYs, maxX } = metrics;\n const { pendingRowCount } = model;\n if (pendingRowCount <= 0) {\n return;\n }\n\n const firstPendingRow =\n model.rowCount - model.pendingRowCount - model.floatingBottomRowCount;\n let y = visibleRowYs.get(firstPendingRow);\n if (y == null) {\n return;\n }\n\n y -= 0.5;\n context.save();\n context.setLineDash([4, 2]);\n context.strokeStyle = theme.pendingTextColor;\n context.lineWidth = 1;\n context.beginPath();\n context.moveTo(0, y);\n context.lineTo(maxX, y);\n context.stroke();\n context.restore();\n }\n\n drawMouseColumnHover(context, state) {\n const { theme, metrics, hoverSelectColumn } = state;\n if (hoverSelectColumn == null || !theme.linkerColumnHoverBackgroundColor) {\n return;\n }\n\n const { visibleColumnWidths, visibleColumnXs, maxY } = metrics;\n\n const x = visibleColumnXs.get(hoverSelectColumn);\n const columnWidth = visibleColumnWidths.get(hoverSelectColumn);\n\n context.fillStyle = theme.linkerColumnHoverBackgroundColor;\n context.fillRect(x, 0, columnWidth, maxY);\n }\n\n drawMouseRowHover(context, state) {\n const { isSelectingColumn } = state;\n if (!isSelectingColumn) {\n super.drawMouseRowHover(context, state);\n }\n }\n\n drawScrim(state) {\n const { context, loadingScrimProgress, metrics, theme } = state;\n if (loadingScrimProgress == null) {\n return;\n }\n\n const { width, height, gridY } = metrics;\n const { scrimBlurSize, scrimColor } = theme;\n\n context.save();\n\n // Use global composite so we can just change the underlying layer to grayscale\n context.globalCompositeOperation = 'color';\n context.filter = `blur(${scrimBlurSize}px)`;\n context.fillStyle = scrimColor;\n\n // Clip the path so the top edge is hard edge, bottom edge is soft/blurry\n context.beginPath();\n context.rect(0, gridY, width, height - gridY);\n context.clip();\n\n // Extend the edges beyond the clip area so they're hard edges\n context.fillRect(\n -scrimBlurSize,\n -scrimBlurSize + gridY,\n scrimBlurSize * 2 + width,\n (scrimBlurSize * 2 + (height - gridY)) * loadingScrimProgress\n );\n\n context.restore();\n }\n\n drawColumnHeaders(context, state) {\n super.drawColumnHeaders(context, state);\n\n const { theme, metrics, model, reverseType } = state;\n const { columnHeaderHeight } = metrics;\n\n this.drawFilterHeaders(context, state);\n\n if (columnHeaderHeight <= 0) {\n return;\n }\n\n const { sort } = model;\n // if there is only one sort bar, it is interior to the header to save space\n if (sort.length === 1) {\n const hasReverse = reverseType !== TableUtils.REVERSE_TYPE.NONE;\n this.drawHeaderBar(\n context,\n state,\n hasReverse ? theme.headerReverseBarColor : theme.headerSortBarColor,\n hasReverse ? theme.reverseHeaderBarHeight : theme.sortHeaderBarHeight\n );\n } else if (sort.length > 1) {\n // if there's multiple bars, the sort is interior to header\n // and the reverse claims space in the table\n if (\n // has table reverse\n reverseType !== TableUtils.REVERSE_TYPE.NONE\n ) {\n this.drawHeaderBar(\n context,\n state,\n theme.headerReverseBarColor,\n theme.reverseHeaderBarHeight,\n false\n );\n }\n this.drawHeaderBar(\n context,\n state,\n theme.headerSortBarColor,\n theme.sortHeaderBarHeight\n );\n }\n }\n\n drawHeaderBar(context, state, color, barHeight, interior = true) {\n const { theme, metrics } = state;\n const { columnHeaderHeight, width } = metrics;\n // Draw casing with 1 pixel above and below the bar,\n // 1px falls on the existing split between grid/headers\n // so don't need to be accounnted for in math elsewhere\n let offset = 0;\n if (!interior) {\n offset = barHeight;\n }\n context.fillStyle = theme.headerBarCasingColor;\n context.fillRect(\n 0,\n columnHeaderHeight - barHeight - 2 + offset,\n width,\n barHeight + 2\n );\n context.fillStyle = color;\n context.fillRect(\n 0,\n columnHeaderHeight - barHeight - 1 + offset,\n width,\n barHeight\n );\n }\n\n drawColumnHeader(context, state, column, columnX, columnWidth) {\n super.drawColumnHeader(context, state, column, columnX, columnWidth);\n\n const { metrics, model, theme } = state;\n const { modelColumns } = metrics;\n const modelColumn = modelColumns.get(column);\n const sort = TableUtils.getSortForColumn(model.sort, modelColumn);\n const icon = this.getSortIcon(sort);\n if (!icon) {\n return;\n }\n\n const { columnHeaderHeight, gridX } = metrics;\n\n const x = gridX + columnX + columnWidth - 13;\n const yOffset =\n sort.direction === TableUtils.sortDirection.ascending ? -6 : -12;\n const y = columnHeaderHeight * 0.5 + yOffset;\n const gradientWidth = 12;\n const gradientX = x - 3;\n\n context.save();\n\n context.beginPath();\n context.rect(columnX, 0, columnWidth, columnHeaderHeight);\n context.clip();\n\n const gradient = context.createLinearGradient(\n gradientX,\n 0,\n gradientX + 5,\n 0\n );\n gradient.addColorStop(0, `${theme.headerBackgroundColor}00`);\n gradient.addColorStop(1, `${theme.headerBackgroundColor}CD`);\n\n context.fillStyle = gradient;\n context.fillRect(gradientX, 0, gradientWidth, columnHeaderHeight);\n\n context.fillStyle = theme.headerSortBarColor;\n context.translate(x, y);\n context.scale(ICON_SCALE, ICON_SCALE);\n context.fill(icon);\n\n context.restore();\n }\n\n drawFilterHeaders(context, state) {\n const { isFilterBarShown, quickFilters, advancedFilters } = state;\n\n if (isFilterBarShown) {\n this.drawExpandedFilterHeaders(context, state);\n } else if (\n (quickFilters && quickFilters.size > 0) ||\n (advancedFilters && advancedFilters.size > 0)\n ) {\n this.drawCollapsedFilterHeaders(context, state);\n }\n }\n\n drawExpandedFilterHeaders(context, state) {\n const { metrics, model, theme, quickFilters, advancedFilters } = state;\n const { filterBarHeight } = theme;\n\n if (filterBarHeight <= 0) {\n return;\n }\n\n const {\n gridX,\n gridY,\n maxX,\n modelColumns,\n visibleColumns,\n visibleColumnWidths,\n visibleColumnXs,\n } = metrics;\n\n const columnHeaderHeight = gridY - filterBarHeight;\n\n context.save();\n\n context.font = theme.font;\n context.textAlign = 'left';\n\n if (\n (quickFilters && quickFilters.size > 0) ||\n (advancedFilters && advancedFilters.size > 0)\n ) {\n // fill style if a fiter is set on any column\n context.fillStyle = theme.filterBarExpandedActiveBackgroundColor;\n } else {\n // fill style with no filters set\n context.fillStyle = theme.filterBarExpandedBackgroundColor;\n }\n\n // Draw the background\n context.fillRect(gridX, columnHeaderHeight, maxX, filterBarHeight - 1);\n\n // Draw the bottom border\n context.fillStyle = theme.headerBarCasingColor;\n context.fillRect(gridX, columnHeaderHeight + filterBarHeight - 1, maxX, 1);\n\n // Draw the filter input boxes\n if (theme.filterBarSeparatorColor) {\n const y1 = columnHeaderHeight;\n context.strokeStyle = theme.filterBarSeparatorColor;\n context.beginPath();\n\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const modelColumn = modelColumns.get(column);\n const columnX = visibleColumnXs.get(column);\n const columnWidth = visibleColumnWidths.get(column);\n if (model.isFilterable(modelColumn) && columnWidth > 0) {\n const x1 = gridX + columnX;\n context.rect(x1 + 0.5, y1 + 0.5, columnWidth, filterBarHeight - 2); // 1 for the border, 1 for the casing\n }\n }\n context.stroke();\n }\n\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const columnWidth = visibleColumnWidths.get(column);\n const x = visibleColumnXs.get(column) + gridX;\n this.drawExpandedFilterHeader(context, state, column, x, columnWidth);\n }\n\n context.restore();\n }\n\n drawExpandedFilterHeader(context, state, column, columnX, columnWidth) {\n if (columnWidth <= 0) {\n return;\n }\n\n const { metrics, theme, quickFilters, advancedFilters } = state;\n const { modelColumns, gridY } = metrics;\n const {\n filterBarHeight,\n filterBarExpandedActiveCellBackgroundColor,\n filterBarErrorColor,\n filterBarHorizontalPadding,\n headerColor,\n } = theme;\n const columnHeaderHeight = gridY - filterBarHeight;\n const modelColumn = modelColumns.get(column);\n const quickFilter = quickFilters.get(modelColumn);\n const advancedFilter = advancedFilters.get(modelColumn);\n if (quickFilter == null && advancedFilter == null) {\n return;\n }\n\n let text = null;\n if (quickFilter != null) {\n const { text: filterText } = quickFilter;\n text = filterText;\n if (!text) {\n text = TableUtils.getFilterText(quickFilter.filter);\n }\n\n if (text) {\n const { fontWidths } = metrics;\n let fontWidth = fontWidths.get(context.font);\n if (!fontWidth) {\n fontWidth = context.measureText('8');\n if (!fontWidth) {\n fontWidth = 10;\n }\n }\n\n const maxLength =\n (columnWidth - filterBarHorizontalPadding * 2) / fontWidth;\n if (maxLength <= 0) {\n text = '';\n } else if (text.length > maxLength) {\n text = `${text.substring(0, maxLength - 1)}…`;\n }\n }\n }\n\n context.save();\n\n const isFilterValid = IrisGridRenderer.isFilterValid(\n advancedFilter,\n quickFilter\n );\n if (isFilterValid) {\n // draw active filter background inside cell\n context.fillStyle = filterBarExpandedActiveCellBackgroundColor;\n context.fillRect(\n columnX + 1, // +1 left border\n columnHeaderHeight + 1, // +1 top border\n columnWidth - 1, // -1 right border\n filterBarHeight - 3 // -3 top, bottom border and bottom casing\n );\n } else {\n // draw error box inside cell\n context.fillStyle = filterBarErrorColor;\n context.lineWidth = 2;\n context.strokeStyle = filterBarErrorColor;\n // Because this is drawn with a strokeRect, we have to add/subtract half the,\n // linewidth from each side to make interior, in addition to accounting for any borders/casings\n const rectLeft = columnX + 2; // 1 for strokeRect, 1 for border\n const rectTop = columnHeaderHeight + 2; // 1 for strokeRect, 1 for border\n const rectWidth = columnWidth - 3; // for 2 border and 1 for strokeRect\n const rectHeight = filterBarHeight - 5; // -2 for strokeRect, -3 for top, bottom border and bottom casing\n context.strokeRect(rectLeft, rectTop, rectWidth, rectHeight);\n }\n\n if (text) {\n const textX = columnX + filterBarHorizontalPadding;\n const textY = columnHeaderHeight + filterBarHeight * 0.5 + 1; // + 1 for border\n context.fillStyle = headerColor;\n context.fillText(text, textX, textY);\n }\n\n context.restore();\n }\n\n drawCollapsedFilterHeaders(context, state) {\n const { metrics, theme } = state;\n const { headerSeparatorColor, filterBarCollapsedHeight } = theme;\n\n if (filterBarCollapsedHeight <= 0) {\n return;\n }\n\n const {\n gridX,\n gridY,\n maxX,\n visibleColumns,\n visibleColumnWidths,\n visibleColumnXs,\n } = metrics;\n const columnHeaderHeight = gridY - filterBarCollapsedHeight;\n\n context.save();\n\n // Draw the background of the collapsed filter bar\n context.fillStyle = headerSeparatorColor;\n context.fillRect(gridX, columnHeaderHeight, maxX, filterBarCollapsedHeight);\n\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const column = visibleColumns[i];\n const columnWidth = visibleColumnWidths.get(column);\n const x = visibleColumnXs.get(column) + gridX;\n // draw the collapsed cells\n this.drawCollapsedFilterHeader(context, state, column, x, columnWidth);\n }\n\n context.restore();\n }\n\n drawCollapsedFilterHeader(context, state, column, columnX, columnWidth) {\n if (columnWidth <= 0) {\n return;\n }\n\n const { metrics, theme, quickFilters, advancedFilters } = state;\n const { modelColumns, gridY } = metrics;\n const modelColumn = modelColumns.get(column);\n\n const quickFilter = quickFilters.get(modelColumn);\n const advancedFilter = advancedFilters.get(modelColumn);\n\n const {\n filterBarCollapsedHeight,\n filterBarActiveColor,\n filterBarActiveBackgroundColor,\n filterBarErrorColor,\n } = theme;\n\n context.save();\n\n const isFilterValid = IrisGridRenderer.isFilterValid(\n advancedFilter,\n quickFilter\n );\n if (quickFilter == null && advancedFilter == null) {\n context.fillStyle = filterBarActiveBackgroundColor;\n } else if (isFilterValid) {\n context.fillStyle = filterBarActiveColor;\n } else {\n context.fillStyle = filterBarErrorColor;\n }\n\n const x = columnX + 1; // for gap between columns\n const y = gridY - filterBarCollapsedHeight;\n const rectWidth = columnWidth - 1; // for gap between columns\n const rectHeight = filterBarCollapsedHeight - 1; // for casing bottom\n context.fillRect(x, y, rectWidth, rectHeight);\n\n context.restore();\n }\n\n drawTreeMarker(context, state, columnX, rowY, treeBox, color, isExpanded) {\n context.save();\n const { x1, y1 } = treeBox;\n const markerIcon = isExpanded\n ? this.getIcon(ICON_NAMES.CARET_DOWN)\n : this.getIcon(ICON_NAMES.CARET_RIGHT);\n const iconX = columnX + x1 - 2;\n const iconY = rowY + y1 + 2.5;\n\n context.fillStyle = color;\n context.textAlign = 'center';\n context.translate(iconX, iconY);\n context.scale(ICON_SCALE, ICON_SCALE);\n context.fill(markerIcon);\n context.restore();\n }\n\n drawRowFooters(context, state) {\n const { metrics, model, mouseX, mouseY, theme } = state;\n const {\n gridY,\n gridX,\n maxX,\n modelRows,\n floatingTopHeight,\n floatingBottomHeight,\n floatingRows,\n rowFooterWidth,\n height,\n horizontalBarHeight,\n verticalBarWidth,\n visibleRowHeights,\n visibleRowYs,\n width,\n } = metrics;\n // Only draw the footers on the floating rows\n if (rowFooterWidth <= 0 || floatingRows.length === 0) {\n return;\n }\n\n const {\n cellHorizontalPadding,\n floatingGridRowColor,\n floatingRowBackgroundColors,\n headerColor,\n rowHoverBackgroundColor,\n } = theme;\n\n context.translate(gridX, gridY);\n\n context.beginPath();\n const x = Math.min(maxX, width - rowFooterWidth - verticalBarWidth - gridX);\n context.fillStyle = floatingRowBackgroundColors;\n if (floatingTopHeight > 0) {\n context.rect(x, 0, rowFooterWidth, floatingTopHeight);\n }\n if (floatingBottomHeight > 0) {\n context.rect(\n x,\n height - gridY - horizontalBarHeight - floatingBottomHeight,\n rowFooterWidth,\n floatingBottomHeight\n );\n }\n context.fill();\n\n const mouseRow =\n mouseX >= gridX && mouseX <= maxX + rowFooterWidth\n ? GridUtils.getRowAtY(mouseY, metrics)\n : null;\n if (mouseRow !== null && floatingRows.includes(mouseRow)) {\n context.fillStyle = rowHoverBackgroundColor;\n const y = visibleRowYs.get(mouseRow);\n const rowHeight = visibleRowHeights.get(mouseRow);\n context.fillRect(x, y, rowFooterWidth, rowHeight);\n }\n\n context.beginPath();\n context.strokeStyle = floatingGridRowColor;\n if (floatingTopHeight > 0) {\n context.moveTo(x + 0.5, 0.5);\n context.lineTo(x + 0.5, floatingTopHeight - 0.5);\n }\n if (floatingBottomHeight > 0) {\n const y = height - gridY - horizontalBarHeight - floatingBottomHeight;\n context.moveTo(x - 0.5, y + 0.5);\n context.lineTo(x - 0.5, y + floatingBottomHeight - 0.5);\n }\n context.stroke();\n\n context.fillStyle = headerColor;\n context.textAlign = 'left';\n\n const textX = x + cellHorizontalPadding;\n for (let i = 0; i < floatingRows.length; i += 1) {\n const row = floatingRows[i];\n const rowHeight = visibleRowHeights.get(row);\n const rowY = visibleRowYs.get(row);\n const modelRow = modelRows.get(row);\n const textY = rowY + rowHeight * 0.5;\n context.fillText(model.textForRowFooter(modelRow), textX, textY);\n }\n\n context.translate(-gridX, -gridY);\n }\n}\n\nexport default IrisGridRenderer;\n","import type { GridThemeType } from '@deephaven/grid';\nimport IrisGridTheme from './IrisGridTheme.module.scss';\n\nexport type IrisGridThemeType = Partial<GridThemeType> & {\n filterBarHeight: number;\n filterBarCollapsedHeight: number;\n reverseHeaderBarHeight: number;\n};\n\nconst theme: IrisGridThemeType = Object.freeze({\n backgroundColor: IrisGridTheme['grid-bg'],\n font: IrisGridTheme.font,\n headerBackgroundColor: IrisGridTheme['header-bg'],\n headerColor: IrisGridTheme['header-color'],\n headerSeparatorColor: IrisGridTheme['header-separator-color'],\n headerSeparatorHoverColor: IrisGridTheme['header-separator-hover-color'],\n headerHiddenSeparatorHoverColor:\n IrisGridTheme['header-hidden-separator-hover-color'],\n headerSortBarColor: IrisGridTheme['header-sort-bar-color'],\n headerReverseBarColor: IrisGridTheme['header-reverse-bar-color'],\n headerBarCasingColor: IrisGridTheme['header-bar-casing-color'],\n headerFont: IrisGridTheme['header-font'],\n rowBackgroundColors: IrisGridTheme['row-background-colors'],\n rowHoverBackgroundColor: IrisGridTheme['row-hover-bg'],\n selectionColor: IrisGridTheme['selection-color'],\n selectionOutlineColor: IrisGridTheme['selection-outline-color'],\n selectionOutlineCasingColor: IrisGridTheme['selection-outline-casing-color'],\n selectedRowHoverBackgroundColor: IrisGridTheme['selected-row-hover-bg'],\n scrollBarBackgroundColor: IrisGridTheme['scroll-bar-bg'],\n scrollBarHoverBackgroundColor: IrisGridTheme['scroll-bar-hover-bg'],\n scrollBarCasingColor: IrisGridTheme['scroll-bar-casing-color'],\n scrollBarCornerColor: IrisGridTheme['scroll-bar-corner-color'],\n scrollBarColor: IrisGridTheme['scroll-bar-color'],\n scrollBarHoverColor: IrisGridTheme['scroll-bar-hover-color'],\n scrollBarActiveColor: IrisGridTheme['scroll-bar-active-color'],\n textColor: IrisGridTheme['text-color'],\n positiveNumberColor: IrisGridTheme['positive-number-color'],\n negativeNumberColor: IrisGridTheme['negative-number-color'],\n zeroNumberColor: IrisGridTheme['zero-number-color'],\n dateColor: IrisGridTheme['date-color'],\n pendingTextColor: IrisGridTheme['pending-text-color'],\n errorTextColor: IrisGridTheme['error-text-color'],\n nullStringColor: IrisGridTheme['null-string-color'],\n filterBarActiveBackgroundColor: IrisGridTheme['filter-bar-active-bg'],\n filterBarExpandedBackgroundColor: IrisGridTheme['filter-bar-expanded-bg'],\n filterBarExpandedActiveBackgroundColor:\n IrisGridTheme['filter-bar-expanded-active-bg'],\n filterBarExpandedActiveCellBackgroundColor:\n IrisGridTheme['filter-bar-expanded-active-cell-bg'],\n filterBarSeparatorColor: IrisGridTheme['filter-bar-separator-color'],\n filterBarActiveColor: IrisGridTheme['filter-bar-active-color'],\n filterBarErrorColor: IrisGridTheme['filter-bar-error-color'],\n filterIconColor: IrisGridTheme['filter-icon-color'],\n scrimColor: IrisGridTheme['scrim-color'],\n contextMenuSortIconColor: IrisGridTheme['context-menu-sort-icon-color'],\n contextMenuReverseIconColor: IrisGridTheme['context-menu-reverse-icon-color'],\n\n allowRowResize: false,\n autoSelectRow: true,\n gridColumnColor: null,\n gridRowColor: null,\n groupedColumnDividerColor: IrisGridTheme['grouped-column-divider-color'],\n columnHoverBackgroundColor: null,\n headerHorizontalPadding: 12,\n scrollBarSize: 13,\n scrollBarHoverSize: 16, // system default scrollbar width is 17\n minScrollHandleSize: 24,\n rowHeight: 19,\n columnWidth: 100,\n rowHeaderWidth: 0,\n rowFooterWidth: 60,\n columnHeaderHeight: 30,\n filterBarHeight: 30, // includes 1px casing at bottom\n filterBarCollapsedHeight: 5, // includes 1px casing at bottom\n sortHeaderBarHeight: 2,\n reverseHeaderBarHeight: 4,\n filterBarHorizontalPadding: 4,\n\n // Amount of blur to apply to the bottom of the scrim while animating in\n scrimBlurSize: 25,\n minScrimTransitionTime: 150,\n maxScrimTransitionTime: 350,\n\n scrollSnapToRow: true,\n\n linkerColumnHoverBackgroundColor: IrisGridTheme['linker-column-hover-bg'],\n\n treeLineColor: IrisGridTheme['tree-line-color'],\n treeMarkerColor: IrisGridTheme['tree-marker-color'],\n treeMarkerHoverColor: IrisGridTheme['tree-marker-hover-color'],\n\n floatingGridColumnColor: null,\n floatingGridRowColor: IrisGridTheme['floating-grid-row-color'],\n floatingRowBackgroundColors: IrisGridTheme['floating-row-background-colors'],\n floatingDividerInnerColor: IrisGridTheme['floating-divider-inner-color'],\n floatingDividerOuterColor: IrisGridTheme['floating-divider-outer-color'],\n});\n\nexport default theme;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n Button,\n ContextActionUtils,\n LoadingSpinner,\n} from '@deephaven/components';\nimport {\n dhFreeze,\n dhRefresh,\n vsCopy,\n vsLock,\n vsPassFilled,\n} from '@deephaven/icons';\nimport { PropTypes as APIPropTypes } from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport { PromiseUtils } from '@deephaven/utils';\nimport IrisGridModel from './IrisGridModel';\nimport './ColumnStatistics.scss';\n\nconst log = Log.module('ColumnStatistics');\nconst STATS_LABEL_OVERRIDES = {\n SIZE: 'Number of Rows',\n};\n\nclass ColumnStatistics extends Component {\n /** Automatically generate the statistics when the row count is below this threshold */\n static AUTO_GENERATE_LIMIT = 100000;\n\n static getStatsLabel(operation) {\n return (\n STATS_LABEL_OVERRIDES[operation] ??\n operation\n .split(' ')\n .map(w => w[0].toUpperCase() + w.substr(1).toLowerCase())\n .join(' ')\n );\n }\n\n constructor(props) {\n super(props);\n\n this.handleError = this.handleError.bind(this);\n this.handleGenerateStatistics = this.handleGenerateStatistics.bind(this);\n this.handleStatistics = this.handleStatistics.bind(this);\n this.handleCopyHeader = this.handleCopyHeader.bind(this);\n\n this.cancelablePromise = null;\n\n this.state = {\n error: null,\n loading: false,\n statistics: null,\n numRows: 0,\n copied: false,\n };\n }\n\n componentDidMount() {\n this.maybeGenerateStatistics();\n }\n\n componentWillUnmount() {\n if (this.cancelablePromise) {\n this.cancelablePromise.cancel();\n }\n }\n\n handleCopyHeader() {\n this.setState({ copied: true });\n }\n\n maybeGenerateStatistics() {\n const { model } = this.props;\n\n const numRows = model.rowCount;\n this.setState({ numRows });\n if (!model.isColumnStatisticsAvailable) {\n this.setState({ loading: false });\n } else if (numRows < ColumnStatistics.AUTO_GENERATE_LIMIT) {\n this.handleGenerateStatistics();\n }\n }\n\n handleGenerateStatistics() {\n this.setState({ loading: true });\n\n const { column, model } = this.props;\n\n this.cancelablePromise = PromiseUtils.makeCancelable(\n model.columnStatistics(column)\n );\n\n this.cancelablePromise.then(this.handleStatistics).catch(this.handleError);\n }\n\n handleStatistics(stats) {\n log.debug('Received statistics', stats);\n\n const { model, onStatistics } = this.props;\n const statistics = [];\n\n stats.statisticsMap.forEach((value, operation) => {\n statistics.push({\n operation: ColumnStatistics.getStatsLabel(operation),\n value,\n type: stats.getType(operation),\n });\n });\n\n stats.uniqueValues.forEach((value, operation) => {\n statistics.push({\n operation,\n className: 'column-statistics-unique-value',\n value,\n type: 'long',\n });\n });\n\n this.setState({\n loading: false,\n statistics,\n numRows: model.rowCount,\n });\n\n onStatistics();\n }\n\n handleError(error) {\n if (error && error.isCanceled) {\n log.debug('Called handleError on a cancelled promise result');\n return;\n }\n\n log.error('Error generating statistics', error);\n this.setState({\n error,\n loading: false,\n statistics: null,\n });\n }\n\n render() {\n const { column, model } = this.props;\n const { error, loading, statistics, numRows, copied } = this.state;\n const showGenerateStatistics =\n !loading &&\n error == null &&\n statistics == null &&\n model.isColumnStatisticsAvailable;\n const statisticElements = [];\n const columnType = column.type.substring(column.type.lastIndexOf('.') + 1);\n const description = column.description === null ? null : column.description;\n if (statistics != null) {\n for (let i = 0; i < statistics.length; i += 1) {\n const { operation, className, value, type } = statistics[i];\n const formattedValue = !type\n ? model.displayString(value, column.type, column.name)\n : model.displayString(value, type);\n const statisticElement = (\n <React.Fragment key={operation}>\n <div\n className={classNames('column-statistic-operation', className)}\n >\n {operation}\n </div>\n <div className=\"column-statistic-value\">{formattedValue}</div>\n </React.Fragment>\n );\n statisticElements.push(statisticElement);\n }\n }\n const rowCountLabel = model.hasExpandableRows\n ? 'Expanded Rows'\n : 'Number of Rows';\n const formattedRowCount = model.displayString(numRows, 'long');\n const columnIndex = model.getColumnIndexByName(column.name);\n return (\n <div className=\"column-statistics\">\n <div className=\"column-statistics-title\">\n {column.name}\n <span className=\"column-statistics-type\">&nbsp;({columnType})</span>\n <Button\n kind=\"ghost\"\n className=\"column-statistics-copy\"\n icon={copied ? vsPassFilled : vsCopy}\n onClick={() => {\n ContextActionUtils.copyToClipboard(column.name)\n .then(this.handleCopyHeader)\n .catch(e => log.error('Unable to column name', e));\n }}\n tooltip={copied ? 'Copied text' : 'Copy column name'}\n />\n </div>\n {description && (\n <div className=\"column-statistics-description\">{description}</div>\n )}\n {!model.isColumnMovable(columnIndex) && (\n <div className=\"column-statistics-status\">\n <FontAwesomeIcon\n icon={model.isColumnFrozen(columnIndex) ? dhFreeze : vsLock}\n className=\"mr-1\"\n />\n {model.isColumnFrozen(columnIndex) ? 'Frozen' : 'Not movable'}\n </div>\n )}\n <div className=\"column-statistics-grid\">\n {statistics == null && (\n <>\n <div className=\"column-statistic-operation\">{rowCountLabel}</div>\n <div className=\"column-statistic-value\">{formattedRowCount}</div>\n </>\n )}\n\n {statisticElements}\n </div>\n {showGenerateStatistics && (\n <button\n type=\"button\"\n className=\"btn btn-link px-0\"\n onClick={this.handleGenerateStatistics}\n >\n Generate Stats\n </button>\n )}\n {error && <div className=\"error-message\">{`${error}`}</div>}\n {statistics && !loading && (\n <button\n type=\"button\"\n className=\"btn btn-link px-0\"\n onClick={this.handleGenerateStatistics}\n >\n <FontAwesomeIcon icon={dhRefresh} className=\"mr-1\" />\n Refresh\n </button>\n )}\n {loading && (\n <div className=\"column-statistics-loading\">\n <LoadingSpinner className=\"mr-2\" />\n Calculating Stats...\n </div>\n )}\n </div>\n );\n }\n}\n\nColumnStatistics.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n column: APIPropTypes.Column.isRequired,\n onStatistics: PropTypes.func.isRequired,\n};\n\nexport default ColumnStatistics;\n","import type { FormattingRule } from './Formatter';\nimport { DateTimeColumnFormatter } from './formatters';\n\nclass FormatterUtils {\n static getColumnFormats(settings: {\n formatter: FormattingRule[];\n }): FormattingRule[] {\n const { formatter } = settings;\n return formatter;\n }\n\n static getDateTimeFormatterOptions(settings: {\n timeZone: string;\n defaultDateTimeFormat: string;\n showTimeZone: boolean;\n showTSeparator: boolean;\n }): Required<ConstructorParameters<typeof DateTimeColumnFormatter>[0]> {\n const {\n timeZone,\n defaultDateTimeFormat,\n showTimeZone,\n showTSeparator,\n } = settings;\n return {\n timeZone,\n defaultDateTimeFormatString: defaultDateTimeFormat,\n showTimeZone,\n showTSeparator,\n };\n }\n}\n\nexport default FormatterUtils;\n","/* eslint react/no-did-update-set-state: \"off\" */\nimport React, { PureComponent } from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { Tooltip } from '@deephaven/components';\nimport { vsTrash } from '@deephaven/icons';\nimport Log from '@deephaven/log';\nimport TableUtils from './TableUtils';\nimport { FilterType, FilterTypeValue } from './filters';\n\nconst log = Log.module('AdvancedFilterCreatorFilterItem');\n\ninterface AdvancedFilterCreatorFilterItemProps {\n column: { type: string };\n filterTypes: FilterTypeValue[];\n onChange(type: FilterTypeValue, value: string): void;\n onDelete(): void;\n selectedType?: FilterTypeValue;\n value?: string;\n}\n\nexport interface AdvancedFilterCreatorFilterItemState {\n selectedType: FilterTypeValue;\n value: string;\n}\n\nclass AdvancedFilterCreatorFilterItem extends PureComponent<\n AdvancedFilterCreatorFilterItemProps,\n AdvancedFilterCreatorFilterItemState\n> {\n static getLabelForTextFilter(filterType: FilterTypeValue): string {\n switch (filterType) {\n case FilterType.eq:\n return 'is exactly';\n case FilterType.eqIgnoreCase:\n return 'is exactly (ignore case)';\n case FilterType.notEq:\n return 'is not exactly';\n case FilterType.notEqIgnoreCase:\n return 'is not exactly (ignore case)';\n case FilterType.contains:\n return 'contains';\n case FilterType.notContains:\n return 'does not contain';\n case FilterType.startsWith:\n return 'starts with';\n case FilterType.endsWith:\n return 'ends with';\n default:\n log.warn('Unrecognized text filter type', filterType);\n return '';\n }\n }\n\n static getLabelForNumberFilter(filterType: FilterTypeValue): string {\n switch (filterType) {\n case FilterType.eq:\n return 'is equal to';\n case FilterType.notEq:\n return 'is not equal to';\n case FilterType.greaterThan:\n return 'greater than';\n case FilterType.greaterThanOrEqualTo:\n return 'greater than or equal to';\n case FilterType.lessThan:\n return 'less than';\n case FilterType.lessThanOrEqualTo:\n return 'less than or equal to';\n default:\n log.warn('Unrecognized number filter type', filterType);\n return '';\n }\n }\n\n static getLabelForDateFilter(filterType: FilterTypeValue): string {\n switch (filterType) {\n case FilterType.eq:\n return 'date is';\n case FilterType.notEq:\n return 'date is not';\n case FilterType.notEqIgnoreCase:\n case FilterType.greaterThan:\n return 'date is after';\n case FilterType.greaterThanOrEqualTo:\n return 'date is after or equal';\n case FilterType.lessThan:\n return 'date is before';\n case FilterType.lessThanOrEqualTo:\n return 'date is before or equal';\n default:\n log.warn('Unrecognized date filter type', filterType);\n return '';\n }\n }\n\n static getLabelForBooleanFilter(filterType: FilterTypeValue): string {\n switch (filterType) {\n case FilterType.isTrue:\n return 'Is True';\n case FilterType.isFalse:\n return 'Is False';\n case FilterType.isNull:\n return 'Is Null';\n default:\n log.warn('Unrecognized boolean filter type', filterType);\n return '';\n }\n }\n\n static getLabelForFilter(\n columnType: string,\n filterType: FilterTypeValue\n ): string {\n if (\n TableUtils.isNumberType(columnType) ||\n TableUtils.isCharType(columnType)\n ) {\n return AdvancedFilterCreatorFilterItem.getLabelForNumberFilter(\n filterType\n );\n }\n if (TableUtils.isTextType(columnType)) {\n return AdvancedFilterCreatorFilterItem.getLabelForTextFilter(filterType);\n }\n if (TableUtils.isDateType(columnType)) {\n return AdvancedFilterCreatorFilterItem.getLabelForDateFilter(filterType);\n }\n if (TableUtils.isBooleanType(columnType)) {\n return AdvancedFilterCreatorFilterItem.getLabelForBooleanFilter(\n filterType\n );\n }\n log.warn('Unrecognized column type: ', columnType);\n return '';\n }\n\n constructor(props: AdvancedFilterCreatorFilterItemProps) {\n super(props);\n\n this.handleDelete = this.handleDelete.bind(this);\n this.handleTypeChange = this.handleTypeChange.bind(this);\n this.handleValueChange = this.handleValueChange.bind(this);\n this.typeDropdown = null;\n\n const { value = '', filterTypes, selectedType = filterTypes[0] } = props;\n\n this.state = {\n selectedType,\n value,\n };\n }\n\n componentDidMount(): void {\n this.typeDropdown?.focus();\n }\n\n componentDidUpdate(prevProps: AdvancedFilterCreatorFilterItemProps): void {\n const {\n value = '',\n filterTypes,\n selectedType = filterTypes[0],\n } = this.props;\n if (prevProps.selectedType !== selectedType || prevProps.value !== value) {\n this.setState({ selectedType, value });\n }\n }\n\n typeDropdown: HTMLSelectElement | null;\n\n handleTypeChange(event: React.ChangeEvent<HTMLSelectElement>): void {\n log.debug2('typeChange');\n const selectedType = event.target.value as FilterTypeValue;\n this.setState({ selectedType });\n\n const { onChange } = this.props;\n const { value } = this.state;\n if (value != null && value.length > 0) {\n // Don't send an update unless there's already a value entered\n onChange(selectedType, value);\n }\n }\n\n handleValueChange(event: React.ChangeEvent<HTMLInputElement>): void {\n log.debug2('valueChange');\n const { value } = event.target;\n this.setState({ value });\n\n const { onChange } = this.props;\n const { selectedType } = this.state;\n if (selectedType != null) {\n // Don't send an update unless they've already selected a type\n onChange(selectedType, value);\n }\n }\n\n handleDelete(): void {\n log.debug('delete');\n\n const { onDelete } = this.props;\n onDelete();\n }\n\n render(): JSX.Element {\n const { column, filterTypes } = this.props;\n const { selectedType, value } = this.state;\n const showValueInput = !TableUtils.isBooleanType(column.type);\n const typeOptionElements = [];\n for (let i = 0; i < filterTypes.length; i += 1) {\n const type = filterTypes[i];\n const label = AdvancedFilterCreatorFilterItem.getLabelForFilter(\n column.type,\n type\n );\n const element = (\n <option key={type} value={type}>\n {label}\n </option>\n );\n typeOptionElements.push(element);\n }\n\n return (\n <div className=\"advanced-filter-creator-filter-item\">\n <div className=\"form-row\">\n <div className=\"form-group col\">\n <select\n className=\"form-control custom-select\"\n value={selectedType}\n onChange={this.handleTypeChange}\n ref={typeDropdown => {\n this.typeDropdown = typeDropdown;\n }}\n >\n {typeOptionElements}\n </select>\n </div>\n {showValueInput && (\n <div className=\"form-group col\">\n <div className=\"input-group\">\n <input\n type=\"text\"\n className=\"form-control\"\n placeholder=\"Enter value\"\n value={value}\n onChange={this.handleValueChange}\n />\n </div>\n </div>\n )}\n <div className=\"form-group col-1 px-0\">\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon w-100 h-100 p-0 m-0\"\n onClick={this.handleDelete}\n >\n <FontAwesomeIcon icon={vsTrash} />\n <Tooltip>Remove Filter</Tooltip>\n </button>\n </div>\n </div>\n </div>\n );\n }\n}\n\nexport default AdvancedFilterCreatorFilterItem;\n","import React, { useState, useEffect, useCallback } from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport shortid from 'shortid';\nimport { useForwardedRef } from '@deephaven/react-hooks';\n\ninterface CheckboxProps {\n checked: boolean | null;\n className?: string;\n disabled?: boolean;\n inputClassName?: string;\n isInvalid?: boolean;\n labelClassName?: string;\n onChange?: React.ChangeEventHandler<HTMLInputElement>;\n children?: React.ReactNode;\n}\n\n/**\n * A simple checkbox component. Automatically generates an id so htmlFor/id attributes are unique.\n */\nconst Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n (props, forwardedRef) => {\n const {\n checked = false,\n children,\n className,\n disabled,\n inputClassName,\n isInvalid,\n labelClassName,\n onChange,\n } = props;\n\n const [id] = useState(shortid());\n\n const ref = useForwardedRef<HTMLInputElement>(forwardedRef);\n\n useEffect(() => {\n if (ref.current) {\n // indeterminate is not actually an html attr, can only be set via JS\n ref.current.indeterminate = checked === null;\n }\n }, [ref, checked]);\n\n const handleOnChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(\n event => {\n if (ref.current) {\n // ref.current can be null in tests, doesn't impact behaviour\n ref.current.indeterminate = checked === null;\n }\n\n if (onChange) {\n onChange(event);\n }\n },\n [ref, checked, onChange]\n );\n\n return (\n <div className={classNames('custom-control custom-checkbox', className)}>\n <input\n type=\"checkbox\"\n ref={ref}\n checked={checked ?? false} // checked attr must always have a value to remain as a controlled component\n className={classNames('custom-control-input', inputClassName, {\n 'is-invalid': isInvalid,\n })}\n disabled={disabled}\n id={id}\n onChange={handleOnChange}\n />\n <label\n className={classNames('custom-control-label', labelClassName)}\n htmlFor={id}\n >\n {children}\n </label>\n </div>\n );\n }\n);\n\n// Forward ref causes a false positive for display-name in eslint:\n// https://github.com/yannickcr/eslint-plugin-react/issues/2269\nCheckbox.displayName = 'Checkbox';\n\nCheckbox.propTypes = {\n /** Current value of the checkbox. */\n checked: (props, propName) => {\n const { [propName]: checkedType } = props;\n if (checkedType !== null && typeof checkedType !== 'boolean') {\n return new Error('Checked must be a boolean or null for indeterminate');\n }\n return null;\n },\n\n /** The node/text to put in the label of this checkbox */\n children: PropTypes.node.isRequired,\n\n /** An extra class name to add to the outer div component */\n className: PropTypes.string,\n\n /** An extra class for disabling the checkbox component */\n disabled: PropTypes.bool,\n\n /** An extra class name for the input component */\n inputClassName: PropTypes.string,\n\n /** Convenience for styling appropriately for an invalid value */\n isInvalid: PropTypes.bool,\n\n /** An extra class name for the label component */\n labelClassName: PropTypes.string,\n\n /** Triggered when the input is checked/unchecked */\n onChange: PropTypes.func,\n};\n\nCheckbox.defaultProps = {\n checked: false,\n className: '',\n disabled: false,\n inputClassName: '',\n isInvalid: false,\n labelClassName: '',\n onChange: undefined,\n};\n\nexport default Checkbox;\n","import React, { useEffect, useRef } from 'react';\n\n/**\n * Takes a ref from forwardRef and makes it safe to use.\n * Sometimes the ref may be undefined, but we want to use the ref internally for something like input focus\n *\n * @param ref The forwarded ref to use\n * @returns A React ref that is safe to use inside forwardRef\n */\nexport default function useForwardedRef<T>(\n ref: ((instance: T | null) => void) | React.MutableRefObject<T | null> | null\n): React.MutableRefObject<T | null> {\n const innerRef = useRef<T | null>(null);\n useEffect(() => {\n if (!ref) return;\n if (typeof ref === 'function') {\n ref(innerRef.current);\n } else {\n // eslint-disable-next-line no-param-reassign\n ref.current = innerRef.current;\n }\n });\n\n return innerRef;\n}\n","import React, { PureComponent } from 'react';\nimport './SelectValueList.scss';\nimport memoize from 'memoizee';\nimport Checkbox from './Checkbox';\n\ninterface SelectItem<T> {\n value: T;\n displayValue?: string;\n isSelected: boolean;\n}\n\ntype SelectValueListProps<T> = {\n disabled: boolean;\n // Total item count\n itemCount: number;\n rowHeight: number;\n\n // Offset of the top item in the items array\n offset: number;\n items: SelectItem<T>[];\n\n onSelect(itemIndex: number, value: T | null): void;\n onViewportChange(topRow: number, bottomRow: number): void;\n};\n\n/**\n * Select values from a long scrollable list.\n * Swaps items in and out for infinite scrolling\n */\nclass SelectValueList<T> extends PureComponent<SelectValueListProps<T>> {\n static defaultProps = {\n disabled: false,\n rowHeight: 21,\n };\n\n constructor(props: SelectValueListProps<T>) {\n super(props);\n\n this.handleScroll = this.handleScroll.bind(this);\n this.handleSelect = this.handleSelect.bind(this);\n\n this.list = React.createRef();\n this.topRow = null;\n this.bottomRow = null;\n }\n\n componentDidMount(): void {\n this.sendViewportUpdate();\n }\n\n componentDidUpdate(): void {\n this.sendViewportUpdate();\n }\n\n list: React.RefObject<HTMLDivElement>;\n\n topRow: number | null;\n\n bottomRow: number | null;\n\n getCachedItem = memoize(\n (\n itemIndex: number,\n key: number,\n value: T,\n displayValue: string | undefined,\n rowHeight: number,\n isSelected: boolean,\n disabled: boolean\n ): JSX.Element => {\n const style = {\n height: rowHeight,\n };\n const text = displayValue != null ? displayValue : value;\n\n return (\n <li className=\"value-list-item\" style={style} key={key}>\n <Checkbox\n checked={isSelected}\n disabled={disabled}\n onChange={() => this.handleSelect(itemIndex)}\n >\n {text}\n </Checkbox>\n </li>\n );\n },\n { max: 1000 }\n );\n\n getCachedItems = memoize(\n (\n items: SelectItem<T>[],\n rowHeight: number,\n offset: number,\n disabled: boolean\n ): React.ReactNode => {\n const itemElements: JSX.Element[] = [];\n for (let i = 0; i < items.length; i += 1) {\n const item = items[i];\n const { value, displayValue, isSelected } = item;\n const itemIndex = offset + i;\n const key = itemIndex;\n const element = this.getCachedItem(\n itemIndex,\n key,\n value,\n displayValue,\n rowHeight,\n isSelected,\n disabled\n );\n itemElements.push(element);\n }\n return itemElements;\n },\n { max: 1 }\n );\n\n handleScroll(): void {\n this.sendViewportUpdate();\n }\n\n handleSelect(itemIndex: number): void {\n const { items, offset, onSelect } = this.props;\n const visibleItemIndex = itemIndex - offset;\n if (visibleItemIndex >= 0 && visibleItemIndex < items.length) {\n const item = items[visibleItemIndex];\n const { value } = item;\n onSelect(itemIndex, value);\n } else {\n onSelect(itemIndex, null);\n }\n }\n\n sendViewportUpdate(): void {\n if (!this.list.current || this.list.current.clientHeight === 0) {\n return;\n }\n\n const { onViewportChange, rowHeight } = this.props;\n const top = this.list.current.scrollTop;\n const bottom = top + this.list.current.clientHeight;\n\n const topRow = Math.floor(top / rowHeight);\n const bottomRow = Math.ceil(bottom / rowHeight);\n\n if (this.topRow !== topRow || this.bottomRow !== bottomRow) {\n this.topRow = topRow;\n this.bottomRow = bottomRow;\n onViewportChange(topRow, bottomRow);\n }\n }\n\n render(): JSX.Element {\n const { disabled, items, itemCount, offset, rowHeight } = this.props;\n const itemElements = this.getCachedItems(\n items,\n rowHeight,\n offset,\n disabled\n );\n\n return (\n <div\n className=\"select-value-list-scroll-pane h-100 w-100\"\n onScroll={this.handleScroll}\n ref={this.list}\n >\n <div\n className=\"select-value-list\"\n style={{ height: itemCount * rowHeight }}\n >\n <ol\n className=\"select-value-list-content\"\n style={{\n position: 'absolute',\n height: items.length * rowHeight,\n top: offset * rowHeight,\n left: 0,\n }}\n >\n {itemElements}\n </ol>\n </div>\n </div>\n );\n }\n}\n\nexport default SelectValueList;\n","/* eslint react/no-did-update-set-state: \"off\" */\nimport React, { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport { CSSTransition } from 'react-transition-group';\nimport dh, { PropTypes as APIPropTypes } from '@deephaven/jsapi-shim';\nimport { LoadingSpinner, SelectValueList } from '@deephaven/components';\nimport Log from '@deephaven/log';\nimport Formatter from './Formatter';\n\nconst log = Log.module('AdvancedFilterCreatorSelectValueList');\n\n/**\n * Select values from a long scrollable list.\n * Swaps items in and out for infinite scrolling\n */\nclass AdvancedFilterCreatorSelectValueList extends PureComponent {\n /**\n * Get the index of a value in an array. Has some special handling for some types, like DateTimes and Longs.\n * @param {Any} value The value to search for\n * @param {Array} values The array of values to search within\n */\n static indexOf(value, values) {\n for (let i = 0; i < values.length; i += 1) {\n const v = values[i];\n if (\n v === value ||\n (v != null &&\n v.valueOf &&\n value != null &&\n value.valueOf &&\n v.valueOf() === value.valueOf())\n ) {\n return i;\n }\n }\n\n return -1;\n }\n\n constructor(props) {\n super(props);\n\n this.handleSelect = this.handleSelect.bind(this);\n this.handleViewportChange = this.handleViewportChange.bind(this);\n this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);\n this.handleTableUpdate = this.handleTableUpdate.bind(this);\n\n this.list = null;\n\n const { selectedValues } = this.props;\n\n this.state = {\n itemCount: 0,\n items: [],\n offset: 0,\n selectedValues,\n isLoading: true,\n };\n }\n\n componentDidMount() {\n const { table } = this.props;\n this.startListening(table);\n }\n\n componentDidUpdate(prevProps) {\n const { filters, invertSelection, selectedValues, table } = this.props;\n if (prevProps.table !== table) {\n this.stopListening(prevProps.table);\n this.startListening(table);\n this.resetViewport();\n }\n\n if (prevProps.invertSelection !== invertSelection) {\n this.setState({ selectedValues: [] }, this.handleSelectionUpdate);\n }\n\n if (prevProps.selectedValues !== selectedValues) {\n this.setState({ selectedValues }, this.handleSelectionUpdate);\n }\n\n if (prevProps.filters !== filters) {\n table.applyFilter(filters);\n this.resetViewport();\n }\n }\n\n componentWillUnmount() {\n this.stopListening();\n }\n\n handleSelect(itemIndex, value) {\n const { invertSelection } = this.props;\n let { selectedValues } = this.state;\n selectedValues = [].concat(selectedValues);\n const selectedIndex = AdvancedFilterCreatorSelectValueList.indexOf(\n value,\n selectedValues\n );\n if (selectedIndex >= 0) {\n selectedValues.splice(selectedIndex, 1);\n } else {\n selectedValues.push(value);\n }\n\n let isSelected = selectedIndex < 0;\n if (invertSelection) {\n isSelected = !isSelected;\n }\n\n const { offset } = this.state;\n let { items } = this.state;\n items = [].concat(items);\n const visibleItemIndex = itemIndex - offset;\n if (visibleItemIndex >= 0 && visibleItemIndex < items.length) {\n items[visibleItemIndex].isSelected = isSelected;\n }\n\n this.setState({ items, selectedValues });\n\n const { onChange } = this.props;\n onChange(selectedValues, invertSelection);\n }\n\n handleViewportChange(top, bottom) {\n this.updateViewport(top, bottom);\n }\n\n handleSelectionUpdate() {\n this.updateItemSelection();\n }\n\n handleTableUpdate(event) {\n const data = event.detail;\n const { offset } = data;\n\n const items = [];\n const { table, formatter } = this.props;\n const column = table.columns[0];\n for (let r = 0; r < data.rows.length; r += 1) {\n const row = data.rows[r];\n const value = row.get(column);\n const displayValue = formatter.getFormattedString(\n value,\n column.type,\n column.name\n );\n const isSelected = this.isValueSelected(value);\n items.push({\n displayValue,\n value,\n isSelected,\n });\n }\n\n log.debug2('Received table update:', offset, items.length);\n\n const itemCount = table.size;\n this.setState({ itemCount, items, offset, isLoading: false });\n }\n\n isValueSelected(value) {\n const { invertSelection } = this.props;\n const { selectedValues } = this.state;\n\n // Need to check if any of the valueOf matches, timestamp value that is equal\n const selectedIndex = AdvancedFilterCreatorSelectValueList.indexOf(\n value,\n selectedValues\n );\n\n return invertSelection ? selectedIndex < 0 : selectedIndex >= 0;\n }\n\n startListening(table) {\n if (table != null) {\n table.addEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);\n }\n }\n\n stopListening(table) {\n if (table != null) {\n table.removeEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);\n }\n }\n\n resetViewport() {\n if (this.list) {\n this.updateViewport(this.list.topRow, this.list.bottomRow, true);\n }\n }\n\n updateItemSelection() {\n let { items } = this.state;\n\n items = [].concat(items);\n\n for (let i = 0; i < items.length; i += 1) {\n const item = items[i];\n const { value } = item;\n item.isSelected = this.isValueSelected(value);\n }\n\n this.setState({ items });\n }\n\n updateViewport(top, bottom, isLoading = false) {\n const { table } = this.props;\n if (table == null) {\n return;\n }\n\n if (isLoading) {\n this.setState({ isLoading: true });\n }\n\n const viewportSize = bottom - top + 1;\n const topRow = Math.max(0, top - viewportSize * 3);\n const bottomRow = Math.max(topRow, bottom + viewportSize * 3);\n\n log.debug2('Setting viewport', topRow, ',', bottomRow);\n table.setViewport(topRow, bottomRow, null);\n }\n\n render() {\n const { offset, isLoading, items, itemCount } = this.state;\n\n return (\n <div className=\"select-value-list-wrapper\">\n <SelectValueList\n itemCount={itemCount}\n items={items}\n offset={offset}\n onSelect={this.handleSelect}\n onViewportChange={this.handleViewportChange}\n ref={list => {\n this.list = list;\n }}\n />\n <CSSTransition\n in={isLoading}\n timeout={250}\n classNames=\"fade\"\n mountOnEnter\n unmountOnExit\n >\n <div className=\"loading-list\">\n <LoadingSpinner className=\"loading-spinner-large\" />\n </div>\n </CSSTransition>\n </div>\n );\n }\n}\n\nAdvancedFilterCreatorSelectValueList.propTypes = {\n table: PropTypes.shape({\n addEventListener: PropTypes.func,\n removeEventListener: PropTypes.func,\n\n applyFilter: PropTypes.func,\n columns: PropTypes.arrayOf(\n PropTypes.shape({\n name: PropTypes.string,\n type: PropTypes.string,\n })\n ),\n setViewport: PropTypes.func,\n size: PropTypes.number,\n }),\n invertSelection: PropTypes.bool,\n selectedValues: PropTypes.arrayOf(PropTypes.any),\n onChange: PropTypes.func,\n filters: PropTypes.arrayOf(APIPropTypes.FilterCondition).isRequired,\n formatter: PropTypes.instanceOf(Formatter).isRequired,\n};\n\nAdvancedFilterCreatorSelectValueList.defaultProps = {\n table: null,\n invertSelection: true,\n selectedValues: [],\n onChange: () => {},\n};\n\nexport default AdvancedFilterCreatorSelectValueList;\n","/* eslint react/no-did-update-set-state: \"off\" */\nimport React, { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport { CSSTransition } from 'react-transition-group';\nimport classNames from 'classnames';\nimport Formatter from './Formatter';\nimport TableUtils from './TableUtils';\nimport AdvancedFilterCreatorSelectValueList from './AdvancedFilterCreatorSelectValueList';\nimport './AdvancedFilterCreatorSelectValue.scss';\n\nclass AdvancedFilterCreatorSelectValue extends PureComponent {\n static searchDebounceTime = 250;\n\n constructor(props) {\n super(props);\n\n this.handleSelectAllClick = this.handleSelectAllClick.bind(this);\n this.handleClearAllClick = this.handleClearAllClick.bind(this);\n this.handleListChange = this.handleListChange.bind(this);\n this.handleSearchChange = this.handleSearchChange.bind(this);\n this.handleUpdateFilterTimeout = this.handleUpdateFilterTimeout.bind(this);\n\n this.searchTablePromise = null;\n this.updateFilterTimer = null;\n\n const { invertSelection, selectedValues } = props;\n\n this.state = {\n error: null,\n filters: [],\n invertSelection,\n selectedValues,\n searchText: '',\n table: null,\n };\n }\n\n componentDidMount() {\n this.initSearchTable();\n }\n\n componentDidUpdate(prevProps, prevState) {\n const { invertSelection, selectedValues, table } = this.props;\n if (prevProps.table !== table) {\n this.initSearchTable();\n }\n\n if (prevProps.invertSelection !== invertSelection) {\n this.setState({ invertSelection });\n }\n\n if (prevProps.selectedValues !== selectedValues) {\n this.setState({ selectedValues });\n }\n\n const { table: searchTable, searchText } = this.state;\n if (searchTable !== prevState.table && prevState.table != null) {\n prevState.table.close();\n }\n\n if (searchText !== prevState.searchText) {\n this.startUpdateFilterTimer();\n }\n }\n\n componentWillUnmount() {\n const { table } = this.state;\n if (table != null) {\n table.close();\n }\n this.searchTablePromise = null;\n\n this.stopUpdateFilterTimer();\n }\n\n getColumnName() {\n const { table } = this.props;\n if (table != null) {\n return table.columns[0].name;\n }\n return '';\n }\n\n getDisplayedValuesCount() {\n const { invertSelection, selectedValues, table } = this.state;\n if (table == null) {\n return null;\n }\n\n if (invertSelection) {\n return table.totalSize - selectedValues.length;\n }\n return selectedValues.length;\n }\n\n getDisplayedValueText() {\n const count = this.getDisplayedValuesCount();\n const { table } = this.state;\n const { formatter } = this.props;\n\n if (count != null && table != null) {\n const formattedCount = formatter.getFormattedString(count, 'long');\n const formattedTableSize = formatter.getFormattedString(\n table.totalSize,\n 'long'\n );\n let prefix = '';\n if (count < 1000000) {\n prefix = 'Displaying ';\n }\n return `${prefix}${formattedCount} of ${formattedTableSize}`;\n }\n return null;\n }\n\n initSearchTable() {\n const { table } = this.props;\n if (table == null) {\n return;\n }\n\n const searchTablePromise = table.copy();\n this.searchTablePromise = searchTablePromise;\n this.searchTablePromise.then(searchTable => {\n if (this.searchTablePromise === searchTablePromise) {\n this.setState({ table: searchTable });\n this.searchTablePromise = null;\n } else {\n searchTable.close();\n }\n });\n }\n\n handleListChange(selectedValues, invertSelection) {\n this.setState({ selectedValues, invertSelection });\n\n const { onChange } = this.props;\n onChange(selectedValues, invertSelection);\n }\n\n handleSearchChange(event) {\n const searchText = event.target.value;\n this.setState({ searchText });\n }\n\n handleSelectAllClick() {\n this.resetSelection(true);\n }\n\n handleClearAllClick() {\n this.resetSelection(false);\n }\n\n handleUpdateFilterTimeout() {\n this.updateFilterTimer = null;\n this.updateTableFilter();\n }\n\n resetSelection(invertSelection) {\n const selectedValues = [];\n\n this.setState({ invertSelection, selectedValues });\n\n const { onChange } = this.props;\n onChange(selectedValues, invertSelection);\n }\n\n startUpdateFilterTimer() {\n this.stopUpdateFilterTimer();\n\n this.updateFilterTimer = setTimeout(\n this.handleUpdateFilterTimeout,\n AdvancedFilterCreatorSelectValue.searchDebounceTime\n );\n }\n\n stopUpdateFilterTimer() {\n if (this.updateFilterTimer) {\n clearTimeout(this.updateFilterTimer);\n this.updateFilterTimer = null;\n }\n }\n\n updateTableFilter() {\n const { table, searchText } = this.state;\n const { timeZone } = this.props;\n const column = table.columns[0];\n const filters = [];\n let error = null;\n if (searchText.length > 0) {\n let filter = null;\n if (TableUtils.isCharType(column.type)) {\n // Just exact match for char\n filter = TableUtils.makeQuickFilter(column, searchText);\n } else if (TableUtils.isTextType(column.type)) {\n // case insensitive & contains search text\n filter = TableUtils.makeQuickFilter(column, `~${searchText}`, timeZone);\n } else {\n // greater than or equal search for everything else\n // we may want to be smarter with some other types (like dates)\n filter = TableUtils.makeQuickFilter(\n column,\n `>=${searchText}`,\n timeZone\n );\n }\n\n if (filter != null) {\n filters.push(filter);\n } else {\n error = 'Invalid search text';\n }\n }\n\n this.setState({ filters, error });\n }\n\n render() {\n const {\n error,\n filters,\n invertSelection,\n selectedValues,\n searchText,\n table,\n } = this.state;\n const { formatter, showSearch } = this.props;\n const columnName = this.getColumnName();\n const displayedValuesText = this.getDisplayedValueText();\n const placeholderText = columnName ? `Find ${columnName}...` : '';\n\n return (\n <div className=\"advanced-filter-creator-select-value\">\n <div className={showSearch ? 'form-group' : ''}>\n <label htmlFor=\"advanced-filter-creator-select-value-input\">\n Select Values\n </label>\n {showSearch && (\n <input\n type=\"text\"\n className={classNames('form-control', {\n 'is-invalid': error != null,\n })}\n id=\"advanced-filter-creator-select-value-input\"\n placeholder={placeholderText}\n value={searchText}\n onChange={this.handleSearchChange}\n />\n )}\n </div>\n <AdvancedFilterCreatorSelectValueList\n table={table}\n filters={filters}\n invertSelection={invertSelection}\n selectedValues={selectedValues}\n formatter={formatter}\n onChange={this.handleListChange}\n />\n <div className=\"advanced-filter-creator-select-meta-row\">\n <div>\n <button\n type=\"button\"\n className=\"btn btn-link\"\n onClick={this.handleSelectAllClick}\n >\n Select All\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link\"\n onClick={this.handleClearAllClick}\n >\n Clear\n </button>\n </div>\n <CSSTransition\n in={displayedValuesText != null}\n timeout={250}\n classNames=\"fade\"\n mountOnEnter\n unmountOnExit\n >\n <div className=\"row-count-info\">{displayedValuesText}</div>\n </CSSTransition>\n </div>\n </div>\n );\n }\n}\n\nAdvancedFilterCreatorSelectValue.propTypes = {\n table: PropTypes.shape({\n close: PropTypes.func,\n columns: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string })),\n copy: PropTypes.func,\n totalSize: PropTypes.number,\n }),\n invertSelection: PropTypes.bool,\n selectedValues: PropTypes.arrayOf(PropTypes.any),\n formatter: PropTypes.instanceOf(Formatter).isRequired,\n onChange: PropTypes.func,\n showSearch: PropTypes.bool,\n timeZone: PropTypes.string.isRequired,\n};\n\nAdvancedFilterCreatorSelectValue.defaultProps = {\n table: null,\n invertSelection: true,\n selectedValues: [],\n onChange: () => {},\n showSearch: true,\n};\n\nexport default AdvancedFilterCreatorSelectValue;\n","/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n// disabled for tab-index on focus traps, which are intentionally non-interactive\n\nimport React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport memoize from 'memoize-one';\nimport { dhSortAmountDown, dhNewCircleLargeFilled } from '@deephaven/icons';\nimport { ContextActionUtils, Tooltip } from '@deephaven/components';\nimport Log from '@deephaven/log';\nimport { PromiseUtils } from '@deephaven/utils';\nimport TableUtils from './TableUtils';\nimport { FilterOperator } from './filters';\nimport AdvancedFilterCreatorFilterItem from './AdvancedFilterCreatorFilterItem';\nimport AdvancedFilterCreatorSelectValue from './AdvancedFilterCreatorSelectValue';\nimport Formatter from './Formatter';\nimport IrisGridModel from './IrisGridModel';\nimport './AdvancedFilterCreator.scss';\n\nconst log = Log.module('AdvancedFilterCreator');\n\nclass AdvancedFilterCreator extends PureComponent {\n static debounceFilterUpdate = 250;\n\n constructor(props) {\n super(props);\n\n this.handleAddAnd = this.handleAddAnd.bind(this);\n this.handleAddOr = this.handleAddOr.bind(this);\n this.handleChangeFilterOperator = this.handleChangeFilterOperator.bind(\n this\n );\n this.handleDone = this.handleDone.bind(this);\n this.handleFilterChange = this.handleFilterChange.bind(this);\n this.handleFilterDelete = this.handleFilterDelete.bind(this);\n this.handleSelectValueChange = this.handleSelectValueChange.bind(this);\n this.handleReset = this.handleReset.bind(this);\n this.handleSortDown = this.handleSortDown.bind(this);\n this.handleSortUp = this.handleSortUp.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleFocusTrapStart = this.handleFocusTrapStart.bind(this);\n this.handleFocusTrapEnd = this.handleFocusTrapEnd.bind(this);\n this.handleUpdateTimeout = this.handleUpdateTimeout.bind(this);\n\n this.focusTrapContainer = React.createRef();\n this.debounceTimeout = null;\n this.filterKey = 0;\n this.valuesTablePromise = null;\n\n const { options } = props;\n let {\n filterItems,\n filterOperators,\n invertSelection,\n selectedValues,\n } = options;\n if (filterItems == null) {\n filterItems = [this.makeFilterItem()];\n }\n if (filterOperators == null) {\n filterOperators = [];\n }\n if (invertSelection == null) {\n invertSelection = true;\n }\n if (selectedValues == null) {\n selectedValues = [];\n }\n\n this.state = {\n // Filter items\n filterItems,\n\n // And/Or between the filter items\n filterOperators,\n\n invertSelection,\n\n selectedValues,\n\n valuesTableError: null,\n valuesTable: null,\n };\n }\n\n componentDidMount() {\n this.initValuesTable();\n }\n\n componentWillUnmount() {\n if (this.debounceTimeout != null) {\n clearTimeout(this.debounceTimeout);\n this.sendUpdate();\n }\n if (this.valuesTablePromise != null) {\n this.valuesTablePromise.cancel();\n }\n }\n\n getFilterChangeHandler(index) {\n return this.handleFilterChange.bind(this, index);\n }\n\n getFilterDeleteHandler(index) {\n return this.handleFilterDelete.bind(this, index);\n }\n\n getFilterTypes = memoize(columnType => TableUtils.getFilterTypes(columnType));\n\n initValuesTable() {\n const { model, column } = this.props;\n if (!model.isValuesTableAvailable) {\n log.debug('No values table for this model, just ignore');\n return;\n }\n\n this.valuesTablePromise = TableUtils.makeCancelableTablePromise(\n model.valuesTable(column)\n );\n this.valuesTablePromise\n .then(valuesTable => {\n const sort = valuesTable.columns[0].sort().asc();\n valuesTable.applySort([sort]);\n\n this.setState({ valuesTable });\n })\n .catch(error => {\n if (PromiseUtils.isCanceled(error)) {\n return;\n }\n\n log.error('Unable to open values table', error);\n this.setState({ valuesTableError: error });\n });\n }\n\n handleFocusTrapEnd() {\n const inputs = this.focusTrapContainer.current.querySelectorAll(\n 'button,select,input,textarea'\n );\n inputs[0].focus();\n }\n\n handleFocusTrapStart() {\n const inputs = this.focusTrapContainer.current.querySelectorAll(\n 'button,select,input,textarea'\n );\n inputs[inputs.length - 1].focus();\n }\n\n handleAddAnd() {\n let { filterItems, filterOperators } = this.state;\n filterItems = filterItems.concat(this.makeFilterItem());\n filterOperators = filterOperators.concat(FilterOperator.and);\n this.setState({ filterItems, filterOperators });\n }\n\n handleAddOr() {\n let { filterItems, filterOperators } = this.state;\n filterItems = filterItems.concat(this.makeFilterItem());\n filterOperators = filterOperators.concat(FilterOperator.or);\n this.setState({ filterItems, filterOperators });\n }\n\n handleChangeFilterOperator(event) {\n const index = parseInt(event.target.dataset.index, 10);\n const { operator } = event.target.dataset;\n\n let { filterOperators } = this.state;\n filterOperators = [].concat(filterOperators);\n filterOperators[index] = operator;\n\n this.setState({ filterOperators });\n\n this.startUpdateTimer();\n }\n\n handleFilterChange(filterIndex, selectedType, value) {\n let { filterItems } = this.state;\n filterItems = [].concat(filterItems);\n const { key } = filterItems[filterIndex];\n filterItems[filterIndex] = { key, selectedType, value };\n\n this.setState({ filterItems });\n\n this.startUpdateTimer();\n }\n\n handleFilterDelete(filterIndex) {\n let { filterItems, filterOperators } = this.state;\n filterItems = [].concat(filterItems);\n filterOperators = [].concat(filterOperators);\n if (filterIndex < filterItems.length) {\n filterItems.splice(filterIndex, 1);\n }\n\n if (filterIndex < filterOperators.length) {\n filterOperators.splice(filterIndex, 1);\n } else if (filterIndex === filterOperators.length) {\n // When deleting the last filter item, we also need to remove the last filter operator\n filterOperators.splice(filterOperators.length - 1, 1);\n }\n\n if (filterItems.length === 0) {\n filterItems.push(this.makeFilterItem());\n }\n\n this.setState({ filterItems, filterOperators });\n\n this.startUpdateTimer();\n }\n\n handleSelectValueChange(selectedValues, invertSelection) {\n this.setState({ selectedValues, invertSelection });\n\n this.startUpdateTimer();\n }\n\n handleReset() {\n log.debug('Resetting Advanced Filter');\n\n this.setState({\n filterItems: [this.makeFilterItem()],\n filterOperators: [],\n selectedValues: [],\n invertSelection: true,\n });\n\n this.startUpdateTimer();\n }\n\n handleSortDown(event) {\n const addToExisting = ContextActionUtils.isModifierKeyDown(event);\n this.sortTable(TableUtils.sortDirection.descending, addToExisting);\n }\n\n handleSortUp(event) {\n const addToExisting = ContextActionUtils.isModifierKeyDown(event);\n this.sortTable(TableUtils.sortDirection.ascending, addToExisting);\n }\n\n handleSubmit(event) {\n log.debug('Submitting Advanced Filter');\n this.stopUpdateTimer();\n this.sendUpdate();\n\n event.preventDefault();\n }\n\n handleDone(event) {\n log.debug('Submitting and Closing Advanced Filter');\n this.stopUpdateTimer();\n this.sendUpdate();\n\n const { onDone } = this.props;\n onDone();\n\n event.preventDefault();\n }\n\n handleUpdateTimeout() {\n this.debounceTimeout = null;\n this.sendUpdate();\n }\n\n makeFilterItem(updateKey = true) {\n const key = this.filterKey;\n if (updateKey) {\n this.filterKey += 1;\n }\n return { selectedType: '', value: '', key };\n }\n\n /**\n * Convenience function to check if the previous filter has been inputted, and\n * we should show the add filter buttons (+ AND OR)\n * @returns true If the add filter buttons should be shown, false otherwise\n */\n shouldShowAddFilter() {\n const { filterItems } = this.state;\n if (filterItems.length === 0) {\n return false;\n }\n\n const filterItem = filterItems[filterItems.length - 1];\n const { selectedType, value } = filterItem;\n\n return (\n selectedType != null &&\n selectedType.length > 0 &&\n value != null &&\n value.length > 0\n );\n }\n\n /**\n * Sorts the table in the specified direction. If already sorted in that direction, remove it.\n * @param {String} direction The sort direction, ASC or DESC\n * @param {boolean} addToExisting Add to the existing sort, or replace the existing table sort\n */\n sortTable(direction, addToExisting = false) {\n const { column, onSortChange } = this.props;\n onSortChange(column, direction, addToExisting);\n }\n\n startUpdateTimer() {\n this.stopUpdateTimer();\n\n this.debounceTimeout = setTimeout(\n this.handleUpdateTimeout,\n AdvancedFilterCreator.debounceFilterUpdate\n );\n }\n\n stopUpdateTimer() {\n if (this.debounceTimeout) {\n clearTimeout(this.debounceTimeout);\n this.debounceTimeout = null;\n }\n }\n\n sendUpdate() {\n const {\n filterItems,\n filterOperators,\n invertSelection,\n selectedValues,\n } = this.state;\n const { column, onFilterChange, model } = this.props;\n const { formatter } = model;\n\n const options = {\n filterItems,\n filterOperators,\n invertSelection,\n selectedValues,\n };\n\n const filter = TableUtils.makeAdvancedFilter(\n column,\n options,\n formatter.timeZone\n );\n\n onFilterChange(column, filter, options);\n }\n\n render() {\n const { column, model, sortDirection, formatter } = this.props;\n const {\n filterItems,\n filterOperators,\n invertSelection,\n selectedValues,\n valuesTable,\n valuesTableError,\n } = this.state;\n const { isValuesTableAvailable } = model;\n const isBoolean = TableUtils.isBooleanType(column.type);\n const isDateType = TableUtils.isDateType(column.type);\n const filterTypes = this.getFilterTypes(column.type);\n const columnType = column.type.substring(column.type.lastIndexOf('.') + 1);\n const filterItemElements = [];\n if (!isBoolean && filterTypes.length) {\n for (let i = 0; i < filterItems.length; i += 1) {\n const filterItem = filterItems[i];\n const { key, selectedType, value } = filterItem;\n\n const element = (\n <AdvancedFilterCreatorFilterItem\n key={key}\n column={column}\n filterTypes={filterTypes}\n onChange={this.getFilterChangeHandler(i)}\n onDelete={this.getFilterDeleteHandler(i)}\n selectedType={selectedType}\n value={value}\n />\n );\n filterItemElements.push(element);\n\n if (i < filterOperators.length) {\n const filterOperator = filterOperators[i];\n const isAndFilter = filterOperator === FilterOperator.and;\n const operatorElement = (\n <div\n key={`filterOperator${key}`}\n className=\"form-row justify-content-end advanced-filter-creator-filter-operator\"\n >\n <button\n type=\"button\"\n className={classNames('btn btn-link filter-operator', {\n active: isAndFilter,\n })}\n onClick={this.handleChangeFilterOperator}\n data-index={i}\n data-operator={FilterOperator.and}\n >\n AND\n </button>\n <button\n type=\"button\"\n className={classNames('btn btn-link filter-operator', {\n active: !isAndFilter,\n })}\n onClick={this.handleChangeFilterOperator}\n data-index={i}\n data-operator={FilterOperator.or}\n >\n OR\n </button>\n </div>\n );\n filterItemElements.push(operatorElement);\n }\n }\n }\n const showAddFilterItem = this.shouldShowAddFilter();\n const addFilterItem = (\n <div\n key=\"addFilterItem\"\n className={classNames('form-row justify-content-end add-filter-item', {\n hidden: !showAddFilterItem,\n })}\n >\n <span className=\"text-muted\">\n <FontAwesomeIcon icon={dhNewCircleLargeFilled} />\n </span>\n <button\n type=\"button\"\n className=\"btn btn-link btn-filter-item\"\n onClick={this.handleAddAnd}\n disabled={!showAddFilterItem}\n >\n AND\n <Tooltip>Add filter with AND</Tooltip>\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-filter-item\"\n onClick={this.handleAddOr}\n disabled={!showAddFilterItem}\n >\n OR\n <Tooltip>Add filter with OR</Tooltip>\n </button>\n </div>\n );\n filterItemElements.push(addFilterItem);\n\n return (\n <div className=\"advanced-filter-creator\" role=\"presentation\">\n <div tabIndex=\"0\" onFocus={this.handleFocusTrapStart} />\n <form onSubmit={this.handleSubmit} ref={this.focusTrapContainer}>\n <div className=\"title-bar\">\n <h6 className=\"advanced-filter-title\">Advanced Filters</h6>\n <div className=\"advanced-filter-menu-buttons\">\n <button\n type=\"button\"\n className={classNames(\n 'btn btn-link btn-link-icon sort-operator',\n {\n active:\n sortDirection === TableUtils.sortDirection.descending,\n }\n )}\n onClick={this.handleSortDown}\n >\n <FontAwesomeIcon icon={dhSortAmountDown} />\n <Tooltip>Sort {column.name} Descending</Tooltip>\n </button>\n <button\n type=\"button\"\n className={classNames(\n 'btn btn-link btn-link-icon sort-operator',\n {\n active:\n sortDirection === TableUtils.sortDirection.ascending,\n }\n )}\n onClick={this.handleSortUp}\n >\n <FontAwesomeIcon rotation={180} icon={dhSortAmountDown} />\n <Tooltip>Sort {column.name} Ascending</Tooltip>\n </button>\n </div>\n </div>\n <hr />\n <div className=\"advanced-filter-column-name\">\n {column.name}&nbsp;\n <span className=\"column-type\">({columnType})</span>\n </div>\n {filterItemElements}\n {isValuesTableAvailable && !valuesTableError && (\n <>\n {!isBoolean && <hr />}\n <div className=\"form-group\">\n <AdvancedFilterCreatorSelectValue\n table={valuesTable}\n onChange={this.handleSelectValueChange}\n invertSelection={invertSelection}\n selectedValues={selectedValues}\n formatter={formatter}\n showSearch={!isDateType}\n timeZone={formatter.timeZone}\n />\n </div>\n </>\n )}\n <div className=\"form-row justify-content-end\">\n <button\n type=\"button\"\n className=\"btn btn-outline-primary mr-2\"\n onClick={this.handleReset}\n >\n Reset\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n onClick={this.handleDone}\n >\n Done\n </button>\n </div>\n </form>\n <div tabIndex=\"0\" onFocus={this.handleFocusTrapEnd} />\n </div>\n );\n }\n}\n\nAdvancedFilterCreator.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n column: PropTypes.shape({ name: PropTypes.string, type: PropTypes.string })\n .isRequired,\n onFilterChange: PropTypes.func.isRequired,\n onSortChange: PropTypes.func.isRequired,\n onDone: PropTypes.func.isRequired,\n options: PropTypes.shape({\n filterItems: PropTypes.arrayOf(PropTypes.shape({})),\n filterOperators: PropTypes.arrayOf(PropTypes.shape({})),\n invertSelection: PropTypes.bool,\n selectedValues: PropTypes.arrayOf(PropTypes.any),\n }),\n sortDirection: PropTypes.string,\n formatter: PropTypes.instanceOf(Formatter).isRequired,\n};\n\nAdvancedFilterCreator.defaultProps = {\n options: {\n filterItems: null,\n filterOperators: null,\n invertSelection: true,\n selectedValues: [],\n },\n sortDirection: null,\n};\n\nexport default AdvancedFilterCreator;\n","enum OptionType {\n ADVANCED_SETTINGS = 'ADVANCED_SETTINGS',\n AGGREGATIONS = 'AGGREGATIONS',\n AGGREGATION_EDIT = 'AGGREGATIONS_EDIT',\n CHART_BUILDER = 'CHART_BUILDER',\n CUSTOM_COLUMN_BUILDER = 'CUSTOM_COLUMN_BUILDER',\n QUICK_FILTERS = 'QUICK_FILTERS',\n ROLLUP_ROWS = 'ROLLUP_ROWS',\n SEARCH_BAR = 'SEARCH_BAR',\n SELECT_DISTINCT = 'SELECT_DISTINCT',\n TABLE_EXPORTER = 'TABLE_EXPORTER',\n VISIBILITY_ORDERING_BUILDER = 'VISIBILITY_ORDERING_BUILDER',\n}\n\nexport default OptionType;\n","import React, { PureComponent } from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsSearch } from '@deephaven/icons';\nimport classNames from 'classnames';\nimport './SearchInput.scss';\n\ninterface SearchInputProps {\n value: string;\n placeholder: string;\n onChange: React.ChangeEventHandler<HTMLInputElement>;\n onKeyDown: React.KeyboardEventHandler<HTMLInputElement>;\n className: string;\n matchCount: number;\n id: string;\n}\n\nclass SearchInput extends PureComponent<SearchInputProps> {\n static defaultProps = {\n placeholder: 'Search',\n className: '',\n matchCount: null,\n onKeyDown(): void {\n // no-op\n },\n id: '',\n };\n\n constructor(props: SearchInputProps) {\n super(props);\n this.inputField = React.createRef();\n }\n\n inputField: React.RefObject<HTMLInputElement>;\n\n focus(): void {\n this.inputField.current?.focus();\n }\n\n render(): JSX.Element {\n const {\n value,\n placeholder,\n onChange,\n className,\n matchCount,\n id,\n onKeyDown,\n } = this.props;\n return (\n <div className={classNames('search-group', className)}>\n <input\n type=\"search\"\n value={value}\n onChange={onChange}\n onKeyDown={onKeyDown}\n className=\"form-control\"\n placeholder={placeholder}\n ref={this.inputField}\n id={id}\n />\n {matchCount != null && (\n <span className=\"search-match\">{matchCount}</span>\n )}\n <span className=\"search-icon\">\n <FontAwesomeIcon icon={vsSearch} />\n </span>\n </div>\n );\n }\n}\n\nexport default SearchInput;\n","/* eslint-disable jsx-a11y/click-events-have-key-events */\nimport React, { Component } from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport { GridUtils } from '@deephaven/grid';\nimport { TextUtils } from '@deephaven/utils';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n dhEye,\n dhEyeSlash,\n dhSortAlphaDown,\n dhSortAlphaUp,\n dhArrowToTop,\n dhArrowToBottom,\n vsChevronUp,\n vsChevronDown,\n vsGripper,\n} from '@deephaven/icons';\nimport { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';\nimport memoize from 'memoizee';\nimport debounce from 'lodash.debounce';\nimport { SearchInput, Tooltip } from '@deephaven/components';\nimport Log from '@deephaven/log';\nimport './VisibilityOrderingBuilder.scss';\nimport IrisGridModel from '../IrisGridModel';\n\nconst log = Log.module('VisibilityOrderingBuilder');\nconst DEBOUNCE_SEARCH_COLUMN = 150;\n\nclass VisibilityOrderingBuilder extends Component {\n static VISIBILITY_OPTIONS = { SHOW: 'SHOW', HIDE: 'HIDE' };\n\n static SORTING_OPTIONS = { DSC: 'DSC', ASC: 'ASC' };\n\n static MOVE_OPTIONS = {\n TOP: 'TOP',\n BOTTOM: 'BOTTOM',\n UP: 'UP',\n DOWN: 'DOWN',\n };\n\n static COLUMN_CHANGE_OPTIONS = { ALL: 'ALL', SELECTION: 'SELECTION' };\n\n constructor(props) {\n super(props);\n\n this.handleSearchInputChange = this.handleSearchInputChange.bind(this);\n this.debouncedSearchColumns = debounce(\n this.searchColumns.bind(this),\n DEBOUNCE_SEARCH_COLUMN\n );\n this.handleOrderDraggingStart = this.handleOrderDraggingStart.bind(this);\n this.handleOrderDraggingEnd = this.handleOrderDraggingEnd.bind(this);\n\n this.state = {\n selectedColumns: [], // model index of selected column(s)\n lastSelectedColumns: [],\n isDraggingVisibility: false,\n visibilityDraggingOption: null,\n visibilityDraggingStartColumn: null,\n isDraggingOrder: false,\n orderDraggingColumn: null,\n searchFilter: '',\n };\n\n this.list = null;\n }\n\n componentWillUnmount() {\n this.debouncedSearchColumns.cancel();\n }\n\n resetVisibilityOrdering() {\n const {\n model,\n onColumnVisibilityChanged,\n onMovedColumnsChanged,\n } = this.props;\n const { columns } = model;\n\n onColumnVisibilityChanged(\n columns.map(column => model.getColumnIndexByName(column.name)),\n VisibilityOrderingBuilder.VISIBILITY_OPTIONS.SHOW\n );\n this.setState({\n selectedColumns: [],\n lastSelectedColumns: [],\n searchFilter: '',\n });\n onMovedColumnsChanged([]);\n }\n\n resetSelection() {\n const { isDraggingOrder } = this.state;\n // don't reset selection if user is dragging column(s)\n if (isDraggingOrder) {\n return;\n }\n this.setState({ selectedColumns: [], lastSelectedColumns: [] });\n }\n\n handleSearchInputChange(event) {\n const searchFilter = event.target.value;\n this.setState({ searchFilter });\n if (!searchFilter) {\n this.debouncedSearchColumns.cancel();\n this.resetSelection();\n return;\n }\n this.debouncedSearchColumns(searchFilter);\n }\n\n searchColumns(searchFilter) {\n const { model, movedColumns } = this.props;\n const { columns } = model;\n\n const columnsMatch = [];\n let visibleIndexToFocus = columns.length;\n columns.forEach((column, index) => {\n const columnName = column.name.toLowerCase();\n if (\n model.isColumnMovable(index) &&\n columnName.includes(searchFilter.toLowerCase())\n ) {\n columnsMatch.push(index);\n visibleIndexToFocus = Math.min(\n visibleIndexToFocus,\n GridUtils.getVisibleIndex(index, movedColumns)\n );\n }\n });\n this.addColumnToSelected(columnsMatch, false);\n if (columnsMatch.length > 0) {\n const columnItemToFocus = this.list.querySelectorAll('.column-item')[\n visibleIndexToFocus\n ];\n columnItemToFocus.scrollIntoView({ block: 'center' });\n }\n }\n\n handleVisibilityKeyDown(modelIndex, visibilityOption) {\n const { onColumnVisibilityChanged } = this.props;\n onColumnVisibilityChanged([modelIndex], visibilityOption);\n }\n\n handleVisibilityDraggingStart(modelIndex, visibilityOption, event) {\n const { onColumnVisibilityChanged, movedColumns } = this.props;\n\n const isModifierKeyDown = GridUtils.isModifierKeyDown(event);\n const isShiftKeyDown = event.shiftKey;\n\n if (isModifierKeyDown || isShiftKeyDown) return;\n\n onColumnVisibilityChanged([modelIndex], visibilityOption);\n\n const visibleIndex = GridUtils.getVisibleIndex(modelIndex, movedColumns);\n\n this.setState({\n isDraggingVisibility: true,\n visibilityDraggingOption: visibilityOption,\n visibilityDraggingStartColumn: visibleIndex,\n });\n\n this.addColumnToSelected([modelIndex]);\n }\n\n handleVisibilityDraggingEnd(event = null) {\n if (event) event.target.focus();\n\n const { isDraggingVisibility } = this.state;\n if (isDraggingVisibility) {\n this.setState({\n isDraggingVisibility: false,\n visibilityDraggingOption: null,\n visibilityDraggingStartColumn: null,\n });\n }\n }\n\n handleOrderDraggingStart(start) {\n document.documentElement.classList.add('drag-pointer-events-none');\n\n const { selectedColumns } = this.state;\n const {\n draggableId,\n source: { index: startIndex },\n } = start;\n const orderDraggingColumn = parseInt(draggableId, 10);\n\n // we want to clear focus from any eye toggles\n // however to maintain react-beautiful-dnd keyboard functionality the only valid\n // focus target is the drag target itself, so we set it there instead of blurring\n this.list.querySelectorAll('.column-item')[startIndex].focus();\n\n if (!selectedColumns.includes(orderDraggingColumn)) {\n this.setState({\n isDraggingOrder: true,\n orderDraggingColumn,\n selectedColumns: [orderDraggingColumn],\n });\n return;\n }\n this.setState({ isDraggingOrder: true, orderDraggingColumn });\n }\n\n handleOrderDraggingEnd(result) {\n document.documentElement.classList.remove('drag-pointer-events-none');\n\n const { movedColumns, onMovedColumnsChanged } = this.props;\n const { selectedColumns, orderDraggingColumn } = this.state;\n\n // reset dragging state\n this.setState({ isDraggingOrder: false, orderDraggingColumn: null });\n\n // if dropped outside the list, re-focus on the dragged item if necessary\n if (!result.destination) {\n return;\n }\n\n const { index: destinationIndex } = result.destination;\n\n const selectedColumnsSortByVisibleIndex = [...selectedColumns].sort(\n (columnA, columnB) =>\n GridUtils.getVisibleIndex(columnA, movedColumns) -\n GridUtils.getVisibleIndex(columnB, movedColumns)\n );\n\n let newMoves = [].concat(movedColumns);\n const draggingVisibleIndex = GridUtils.getVisibleIndex(\n orderDraggingColumn,\n newMoves\n );\n const upper = [];\n const lower = [];\n\n // move the dragged column to destination first,\n newMoves = GridUtils.moveItem(\n draggingVisibleIndex,\n destinationIndex,\n newMoves\n );\n\n // split selected columns into two parts on drop destination index: top & bottom\n selectedColumnsSortByVisibleIndex.forEach(column => {\n const columnVisibleIndex = GridUtils.getVisibleIndex(column, newMoves);\n if (column === orderDraggingColumn) {\n return;\n }\n if (columnVisibleIndex < destinationIndex) {\n upper.push(column);\n } else {\n lower.push(column);\n }\n });\n\n // for the top part, move column(s) to the destination index\n upper.forEach(column => {\n const visibleIndex = GridUtils.getVisibleIndex(column, newMoves);\n newMoves = GridUtils.moveItem(visibleIndex, destinationIndex, newMoves);\n });\n\n // for the bottom part, in reverse order, move column(s) to the drop destination index if there's no top column(s) or the dragged column is not dropped upside\n // otherwise, move column(s) under the dropping destination index\n const bottomDestinationIndex =\n upper.length > 0 || draggingVisibleIndex > destinationIndex\n ? destinationIndex + 1\n : destinationIndex;\n\n lower.reverse().forEach(column => {\n const visibleIndex = GridUtils.getVisibleIndex(column, newMoves);\n newMoves = GridUtils.moveItem(\n visibleIndex,\n bottomDestinationIndex,\n newMoves\n );\n });\n\n onMovedColumnsChanged(newMoves);\n log.debug('move column order by drag & drop', newMoves);\n }\n\n handleMouseEnter(targetModelIndex, event) {\n const {\n onColumnVisibilityChanged,\n movedColumns,\n userColumnWidths,\n } = this.props;\n const {\n isDraggingVisibility,\n visibilityDraggingOption,\n visibilityDraggingStartColumn: draggingStartVisibleIndex,\n } = this.state;\n const targetVisibleIndex = GridUtils.getVisibleIndex(\n targetModelIndex,\n movedColumns\n );\n const isModifierKeyDown = GridUtils.isModifierKeyDown(event);\n const isShiftKeyDown = event.shiftKey;\n\n if (!isDraggingVisibility || isModifierKeyDown || isShiftKeyDown) {\n return;\n }\n\n event.target.focus();\n\n // browser can skip mouseEnter / mouseMove event if user moves the mouse too fast\n // try to check columns between dragging start index to current index to compensate missing event,\n const columnsToChangeVisibility = [targetModelIndex];\n const checkDownward = targetVisibleIndex > draggingStartVisibleIndex;\n\n for (\n let visibleIndexToCheck = draggingStartVisibleIndex;\n checkDownward\n ? visibleIndexToCheck < targetVisibleIndex\n : visibleIndexToCheck > targetVisibleIndex;\n checkDownward ? (visibleIndexToCheck += 1) : (visibleIndexToCheck -= 1)\n ) {\n const modelIndexToCheck = GridUtils.getModelIndex(\n visibleIndexToCheck,\n movedColumns\n );\n const isHidden = GridUtils.checkColumnHidden(\n modelIndexToCheck,\n userColumnWidths\n );\n if (\n isHidden &&\n visibilityDraggingOption ===\n VisibilityOrderingBuilder.VISIBILITY_OPTIONS.SHOW\n ) {\n columnsToChangeVisibility.push(modelIndexToCheck);\n } else if (\n !isHidden &&\n visibilityDraggingOption ===\n VisibilityOrderingBuilder.VISIBILITY_OPTIONS.HIDE\n ) {\n columnsToChangeVisibility.push(modelIndexToCheck);\n }\n }\n\n this.addColumnToSelected(columnsToChangeVisibility, true);\n\n onColumnVisibilityChanged(\n columnsToChangeVisibility,\n visibilityDraggingOption\n );\n }\n\n handleMoveColumns(option) {\n const { movedColumns, onMovedColumnsChanged, model } = this.props;\n const { columns } = model;\n const { selectedColumns } = this.state;\n if (selectedColumns.length === 0) {\n return;\n }\n\n const firstMovableIndex = this.getFirstMovableIndex(model, columns);\n const lastMovableIndex = this.getLastMovableIndex(model, columns);\n if (firstMovableIndex == null || lastMovableIndex == null) {\n return;\n }\n\n // for moving up and to the top, move column(s) in visibility index order\n // for moving down and to the bottom, move column(s) in reverse visibility index order\n const sortedSelectedColumns = [\n ...selectedColumns,\n ].sort((columnA, columnB) =>\n option === VisibilityOrderingBuilder.MOVE_OPTIONS.TOP ||\n option === VisibilityOrderingBuilder.MOVE_OPTIONS.UP\n ? GridUtils.getVisibleIndex(columnA, movedColumns) -\n GridUtils.getVisibleIndex(columnB, movedColumns)\n : GridUtils.getVisibleIndex(columnB, movedColumns) -\n GridUtils.getVisibleIndex(columnA, movedColumns)\n );\n\n let newMoves = [];\n let scrollListAfterMove = () => {};\n\n switch (option) {\n case VisibilityOrderingBuilder.MOVE_OPTIONS.TOP:\n sortedSelectedColumns.forEach((columnModelIndex, index) => {\n const visibleIndex = GridUtils.getVisibleIndex(\n columnModelIndex,\n movedColumns\n );\n newMoves = GridUtils.moveItem(\n visibleIndex,\n firstMovableIndex + index,\n newMoves\n );\n });\n scrollListAfterMove = () => {\n this.list.scrollTop = 0;\n };\n break;\n case VisibilityOrderingBuilder.MOVE_OPTIONS.BOTTOM:\n sortedSelectedColumns.forEach((columnModelIndex, index) => {\n const visibleIndex = GridUtils.getVisibleIndex(\n columnModelIndex,\n movedColumns\n );\n newMoves = GridUtils.moveItem(\n visibleIndex,\n lastMovableIndex - index,\n newMoves\n );\n });\n scrollListAfterMove = () => {\n this.list.scrollTop = this.list.scrollHeight;\n };\n\n break;\n case VisibilityOrderingBuilder.MOVE_OPTIONS.UP:\n if (\n GridUtils.getVisibleIndex(sortedSelectedColumns[0], movedColumns) !==\n firstMovableIndex // check if the first visible column has reached top\n ) {\n sortedSelectedColumns.forEach(columnModelIndex => {\n const visibleIndex = GridUtils.getVisibleIndex(\n columnModelIndex,\n movedColumns\n );\n newMoves = GridUtils.moveItem(\n visibleIndex,\n visibleIndex - 1,\n newMoves\n );\n });\n }\n break;\n case VisibilityOrderingBuilder.MOVE_OPTIONS.DOWN:\n if (\n GridUtils.getVisibleIndex(sortedSelectedColumns[0], movedColumns) !==\n lastMovableIndex // check if the last visible column has reached bottom\n ) {\n sortedSelectedColumns.forEach(columnModelIndex => {\n const visibleIndex = GridUtils.getVisibleIndex(\n columnModelIndex,\n movedColumns\n );\n newMoves = GridUtils.moveItem(\n visibleIndex,\n visibleIndex + 1,\n newMoves\n );\n });\n }\n break;\n default:\n break;\n }\n if (newMoves.length > 0) {\n onMovedColumnsChanged(movedColumns.concat(newMoves), scrollListAfterMove);\n }\n }\n\n handleSortColumns(option) {\n const { model, onMovedColumnsChanged } = this.props;\n const { columns } = model;\n\n // We can't move the immovable columns when sorting, so separate them out first\n const movableColumns = [];\n const immovableColumns = [];\n for (let modelIndex = 0; modelIndex < columns.length; modelIndex += 1) {\n if (model.isColumnMovable(modelIndex)) {\n movableColumns.push(modelIndex);\n } else {\n immovableColumns.push(modelIndex);\n }\n }\n\n // Sort all the movable columns\n const movableColumnsSorted = movableColumns.sort((a, b) => {\n const isAscending =\n option === VisibilityOrderingBuilder.SORTING_OPTIONS.ASC;\n const aName = columns[a].name.toUpperCase();\n const bName = columns[b].name.toUpperCase();\n return TextUtils.sort(aName, bName, isAscending);\n });\n\n // Place all the immovable columns where they need to be\n const modelIndexAlphaSorted = [];\n for (let i = 0; i < immovableColumns.length; i += 1) {\n const modelIndex = immovableColumns[i];\n modelIndexAlphaSorted[modelIndex] = modelIndex;\n }\n\n // Then the rest of the sorted columns can be put in the empty spaces\n let insertIndex = 0;\n for (let i = 0; i < movableColumnsSorted.length; i += 1) {\n while (modelIndexAlphaSorted[insertIndex] != null) {\n insertIndex += 1;\n }\n\n modelIndexAlphaSorted[insertIndex] = movableColumnsSorted[i];\n }\n\n let newMoves = [];\n modelIndexAlphaSorted.forEach((modelIndex, index) => {\n const visibleIndex = GridUtils.getVisibleIndex(modelIndex, newMoves);\n newMoves = GridUtils.moveItem(visibleIndex, index, newMoves);\n });\n onMovedColumnsChanged(newMoves);\n }\n\n handleItemClick(modelIndexClicked, event, removeSelectionOnClick = true) {\n event.stopPropagation();\n event.currentTarget.focus();\n\n const { selectedColumns, lastSelectedColumns } = this.state;\n const isModifierKeyDown = GridUtils.isModifierKeyDown(event);\n const isShiftKeyDown = event.shiftKey;\n const isSelected = selectedColumns.includes(modelIndexClicked);\n const columnsToBeAdded = [modelIndexClicked];\n\n if (isSelected && isModifierKeyDown) {\n this.removeColumnFromSelected(modelIndexClicked);\n return;\n }\n\n if (isSelected && selectedColumns.length === 1 && removeSelectionOnClick) {\n this.removeColumnFromSelected(modelIndexClicked);\n return;\n }\n\n if (isShiftKeyDown) {\n const { movedColumns } = this.props;\n const lastSelectedColumn =\n lastSelectedColumns[lastSelectedColumns.length - 1];\n const lastSelectedColumnVisibleIndex = GridUtils.getVisibleIndex(\n lastSelectedColumn,\n movedColumns\n );\n const visibleIndexToBeSelected = GridUtils.getVisibleIndex(\n modelIndexClicked,\n movedColumns\n );\n const checkDownward =\n visibleIndexToBeSelected > lastSelectedColumnVisibleIndex;\n const columnsInBetween = [];\n for (\n let i = lastSelectedColumnVisibleIndex;\n checkDownward\n ? i < visibleIndexToBeSelected\n : i > visibleIndexToBeSelected;\n checkDownward ? (i += 1) : (i -= 1)\n ) {\n columnsInBetween.push(GridUtils.getModelIndex(i, movedColumns));\n }\n columnsInBetween.forEach(column => {\n if (!selectedColumns.includes(column)) {\n columnsToBeAdded.push(column);\n }\n });\n }\n\n this.addColumnToSelected(\n columnsToBeAdded,\n isModifierKeyDown || isShiftKeyDown\n );\n }\n\n addColumnToSelected(columnsToBeAdded, addToExisting = false) {\n const { selectedColumns, lastSelectedColumns } = this.state;\n const newSelectedColumns = addToExisting\n ? selectedColumns.concat(columnsToBeAdded)\n : columnsToBeAdded;\n const newLastSelectedColumns = addToExisting\n ? lastSelectedColumns.concat(columnsToBeAdded)\n : columnsToBeAdded;\n\n this.setState({\n selectedColumns: newSelectedColumns,\n lastSelectedColumns: newLastSelectedColumns,\n });\n }\n\n removeColumnFromSelected(modelIndex) {\n const { selectedColumns, lastSelectedColumns } = this.state;\n const newSelectedColumns = [...selectedColumns];\n\n newSelectedColumns.splice(\n newSelectedColumns.findIndex(selected => selected === modelIndex),\n 1\n );\n const lastSelectedColumn =\n lastSelectedColumns[lastSelectedColumns.length - 1];\n const newLastSelectedColumns = [...lastSelectedColumns];\n if (lastSelectedColumn === modelIndex) {\n newLastSelectedColumns.pop();\n }\n this.setState({\n selectedColumns: newSelectedColumns,\n lastSelectedColumns: newLastSelectedColumns,\n });\n }\n\n makeVisibilityOrderingList() {\n const { model, userColumnWidths, movedColumns } = this.props;\n const { columns } = model;\n const {\n selectedColumns,\n isDraggingOrder,\n orderDraggingColumn,\n } = this.state;\n\n const elements = [];\n let wasMovable = false;\n for (\n let visibleIndex = 0;\n visibleIndex < columns.length;\n visibleIndex += 1\n ) {\n const modelIndex = GridUtils.getModelIndex(visibleIndex, movedColumns);\n const column = columns[modelIndex];\n const isMovable = model.isColumnMovable(modelIndex);\n if (visibleIndex > 0 && isMovable !== wasMovable) {\n elements.push(<hr />);\n }\n if (isMovable) {\n const isHidden = userColumnWidths.get(modelIndex) === 0;\n const isSelected = selectedColumns.includes(modelIndex);\n const isDragged = orderDraggingColumn === modelIndex;\n const columnsDragged =\n isDraggingOrder && isDragged && selectedColumns.length > 1\n ? selectedColumns.length\n : null;\n elements.push(\n this.renderVisibilityOrderingItem(\n column.name,\n modelIndex,\n visibleIndex,\n isHidden,\n isSelected,\n isDraggingOrder,\n isDragged,\n columnsDragged\n )\n );\n } else {\n elements.push(this.renderImmovableItem(column.name));\n }\n\n wasMovable = isMovable;\n }\n\n return elements;\n }\n\n getFirstMovableIndex = memoize((model, columns) => {\n for (let i = 0; i < columns.length; i += 1) {\n if (model.isColumnMovable(i)) {\n return i;\n }\n }\n\n return null;\n });\n\n getLastMovableIndex = memoize((model, columns) => {\n for (let i = columns.length - 1; i >= 0; i -= 1) {\n if (model.isColumnMovable(i)) {\n return i;\n }\n }\n\n return null;\n });\n\n renderImmovableItem = memoize(columnName => (\n <div className=\"visibility-ordering-list-item immovable\" key={columnName}>\n <div className=\"column-item\">\n <span className=\"column-name\">{columnName}</span>\n </div>\n </div>\n ));\n\n renderVisibilityOrderingItem = memoize(\n (\n columnName,\n modelIndex,\n visibleIndex,\n isHidden,\n isSelected,\n isDragging,\n isDragged,\n columnsDragged\n ) => (\n <Draggable\n draggableId={`${modelIndex}`} // draggableId requires string input\n index={visibleIndex}\n key={columnName}\n disableInteractiveElementBlocking\n >\n {provided => (\n <div\n className=\"visibility-ordering-list-item\"\n ref={provided.innerRef}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.draggableProps}\n >\n <button\n type=\"button\"\n className=\"visibility btn btn-link btn-link-icon\"\n onMouseDown={event => {\n this.handleVisibilityDraggingStart(\n modelIndex,\n isHidden\n ? VisibilityOrderingBuilder.VISIBILITY_OPTIONS.SHOW\n : VisibilityOrderingBuilder.VISIBILITY_OPTIONS.HIDE,\n event\n );\n }}\n onMouseEnter={event => {\n this.handleMouseEnter(modelIndex, event);\n }}\n onMouseUp={event => {\n this.handleVisibilityDraggingEnd(event);\n }}\n onClick={event => {\n this.handleItemClick(modelIndex, event, false);\n }}\n onKeyDown={event => {\n // trigger on keyboard enter or space keys\n if (event.key === 'Enter' || event.key === ' ') {\n this.handleVisibilityKeyDown(\n modelIndex,\n isHidden\n ? VisibilityOrderingBuilder.VISIBILITY_OPTIONS.SHOW\n : VisibilityOrderingBuilder.VISIBILITY_OPTIONS.HIDE\n );\n event.stopPropagation();\n event.preventDefault();\n }\n }}\n >\n <FontAwesomeIcon icon={isHidden ? dhEyeSlash : dhEye} />\n </button>\n <div\n role=\"menuitem\"\n tabIndex=\"0\"\n className={classNames(\n 'ordering column-item',\n {\n isSelected,\n },\n { isDragging },\n { isDragged },\n { 'two-dragged': columnsDragged === 2 },\n { 'multiple-dragged': columnsDragged > 2 }\n )}\n onClick={event => {\n this.handleItemClick(modelIndex, event);\n }}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.dragHandleProps}\n >\n <span className=\"column-name\">{columnName}</span>\n <div>\n {columnsDragged && (\n <span className=\"number-badge\">{columnsDragged}</span>\n )}\n <Tooltip>Drag to re-order</Tooltip>\n <FontAwesomeIcon icon={vsGripper} />\n </div>\n </div>\n </div>\n )}\n </Draggable>\n )\n );\n\n render() {\n const { model, userColumnWidths, onColumnVisibilityChanged } = this.props;\n const { selectedColumns, searchFilter } = this.state;\n const { columns } = model;\n const noSelection = selectedColumns.length === 0;\n const columnsToToggle = noSelection\n ? columns.map((c, i) => i).filter(i => model.isColumnMovable(i))\n : [...selectedColumns];\n const toggleToShow = GridUtils.checkAllColumnsHidden(\n columnsToToggle,\n userColumnWidths\n );\n const selectedToggleText = toggleToShow ? 'Show Selected' : 'Hide Selected';\n\n const columnItems = this.makeVisibilityOrderingList();\n\n return (\n <div\n role=\"menu\"\n className=\"visibility-ordering-builder\"\n tabIndex=\"0\"\n onMouseUp={() => {\n this.handleVisibilityDraggingEnd();\n }}\n onMouseLeave={() => {\n this.handleVisibilityDraggingEnd();\n }}\n >\n <div className=\"top-menu\">\n <button\n type=\"button\"\n className=\"btn btn-link\"\n onClick={() => {\n onColumnVisibilityChanged(\n columnsToToggle,\n toggleToShow\n ? VisibilityOrderingBuilder.VISIBILITY_OPTIONS.SHOW\n : VisibilityOrderingBuilder.VISIBILITY_OPTIONS.HIDE\n );\n }}\n >\n <FontAwesomeIcon icon={toggleToShow ? dhEyeSlash : dhEye} />\n <Tooltip>Toggle column visibility</Tooltip>\n {noSelection ? 'Toggle All' : selectedToggleText}\n </button>\n\n <div>\n <button\n type=\"button\"\n className=\"btn btn-link text-muted\"\n onClick={() => {\n this.resetVisibilityOrdering();\n }}\n >\n Reset\n <Tooltip>Reset to default</Tooltip>\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={() => {\n this.handleSortColumns(\n VisibilityOrderingBuilder.SORTING_OPTIONS.ASC\n );\n }}\n >\n <FontAwesomeIcon icon={dhSortAlphaDown} />\n <Tooltip>Sort ascending</Tooltip>\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={() => {\n this.handleSortColumns(\n VisibilityOrderingBuilder.SORTING_OPTIONS.DSC\n );\n }}\n >\n <FontAwesomeIcon icon={dhSortAlphaUp} />\n <Tooltip>Sort descending</Tooltip>\n </button>\n <span className=\"vertical-divider\" />\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={() => {\n this.handleMoveColumns(\n VisibilityOrderingBuilder.MOVE_OPTIONS.UP\n );\n }}\n disabled={noSelection}\n >\n <FontAwesomeIcon icon={vsChevronUp} />\n <Tooltip>Move selection up</Tooltip>\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={() => {\n this.handleMoveColumns(\n VisibilityOrderingBuilder.MOVE_OPTIONS.DOWN\n );\n }}\n disabled={noSelection}\n >\n <FontAwesomeIcon icon={vsChevronDown} />\n <Tooltip>Move selection down</Tooltip>\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={() => {\n this.handleMoveColumns(\n VisibilityOrderingBuilder.MOVE_OPTIONS.TOP\n );\n }}\n disabled={noSelection}\n >\n <FontAwesomeIcon icon={dhArrowToTop} />\n <Tooltip>Move selection to top</Tooltip>\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={() => {\n this.handleMoveColumns(\n VisibilityOrderingBuilder.MOVE_OPTIONS.BOTTOM\n );\n }}\n disabled={noSelection}\n >\n <FontAwesomeIcon icon={dhArrowToBottom} />\n <Tooltip>Move selection to bottom</Tooltip>\n </button>\n </div>\n </div>\n <div className=\"top-menu\">\n <SearchInput\n className=\"w-100\"\n value={searchFilter}\n matchCount={searchFilter ? selectedColumns.length : null}\n onChange={this.handleSearchInputChange}\n />\n </div>\n <DragDropContext\n onDragStart={this.handleOrderDraggingStart}\n onDragEnd={this.handleOrderDraggingEnd}\n >\n <Droppable droppableId=\"droppable-visibility-order-list\">\n {(provided, snapshot) => (\n // eslint-disable-next-line jsx-a11y/interactive-supports-focus\n <div\n role=\"menu\"\n className={classNames('visibility-ordering-list', {\n isDragging: snapshot.draggingFromThisWith,\n })}\n ref={provided.innerRef}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.droppableProps}\n >\n <div\n className=\"column-list\"\n ref={list => {\n this.list = list;\n }}\n >\n {columnItems}\n {provided.placeholder}\n </div>\n </div>\n )}\n </Droppable>\n </DragDropContext>\n </div>\n );\n }\n}\n\nVisibilityOrderingBuilder.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n movedColumns: PropTypes.arrayOf(\n PropTypes.shape({\n from: PropTypes.number,\n to: PropTypes.number,\n })\n ),\n userColumnWidths: PropTypes.instanceOf(Map).isRequired,\n onColumnVisibilityChanged: PropTypes.func,\n onMovedColumnsChanged: PropTypes.func,\n};\n\nVisibilityOrderingBuilder.defaultProps = {\n movedColumns: [],\n onColumnVisibilityChanged: () => {},\n onMovedColumnsChanged: () => {},\n};\n\nexport default VisibilityOrderingBuilder;\n","import React, { useState } from 'react';\nimport shortid from 'shortid';\n\ntype RadioGroupProps = {\n /** The radio items to populate this radio. Should be of type RadioItem. */\n children?: React.ReactElement | React.ReactElement[];\n\n /** The name to use for the radio items. If not specified, a name is automatically generated */\n name?: string;\n\n /** Triggered when a radio button is changed */\n onChange: React.ChangeEventHandler<HTMLInputElement>;\n\n /** The currently selected value. Will automatically set the `checked` attribute of the RadioItem. */\n value?: string;\n\n disabled?: boolean;\n};\n\n/**\n * A group of radio buttons. Use with RadioItems to populate, eg.\n * <RadioGroup>\n * <RadioItem .../>\n * <RadioItem .../>\n * </RadioGroup>\n */\nconst RadioGroup = (props: RadioGroupProps): JSX.Element => {\n const {\n children,\n disabled = false,\n name: propsName,\n onChange,\n value = '',\n } = props;\n const [name] = useState(propsName || shortid());\n\n // Need to use \"text\" type so we can apply a pattern and make selection properly\n return (\n <>\n {React.Children.map(children, child =>\n child\n ? React.cloneElement(child, {\n name,\n onChange: child.props.onChange || onChange,\n checked: value === child.props.value,\n disabled: child.props.disabled || disabled,\n })\n : null\n )}\n </>\n );\n};\n\nexport default RadioGroup;\n","import React, { useState } from 'react';\nimport classNames from 'classnames';\nimport shortid from 'shortid';\n\ntype RadioItemProps = {\n /** Whether this value is currently checked or not */\n checked?: boolean;\n\n /** The node/text to put in the label of this radio item */\n children: React.ReactNode;\n\n /** An extra class name to add to the outer div component */\n className?: string;\n\n /** An extra class for disabling the radio button component */\n disabled?: boolean;\n\n /** An extra class name for the input component */\n inputClassName?: string;\n\n /** The value is invalid, style to show it's invalid */\n isInvalid?: boolean;\n\n /** An extra class name for the label component */\n labelClassName?: string;\n\n /** The name for this RadioItem. Should be specified by the parent Radio component */\n name?: string;\n\n /** Triggered when the input is checked/unchecked. Provided by the parent Radio component. */\n onChange?: React.ChangeEventHandler<HTMLInputElement>;\n\n /** The value to associate with this radio item */\n value: string;\n};\n\n/**\n * A RadioItem to be used within the Radio component.\n */\nconst RadioItem = React.forwardRef<HTMLInputElement, RadioItemProps>(\n (props: RadioItemProps, ref) => {\n const {\n checked,\n children,\n className = '',\n disabled = false,\n inputClassName = '',\n isInvalid = false,\n labelClassName = '',\n name,\n onChange,\n value,\n } = props;\n\n const [id] = useState(shortid());\n\n return (\n <div className={classNames('custom-control custom-radio', className)}>\n <input\n type=\"radio\"\n id={id}\n name={name}\n ref={ref}\n className={classNames('custom-control-input', inputClassName, {\n 'is-invalid': isInvalid,\n })}\n checked={checked}\n disabled={disabled}\n value={value}\n onChange={onChange}\n />\n <label\n className={classNames('custom-control-label', labelClassName)}\n htmlFor={id}\n >\n {children}\n </label>\n </div>\n );\n }\n);\n\nRadioItem.displayName = 'RadioItem';\n\nRadioItem.defaultProps = {\n checked: undefined,\n className: '',\n disabled: false,\n inputClassName: '',\n isInvalid: false,\n labelClassName: '',\n name: undefined,\n onChange: undefined,\n};\n\nexport default RadioItem;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport ClassNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { LoadingSpinner, RadioGroup, RadioItem } from '@deephaven/components';\nimport { GridRange } from '@deephaven/grid';\nimport { vsIssues } from '@deephaven/icons';\nimport dh from '@deephaven/jsapi-shim';\nimport { TimeUtils } from '@deephaven/utils';\nimport shortid from 'shortid';\nimport IrisGridModel from '../IrisGridModel';\nimport './TableCsvExporter.scss';\n\nclass TableCsvExporter extends Component {\n static FILENAME_DATE_FORMAT = 'yyyy-MM-dd-HHmmss';\n\n static DOWNLOAD_STATUS = {\n INITIATING: 'INITIATING',\n DOWNLOADING: 'DOWNLOADING',\n FINISHED: 'FINISHED',\n CANCELED: 'CANCELED',\n };\n\n static DOWNLOAD_OPTIONS = {\n ALL_ROWS: 'ALL_ROWS',\n SELECTED_ROWS: 'SELECTED_ROWS',\n CUSTOMIZED_ROWS: 'CUSTOMIZED_ROWS',\n };\n\n static CUSTOMIZED_ROWS_OPTIONS = {\n FIRST: 'FIRST',\n LAST: 'LAST',\n };\n\n static DEFAULT_DOWNLOAD_ROWS = 100;\n\n static getDateString() {\n return dh.i18n.DateTimeFormat.format(\n TableCsvExporter.FILENAME_DATE_FORMAT,\n new Date()\n );\n }\n\n constructor(props) {\n super(props);\n\n this.handleDownloadClick = this.handleDownloadClick.bind(this);\n this.handleDownloadOptionChanged = this.handleDownloadOptionChanged.bind(\n this\n );\n this.handleCustomizedDownloadOptionChanged = this.handleCustomizedDownloadOptionChanged.bind(\n this\n );\n this.handleCustomizedDownloadRowsChanged = this.handleCustomizedDownloadRowsChanged.bind(\n this\n );\n\n const { name } = props;\n this.state = {\n fileName: `${name}-${TableCsvExporter.getDateString()}.csv`,\n\n downloadOption: TableCsvExporter.DOWNLOAD_OPTIONS.ALL_ROWS,\n customizedDownloadOption: TableCsvExporter.CUSTOMIZED_ROWS_OPTIONS.FIRST,\n customizedDownloadRows: TableCsvExporter.DEFAULT_DOWNLOAD_ROWS,\n\n errorMessage: null,\n id: shortid.generate(),\n };\n }\n\n getSnapshotRanges() {\n const { model, selectedRanges } = this.props;\n const {\n downloadOption,\n customizedDownloadOption,\n customizedDownloadRows,\n } = this.state;\n const { rowCount } = model;\n let snapshotRanges = [];\n switch (downloadOption) {\n case TableCsvExporter.DOWNLOAD_OPTIONS.ALL_ROWS:\n snapshotRanges.push(new GridRange(null, 0, null, rowCount - 1));\n break;\n case TableCsvExporter.DOWNLOAD_OPTIONS.SELECTED_ROWS:\n snapshotRanges = [...selectedRanges].sort(\n (rangeA, rangeB) => rangeA.startRow - rangeB.startRow\n );\n break;\n case TableCsvExporter.DOWNLOAD_OPTIONS.CUSTOMIZED_ROWS:\n switch (customizedDownloadOption) {\n case TableCsvExporter.CUSTOMIZED_ROWS_OPTIONS.FIRST:\n snapshotRanges.push(\n new GridRange(\n null,\n 0,\n null,\n Math.min(customizedDownloadRows - 1, rowCount - 1)\n )\n );\n break;\n case TableCsvExporter.CUSTOMIZED_ROWS_OPTIONS.LAST:\n snapshotRanges.push(\n new GridRange(\n null,\n Math.max(0, rowCount - customizedDownloadRows),\n null,\n rowCount - 1\n )\n );\n break;\n default:\n break;\n }\n break;\n default:\n break;\n }\n return snapshotRanges;\n }\n\n resetDownloadState() {\n this.setState({ errorMessage: null });\n }\n\n handleDownloadClick() {\n const {\n model,\n isDownloading,\n onDownloadStart,\n onDownload,\n onCancel,\n } = this.props;\n const { fileName } = this.state;\n\n if (isDownloading) {\n onCancel();\n return;\n }\n\n this.resetDownloadState();\n\n const snapshotRanges = this.getSnapshotRanges();\n if (this.validateOptionInput()) {\n onDownloadStart();\n model.export().then(frozenTable => {\n const tableSubscription = frozenTable.setViewport(0, 0);\n tableSubscription.getViewportData().then(() => {\n onDownload(fileName, frozenTable, tableSubscription, snapshotRanges);\n });\n });\n }\n }\n\n handleDownloadOptionChanged(event) {\n this.setState({ downloadOption: event.target.value });\n }\n\n handleCustomizedDownloadOptionChanged(event) {\n this.setState({ customizedDownloadOption: event.target.value });\n }\n\n handleCustomizedDownloadRowsChanged(event) {\n this.setState({ customizedDownloadRows: event.target.value });\n }\n\n validateOptionInput() {\n const { selectedRanges } = this.props;\n const { downloadOption, customizedDownloadRows } = this.state;\n\n if (\n downloadOption === TableCsvExporter.DOWNLOAD_OPTIONS.SELECTED_ROWS &&\n selectedRanges.length === 0\n ) {\n this.setState({\n errorMessage: (\n <p>\n <FontAwesomeIcon icon={vsIssues} /> No rows selected. Please select\n some rows in the table.\n </p>\n ),\n });\n return false;\n }\n\n if (\n downloadOption === TableCsvExporter.DOWNLOAD_OPTIONS.CUSTOMIZED_ROWS &&\n customizedDownloadRows <= 0\n ) {\n this.setState({\n errorMessage: (\n <p>\n <FontAwesomeIcon icon={vsIssues} /> Number of rows to output must be\n greater than 0\n </p>\n ),\n });\n return false;\n }\n return true;\n }\n\n render() {\n const {\n model,\n isDownloading,\n tableDownloadProgress,\n tableDownloadEstimatedTime,\n selectedRanges,\n tableDownloadStatus,\n } = this.props;\n const {\n fileName,\n downloadOption,\n customizedDownloadOption,\n customizedDownloadRows,\n errorMessage,\n id,\n } = this.state;\n const { rowCount } = model;\n return (\n <div className=\"table-csv-exporter\">\n <div className=\"section-title\">Download Rows</div>\n <div className=\"form-group\">\n <RadioGroup\n onChange={this.handleDownloadOptionChanged}\n value={downloadOption}\n disabled={isDownloading}\n >\n <RadioItem value={TableCsvExporter.DOWNLOAD_OPTIONS.ALL_ROWS}>\n All Rows\n <span className=\"text-muted ml-2\">\n {`(${rowCount\n .toString()\n .replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, '$1,')} rows)`}\n </span>\n </RadioItem>\n <RadioItem value={TableCsvExporter.DOWNLOAD_OPTIONS.SELECTED_ROWS}>\n Only Selected Rows\n <span className=\"text-muted ml-2\">\n {selectedRanges.length > 0\n ? `(${GridRange.rowCount(selectedRanges)\n .toString()\n .replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, '$1,')} rows)`\n : null}\n </span>\n </RadioItem>\n <RadioItem\n value={TableCsvExporter.DOWNLOAD_OPTIONS.CUSTOMIZED_ROWS}\n >\n <div\n className=\"radio-input-row\"\n role=\"presentation\"\n onClick={() => {\n this.setState({\n downloadOption:\n TableCsvExporter.DOWNLOAD_OPTIONS.CUSTOMIZED_ROWS,\n });\n }}\n >\n <select\n defaultValue={TableCsvExporter.DOWNLOAD_OPTIONS.FIRST}\n value={customizedDownloadOption}\n className=\"custom-select\"\n disabled={isDownloading}\n onChange={this.handleCustomizedDownloadOptionChanged}\n >\n <option value=\"FIRST\">First</option>\n <option value=\"LAST\">Last</option>\n </select>\n <input\n type=\"number\"\n className=\"form-control\"\n id={`customizedRows-${id}`}\n name={`customizedRows-${id}`}\n placeholder=\"100\"\n value={customizedDownloadRows}\n disabled={isDownloading}\n onChange={this.handleCustomizedDownloadRowsChanged}\n />\n <div>Rows</div>\n </div>\n </RadioItem>\n </RadioGroup>\n </div>\n <div className=\"form-group\">\n <label htmlFor={`customizedRows-${id}`}>File Name</label>\n <input\n type=\"text\"\n className=\"form-control\"\n id={`filename-${id}`}\n name={`filename-${id}`}\n value={fileName}\n onChange={event => {\n this.setState({ fileName: event.target.value });\n }}\n disabled={isDownloading}\n />\n </div>\n <div className=\"section-footer flex-column\">\n {errorMessage && <div className=\"error-message\">{errorMessage}</div>}\n {tableDownloadStatus && (\n <div className=\"download-status\">\n {(tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.DOWNLOADING ||\n tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.INITIATING) && (\n <>\n {tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.INITIATING && (\n <div className=\"text-muted\">Starting Download...</div>\n )}\n {tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.DOWNLOADING && (\n <div className=\"text-muted d-flex justify-content-between\">\n <span>\n {tableDownloadEstimatedTime ||\n tableDownloadEstimatedTime === 0\n ? `Estimated time: ${TimeUtils.formatElapsedTime(\n tableDownloadEstimatedTime\n )}`\n : null}\n </span>\n <span>{`${tableDownloadProgress}%`}</span>\n </div>\n )}\n </>\n )}\n {tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.FINISHED && (\n <div className=\"text-muted text-right\">Download Completed</div>\n )}\n {tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.CANCELED && (\n <div className=\"text-muted\">Download Canceled</div>\n )}\n\n {(tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.DOWNLOADING ||\n tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.INITIATING) && (\n <div className=\"progress\">\n <div\n className=\"progress-bar progress-bar-striped progress-bar-animated\"\n style={{ width: `${tableDownloadProgress}%` }}\n />\n </div>\n )}\n {tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.FINISHED && (\n <div className=\"progress\">\n <div\n className=\"progress-bar bg-success\"\n style={{ width: `${tableDownloadProgress}%` }}\n />\n </div>\n )}\n </div>\n )}\n <button\n type=\"button\"\n className={ClassNames('btn btn-primary btn-downloading', {\n 'btn-spinner btn-cancelable': isDownloading,\n })}\n onClick={this.handleDownloadClick}\n >\n {isDownloading && (\n <span>\n <LoadingSpinner />\n <span className=\"btn-normal-content\">Downloading</span>\n <span className=\"btn-hover-content\">Cancel</span>\n </span>\n )}\n {!isDownloading && 'Download'}\n </button>\n </div>\n </div>\n );\n }\n}\n\nTableCsvExporter.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n name: PropTypes.string.isRequired,\n isDownloading: PropTypes.bool,\n tableDownloadStatus: PropTypes.string,\n tableDownloadProgress: PropTypes.number,\n tableDownloadEstimatedTime: PropTypes.number,\n onDownloadStart: PropTypes.func,\n onDownload: PropTypes.func.isRequired,\n onCancel: PropTypes.func.isRequired,\n selectedRanges: PropTypes.arrayOf(PropTypes.instanceOf(GridRange)),\n};\n\nTableCsvExporter.defaultProps = {\n onDownloadStart: () => {},\n isDownloading: false,\n tableDownloadStatus: '',\n tableDownloadProgress: 0,\n tableDownloadEstimatedTime: null,\n selectedRanges: [],\n};\nexport default TableCsvExporter;\n","import * as React from 'react';\n\nfunction SvgLineIcon(\n props: JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>\n): JSX.Element {\n return (\n // eslint-disable-next-line react/jsx-props-no-spreading\n <svg width={48} height={48} xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"#C1C0C0\" d=\"M4 4h1v40H4zM44 43v1H5v-1z\" />\n <path\n stroke=\"#7DA4FF\"\n d=\"M7.984 32.44l7.982-11.378 5.273 3.739 9.952-10.838 2.826 1.894 7.45-5.802\"\n />\n <path\n stroke=\"#BECDEF\"\n d=\"M8.244 37.926L17 33.496l5 .87 10.637-10.35 10.615-1.381\"\n />\n </g>\n </svg>\n );\n}\n\nexport default SvgLineIcon;\n","import * as React from 'react';\n\nfunction SvgBarIcon(\n props: JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>\n): JSX.Element {\n return (\n // eslint-disable-next-line react/jsx-props-no-spreading\n <svg width={48} height={48} xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"#C1C0C0\" d=\"M44 43v1H4v-1z\" />\n <path\n fill=\"#7DA4FF\"\n d=\"M8 26h4v15H8zM15 17h4v24h-4zM22 21h4v20h-4zM29 17h4v24h-4zM36 11h4v30h-4z\"\n />\n </g>\n </svg>\n );\n}\n\nexport default SvgBarIcon;\n","import * as React from 'react';\n\nfunction SvgScatterIcon(\n props: JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>\n): JSX.Element {\n return (\n // eslint-disable-next-line react/jsx-props-no-spreading\n <svg width={48} height={48} xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"#C1C0C0\" d=\"M44 43v1H4v-1z\" />\n <path fill=\"#939293\" d=\"M44 34v1H4v-1zM44 25v1H4v-1zM44 16v1H4v-1z\" />\n <circle fill=\"#7DA4FF\" cx={9.5} cy={37.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={16.5} cy={30.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={22.5} cy={36.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={28.5} cy={30.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={15.5} cy={38.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={23.5} cy={25.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={19.5} cy={19.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={29.5} cy={19.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={32.5} cy={26.5} r={1.5} />\n <circle fill=\"#7DA4FF\" cx={36.5} cy={13.5} r={1.5} />\n </g>\n </svg>\n );\n}\n\nexport default SvgScatterIcon;\n","import * as React from 'react';\n\nfunction SvgPieIcon(\n props: JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>\n): JSX.Element {\n return (\n // eslint-disable-next-line react/jsx-props-no-spreading\n <svg width={48} height={48} xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n <g fill=\"none\" fillRule=\"evenodd\">\n <path\n d=\"M24 10c7.732 0 14 6.268 14 14s-6.268 14-14 14-14-6.268-14-14h14V10z\"\n fill=\"#80A6FF\"\n />\n <path d=\"M10 24c0-7.732 6.268-14 14-14v14H10z\" fill=\"#C1C0C0\" />\n </g>\n </svg>\n );\n}\n\nexport default SvgPieIcon;\n","import * as React from 'react';\n\nfunction SvgHistogramIcon(\n props: JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>\n): JSX.Element {\n return (\n // eslint-disable-next-line react/jsx-props-no-spreading\n <svg width={48} height={48} xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"#C1C0C0\" d=\"M44 43v1H4v-1z\" />\n <path\n fill=\"#7DA4FF\"\n d=\"M7 34h4v8H7zM12 31h4v11h-4zM17 27h4v15h-4zM22 22h4v20h-4zM27 27h4v15h-4zM32 29h4v13h-4zM37 31h4v11h-4z\"\n />\n </g>\n </svg>\n );\n}\n\nexport default SvgHistogramIcon;\n","import React, { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { RadioGroup, RadioItem } from '@deephaven/components';\nimport {\n vsLink,\n dhUnlink,\n dhTable,\n dhNewCircleLargeFilled,\n vsCircleLargeFilled,\n vsTrash,\n} from '@deephaven/icons';\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport shortid from 'shortid';\nimport {\n BarIcon,\n HistogramIcon,\n LineIcon,\n PieIcon,\n ScatterIcon,\n} from './icons';\nimport './ChartBuilder.scss';\nimport IrisGridModel from '../IrisGridModel';\n\nconst log = Log.module('ChartBuilder');\n\n/**\n * Form for configuring all the settings when creating a console.\n */\nclass ChartBuilder extends PureComponent {\n static types = [\n dh.plot.SeriesPlotStyle.LINE,\n dh.plot.SeriesPlotStyle.BAR,\n dh.plot.SeriesPlotStyle.SCATTER,\n dh.plot.SeriesPlotStyle.PIE,\n // IDS-6808: Disable Histogram in Chart Builder until we pipe histogram creation through the API\n // dh.plot.SeriesPlotStyle.HISTOGRAM,\n ];\n\n /**\n * Converts the provided chart type into a readable type.\n * Just replaces underscores with spaces and capitals the first letter of each word.\n */\n static getTypeName(type) {\n switch (type) {\n case dh.plot.SeriesPlotStyle.LINE:\n return 'Line';\n case dh.plot.SeriesPlotStyle.BAR:\n return 'Bar';\n case dh.plot.SeriesPlotStyle.SCATTER:\n return 'Scatter';\n case dh.plot.SeriesPlotStyle.PIE:\n return 'Pie';\n case dh.plot.SeriesPlotStyle.HISTOGRAM:\n return 'Histogram';\n default:\n return type;\n }\n }\n\n static getTypeIcon(type) {\n switch (type) {\n case dh.plot.SeriesPlotStyle.LINE:\n return <LineIcon />;\n case dh.plot.SeriesPlotStyle.BAR:\n return <BarIcon />;\n case dh.plot.SeriesPlotStyle.SCATTER:\n return <ScatterIcon />;\n case dh.plot.SeriesPlotStyle.PIE:\n return <PieIcon />;\n case dh.plot.SeriesPlotStyle.HISTOGRAM:\n return <HistogramIcon />;\n default:\n return null;\n }\n }\n\n static getMaxSeriesCount(type) {\n switch (type) {\n case dh.plot.SeriesPlotStyle.PIE:\n return 1;\n case dh.plot.SeriesPlotStyle.HISTOGRAM:\n return 0;\n default:\n return 100;\n }\n }\n\n static getXAxisLabel(type) {\n switch (type) {\n case dh.plot.SeriesPlotStyle.PIE:\n return 'Labels';\n case dh.plot.SeriesPlotStyle.HISTOGRAM:\n return 'Data';\n default:\n return 'X-Axis';\n }\n }\n\n static getSeriesLabel(type) {\n switch (type) {\n case dh.plot.SeriesPlotStyle.PIE:\n return 'Values';\n default:\n return 'Series';\n }\n }\n\n static makeSeriesItem(value) {\n return { id: shortid.generate(), value };\n }\n\n static makeDefaultSeriesItems(type, columns) {\n const maxSeriesCount = ChartBuilder.getMaxSeriesCount(type);\n if (maxSeriesCount === 0 || columns == null || columns.length === 0) {\n return [];\n }\n\n const value = columns.length > 1 ? columns[1].name : columns[0].name;\n return [ChartBuilder.makeSeriesItem(value)];\n }\n\n static getDefaultXAxis(type, columns) {\n if (columns != null && columns.length > 0) {\n return columns[0].name;\n }\n\n return null;\n }\n\n constructor(props) {\n super(props);\n\n this.handleAddSeries = this.handleAddSeries.bind(this);\n this.handleLinkStateChange = this.handleLinkStateChange.bind(this);\n this.handleReset = this.handleReset.bind(this);\n this.handleSeriesChange = this.handleSeriesChange.bind(this);\n this.handleSeriesDeleteClick = this.handleSeriesDeleteClick.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleTypeClick = this.handleTypeClick.bind(this);\n this.handleXAxisChange = this.handleXAxisChange.bind(this);\n\n const { model } = props;\n const { columns } = model;\n\n const type = ChartBuilder.types[0];\n const xAxis = ChartBuilder.getDefaultXAxis(type, columns);\n const seriesItems = ChartBuilder.makeDefaultSeriesItems(type, columns);\n\n this.state = {\n /** The selected chart type */\n type,\n\n /** Array of column names of the series to display */\n seriesItems,\n\n /** The column name to use as the x-axis */\n xAxis,\n\n /** Whether the newly created chart should be linked with the table (update when filters update) */\n isLinked: true,\n };\n }\n\n handleAddSeries() {\n this.setState(\n state => {\n let { seriesItems } = state;\n seriesItems = [].concat(seriesItems);\n\n const { model } = this.props;\n const { columns } = model;\n seriesItems.push({\n id: shortid.generate(),\n value: columns[0].name,\n });\n\n return { seriesItems };\n },\n () => {\n this.sendChange();\n }\n );\n }\n\n handleLinkStateChange(event) {\n this.setState({ isLinked: event.target.value === 'true' });\n }\n\n handleReset() {\n const { model } = this.props;\n const { columns } = model;\n\n const type = ChartBuilder.types[0];\n const xAxis = ChartBuilder.getDefaultXAxis(type, columns);\n const seriesItems = ChartBuilder.makeDefaultSeriesItems(type, columns);\n const isLinked = true;\n\n this.setState({ type, seriesItems, xAxis, isLinked }, () => {\n this.sendChange();\n });\n }\n\n handleSeriesChange(event) {\n const { value } = event.target;\n const index = event.target.getAttribute('data-index');\n\n this.setState(\n state => {\n let { seriesItems } = state;\n\n seriesItems = [].concat(seriesItems);\n seriesItems[index].value = value;\n\n return { seriesItems };\n },\n () => {\n this.sendChange();\n }\n );\n }\n\n handleSeriesDeleteClick(event) {\n const index = event.target.getAttribute('data-index');\n\n this.setState(\n state => {\n let { seriesItems } = state;\n\n seriesItems = [].concat(seriesItems);\n seriesItems.splice(index, 1);\n\n return { seriesItems };\n },\n () => {\n this.sendChange();\n }\n );\n }\n\n handleSubmit(event) {\n event.preventDefault();\n\n const { onSubmit } = this.props;\n const { type, seriesItems, xAxis, isLinked } = this.state;\n const series = seriesItems.map(item => item.value);\n onSubmit({ type, series, xAxis, isLinked });\n }\n\n handleTypeClick(event) {\n const index = event.target.getAttribute('data-index');\n const type = ChartBuilder.types[index];\n\n log.debug2('handleTypeSelect', type);\n\n this.setState(\n state => {\n const maxSeriesCount = ChartBuilder.getMaxSeriesCount(type);\n let { seriesItems } = state;\n seriesItems = seriesItems.slice(0, maxSeriesCount);\n if (seriesItems.length === 0 && maxSeriesCount > 0) {\n const { model } = this.props;\n const { columns } = model;\n seriesItems = ChartBuilder.makeDefaultSeriesItems(type, columns);\n }\n\n return { type, seriesItems };\n },\n () => {\n this.sendChange();\n }\n );\n }\n\n handleXAxisChange(event) {\n const xAxis = event.target.value;\n log.debug2('x-axis change', xAxis);\n\n this.setState({ xAxis }, () => {\n this.sendChange();\n });\n }\n\n sendChange() {\n const { onChange } = this.props;\n const { isLinked, type, seriesItems, xAxis } = this.state;\n const series = seriesItems.map(item => item.value);\n\n onChange({ type, series, xAxis, isLinked });\n }\n\n render() {\n const { model } = this.props;\n const { columns } = model;\n const { seriesItems, type, xAxis, isLinked } = this.state;\n const maxSeriesCount = ChartBuilder.getMaxSeriesCount(type);\n const xAxisLabel = ChartBuilder.getXAxisLabel(type);\n const seriesLabel = ChartBuilder.getSeriesLabel(type);\n const isSeriesVisible = seriesItems.length > 0;\n const isAddSeriesVisible = seriesItems.length < maxSeriesCount;\n\n return (\n <div className=\"chart-builder\">\n <form onSubmit={this.handleSubmit}>\n <div className=\"form-row\">\n <label>Select Chart Type</label>\n <div className=\"form-row\">\n {ChartBuilder.types.map((chartType, index) => (\n <div key={chartType} className=\"col col-chart-type\">\n <button\n type=\"button\"\n className={classNames('btn', 'btn-icon', 'btn-chart-type', {\n active: chartType === type,\n })}\n data-index={index}\n onClick={this.handleTypeClick}\n >\n {ChartBuilder.getTypeIcon(chartType)}\n {ChartBuilder.getTypeName(chartType)}\n </button>\n </div>\n ))}\n </div>\n </div>\n <hr />\n <div className=\"form-row form-inline\">\n <label className=\"col-2 label-left\">{xAxisLabel}</label>\n <select\n className=\"form-control custom-select select-x-axis col\"\n value={xAxis}\n onChange={this.handleXAxisChange}\n >\n {columns.map(column => (\n <option key={column.name} value={column.name}>\n {column.name}\n </option>\n ))}\n </select>\n </div>\n {isSeriesVisible && <hr />}\n {seriesItems.map((seriesItem, i) => (\n <div\n className=\"form-row form-inline form-series-item\"\n key={seriesItem.id}\n >\n <label className=\"col-2 label-left\">\n {i === 0 ? seriesLabel : ''}\n </label>\n <select\n className=\"form-control custom-select select-series col\"\n value={seriesItem.value}\n onChange={this.handleSeriesChange}\n data-index={i}\n >\n {columns.map(column => (\n <option key={column.name} value={column.name} data-index={i}>\n {column.name}\n </option>\n ))}\n </select>\n {seriesItems.length > 1 && (\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon btn-delete-series ml-2 px-2\"\n data-index={i}\n onClick={this.handleSeriesDeleteClick}\n >\n <FontAwesomeIcon icon={vsTrash} />\n </button>\n )}\n </div>\n ))}\n {isAddSeriesVisible && (\n <div className=\"form-row\">\n <div className=\"col-2\" />\n <button\n type=\"button\"\n className=\"btn btn-link btn-add-series mt-1\"\n onClick={this.handleAddSeries}\n >\n <FontAwesomeIcon icon={dhNewCircleLargeFilled} />\n Add Series\n </button>\n </div>\n )}\n <div className=\"form-row chart-builder-link\">\n <label className=\"col-2 label-right\">\n <div className=\"fa-md fa-layers\">\n <FontAwesomeIcon\n mask={dhTable}\n icon={vsCircleLargeFilled}\n transform=\"right-5 down-5\"\n />\n <FontAwesomeIcon\n icon={isLinked ? vsLink : dhUnlink}\n transform=\"grow-2 right-8 down-6\"\n />\n </div>\n </label>\n <RadioGroup\n onChange={this.handleLinkStateChange}\n value={`${isLinked}`}\n >\n <RadioItem value=\"true\">Sync State</RadioItem>\n <RadioItem value=\"false\">Freeze State</RadioItem>\n </RadioGroup>\n </div>\n <div className=\"form-row\">\n <div className=\"col-2 label-right\" />\n <div className=\"col chart-builder-link-info\">\n {isLinked\n ? 'Charts with synced state will update to match any filters or user modifications applied to the parent table.'\n : 'Freeze State disconnects the chart state from the parent table. New filters or user modifications on the parent table will not be applied.'}\n </div>\n </div>\n <div\n className={classNames('form-row', 'justify-content-end', 'my-3')}\n >\n <button\n type=\"button\"\n className=\"btn btn-outline-primary btn-reset\"\n onClick={this.handleReset}\n >\n Reset\n </button>\n <button type=\"submit\" className=\"btn btn-primary btn-submit\">\n Create\n </button>\n </div>\n </form>\n </div>\n );\n }\n}\n\nChartBuilder.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n onSubmit: PropTypes.func.isRequired,\n onChange: PropTypes.func.isRequired,\n};\n\nexport default ChartBuilder;\n","import flatten from 'lodash.flatten';\n\ntype Range = [number, number];\n\nclass DragUtils {\n /**\n * Re-orders the provided item lists in place based on the selectedRanges and destinationIndex provided\n * @param sourceList Array of the source items\n * @param selectedRanges Array of the selected ranges in the source list\n * @param destinationList Destination items. If dragging within the same list, set it to sourceItems\n * @param destinationIndex The index items are being dropped in the destinationList, adjusted for the removed items\n * @returns The items that were dragged\n */\n static reorder<T>(\n sourceList: T[],\n selectedRanges: Range[],\n destinationList: T[],\n destinationIndex: number\n ): T[] {\n const insertIndex =\n sourceList === destinationList\n ? DragUtils.adjustDestinationIndex(destinationIndex, selectedRanges)\n : destinationIndex;\n const draggedItems = DragUtils.removeItems(sourceList, selectedRanges);\n destinationList.splice(insertIndex, 0, ...draggedItems);\n return draggedItems;\n }\n\n /**\n * Removes the provided ranges from the list in place\n * @param list Array of items to remove the ranges.\n * @param ranges Array of the ranges to remove.\n * @returns The removed items, in the order of the ranges removed.\n */\n static removeItems<T>(list: T[], ranges: Range[]): T[] {\n const items = [];\n\n // Sort them in reverse, so we don't screw up the range indexes\n const sortedRanges = ranges\n .map((range, index) => ({ range, index }))\n .sort((a, b) => b.range[0] - a.range[0]);\n for (let i = 0; i < sortedRanges.length; i += 1) {\n const { range, index } = sortedRanges[i];\n const [start, end] = range;\n items[index] = list.splice(start, end - start + 1);\n }\n\n return flatten(items);\n }\n\n /**\n * Adjusts the destination index for when dropping into the same list you're dragging from.\n * @param destinationIndex The original destination index\n * @param ranges The ranges that are moving\n * @returns Index where item should be inserted after all ranges are removed\n */\n static adjustDestinationIndex(\n destinationIndex: number,\n ranges: Range[]\n ): number {\n let adjustedIndex = destinationIndex;\n for (let i = 0; i < ranges.length; i += 1) {\n const [start, end] = ranges[i];\n if (start > destinationIndex) {\n break;\n }\n\n adjustedIndex -= Math.min(end, destinationIndex - 1) - start + 1;\n }\n return adjustedIndex;\n }\n\n static startDragging(): void {\n document.documentElement.classList.add('drag-pointer-events-none');\n }\n\n static stopDragging(): void {\n document.documentElement.classList.remove('drag-pointer-events-none');\n }\n}\n\nexport default DragUtils;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';\nimport classNames from 'classnames';\nimport './InputEditor.scss';\n\n/**\n * A monaco editor that looks like an general input\n */\n\nexport default class InputEditor extends Component {\n constructor(props) {\n super(props);\n\n this.handleContentChanged = this.handleContentChanged.bind(this);\n this.handleEditorFocus = this.handleEditorFocus.bind(this);\n this.handleEditorBlur = this.handleEditorBlur.bind(this);\n this.handleContainerClick = this.handleContainerClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n\n this.state = {\n isEditorFocused: false,\n isEditorEmpty: true,\n };\n this.editorContainer = null;\n this.editor = null;\n }\n\n componentDidMount() {\n this.initEditor();\n }\n\n componentWillUnmount() {\n this.destroyEditor();\n }\n\n initEditor() {\n const { value, editorSettings } = this.props;\n const inputEditorSettings = {\n copyWithSyntaxHighlighting: 'false',\n fixedOverflowWidgets: true,\n folding: false,\n fontFamily: 'Fira Mono',\n glyphMargin: false,\n language: 'groovyDB',\n lineDecorationsWidth: 8,\n lineNumbers: 'off',\n minimap: { enabled: false },\n renderLineHighlight: 'none',\n scrollbar: {\n arrowSize: 0,\n horizontal: 'hidden',\n horizontalScrollbarSize: 0,\n },\n scrollBeyondLastLine: false,\n padding: {\n top: 6,\n bottom: 6,\n },\n tabCompletion: 'off',\n useTabStops: true,\n value,\n wordWrap: 'on',\n automaticLayout: true,\n ...editorSettings,\n };\n this.editor = monaco.editor.create(\n this.editorContainer,\n inputEditorSettings\n );\n this.editor.layout();\n\n // disable tab to spaces in this editor to improve tab navigation\n this.editor.getModel().updateOptions({ tabSize: 0 });\n\n this.editor.onDidChangeModelContent(this.handleContentChanged);\n this.editor.onDidFocusEditorText(this.handleEditorFocus);\n this.editor.onDidBlurEditorText(this.handleEditorBlur);\n }\n\n destroyEditor() {\n this.editor.dispose();\n this.editor = null;\n }\n\n handleContentChanged() {\n const { onContentChanged } = this.props;\n const value = this.editor.getModel().getValue();\n this.setState({ isEditorEmpty: value.length === 0 });\n\n onContentChanged(value);\n }\n\n handleEditorFocus() {\n this.setState({ isEditorFocused: true });\n }\n\n handleEditorBlur() {\n const value = this.editor.getModel().getValue();\n this.setState({\n isEditorEmpty: value.length === 0,\n isEditorFocused: false,\n });\n }\n\n // force editor to focus if clicked\n handleContainerClick() {\n const { isEditorFocused } = this.state;\n if (isEditorFocused) {\n return;\n }\n this.editor.focus();\n }\n\n handleKeyDown(event) {\n const { onTab, editorIndex } = this.props;\n if (event.key === 'Tab') {\n onTab(editorIndex, event.shiftKey);\n }\n }\n\n render() {\n const { value, invalid } = this.props;\n const { isEditorFocused, isEditorEmpty } = this.state;\n return (\n <div\n className={classNames('input-editor-wrapper', {\n focused: isEditorFocused,\n invalid,\n })}\n onKeyDown={this.handleKeyDown}\n role=\"presentation\"\n onClick={this.handleContainerClick}\n >\n <div\n className=\"editor-container\"\n ref={editorContainer => {\n this.editorContainer = editorContainer;\n }}\n />\n {isEditorEmpty && !value && (\n <div className=\"editor-placeholder text-muted\">Column Formula</div>\n )}\n </div>\n );\n }\n}\n\nInputEditor.propTypes = {\n value: PropTypes.string,\n onContentChanged: PropTypes.func,\n editorSettings: PropTypes.shape({}),\n editorIndex: PropTypes.number,\n onTab: PropTypes.func,\n invalid: PropTypes.bool,\n};\n\nInputEditor.defaultProps = {\n value: '',\n onContentChanged: () => {},\n editorSettings: {},\n editorIndex: 0,\n onTab: () => {},\n invalid: false,\n};\n","import React, { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { Draggable } from 'react-beautiful-dnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { Tooltip } from '@deephaven/components';\nimport { vsTrash, vsGripper } from '@deephaven/icons';\nimport InputEditor from './InputEditor';\n\nclass CustomColumnInput extends PureComponent {\n static INPUT_TYPE = {\n NAME: 'name',\n FORMULA: 'formula',\n };\n\n constructor(props) {\n super(props);\n this.handleFormulaEditorContentChanged = this.handleFormulaEditorContentChanged.bind(\n this\n );\n\n this.editorContainer = null;\n this.formulaEditor = null;\n }\n\n handleFormulaEditorContentChanged(formulaValue) {\n const { onChange, eventKey } = this.props;\n formulaValue.replace(/(\\r\\n|\\n|\\r)/gm, ''); // remove line break\n onChange(eventKey, CustomColumnInput.INPUT_TYPE.FORMULA, formulaValue);\n }\n\n render() {\n const {\n eventKey,\n name,\n formula,\n onChange,\n onDeleteColumn,\n inputIndex,\n onTabInEditor,\n invalid,\n } = this.props;\n return (\n <Draggable\n draggableId={eventKey}\n index={inputIndex}\n disableInteractiveElementBlocking\n >\n {(provided, snapshot) => (\n <div\n className={classNames('draggable-container', {\n dragging: snapshot.isDragging,\n })}\n ref={provided.innerRef}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.draggableProps}\n >\n <div className=\"custom-column-input-container\">\n <div className=\"d-flex flex-row pb-3 custom-column-name\">\n <input\n className={classNames('form-control custom-column-input', {\n 'is-invalid': invalid,\n })}\n placeholder=\"Column Name\"\n value={name}\n onChange={event => {\n onChange(\n eventKey,\n CustomColumnInput.INPUT_TYPE.NAME,\n event.target.value\n );\n }}\n />\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon ml-1 px-2\"\n onClick={() => {\n onDeleteColumn(eventKey);\n }}\n >\n <Tooltip>Delete custom column</Tooltip>\n <FontAwesomeIcon icon={vsTrash} />\n </button>\n\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon px-2 btn-drag-handle\"\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.dragHandleProps}\n >\n <Tooltip>Drag column to re-order</Tooltip>\n <FontAwesomeIcon icon={vsGripper} />\n </button>\n </div>\n <InputEditor\n editorSettings={{ language: 'deephavenDb' }}\n editorIndex={inputIndex}\n value={formula}\n onContentChanged={this.handleFormulaEditorContentChanged}\n onTab={onTabInEditor}\n invalid={invalid}\n />\n </div>\n <hr />\n </div>\n )}\n </Draggable>\n );\n }\n}\n\nCustomColumnInput.propTypes = {\n eventKey: PropTypes.string.isRequired,\n inputIndex: PropTypes.number,\n name: PropTypes.string,\n formula: PropTypes.string,\n onChange: PropTypes.func,\n onDeleteColumn: PropTypes.func,\n onTabInEditor: PropTypes.func,\n invalid: PropTypes.bool,\n};\n\nCustomColumnInput.defaultProps = {\n name: '',\n inputIndex: 0,\n formula: '',\n onChange: () => {},\n onDeleteColumn: () => {},\n onTabInEditor: () => {},\n invalid: false,\n};\n\nexport default CustomColumnInput;\n","import React, { Component } from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport shortid from 'shortid';\nimport memoize from 'memoize-one';\nimport { DragDropContext, Droppable } from 'react-beautiful-dnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { DragUtils, LoadingSpinner } from '@deephaven/components';\nimport { dhNewCircleLargeFilled, vsIssues, vsPass } from '@deephaven/icons';\nimport CustomColumnInput from './CustomColumnInput';\nimport './CustomColumnBuilder.scss';\nimport IrisGridModel from '../IrisGridModel';\n\nclass CustomColumnBuilder extends Component {\n static SUCCESS_SHOW_DURATION = 750;\n\n static makeCustomColumnInputEventKey() {\n return shortid.generate();\n }\n\n static createCustomColumnInput() {\n return {\n eventKey: shortid.generate(),\n name: '',\n formula: '',\n };\n }\n\n constructor(props) {\n super(props);\n\n this.handleAddColumnClick = this.handleAddColumnClick.bind(this);\n this.handleSaveClick = this.handleSaveClick.bind(this);\n this.handleInputChange = this.handleInputChange.bind(this);\n this.handleDeleteColumn = this.handleDeleteColumn.bind(this);\n this.handleCustomColumnUpdated = this.handleCustomColumnUpdated.bind(this);\n this.handleRequestFailed = this.handleRequestFailed.bind(this);\n this.handleDragEnd = this.handleDragEnd.bind(this);\n this.resetRequestFailed = this.resetRequestFailed.bind(this);\n\n this.handleEditorTabNavigation = this.handleEditorTabNavigation.bind(this);\n\n this.state = {\n inputs: [],\n isCustomColumnApplying: false,\n errorMessage: null,\n hasRequestFailed: false,\n isSuccessShowing: false,\n };\n this.container = null;\n this.successButtonTimer = null;\n }\n\n componentDidMount() {\n const { customColumns } = this.props;\n this.parseCustomColumns(customColumns);\n this.startListening();\n }\n\n componentWillUnmount() {\n this.stopListening();\n if (this.messageTimer) {\n clearTimeout(this.messageTimer);\n }\n if (this.successButtonTimer) {\n clearTimeout(this.successButtonTimer);\n }\n }\n\n getInput = memoize((inputs, key) =>\n inputs.find(input => input.eventKey === key)\n );\n\n getInputIndex = memoize((inputs, key) =>\n inputs.findIndex(input => input.eventKey === key)\n );\n\n resetErrorMessage() {\n this.setState({ errorMessage: null });\n }\n\n startListening() {\n const { model } = this.props;\n model.addEventListener(\n IrisGridModel.EVENT.COLUMNS_CHANGED,\n this.handleCustomColumnUpdated\n );\n model.addEventListener(\n IrisGridModel.EVENT.UPDATED,\n this.handleCustomColumnUpdated\n );\n model.addEventListener(\n IrisGridModel.EVENT.REQUEST_FAILED,\n this.handleRequestFailed\n );\n }\n\n stopListening() {\n const { model } = this.props;\n model.removeEventListener(\n IrisGridModel.EVENT.COLUMNS_CHANGED,\n this.handleCustomColumnUpdated\n );\n model.removeEventListener(\n IrisGridModel.EVENT.UPDATED,\n this.handleCustomColumnUpdated\n );\n model.removeEventListener(\n IrisGridModel.EVENT.REQUEST_FAILED,\n this.handleRequestFailed\n );\n }\n\n parseCustomColumns(customColumns) {\n if (customColumns.length > 0) {\n const customColumnInputs = customColumns.map(customColumn => {\n const input = customColumn.split(/=(.+)/, 2);\n return {\n eventKey: CustomColumnBuilder.makeCustomColumnInputEventKey(),\n name: input[0],\n formula: input[1],\n };\n });\n this.setState({ inputs: customColumnInputs });\n } else {\n this.setState({\n inputs: [CustomColumnBuilder.createCustomColumnInput()],\n });\n }\n }\n\n handleAddColumnClick() {\n const { inputs } = this.state;\n const newInputs = [...inputs];\n newInputs.push(CustomColumnBuilder.createCustomColumnInput());\n this.setState({\n inputs: newInputs,\n });\n }\n\n handleDeleteColumn(eventKey) {\n const { inputs } = this.state;\n const customColumnIndex = this.getInputIndex(inputs, eventKey);\n const newInputs = [...inputs];\n newInputs.splice(customColumnIndex, 1);\n if (newInputs.length === 0) {\n newInputs.push(CustomColumnBuilder.createCustomColumnInput());\n }\n this.setState({\n inputs: newInputs,\n });\n }\n\n handleInputChange(eventKey, type, value) {\n const { inputs } = this.state;\n const customColumnIndex = this.getInputIndex(inputs, eventKey);\n const customColumnInput = this.getInput(inputs, eventKey);\n\n const newCustomInput = { ...customColumnInput };\n newCustomInput[type] = value;\n\n const newInputs = [...inputs];\n newInputs.splice(customColumnIndex, 1, newCustomInput);\n this.setState({\n inputs: newInputs,\n });\n }\n\n handleCustomColumnUpdated() {\n const { isCustomColumnApplying } = this.state;\n if (!isCustomColumnApplying) {\n return;\n }\n this.setState(\n { isCustomColumnApplying: false, isSuccessShowing: true },\n () => {\n this.successButtonTimer = setTimeout(\n () => this.setState({ isSuccessShowing: false }),\n CustomColumnBuilder.SUCCESS_SHOW_DURATION\n );\n }\n );\n }\n\n handleRequestFailed(event) {\n const { isCustomColumnApplying } = this.state;\n if (!isCustomColumnApplying) {\n return;\n }\n\n this.setState({\n isCustomColumnApplying: false,\n errorMessage: (\n <>\n <p>\n <FontAwesomeIcon icon={vsIssues} /> Failed to apply custom columns.\n </p>\n <div className=\"error-box\">\n {event.detail.errorMessage}\n <br />\n Table configuration: {JSON.stringify(event.detail.configuration)}\n </div>\n </>\n ),\n hasRequestFailed: true,\n });\n }\n\n handleDragEnd(result) {\n DragUtils.stopDragging();\n\n // if dropped outside the list\n if (!result.destination) {\n return;\n }\n const { inputs } = this.state;\n const sourceIndex = result.source.index;\n const destinationIndex = result.destination.index;\n const newInputs = [...inputs];\n const sourceInput = inputs[sourceIndex];\n\n newInputs.splice(sourceIndex, 1);\n newInputs.splice(destinationIndex, 0, sourceInput);\n\n this.setState({ inputs: newInputs });\n }\n\n handleEditorTabNavigation(focusEditorIndex, shiftKey) {\n const { inputs } = this.state;\n // focus on drag handle\n if (shiftKey) {\n this.container\n .querySelectorAll(`.btn-drag-handle`) // eslint-disable-next-line no-unexpected-multiline\n [focusEditorIndex].focus();\n return;\n }\n if (focusEditorIndex === inputs.length - 1) {\n // focus on add another column button\n this.container.querySelector('.btn-add-column').focus();\n } else {\n // focus on next column name input\n const nextFocusIndex = focusEditorIndex + 1;\n this.container\n .querySelectorAll('.custom-column-input') // eslint-disable-next-line no-unexpected-multiline\n [nextFocusIndex].focus();\n }\n }\n\n handleSaveClick() {\n const { onSave } = this.props;\n const { inputs, isCustomColumnApplying } = this.state;\n if (isCustomColumnApplying) {\n return;\n }\n const customColumns = [];\n inputs.forEach(input => {\n const { name, formula } = input;\n if (name && formula) {\n customColumns.push(`${name}=${formula}`);\n }\n });\n this.resetErrorMessage();\n this.setState({ isCustomColumnApplying: true });\n onSave(customColumns);\n }\n\n resetRequestFailed() {\n this.setState(({ hasRequestFailed }) => {\n if (hasRequestFailed) {\n return { hasRequestFailed: false };\n }\n return null;\n });\n }\n\n renderInputs() {\n const { inputs, hasRequestFailed } = this.state;\n\n return inputs.map((input, index) => {\n const { eventKey, name, formula } = input;\n return (\n <CustomColumnInput\n key={eventKey}\n inputIndex={index}\n eventKey={eventKey}\n name={name}\n formula={formula}\n onChange={this.handleInputChange}\n onDeleteColumn={this.handleDeleteColumn}\n onTabInEditor={this.handleEditorTabNavigation}\n invalid={hasRequestFailed}\n />\n );\n });\n }\n\n renderSaveButton() {\n const { inputs, isCustomColumnApplying, isSuccessShowing } = this.state;\n const saveText = inputs.length > 1 ? 'Save Columns' : 'Save Column';\n\n return (\n <button\n type=\"button\"\n className={classNames(\n 'btn btn-apply',\n {\n 'btn-spinner': isCustomColumnApplying,\n },\n isSuccessShowing ? 'btn-success' : 'btn-primary'\n )}\n disabled={isSuccessShowing || isCustomColumnApplying}\n onClick={this.handleSaveClick}\n >\n {isCustomColumnApplying && (\n <span>\n <LoadingSpinner />\n <span className=\"btn-normal-content\">Applying</span>\n <span className=\"btn-hover-content\">Applying</span>\n </span>\n )}\n {!isSuccessShowing && !isCustomColumnApplying && saveText}\n {isSuccessShowing && (\n <>\n <FontAwesomeIcon icon={vsPass} /> Success\n </>\n )}\n </button>\n );\n }\n\n render() {\n const { onCancel } = this.props;\n const { errorMessage } = this.state;\n return (\n <div\n role=\"presentation\"\n className=\"custom-column-builder-container\"\n ref={container => {\n this.container = container;\n }}\n onClick={this.resetRequestFailed}\n onFocus={this.resetRequestFailed}\n >\n <div className=\"section-title\">Custom Column Name and Formula</div>\n <hr />\n <DragDropContext\n onDragStart={DragUtils.startDragging}\n onDragEnd={this.handleDragEnd}\n >\n <Droppable droppableId=\"droppable-custom-columns\">\n {(provided, snapshot) => (\n <div\n ref={provided.innerRef}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.droppableProps}\n className={classNames('droppable-container', {\n dragging: snapshot.draggingFromThisWith,\n })}\n >\n {this.renderInputs()}\n {provided.placeholder}\n </div>\n )}\n </Droppable>\n </DragDropContext>\n\n <div className=\"pt-1 px-3\">\n <button\n type=\"button\"\n className=\"btn btn-link btn-add-column\"\n onClick={this.handleAddColumnClick}\n >\n <FontAwesomeIcon icon={dhNewCircleLargeFilled} />\n Add Another Column\n </button>\n </div>\n\n <div className=\"custom-column-builder-footer\">\n {errorMessage && <div className=\"error-message\">{errorMessage}</div>}\n\n <div className=\"d-flex justify-content-end\">\n <button\n type=\"button\"\n className=\"btn btn-outline-primary mr-2\"\n onClick={onCancel}\n >\n Cancel\n </button>\n {this.renderSaveButton()}\n </div>\n </div>\n </div>\n );\n }\n}\n\nCustomColumnBuilder.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n customColumns: PropTypes.arrayOf(PropTypes.string),\n onSave: PropTypes.func,\n onCancel: PropTypes.func,\n};\n\nCustomColumnBuilder.defaultProps = {\n customColumns: [],\n onSave: () => {},\n onCancel: () => {},\n};\n\nexport default CustomColumnBuilder;\n","import React, { Component } from 'react';\nimport classNames from 'classnames';\nimport './ItemListItem.scss';\nimport Log from '@deephaven/log';\n\nconst log = Log.module('ItemListItem');\n\ninterface ItemListItemProps {\n isDraggable: boolean;\n isFocused: boolean;\n isSelected: boolean;\n itemIndex: number;\n disableSelect: boolean;\n onBlur(index: number, e: React.FocusEvent<HTMLDivElement>): void;\n onClick(index: number, e: React.MouseEvent<HTMLDivElement>): void;\n onContextMenu(index: number, e: React.MouseEvent<HTMLDivElement>): void;\n onDragStart(index: number, e: React.DragEvent<HTMLDivElement>): void;\n onDrag(index: number, e: React.DragEvent<HTMLDivElement>): void;\n onDragOver(index: number, e: React.DragEvent<HTMLDivElement>): void;\n onDragEnd(index: number, e: React.DragEvent<HTMLDivElement>): void;\n onDrop(index: number, e: React.DragEvent<HTMLDivElement>): void;\n onDoubleClick(index: number, e: React.MouseEvent<HTMLDivElement>): void;\n onFocus(index: number, e: React.FocusEvent<HTMLDivElement>): void;\n onMouseDown(index: number, e: React.MouseEvent<HTMLDivElement>): void;\n onMouseMove(index: number, e: React.MouseEvent<HTMLDivElement>): void;\n onMouseUp(index: number, e: React.MouseEvent<HTMLDivElement>): void;\n style: React.CSSProperties;\n children: React.ReactNode;\n}\n\nclass ItemListItem extends Component<ItemListItemProps, Record<string, never>> {\n static defaultProps = {\n children: null,\n isDraggable: false,\n isFocused: false,\n isSelected: false,\n itemIndex: 0,\n disableSelect: false,\n\n onBlur(): void {\n // no-op\n },\n onClick(): void {\n // no-op\n },\n onContextMenu(): void {\n // no-op\n },\n onDragStart(): void {\n // no-op\n },\n onDrag(): void {\n // no-op\n },\n onDragOver(): void {\n // no-op\n },\n onDragEnd(): void {\n // no-op\n },\n onDrop(): void {\n // no-op\n },\n onDoubleClick(): void {\n // no-op\n },\n onFocus(): void {\n // no-op\n },\n onMouseDown(): void {\n // no-op\n },\n onMouseMove(): void {\n // no-op\n },\n onMouseUp(): void {\n // no-op\n },\n style: {},\n };\n\n static handleKeyDown(): boolean {\n log.log('ItemListItem.handleKeyDown false');\n return false;\n }\n\n constructor(props: ItemListItemProps) {\n super(props);\n\n this.handleBlur = this.handleBlur.bind(this);\n this.handleFocus = this.handleFocus.bind(this);\n this.handleClick = this.handleClick.bind(this);\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleDragStart = this.handleDragStart.bind(this);\n this.handleDrag = this.handleDrag.bind(this);\n this.handleDragOver = this.handleDragOver.bind(this);\n this.handleDragEnd = this.handleDragEnd.bind(this);\n this.handleDrop = this.handleDrop.bind(this);\n this.handleDoubleClick = this.handleDoubleClick.bind(this);\n this.handleMouseDown = this.handleMouseDown.bind(this);\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleMouseUp = this.handleMouseUp.bind(this);\n\n this.itemRef = React.createRef();\n }\n\n itemRef: React.RefObject<HTMLDivElement>;\n\n handleBlur(e: React.FocusEvent<HTMLDivElement>): void {\n const { itemIndex, onBlur } = this.props;\n onBlur(itemIndex, e);\n }\n\n handleFocus(e: React.FocusEvent<HTMLDivElement>): void {\n const { itemIndex, onFocus } = this.props;\n onFocus(itemIndex, e);\n }\n\n handleClick(e: React.MouseEvent<HTMLDivElement>): void {\n const { itemIndex, onClick } = this.props;\n onClick(itemIndex, e);\n }\n\n handleContextMenu(e: React.MouseEvent<HTMLDivElement>): void {\n const { itemIndex, onContextMenu } = this.props;\n onContextMenu(itemIndex, e);\n }\n\n handleDragStart(e: React.DragEvent<HTMLDivElement>): void {\n const { itemIndex, onDragStart } = this.props;\n onDragStart(itemIndex, e);\n }\n\n handleDrag(e: React.DragEvent<HTMLDivElement>): void {\n const { itemIndex, onDrag } = this.props;\n onDrag(itemIndex, e);\n }\n\n handleDragOver(e: React.DragEvent<HTMLDivElement>): void {\n // Have to call preventDefault otherwise onDrop won't get triggered\n e.preventDefault();\n const { itemIndex, onDragOver } = this.props;\n onDragOver(itemIndex, e);\n }\n\n handleDragEnd(e: React.DragEvent<HTMLDivElement>): void {\n const { itemIndex, onDragEnd } = this.props;\n onDragEnd(itemIndex, e);\n }\n\n handleDrop(e: React.DragEvent<HTMLDivElement>): void {\n const { itemIndex, onDrop } = this.props;\n onDrop(itemIndex, e);\n }\n\n handleDoubleClick(e: React.MouseEvent<HTMLDivElement>): void {\n const { itemIndex, onDoubleClick } = this.props;\n onDoubleClick(itemIndex, e);\n }\n\n handleMouseMove(e: React.MouseEvent<HTMLDivElement>): void {\n const { itemIndex, onMouseMove } = this.props;\n onMouseMove(itemIndex, e);\n }\n\n handleMouseDown(e: React.MouseEvent<HTMLDivElement>): void {\n const { itemIndex, onMouseDown } = this.props;\n onMouseDown(itemIndex, e);\n }\n\n handleMouseUp(e: React.MouseEvent<HTMLDivElement>): void {\n const { itemIndex, onMouseUp } = this.props;\n onMouseUp(itemIndex, e);\n }\n\n render(): JSX.Element {\n const { isDraggable, isFocused, isSelected, style, children } = this.props;\n return (\n <div\n className={classNames(\n 'item-list-item',\n { active: isSelected },\n { 'is-focused': isFocused },\n { 'is-draggable': isDraggable }\n )}\n onKeyDown={ItemListItem.handleKeyDown}\n onContextMenu={this.handleContextMenu}\n onClick={this.handleClick}\n onDrag={this.handleDrag}\n onDragStart={this.handleDragStart}\n onDragOver={this.handleDragOver}\n onDragEnd={this.handleDragEnd}\n onDrop={this.handleDrop}\n onDoubleClick={this.handleDoubleClick}\n onMouseDown={this.handleMouseDown}\n onMouseMove={this.handleMouseMove}\n onMouseUp={this.handleMouseUp}\n tabIndex={-1}\n ref={this.itemRef}\n role=\"presentation\"\n style={style}\n onFocus={this.handleFocus}\n onBlur={this.handleBlur}\n draggable={isDraggable}\n >\n {children}\n </div>\n );\n }\n}\n\nexport default ItemListItem;\n","import React, { PureComponent } from 'react';\nimport memoize from 'memoizee';\nimport {\n FixedSizeList as List,\n ListOnItemsRenderedProps,\n ListOnScrollProps,\n} from 'react-window';\nimport AutoSizer, { Size } from 'react-virtualized-auto-sizer';\nimport Log from '@deephaven/log';\nimport { RangeUtils, Range } from '@deephaven/utils';\nimport ItemListItem from './ItemListItem';\nimport { ContextActionUtils } from './context-actions';\nimport './ItemList.scss';\n\nconst log = Log.module('ItemList');\n\nexport interface DefaultListItem {\n value?: string;\n displayValue?: string;\n}\n\nexport type RenderItemProps<T> = {\n item: T;\n itemIndex: number;\n isFocused: boolean;\n isSelected: boolean;\n style: React.CSSProperties;\n};\n\nexport type RenderItemFn<T> = (props: RenderItemProps<T>) => React.ReactNode;\n\nexport type ItemDragEventHandler = (\n index: number,\n event: React.DragEvent<HTMLDivElement>\n) => void;\n\nexport type ItemListProps<T> = {\n // Total item count\n itemCount: number;\n rowHeight: number;\n // Offset of the top item in the items array\n offset: number;\n // Item object format expected by the default renderItem function\n // Can be anything as long as it's supported by the renderItem\n // Default renderItem will look for a `displayValue` property, fallback\n // to the `value` property, or stringify the object if neither are defined\n items: T[];\n // Whether clicking a selected item should deselect in the item list or not. Defaults to true\n isDeselectOnClick: boolean;\n // Whether selection requires a double click or not\n isDoubleClickSelect: boolean;\n // Whether to allow dragging to change the selection after clicking\n isDragSelect: boolean;\n // Whether to allow multiple selections in this item list\n isMultiSelect: boolean;\n // Set to true if you want the list to scroll when new items are added and it's already at the bottom\n isStickyBottom: boolean;\n // Fired when an item gets focused\n onFocusChange(index: number | null): void;\n\n // Fired when an item is clicked. With multiple selection, fired on double click.\n onSelect(index: number, event: React.SyntheticEvent): void;\n onSelectionChange(ranges: Range[]): void;\n onViewportChange(topRow: number, bottomRow: number): void;\n overscanCount: number;\n selectedRanges: Range[];\n disableSelect: boolean;\n renderItem: RenderItemFn<T>;\n focusSelector: string;\n};\n\ntype ItemListState = {\n focusIndex: number | null;\n mouseDownIndex: number | null;\n selectedRanges: Range[];\n overscanStartIndex: number;\n height: number | null;\n isDragging: boolean;\n isStuckToBottom: boolean;\n scrollOffset: number | null;\n};\n\n/**\n * Show items in a long scrollable list.\n * Can be navigated via keyboard or mouse.\n */\nexport class ItemList<T> extends PureComponent<\n ItemListProps<T>,\n ItemListState\n> {\n static CACHE_SIZE = 1000;\n\n static DEFAULT_ROW_HEIGHT = 20;\n\n // By drawing an additional 10 items on each side, tab/keyboard navigation works better (as the next element exists)\n static DEFAULT_OVERSCAN = 10;\n\n static defaultProps = {\n offset: 0,\n items: [],\n rowHeight: ItemList.DEFAULT_ROW_HEIGHT,\n\n isDeselectOnClick: true,\n\n isDoubleClickSelect: false,\n\n isDragSelect: true,\n\n isMultiSelect: false,\n\n isStickyBottom: false,\n\n disableSelect: false,\n\n onFocusChange(): void {\n // no-op\n },\n onSelect(): void {\n // no-op\n },\n onSelectionChange(): void {\n // no-op\n },\n onViewportChange(): void {\n // no-op\n },\n\n overscanCount: ItemList.DEFAULT_OVERSCAN,\n\n renderItem: ItemList.renderItem,\n selectedRanges: [],\n\n focusSelector: '.item-list-item',\n };\n\n static renderItem<P extends DefaultListItem>({\n item,\n }: RenderItemProps<P>): JSX.Element {\n return (\n <div className=\"item-list-item-content\">\n {item && (item.displayValue || item.value || `${item}`)}\n </div>\n );\n }\n\n constructor(props: ItemListProps<T>) {\n super(props);\n\n this.handleItemBlur = this.handleItemBlur.bind(this);\n this.handleItemContextMenu = this.handleItemContextMenu.bind(this);\n this.handleItemFocus = this.handleItemFocus.bind(this);\n this.handleItemDoubleClick = this.handleItemDoubleClick.bind(this);\n this.handleItemMouseDown = this.handleItemMouseDown.bind(this);\n this.handleItemMouseMove = this.handleItemMouseMove.bind(this);\n this.handleItemMouseUp = this.handleItemMouseUp.bind(this);\n this.handleItemsRendered = this.handleItemsRendered.bind(this);\n this.handleWindowMouseUp = this.handleWindowMouseUp.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleScroll = this.handleScroll.bind(this);\n this.handleResize = this.handleResize.bind(this);\n this.renderInnerElement = this.renderInnerElement.bind(this);\n\n this.list = React.createRef();\n this.listContainer = React.createRef();\n\n const { isStickyBottom, selectedRanges } = props;\n\n this.state = {\n focusIndex: null,\n mouseDownIndex: null,\n selectedRanges,\n overscanStartIndex: 0,\n height: null,\n isDragging: false,\n isStuckToBottom: isStickyBottom,\n scrollOffset: null,\n };\n }\n\n componentDidMount(): void {\n const { isStickyBottom } = this.props;\n if (isStickyBottom && !this.isListAtBottom()) {\n this.scrollToBottom();\n }\n }\n\n componentDidUpdate(\n prevProps: ItemListProps<T>,\n prevState: ItemListState\n ): void {\n const { selectedRanges: propSelectedRanges } = this.props;\n const {\n focusIndex,\n isStuckToBottom,\n scrollOffset,\n height,\n selectedRanges,\n } = this.state;\n if (isStuckToBottom && !this.isListAtBottom()) {\n this.scrollToBottom();\n }\n\n if (\n scrollOffset !== prevState.scrollOffset ||\n height !== prevState.height\n ) {\n this.sendViewportUpdate();\n }\n\n if (\n propSelectedRanges !== prevProps.selectedRanges &&\n propSelectedRanges !== selectedRanges\n ) {\n this.setSelectedRanges(propSelectedRanges);\n } else if (selectedRanges !== prevState.selectedRanges) {\n const { onSelectionChange } = this.props;\n onSelectionChange(selectedRanges);\n }\n\n if (focusIndex !== prevState.focusIndex) {\n const { onFocusChange } = this.props;\n onFocusChange(focusIndex);\n }\n }\n\n componentWillUnmount(): void {\n window.removeEventListener('mouseup', this.handleWindowMouseUp);\n }\n\n list: React.RefObject<List>;\n\n listContainer: React.RefObject<HTMLDivElement>;\n\n getItemSelected = memoize(\n (index: number, selectedRanges: Range[]) =>\n RangeUtils.isSelected(selectedRanges, index),\n { max: ItemList.CACHE_SIZE }\n );\n\n getCachedItem = memoize(\n (\n itemIndex: number,\n key: number,\n item: T,\n isFocused: boolean,\n isSelected: boolean,\n renderItem: RenderItemFn<T>,\n style: React.CSSProperties,\n disableSelect: boolean\n ) => {\n const content = renderItem({\n item,\n itemIndex,\n isFocused,\n isSelected,\n style,\n });\n\n return (\n <ItemListItem\n onContextMenu={this.handleItemContextMenu}\n onDoubleClick={this.handleItemDoubleClick}\n onMouseDown={this.handleItemMouseDown}\n onFocus={this.handleItemFocus}\n onBlur={this.handleItemBlur}\n disableSelect={disableSelect}\n onMouseMove={this.handleItemMouseMove}\n onMouseUp={this.handleItemMouseUp}\n isFocused={isFocused}\n isSelected={isSelected}\n itemIndex={itemIndex}\n style={style}\n key={key}\n >\n {content}\n </ItemListItem>\n );\n },\n { max: ItemList.CACHE_SIZE }\n );\n\n getOuterElement = memoize((onKeyDown: React.KeyboardEventHandler) => {\n const component = React.forwardRef<HTMLDivElement>((props, ref) => (\n // We need to add the tabIndex to make sure it is focusable, otherwise we can't get key events\n <div\n ref={ref}\n tabIndex={-1}\n onKeyDown={onKeyDown}\n role=\"presentation\"\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...props}\n />\n ));\n component.displayName = 'ItemListOuterElement';\n return component;\n });\n\n getInnerElement = memoize(() => {\n const component = React.forwardRef<HTMLDivElement>((props, ref) => (\n <div\n className=\"item-list-inner-element\"\n ref={ref}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...props}\n />\n ));\n component.displayName = 'ItemListInnerElement';\n return component;\n });\n\n getItemData = memoize(\n (items: T[], selectedRanges: Range[], renderItem: RenderItemFn<T>) => ({\n items,\n selectedRanges,\n renderItem,\n })\n );\n\n focus(): void {\n this.listContainer.current?.focus();\n }\n\n getElement(itemIndex: number): Element | null {\n if (this.listContainer.current == null) {\n return null;\n }\n\n const { focusSelector } = this.props;\n const { overscanStartIndex } = this.state;\n const elements = this.listContainer.current.querySelectorAll(focusSelector);\n const elementIndex = itemIndex - overscanStartIndex;\n return elements[elementIndex];\n }\n\n focusItem(itemIndex: number): void {\n const { disableSelect } = this.props;\n if (disableSelect) return;\n\n this.setState({ focusIndex: itemIndex });\n\n const element = this.getElement(itemIndex);\n if (element instanceof HTMLElement) {\n element.focus();\n }\n }\n\n scrollToItem(itemIndex: number): void {\n const element = this.getElement(itemIndex);\n if (element != null) {\n element.scrollIntoView({ block: 'center' });\n }\n }\n\n handleItemContextMenu(\n itemIndex: number,\n e: React.MouseEvent<HTMLDivElement>\n ): void {\n // Update the selection, but don't consume the mouse event - it will trigger the context menu\n const { selectedRanges } = this.state;\n const isSelected = RangeUtils.isSelected(selectedRanges, itemIndex);\n\n // When right-clicking, we want to maintain the current selection if the right click happened within the selection even if the modifier key isn't down\n const isModifierDown =\n isSelected || ContextActionUtils.isModifierKeyDown(e);\n this.toggleSelect(itemIndex, e.shiftKey, isModifierDown, false);\n }\n\n handleItemDoubleClick(itemIndex: number, e: React.MouseEvent): void {\n const { isDoubleClickSelect, onSelect } = this.props;\n\n if (isDoubleClickSelect) {\n this.setState(\n ({ selectedRanges }) => ({\n selectedRanges: RangeUtils.selectRange(selectedRanges, [\n itemIndex,\n itemIndex,\n ]),\n }),\n () => {\n onSelect(itemIndex, e);\n }\n );\n }\n }\n\n handleItemMouseDown(index: number, e: React.MouseEvent): void {\n const { selectedRanges } = this.state;\n\n if (\n e.target instanceof HTMLElement &&\n ['button', 'select', 'input', 'textarea'].indexOf(\n e.target.tagName.toLowerCase()\n ) !== -1\n ) {\n // allow these elements to do their own behaviours\n return;\n }\n\n if (e.button === 2 && selectedRanges.length === 0) {\n // allow right click to act as a selection if selection is empty\n this.focusItem(index);\n this.selectItem(index);\n return;\n }\n\n if (e.button != null && e.button !== 0) {\n return;\n }\n\n this.setState({ mouseDownIndex: index });\n\n window.addEventListener('mouseup', this.handleWindowMouseUp);\n\n // Leave selection until mouse up, to allow for dragging behaviour\n }\n\n handleItemBlur(itemIndex: number, e: React.FocusEvent): void {\n log.debug2('item blur', itemIndex, e.currentTarget, e.relatedTarget);\n if (\n !e.relatedTarget ||\n (this.listContainer.current &&\n e.relatedTarget instanceof HTMLElement &&\n !this.listContainer.current.contains(e.relatedTarget))\n ) {\n // Next focused element is outside of the ItemList\n this.setState({ focusIndex: null });\n }\n }\n\n handleItemFocus(itemIndex: number, e: React.FocusEvent): void {\n log.debug2('item focus', itemIndex, e.target);\n this.setState(state => {\n const { focusIndex } = state;\n if (focusIndex !== itemIndex) {\n return { focusIndex: itemIndex };\n }\n return null;\n });\n }\n\n handleItemMouseMove(itemIndex: number, e: React.MouseEvent): void {\n const { isDragSelect, isMultiSelect, disableSelect } = this.props;\n const { mouseDownIndex, selectedRanges } = this.state;\n\n if (mouseDownIndex == null || disableSelect) return;\n\n this.setState({ isDragging: true });\n\n if (isDragSelect || mouseDownIndex === itemIndex) {\n this.focusItem(itemIndex);\n\n if (isMultiSelect) {\n if (\n !isDragSelect &&\n !this.getItemSelected(itemIndex, selectedRanges) &&\n !ContextActionUtils.isModifierKeyDown(e)\n ) {\n // If there's already a selection and they select outside of that range while dragging without a modifier key, start a new selection with just the new item\n this.deselectAll();\n }\n this.selectRange([\n Math.min(mouseDownIndex, itemIndex),\n Math.max(mouseDownIndex, itemIndex),\n ]);\n } else {\n this.toggleSelect(\n itemIndex,\n e.shiftKey,\n ContextActionUtils.isModifierKeyDown(e),\n false\n );\n }\n }\n }\n\n handleItemMouseUp(index: number, e: React.MouseEvent): void {\n const { isDeselectOnClick, isDoubleClickSelect, onSelect } = this.props;\n const { mouseDownIndex, isDragging } = this.state;\n\n if (\n e.target instanceof HTMLElement &&\n ['button', 'select', 'input', 'textarea'].indexOf(\n e.target.tagName.toLowerCase()\n ) !== -1\n ) {\n return;\n }\n\n if (mouseDownIndex === index && !isDragging) {\n const isShiftDown = e.shiftKey;\n const isModifierDown = ContextActionUtils.isModifierKeyDown(e);\n this.focusItem(index);\n this.toggleSelect(index, isShiftDown, isModifierDown, isDeselectOnClick);\n\n if (!isDoubleClickSelect && !isShiftDown && !isModifierDown) {\n onSelect(index, e);\n }\n }\n\n this.resetMouseState();\n }\n\n handleItemsRendered({ overscanStartIndex }: ListOnItemsRenderedProps): void {\n this.setState({ overscanStartIndex });\n }\n\n handleResize({ height }: Size): void {\n this.setState({ height });\n }\n\n handleMouseLeave(): void {\n this.setState({ mouseDownIndex: null });\n }\n\n handleWindowMouseUp(): void {\n this.resetMouseState();\n window.removeEventListener('mouseup', this.handleWindowMouseUp);\n }\n\n handleKeyDown(e: React.KeyboardEvent): void {\n const { isMultiSelect, itemCount, onSelect } = this.props;\n const { focusIndex: oldFocus } = this.state;\n let newFocus = oldFocus;\n\n if (e.key === 'Enter' || e.key === ' ') {\n if (!isMultiSelect && newFocus != null) {\n this.setState({ selectedRanges: [[newFocus, newFocus]] }, () => {\n if (newFocus != null) {\n onSelect(newFocus, e);\n }\n });\n }\n return;\n }\n\n if (e.key === 'ArrowUp') {\n if (newFocus != null && newFocus >= 0) {\n newFocus = Math.max(0, newFocus - 1);\n } else {\n newFocus = itemCount - 1;\n }\n } else if (e.key === 'ArrowDown') {\n if (newFocus != null && newFocus >= 0) {\n newFocus = Math.min(newFocus + 1, itemCount - 1);\n } else {\n newFocus = 0;\n }\n } else {\n return;\n }\n\n if (oldFocus !== newFocus) {\n e.stopPropagation();\n e.preventDefault();\n\n this.focusItem(newFocus);\n\n const { selectedRanges } = this.state;\n if (e.shiftKey && selectedRanges.length > 0) {\n const lastRange = selectedRanges[selectedRanges.length - 1];\n this.selectRange([\n Math.min(newFocus, lastRange[0]),\n Math.max(newFocus, lastRange[1]),\n ]);\n } else {\n this.deselectAll();\n if (newFocus !== null) {\n this.selectItem(newFocus);\n } else {\n this.listContainer.current?.focus();\n }\n }\n\n this.scrollIntoView(newFocus);\n }\n }\n\n handleScroll({\n scrollUpdateWasRequested,\n scrollOffset,\n }: ListOnScrollProps): void {\n this.setState(state => {\n if (scrollUpdateWasRequested) {\n // The scroll was caused by scrollTo() or scrollToItem()\n // Don't re-calc isStuckToBottom\n return { scrollOffset } as ItemListState;\n }\n\n const { isStickyBottom } = this.props;\n const { height } = state;\n\n const isStuckToBottom =\n isStickyBottom && this.isListAtBottom({ scrollOffset, height });\n return { isStuckToBottom, scrollOffset } as ItemListState;\n });\n }\n\n resetMouseState(): void {\n this.setState({ mouseDownIndex: null, isDragging: false });\n }\n\n scrollToBottom(): void {\n const { itemCount } = this.props;\n if (this.list.current) {\n this.list.current.scrollToItem(itemCount);\n }\n }\n\n scrollIntoView(itemIndex: number): void {\n if (this.list.current) {\n this.list.current.scrollToItem(itemIndex);\n }\n }\n\n /**\n * @param index The index to toggle selection for\n * @param isShiftDown True if the shift modifier key is down\n * @param isModifierDown True if the meta modifier key is down\n * @param isDeselectable True if item should be deselected if already selected\n */\n toggleSelect(\n index: number,\n isShiftDown: boolean,\n isModifierDown: boolean,\n isDeselectable = true\n ): void {\n const { isMultiSelect } = this.props;\n const { selectedRanges } = this.state;\n\n if (isMultiSelect && isShiftDown && selectedRanges.length > 0) {\n const lastRange = selectedRanges[selectedRanges.length - 1];\n this.selectRange([\n Math.min(lastRange[0], index),\n Math.max(index, lastRange[1]),\n ]);\n } else if (\n isMultiSelect &&\n selectedRanges.length === 1 &&\n selectedRanges[0][0] === index &&\n selectedRanges[0][1] === index\n ) {\n if (isDeselectable) {\n this.deselectItem(index);\n }\n } else if (isMultiSelect && isModifierDown) {\n if (this.getItemSelected(index, selectedRanges)) {\n if (isDeselectable) {\n this.deselectItem(index);\n }\n } else {\n this.selectItem(index);\n }\n } else {\n this.deselectAll();\n this.selectItem(index);\n }\n }\n\n deselectAll(): void {\n const { itemCount } = this.props;\n this.deselectRange([0, itemCount]);\n }\n\n deselectItem(index: number): void {\n this.deselectRange([index, index]);\n }\n\n deselectRange(range: Range): void {\n RangeUtils.validateRange(range);\n\n this.setState(({ selectedRanges }) => ({\n selectedRanges: RangeUtils.deselectRange(selectedRanges, range),\n }));\n }\n\n selectItem(index: number): void {\n const { disableSelect } = this.props;\n if (disableSelect) return;\n\n this.selectRange([index, index]);\n }\n\n selectRange(range: Range): void {\n RangeUtils.validateRange(range);\n\n this.setState(({ selectedRanges }) => ({\n selectedRanges: RangeUtils.selectRange(selectedRanges, range),\n }));\n }\n\n setSelectedRanges(selectedRanges: Range[]): void {\n this.setState({ selectedRanges });\n }\n\n sendViewportUpdate(): void {\n const { scrollOffset, height } = this.state;\n if (scrollOffset != null && height != null) {\n const { onViewportChange, rowHeight } = this.props;\n const topRow = Math.floor(scrollOffset / rowHeight);\n const bottomRow = topRow + Math.ceil(height / rowHeight);\n onViewportChange(topRow, bottomRow);\n }\n }\n\n isListAtBottom(\n {\n scrollOffset,\n height,\n }: Pick<ItemListState, 'scrollOffset' | 'height'> = this.state\n ): boolean {\n if (height == null || scrollOffset == null) {\n return false;\n }\n\n const { itemCount, rowHeight } = this.props;\n return scrollOffset + height >= itemCount * rowHeight;\n }\n\n renderInnerElement({\n index: itemIndex,\n style,\n }: {\n index: number;\n style: React.CSSProperties;\n }): React.ReactElement | null {\n const { items, offset, renderItem, disableSelect } = this.props;\n const { focusIndex, selectedRanges } = this.state;\n if (itemIndex < offset || itemIndex >= offset + items.length) {\n return null;\n }\n\n const item = items[itemIndex - offset];\n return this.getCachedItem(\n itemIndex,\n itemIndex,\n item,\n itemIndex === focusIndex && !disableSelect,\n this.getItemSelected(itemIndex, selectedRanges),\n renderItem,\n style,\n disableSelect\n );\n }\n\n render(): JSX.Element {\n const {\n items,\n itemCount,\n overscanCount,\n renderItem,\n rowHeight,\n } = this.props;\n const { selectedRanges } = this.state;\n return (\n <AutoSizer className=\"item-list-auto-sizer\" onResize={this.handleResize}>\n {({ width, height }) => (\n <List\n className=\"item-list-scroll-pane\"\n height={height}\n width={width}\n itemCount={itemCount}\n itemSize={rowHeight}\n // This prop isn't actually used by us, it is passed to the render function by react-window\n // Used here to force a re-render of the List component.\n // Otherwise it doesn't know to call the render again when selection or renderItem changes\n itemData={this.getItemData(items, selectedRanges, renderItem)}\n onScroll={this.handleScroll}\n onItemsRendered={this.handleItemsRendered}\n ref={this.list}\n outerElementType={this.getOuterElement(this.handleKeyDown)}\n outerRef={this.listContainer}\n innerElementType={this.getInnerElement()}\n overscanCount={overscanCount}\n >\n {this.renderInnerElement}\n </List>\n )}\n </AutoSizer>\n );\n }\n}\n\nexport default ItemList;\n","import React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport memoize from 'memoizee';\nimport { Draggable, Droppable, DraggableChildrenFn } from 'react-beautiful-dnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsGripper } from '@deephaven/icons';\nimport { RangeUtils, Range } from '@deephaven/utils';\nimport ItemList, {\n RenderItemProps,\n DefaultListItem,\n ItemListProps,\n} from './ItemList';\nimport { Tooltip } from './popper';\nimport './DraggableItemList.scss';\n\nexport type DraggableRenderItemProps<T> = RenderItemProps<T> & {\n isClone?: boolean;\n selectedCount?: number;\n};\n\ntype DraggableRenderItemFn<T> = (\n props: DraggableRenderItemProps<T>\n) => React.ReactNode;\n\ntype DraggableItemListProps<T> = Omit<\n ItemListProps<T>,\n 'overscanCount' | 'focusSelector' | 'isDragSelect'\n> & {\n className: string;\n draggingItemClassName: string;\n isDropDisabled: boolean;\n // Whether to allow dragging items from this list\n isDragDisabled: boolean;\n\n renderItem: DraggableRenderItemFn<T>;\n style: React.CSSProperties;\n\n // The prefix to add to all draggable item IDs\n draggablePrefix: string;\n // The ID to give the droppable list\n droppableId: string;\n};\n\ntype DraggableItemListState = {\n selectedCount: number;\n};\n\n/**\n * Show a draggable item list. It _must_ be used within a `DragDropContext`.\n * This implementation uses react-beautiful-dnd for handling dragging and dropping of items.\n * We use ItemList to handle selection for multi drag and drop (not built in to react-beautiful-dnd).\n * One caveat with the use of react-beautiful-dnd is that it doesn't allow a drag to be initiated while\n * using a modifier key: https://github.com/atlassian/react-beautiful-dnd/issues/1678\n */\nclass DraggableItemList<T> extends PureComponent<\n DraggableItemListProps<T>,\n DraggableItemListState\n> {\n static DEFAULT_ROW_HEIGHT = 30;\n\n static defaultProps = {\n className: '',\n draggingItemClassName: '',\n offset: 0,\n items: [],\n rowHeight: DraggableItemList.DEFAULT_ROW_HEIGHT,\n isDeselectOnClick: true,\n isDoubleClickSelect: true,\n isDropDisabled: false,\n isDragDisabled: false,\n isMultiSelect: false,\n isStickyBottom: false,\n disableSelect: false,\n style: null,\n onFocusChange(): void {\n // no-op\n },\n onSelect(): void {\n // no-op\n },\n onSelectionChange(): void {\n // no-op\n },\n onViewportChange(): void {\n // no-op\n },\n renderItem: DraggableItemList.renderItem,\n selectedRanges: [],\n draggablePrefix: 'draggable-item',\n droppableId: 'droppable-item-list',\n };\n\n static renderHandle(): JSX.Element {\n return (\n <div>\n <Tooltip>Drag to re-order</Tooltip>\n <FontAwesomeIcon icon={vsGripper} />\n </div>\n );\n }\n\n static renderBadge({ text }: { text?: string }): React.ReactNode {\n return text ? <span className=\"number-badge\">{text}</span> : null;\n }\n\n static renderTextItem({\n text,\n badgeText = '',\n className = '',\n }: {\n text: string;\n badgeText: string;\n className: string;\n }): JSX.Element {\n return (\n <div\n className={classNames(\n 'item-list-item-content',\n 'draggable-item-list-item-content',\n className\n )}\n >\n <span className=\"title\">{text}</span>\n {DraggableItemList.renderBadge({ text: badgeText })}\n {DraggableItemList.renderHandle()}\n </div>\n );\n }\n\n static renderItem<P extends DefaultListItem>({\n item,\n isClone,\n selectedCount,\n }: DraggableRenderItemProps<P>): JSX.Element {\n const text = item && (item.displayValue || item.value || `${item}`);\n const badgeText = isClone ? `${selectedCount}` : '';\n const className = isClone ? 'item-list-item-clone' : '';\n return DraggableItemList.renderTextItem({ text, badgeText, className });\n }\n\n static getDraggableId(draggablePrefix: string, itemIndex: number): string {\n return `${draggablePrefix}/${itemIndex}`;\n }\n\n static getDraggableIndex(draggableId: string): number {\n return parseInt(draggableId.split('/').pop() || '', 10);\n }\n\n constructor(props: DraggableItemListProps<T>) {\n super(props);\n\n this.handleSelectionChange = this.handleSelectionChange.bind(this);\n\n this.itemList = React.createRef();\n\n this.state = {\n selectedCount: 0,\n };\n }\n\n itemList: React.RefObject<ItemList<T>>;\n\n selectItem(itemIndex: number): void {\n this.itemList.current?.selectItem(itemIndex);\n }\n\n focusItem(itemIndex: number): void {\n this.itemList.current?.focusItem(itemIndex);\n }\n\n scrollToItem(itemIndex: number): void {\n this.itemList.current?.scrollToItem(itemIndex);\n }\n\n getCachedDraggableItem = memoize(\n (\n draggablePrefix: string,\n renderItem: DraggableRenderItemFn<T>,\n item: T,\n itemIndex: number,\n isFocused: boolean,\n isSelected: boolean,\n isDragDisabled: boolean,\n style: React.CSSProperties\n ) => (\n <Draggable\n key={itemIndex}\n draggableId={DraggableItemList.getDraggableId(\n draggablePrefix,\n itemIndex\n )}\n index={itemIndex}\n isDragDisabled={isDragDisabled}\n >\n {provided => (\n <div\n role=\"menuitem\"\n className=\"draggable-item-list-item\"\n ref={provided.innerRef}\n tabIndex={-1}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.draggableProps}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.dragHandleProps}\n >\n {renderItem({\n item,\n itemIndex,\n isFocused,\n isSelected,\n style,\n isClone: false,\n })}\n </div>\n )}\n </Draggable>\n ),\n { max: ItemList.CACHE_SIZE }\n );\n\n handleSelectionChange(selectedRanges: Range[]): void {\n this.setState({ selectedCount: RangeUtils.count(selectedRanges) });\n\n const { onSelectionChange } = this.props;\n onSelectionChange(selectedRanges);\n }\n\n getCachedRenderDraggableItem = memoize(\n (\n draggablePrefix: string,\n isDragDisabled: boolean,\n renderItem: DraggableRenderItemFn<T>\n ) => ({\n item,\n itemIndex,\n isFocused,\n isSelected,\n style,\n }: RenderItemProps<T>) =>\n this.getCachedDraggableItem(\n draggablePrefix,\n renderItem,\n item,\n itemIndex,\n isFocused,\n isSelected,\n isDragDisabled,\n style\n ),\n { max: 1 }\n );\n\n getCachedRenderClone = memoize(\n (\n draggingItemClassName: string,\n items: T[],\n offset: number,\n renderItem: DraggableRenderItemFn<T>\n ): DraggableChildrenFn => (provided, snapshot, rubric) => {\n const { selectedCount } = this.state;\n const { index: itemIndex } = rubric.source;\n const item = items[itemIndex - offset];\n return (\n <div\n className={classNames(\n 'draggable-item-list-dragging-item-container',\n draggingItemClassName\n )}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.draggableProps}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.dragHandleProps}\n ref={provided.innerRef}\n >\n <div\n className={classNames(\n 'draggable-item-list-dragging-item',\n { 'two-dragged': selectedCount === 2 },\n { 'multiple-dragged': selectedCount > 2 }\n )}\n >\n {renderItem({\n item,\n itemIndex,\n isFocused: false,\n isSelected: true,\n style: {},\n isClone: true,\n selectedCount,\n })}\n </div>\n </div>\n );\n },\n { max: 1 }\n );\n\n render(): JSX.Element {\n const {\n className,\n draggablePrefix,\n draggingItemClassName,\n droppableId,\n isDoubleClickSelect,\n isDragDisabled,\n isDropDisabled,\n isMultiSelect,\n isStickyBottom,\n itemCount,\n items,\n offset,\n onFocusChange,\n onSelect,\n onViewportChange,\n renderItem,\n rowHeight,\n selectedRanges,\n style,\n } = this.props;\n return (\n <Droppable\n isDropDisabled={isDropDisabled}\n droppableId={droppableId}\n mode=\"virtual\"\n renderClone={this.getCachedRenderClone(\n draggingItemClassName,\n items,\n offset,\n renderItem\n )}\n >\n {(provided, snapshot) => (\n <div\n role=\"menu\"\n className={classNames('draggable-item-list', className, {\n 'is-drop-disabled': isDropDisabled,\n 'is-drag-disabled': isDragDisabled,\n 'is-dragging-from-this': snapshot.draggingFromThisWith,\n 'is-dragging-over': snapshot.isDraggingOver,\n 'is-dropping': snapshot.draggingOverWith,\n })}\n style={style}\n ref={provided.innerRef}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.droppableProps}\n >\n <ItemList\n focusSelector=\".draggable-item-list-item\"\n isDoubleClickSelect={isDoubleClickSelect}\n isDragSelect={false}\n isMultiSelect={isMultiSelect}\n isStickyBottom={isStickyBottom}\n itemCount={itemCount}\n items={items}\n onFocusChange={onFocusChange}\n onSelect={onSelect}\n onSelectionChange={this.handleSelectionChange}\n onViewportChange={onViewportChange}\n offset={offset}\n ref={this.itemList}\n renderItem={this.getCachedRenderDraggableItem(\n draggablePrefix,\n isDragDisabled,\n renderItem\n )}\n rowHeight={rowHeight}\n selectedRanges={selectedRanges}\n />\n </div>\n )}\n </Droppable>\n );\n }\n}\n\nexport default DraggableItemList;\n","import React from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\n\nconst Button = React.forwardRef((props, ref) => {\n const { children, className, disabled, onClick, style, id } = props;\n return (\n <button\n ref={ref}\n type=\"button\"\n className={classNames('btn', className)}\n onClick={onClick}\n style={style}\n disabled={disabled}\n id={id}\n >\n {children}\n </button>\n );\n});\n\nButton.displayName = 'Button';\n\nButton.propTypes = {\n children: PropTypes.node,\n className: PropTypes.string,\n disabled: PropTypes.bool,\n onClick: PropTypes.func,\n style: PropTypes.shape({}),\n id: PropTypes.string,\n};\n\nButton.defaultProps = {\n children: null,\n className: '',\n disabled: false,\n onClick: () => {},\n style: {},\n id: '',\n};\n\nexport default Button;\n","/* eslint-disable jsx-a11y/click-events-have-key-events */\nimport React, { Component } from 'react';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { DragDropContext, Droppable } from 'react-beautiful-dnd';\nimport {\n ButtonOld,\n Checkbox,\n DraggableItemList,\n DragUtils,\n SearchInput,\n Tooltip,\n} from '@deephaven/components';\nimport { vsTrash, dhSortAlphaDown, dhSortAlphaUp } from '@deephaven/icons';\nimport memoize from 'memoizee';\nimport debounce from 'lodash.debounce';\nimport Log from '@deephaven/log';\nimport './RollupRows.scss';\nimport IrisGridModel from '../IrisGridModel';\nimport TableUtils from '../TableUtils';\n\nconst log = Log.module('RollupRows');\nconst DEBOUNCE_SEARCH = 150;\nconst GROUPED_LIST_ID = 'grouped-rollup-rows';\nconst UNGROUPED_LIST_ID = 'ungrouped-rollup-rows';\n\nclass RollupRows extends Component {\n static SORT = Object.freeze({\n ASCENDING: 'ASCENDING',\n DESCENDING: 'DESCENDING',\n });\n\n static renderColumn({ item, isClone, selectedCount }) {\n const text = item && item.name;\n const badgeText = isClone ? `${selectedCount}` : null;\n const className = isClone ? 'item-list-item-clone' : '';\n return DraggableItemList.renderTextItem({ text, badgeText, className });\n }\n\n static addGroupings(\n currentGroupings,\n newGroupings,\n index = currentGroupings.length\n ) {\n if (newGroupings == null || newGroupings.length === 0) {\n return currentGroupings;\n }\n\n let insertIndex = index;\n const groupings = currentGroupings.filter((grouping, i) => {\n if (newGroupings.includes(grouping)) {\n if (i < insertIndex) {\n insertIndex -= 1;\n }\n return false;\n }\n return true;\n });\n groupings.splice(insertIndex, 0, ...newGroupings);\n return groupings;\n }\n\n static isGroupable(column) {\n return !TableUtils.isDecimalType(column.type);\n }\n\n constructor(props) {\n super(props);\n\n this.search = debounce(this.search.bind(this), DEBOUNCE_SEARCH);\n\n this.handleDeleteClicked = this.handleDeleteClicked.bind(this);\n this.handleSearchChange = this.handleSearchChange.bind(this);\n this.handleUngroupedSelect = this.handleUngroupedSelect.bind(this);\n this.handleUngroupedSelectionChange = this.handleUngroupedSelectionChange.bind(\n this\n );\n this.handleDragStart = this.handleDragStart.bind(this);\n this.handleDragEnd = this.handleDragEnd.bind(this);\n this.handleGroupedSelectionChange = this.handleGroupedSelectionChange.bind(\n this\n );\n this.handleShowConstituentsChange = this.handleShowConstituentsChange.bind(\n this\n );\n this.handleShowNonAggregatedColumnsChange = this.handleShowNonAggregatedColumnsChange.bind(\n this\n );\n this.handleSortAscending = this.handleSortAscending.bind(this);\n this.handleSortDescending = this.handleSortDescending.bind(this);\n this.renderGroupedItem = this.renderGroupedItem.bind(this);\n\n this.ungroupedList = React.createRef();\n this.groupedList = React.createRef();\n\n const { config } = props;\n const {\n columns = [],\n showConstituents = true,\n showNonAggregatedColumns = true,\n } = config ?? {};\n\n this.state = {\n ungroupedSelectedRanges: [],\n columns,\n groupedSelectedRanges: [],\n searchFilter: '',\n showConstituents,\n showNonAggregatedColumns,\n dragSource: null,\n sort: null,\n };\n }\n\n componentDidUpdate(prevProps, prevState) {\n const { config } = this.props;\n const { columns, showConstituents, showNonAggregatedColumns } = this.state;\n if (config !== prevProps.config) {\n this.updateFromConfig();\n } else if (\n columns !== prevState.columns ||\n showConstituents !== prevState.showConstituents ||\n showNonAggregatedColumns !== prevState.showNonAggregatedColumns\n ) {\n if (\n config == null ||\n columns !== config.columns ||\n showConstituents !== config.showConstituents ||\n showNonAggregatedColumns !== config.showNonAggregatedColumns\n ) {\n this.sendChange();\n }\n }\n }\n\n componentWillUnmount() {\n this.search.cancel();\n }\n\n handleSearchChange(event) {\n const searchFilter = event.target.value;\n this.setState({ searchFilter });\n if (!searchFilter) {\n this.search.cancel();\n this.resetSelection();\n return;\n }\n this.search(searchFilter);\n }\n\n handleSortAscending() {\n this.setState(({ sort }) => ({\n sort:\n sort === RollupRows.SORT.ASCENDING ? null : RollupRows.SORT.ASCENDING,\n }));\n }\n\n handleSortDescending() {\n this.setState(({ sort }) => ({\n sort:\n sort === RollupRows.SORT.DESCENDING ? null : RollupRows.SORT.DESCENDING,\n }));\n }\n\n resetSelection() {\n this.setState({ ungroupedSelectedRanges: [], groupedSelectedRanges: [] });\n }\n\n search(searchFilter) {\n const columns = this.getSortedUngroupedColumns();\n const selectedRanges = [];\n let focusIndex = null;\n for (let i = 0; i < columns.length; i += 1) {\n const column = columns[i];\n if (column.name.toLowerCase().includes(searchFilter.toLowerCase())) {\n if (focusIndex == null) {\n focusIndex = i;\n }\n selectedRanges.push([i, i]);\n }\n }\n this.setState({ ungroupedSelectedRanges: selectedRanges });\n\n if (selectedRanges.length > 0 && this.ungroupedList.current) {\n this.ungroupedList.current.scrollToItem(focusIndex);\n }\n }\n\n handleDragStart(e) {\n log.debug('handleDragStart', e);\n\n document.documentElement.classList.add('drag-pointer-events-none');\n\n this.setState({ dragSource: e.source });\n }\n\n handleDragEnd(e) {\n log.debug('handleDragEnd', e);\n\n document.documentElement.classList.remove('drag-pointer-events-none');\n\n this.setState({ dragSource: null });\n\n const { destination, source } = e;\n if (destination == null || source == null) {\n return;\n }\n\n // We don't allow dragging within the ungrouped list, so if we're dragging into the ungrouped list,\n // it must have came from the grouped list. Remove those grouped columns.\n if (destination.droppableId === UNGROUPED_LIST_ID) {\n this.setState(({ groupedSelectedRanges, columns }) => {\n const newColumns = [...columns];\n DragUtils.reorder(newColumns, groupedSelectedRanges, [], 0);\n return {\n columns: newColumns,\n ungroupedSelectedRanges: [],\n groupedSelectedRanges: [],\n };\n });\n return;\n }\n\n // Otherwise, it must be dropping into the grouped list, so we just need to check the source\n const isSameList = source.droppableId === GROUPED_LIST_ID;\n let destinationIndex = destination.index;\n if (isSameList && source.index < destination.index) {\n // react-beautiful-dnd adjusts the index when dragging within a list already, however that only supports single selection\n // We need to change it back to the index we actually want it to drop at before adjusting for the removed source index, as\n // we adjust the index based on all the selected ranges, not just the source.index.\n destinationIndex += 1;\n }\n this.setState(\n ({ columns, ungroupedSelectedRanges, groupedSelectedRanges }) => {\n const newColumns = [...columns];\n const sourceItems = isSameList\n ? newColumns\n : this.getSortedUngroupedColumns().map(c => c.name);\n const sourceRanges = isSameList\n ? groupedSelectedRanges\n : ungroupedSelectedRanges;\n const draggedItems = DragUtils.reorder(\n sourceItems,\n sourceRanges,\n newColumns,\n destinationIndex\n );\n\n // Select the newly dropped items\n const insertIndex = isSameList\n ? DragUtils.adjustDestinationIndex(\n destinationIndex,\n groupedSelectedRanges\n )\n : destinationIndex;\n const newSelectedRanges = [\n [insertIndex, insertIndex + draggedItems.length - 1],\n ];\n return {\n columns: newColumns,\n ungroupedSelectedRanges: [],\n groupedSelectedRanges: newSelectedRanges,\n };\n }\n );\n this.resetSelection();\n }\n\n handleUngroupedSelect(itemIndex) {\n log.debug('handleUngroupedSelect');\n\n this.setState(({ columns }) => ({\n columns: RollupRows.addGroupings(columns, [\n this.getSortedUngroupedColumns()[itemIndex].name,\n ]),\n ungroupedSelectedRanges: [],\n groupedSelectedRanges: [],\n }));\n }\n\n handleUngroupedSelectionChange(ungroupedSelectedRanges) {\n log.debug2('handleUngroupedSelectionChange', ungroupedSelectedRanges);\n this.setState(\n ({ ungroupedSelectedRanges: stateUngroupedSelectedRanges }) => {\n if (ungroupedSelectedRanges === stateUngroupedSelectedRanges) {\n return null;\n }\n\n return { ungroupedSelectedRanges, groupedSelectedRanges: [] };\n }\n );\n }\n\n handleGroupedSelectionChange(groupedSelectedRanges) {\n log.debug2('handleGroupedSelectedRanges', groupedSelectedRanges);\n this.setState(({ groupedSelectedRanges: stateGroupedSelectedRanges }) => {\n if (groupedSelectedRanges === stateGroupedSelectedRanges) {\n return null;\n }\n\n return { groupedSelectedRanges, ungroupedSelectedRanges: [] };\n });\n }\n\n handleDeleteClicked(index) {\n this.setState(({ columns }) => {\n const newColumns = columns.slice();\n newColumns.splice(index, 1);\n return { columns: newColumns };\n });\n }\n\n handleShowConstituentsChange() {\n this.setState(({ showConstituents }) => ({\n showConstituents: !showConstituents,\n }));\n }\n\n handleShowNonAggregatedColumnsChange() {\n this.setState(({ showNonAggregatedColumns }) => ({\n showNonAggregatedColumns: !showNonAggregatedColumns,\n }));\n }\n\n updateFromConfig() {\n const { config } = this.props;\n const {\n columns = [],\n showConstituents = true,\n showNonAggregatedColumns = true,\n } = config ?? {};\n this.setState({ columns, showConstituents, showNonAggregatedColumns });\n }\n\n sendChange() {\n const { onChange } = this.props;\n const { columns, showConstituents, showNonAggregatedColumns } = this.state;\n onChange({\n columns,\n showConstituents,\n showNonAggregatedColumns,\n });\n }\n\n getCachedUngroupedColumns = memoize((columns, groupedColumns) =>\n columns.filter(\n column =>\n RollupRows.isGroupable(column) &&\n !groupedColumns.find(name => name === column.name)\n )\n );\n\n getCachedSortedColumns = memoize((columns, sort) =>\n sort == null\n ? [...columns]\n : TableUtils.sortColumns(columns, sort === RollupRows.SORT.ASCENDING)\n );\n\n getUngroupedColumns() {\n const { model } = this.props;\n const { columns, searchFilter } = this.state;\n const { originalColumns } = model;\n\n return this.getCachedUngroupedColumns(\n originalColumns,\n columns,\n searchFilter\n );\n }\n\n getSortedUngroupedColumns() {\n const { sort } = this.state;\n const columns = this.getUngroupedColumns();\n return this.getCachedSortedColumns(columns, sort);\n }\n\n renderGroupedItem({ item, itemIndex, isClone, selectedCount }) {\n const indent = isClone ? '' : '\\u00A0\\u00A0'.repeat(itemIndex);\n const text = `${indent}${item}`;\n const badgeText = isClone ? `${selectedCount}` : null;\n const className = isClone ? 'item-list-item-clone' : '';\n return (\n <>\n {DraggableItemList.renderTextItem({ text, badgeText, className })}\n {!isClone && (\n <ButtonOld\n className=\"btn btn-link btn-link-icon btn-delete-grouping float-right\"\n onClick={() => this.handleDeleteClicked(itemIndex)}\n >\n <FontAwesomeIcon icon={vsTrash} />\n </ButtonOld>\n )}\n </>\n );\n }\n\n render() {\n const {\n columns,\n dragSource,\n searchFilter,\n groupedSelectedRanges,\n ungroupedSelectedRanges,\n showConstituents,\n showNonAggregatedColumns,\n sort,\n } = this.state;\n\n const ungroupedColumns = this.getSortedUngroupedColumns();\n let groupListHeight = columns.length * DraggableItemList.DEFAULT_ROW_HEIGHT;\n if (dragSource?.droppableId === UNGROUPED_LIST_ID) {\n groupListHeight += DraggableItemList.DEFAULT_ROW_HEIGHT;\n }\n const ungroupMaxListHeight =\n ungroupedColumns.length * DraggableItemList.DEFAULT_ROW_HEIGHT + 10;\n const ungroupMinListHeight = Math.min(\n 3 * DraggableItemList.DEFAULT_ROW_HEIGHT,\n ungroupMaxListHeight\n );\n\n return (\n <div\n role=\"menu\"\n className={classNames('rollup-rows', {\n 'is-dragging': dragSource != null,\n })}\n tabIndex=\"0\"\n >\n <DragDropContext\n onDragEnd={this.handleDragEnd}\n onDragStart={this.handleDragStart}\n >\n <div className=\"rollup-rows-group-by\">\n <div className=\"section-title\">Group By</div>\n {columns.length === 0 && (\n <Droppable isDragDisabled droppableId=\"placeholder\">\n {(provided, snapshot) => (\n <div\n className={classNames('placeholder', 'text-muted', {\n 'is-dragging-from-this': snapshot.draggingFromThisWith,\n 'is-dragging-over': snapshot.isDraggingOver,\n 'is-dropping': snapshot.draggingOverWith,\n })}\n ref={provided.innerRef}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...provided.droppableProps}\n >\n Create rollup by dragging columns here, from the available\n columns list below.\n </div>\n )}\n </Droppable>\n )}\n {columns.length > 0 && (\n <DraggableItemList\n draggingItemClassName=\"rollup-rows-dragging-grouped-item\"\n draggablePrefix={GROUPED_LIST_ID}\n droppableId={GROUPED_LIST_ID}\n itemCount={columns.length}\n items={columns}\n offset={0}\n onSelectionChange={this.handleGroupedSelectionChange}\n ref={this.groupedList}\n renderItem={this.renderGroupedItem}\n selectedRanges={groupedSelectedRanges}\n style={{ height: groupListHeight }}\n isMultiSelect\n />\n )}\n </div>\n <div className=\"rollup-rows-available-columns\">\n <div className=\"section-title\">Available Grouping Columns</div>\n <div className=\"top-menu\">\n <SearchInput\n className=\"w-100\"\n value={searchFilter}\n matchCount={\n searchFilter ? ungroupedSelectedRanges.length : null\n }\n placeholder=\"Find column...\"\n onChange={this.handleSearchChange}\n />\n <ButtonOld\n className={classNames('btn-link btn-link-icon', {\n active: sort === RollupRows.SORT.ASCENDING,\n })}\n onClick={this.handleSortAscending}\n >\n <FontAwesomeIcon icon={dhSortAlphaDown} />\n <Tooltip>Sort ascending</Tooltip>\n </ButtonOld>\n <ButtonOld\n className={classNames('btn-link btn-link-icon', {\n active: sort === RollupRows.SORT.DESCENDING,\n })}\n onClick={this.handleSortDescending}\n >\n <FontAwesomeIcon icon={dhSortAlphaUp} />\n <Tooltip>Sort descending</Tooltip>\n </ButtonOld>\n </div>\n <DraggableItemList\n className=\"rollup-available-grouping-columns\"\n draggablePrefix={UNGROUPED_LIST_ID}\n droppableId={UNGROUPED_LIST_ID}\n itemCount={ungroupedColumns.length}\n items={ungroupedColumns}\n renderItem={RollupRows.renderColumn}\n offset={0}\n onSelect={this.handleUngroupedSelect}\n onSelectionChange={this.handleUngroupedSelectionChange}\n ref={this.ungroupedList}\n selectedRanges={ungroupedSelectedRanges}\n style={{\n maxHeight: ungroupMaxListHeight,\n minHeight: ungroupMinListHeight,\n }}\n isDropDisabled={dragSource?.droppableId !== GROUPED_LIST_ID}\n isMultiSelect\n />\n <div className=\"bottom-menu\">\n <div className=\"label\">Show:</div>\n <Checkbox\n checked={showConstituents}\n onChange={this.handleShowConstituentsChange}\n >\n Constituents\n </Checkbox>\n <Checkbox\n checked={showNonAggregatedColumns}\n onChange={this.handleShowNonAggregatedColumnsChange}\n >\n Non-Aggregated Columns\n </Checkbox>\n </div>\n </div>\n </DragDropContext>\n </div>\n );\n }\n}\n\nRollupRows.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n onChange: PropTypes.func,\n config: PropTypes.shape({\n columns: PropTypes.arrayOf(PropTypes.string),\n showConstituents: PropTypes.bool,\n showNonAggregatedColumns: PropTypes.bool,\n }),\n};\n\nRollupRows.defaultProps = {\n config: null,\n onChange: () => {},\n};\n\nexport default RollupRows;\n","import React, { useCallback } from 'react';\nimport classNames from 'classnames';\n\nexport type SelectProps = {\n children: React.ReactNode;\n onChange: (value: string) => void;\n className?: string;\n defaultValue?: string;\n value?: string;\n disabled?: boolean;\n};\n\nconst Select = ({\n children,\n onChange,\n className,\n defaultValue,\n value,\n disabled,\n}: SelectProps): JSX.Element => {\n const handleChange = useCallback(\n event => {\n onChange(event.target.value);\n },\n [onChange]\n );\n\n return (\n <select\n className={classNames('custom-select', className)}\n onChange={handleChange}\n defaultValue={defaultValue}\n value={value}\n disabled={disabled}\n >\n {children}\n </select>\n );\n};\n\nexport default Select;\n","import React from 'react';\n\nexport type OptionProps = {\n children: React.ReactNode;\n value: string;\n};\n\nconst Option = ({ children, value }: OptionProps): JSX.Element => (\n <option value={value}>{children}</option>\n);\n\nexport default Option;\n","import React, {\n ChangeEvent,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { DragDropContext } from 'react-beautiful-dnd';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n dhNewCircleLargeFilled,\n vsTrash,\n vsEdit,\n dhWarningFilled,\n} from '@deephaven/icons';\nimport Log from '@deephaven/log';\nimport {\n DraggableItemList,\n DragUtils,\n Option,\n Select,\n RadioItem,\n RadioGroup,\n Button,\n} from '@deephaven/components';\nimport type { DraggableRenderItemProps, Range } from '@deephaven/components';\nimport AggregationOperation from './AggregationOperation';\nimport AggregationUtils from './AggregationUtils';\nimport './Aggregations.scss';\n\nconst log = Log.module('Aggregations');\n\nexport type Aggregation = {\n operation: AggregationOperation;\n selected: string[];\n invert: boolean;\n};\n\nexport type AggregationSettings = {\n aggregations: Aggregation[];\n showOnTop: boolean;\n};\n\nexport type AggregationsProps = {\n isRollup: boolean;\n settings: AggregationSettings;\n onChange: (settings: AggregationSettings) => void;\n onEdit: (aggregation: Aggregation) => void;\n};\n\nexport const SELECTABLE_OPTIONS = [\n AggregationOperation.SUM,\n AggregationOperation.ABS_SUM,\n AggregationOperation.MIN,\n AggregationOperation.MAX,\n AggregationOperation.VAR,\n AggregationOperation.AVG,\n AggregationOperation.STD,\n AggregationOperation.FIRST,\n AggregationOperation.LAST,\n AggregationOperation.COUNT_DISTINCT,\n AggregationOperation.DISTINCT,\n AggregationOperation.COUNT,\n AggregationOperation.UNIQUE,\n];\n\nconst Aggregations = ({\n isRollup,\n settings,\n onChange,\n onEdit,\n}: AggregationsProps): JSX.Element => {\n const { aggregations, showOnTop } = settings;\n const options = useMemo(\n () =>\n SELECTABLE_OPTIONS.filter(\n option =>\n !aggregations.some(aggregation => aggregation.operation === option)\n ),\n [aggregations]\n );\n const [selectedOperation, setSelectedOperation] = useState(options[0]);\n const [selectedRanges, setSelectedRanges] = useState<Range[]>([]);\n const changeSettings = useCallback(\n changedSettings => {\n onChange({ ...settings, ...changedSettings });\n },\n [onChange, settings]\n );\n const changeAggregations = useCallback(\n newAggregations => {\n changeSettings({ aggregations: newAggregations });\n },\n [changeSettings]\n );\n\n const changeShowOnTop = useCallback(\n newShowOnTop => {\n changeSettings({ showOnTop: newShowOnTop });\n },\n [changeSettings]\n );\n\n const handleDragStart = useCallback(() => {\n log.debug('handleDragStart');\n\n DragUtils.startDragging();\n }, []);\n\n const handleDragEnd = useCallback(\n ({ destination, source }) => {\n log.debug('handleDragEnd', destination, source);\n\n DragUtils.stopDragging();\n\n if (destination === null) {\n return;\n }\n\n let destinationIndex = destination.index;\n if (source.index < destination.index) {\n destinationIndex += 1;\n }\n\n const newAggregations = [...aggregations];\n const draggedItems = DragUtils.reorder(\n newAggregations,\n selectedRanges,\n newAggregations,\n destinationIndex\n );\n const insertIndex = DragUtils.adjustDestinationIndex(\n destinationIndex,\n selectedRanges\n );\n const newSelectedRanges: Range[] = [\n [insertIndex, insertIndex + draggedItems.length - 1],\n ];\n changeAggregations(newAggregations);\n setSelectedRanges(newSelectedRanges);\n },\n [changeAggregations, aggregations, selectedRanges, setSelectedRanges]\n );\n\n const handleOperationChange = useCallback(\n operation => {\n setSelectedOperation(operation);\n },\n [setSelectedOperation]\n );\n\n const handleAdd = useCallback(() => {\n changeAggregations([\n ...aggregations,\n { operation: selectedOperation, selected: [], invert: true },\n ]);\n }, [aggregations, selectedOperation, changeAggregations]);\n\n const handleDeleteClicked = useCallback(\n (itemIndex: number) => {\n changeAggregations(\n aggregations.filter((aggregation, index) => index !== itemIndex)\n );\n },\n [aggregations, changeAggregations]\n );\n\n const handleAggregationSelectionChange = useCallback(\n newSelectedRanges => {\n setSelectedRanges(newSelectedRanges);\n },\n [setSelectedRanges]\n );\n\n const handleAggregationSelect = useCallback(\n itemIndex => {\n const aggregation = aggregations[itemIndex];\n if (!AggregationUtils.isRollupOperation(aggregation.operation)) {\n onEdit(aggregation);\n }\n },\n [aggregations, onEdit]\n );\n\n const handleShowOnTopChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n changeShowOnTop(event.target.value === 'true');\n },\n [changeShowOnTop]\n );\n\n useEffect(() => {\n if (options.length > 0 && !options.includes(selectedOperation)) {\n setSelectedOperation(options[0]);\n }\n }, [options, selectedOperation]);\n\n const renderAggregation = useCallback(\n ({\n item,\n itemIndex,\n isClone,\n selectedCount,\n }: DraggableRenderItemProps<Aggregation>) => {\n const text = item.operation;\n const badgeText = isClone ? `${selectedCount}` : undefined;\n const className = isClone ? 'item-list-item-clone' : undefined;\n const isRollupOperation = AggregationUtils.isRollupOperation(\n item.operation\n );\n const isEditable = !isClone && !isRollupOperation;\n return (\n <>\n <div\n className={classNames(\n 'item-list-item-content',\n 'draggable-item-list-item-content',\n className\n )}\n >\n <span className=\"title\">\n {text}\n {!isRollup && isRollupOperation && (\n <span className=\"small text-warning\">\n <FontAwesomeIcon icon={dhWarningFilled} /> Requires rollup\n </span>\n )}\n </span>\n {DraggableItemList.renderBadge({ text: badgeText })}\n {DraggableItemList.renderHandle()}\n </div>\n {!isClone && (\n <>\n <Button\n kind=\"ghost\"\n className=\"btn-edit\"\n icon={vsEdit}\n tooltip=\"Edit Columns\"\n onClick={() => onEdit(item)}\n disabled={!isEditable}\n />\n <Button\n kind=\"ghost\"\n className=\"btn-delete\"\n icon={vsTrash}\n tooltip=\"Delete Aggregation\"\n onClick={() => handleDeleteClicked(itemIndex)}\n />\n </>\n )}\n </>\n );\n },\n [handleDeleteClicked, onEdit, isRollup]\n );\n\n const isOptionsShown = options.length > 0;\n const isAggregationsShown = aggregations.length > 0;\n\n return (\n <div className=\"aggregations\">\n {isOptionsShown && (\n <div className=\"form-inline\">\n <Select onChange={handleOperationChange} value={selectedOperation}>\n {options.map(option => (\n <Option value={option} key={option}>\n {option}\n </Option>\n ))}\n </Select>\n <button\n type=\"button\"\n className=\"btn btn-link btn-add\"\n onClick={handleAdd}\n >\n <FontAwesomeIcon icon={dhNewCircleLargeFilled} />\n Add Aggregation\n </button>\n </div>\n )}\n {isOptionsShown && isAggregationsShown && <hr />}\n {isAggregationsShown && (\n <>\n {!isRollup && (\n <div className=\"form-inline\">\n <label>Placement:&nbsp;</label>\n <RadioGroup\n onChange={handleShowOnTopChange}\n value={`${showOnTop}`}\n >\n <RadioItem value=\"true\">Top</RadioItem>\n <RadioItem value=\"false\">Bottom</RadioItem>\n </RadioGroup>\n </div>\n )}\n <DragDropContext\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <DraggableItemList<Aggregation>\n className=\"selected-aggregations\"\n itemCount={aggregations.length}\n items={aggregations}\n renderItem={renderAggregation}\n offset={0}\n onSelectionChange={handleAggregationSelectionChange}\n onSelect={handleAggregationSelect}\n selectedRanges={selectedRanges}\n isMultiSelect\n />\n </DragDropContext>\n </>\n )}\n </div>\n );\n};\n\nexport default Aggregations;\n","import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport classNames from 'classnames';\nimport { CSSTransition } from 'react-transition-group';\nimport { Button, Checkbox, ItemList, ThemeExport } from '@deephaven/components';\nimport { dhSortAlphaDown, dhSortAlphaUp } from '@deephaven/icons';\nimport type { Column } from '@deephaven/jsapi-shim';\nimport { Aggregation } from './Aggregations';\nimport { filterValidColumns } from './AggregationUtils';\nimport './AggregationEdit.scss';\nimport TableUtils from '../../TableUtils';\n\ninterface AggregationEditItem {\n value: string;\n displayValue: string;\n}\n\nexport type AggregationEditProps = {\n aggregation: Aggregation;\n columns: Column[];\n onChange: (aggregation: Aggregation) => void;\n};\n\nenum SortType {\n NONE,\n ASCENDING,\n DESCENDING,\n}\n\nconst DEFAULT_ROW_HEIGHT = 30;\n\nconst AggregationEdit = ({\n aggregation,\n columns,\n onChange,\n}: AggregationEditProps): JSX.Element => {\n const [top, setTop] = useState(-1);\n const [bottom, setBottom] = useState(-1);\n const [sort, setSort] = useState(SortType.NONE);\n const { invert, selected } = aggregation;\n const list = useRef<ItemList<AggregationEditItem>>(null);\n\n const isSelected = useCallback(\n name => (selected.includes(name) ? !invert : invert),\n [invert, selected]\n );\n\n const validColumns = useMemo(() => {\n let filteredColumns = filterValidColumns(columns, aggregation.operation);\n if (sort !== SortType.NONE) {\n filteredColumns = TableUtils.sortColumns(\n filteredColumns,\n sort === SortType.ASCENDING\n );\n }\n return filteredColumns;\n }, [columns, aggregation.operation, sort]);\n\n const items = useMemo(\n () =>\n top >= 0\n ? validColumns.slice(top, bottom + 1).map(c => ({\n value: c.name,\n displayValue: c.name,\n isSelected: isSelected(c.name),\n }))\n : [],\n [validColumns, isSelected, bottom, top]\n );\n\n const handleSelect = useCallback(\n itemIndex => {\n const { name } = validColumns[itemIndex];\n const selectedIndex = selected.indexOf(name);\n let newSelected = [...selected];\n let newInvert = invert;\n if (selectedIndex >= 0) {\n newSelected.splice(selectedIndex, 1);\n } else {\n newSelected.push(name);\n if (newSelected.length === validColumns.length) {\n // Every item is either selected or deselected, flip the inversion bit\n newSelected = [];\n newInvert = !invert;\n }\n }\n\n onChange({ ...aggregation, selected: newSelected, invert: newInvert });\n },\n [aggregation, invert, validColumns, selected, onChange]\n );\n\n const handleReset = useCallback(() => {\n setSort(SortType.NONE);\n onChange({ ...aggregation, selected: [], invert: true });\n }, [aggregation, onChange]);\n\n const handleViewportChange = useCallback(\n (newTop, newBottom) => {\n setTop(newTop);\n setBottom(newBottom);\n },\n [setTop, setBottom]\n );\n\n const toggleAll = useCallback(() => {\n if (selected.length === 0) {\n onChange({ ...aggregation, invert: !invert });\n } else {\n onChange({ ...aggregation, selected: [], invert: true });\n }\n }, [aggregation, invert, onChange, selected]);\n\n const checked = selected.length === 0 ? invert : null;\n const isModified = selected.length !== 0 || !invert || sort !== SortType.NONE;\n\n return (\n <div role=\"menu\" className=\"aggregation-edit\">\n <div className=\"top-menu\">\n <div className=\"form-inline\">\n <Checkbox checked={checked} onChange={toggleAll}>\n Toggle All\n </Checkbox>\n <div className=\"spacer\" />\n <CSSTransition\n in={isModified}\n timeout={ThemeExport.transitionSlowMs}\n classNames=\"fade\"\n mountOnEnter\n unmountOnExit\n >\n <Button kind=\"ghost\" className=\"btn-reset\" onClick={handleReset}>\n Reset\n </Button>\n </CSSTransition>\n <Button\n kind=\"ghost\"\n className={classNames({\n active: sort === SortType.ASCENDING,\n })}\n icon={dhSortAlphaDown}\n tooltip=\"Sort ascending\"\n onClick={() => setSort(SortType.ASCENDING)}\n />\n <Button\n kind=\"ghost\"\n className={classNames({\n active: sort === SortType.DESCENDING,\n })}\n icon={dhSortAlphaUp}\n tooltip=\"Sort descending\"\n onClick={() => setSort(SortType.DESCENDING)}\n />\n </div>\n </div>\n <div className=\"aggregation-edit-item-list\">\n <ItemList\n itemCount={validColumns.length}\n items={items}\n offset={top}\n renderItem={({ item }) => (\n <Checkbox checked={isSelected(item.value)}>\n {item.displayValue}\n </Checkbox>\n )}\n onSelect={handleSelect}\n onViewportChange={handleViewportChange}\n rowHeight={DEFAULT_ROW_HEIGHT}\n focusSelector=\"input\"\n ref={list}\n />\n </div>\n </div>\n );\n};\n\nexport default AggregationEdit;\n","import { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport { WritableStream as ponyfillWritableStream } from 'web-streams-polyfill/dist/ponyfill.js';\nimport dh from '@deephaven/jsapi-shim';\nimport Log from '@deephaven/log';\nimport { PromiseUtils } from '@deephaven/utils';\nimport Formatter from '../Formatter';\n\nconst log = Log.module('TableSaver');\n\nexport default class TableSaver extends PureComponent {\n static DOWNLOAD_CELL_CHUNK = 6000;\n\n static SNAPSHOT_BUFFER_SIZE = 5;\n\n static STREAM_TIMEOUT = 8000;\n\n static SNAPSHOT_HANDLER_TIMEOUT = 5;\n\n static csvEscapeString(str) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n constructor(props) {\n super(props);\n\n this.handlePortMessage = this.handlePortMessage.bind(this);\n this.handleSnapshotResolved = this.handleSnapshotResolved.bind(this);\n this.handleDownloadTimeout = this.handleDownloadTimeout.bind(this);\n\n this.state = {};\n\n this.sw = null;\n this.port = null;\n this.fileWriter = null;\n\n this.table = null;\n this.tableSubscription = null;\n this.columns = null;\n\n this.fileName = null;\n\n this.chunkRows = null;\n\n this.gridRanges = [];\n this.gridRangeCounter = 0;\n this.rangedSnapshotsTotal = [];\n this.rangedSnapshotCounter = 0;\n\n this.snapshotsTotal = 0;\n this.snapshotCounter = 0;\n this.snapshotsBuffer = new Map();\n\n this.currentSnapshotIndex = 0;\n this.snapshotPending = 0;\n this.cancelableSnapshots = [];\n\n // WritableStream is not supported in Firefox (also IE) yet. use ponyfillWritableStream instead\n this.WritableStream = window.WritableStream || ponyfillWritableStream;\n\n // Due to an open issue in Chromium, readableStream.cancel() is never called when a user cancel the stream from Chromium's UI and the stream goes on even it's canceled.\n // Instead, we monitor the pull() behavior from the readableStream called when the stream wants more data to write.\n // If the stream doesn't pull for long enough time, chances are the stream is already canceled, so we stop the stream.\n // Issue ticket on Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=638494\n this.streamTimeout = null;\n\n this.snapshotHandlerTimeout = null;\n\n this.downloadStartTime = null;\n\n this.iframes = [];\n\n this.useBlobFallback = !!window.safari;\n }\n\n componentDidMount() {\n const { getDownloadWorker } = this.props;\n getDownloadWorker()\n .then(sw => {\n log.info('found active service worker');\n this.sw = sw;\n this.sw.postMessage('ping'); // just to activate the service worker\n })\n .catch(error => {\n // if service worker is not available, use blob as fallback to download table csv\n log.warn('Download csv is not optimized.', error);\n this.useBlobFallback = true;\n });\n }\n\n componentWillUnmount() {\n if (this.iframes.length > 0) {\n this.iframes.forEach(iframe => {\n iframe.remove();\n });\n }\n clearTimeout(this.streamTimeout);\n clearTimeout(this.snapshotHandlerTimeout);\n }\n\n createWriterStream(port) {\n // use blob fall back if it's safari\n const useBlob = this.useBlobFallback;\n const chunks = [];\n let encode = null;\n if (useBlob) {\n encode = TextEncoder.prototype.encode.bind(new TextEncoder());\n }\n const { fileName } = this;\n\n const streamConfig = {};\n if (useBlob) {\n streamConfig.write = chunk => {\n chunks.push(encode(chunk.rows));\n };\n streamConfig.close = () => {\n const blob = new Blob(chunks, {\n type: 'application/octet-stream; charset=utf-8',\n });\n const link = document.createElement('a');\n link.href = URL.createObjectURL(blob);\n link.download = fileName;\n link.click();\n };\n streamConfig.abort = () => {\n port.postMessage({ cancel: true });\n port.close();\n };\n } else {\n streamConfig.write = chunk => {\n port.postMessage(chunk);\n };\n streamConfig.close = () => {\n port.postMessage({ end: true });\n port.close();\n };\n streamConfig.abort = () => {\n port.postMessage({ cancel: true });\n port.close();\n };\n }\n\n return new this.WritableStream(streamConfig);\n }\n\n startDownload(fileName, frozenTable, tableSubscription, gridRanges) {\n // don't trigger another download when a download is ongoing\n const { isDownloading } = this.props;\n if (isDownloading) {\n return;\n }\n\n this.downloadStartTime = Date.now();\n log.info(`start downloading ${fileName}`);\n\n this.table = frozenTable;\n this.columns = frozenTable.columns;\n this.tableSubscription = tableSubscription;\n this.gridRanges = gridRanges;\n\n // Make filename RFC5987 compatible\n const encodedFileName = encodeURIComponent(fileName.replace(/\\//g, ':'))\n .replace(/['()]/g, escape)\n .replace(/\\*/g, '%2A');\n\n const messageChannel = new MessageChannel();\n this.port = messageChannel.port1;\n this.fileName = fileName;\n this.fileWriter = this.createWriterStream(this.port).getWriter();\n\n // if the browser doesn't support stream or there's no active service worker, use blobs for table download\n if (this.useBlobFallback) {\n this.writeCsvTable();\n return;\n }\n\n if (this.sw) {\n // send file name and port to service worker\n this.sw.postMessage({ encodedFileName }, [messageChannel.port2]);\n }\n this.port.onmessage = this.handlePortMessage;\n }\n\n finishDownload() {\n if (this.table) {\n this.table.close();\n }\n if (this.tableSubscription) {\n this.tableSubscription.close();\n }\n if (this.fileWriter) {\n this.fileWriter.close();\n }\n\n const { onDownloadCompleted } = this.props;\n onDownloadCompleted();\n this.resetTableSaver();\n\n log.info(\n `download finished, total elapsed time ${\n (Date.now() - this.downloadStartTime) / 1000\n } seconds`\n );\n }\n\n cancelDownload() {\n if (this.table) {\n this.table.close();\n }\n if (this.tableSubscription) {\n this.tableSubscription.close();\n }\n if (this.fileWriter) {\n this.fileWriter.abort();\n }\n\n this.cancelableSnapshots.forEach(cancelable => {\n if (cancelable) {\n cancelable.catch(() => {});\n cancelable.cancel();\n }\n });\n const { onDownloadCanceled } = this.props;\n onDownloadCanceled();\n this.resetTableSaver();\n }\n\n resetTableSaver() {\n this.table = null;\n this.tableSubscription = null;\n this.columns = null;\n this.chunkRows = null;\n\n this.gridRanges = [];\n this.gridRangeCounter = 0;\n this.rangedSnapshotsTotal = [];\n this.rangedSnapshotCounter = 0;\n\n this.snapshotsTotal = 0;\n this.snapshotCounter = 0;\n this.snapshotsBuffer = new Map();\n\n this.currentSnapshotIndex = 0;\n this.snapshotPending = 0;\n this.cancelableSnapshots = [];\n\n clearTimeout(this.streamTimeout);\n clearTimeout(this.snapshotHandlerTimeout);\n this.streamTimeout = null;\n this.snapshotHandlerTimeout = null;\n }\n\n handleDownloadTimeout() {\n log.info('download canceled');\n this.cancelDownload();\n }\n\n writeTableHeader() {\n let headerString = '';\n for (let i = 0; i < this.columns.length; i += 1) {\n headerString += this.columns[i].name;\n headerString += i === this.columns.length - 1 ? '\\n' : ',';\n }\n this.fileWriter.write({ header: headerString }).then(() => {});\n }\n\n startWriteTableBody() {\n this.chunkRows = Math.floor(\n TableSaver.DOWNLOAD_CELL_CHUNK / this.columns.length\n );\n\n this.rangedSnapshotsTotal = this.gridRanges.map(range =>\n Math.ceil((range.endRow - range.startRow + 1) / this.chunkRows)\n );\n this.snapshotsTotal = this.rangedSnapshotsTotal.reduce(\n (total, snapshotCount) => total + snapshotCount\n );\n\n log.info(`start writing table, total snapshots: `, this.snapshotsTotal);\n\n this.makeSnapshot(\n Math.min(TableSaver.SNAPSHOT_BUFFER_SIZE, this.snapshotsTotal)\n );\n }\n\n writeCsvTable() {\n this.writeTableHeader();\n this.startWriteTableBody();\n }\n\n writeSnapshot(snapshotIndex, snapshotStartRow, snapshotEndRow) {\n if (this.currentSnapshotIndex === snapshotIndex && this.fileWriter) {\n while (this.snapshotsBuffer.has(this.currentSnapshotIndex)) {\n this.fileWriter.write({\n rows: this.convertSnapshotIntoCsv(\n this.snapshotsBuffer.get(this.currentSnapshotIndex),\n snapshotStartRow,\n snapshotEndRow\n ),\n });\n this.snapshotsBuffer.delete(this.currentSnapshotIndex);\n this.currentSnapshotIndex += 1;\n\n this.updateDownloadProgress(snapshotIndex);\n }\n if (this.currentSnapshotIndex >= this.snapshotsTotal) {\n this.finishDownload();\n return;\n }\n }\n\n if (this.snapshotCounter < this.snapshotsTotal) {\n log.debug2(\n `\n current range index: ${this.gridRangeCounter}, \n snapshotIndexCounter: ${this.snapshotCounter}, \n currentRangedSnapshotIndex : ${this.rangedSnapshotCounter}, \n snapshotpending: ${this.snapshotPending}, \n buffered ${this.snapshotsBuffer.size}\n making ${Math.min(\n TableSaver.SNAPSHOT_BUFFER_SIZE -\n this.snapshotsBuffer.size -\n this.snapshotPending,\n this.snapshotsTotal - this.snapshotCounter\n )} more snapshots\n `\n );\n this.makeSnapshot(\n Math.min(\n TableSaver.SNAPSHOT_BUFFER_SIZE -\n this.snapshotsBuffer.size -\n this.snapshotPending,\n this.snapshotsTotal - this.snapshotCounter\n )\n );\n }\n }\n\n updateDownloadProgress(snapshotIndex) {\n const { onDownloadProgressUpdate } = this.props;\n const downloadProgress = Math.floor(\n (snapshotIndex * 100) / this.snapshotsTotal\n );\n const estimateTime =\n snapshotIndex > 1\n ? Math.floor(\n ((Date.now() - this.downloadStartTime) *\n (this.snapshotsTotal - snapshotIndex)) /\n snapshotIndex /\n 1000\n )\n : null;\n\n onDownloadProgressUpdate(downloadProgress, estimateTime);\n }\n\n convertSnapshotIntoCsv(snapshot) {\n let csvString = '';\n const snapshotIterator = snapshot.added.iterator();\n const { formatter } = this.props;\n\n const rows = [];\n while (snapshotIterator.hasNext()) {\n rows.push(snapshotIterator.next().value);\n }\n\n for (let i = 0; i < rows.length; i += 1) {\n const rowIdx = rows[i];\n for (let j = 0; j < this.columns.length; j += 1) {\n const cellData = formatter.getFormattedString(\n snapshot.getData(rowIdx, this.columns[j]),\n this.columns[j].type,\n this.columns[j].name\n );\n csvString += TableSaver.csvEscapeString(cellData);\n csvString += j === this.columns.length - 1 ? '\\n' : ',';\n }\n }\n\n return csvString;\n }\n\n makeSnapshot(n) {\n if (n <= 0) {\n return;\n }\n let i = 0;\n let currentGridRange = this.gridRanges[this.gridRangeCounter];\n while (i < n) {\n const snapshotStartRow =\n currentGridRange.startRow + this.rangedSnapshotCounter * this.chunkRows;\n const snapshotEndRow = Math.min(\n snapshotStartRow + this.chunkRows - 1,\n currentGridRange.endRow\n );\n\n const snapshotIndex = this.snapshotCounter;\n this.cancelableSnapshots.push(\n PromiseUtils.makeCancelable(\n this.tableSubscription\n .snapshot(\n dh.RangeSet.ofRange(snapshotStartRow, snapshotEndRow),\n this.columns\n )\n .then(snapshot => {\n this.handleSnapshotResolved(\n snapshot,\n snapshotIndex,\n snapshotStartRow,\n snapshotEndRow\n );\n\n return snapshotIndex;\n })\n .catch(err => {\n log.error(err);\n }),\n val => {\n log.info(`snapshot ${val} has been canceled`);\n }\n )\n );\n\n this.rangedSnapshotCounter += 1;\n this.snapshotCounter += 1;\n this.snapshotPending += 1;\n\n if (\n this.rangedSnapshotCounter >=\n this.rangedSnapshotsTotal[this.gridRangeCounter]\n ) {\n this.gridRangeCounter += 1;\n this.rangedSnapshotCounter = 0;\n currentGridRange = this.gridRanges[this.gridRangeCounter];\n }\n i += 1;\n }\n }\n\n handlePortMessage({ data }) {\n const { download, readableStreamPulling } = data;\n if (this.useBlobFallback) {\n return;\n }\n if (download) {\n this.makeIframe(`${download}`);\n this.writeCsvTable();\n }\n if (readableStreamPulling) {\n if (!this.useBlobFallback) {\n clearTimeout(this.streamTimeout);\n\n this.streamTimeout = setTimeout(\n this.handleDownloadTimeout,\n TableSaver.STREAM_TIMEOUT\n );\n }\n }\n }\n\n handleSnapshotResolved(\n snapshot,\n snapshotIndex,\n snapshotStartRow,\n snapshotEndRow\n ) {\n // use time out to break writeSnapshot into an individual task in browser with timeout, so there's window for the browser to update table in needed.\n this.snapshotHandlerTimeout = setTimeout(() => {\n this.snapshotsBuffer.set(snapshotIndex, snapshot);\n this.snapshotPending -= 1;\n this.writeSnapshot(snapshotIndex, snapshotStartRow, snapshotEndRow);\n this.cancelableSnapshots[snapshotIndex] = null;\n }, TableSaver.SNAPSHOT_HANDLER_TIMEOUT);\n }\n\n makeIframe(src) {\n // make a return value and make it static method\n const iframe = document.createElement('iframe');\n iframe.hidden = true;\n iframe.src = `download/${src}`;\n iframe.loaded = false;\n iframe.name = 'iframe';\n iframe.isIframe = true;\n iframe.addEventListener(\n 'load',\n () => {\n iframe.loaded = true;\n },\n false\n );\n document.body.appendChild(iframe);\n this.iframes.push(iframe);\n }\n\n render() {\n return null;\n }\n}\n\nTableSaver.propTypes = {\n getDownloadWorker: PropTypes.func,\n isDownloading: PropTypes.bool,\n onDownloadCompleted: PropTypes.func,\n onDownloadCanceled: PropTypes.func,\n onDownloadProgressUpdate: PropTypes.func,\n formatter: PropTypes.instanceOf(Formatter).isRequired,\n};\n\nTableSaver.defaultProps = {\n getDownloadWorker: () =>\n Promise.reject(new Error('Download worker not provided')),\n isDownloading: false,\n onDownloadCompleted: () => {},\n onDownloadCanceled: () => {},\n onDownloadProgressUpdate: () => {},\n};\n","import React, { PureComponent } from 'react';\nimport PropTypes from 'prop-types';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { Checkbox, Popper, SearchInput, Tooltip } from '@deephaven/components';\nimport {\n dhGearFilled,\n dhCheckSquare,\n dhSquareFilled,\n dhRemoveSquareFilled,\n dhWarningCircleFilled,\n vsCircleLargeFilled,\n} from '@deephaven/icons';\nimport dh from '@deephaven/jsapi-shim';\nimport TableUtils from './TableUtils';\nimport './CrossColumnSearch.scss';\n\nclass CrossColumnSearch extends PureComponent {\n static createSearchFilter(\n searchValue,\n selectedColumns,\n columns,\n invertSelection\n ) {\n const filterColumns = invertSelection\n ? columns\n .filter(column => !selectedColumns.includes(column.name))\n .map(column => column.name)\n : selectedColumns;\n if (searchValue && filterColumns.length > 0) {\n const filterValue = dh.FilterValue.ofString(searchValue);\n const searchFilter =\n filterColumns.length === columns.length\n ? dh.FilterCondition.search(filterValue)\n : dh.FilterCondition.search(\n filterValue,\n columns\n .filter(column => filterColumns.includes(column.name))\n .map(column => column.filter())\n );\n return searchFilter;\n }\n return null;\n }\n\n constructor(props) {\n super(props);\n this.handleSearchValueChange = this.handleSearchValueChange.bind(this);\n this.toggleColumn = this.toggleColumn.bind(this);\n this.selectAll = this.selectAll.bind(this);\n this.clear = this.clear.bind(this);\n this.selectNumbers = this.selectNumbers.bind(this);\n\n this.searchField = React.createRef();\n\n this.state = {\n isConfigureColumnsShown: false,\n };\n }\n\n focus() {\n this.searchField.current.focus();\n }\n\n handleSearchValueChange(event) {\n const { onChange, selectedColumns, invertSelection } = this.props;\n onChange(event.target.value, selectedColumns, invertSelection);\n }\n\n sendColumnChange(selectedColumns, invertSelection) {\n const { onChange, value } = this.props;\n onChange(value, selectedColumns, invertSelection);\n }\n\n setInvertSelection(invertSelection) {\n const { onChange, value } = this.props;\n onChange(value, [], invertSelection);\n }\n\n toggleColumn(name) {\n const { selectedColumns, invertSelection } = this.props;\n if (selectedColumns.includes(name)) {\n this.sendColumnChange(\n selectedColumns.filter(c => c !== name),\n invertSelection\n );\n } else {\n const update = selectedColumns.slice();\n update.push(name);\n this.sendColumnChange(update, invertSelection);\n }\n }\n\n selectAll() {\n this.setInvertSelection(true);\n }\n\n clear() {\n this.setInvertSelection(false);\n }\n\n selectNumbers() {\n const { columns } = this.props;\n this.sendColumnChange(\n columns\n .filter(c => TableUtils.isNumberType(c.type))\n .map(column => column.name),\n false\n );\n }\n\n render() {\n const { value, selectedColumns, invertSelection, columns } = this.props;\n const { isConfigureColumnsShown } = this.state;\n const hasAllColumnsSelected =\n (selectedColumns.length === 0 && invertSelection === true) ||\n (selectedColumns.length === columns.length && invertSelection === false);\n const hasNoColumnsSelected =\n (selectedColumns.length === 0 && invertSelection === false) ||\n (selectedColumns.length === columns.length && invertSelection === true);\n\n // set icon layers\n let icon;\n if (hasAllColumnsSelected) {\n // icon if all columns selected for search\n icon = (\n <>\n <FontAwesomeIcon\n icon={dhSquareFilled}\n mask={dhGearFilled}\n transform=\"shrink-2 down-5 right-7\"\n />\n <FontAwesomeIcon\n icon={dhCheckSquare}\n className=\"text-primary\"\n transform=\"shrink-4 down-5 right-7\"\n />\n </>\n );\n } else if (hasNoColumnsSelected) {\n // icon error, no columns selected for searching\n icon = (\n <>\n <FontAwesomeIcon\n icon={vsCircleLargeFilled}\n mask={dhGearFilled}\n transform=\"shrink-1 down-5 right-7\"\n />\n <FontAwesomeIcon\n icon={dhWarningCircleFilled}\n className=\"text-danger\"\n transform=\"shrink-4 down-5 right-7\"\n />\n </>\n );\n } else {\n // icon if some columns selected, but not all\n icon = (\n <>\n <FontAwesomeIcon\n icon={dhSquareFilled}\n mask={dhGearFilled}\n transform=\"shrink-2 down-5 right-7\"\n />\n <FontAwesomeIcon\n icon={dhRemoveSquareFilled}\n className=\"text-primary\"\n transform=\"shrink-4 down-5 right-7\"\n />\n </>\n );\n }\n\n return (\n <div className=\"cross-column-container\">\n <SearchInput\n className=\"cross-column-search\"\n placeholder=\"Search Data...\"\n value={value}\n onChange={this.handleSearchValueChange}\n ref={this.searchField}\n />\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon px-2\"\n onClick={() => {\n if (isConfigureColumnsShown) {\n this.setState({ isConfigureColumnsShown: false });\n } else {\n this.setState({ isConfigureColumnsShown: true });\n }\n }}\n >\n <div className=\"fa-layers\">{icon}</div>\n <Tooltip>Configure Columns</Tooltip>\n <Popper\n isShown={isConfigureColumnsShown}\n className=\"cross-column-popper\"\n onExited={() => {\n this.setState({ isConfigureColumnsShown: false });\n }}\n closeOnBlur\n interactive\n >\n <div className=\"cross-column-popup\">\n Searched Columns\n <div className=\"cross-column-scroll\">\n {columns.map(column => (\n <React.Fragment key={column.name}>\n <Checkbox\n className=\"cross-column-checkbox\"\n checked={\n invertSelection\n ? !selectedColumns.includes(column.name)\n : selectedColumns.includes(column.name)\n }\n onChange={() => this.toggleColumn(column.name)}\n >\n {column.name}\n </Checkbox>\n\n {column.type.substring(column.type.lastIndexOf('.') + 1)}\n </React.Fragment>\n ))}\n </div>\n <div className=\"cross-column-button-bar\">\n <button\n type=\"button\"\n className=\"btn btn-link\"\n onClick={this.selectAll}\n >\n Select All\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link\"\n onClick={this.clear}\n >\n Clear\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link\"\n onClick={this.selectNumbers}\n >\n Numbers Only\n </button>\n </div>\n {hasNoColumnsSelected && (\n <p className=\"text-danger\">\n <FontAwesomeIcon icon={dhWarningCircleFilled} /> Select at\n least one column to search.\n </p>\n )}\n </div>\n </Popper>\n </button>\n </div>\n );\n }\n}\n\nCrossColumnSearch.propTypes = {\n value: PropTypes.string.isRequired,\n selectedColumns: PropTypes.arrayOf(PropTypes.string).isRequired,\n invertSelection: PropTypes.bool.isRequired,\n onChange: PropTypes.func.isRequired,\n columns: PropTypes.arrayOf(\n PropTypes.shape({\n name: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n })\n ).isRequired,\n};\n\nexport default CrossColumnSearch;\n","import React, { PureComponent } from 'react';\nimport ContextActionUtils, {\n ContextAction,\n} from '../context-actions/ContextActionUtils';\nimport ContextMenuItem from '../context-actions/ContextMenuItem';\n\nexport type MenuOptions = {\n doNotVerifyPosition?: boolean;\n separateKeyboardMouse?: boolean;\n initialKeyboardIndex?: number;\n};\n\ntype MenuProps = {\n actions: ContextAction | ContextAction[];\n closeMenu(closeAll: boolean): void;\n onMenuClosed(menu: Menu): void;\n onMenuOpened(menu: Menu): void;\n options: MenuOptions;\n menuStyle: React.CSSProperties;\n};\n\ntype MenuState = {\n menuItems: ContextAction[];\n keyboardIndex: number;\n mouseIndex: number;\n};\n\n/**\n * Do not use this class directly. Use DropdownMenu instead.\n *\n * Generates list from actions for use by DropdownMenu.\n * It has beem split from the context-actions component, due to divergering requirements,\n * but still re-uses styling from context-menu. Depending on how usage evolves, may get split further.\n *\n */\n\nclass Menu extends PureComponent<MenuProps, MenuState> {\n static defaultProps = {\n closeMenu(): void {\n // no-op\n },\n onMenuOpened(): void {\n // no-op\n },\n onMenuClosed(): void {\n // no-op\n },\n options: {},\n menuStyle: {},\n };\n\n constructor(props: MenuProps) {\n super(props);\n\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleMenuItemClick = this.handleMenuItemClick.bind(this);\n this.handleMenuItemMouseMove = this.handleMenuItemMouseMove.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleCloseMenu = this.handleCloseMenu.bind(this);\n\n this.container = React.createRef();\n this.oldFocus = document.activeElement;\n this.rAF = 0;\n\n const { options } = props;\n const keyboardIndex = options.initialKeyboardIndex ?? -1;\n\n this.state = {\n menuItems: [],\n keyboardIndex,\n mouseIndex: -1,\n };\n }\n\n componentDidMount(): void {\n this.initMenu();\n\n this.rAF = window.requestAnimationFrame(() => {\n // set initial focus to container so keyboard navigation works\n // components can still override focus in onMenuOpened callback\n this.container.current?.focus();\n const { onMenuOpened } = this.props;\n onMenuOpened(this);\n });\n }\n\n componentDidUpdate(prevProps: MenuProps): void {\n const { actions } = this.props;\n if (prevProps.actions !== actions) {\n this.initMenu();\n }\n }\n\n componentWillUnmount(): void {\n cancelAnimationFrame(this.rAF);\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n oldFocus: Element | null;\n\n rAF: number;\n\n getKeyboardIndex(): number | null {\n const { options } = this.props;\n if (options.separateKeyboardMouse) {\n const { keyboardIndex } = this.state;\n return keyboardIndex;\n }\n\n return this.getMouseIndex();\n }\n\n setKeyboardIndex(index: number): void {\n const { options } = this.props;\n if (options.separateKeyboardMouse) {\n this.setState({ keyboardIndex: index });\n } else {\n this.setMouseIndex(index);\n }\n }\n\n getMouseIndex(): number {\n const { mouseIndex } = this.state;\n return mouseIndex;\n }\n\n setMouseIndex(index: number): void {\n this.setState({ mouseIndex: index });\n }\n\n initMenu(): void {\n // cancel any pending close\n cancelAnimationFrame(this.rAF);\n\n this.setState({\n menuItems: [],\n });\n\n const { actions } = this.props;\n const menuItems = ContextActionUtils.getMenuItems(actions, false);\n\n if (menuItems.length > 0) {\n this.setState(state => ({\n menuItems: ContextActionUtils.sortActions(\n state.menuItems.concat(menuItems)\n ),\n }));\n }\n }\n\n handleKeyDown(e: React.KeyboardEvent): void {\n const { menuItems } = this.state;\n const oldFocus = this.getKeyboardIndex();\n let newFocus = oldFocus;\n\n if (e.key === 'Enter' || e.key === ' ') {\n if (oldFocus != null && oldFocus >= 0 && oldFocus < menuItems.length) {\n this.handleMenuItemClick(menuItems[oldFocus], e);\n }\n return;\n }\n\n if (e.key === 'Escape') {\n newFocus = null;\n } else if (\n e.key === 'ArrowUp' ||\n (e.key === 'Tab' && e.shiftKey === true)\n ) {\n newFocus = ContextActionUtils.getNextMenuItem(\n newFocus ?? 0,\n -1,\n menuItems\n );\n } else if (\n e.key === 'ArrowDown' ||\n (e.key === 'Tab' && e.shiftKey === false)\n ) {\n newFocus = ContextActionUtils.getNextMenuItem(\n newFocus ?? 0,\n 1,\n menuItems\n );\n }\n\n if (oldFocus !== newFocus) {\n if (newFocus !== null) {\n this.setKeyboardIndex(newFocus);\n } else {\n this.closeMenu();\n if (this.oldFocus instanceof HTMLElement) {\n this.oldFocus.focus();\n }\n }\n\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n closeMenu(closeAll = false): void {\n const { closeMenu, onMenuClosed } = this.props;\n cancelAnimationFrame(this.rAF);\n this.rAF = window.requestAnimationFrame(() => {\n closeMenu(closeAll);\n onMenuClosed(this);\n });\n }\n\n handleCloseMenu(): void {\n this.closeMenu();\n }\n\n handleMenuItemClick(menuItem: ContextAction, e: React.SyntheticEvent): void {\n e.preventDefault();\n e.stopPropagation();\n\n if (menuItem != null && !menuItem.disabled && menuItem.action != null) {\n menuItem.action();\n this.closeMenu(true);\n }\n }\n\n handleMenuItemMouseMove(menuItem: ContextAction): void {\n const { menuItems } = this.state;\n const focusIndex = menuItems.indexOf(menuItem);\n this.setMouseIndex(focusIndex);\n }\n\n handleMouseLeave(): void {\n this.setMouseIndex(-1);\n }\n\n render(): JSX.Element {\n const menuItemElements = [];\n const { keyboardIndex, menuItems, mouseIndex } = this.state;\n for (let i = 0; i < menuItems.length; i += 1) {\n const menuItem = menuItems[i];\n\n if (i > 0 && menuItem.group !== menuItems[i - 1].group) {\n menuItemElements.push(<hr key={`${i}.separator`} />);\n }\n\n const menuItemElement = (\n <ContextMenuItem\n key={i}\n isKeyboardSelected={keyboardIndex === i}\n isMouseSelected={mouseIndex === i}\n menuItem={menuItem}\n closeMenu={this.handleCloseMenu}\n onMenuItemClick={this.handleMenuItemClick}\n onMenuItemMouseMove={this.handleMenuItemMouseMove}\n onMenuItemContextMenu={() => false}\n />\n );\n\n menuItemElements.push(menuItemElement);\n }\n\n const { menuStyle } = this.props;\n\n return (\n <div\n className=\"context-menu-container\"\n style={{ ...menuStyle }}\n ref={this.container}\n onKeyDown={this.handleKeyDown}\n onMouseLeave={this.handleMouseLeave}\n role=\"menuitem\"\n tabIndex={0}\n >\n {menuItemElements}\n </div>\n );\n }\n}\n\nexport default Menu;\n","/**\n * Add dropdown menu that you add onto any component.\n *\n * Similar to the context-actions package, accepts list of actions to create a dropdown menu.\n * Note: Does not support nested sub-menus.\n *\n * Usage:\n * let actions = [{\n * title: 'My Action',\n * action: () => { alert('My Action Clicked!') }\n * icon: faPrint, // Limited to FontAwesome icons for now.\n * shortcut: Shortcut, // Shortcut class instance\n * group: ContextActions.groups.default, // What group to group the context action with\n * order: null // Int where to order within group\n * }];\n *\n * Usage:\n * 1. Auto bind click to open event to parent\n * <div>\n * Click in this container\n * <DropdownMenu actions={actions}/>\n * </div>\n *\n * 2. Control via prop\n * <div>\n * DropdownMenu will not react to the click event if isShown prop is used\n * <DropdownMenu actions={actions} isShown={isShown} />\n * </div>\n *\n */\nimport React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport { PopperOptions } from 'popper.js';\nimport { Popper } from '../popper';\nimport Menu, { MenuOptions } from './Menu';\nimport { ContextAction } from '../context-actions/ContextActionUtils';\nimport './DropdownMenu.scss';\n\ntype DropdownMenuProps = {\n // Override to prevent nested lists\n actions:\n | (ContextAction & { actions?: never })\n | (ContextAction & { actions?: never })[];\n isShown: boolean | null;\n onMenuClosed(): void;\n onMenuOpened(): void;\n options: MenuOptions;\n popperOptions: PopperOptions;\n popperClassName: string;\n menuStyle: React.CSSProperties;\n};\n\nclass DropdownMenu extends PureComponent<DropdownMenuProps> {\n static defaultProps = {\n isShown: null,\n onMenuClosed(): void {\n // no-op\n },\n onMenuOpened(): void {\n // no-op\n },\n options: {},\n popperOptions: {},\n popperClassName: '',\n menuStyle: {},\n };\n\n constructor(props: DropdownMenuProps) {\n super(props);\n\n this.handleClick = this.handleClick.bind(this);\n this.handleCloseMenu = this.handleCloseMenu.bind(this);\n this.handleExited = this.handleExited.bind(this);\n\n this.container = React.createRef();\n this.parent = null;\n this.popper = React.createRef();\n\n this.isOpen = false;\n }\n\n componentDidMount(): void {\n const { isShown } = this.props;\n\n if (isShown === null) {\n if (this.container.current?.parentElement) {\n this.parent = this.container.current.parentElement;\n this.parent.addEventListener('click', this.handleClick);\n }\n } else if (isShown) {\n this.openMenu();\n }\n }\n\n componentDidUpdate(prevProps: DropdownMenuProps): void {\n const { isShown } = this.props;\n\n if (prevProps.isShown !== isShown) {\n if (isShown) {\n // https://github.com/reactjs/react-transition-group/issues/382\n window.requestAnimationFrame(() => {\n this.openMenu();\n });\n } else {\n this.closeMenu();\n }\n }\n }\n\n componentWillUnmount(): void {\n if (this.parent) {\n this.parent.removeEventListener('click', this.handleClick);\n }\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n parent: Element | null;\n\n popper: React.RefObject<Popper>;\n\n isOpen: boolean;\n\n closeMenu(): void {\n this.popper.current?.hide();\n }\n\n openMenu(): void {\n if (this.popper.current && !this.isOpen) {\n this.popper.current.show();\n this.isOpen = true;\n }\n }\n\n scheduleUpdate(): void {\n this.popper.current?.scheduleUpdate();\n }\n\n handleClick(e: Event): void {\n e.preventDefault();\n e.stopPropagation();\n\n this.openMenu();\n }\n\n handleCloseMenu(): void {\n this.closeMenu();\n }\n\n handleExited(): void {\n this.isOpen = false;\n\n const { onMenuClosed } = this.props;\n onMenuClosed();\n }\n\n render(): JSX.Element {\n const { actions, onMenuOpened, popperClassName } = this.props;\n const { menuStyle } = this.props;\n let { options, popperOptions } = this.props;\n popperOptions = { placement: 'bottom', ...popperOptions };\n options = {\n separateKeyboardMouse: true,\n ...options,\n };\n return (\n <div className=\"menu-actions-listener\" ref={this.container}>\n <Popper\n ref={this.popper}\n options={popperOptions}\n className={classNames('menu-popper', popperClassName)}\n onExited={this.handleExited}\n closeOnBlur\n interactive\n >\n <Menu\n actions={actions}\n closeMenu={this.handleCloseMenu}\n onMenuOpened={onMenuOpened}\n options={options}\n menuStyle={menuStyle}\n />\n </Popper>\n </div>\n );\n }\n}\n\nexport default DropdownMenu;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport debounce from 'lodash.debounce';\nimport dh from '@deephaven/jsapi-shim';\nimport { ItemList, LoadingSpinner } from '@deephaven/components';\nimport Log from '@deephaven/log';\nimport { CanceledPromiseError } from '@deephaven/utils';\nimport './PartitionSelectorSearch.scss';\n\nconst log = Log.module('PartitionSelectorSearch');\nconst DEBOUNCE_UPDATE_FILTER = 150;\n\nclass PartitionSelectorSearch extends Component {\n static MAX_VISIBLE_ITEMS = 12;\n\n static handleError(error) {\n if (!(error instanceof CanceledPromiseError)) {\n log.error(error);\n }\n }\n\n constructor(props) {\n super(props);\n\n this.debounceUpdateFilter = debounce(\n this.debounceUpdateFilter.bind(this),\n DEBOUNCE_UPDATE_FILTER\n );\n this.handleFilterChange = this.handleFilterChange.bind(this);\n this.handleInputFocus = this.handleInputFocus.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleListKeydown = this.handleListKeydown.bind(this);\n this.handleSelect = this.handleSelect.bind(this);\n this.handleTableUpdate = this.handleTableUpdate.bind(this);\n this.handleTextChange = this.handleTextChange.bind(this);\n this.handleViewportChange = this.handleViewportChange.bind(this);\n\n this.itemList = null;\n this.searchInput = null;\n this.timer = null;\n\n this.state = {\n offset: 0,\n itemCount: 0,\n items: [],\n text: '',\n isLoading: true,\n };\n }\n\n componentDidMount() {\n this.startListening();\n }\n\n componentDidUpdate(prevProps, prevState) {\n const { isLoading, itemCount } = this.state;\n const { onListResized } = this.props;\n if (\n itemCount !== prevState.itemCount ||\n isLoading !== prevState.isLoading\n ) {\n onListResized();\n }\n }\n\n componentWillUnmount() {\n this.debounceUpdateFilter.cancel();\n\n this.stopListening();\n }\n\n handleKeyDown(event) {\n if (this.itemList == null) {\n return false;\n }\n\n const { items, itemCount } = this.state;\n switch (event.key) {\n case 'Enter': {\n let selectedValue = null;\n if (items.length > 0) {\n selectedValue = items[0].value;\n } else {\n const { text } = this.state;\n selectedValue = text.trim();\n }\n\n if (selectedValue.length > 0) {\n const { onSelect } = this.props;\n onSelect(selectedValue);\n }\n\n event.stopPropagation();\n event.preventDefault();\n return true;\n }\n case 'ArrowDown':\n if (itemCount > 0) {\n this.itemList.focusItem(1);\n }\n event.stopPropagation();\n event.preventDefault();\n return true;\n default:\n return false;\n }\n }\n\n handleListKeydown(event) {\n switch (event.key) {\n case 'Escape':\n // Do nothing\n break;\n default:\n this.focus();\n break;\n }\n }\n\n handleFilterChange() {\n log.debug2('handleFilterChange');\n\n const { table } = this.props;\n const itemCount = table.size;\n this.setState({ itemCount, isLoading: true });\n }\n\n handleInputFocus() {\n if (this.itemList) {\n this.itemList.focusItem(0);\n }\n }\n\n handleSelect(itemIndex) {\n log.debug2('handleSelect', itemIndex);\n\n const { onSelect } = this.props;\n const { offset, items } = this.state;\n const offsetIndex = itemIndex - offset;\n if (offsetIndex < 0 || items.length <= offsetIndex) {\n log.error('No data for item', itemIndex);\n return;\n }\n\n const { value } = items[offsetIndex];\n onSelect(value);\n }\n\n handleTableUpdate(event) {\n const data = event.detail;\n const { offset } = data;\n\n const items = [];\n const { getFormattedString, table } = this.props;\n const column = table.columns[0];\n for (let r = 0; r < data.rows.length; r += 1) {\n const row = data.rows[r];\n const value = row.get(column);\n const displayValue = getFormattedString(value, column.type, column.name);\n items.push({\n displayValue,\n value,\n });\n }\n\n const itemCount = table.size;\n log.debug2('handleTableUpdate', itemCount, offset, items.length);\n this.setState({ itemCount, items, offset, isLoading: false });\n }\n\n handleTextChange(event) {\n log.debug2('handleTextChange');\n\n const { value: text } = event.target;\n\n this.setState({ text });\n\n this.debounceUpdateFilter();\n }\n\n handleViewportChange(topRow, bottomRow) {\n log.debug2('handleViewportChange', topRow, bottomRow);\n\n const delta = Math.max(1, bottomRow - topRow);\n const top = Math.max(0, topRow - delta);\n const bottom = bottomRow + delta;\n\n const { table } = this.props;\n table.setViewport(top, bottom);\n }\n\n debounceUpdateFilter() {\n this.updateFilter();\n }\n\n focus() {\n if (this.searchInput) {\n this.searchInput.focus();\n }\n }\n\n startListening() {\n const { initialPageSize, table } = this.props;\n table.addEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);\n table.addEventListener(\n dh.Table.EVENT_FILTERCHANGED,\n this.handleFilterChange\n );\n table.setViewport(0, initialPageSize);\n }\n\n stopListening() {\n const { table } = this.props;\n table.removeEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);\n table.removeEventListener(\n dh.Table.EVENT_FILTERCHANGED,\n this.handleFilterChange\n );\n }\n\n updateFilter() {\n const { initialPageSize, table } = this.props;\n const { text } = this.state;\n const filterText = text.trim();\n const filters = [];\n if (filterText.length > 0) {\n const column = table.columns[0];\n const filter = column\n .filter()\n .invoke(\n 'matches',\n dh.FilterValue.ofString(`(?s)(?i).*\\\\Q${filterText}\\\\E.*`)\n );\n filters.push(filter);\n }\n\n log.debug2('updateFilter', filters);\n\n table.applyFilter(filters);\n table.setViewport(0, initialPageSize);\n }\n\n render() {\n const { isLoading, itemCount, items, offset, text } = this.state;\n const listHeight =\n Math.min(itemCount, PartitionSelectorSearch.MAX_VISIBLE_ITEMS) *\n ItemList.DEFAULT_ROW_HEIGHT +\n // Adjust for ListItem vertical padding - .375rem ~ 5.25px\n 11;\n return (\n <div className=\"iris-grid-partition-selector-search\">\n <div className=\"search-container\">\n <input\n type=\"text\"\n ref={searchInput => {\n this.searchInput = searchInput;\n }}\n value={text}\n placeholder=\"Available Partitions\"\n onChange={this.handleTextChange}\n onFocus={this.handleInputFocus}\n onKeyDown={this.handleKeyDown}\n className=\"form-control input-partition\"\n />\n </div>\n {!isLoading && itemCount > 0 && (\n <div\n className=\"iris-grid-partition-selector-search-list\"\n onKeyDown={this.handleListKeydown}\n role=\"presentation\"\n style={{ height: listHeight }}\n >\n <ItemList\n ref={itemList => {\n this.itemList = itemList;\n }}\n itemCount={itemCount}\n items={items}\n offset={offset}\n onSelect={this.handleSelect}\n onViewportChange={this.handleViewportChange}\n />\n </div>\n )}\n {!isLoading && itemCount === 0 && (\n <div className=\"iris-grid-partition-selector-search-empty\">\n No results\n </div>\n )}\n {isLoading && (\n <div className=\"iris-grid-partition-selector-loading\">\n <LoadingSpinner />\n &nbsp;Loading...\n </div>\n )}\n </div>\n );\n }\n}\n\nPartitionSelectorSearch.propTypes = {\n getFormattedString: PropTypes.func.isRequired,\n table: PropTypes.shape({\n addEventListener: PropTypes.func.isRequired,\n removeEventListener: PropTypes.func.isRequired,\n columns: PropTypes.arrayOf(\n PropTypes.shape({\n name: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n filter: PropTypes.func.isRequired,\n })\n ),\n size: PropTypes.number.isRequired,\n applyFilter: PropTypes.func.isRequired,\n setViewport: PropTypes.func.isRequired,\n }).isRequired,\n initialPageSize: PropTypes.number,\n onSelect: PropTypes.func,\n onListResized: PropTypes.func,\n};\n\nPartitionSelectorSearch.defaultProps = {\n initialPageSize: 100,\n onSelect: () => {},\n onListResized: () => {},\n};\n\nexport default PartitionSelectorSearch;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { DropdownMenu, Tooltip } from '@deephaven/components';\nimport { vsTriangleDown, vsClose } from '@deephaven/icons';\nimport Log from '@deephaven/log';\nimport debounce from 'lodash.debounce';\nimport PartitionSelectorSearch from './PartitionSelectorSearch';\nimport './IrisGridPartitionSelector.scss';\n\nconst log = Log.module('IrisGridPartitionSelector');\n\nconst PARTITION_CHANGE_DEBOUNCE_MS = 250;\n\nclass IrisGridPartitionSelector extends Component {\n constructor(props) {\n super(props);\n\n this.debounceUpdate = debounce(\n this.debounceUpdate.bind(this),\n PARTITION_CHANGE_DEBOUNCE_MS\n );\n this.handleAppendClick = this.handleAppendClick.bind(this);\n this.handleCloseClick = this.handleCloseClick.bind(this);\n this.handleIgnoreClick = this.handleIgnoreClick.bind(this);\n this.handlePartitionChange = this.handlePartitionChange.bind(this);\n this.handlePartitionSelect = this.handlePartitionSelect.bind(this);\n this.handlePartitionListResized = this.handlePartitionListResized.bind(\n this\n );\n this.handleSearchOpened = this.handleSearchOpened.bind(this);\n this.handleSearchClosed = this.handleSearchClosed.bind(this);\n\n this.searchMenu = null;\n this.selectorSearch = null;\n\n const { partition } = props;\n this.state = {\n partition,\n };\n }\n\n componentWillUnmount() {\n this.debounceUpdate.cancel();\n }\n\n handleAppendClick() {\n log.debug2('handleAppendClick');\n\n const { onAppend } = this.props;\n const { partition } = this.state;\n onAppend(partition);\n }\n\n handleCloseClick() {\n log.debug2('handleCloseClick');\n\n this.sendDone();\n }\n\n handleIgnoreClick() {\n log.debug2('handleIgnoreClick');\n\n this.sendFetchAll();\n }\n\n handlePartitionChange(event) {\n log.debug2('handlePartitionChange');\n\n const { value: partition } = event.target;\n\n this.setState({ partition });\n\n this.debounceUpdate();\n }\n\n handlePartitionSelect(partition) {\n if (this.searchMenu) {\n this.searchMenu.closeMenu();\n }\n\n this.setState({ partition }, () => {\n this.sendUpdate();\n });\n }\n\n handlePartitionListResized() {\n if (this.searchMenu) {\n this.searchMenu.scheduleUpdate();\n }\n }\n\n handleSearchClosed() {\n // Reset the table filter so it's ready next time user opens search\n const { table } = this.props;\n table.applyFilter([]);\n }\n\n handleSearchOpened() {\n if (this.selectorSearch) {\n this.selectorSearch.focus();\n }\n }\n\n debounceUpdate() {\n this.sendUpdate();\n }\n\n sendDone() {\n this.debounceUpdate.flush();\n\n const { onDone } = this.props;\n onDone();\n }\n\n sendUpdate() {\n log.debug2('sendUpdate');\n\n const { onChange } = this.props;\n const { partition } = this.state;\n onChange(partition);\n }\n\n sendFetchAll() {\n log.debug2('sendFetchAll');\n\n this.debounceUpdate.cancel();\n\n const { onFetchAll } = this.props;\n onFetchAll();\n }\n\n render() {\n const { columnName, getFormattedString, onDone, table } = this.props;\n const { partition } = this.state;\n const partitionSelectorSearch = (\n <PartitionSelectorSearch\n key=\"search\"\n getFormattedString={getFormattedString}\n table={table}\n onSelect={this.handlePartitionSelect}\n onListResized={this.handlePartitionListResized}\n ref={selectorSearch => {\n this.selectorSearch = selectorSearch;\n }}\n />\n );\n return (\n <div className=\"iris-grid-partition-selector\">\n <div className=\"status-message\">\n <span>Filtering &quot;{columnName}&quot; partition to</span>\n </div>\n <div className=\"input-group\">\n <input\n type=\"text\"\n value={partition}\n onChange={this.handlePartitionChange}\n className=\"form-control input-partition\"\n />\n <div className=\"input-group-append\">\n <button type=\"button\" className=\"btn btn-outline-primary\">\n <FontAwesomeIcon icon={vsTriangleDown} />\n <Tooltip>Partitions</Tooltip>\n <DropdownMenu\n ref={searchMenu => {\n this.searchMenu = searchMenu;\n }}\n actions={[{ menuElement: partitionSelectorSearch }]}\n onMenuOpened={this.handleSearchOpened}\n onMenuClosed={this.handleSearchClosed}\n />\n </button>\n </div>\n </div>\n <div className=\"iris-grid-partition-selector-spacer\" />\n <button\n type=\"button\"\n className=\"btn btn-outline-primary btn-ignore\"\n onClick={this.handleIgnoreClick}\n >\n Ignore &amp; Fetch All\n </button>\n <button\n type=\"button\"\n className=\"btn btn-outline-primary btn-append\"\n onClick={this.handleAppendClick}\n >\n Append Command\n </button>\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon btn-close\"\n onClick={onDone}\n >\n <FontAwesomeIcon icon={vsClose} />\n </button>\n </div>\n );\n }\n}\n\nIrisGridPartitionSelector.propTypes = {\n getFormattedString: PropTypes.func.isRequired,\n table: PropTypes.shape({ applyFilter: PropTypes.func }).isRequired,\n columnName: PropTypes.string.isRequired,\n partition: PropTypes.string,\n onAppend: PropTypes.func,\n onChange: PropTypes.func,\n onFetchAll: PropTypes.func,\n onDone: PropTypes.func,\n};\n\nIrisGridPartitionSelector.defaultProps = {\n onAppend: () => {},\n onChange: () => {},\n onFetchAll: () => {},\n onDone: () => {},\n partition: '',\n};\n\nexport default IrisGridPartitionSelector;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport deepEqual from 'deep-equal';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { dhNewCircleLargeFilled, vsTrash } from '@deephaven/icons';\nimport { Tooltip } from '@deephaven/components';\nimport Log from '@deephaven/log';\nimport IrisGridModel from '../IrisGridModel';\n\nimport './SelectDistinctBuilder.scss';\n\nconst log = Log.module('SelectDistinctBuilder');\n\nclass SelectDistinctBuilder extends Component {\n constructor(props) {\n super(props);\n\n this.handleAddColumnClick = this.handleAddColumnClick.bind(this);\n this.handleDeleteColumn = this.handleDeleteColumn.bind(this);\n this.handleDropdownChanged = this.handleDropdownChanged.bind(this);\n\n const { model, selectDistinctColumns } = this.props;\n\n this.state = {\n inputs:\n selectDistinctColumns.length > 0 ? [...selectDistinctColumns] : [''],\n columns: model.originalColumns,\n };\n }\n\n componentDidUpdate(prevProps, prevState) {\n const { inputs } = this.state;\n const { onChange } = this.props;\n if (prevState.inputs !== inputs) {\n const filteredInputs = inputs.filter(val => val !== '');\n if (\n !deepEqual(\n prevState.inputs.filter(val => val !== ''),\n filteredInputs\n )\n ) {\n onChange(filteredInputs);\n }\n }\n }\n\n handleAddColumnClick() {\n this.setState(({ inputs: prevInputs }) => ({\n inputs: [...prevInputs, ''],\n }));\n }\n\n handleDeleteColumn(index) {\n this.setState(({ inputs }) => ({\n inputs:\n inputs.length === 1 && index === 0\n ? ['']\n : inputs.filter((input, inputIndex) => index !== inputIndex),\n }));\n }\n\n handleDropdownChanged(index, event) {\n log.debug('handleDropdownChanged', index, event);\n const { value } = event.target;\n this.setState(({ inputs: prevInputs }) => {\n const inputs = [...prevInputs];\n inputs[index] = value;\n return { inputs };\n });\n }\n\n renderInputs() {\n const { columns, inputs } = this.state;\n\n return inputs.map((value, index) => {\n const options = columns\n .filter(({ name }) => name === value || !inputs.includes(name))\n .map(({ name }) => (\n <option value={name} key={name}>\n {name}\n </option>\n ));\n return (\n // eslint-disable-next-line react/no-array-index-key\n <div className=\"form-inline px-3 pb-3\" key={index}>\n <select\n className=\"form-control custom-select col\"\n value={value}\n onChange={event => this.handleDropdownChanged(index, event)}\n >\n <option value=\"\">Select a column</option>\n {options}\n </select>\n\n {(inputs.length > 1 || value !== '') && (\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon ml-1 px-2\"\n onClick={() => {\n this.handleDeleteColumn(index);\n }}\n >\n <Tooltip>Delete column</Tooltip>\n <FontAwesomeIcon icon={vsTrash} transform=\"grow-3\" />\n </button>\n )}\n </div>\n );\n });\n }\n\n render() {\n const { columns, inputs } = this.state;\n const disableAddButton = inputs.length >= columns.length;\n return (\n <div\n role=\"presentation\"\n className=\"select-distinct-builder-container h-100\"\n >\n <div className=\"select-distinct-title\">Display Unique Values From</div>\n\n {this.renderInputs()}\n\n <hr />\n\n <div className=\"pt-1 px-3\">\n <button\n type=\"button\"\n className=\"btn btn-link btn-add-column\"\n onClick={this.handleAddColumnClick}\n disabled={disableAddButton}\n >\n <FontAwesomeIcon icon={dhNewCircleLargeFilled} />\n Add Additional Column\n </button>\n </div>\n\n <div className=\"select-distinct-builder-footer\">\n <div className=\"select-distinct-builder-hint\">\n Modifies a table to show unique value from a column, same as{' '}\n <span className=\"inline-code-snippet\">\n selectDistinct(&quot;Column&quot;)\n </span>\n . Filters will be reset and the resulting table will contain only\n the selected columns above.\n </div>\n </div>\n </div>\n );\n }\n}\n\nSelectDistinctBuilder.propTypes = {\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n selectDistinctColumns: PropTypes.arrayOf(PropTypes.string),\n onChange: PropTypes.func,\n};\n\nSelectDistinctBuilder.defaultProps = {\n selectDistinctColumns: [],\n onChange: () => {},\n};\n\nexport default SelectDistinctBuilder;\n","import React from 'react';\nimport { Menu, SwitchMenuItemDef } from '@deephaven/components';\nimport AdvancedSettingsType from './AdvancedSettingsType';\n\nexport type AdvancedSettingsMenuCallback = (\n key: AdvancedSettingsType,\n isOn: boolean\n) => void;\n\nexport type AdvancedSettingsMenuProps = {\n items: Map<AdvancedSettingsType, boolean>;\n onChange?: AdvancedSettingsMenuCallback;\n};\n\nconst AdvancedSettingsMenu = ({\n items,\n onChange = () => undefined,\n}: AdvancedSettingsMenuProps): JSX.Element => (\n <Menu\n items={Array.from(items.entries()).map(\n ([key, isOn]): SwitchMenuItemDef => ({\n title: AdvancedSettingsMenu.getAdvancedSettingsTitleForKey(key),\n isOn,\n onChange: (value: boolean) => onChange(key, value),\n })\n )}\n />\n);\n\nAdvancedSettingsMenu.getAdvancedSettingsTitleForKey = (\n key: AdvancedSettingsType\n): string => {\n switch (key) {\n case AdvancedSettingsType.FILTER_CONTROL_CHANGE_CLEARS_ALL_FILTERS:\n return 'Control filters clear existing table filters';\n case AdvancedSettingsType.LINK_CHANGE_CLEARS_ALL_FILTERS:\n return 'Inbound links clear existing table filters';\n }\n};\n\nexport default AdvancedSettingsMenu;\n","import React, { Component } from 'react';\nimport memoize from 'memoizee';\nimport classNames from 'classnames';\nimport { CSSTransition } from 'react-transition-group';\nimport PropTypes from 'prop-types';\nimport deepEqual from 'deep-equal';\nimport Log from '@deephaven/log';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n ContextActionUtils,\n ContextActions,\n DeephavenSpinner,\n Stack,\n Menu,\n Page,\n Popper,\n ThemeExport,\n Tooltip,\n} from '@deephaven/components';\nimport { Grid, GridRange, GridUtils } from '@deephaven/grid';\nimport {\n dhEye,\n dhFilterFilled,\n dhGraphLineUp,\n dhTriangleDownSquare,\n vsCloudDownload,\n vsFilter,\n vsMenu,\n vsRuby,\n vsSearch,\n vsSplitHorizontal,\n vsSymbolOperator,\n vsTools,\n} from '@deephaven/icons';\nimport dh, { PropTypes as APIPropTypes } from '@deephaven/jsapi-shim';\nimport { Pending, PromiseUtils, ValidationError } from '@deephaven/utils';\nimport throttle from 'lodash.throttle';\nimport debounce from 'lodash.debounce';\nimport clamp from 'lodash.clamp';\nimport PendingDataBottomBar from './PendingDataBottomBar';\nimport IrisGridCopyHandler from './IrisGridCopyHandler';\nimport FilterInputField from './FilterInputField';\nimport {\n ClearFilterKeyHandler,\n CopyKeyHandler,\n ReverseKeyHandler,\n} from './key-handlers';\nimport {\n IrisGridColumnSelectMouseHandler,\n IrisGridColumnTooltipMouseHandler,\n IrisGridContextMenuHandler,\n IrisGridDataSelectMouseHandler,\n IrisGridFilterMouseHandler,\n IrisGridSortMouseHandler,\n PendingMouseHandler,\n} from './mousehandlers';\nimport ToastBottomBar from './ToastBottomBar';\nimport IrisGridMetricCalculator from './IrisGridMetricCalculator';\nimport IrisGridModelUpdater from './IrisGridModelUpdater';\nimport IrisGridRenderer from './IrisGridRenderer';\nimport IrisGridTheme from './IrisGridTheme';\nimport ColumnStatistics from './ColumnStatistics';\nimport './IrisGrid.scss';\nimport Formatter from './Formatter';\nimport FormatterUtils from './FormatterUtils';\nimport TableUtils from './TableUtils';\nimport AdvancedFilterCreator from './AdvancedFilterCreator';\nimport {\n Aggregations,\n AggregationEdit,\n AggregationUtils,\n ChartBuilder,\n CustomColumnBuilder,\n OptionType,\n RollupRows,\n TableCsvExporter,\n TableSaver,\n VisibilityOrderingBuilder,\n} from './sidebar';\nimport IrisGridUtils from './IrisGridUtils';\nimport CrossColumnSearch from './CrossColumnSearch';\nimport IrisGridModel from './IrisGridModel';\nimport IrisGridPartitionSelector from './IrisGridPartitionSelector';\nimport SelectDistinctBuilder from './sidebar/SelectDistinctBuilder';\nimport AdvancedSettingsType from './sidebar/AdvancedSettingsType';\nimport AdvancedSettingsMenu from './sidebar/AdvancedSettingsMenu';\nimport SHORTCUTS from './IrisGridShortcuts';\nimport DateUtils from './DateUtils';\n\nconst log = Log.module('IrisGrid');\n\nconst UPDATE_DOWNLOAD_THROTTLE = 500;\n\nconst SET_FILTER_DEBOUNCE = 250;\n\nfunction isEmptyConfig({\n advancedFilters,\n quickFilters,\n sorts,\n customColumns,\n reverseType,\n searchFilter,\n}) {\n return (\n advancedFilters.size === 0 &&\n quickFilters.size === 0 &&\n sorts.length === 0 &&\n customColumns.length === 0 &&\n reverseType === TableUtils.REVERSE_TYPE.NONE &&\n searchFilter == null\n );\n}\n\nexport class IrisGrid extends Component {\n static minDebounce = 150;\n\n static maxDebounce = 500;\n\n static loadingSpinnerDelay = 800;\n\n static makeQuickFilter(column, text, timeZone) {\n try {\n return TableUtils.makeQuickFilter(column, text, timeZone);\n } catch (err) {\n log.error('Error creating quick filter', err);\n }\n return null;\n }\n\n constructor(props) {\n super(props);\n\n this.handleAdvancedFilterChange = this.handleAdvancedFilterChange.bind(\n this\n );\n this.handleAdvancedFilterSortChange = this.handleAdvancedFilterSortChange.bind(\n this\n );\n this.handleAdvancedFilterDone = this.handleAdvancedFilterDone.bind(this);\n this.handleAdvancedMenuOpened = this.handleAdvancedMenuOpened.bind(this);\n this.handleAdvancedMenuClosed = this.handleAdvancedMenuClosed.bind(this);\n this.handleAggregationChange = this.handleAggregationChange.bind(this);\n this.handleAggregationsChange = this.handleAggregationsChange.bind(this);\n this.handleAggregationEdit = this.handleAggregationEdit.bind(this);\n this.handleAnimationLoop = this.handleAnimationLoop.bind(this);\n this.handleAnimationStart = this.handleAnimationStart.bind(this);\n this.handleAnimationEnd = this.handleAnimationEnd.bind(this);\n this.handleChartChange = this.handleChartChange.bind(this);\n this.handleChartCreate = this.handleChartCreate.bind(this);\n this.handleGridError = this.handleGridError.bind(this);\n this.handleFilterBarChange = this.handleFilterBarChange.bind(this);\n this.handleFilterBarDone = this.handleFilterBarDone.bind(this);\n this.handleFilterBarTab = this.handleFilterBarTab.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleMenu = this.handleMenu.bind(this);\n this.handleMenuClose = this.handleMenuClose.bind(this);\n this.handleMenuSelect = this.handleMenuSelect.bind(this);\n this.handleMenuBack = this.handleMenuBack.bind(this);\n this.handleRequestFailed = this.handleRequestFailed.bind(this);\n this.handleSelectionChanged = this.handleSelectionChanged.bind(this);\n this.handleMovedColumnsChanged = this.handleMovedColumnsChanged.bind(this);\n this.handleUpdate = this.handleUpdate.bind(this);\n this.handleTooltipRef = this.handleTooltipRef.bind(this);\n this.handleViewChanged = this.handleViewChanged.bind(this);\n this.handleFormatSelection = this.handleFormatSelection.bind(this);\n\n this.handleUpdateCustomColumns = this.handleUpdateCustomColumns.bind(this);\n this.handleCustomColumnsChanged = this.handleCustomColumnsChanged.bind(\n this\n );\n this.handleSelectDistinctChanged = this.handleSelectDistinctChanged.bind(\n this\n );\n this.handlePendingDataUpdated = this.handlePendingDataUpdated.bind(this);\n this.handlePendingCommitClicked = this.handlePendingCommitClicked.bind(\n this\n );\n this.handlePendingDiscardClicked = this.handlePendingDiscardClicked.bind(\n this\n );\n\n this.handleDownloadTable = this.handleDownloadTable.bind(this);\n this.handleDownloadTableStart = this.handleDownloadTableStart.bind(this);\n this.handleCancelDownloadTable = this.handleCancelDownloadTable.bind(this);\n this.handleDownloadCanceled = this.handleDownloadCanceled.bind(this);\n this.handleDownloadProgressUpdate = throttle(\n this.handleDownloadProgressUpdate.bind(this),\n UPDATE_DOWNLOAD_THROTTLE\n );\n this.handleDownloadCompleted = this.handleDownloadCompleted.bind(this);\n this.handlePartitionAppend = this.handlePartitionAppend.bind(this);\n this.handlePartitionChange = this.handlePartitionChange.bind(this);\n this.handlePartitionFetchAll = this.handlePartitionFetchAll.bind(this);\n this.handlePartitionDone = this.handlePartitionDone.bind(this);\n this.handleColumnVisibilityChanged = this.handleColumnVisibilityChanged.bind(\n this\n );\n this.handleCrossColumnSearch = this.handleCrossColumnSearch.bind(this);\n this.handleRollupChange = this.handleRollupChange.bind(this);\n\n this.updateSearchFilter = debounce(\n this.updateSearchFilter.bind(this),\n SET_FILTER_DEBOUNCE\n );\n\n this.grid = null;\n this.gridWrapper = null;\n this.lastFocusedFilterBarColumn = null;\n this.lastLoadedConfig = null;\n this.tooltip = null;\n this.pending = new Pending();\n this.globalColumnFormats = [];\n this.dateTimeFormatterOptions = {};\n this.decimalFormatOptions = {};\n this.integerFormatOptions = {};\n\n // When the loading scrim started/when it should extend to the end of the screen.\n this.loadingScrimStartTime = null;\n this.loadingScrimFinishTime = null;\n this.loadingTimer = null;\n this.renderer = new IrisGridRenderer();\n this.tableSaver = null;\n this.crossColumnRef = React.createRef();\n this.isAnimating = false;\n this.animationFrame = null;\n this.filterInputRef = React.createRef();\n\n this.toggleFilterBarAction = {\n action: () => this.toggleFilterBar(),\n shortcut: SHORTCUTS.TABLE.TOGGLE_QUICK_FILTER,\n };\n this.toggleSearchBarAction = {\n action: () => this.toggleSearchBar(),\n shortcut: SHORTCUTS.TABLE.TOGGLE_SEARCH,\n };\n this.discardAction = {\n action: () => {\n const { model } = this.props;\n if (model.isEditable && model.pendingDataMap.size > 0) {\n this.discardPending().catch(log.error);\n }\n },\n shortcut: SHORTCUTS.INPUT_TABLE.DISCARD,\n };\n this.commitAction = {\n action: () => {\n const { model } = this.props;\n if (\n model.isEditable &&\n model.pendingDataMap.size > 0 &&\n model.pendingDataErrors.size === 0\n ) {\n this.commitPending().catch(log.error);\n }\n },\n shortcut: SHORTCUTS.INPUT_TABLE.COMMIT,\n };\n this.contextActions = [\n this.toggleFilterBarAction,\n this.toggleSearchBarAction,\n this.discardAction,\n this.commitAction,\n ];\n\n const {\n aggregationSettings,\n customColumnFormatMap,\n isFilterBarShown,\n isSelectingPartition,\n model,\n movedColumns,\n movedRows,\n partition,\n partitionColumn,\n rollupConfig,\n userColumnWidths,\n userRowHeights,\n showSearchBar,\n searchValue,\n selectedSearchColumns,\n invertSearchColumns,\n advancedFilters,\n quickFilters,\n selectDistinctColumns,\n pendingDataMap,\n canCopy,\n frozenColumns,\n } = props;\n\n const keyHandlers = [\n new ReverseKeyHandler(this),\n new ClearFilterKeyHandler(this),\n ];\n if (canCopy) {\n keyHandlers.push(new CopyKeyHandler(this));\n }\n const mouseHandlers = [\n new IrisGridColumnSelectMouseHandler(this),\n new IrisGridColumnTooltipMouseHandler(this),\n new IrisGridSortMouseHandler(this),\n new IrisGridFilterMouseHandler(this),\n new IrisGridContextMenuHandler(this),\n new IrisGridDataSelectMouseHandler(this),\n new PendingMouseHandler(this),\n ];\n\n const metricCalculator = new IrisGridMetricCalculator({\n userColumnWidths: new Map(userColumnWidths),\n userRowHeights: new Map(userRowHeights),\n });\n const searchColumns = selectedSearchColumns ?? [];\n const searchFilter = CrossColumnSearch.createSearchFilter(\n searchValue,\n searchColumns,\n model.columns,\n invertSearchColumns\n );\n\n this.state = {\n isFilterBarShown,\n isSelectingPartition,\n focusedFilterBarColumn: null,\n metricCalculator,\n metrics: null,\n keyHandlers,\n mouseHandlers,\n\n partition,\n partitionColumn,\n partitionTable: null,\n partitionFilters: [],\n // setAdvancedFilter and setQuickFilter mutate the arguments\n // so we want to always use map copies from the state instead of props\n quickFilters: new Map(quickFilters),\n advancedFilters: new Map(advancedFilters),\n shownAdvancedFilter: null,\n hoverAdvancedFilter: null,\n\n filter: [],\n sorts: [],\n reverseType: TableUtils.REVERSE_TYPE.NONE,\n customColumns: [],\n selectDistinctColumns,\n\n // selected range in table\n selectedRanges: [],\n\n // Current ongoing copy operation\n copyOperation: null,\n\n // The filter that is currently being applied. Reset after update is received\n loadingText: null,\n loadingScrimProgress: null,\n loadingSpinnerShown: false,\n\n movedColumns,\n movedRows,\n\n shownColumnTooltip: null,\n\n formatter: new Formatter(),\n isMenuShown: false,\n customColumnFormatMap: new Map(customColumnFormatMap),\n\n // Column user is hovering over for selection\n hoverSelectColumn: null,\n\n isTableDownloading: false,\n isReady: false,\n tableDownloadStatus: '',\n tableDownloadProgress: 0,\n tableDownloadEstimatedTime: 0,\n\n showSearchBar,\n searchFilter,\n searchValue,\n selectedSearchColumns: searchColumns,\n invertSearchColumns,\n\n rollupConfig,\n rollupSelectedColumns: [],\n aggregationSettings,\n selectedAggregation: null,\n\n openOptions: [],\n\n pendingRowCount: 0,\n pendingDataMap,\n pendingDataErrors: new Map(),\n pendingSavePromise: null,\n pendingSaveError: null,\n\n toastMessage: null,\n frozenColumns,\n };\n }\n\n componentDidMount() {\n const { partitionColumn, model } = this.props;\n const column =\n partitionColumn || model.columns.find(c => c.isPartitionColumn);\n if (\n model.isFilterRequired &&\n model.isValuesTableAvailable &&\n column != null\n ) {\n this.loadPartitionsTable(column);\n } else {\n this.initState();\n }\n this.startListening(model);\n }\n\n componentDidUpdate(prevProps) {\n const {\n inputFilters,\n isSelectingColumn,\n settings,\n model,\n customFilters,\n sorts,\n } = this.props;\n\n if (model !== prevProps.model) {\n this.stopListening(prevProps.model);\n this.startListening(model);\n }\n\n const changedInputFilters =\n inputFilters !== prevProps.inputFilters\n ? inputFilters.filter(\n inputFilter => !prevProps.inputFilters.includes(inputFilter)\n )\n : [];\n if (changedInputFilters.length > 0) {\n const { advancedSettings } = this.props;\n const replaceExistingFilters =\n advancedSettings.get(\n AdvancedSettingsType.FILTER_CONTROL_CHANGE_CLEARS_ALL_FILTERS\n ) ?? false;\n if (replaceExistingFilters) {\n this.clearGridInputField();\n this.clearCrossColumSearch();\n }\n this.startLoading('Filtering...', true);\n this.applyInputFilters(changedInputFilters, replaceExistingFilters);\n }\n\n if (isSelectingColumn !== prevProps.isSelectingColumn) {\n this.resetColumnSelection();\n }\n if (settings !== prevProps.settings) {\n this.updateFormatterSettings(settings);\n }\n if (customFilters !== prevProps.customFilters) {\n this.startLoading('Filtering...', true);\n }\n if (sorts !== prevProps.sorts) {\n this.updateSorts(sorts);\n }\n\n const { loadingScrimStartTime, loadingScrimFinishTime } = this;\n if (loadingScrimStartTime != null && loadingScrimFinishTime != null) {\n window.requestAnimationFrame(() => {\n const now = Date.now();\n const currentTime = now - loadingScrimStartTime;\n const totalTime = loadingScrimFinishTime - loadingScrimStartTime;\n const loadingScrimProgress = Math.min(currentTime / totalTime, 1);\n if (loadingScrimFinishTime < now) {\n this.loadingScrimStartTime = null;\n this.loadingScrimFinishTime = null;\n }\n\n this.setState(state => {\n if (state.loadingScrimProgress == null) {\n log.debug2('Ignoring scrim update because loading cancelled.');\n return null;\n }\n\n return { loadingScrimProgress };\n });\n });\n }\n\n this.sendStateChange();\n }\n\n componentWillUnmount() {\n const { model } = this.props;\n this.stopListening(model);\n this.pending.cancel();\n this.updateSearchFilter.cancel();\n\n if (this.loadingTimer) {\n clearTimeout(this.loadingTimer);\n }\n this.handleDownloadProgressUpdate.cancel();\n cancelAnimationFrame(this.animationFrame);\n }\n\n getAdvancedMenuOpenedHandler = memoize(\n column => this.handleAdvancedMenuOpened.bind(this, column),\n { max: 100 }\n );\n\n getCachedAdvancedFilterMenuActions = memoize(\n (model, column, advancedFilterOptions, sortDirection, formatter) => (\n <AdvancedFilterCreator\n model={model}\n column={column}\n onFilterChange={this.handleAdvancedFilterChange}\n onSortChange={this.handleAdvancedFilterSortChange}\n onDone={this.handleAdvancedFilterDone}\n options={advancedFilterOptions}\n sortDirection={sortDirection}\n formatter={formatter}\n />\n ),\n { max: 50 }\n );\n\n getCachedOptionItems = memoize(\n (\n isChartBuilderAvailable,\n isCustomColumnsAvailable,\n isRollupAvailable,\n isTotalsAvailable,\n isSelectDistinctAvailable,\n isExportAvailable,\n toggleFilterBarAction,\n toggleSearchBarAction,\n isFilterBarShown,\n showSearchBar,\n canDownloadCsv,\n canToggleSearch\n ) => {\n const optionItems = [];\n if (isChartBuilderAvailable) {\n optionItems.push({\n type: OptionType.CHART_BUILDER,\n title: 'Chart Builder',\n icon: dhGraphLineUp,\n });\n }\n optionItems.push({\n type: OptionType.VISIBILITY_ORDERING_BUILDER,\n title: 'Column Visibility & Ordering',\n icon: dhEye,\n });\n if (isCustomColumnsAvailable) {\n optionItems.push({\n type: OptionType.CUSTOM_COLUMN_BUILDER,\n title: 'Manage Custom Columns',\n icon: vsSplitHorizontal,\n });\n }\n if (isRollupAvailable) {\n optionItems.push({\n type: OptionType.ROLLUP_ROWS,\n title: 'Rollup Rows',\n icon: dhTriangleDownSquare,\n });\n }\n if (isTotalsAvailable) {\n optionItems.push({\n type: OptionType.AGGREGATIONS,\n title: 'Aggregate Columns',\n icon: vsSymbolOperator,\n });\n }\n if (isSelectDistinctAvailable) {\n optionItems.push({\n type: OptionType.SELECT_DISTINCT,\n title: 'Select Distinct Values',\n icon: vsRuby,\n });\n }\n if (isExportAvailable && canDownloadCsv) {\n optionItems.push({\n type: OptionType.TABLE_EXPORTER,\n title: 'Download CSV',\n icon: vsCloudDownload,\n });\n }\n optionItems.push({\n type: OptionType.ADVANCED_SETTINGS,\n title: 'Advanced Settings',\n icon: vsTools,\n });\n optionItems.push({\n type: OptionType.QUICK_FILTERS,\n title: 'Quick Filters',\n subtitle: toggleFilterBarAction.shortcut.getDisplayText(),\n icon: vsFilter,\n isOn: isFilterBarShown,\n onChange: toggleFilterBarAction.action,\n });\n if (canToggleSearch) {\n optionItems.push({\n type: OptionType.SEARCH_BAR,\n title: 'Search Bar',\n subtitle: toggleSearchBarAction.shortcut.getDisplayText(),\n icon: vsSearch,\n isOn: showSearchBar,\n onChange: toggleSearchBarAction.action,\n });\n }\n\n return optionItems;\n },\n { max: 1 }\n );\n\n getCachedHiddenColumns = memoize(hiddenColumns => hiddenColumns, {\n max: 1,\n normalizer: ([hiddenColumns]) => hiddenColumns.join(),\n });\n\n getAggregationMap = memoize((columns, aggregations) => {\n const aggregationMap = {};\n aggregations.forEach(({ operation, selected, invert }) => {\n aggregationMap[operation] = AggregationUtils.getOperationColumnNames(\n columns,\n operation,\n selected,\n invert\n );\n });\n return aggregationMap;\n });\n\n getOperationMap = memoize((columns, aggregations) => {\n const operationMap = {};\n aggregations\n .filter(a => !AggregationUtils.isRollupOperation(a.operation))\n .forEach(({ operation, selected, invert }) => {\n AggregationUtils.getOperationColumnNames(\n columns,\n operation,\n selected,\n invert\n ).forEach(name => {\n const newOperations = [...(operationMap[name] ?? []), operation];\n operationMap[name] = newOperations;\n });\n });\n return operationMap;\n });\n\n getOperationOrder = memoize(aggregations =>\n aggregations\n .map(a => a.operation)\n .filter(o => !AggregationUtils.isRollupOperation(o))\n );\n\n getModelRollupConfig = memoize(\n (originalColumns, config, aggregationSettings) =>\n IrisGridUtils.getModelRollupConfig(\n originalColumns,\n config,\n aggregationSettings\n )\n );\n\n getModelTotalsConfig = memoize((columns, config, aggregationSettings) => {\n const { aggregations, showOnTop } = aggregationSettings;\n // If we've got rollups, then aggregations are applied as part of that...\n if (\n (config?.columns?.length ?? 0) > 0 ||\n (aggregations?.length ?? 0) === 0\n ) {\n return null;\n }\n\n const operationMap = this.getOperationMap(columns, aggregations);\n const operationOrder = this.getOperationOrder(aggregations);\n\n return { operationMap, operationOrder, showOnTop };\n });\n\n getCachedStateOverride = memoize(\n (\n hoverSelectColumn,\n isFilterBarShown,\n isSelectingColumn,\n loadingScrimProgress,\n quickFilters,\n advancedFilters,\n sorts,\n reverseType,\n rollupConfig\n ) => ({\n hoverSelectColumn,\n isFilterBarShown,\n isSelectingColumn,\n loadingScrimProgress,\n quickFilters,\n advancedFilters,\n sorts,\n reverseType,\n rollupConfig,\n }),\n { max: 1 }\n );\n\n getCachedFilter = memoize(\n (\n customFilters,\n quickFilters,\n advancedFilters,\n partitionFilters,\n searchFilter\n ) => [\n ...customFilters,\n ...partitionFilters,\n ...IrisGridUtils.getFiltersFromFilterMap(quickFilters),\n ...IrisGridUtils.getFiltersFromFilterMap(advancedFilters),\n ...(searchFilter ? [searchFilter] : []), // null check\n ],\n { max: 1 }\n );\n\n getCachedTheme = memoize(\n (theme, isEditable) => ({\n ...IrisGridTheme,\n autoSelectRow: !isEditable,\n ...theme,\n }),\n { max: 1 }\n );\n\n getValueForCell(columnIndex, rowIndex, rawValue = false) {\n const { model } = this.props;\n const modelColumn = this.getModelColumn(columnIndex);\n const modelRow = this.getModelRow(rowIndex);\n if (rawValue) {\n return model.valueForCell(modelColumn, modelRow);\n }\n return model.textForCell(modelColumn, modelRow);\n }\n\n getModelColumn(columnIndex) {\n const { metrics } = this.state;\n const { modelColumns } = metrics;\n if (!modelColumns) {\n return null;\n }\n\n return modelColumns.get(columnIndex);\n }\n\n getModelRow(rowIndex) {\n const { metrics } = this.state;\n const { modelRows } = metrics;\n if (!modelRows) {\n return null;\n }\n\n return modelRows.get(rowIndex);\n }\n\n getTheme() {\n const { model, theme } = this.props;\n return this.getCachedTheme(theme, model.isEditable);\n }\n\n getVisibleColumn(modelIndex) {\n const { movedColumns } = this.state;\n return GridUtils.getVisibleIndex(modelIndex, movedColumns);\n }\n\n /**\n * Applies the provided input filters as quick filters,\n * and clears any existing quickFilters or advancedFilters on that column\n * @param {inputFilter[]} inputFilters Array of input filters to apply\n * @param {boolean} replaceExisting If true, new filters will replace the existing ones, instead of merging\n */\n applyInputFilters(inputFilters, replaceExisting = false) {\n const { model } = this.props;\n const { advancedFilters, quickFilters } = this.state;\n const newAdvancedFilters = replaceExisting\n ? new Map()\n : new Map(advancedFilters);\n const newQuickFilters = replaceExisting ? new Map() : new Map(quickFilters);\n\n let isChanged = replaceExisting && advancedFilters.size > 0;\n inputFilters.forEach(({ name, type, value }) => {\n const modelIndex = model.columns.findIndex(\n ({ name: columnName, type: columnType }) =>\n columnName === name && columnType === type\n );\n if (modelIndex >= 0) {\n isChanged = newAdvancedFilters.delete(modelIndex) || isChanged;\n isChanged =\n this.applyQuickFilter(modelIndex, value, newQuickFilters) ||\n isChanged;\n } else {\n log.error('Unable to find column for inputFilter', name, type, value);\n }\n });\n if (isChanged) {\n this.setState({\n quickFilters: newQuickFilters,\n advancedFilters: newAdvancedFilters,\n });\n }\n }\n\n /**\n * Applies a quick filter\n * @param {number} modelIndex The index in the model of the column to set\n * @param {string} value The string value to set to the quick filter\n * @param {Map} quickFilters The quick filters map\n * @returns {boolean} True if the filters have changed because this quick filter was applied\n */\n applyQuickFilter(modelIndex, value, quickFilters) {\n const { model } = this.props;\n const { formatter } = model;\n const column = model.columns[modelIndex];\n\n if (value != null && `${value}`.trim().length > 0) {\n const quickFilter = quickFilters.get(modelIndex);\n if (quickFilter != null) {\n const { text } = quickFilter;\n if (text === value) {\n log.debug2('Ignoring change to existing filter');\n return false;\n }\n }\n quickFilters.set(modelIndex, {\n text: value,\n filter: IrisGrid.makeQuickFilter(column, value, formatter.timeZone),\n });\n return true;\n }\n return quickFilters.delete(modelIndex);\n }\n\n setAdvancedFilter(modelIndex, filter, options) {\n if (modelIndex == null) {\n log.error('Invalid model index to filter on');\n return;\n }\n\n log.debug('Setting advanced filter', modelIndex, filter);\n\n this.startLoading('Filtering...', true);\n\n this.setState(({ advancedFilters }) => {\n const newAdvancedFilters = new Map(advancedFilters);\n if (filter == null) {\n newAdvancedFilters.delete(modelIndex);\n } else {\n newAdvancedFilters.set(modelIndex, {\n filter,\n options,\n });\n }\n return { advancedFilters: newAdvancedFilters };\n });\n }\n\n /**\n * Sets a quick filter against the provided column\n * @param {Number} modelIndex The index in the model for the column this filter is applied to\n * @param {dh.FilterCondition} filter A filter to apply to the column, or null if there was an error\n * @param {String} text The original text the filter was created with\n */\n setQuickFilter(modelIndex, filter, text) {\n log.debug('Setting quick filter', modelIndex, filter, text);\n\n this.startLoading('Filtering...', true);\n\n this.setState(({ quickFilters }) => {\n const newQuickFilters = new Map(quickFilters);\n newQuickFilters.set(modelIndex, { filter, text });\n return { quickFilters: newQuickFilters };\n });\n }\n\n /**\n * Set grid filters based on the filter map\n * @param {Map<string, Object>} filterMap Filter map\n */\n setFilterMap(filterMap) {\n log.debug('setFilterMap', filterMap);\n\n const { advancedSettings } = this.props;\n const clearFiltersOnLinkerFilterUpdate =\n advancedSettings.get(\n AdvancedSettingsType.LINK_CHANGE_CLEARS_ALL_FILTERS\n ) ?? false;\n if (clearFiltersOnLinkerFilterUpdate) {\n this.clearAllFilters();\n }\n\n const { model } = this.props;\n filterMap.forEach(({ columnType, text, value }, columnName) => {\n const column = model.columns.find(\n c => c.name === columnName && c.type === columnType\n );\n if (column == null) {\n return;\n }\n const columnIndex = model.getColumnIndexByName(column.name);\n if (value === null) {\n this.setQuickFilter(columnIndex, column.filter().isNull(), '=null');\n } else {\n const filterValue = TableUtils.isTextType(columnType)\n ? dh.FilterValue.ofString(value)\n : dh.FilterValue.ofNumber(value);\n this.setQuickFilter(\n columnIndex,\n column.filter().eq(filterValue),\n `${text}`\n );\n }\n });\n }\n\n removeColumnFilter(modelColumn) {\n this.startLoading('Filtering...', true);\n\n this.setState(({ advancedFilters, quickFilters }) => {\n const newAdvancedFilters = new Map(advancedFilters);\n const newQuickFilters = new Map(quickFilters);\n newQuickFilters.delete(modelColumn);\n newAdvancedFilters.delete(modelColumn);\n\n return {\n quickFilters: newQuickFilters,\n advancedFilters: newAdvancedFilters,\n };\n });\n }\n\n clearAllFilters() {\n log.debug('Clearing all filters');\n\n const { advancedFilters, quickFilters, searchFilter } = this.state;\n if (\n quickFilters.size === 0 &&\n advancedFilters.size === 0 &&\n searchFilter === null\n ) {\n return;\n }\n\n // if there is an active quick filter input field, reset it as well\n this.clearGridInputField();\n\n this.startLoading('Clearing Filters...', true);\n this.setState({\n quickFilters: new Map(),\n advancedFilters: new Map(),\n searchValue: '',\n searchFilter: null,\n });\n }\n\n clearCrossColumSearch() {\n log.debug('Clearing cross-column search');\n\n this.setState({\n searchValue: '',\n searchFilter: null,\n });\n }\n\n clearGridInputField() {\n if (this.filterInputRef.current != null) {\n this.filterInputRef.current.setValue('');\n }\n }\n\n /**\n * Rebuilds all the current filters. Necessary if something like the time zone has changed.\n */\n rebuildFilters() {\n log.debug('Rebuilding filters');\n\n const { model } = this.props;\n const { advancedFilters, quickFilters } = this.state;\n const { columns, formatter } = model;\n\n const newAdvancedFilters = new Map();\n const newQuickFilters = new Map();\n\n advancedFilters.forEach((value, key) => {\n const { options } = value;\n const column = columns[key];\n const filter = TableUtils.makeAdvancedFilter(\n column,\n options,\n formatter.timeZone\n );\n newAdvancedFilters.set(key, {\n options,\n filter,\n });\n });\n\n quickFilters.forEach((value, key) => {\n const { text } = value;\n const column = columns[key];\n newQuickFilters.set(key, {\n text,\n filter: IrisGrid.makeQuickFilter(column, text, formatter.timeZone),\n });\n });\n\n this.startLoading('Rebuilding filters...', true);\n this.setState({\n quickFilters: newQuickFilters,\n advancedFilters: newAdvancedFilters,\n });\n }\n\n setFilters({ quickFilters, advancedFilters }) {\n this.setState({\n quickFilters,\n advancedFilters,\n });\n }\n\n updateFormatterSettings(settings, forceUpdate = true) {\n const globalColumnFormats = FormatterUtils.getColumnFormats(settings);\n const dateTimeFormatterOptions = FormatterUtils.getDateTimeFormatterOptions(\n settings\n );\n const {\n defaultDecimalFormatOptions = {},\n defaultIntegerFormatOptions = {},\n } = settings;\n\n const isColumnFormatChanged = !deepEqual(\n this.globalColumnFormats,\n globalColumnFormats\n );\n const isDateFormattingChanged = !deepEqual(\n this.dateTimeFormatterOptions,\n dateTimeFormatterOptions\n );\n const isDecimalFormattingChanged = !deepEqual(\n this.decimalFormatOptions,\n defaultDecimalFormatOptions\n );\n const isIntegerFormattingChanged = !deepEqual(\n this.integerFormatOptions,\n defaultIntegerFormatOptions\n );\n if (\n isColumnFormatChanged ||\n isDateFormattingChanged ||\n isDecimalFormattingChanged ||\n isIntegerFormattingChanged\n ) {\n this.globalColumnFormats = globalColumnFormats;\n this.dateTimeFormatterOptions = dateTimeFormatterOptions;\n this.decimalFormatOptions = defaultDecimalFormatOptions;\n this.integerFormatOptions = defaultIntegerFormatOptions;\n this.updateFormatter({}, forceUpdate);\n\n if (isDateFormattingChanged && forceUpdate) {\n this.rebuildFilters();\n }\n }\n }\n\n getAlwaysFetchColumns = memoize(\n (\n alwaysFetchColumns,\n columns,\n floatingLeftColumnCount,\n floatingRightColumnCount\n ) => {\n let floatingLeftColumns = [];\n let floatingRightColumns = [];\n\n if (floatingLeftColumnCount) {\n floatingLeftColumns = columns\n .slice(0, floatingLeftColumnCount)\n .map(col => col.name);\n }\n\n if (floatingRightColumnCount) {\n floatingRightColumns = columns\n .slice(-floatingRightColumnCount)\n .map(col => col.name);\n }\n\n const columnSet = new Set([\n ...alwaysFetchColumns,\n ...floatingLeftColumns,\n ...floatingRightColumns,\n ]);\n\n return [...columnSet];\n }\n );\n\n updateFormatter(updatedFormats, forceUpdate = true) {\n const { customColumnFormatMap } = this.state;\n const update = {\n customColumnFormatMap,\n ...updatedFormats,\n };\n const mergedColumnFormats = [\n ...this.globalColumnFormats,\n ...update.customColumnFormatMap.values(),\n ];\n const formatter = new Formatter(\n mergedColumnFormats,\n this.dateTimeFormatterOptions,\n this.decimalFormatOptions,\n this.integerFormatOptions\n );\n\n log.debug('updateFormatter', this.globalColumnFormats, mergedColumnFormats);\n\n this.setState({ ...update, formatter }, () => {\n if (forceUpdate && this.grid) {\n this.grid.forceUpdate();\n }\n });\n }\n\n initFormatter() {\n const { settings } = this.props;\n this.updateFormatterSettings(settings);\n }\n\n initState() {\n const {\n applyInputFiltersOnInit,\n inputFilters,\n sorts,\n model,\n reverseType,\n customColumns,\n searchValue,\n selectedSearchColumns,\n invertSearchColumns,\n } = this.props;\n\n const searchColumns = selectedSearchColumns ?? [];\n const searchFilter = CrossColumnSearch.createSearchFilter(\n searchValue,\n searchColumns,\n model.columns,\n invertSearchColumns\n );\n\n if (applyInputFiltersOnInit) {\n // There may be more than one input filter on the same column with value === '' applied last\n // We don't want to skip it here, so only excluding the ones that were never applied (null)\n const inputFiltersWithValues = inputFilters.filter(\n inputFilter => inputFilter.value != null\n );\n this.applyInputFilters(inputFiltersWithValues);\n }\n\n this.setState({\n sorts,\n reverseType,\n customColumns,\n isReady: true,\n searchFilter,\n });\n this.initFormatter();\n }\n\n async loadPartitionsTable(partitionColumn) {\n const { model } = this.props;\n this.setState({ isSelectingPartition: true });\n\n try {\n const partitionTable = await this.pending.add(\n model.valuesTable(partitionColumn),\n resolved => resolved.close()\n );\n\n const column = partitionTable.columns[0];\n const sort = column.sort().desc();\n partitionTable.applySort([sort]);\n partitionTable.setViewport(0, 0, [column]);\n\n const data = await this.pending.add(partitionTable.getViewportData());\n if (data.rows.length > 0) {\n const row = data.rows[0];\n const value = row.get(column);\n\n this.updatePartition(value, partitionColumn);\n\n this.setState({ isSelectingPartition: true });\n } else {\n log.info('Table does not have any data, just fetching all');\n this.setState({ isSelectingPartition: false });\n this.handlePartitionFetchAll();\n }\n this.setState({ partitionTable, partitionColumn }, () => {\n this.initState();\n });\n } catch (error) {\n this.handleTableLoadError(error);\n }\n }\n\n updatePartition(partition, partitionColumn) {\n const partitionFilter = partitionColumn\n .filter()\n .eq(dh.FilterValue.ofString(partition));\n const partitionFilters = [partitionFilter];\n this.setState({\n partition,\n partitionFilters,\n });\n }\n\n copyCell(columnIndex, rowIndex, rawValue = false) {\n const { canCopy } = this.props;\n if (canCopy) {\n const value = this.getValueForCell(columnIndex, rowIndex, rawValue);\n ContextActionUtils.copyToClipboard(value).catch(e =>\n log.error('Unable to copy cell', e)\n );\n } else {\n log.error('Attempted to copyCell for user without copy permission.');\n }\n }\n\n /**\n * Copy the provided ranges to the clipboard\n * @param {GridRange[]} ranges The ranges to copy\n * @param {boolean} includeHeaders Include the headers or not\n * @param {boolean} formatValues Whether to format values or not\n * @param {string|null} error Error message if one occurred\n */\n copyRanges(\n ranges,\n includeHeaders = false,\n formatValues = true,\n error = null\n ) {\n const { model, canCopy } = this.props;\n const { metricCalculator, movedColumns } = this.state;\n const { userColumnWidths } = metricCalculator;\n\n if (canCopy) {\n const copyOperation = {\n ranges: GridRange.boundedRanges(\n ranges,\n model.columnCount,\n model.rowCount\n ),\n includeHeaders,\n formatValues,\n movedColumns,\n userColumnWidths,\n error,\n };\n\n this.setState({ copyOperation });\n } else {\n log.error('Attempted copyRanges for user without copy permission.');\n }\n }\n\n startLoading(loadingText, resetRanges = false) {\n this.setState({ loadingText });\n\n const theme = this.getTheme();\n\n if (resetRanges && this.grid) {\n this.grid.clearSelectedRanges();\n this.grid.setViewState({ top: 0 }, true);\n }\n\n if (this.loadingScrimStartTime == null) {\n const { minScrimTransitionTime, maxScrimTransitionTime } = theme;\n const height = this.gridWrapper?.getBoundingClientRect().height ?? 0;\n const scrimTransitionTime = Math.max(\n minScrimTransitionTime,\n Math.min(height / 2, maxScrimTransitionTime)\n );\n this.loadingScrimStartTime = Date.now();\n this.loadingScrimFinishTime =\n this.loadingScrimStartTime + scrimTransitionTime;\n this.setState({\n loadingScrimProgress: 0,\n });\n this.loadingTimer = setTimeout(() => {\n this.setState({\n loadingSpinnerShown: true,\n });\n }, IrisGrid.loadingSpinnerDelay);\n }\n }\n\n stopLoading() {\n this.loadingScrimStartTime = null;\n this.loadingScrimFinishTime = null;\n this.setState({\n loadingText: null,\n loadingScrimProgress: null,\n loadingSpinnerShown: false,\n });\n\n if (this.loadingTimer) {\n clearTimeout(this.loadingTimer);\n this.loadingTimer = null;\n }\n }\n\n /**\n * Rolls back the table state to the last known safe state, or if that's not available then clears all sorts/filters/custom columns.\n */\n rollback() {\n if (this.lastLoadedConfig) {\n log.debug('loading last loading config', this.lastLoadedConfig);\n const {\n advancedFilters,\n customColumns,\n quickFilters,\n reverseType,\n searchFilter,\n sorts,\n } = this.lastLoadedConfig;\n this.lastLoadedConfig = null;\n this.setState({\n advancedFilters,\n customColumns,\n quickFilters,\n reverseType,\n searchFilter,\n sorts,\n });\n } else {\n log.debug('remove all sorts, filters, and custom columns');\n this.setState({\n advancedFilters: new Map(),\n quickFilters: new Map(),\n sorts: [],\n customColumns: [],\n reverseType: TableUtils.REVERSE_TYPE.NONE,\n });\n }\n }\n\n /**\n * Check if we can rollback the current state to a safe state.\n * @returns {boolean} true if there's a previously known safe state or if some of the current state isn't empty.\n */\n canRollback() {\n return this.lastLoadedConfig != null || !isEmptyConfig(this.state);\n }\n\n startListening(model) {\n model.addEventListener(IrisGridModel.EVENT.UPDATED, this.handleUpdate);\n model.addEventListener(\n IrisGridModel.EVENT.REQUEST_FAILED,\n this.handleRequestFailed\n );\n model.addEventListener(\n IrisGridModel.EVENT.COLUMNS_CHANGED,\n this.handleCustomColumnsChanged\n );\n model.addEventListener(\n IrisGridModel.EVENT.PENDING_DATA_UPDATED,\n this.handlePendingDataUpdated\n );\n }\n\n stopListening(model) {\n model.removeEventListener(IrisGridModel.EVENT.UPDATED, this.handleUpdate);\n model.removeEventListener(\n IrisGridModel.EVENT.REQUEST_FAILED,\n this.handleRequestFailed\n );\n model.removeEventListener(\n IrisGridModel.EVENT.COLUMNS_CHANGED,\n this.handleCustomColumnsChanged\n );\n model.removeEventListener(\n IrisGridModel.EVENT.PENDING_DATA_UPDATED,\n this.handlePendingDataUpdated\n );\n }\n\n focusFilterBar(column) {\n const { model } = this.props;\n const { columnCount } = model;\n const modelColumn = this.getModelColumn(column);\n\n if (\n column == null ||\n column < 0 ||\n columnCount <= column ||\n !model.isFilterable(modelColumn)\n ) {\n this.setState({ focusedFilterBarColumn: null });\n return;\n }\n\n const { metricCalculator, metrics } = this.state;\n const { gridX, left, rightVisible, lastLeft } = metrics;\n if (column < left) {\n this.grid.setViewState({ left: column }, true);\n } else if (rightVisible < column) {\n const metricState = this.grid.getMetricState();\n const newLeft = metricCalculator.getLastLeft(metricState, column, gridX);\n this.grid.setViewState({ left: Math.min(newLeft, lastLeft) }, true);\n }\n this.lastFocusedFilterBarColumn = column;\n this.setState({ focusedFilterBarColumn: column, isFilterBarShown: true });\n }\n\n hideColumnByVisibleIndex(columnVisibleIndex) {\n const { metricCalculator, movedColumns } = this.state;\n metricCalculator.setColumnWidth(\n GridUtils.getModelIndex(columnVisibleIndex, movedColumns),\n 0\n );\n\n this.grid.forceUpdate();\n }\n\n freezeColumnByColumnName(columnName) {\n const { frozenColumns } = this.state;\n const { model } = this.props;\n log.debug2('freezing column', columnName);\n\n let allFrozenColumns;\n\n if (frozenColumns == null) {\n allFrozenColumns = new Set(model.layoutHints?.frozenColumns ?? []);\n allFrozenColumns.add(columnName);\n } else {\n allFrozenColumns = new Set([...frozenColumns, columnName]);\n }\n\n this.setState({\n frozenColumns: [...allFrozenColumns],\n });\n }\n\n unFreezeColumnByColumnName(columnName) {\n const { frozenColumns } = this.state;\n const { model } = this.props;\n log.debug2('unfreezing column', columnName);\n\n let allFrozenColumns;\n\n if (frozenColumns == null) {\n allFrozenColumns = new Set(model.layoutHints?.frozenColumns ?? []);\n allFrozenColumns.delete(columnName);\n } else {\n allFrozenColumns = new Set(\n frozenColumns.filter(col => col !== columnName)\n );\n }\n\n this.setState({\n frozenColumns: [...allFrozenColumns],\n });\n }\n\n handleColumnVisibilityChanged(modelIndexes, visibilityOption) {\n const { metricCalculator } = this.state;\n if (\n visibilityOption === VisibilityOrderingBuilder.VISIBILITY_OPTIONS.SHOW\n ) {\n modelIndexes.forEach(modelIndex => {\n metricCalculator.resetColumnWidth(modelIndex);\n });\n } else {\n modelIndexes.forEach(modelIndex => {\n metricCalculator.setColumnWidth(modelIndex, 0);\n });\n }\n this.grid.forceUpdate();\n }\n\n handleCrossColumnSearch(\n searchValue,\n selectedSearchColumns,\n invertSearchColumns\n ) {\n const { model } = this.props;\n\n this.updateSearchFilter(\n searchValue,\n selectedSearchColumns,\n model.columns,\n invertSearchColumns\n );\n\n this.setState({\n searchValue,\n selectedSearchColumns,\n invertSearchColumns,\n });\n }\n\n updateSearchFilter(\n searchValue,\n selectedSearchColumns,\n columns,\n invertSearchColumns\n ) {\n const searchFilter = CrossColumnSearch.createSearchFilter(\n searchValue,\n selectedSearchColumns,\n columns,\n invertSearchColumns\n );\n this.setState({ searchFilter });\n }\n\n handleAnimationLoop() {\n this.grid.updateCanvasScale();\n this.grid.updateCanvas();\n\n if (this.isAnimating) {\n this.animationFrame = requestAnimationFrame(this.handleAnimationLoop);\n }\n }\n\n handleAnimationStart() {\n log.debug2('handleAnimationStart');\n\n this.isAnimating = true;\n\n this.animationFrame = requestAnimationFrame(this.handleAnimationLoop);\n }\n\n handleAnimationEnd() {\n log.debug2('handleAnimationEnd');\n\n this.isAnimating = false;\n }\n\n handlePartitionAppend(value) {\n const { onPartitionAppend } = this.props;\n const { partitionColumn } = this.state;\n onPartitionAppend(partitionColumn, value);\n }\n\n handlePartitionChange(partition) {\n const { partitionColumn } = this.state;\n this.updatePartition(partition, partitionColumn);\n }\n\n handlePartitionFetchAll() {\n this.setState({\n partitionFilters: [],\n isSelectingPartition: false,\n });\n }\n\n handlePartitionDone() {\n this.setState({ isSelectingPartition: false });\n }\n\n handleTableLoadError(error) {\n if (PromiseUtils.isCanceled(error)) {\n return;\n }\n\n log.error(error);\n\n const { onError } = this.props;\n onError(error);\n }\n\n showAllColumns() {\n const { metricCalculator } = this.state;\n const { userColumnWidths } = metricCalculator;\n const entries = [...userColumnWidths.entries()];\n for (let i = 0; i < entries.length; i += 1) {\n const [modelIndex, columnWidth] = entries[i];\n if (columnWidth === 0) {\n metricCalculator.resetColumnWidth(modelIndex);\n }\n }\n this.grid.forceUpdate();\n }\n\n toggleSort(columnIndex, addToExisting) {\n log.info('Toggling sort for column', columnIndex);\n\n const { model } = this.props;\n const { sorts: currentSorts } = this.state;\n const modelColumn = this.getModelColumn(columnIndex);\n const sorts = TableUtils.toggleSortForColumn(\n currentSorts,\n model.table,\n modelColumn,\n addToExisting\n );\n this.updateSorts(sorts);\n }\n\n updateSorts(sorts) {\n this.startLoading('Sorting...');\n this.setState({ sorts });\n this.grid.forceUpdate();\n }\n\n sortColumn(modelColumn, direction, isAbs = false, addToExisting = false) {\n const { model } = this.props;\n const sorts = TableUtils.sortColumn(\n model.table,\n modelColumn,\n direction,\n isAbs,\n addToExisting\n );\n this.startLoading('Sorting...');\n this.setState({ sorts });\n this.grid.forceUpdate();\n }\n\n reverse(reverseType) {\n this.startLoading('Reversing...');\n this.setState({ reverseType });\n this.grid.forceUpdate();\n }\n\n isReversible() {\n const { model } = this.props;\n return model.isReversible;\n }\n\n toggleFilterBar(focusIndex = this.lastFocusedFilterBarColumn) {\n let { isFilterBarShown } = this.state;\n isFilterBarShown = !isFilterBarShown;\n this.setState({ isFilterBarShown });\n\n if (isFilterBarShown) {\n if (focusIndex != null) {\n this.focusFilterBar(focusIndex);\n } else {\n let columnIndex = 0;\n const { model } = this.props;\n const { columnCount } = model;\n for (let i = 0; i < columnCount; i += 1) {\n const modelColumn = this.getModelColumn(i);\n if (modelColumn != null) {\n const column = model.columns[modelColumn];\n if (column != null && TableUtils.isTextType(column.type)) {\n columnIndex = i;\n break;\n }\n }\n }\n this.focusFilterBar(columnIndex);\n }\n } else {\n this.grid.focus();\n }\n }\n\n isTableSearchAvailable() {\n const { model, canToggleSearch } = this.props;\n const searchDisplayMode = model?.layoutHints?.searchDisplayMode;\n\n if (searchDisplayMode === dh.SearchDisplayMode?.SEARCH_DISPLAY_HIDE) {\n return false;\n }\n if (searchDisplayMode === dh.SearchDisplayMode?.SEARCH_DISPLAY_SHOW) {\n return true;\n }\n\n return canToggleSearch;\n }\n\n toggleSearchBar() {\n const { showSearchBar } = this.state;\n if (!this.isTableSearchAvailable()) {\n return;\n }\n\n const update = !showSearchBar;\n this.setState(\n {\n showSearchBar: update,\n },\n () => {\n if (update && this.crossColumnRef.current) {\n this.crossColumnRef.current.focus();\n } else {\n this.grid.focus();\n }\n }\n );\n }\n\n async commitPending() {\n const { model } = this.props;\n if (!model.isEditable) {\n throw new Error('Cannot save, table is not editable');\n }\n\n const { pendingSavePromise } = this.state;\n if (pendingSavePromise != null) {\n throw new Error('Save already in progress');\n }\n\n if (document.activeElement.classList.contains('grid-cell-input-field')) {\n if (document.activeElement.classList.contains('error')) {\n throw new ValidationError('Current input is invalid');\n }\n\n // Focus the grid again to commit any pending input changes\n this.grid.focus();\n }\n\n const newPendingSavePromise = this.pending\n .add(model.commitPending())\n .then(() => {\n this.setState({ pendingSaveError: null, pendingSavePromise: null });\n })\n .catch(err => {\n if (!PromiseUtils.isCanceled(err)) {\n this.setState({ pendingSaveError: err, pendingSavePromise: null });\n }\n });\n this.setState({ pendingSavePromise: newPendingSavePromise });\n return newPendingSavePromise;\n }\n\n async discardPending() {\n const { pendingSavePromise } = this.state;\n if (pendingSavePromise != null) {\n throw new Error('Cannot cancel a save in progress');\n }\n\n this.setState({\n pendingSavePromise: null,\n pendingSaveError: null,\n pendingDataMap: new Map(),\n pendingDataErrors: new Map(),\n });\n }\n\n /**\n * Select the passed in column and notify listener\n * @param {dh.Column} column The column in this table to link\n */\n selectColumn(column) {\n const { onColumnSelected } = this.props;\n onColumnSelected(column);\n }\n\n /**\n * Select all the data for a given row and notify listener\n */\n selectData(columnIndex, rowIndex) {\n const { model } = this.props;\n const { columns } = model;\n const dataMap = {};\n for (let i = 0; i < columns.length; i += 1) {\n const column = columns[i];\n const { name, type } = column;\n const value = model.valueForCell(i, rowIndex);\n const text = model.textForCell(i, rowIndex);\n dataMap[name] = { value, text, type };\n }\n\n const { onDataSelected } = this.props;\n onDataSelected(rowIndex, dataMap);\n }\n\n handleAdvancedFilterChange(column, filter, options) {\n const { model } = this.props;\n this.setAdvancedFilter(\n model.getColumnIndexByName(column.name),\n filter,\n options\n );\n }\n\n handleAdvancedFilterSortChange(column, direction, addToExisting = false) {\n const { model } = this.props;\n const columnIndex = model.getColumnIndexByName(column.name);\n const oldSort = TableUtils.getSortForColumn(model.sort, columnIndex);\n let newSort = null;\n\n if (oldSort == null || oldSort.direction !== direction) {\n if (direction === TableUtils.sortDirection.descending) {\n newSort = column.sort().desc();\n } else {\n newSort = column.sort().asc();\n }\n }\n\n const sorts = TableUtils.setSortForColumn(\n model.sort,\n columnIndex,\n newSort,\n addToExisting\n );\n log.info('Setting table sorts', sorts);\n\n this.startLoading('Sorting...');\n this.setState({ sorts });\n\n this.grid.forceUpdate();\n }\n\n handleAdvancedFilterDone() {\n this.grid.focus();\n }\n\n handleAdvancedMenuOpened(column) {\n this.setState({ shownAdvancedFilter: column });\n }\n\n handleAdvancedMenuClosed(columnIndex) {\n const { focusedFilterBarColumn, isFilterBarShown } = this.state;\n if (\n isFilterBarShown &&\n focusedFilterBarColumn === columnIndex &&\n this.filterInputRef.current !== null\n ) {\n this.filterInputRef.current.focus();\n this.setState({ shownAdvancedFilter: null });\n } else {\n this.setState({\n focusedFilterBarColumn: null,\n shownAdvancedFilter: null,\n });\n }\n }\n\n handleCancel() {\n this.rollback();\n }\n\n // eslint-disable-next-line class-methods-use-this\n handleChartChange() {\n // TODO: IDS-4242 Update Chart Preview\n }\n\n handleChartCreate(settings) {\n const { model, onCreateChart } = this.props;\n onCreateChart(settings, model.table);\n }\n\n handleGridError(error) {\n log.warn('Grid Error', error);\n this.setState({\n toastMessage: <div className=\"error-message\">{`${error}`}</div>,\n });\n }\n\n handleFilterBarChange(value) {\n this.startLoading('Filtering...', true);\n\n this.setState(({ focusedFilterBarColumn, quickFilters }) => {\n const newQuickFilters = new Map(quickFilters);\n const modelIndex = this.getModelColumn(focusedFilterBarColumn);\n this.applyQuickFilter(modelIndex, value, newQuickFilters);\n return { quickFilters: newQuickFilters };\n });\n }\n\n handleFilterBarDone(setGridFocus = true, defocusInput = true) {\n if (setGridFocus) {\n this.grid.focus();\n }\n if (defocusInput) {\n this.setState({ focusedFilterBarColumn: null });\n }\n }\n\n handleFilterBarTab(backward) {\n const { focusedFilterBarColumn } = this.state;\n if (backward) {\n this.focusFilterBar(focusedFilterBarColumn - 1);\n } else {\n this.focusFilterBar(focusedFilterBarColumn + 1);\n }\n }\n\n handleFormatSelection(modelIndex, selectedFormat) {\n const { model } = this.props;\n const column = model.columns[modelIndex];\n const { customColumnFormatMap: prevCustomColumnFormatMap } = this.state;\n const customColumnFormatMap = new Map(prevCustomColumnFormatMap);\n\n if (selectedFormat) {\n const normalizedType = TableUtils.getNormalizedType(column.type);\n const columnFormattingRule = Formatter.makeColumnFormattingRule(\n normalizedType,\n column.name,\n selectedFormat\n );\n\n customColumnFormatMap.set(column.name, columnFormattingRule);\n } else {\n customColumnFormatMap.delete(column.name);\n }\n\n this.updateFormatter({ customColumnFormatMap });\n }\n\n handleMenu() {\n this.setState({ isMenuShown: true });\n }\n\n handleMenuClose() {\n this.setState({ isMenuShown: false, openOptions: [] });\n }\n\n handleMenuBack() {\n this.setState(({ openOptions }) => {\n const newOptions = [...openOptions];\n newOptions.pop();\n return { openOptions: newOptions };\n });\n }\n\n handleMenuSelect(option) {\n this.setState(({ openOptions }) => ({\n openOptions: [...openOptions, option],\n }));\n }\n\n handleRequestFailed(event) {\n log.error('request failed:', event.detail);\n this.stopLoading();\n if (this.canRollback()) {\n this.startLoading('Rolling back changes...', true);\n this.rollback();\n } else {\n log.error('Table failed and unable to rollback');\n const { onError } = this.props;\n onError(new Error(`Error displaying table: ${event.detail}`));\n }\n }\n\n handleUpdate() {\n this.stopLoading();\n log.debug2('Received model update');\n\n const {\n advancedFilters,\n customColumns,\n quickFilters,\n reverseType,\n searchFilter,\n sorts,\n } = this.state;\n const config = {\n advancedFilters,\n customColumns,\n reverseType,\n quickFilters,\n searchFilter,\n sorts,\n };\n if (!isEmptyConfig(config)) {\n this.lastLoadedConfig = config;\n } else {\n this.lastLoadedConfig = null;\n }\n\n this.grid.forceUpdate();\n }\n\n handleViewChanged(metrics) {\n const { model } = this.props;\n const { bottomViewport } = metrics;\n const { selectionEndRow = 0 } = this.grid?.state ?? {};\n let pendingRowCount = 0;\n if (model.isEditable) {\n // We have an editable table that we can add new rows to\n // Display empty rows beneath the table rows that user can fill in\n const bottomNonFloating = model.rowCount - model.floatingBottomRowCount;\n if (selectionEndRow === bottomNonFloating - 1) {\n // Selection is in the last row, add another blank row\n pendingRowCount = model.pendingRowCount + 1;\n } else if (selectionEndRow === bottomNonFloating - 2) {\n // We may have just added a row based on selection moving, so just leave it as is\n pendingRowCount = model.pendingRowCount;\n } else {\n // Otherwise fill up the viewport with empty cells\n pendingRowCount = Math.max(\n 0,\n bottomViewport -\n (model.rowCount - model.pendingRowCount) -\n model.floatingTopRowCount -\n model.floatingBottomRowCount -\n 1\n );\n }\n }\n\n this.setState({ metrics, pendingRowCount });\n }\n\n handleSelectionChanged(selectedRanges) {\n const { onSelectionChanged } = this.props;\n const { copyOperation } = this.state;\n this.setState({ selectedRanges });\n if (copyOperation != null) {\n this.setState({ copyOperation: null });\n }\n onSelectionChanged(selectedRanges);\n }\n\n handleMovedColumnsChanged(movedColumns, onChangeApplied = () => {}) {\n this.setState({ movedColumns }, onChangeApplied);\n }\n\n handleTooltipRef(tooltip) {\n // Need to start the timer right away, since we're creating the tooltip when we want the timer to start\n if (tooltip) {\n tooltip.startTimer();\n }\n\n this.tooltip = tooltip;\n }\n\n handleUpdateCustomColumns(customColumns) {\n log.info(`handleUpdateCustomColumns:`, customColumns);\n\n const { model } = this.props;\n const {\n movedColumns,\n sorts,\n quickFilters,\n advancedFilters,\n selectDistinctColumns,\n } = this.state;\n\n const { columns } = model;\n const oldCustomColumns = model.customColumns.map(\n customColumn => `${customColumn}`\n );\n\n const removedColumnNames = IrisGridUtils.getRemovedCustomColumnNames(\n oldCustomColumns,\n customColumns\n );\n if (removedColumnNames.length > 0) {\n const newSorts = IrisGridUtils.removeSortsInColumns(\n sorts,\n removedColumnNames\n );\n const newQuickFilters = IrisGridUtils.removeFiltersInColumns(\n columns,\n quickFilters,\n removedColumnNames\n );\n const newAdvancedFilters = IrisGridUtils.removeFiltersInColumns(\n columns,\n advancedFilters,\n removedColumnNames\n );\n const newMovedColumns = IrisGridUtils.removeColumnFromMovedColumns(\n columns,\n movedColumns,\n removedColumnNames\n );\n const newSelectDistinctColumns = IrisGridUtils.removeColumnsFromSelectDistinctColumns(\n selectDistinctColumns,\n removedColumnNames\n );\n if (newSorts.length !== sorts) {\n log.debug('removing sorts from removed custom columns...');\n this.setState({ sorts: newSorts });\n }\n if (\n newQuickFilters.size !== quickFilters.size ||\n newAdvancedFilters.size !== advancedFilters.size\n ) {\n log.debug(`removing filters from removed custom columns...`);\n this.setState({\n quickFilters: newQuickFilters,\n advancedFilters: newAdvancedFilters,\n });\n }\n if (!deepEqual(movedColumns, newMovedColumns)) {\n log.debug(\n `change moved columns for removed custom columns`,\n newMovedColumns\n );\n this.setState({ movedColumns: newMovedColumns });\n }\n if (!deepEqual(selectDistinctColumns, newSelectDistinctColumns)) {\n log.debug(\n `change selectDistinct columns for removed custom columns`,\n newMovedColumns\n );\n this.setState({ selectDistinctColumns: newSelectDistinctColumns });\n }\n }\n\n this.setState({ customColumns, top: 0 });\n this.startLoading('Applying custom columns...');\n }\n\n handleCustomColumnsChanged() {\n log.debug('custom columns changed');\n const { isReady } = this.state;\n if (isReady) {\n this.stopLoading();\n this.grid.forceUpdate();\n } else {\n this.initState();\n }\n }\n\n handlePendingCommitClicked() {\n return this.commitPending();\n }\n\n handlePendingDiscardClicked() {\n return this.discardPending();\n }\n\n handlePendingDataUpdated() {\n log.debug('pending data updated');\n const { model } = this.props;\n const { pendingDataMap, pendingDataErrors } = model;\n this.setState({\n pendingDataMap,\n pendingDataErrors,\n pendingSaveError: null,\n });\n this.grid.forceUpdate();\n }\n\n /**\n * User added, removed, or changed the order of aggregations, or position\n * @param {AggregationSettings} aggregationSettings The new aggregation settings\n */\n handleAggregationsChange(aggregationSettings) {\n log.debug('handleAggregationsChange', aggregationSettings);\n\n this.startLoading(\n `Aggregating ${aggregationSettings.aggregations\n .map(a => a.operation)\n .join(', ')}...`\n );\n this.setState({ aggregationSettings });\n }\n\n /**\n * A specific aggregation has been modified\n * @param {Aggregation} aggregation The new aggregation\n */\n handleAggregationChange(aggregation) {\n log.debug('handleAggregationChange', aggregation);\n\n this.startLoading(`Aggregating ${aggregation.operation}...`);\n this.setState(({ aggregationSettings }) => ({\n selectedAggregation: aggregation,\n aggregationSettings: {\n ...aggregationSettings,\n aggregations: aggregationSettings.aggregations.map(a =>\n a.operation === aggregation.operation ? aggregation : a\n ),\n },\n }));\n }\n\n /**\n * An aggregations has been selected for editing\n * @param {Aggregation} aggregation The aggregation to edit\n */\n handleAggregationEdit(aggregation) {\n log.debug('handleAggregationEdit', aggregation);\n\n const { openOptions } = this.state;\n\n this.setState({\n openOptions: [\n ...openOptions,\n {\n type: OptionType.AGGREGATION_EDIT,\n title: `Edit Columns to ${aggregation.operation}`,\n },\n ],\n selectedAggregation: aggregation,\n });\n }\n\n handleRollupChange(rollupConfig) {\n log.info('Rollup change', rollupConfig);\n\n this.resetGridViewState();\n this.showAllColumns();\n this.clearAllFilters();\n\n this.startLoading(\n `Grouping by columns ${rollupConfig?.columns?.join(', ') ?? ''}...`\n );\n\n // Have to clear select distinct since rollup uses the original columns, not the current ones.\n // IrisGridProxyModel has a check to prevent model update\n // when selectDistinctModel is cleared and the rollupConfig is set on the model.\n this.setState({\n rollupConfig,\n movedColumns: [],\n sorts: [],\n reverseType: TableUtils.REVERSE_TYPE.NONE,\n selectDistinctColumns: [],\n });\n }\n\n handleSelectDistinctChanged(columnNames) {\n log.debug('SelectDistinct change', columnNames);\n\n this.resetGridViewState();\n\n this.showAllColumns();\n this.clearAllFilters();\n\n this.startLoading(\n `Selecting distinct values in ${\n columnNames.length > 0 ? columnNames.join(', ') : ''\n }...`\n );\n\n this.setState({\n selectDistinctColumns: columnNames,\n movedColumns: [],\n sorts: [],\n reverseType: TableUtils.REVERSE_TYPE.NONE,\n });\n }\n\n handleDownloadTableStart() {\n const { canDownloadCsv } = this.props;\n if (canDownloadCsv) {\n this.setState({\n isTableDownloading: true,\n tableDownloadProgress: 0,\n tableDownloadEstimatedTime: null,\n tableDownloadStatus: TableCsvExporter.DOWNLOAD_STATUS.INITIATING,\n });\n } else {\n log.error(\n 'Attempted to handleDownloadTableStart for user without download CSV permission.'\n );\n }\n }\n\n handleDownloadTable(...args) {\n const { canDownloadCsv } = this.props;\n if (canDownloadCsv) {\n log.info('start table downloading', ...args);\n this.setState(() => {\n if (this.tableSaver) {\n this.tableSaver.startDownload(...args);\n }\n return {\n tableDownloadStatus: TableCsvExporter.DOWNLOAD_STATUS.DOWNLOADING,\n };\n });\n } else {\n log.error(\n 'Attempted to handleDownloadTable for user without download CSV permission.'\n );\n }\n }\n\n handleCancelDownloadTable() {\n this.tableSaver.cancelDownload();\n this.setState({ isTableDownloading: false });\n }\n\n handleDownloadProgressUpdate(\n tableDownloadProgress,\n tableDownloadEstimatedTime\n ) {\n const { tableDownloadStatus } = this.state;\n if (tableDownloadStatus === TableCsvExporter.DOWNLOAD_STATUS.DOWNLOADING) {\n this.setState({\n tableDownloadProgress,\n tableDownloadEstimatedTime,\n });\n }\n }\n\n handleDownloadCompleted() {\n this.setState({\n isTableDownloading: false,\n tableDownloadProgress: 100,\n tableDownloadStatus: TableCsvExporter.DOWNLOAD_STATUS.FINISHED,\n });\n }\n\n handleDownloadCanceled() {\n this.setState({\n isTableDownloading: false,\n tableDownloadProgress: 0,\n tableDownloadStatus: TableCsvExporter.DOWNLOAD_STATUS.CANCELED,\n });\n }\n\n /**\n * Delete the specified ranges from the table.\n * @param {GridRange[]} ranges The ranges to delete\n */\n deleteRanges(ranges) {\n const { model } = this.props;\n this.pending.add(model.delete(ranges)).catch(e => {\n if (!PromiseUtils.isCanceled(e)) {\n log.error('Unable to delete ranges', ranges, e);\n }\n });\n }\n\n resetColumnSelection() {\n if (this.grid == null) {\n return;\n }\n const { isSelectingColumn } = this.props;\n if (isSelectingColumn) {\n const { columnAllowedCursor } = this.props;\n this.grid.setState({ cursor: columnAllowedCursor });\n } else {\n this.grid.setState({ cursor: Grid.CURSOR_TYPE_DEFAULT });\n this.setState({ hoverSelectColumn: null });\n }\n }\n\n resetGridViewState(forceUpdate = true) {\n if (!this.grid) {\n return;\n }\n\n this.grid.clearSelectedRanges();\n this.grid.setViewState(\n { left: 0, top: 0, topOffset: 0, leftOffset: 0 },\n forceUpdate\n );\n }\n\n sendStateChange() {\n if (!this.grid) {\n return;\n }\n const { state: irisGridState } = this;\n const { state: gridState } = this.grid;\n const { onStateChange } = this.props;\n\n onStateChange(irisGridState, gridState);\n }\n\n render() {\n const {\n children,\n customFilters,\n getDownloadWorker,\n isSelectingColumn,\n isStuckToBottom,\n isStuckToRight,\n model,\n name,\n onlyFetchVisibleColumns,\n alwaysFetchColumns,\n advancedSettings,\n onAdvancedSettingsChange,\n canDownloadCsv,\n } = this.props;\n const {\n metricCalculator,\n metrics,\n isFilterBarShown,\n isSelectingPartition,\n isMenuShown,\n isReady,\n copyOperation,\n focusedFilterBarColumn,\n loadingText,\n loadingScrimProgress,\n loadingSpinnerShown,\n keyHandlers,\n mouseHandlers,\n shownColumnTooltip,\n hoverAdvancedFilter,\n shownAdvancedFilter,\n hoverSelectColumn,\n quickFilters,\n advancedFilters,\n partition,\n partitionFilters,\n partitionTable,\n partitionColumn,\n searchFilter,\n selectDistinctColumns,\n\n movedColumns,\n movedRows,\n\n formatter,\n\n sorts,\n reverseType,\n customColumns,\n\n selectedRanges,\n isTableDownloading,\n tableDownloadStatus,\n tableDownloadProgress,\n tableDownloadEstimatedTime,\n\n showSearchBar,\n searchValue,\n selectedSearchColumns,\n invertSearchColumns,\n\n aggregationSettings,\n selectedAggregation,\n rollupConfig,\n openOptions,\n pendingSavePromise,\n pendingSaveError,\n pendingRowCount,\n pendingDataErrors,\n pendingDataMap,\n toastMessage,\n frozenColumns,\n } = this.state;\n if (!isReady) {\n return null;\n }\n\n const theme = this.getTheme();\n\n const filter = this.getCachedFilter(\n customFilters,\n quickFilters,\n advancedFilters,\n partitionFilters,\n searchFilter\n );\n\n const { userColumnWidths } = metricCalculator;\n const stateOverride = this.getCachedStateOverride(\n hoverSelectColumn,\n isFilterBarShown,\n isSelectingColumn,\n loadingScrimProgress,\n quickFilters,\n advancedFilters,\n sorts,\n reverseType,\n rollupConfig\n );\n const top = metrics ? metrics.top : 0;\n const bottom = metrics ? metrics.bottomViewport : 0;\n let left = null;\n let right = null;\n if (onlyFetchVisibleColumns) {\n left = metrics ? metrics.left : 0;\n right = metrics ? metrics.right : 0;\n }\n const isVisible =\n metrics != null && metrics.width > 0 && metrics.height > 0;\n const isRollup = (rollupConfig?.columns?.length ?? 0) > 0;\n\n let focusField = null;\n\n const debounceMs = metrics\n ? Math.min(\n Math.max(IrisGrid.minDebounce, Math.round(metrics.rowCount / 200)),\n IrisGrid.maxDebounce\n )\n : IrisGrid.maxDebounce;\n\n if (isFilterBarShown && focusedFilterBarColumn != null && metrics != null) {\n const { gridX, gridY, visibleColumnXs, visibleColumnWidths } = metrics;\n const columnX = visibleColumnXs.get(focusedFilterBarColumn);\n const columnWidth = visibleColumnWidths.get(focusedFilterBarColumn);\n if (columnX != null && columnWidth != null) {\n const x = gridX + columnX;\n const y = gridY - theme.filterBarHeight;\n const fieldWidth = columnWidth + 1; // cover right border\n const fieldHeight = theme.filterBarHeight - 1; // remove bottom border\n const style = {\n top: y,\n left: x,\n minWidth: fieldWidth,\n height: fieldHeight,\n };\n let value = '';\n let isValid = true;\n const modelColumn = this.getModelColumn(focusedFilterBarColumn);\n const quickFilter = quickFilters.get(modelColumn);\n const advancedFilter = advancedFilters.get(modelColumn);\n if (quickFilter != null) {\n value = quickFilter.text;\n isValid = quickFilter.filter != null;\n }\n const isBarFiltered =\n quickFilters.size !== 0 || advancedFilters.size !== 0;\n focusField = (\n <FilterInputField\n ref={this.filterInputRef}\n style={style}\n className={classNames({\n error: !isValid,\n active: value !== '' || advancedFilter != null,\n 'iris-grid-has-filter': isBarFiltered,\n })}\n isAdvancedFilterSet={advancedFilter != null}\n onAdvancedFiltersTriggered={() => {\n this.setState({ shownAdvancedFilter: focusedFilterBarColumn });\n }}\n key={focusedFilterBarColumn}\n onChange={this.handleFilterBarChange}\n onDone={this.handleFilterBarDone}\n onTab={this.handleFilterBarTab}\n onContextMenu={this.grid.handleContextMenu}\n debounceMs={debounceMs}\n value={value}\n />\n );\n }\n }\n\n let loadingElement = null;\n if (loadingText != null) {\n const loadingStatus = (\n <div className=\"iris-grid-loading-status\">{loadingText}</div>\n );\n const loader = <DeephavenSpinner show={loadingSpinnerShown} />;\n const cancelButton = (\n <button\n type=\"button\"\n onClick={this.handleCancel}\n className={classNames(\n 'btn btn-secondary btn-cancelable iris-grid-btn-cancel',\n {\n show: loadingSpinnerShown,\n }\n )}\n >\n Cancel\n </button>\n );\n\n const gridY = metrics ? metrics.gridY : 0;\n loadingElement = (\n <div className=\"iris-grid-loading\" style={{ top: gridY }}>\n {loadingStatus}\n {loader}\n {cancelButton}\n </div>\n );\n }\n\n let columnTooltip = null;\n if (shownColumnTooltip != null && metrics && this.gridWrapper) {\n const {\n columnHeaderHeight,\n visibleColumnXs,\n visibleColumnWidths,\n width,\n } = metrics;\n const columnX = visibleColumnXs.get(shownColumnTooltip);\n const columnWidth = visibleColumnWidths.get(shownColumnTooltip);\n\n /**\n * Create a wrapper dom element, the size of the column header.\n * The wrapper acts as tooltip parent, the tooltip component\n * will trigger hide on mouseleave of wrapper or tooltip.\n * The wrapper should be bound to within the grid dimensions,\n * so popper only remains triggered while mouse is inside the panel.\n */\n const boundedLeft = Math.max(0, columnX);\n let boundedWidth = columnWidth;\n if (columnX + columnWidth > width) {\n // column is extending past right edge\n boundedWidth = width - columnX;\n } else if (columnX < 0) {\n // column is extending past left edge\n boundedWidth = columnWidth - Math.abs(columnX);\n }\n\n const wrapperStyle = {\n position: 'absolute',\n top: 0,\n left: boundedLeft,\n width: boundedWidth,\n height: columnHeaderHeight,\n pointerEvents: 'none',\n };\n\n /**\n * Because the popper parent wrapper center is no longer the same as\n * the column label center, we create a popper virtual ref, to handle\n * positioning and keep the popper centered on the label. Creates a\n * 1px x headerHeight virtual object, placed centered on the column\n * label, clamped to 0 + margin to width - margin. We add a margin,\n * otherwise the arrow wants to escape the boundary.\n */\n const gridRect = this.gridWrapper.getBoundingClientRect();\n const popperMargin = 20;\n const virtualReference = {\n clientWidth: 1,\n clientHeight: columnHeaderHeight,\n getBoundingClientRect() {\n return {\n top: gridRect.top,\n left:\n gridRect.left +\n clamp(\n columnX + columnWidth / 2,\n popperMargin,\n width - popperMargin\n ),\n bottom: gridRect.top + columnHeaderHeight,\n right:\n gridRect.left +\n clamp(\n columnX + columnWidth / 2,\n popperMargin,\n width - popperMargin\n ) +\n 1,\n width: 1,\n height: columnHeaderHeight,\n };\n },\n };\n\n const popperOptions = {\n placement: 'bottom',\n modifiers: {\n flip: {\n behavior: ['bottom', 'top'],\n },\n },\n };\n\n const modelColumn = this.getModelColumn(shownColumnTooltip);\n const column = model.columns[modelColumn];\n\n if (column != null) {\n columnTooltip = (\n <div style={wrapperStyle}>\n <Tooltip\n key={column.name}\n timeout={400}\n interactive\n options={popperOptions}\n ref={this.handleTooltipRef}\n referenceObject={virtualReference}\n onExited={() => {\n this.setState({ shownColumnTooltip: null });\n }}\n >\n <ColumnStatistics\n model={model}\n column={column}\n onStatistics={() => {\n if (this.tooltip) this.tooltip.update();\n }}\n />\n </Tooltip>\n </div>\n );\n }\n }\n\n const filterBar = [];\n if (metrics && isFilterBarShown) {\n const {\n gridX,\n gridY,\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths,\n } = metrics;\n const { filterBarHeight } = theme;\n\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const columnIndex = visibleColumns[i];\n\n const columnX = visibleColumnXs.get(columnIndex);\n const columnWidth = visibleColumnWidths.get(columnIndex);\n const modelColumn = this.getModelColumn(columnIndex);\n const isFilterable = model.isFilterable(modelColumn);\n if (\n isFilterable &&\n columnX != null &&\n columnWidth != null &&\n columnWidth > 0\n ) {\n const x = gridX + columnX + columnWidth - 24;\n const y = gridY - filterBarHeight + 2; // 2 acts as top margin for the button\n const style = {\n position: 'absolute',\n top: y,\n left: x,\n };\n const advancedFilter = advancedFilters.get(modelColumn);\n const isFilterSet = advancedFilter != null;\n const isFilterVisible =\n columnIndex === hoverAdvancedFilter ||\n columnIndex === focusedFilterBarColumn ||\n isFilterSet;\n const element = (\n <div\n className={classNames('advanced-filter-button-container', {\n hidden: !isFilterVisible,\n })}\n key={columnIndex}\n style={style}\n >\n {isFilterVisible && (\n <button\n type=\"button\"\n className={classNames(\n 'btn btn-link btn-link-icon advanced-filter-button',\n {\n 'filter-set': isFilterSet,\n }\n )}\n onClick={() => {\n this.setState({ shownAdvancedFilter: columnIndex });\n }}\n onContextMenu={event => {\n this.grid.handleContextMenu(event);\n }}\n onMouseEnter={() => {\n this.setState({ hoverAdvancedFilter: columnIndex });\n }}\n onMouseLeave={() => {\n this.setState({ hoverAdvancedFilter: null });\n }}\n >\n <div className=\"fa-layers\">\n <FontAwesomeIcon\n icon={dhFilterFilled}\n className=\"filter-solid\"\n />\n <FontAwesomeIcon icon={vsFilter} className=\"filter-light\" />\n </div>\n </button>\n )}\n </div>\n );\n filterBar.push(element);\n }\n }\n }\n const advancedFilterMenus = [];\n if (metrics) {\n const {\n gridX,\n visibleColumns,\n visibleColumnXs,\n visibleColumnWidths,\n columnHeaderHeight,\n } = metrics;\n for (let i = 0; i < visibleColumns.length; i += 1) {\n const columnIndex = visibleColumns[i];\n const columnX = visibleColumnXs.get(columnIndex);\n const columnWidth = visibleColumnWidths.get(columnIndex);\n if (columnX != null && columnWidth != null && columnWidth > 0) {\n const xColumnHeader = gridX + columnX;\n const xFilterBar = gridX + columnX + columnWidth - 20;\n const style = isFilterBarShown\n ? {\n position: 'absolute',\n top: columnHeaderHeight,\n left: xFilterBar,\n width: 20,\n height: theme.filterBarHeight,\n }\n : {\n position: 'absolute',\n top: 0,\n left: xColumnHeader,\n width: columnWidth,\n height: columnHeaderHeight,\n };\n const modelColumn = this.getModelColumn(columnIndex);\n const column = model.columns[modelColumn];\n const advancedFilter = advancedFilters.get(modelColumn);\n const { options: advancedFilterOptions } = advancedFilter || {};\n const sort = TableUtils.getSortForColumn(model.sort, modelColumn);\n const sortDirection = sort ? sort.direction : null;\n const element = (\n <div\n key={columnIndex}\n className=\"advanced-filter-menu-container\"\n style={style}\n >\n <Popper\n className=\"advanced-filter-menu-popper\"\n onEntered={this.getAdvancedMenuOpenedHandler(columnIndex)}\n onExited={() => {\n this.handleAdvancedMenuClosed(columnIndex);\n }}\n isShown={shownAdvancedFilter === columnIndex}\n interactive\n closeOnBlur\n >\n {this.getCachedAdvancedFilterMenuActions(\n model,\n column,\n advancedFilterOptions,\n sortDirection,\n formatter\n )}\n </Popper>\n </div>\n );\n advancedFilterMenus.push(element);\n }\n }\n }\n\n const optionItems = this.getCachedOptionItems(\n model.isChartBuilderAvailable,\n model.isCustomColumnsAvailable,\n model.isRollupAvailable,\n model.isTotalsAvailable,\n model.isSelectDistinctAvailable,\n model.isExportAvailable,\n this.toggleFilterBarAction,\n this.toggleSearchBarAction,\n isFilterBarShown,\n showSearchBar,\n canDownloadCsv,\n this.isTableSearchAvailable()\n );\n\n const openOptionsStack = openOptions.map(option => {\n switch (option.type) {\n case OptionType.CHART_BUILDER:\n return (\n <ChartBuilder\n model={model}\n onChange={this.handleChartChange}\n onSubmit={this.handleChartCreate}\n key={OptionType.CHART_BUILDER}\n />\n );\n case OptionType.VISIBILITY_ORDERING_BUILDER:\n return (\n <VisibilityOrderingBuilder\n model={model}\n movedColumns={movedColumns}\n userColumnWidths={userColumnWidths}\n onColumnVisibilityChanged={this.handleColumnVisibilityChanged}\n onMovedColumnsChanged={this.handleMovedColumnsChanged}\n key={OptionType.VISIBILITY_ORDERING_BUILDER}\n />\n );\n case OptionType.CUSTOM_COLUMN_BUILDER:\n return (\n <CustomColumnBuilder\n model={model}\n customColumns={customColumns}\n onSave={this.handleUpdateCustomColumns}\n onCancel={this.handleMenuBack}\n key={OptionType.CUSTOM_COLUMN_BUILDER}\n />\n );\n case OptionType.ROLLUP_ROWS:\n return (\n <RollupRows\n metrics={metrics}\n model={model}\n onChange={this.handleRollupChange}\n config={rollupConfig}\n key={OptionType.ROLLUP_ROWS}\n />\n );\n case OptionType.AGGREGATIONS:\n return (\n <Aggregations\n settings={aggregationSettings}\n isRollup={isRollup}\n onChange={this.handleAggregationsChange}\n onEdit={this.handleAggregationEdit}\n />\n );\n case OptionType.AGGREGATION_EDIT:\n return (\n <AggregationEdit\n aggregation={selectedAggregation}\n columns={model.originalColumns}\n onChange={this.handleAggregationChange}\n />\n );\n case OptionType.TABLE_EXPORTER:\n return (\n <TableCsvExporter\n model={model}\n name={name}\n isDownloading={isTableDownloading}\n tableDownloadStatus={tableDownloadStatus}\n tableDownloadProgress={tableDownloadProgress}\n tableDownloadEstimatedTime={tableDownloadEstimatedTime}\n onDownload={this.handleDownloadTable}\n onDownloadStart={this.handleDownloadTableStart}\n onCancel={this.handleCancelDownloadTable}\n selectedRanges={selectedRanges}\n key={OptionType.TABLE_EXPORTER}\n />\n );\n case OptionType.SELECT_DISTINCT:\n return (\n <SelectDistinctBuilder\n model={model}\n selectDistinctColumns={selectDistinctColumns}\n onChange={this.handleSelectDistinctChanged}\n />\n );\n case OptionType.ADVANCED_SETTINGS:\n return (\n <AdvancedSettingsMenu\n items={advancedSettings}\n onChange={onAdvancedSettingsChange}\n />\n );\n\n default:\n throw Error('Unexpected option type', option.type);\n }\n });\n\n const hiddenColumns = this.getCachedHiddenColumns(\n IrisGridUtils.getHiddenColumns(userColumnWidths)\n );\n\n return (\n <div className=\"iris-grid\" role=\"presentation\">\n <div className=\"iris-grid-column\">\n {children && <div className=\"iris-grid-bar\">{children}</div>}\n <CSSTransition\n in={isSelectingPartition}\n timeout={ThemeExport.transitionSlowMs}\n classNames=\"iris-grid-bar-horizontal\"\n onEnter={this.handleAnimationStart}\n onEntered={this.handleAnimationEnd}\n onExit={this.handleAnimationStart}\n onExited={this.handleAnimationEnd}\n mountOnEnter\n unmountOnExit\n >\n <div className=\"iris-grid-partition-selector-wrapper iris-grid-bar iris-grid-bar-primary\">\n {partitionTable && partitionColumn && (\n <IrisGridPartitionSelector\n table={partitionTable}\n getFormattedString={(...args) => model.displayString(...args)}\n columnName={partitionColumn.name}\n partition={partition}\n onChange={this.handlePartitionChange}\n onFetchAll={this.handlePartitionFetchAll}\n onAppend={this.handlePartitionAppend}\n onDone={this.handlePartitionDone}\n />\n )}\n </div>\n </CSSTransition>\n <CSSTransition\n in={showSearchBar}\n timeout={ThemeExport.transitionSlowMs}\n classNames=\"iris-grid-bar-horizontal\"\n onEnter={this.handleAnimationStart}\n onEntered={this.handleAnimationEnd}\n onExit={this.handleAnimationStart}\n onExited={this.handleAnimationEnd}\n mountOnEnter\n unmountOnExit\n >\n <div className=\"iris-grid-bar\">\n <CrossColumnSearch\n value={searchValue}\n selectedColumns={selectedSearchColumns}\n invertSelection={invertSearchColumns}\n onChange={this.handleCrossColumnSearch}\n columns={model.columns}\n ref={this.crossColumnRef}\n />\n </div>\n </CSSTransition>\n <div\n className=\"grid-wrapper\"\n ref={gridWrapper => {\n this.gridWrapper = gridWrapper;\n }}\n >\n <Grid\n ref={grid => {\n this.grid = grid;\n }}\n isStickyBottom={!model.isEditable}\n isStuckToBottom={isStuckToBottom}\n isStuckToRight={isStuckToRight}\n metricCalculator={metricCalculator}\n model={model}\n keyHandlers={keyHandlers}\n mouseHandlers={mouseHandlers}\n movedColumns={movedColumns}\n movedRows={movedRows}\n onError={this.handleGridError}\n onViewChanged={this.handleViewChanged}\n onSelectionChanged={this.handleSelectionChanged}\n onMovedColumnsChanged={this.handleMovedColumnsChanged}\n renderer={this.renderer}\n stateOverride={stateOverride}\n theme={theme}\n />\n {isVisible && (\n <IrisGridModelUpdater\n model={model}\n modelColumns={model.columns}\n top={top}\n bottom={bottom}\n left={left}\n right={right}\n filter={filter}\n formatter={formatter}\n sorts={sorts}\n reverseType={reverseType}\n movedColumns={movedColumns}\n customColumns={customColumns}\n hiddenColumns={hiddenColumns}\n alwaysFetchColumns={this.getAlwaysFetchColumns(\n alwaysFetchColumns,\n model.columns,\n model.floatingLeftColumnCount,\n model.floatingRightColumnCount\n )}\n rollupConfig={this.getModelRollupConfig(\n model.originalColumns,\n rollupConfig,\n aggregationSettings\n )}\n totalsConfig={this.getModelTotalsConfig(\n model.columns,\n rollupConfig,\n aggregationSettings\n )}\n selectDistinctColumns={selectDistinctColumns}\n pendingRowCount={pendingRowCount}\n pendingDataMap={pendingDataMap}\n frozenColumns={frozenColumns}\n />\n )}\n <div\n className={classNames('grid-settings-button', {\n 'is-menu-shown': isMenuShown,\n })}\n >\n <button\n type=\"button\"\n className=\"btn btn-link btn-link-icon\"\n onClick={this.handleMenu}\n >\n <FontAwesomeIcon icon={vsMenu} transform=\"up-1\" />\n </button>\n </div>\n {focusField}\n {loadingElement}\n {filterBar}\n {columnTooltip}\n {advancedFilterMenus}\n </div>\n <PendingDataBottomBar\n error={pendingSaveError}\n isSaving={pendingSavePromise != null}\n saveTooltip={`Commit (${this.commitAction.shortcut.getDisplayText()})`}\n discardTooltip={`Discard (${this.discardAction.shortcut.getDisplayText()})`}\n pendingDataErrors={pendingDataErrors}\n pendingDataMap={pendingDataMap}\n onEntering={this.handleAnimationStart}\n onEntered={this.handleAnimationEnd}\n onExiting={this.handleAnimationStart}\n onExited={this.handleAnimationEnd}\n onSave={this.handlePendingCommitClicked}\n onDiscard={this.handlePendingDiscardClicked}\n />\n <ToastBottomBar>{toastMessage}</ToastBottomBar>\n <IrisGridCopyHandler\n model={model}\n copyOperation={copyOperation}\n onEntering={this.handleAnimationStart}\n onEntered={this.handleAnimationEnd}\n onExiting={this.handleAnimationStart}\n onExited={this.handleAnimationEnd}\n />\n <TableSaver\n ref={tableSaver => {\n this.tableSaver = tableSaver;\n }}\n getDownloadWorker={getDownloadWorker}\n onDownloadCompleted={this.handleDownloadCompleted}\n onDownloadCanceled={this.handleDownloadCanceled}\n onDownloadProgressUpdate={this.handleDownloadProgressUpdate}\n isDownloading={\n tableDownloadStatus ===\n TableCsvExporter.DOWNLOAD_STATUS.DOWNLOADING\n }\n formatter={formatter}\n />\n </div>\n <CSSTransition\n in={isMenuShown}\n timeout={ThemeExport.transitionMidMs}\n classNames=\"slide-left\"\n onEntering={this.handleAnimationStart}\n onEntered={this.handleAnimationEnd}\n onExiting={this.handleAnimationStart}\n onExited={this.handleAnimationEnd}\n mountOnEnter\n unmountOnExit\n >\n <div className=\"table-sidebar\">\n <Stack>\n <Page title=\"Table Options\" onClose={this.handleMenuClose}>\n <Menu\n onSelect={i => this.handleMenuSelect(optionItems[i])}\n items={optionItems}\n />\n </Page>\n {openOptionsStack.map((option, i) => (\n <Page\n title={openOptions[i].title}\n onBack={this.handleMenuBack}\n onClose={this.handleMenuClose}\n key={openOptions[i].type}\n >\n {option}\n </Page>\n ))}\n </Stack>\n </div>\n </CSSTransition>\n <ContextActions actions={this.contextActions} />\n </div>\n );\n }\n}\n\nIrisGrid.propTypes = {\n children: PropTypes.node,\n advancedFilters: PropTypes.instanceOf(Map),\n advancedSettings: PropTypes.instanceOf(Map),\n alwaysFetchColumns: PropTypes.arrayOf(PropTypes.string),\n isFilterBarShown: PropTypes.bool,\n applyInputFiltersOnInit: PropTypes.bool,\n customColumnFormatMap: PropTypes.instanceOf(Map),\n movedColumns: PropTypes.arrayOf(\n PropTypes.shape({\n from: PropTypes.number.isRequired,\n to: PropTypes.number.isRequired,\n })\n ),\n movedRows: PropTypes.arrayOf(\n PropTypes.shape({\n from: PropTypes.number.isRequired,\n to: PropTypes.number.isRequired,\n })\n ),\n inputFilters: PropTypes.arrayOf(\n PropTypes.shape({\n name: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n value: PropTypes.string.isRequired,\n })\n ),\n customFilters: PropTypes.arrayOf(PropTypes.shape({})),\n model: PropTypes.instanceOf(IrisGridModel).isRequired,\n onCreateChart: PropTypes.func,\n onColumnSelected: PropTypes.func,\n onError: PropTypes.func,\n onDataSelected: PropTypes.func,\n onStateChange: PropTypes.func,\n onPartitionAppend: PropTypes.func,\n onAdvancedSettingsChange: PropTypes.func,\n partition: PropTypes.string,\n partitionColumn: APIPropTypes.Column,\n sorts: PropTypes.arrayOf(PropTypes.shape({})),\n reverseType: PropTypes.string,\n quickFilters: PropTypes.instanceOf(Map),\n customColumns: PropTypes.arrayOf(PropTypes.string),\n selectDistinctColumns: PropTypes.arrayOf(PropTypes.string),\n // These settings come from the redux store\n settings: PropTypes.shape({\n timeZone: PropTypes.string.isRequired,\n defaultDateTimeFormat: PropTypes.string.isRequired,\n showTimeZone: PropTypes.bool.isRequired,\n showTSeparator: PropTypes.bool.isRequired,\n formatter: PropTypes.arrayOf(PropTypes.shape({})).isRequired,\n }),\n userColumnWidths: PropTypes.instanceOf(Map),\n userRowHeights: PropTypes.instanceOf(Map),\n onSelectionChanged: PropTypes.func,\n rollupConfig: PropTypes.shape({\n columns: PropTypes.arrayOf(PropTypes.string),\n showConstituents: PropTypes.bool,\n showNonAggregatedColumns: PropTypes.bool,\n includeDescriptions: PropTypes.bool,\n }),\n aggregationSettings: PropTypes.shape({\n aggregations: PropTypes.arrayOf(\n PropTypes.shape({\n operation: PropTypes.string.isRequired,\n selected: PropTypes.arrayOf(PropTypes.string).isRequired,\n invert: PropTypes.bool.isRequired,\n })\n ),\n showOnTop: PropTypes.bool,\n }),\n\n isSelectingColumn: PropTypes.bool,\n isSelectingPartition: PropTypes.bool,\n isStuckToBottom: PropTypes.bool,\n isStuckToRight: PropTypes.bool,\n\n // eslint-disable-next-line react/no-unused-prop-types\n columnSelectionValidator: PropTypes.func,\n columnAllowedCursor: PropTypes.string,\n\n // eslint-disable-next-line react/no-unused-prop-types\n columnNotAllowedCursor: PropTypes.string,\n name: PropTypes.string,\n onlyFetchVisibleColumns: PropTypes.bool,\n\n showSearchBar: PropTypes.bool,\n searchValue: PropTypes.string,\n selectedSearchColumns: PropTypes.arrayOf(PropTypes.string),\n invertSearchColumns: PropTypes.bool,\n\n // eslint-disable-next-line react/no-unused-prop-types\n onContextMenu: PropTypes.func,\n\n pendingDataMap: PropTypes.instanceOf(Map),\n getDownloadWorker: PropTypes.func,\n\n canCopy: PropTypes.bool,\n canDownloadCsv: PropTypes.bool,\n frozenColumns: PropTypes.arrayOf(PropTypes.string),\n\n // Theme override for IrisGridTheme\n theme: PropTypes.shape({}),\n\n canToggleSearch: PropTypes.bool,\n};\n\nIrisGrid.defaultProps = {\n children: null,\n advancedFilters: new Map(),\n advancedSettings: new Map(),\n alwaysFetchColumns: [],\n customColumnFormatMap: new Map(),\n isFilterBarShown: false,\n applyInputFiltersOnInit: false,\n movedColumns: [],\n movedRows: [],\n inputFilters: [],\n customFilters: [],\n onCreateChart: () => {},\n onColumnSelected: () => {},\n onDataSelected: () => {},\n onError: () => {},\n onStateChange: () => {},\n onPartitionAppend: () => {},\n onAdvancedSettingsChange: () => {},\n partition: null,\n partitionColumn: null,\n quickFilters: new Map(),\n selectDistinctColumns: [],\n sorts: [],\n reverseType: TableUtils.REVERSE_TYPE.NONE,\n customColumns: [],\n aggregationSettings: { aggregations: [], showOnTop: false },\n rollupConfig: null,\n userColumnWidths: new Map(),\n userRowHeights: new Map(),\n onSelectionChanged: () => {},\n isSelectingColumn: false,\n isSelectingPartition: false,\n isStuckToBottom: false,\n isStuckToRight: false,\n columnSelectionValidator: null,\n columnAllowedCursor: null,\n columnNotAllowedCursor: null,\n name: 'table',\n onlyFetchVisibleColumns: true,\n showSearchBar: false,\n searchValue: '',\n selectedSearchColumns: null,\n invertSearchColumns: true,\n onContextMenu: () => [],\n pendingDataMap: new Map(),\n getDownloadWorker: undefined,\n settings: {\n timeZone: 'America/New_York',\n defaultDateTimeFormat: DateUtils.FULL_DATE_FORMAT,\n showTimeZone: false,\n showTSeparator: true,\n formatter: [],\n decimalFormatOptions: PropTypes.shape({\n defaultFormatString: PropTypes.string,\n }),\n integerFormatOptions: PropTypes.shape({\n defaultFormatString: PropTypes.string,\n }),\n },\n canCopy: true,\n canDownloadCsv: true,\n frozenColumns: null,\n theme: {},\n canToggleSearch: true,\n};\n\nexport default IrisGrid;\n","import React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { ContextMenuRoot, LoadingOverlay } from '@deephaven/components'; // Use the loading spinner from the Deephaven components package\nimport {\n IrisGrid,\n IrisGridModel,\n IrisGridModelFactory,\n TableUtils,\n} from '@deephaven/iris-grid'; // iris-grid is used to display Deephaven tables\nimport dh from '@deephaven/jsapi-shim'; // Import the shim to use the JS API\nimport Log from '@deephaven/log';\nimport './App.scss'; // Styles for in this app\n\nconst log = Log.module('EmbedGrid.App');\n\nexport type Command = 'filter' | 'sort';\n\n/** Input value for filter commands */\nexport type FilterCommandType = {\n name: string;\n value: string;\n};\n\nexport type SortCommandType = {\n name: string;\n direction?: 'ASC' | 'DESC';\n};\n\n/**\n * Load an existing Deephaven table with the session provided\n * @param session The Deephaven session object\n * @param name Name of the table to load\n * @returns Deephaven table\n */\nasync function loadTable(session: typeof dh.Session, name: string) {\n log.info(`Fetching table ${name}...`);\n\n const definition = { name, type: dh.VariableType.TABLE };\n return session.getObject(definition);\n}\n\n/**\n * A functional React component that displays a Deephaven table in an IrisGrid using the @deephaven/iris-grid package.\n * It will attempt to open and display the table specified with the `name` parameter, expecting it to be present on the server.\n * E.g. http://localhost:3000/?name=myTable will attempt to open a table `myTable`\n * If no query param is provided, it will attempt to open a new session and create a basic time table and display that.\n * By default, tries to connect to the server defined in the REACT_APP_CORE_API_URL variable, which is set to http://localhost:1000/jsapi\n * See create-react-app docs for how to update these env vars: https://create-react-app.dev/docs/adding-custom-environment-variables/\n */\nfunction App(): JSX.Element {\n const [model, setModel] = useState<IrisGridModel>();\n const [error, setError] = useState<string>();\n const [inputFilters, setInputFilters] = useState<unknown[]>();\n const [sorts, setSorts] = useState<unknown[]>();\n const [isLoading, setIsLoading] = useState(true);\n const searchParams = useMemo(\n () => new URLSearchParams(window.location.search),\n []\n );\n const canCopy = searchParams.get('canCopy') != null;\n const canDownloadCsv = searchParams.get('canDownloadCsv') != null;\n\n const initApp = useCallback(async () => {\n try {\n // Connect to the Web API server\n const baseUrl = new URL(\n process.env.REACT_APP_CORE_API_URL ?? '',\n `${window.location}`\n );\n\n const websocketUrl = `${baseUrl.protocol}//${baseUrl.host}`;\n\n log.debug(`Starting connection...`);\n const connection = new dh.IdeConnection(websocketUrl);\n\n // Start a code session. For this example, we use python.\n log.debug(`Starting session...`);\n const session = await connection.startSession('python');\n\n // Get the table name from the query param `name`.\n const name = searchParams.get('name');\n\n if (!name) {\n throw new Error('No name param provided');\n }\n\n log.debug('Loading table', name, '...');\n\n // Load the table up.\n const table = await loadTable(session, name);\n\n // Create the `IrisGridModel` for use with the `IrisGrid` component\n log.debug(`Creating model...`);\n\n const newModel = await IrisGridModelFactory.makeModel(table);\n\n setModel(newModel);\n\n log.debug('Table successfully loaded!');\n } catch (e: unknown) {\n log.error('Unable to load table', e);\n setError(`${e}`);\n }\n setIsLoading(false);\n }, [searchParams]);\n\n useEffect(() => {\n initApp();\n }, [initApp]);\n\n useEffect(() => {\n function receiveMessage(e: MessageEvent) {\n const { command, value } = e.data as { command: Command; value: unknown };\n switch (command) {\n case 'filter': {\n const filterCommandValues = value as FilterCommandType[];\n const newInputFilters = filterCommandValues.map(\n ({ name, value: filterValue }) => {\n const column = model?.columns.find(c => c.name === name);\n if (column == null) {\n throw new Error(`Could not find column named ${name}`);\n }\n return {\n name,\n value: filterValue,\n type: TableUtils.getNormalizedType(column.type),\n };\n }\n );\n setInputFilters(newInputFilters);\n break;\n }\n case 'sort': {\n const sortCommandValues = value as SortCommandType[];\n const newSorts = sortCommandValues.map(({ name, direction }) => {\n const column = model?.columns.find(c => c.name === name);\n if (column == null) {\n throw new Error(`Could not find column named ${name}`);\n }\n return direction === 'DESC'\n ? column.sort().desc()\n : column.sort().asc();\n });\n setSorts(newSorts);\n break;\n }\n }\n }\n window.addEventListener('message', receiveMessage);\n\n return () => {\n window.removeEventListener('message', receiveMessage);\n };\n }, [model]);\n\n const isLoaded = model != null;\n\n return (\n <div className=\"App\">\n {isLoaded && (\n <IrisGrid\n canCopy={canCopy}\n canDownloadCsv={canDownloadCsv}\n model={model}\n inputFilters={inputFilters}\n sorts={sorts}\n />\n )}\n {!isLoaded && (\n <LoadingOverlay\n isLoaded={isLoaded}\n isLoading={isLoading}\n errorMessage={error ?? null}\n />\n )}\n <ContextMenuRoot />\n </div>\n );\n}\n\nexport default App;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\n\n// Fira fonts are not necessary, but look the best\nimport 'fira';\n\n// Need to import the base style sheet for proper styling\n// eslint-disable-next-line import/no-unresolved\nimport '@deephaven/components/dist/BaseStyleSheet.css';\nimport './index.scss';\nimport App from './App';\n\nReactDOM.render(<App />, document.getElementById('root'));\n","interface MockContext {\n arc: jest.Mock<void>;\n beginPath: jest.Mock<void>;\n clip: jest.Mock<void>;\n closePath: jest.Mock<void>;\n createLinearGradient: jest.Mock<{ addColorStop: jest.Mock<void> }>;\n fill: jest.Mock<void>;\n fillRect: jest.Mock<void>;\n fillText: jest.Mock<void>;\n lineTo: jest.Mock<void>;\n measureText: jest.Mock<{ width: number }, [string]>;\n moveTo: jest.Mock<void>;\n rect: jest.Mock<void>;\n restore: jest.Mock<void>;\n setTransform: jest.Mock<void>;\n save: jest.Mock<void>;\n stroke: jest.Mock<void>;\n strokeRect: jest.Mock<void>;\n translate: jest.Mock<void>;\n scale: jest.Mock<void>;\n createPattern: jest.Mock<void>;\n}\n\nclass TestUtils {\n static makeMockContext(): MockContext {\n return {\n arc: jest.fn(),\n beginPath: jest.fn(),\n clip: jest.fn(),\n closePath: jest.fn(),\n createLinearGradient: jest.fn(() => ({\n addColorStop: jest.fn(),\n })),\n fill: jest.fn(),\n fillRect: jest.fn(),\n fillText: jest.fn(),\n lineTo: jest.fn(),\n measureText: jest.fn((str: string) => ({ width: str.length * 10 })),\n moveTo: jest.fn(),\n rect: jest.fn(),\n restore: jest.fn(),\n setTransform: jest.fn(),\n save: jest.fn(),\n stroke: jest.fn(),\n strokeRect: jest.fn(),\n translate: jest.fn(),\n scale: jest.fn(),\n createPattern: jest.fn(),\n };\n }\n\n static async flushPromises(): Promise<void> {\n await new Promise(setImmediate);\n }\n\n static REGULAR_USER = {\n name: 'test',\n operateAs: 'test',\n groups: ['allusers', 'test'],\n permissions: {\n isSuperUser: false,\n isQueryViewOnly: false,\n isNonInteractive: false,\n canUsePanels: true,\n canCreateDashboard: true,\n canCreateCodeStudio: true,\n canCreateQueryMonitor: true,\n canCopy: true,\n canDownloadCsv: true,\n },\n };\n}\n\nexport default TestUtils;\n","// extracted by mini-css-extract-plugin\nmodule.exports = {\"grid-bg\":\"#211f22\",\"font\":\"12px Fira Sans, sans-serif\",\"header-bg\":\"#2d2a2e\",\"header-color\":\"#f0f0ee\",\"header-separator-color\":\"#211f22\",\"header-separator-hover-color\":\"#929192\",\"header-hidden-separator-hover-color\":\"#4878ea\",\"header-sort-bar-color\":\"#aa9af4\",\"header-reverse-bar-color\":\"#548d29\",\"header-bar-casing-color\":\"#211f22\",\"header-font\":\"600 12px Fira Sans, sans-serif\",\"row-background-colors\":\"#373438 #2d2a2e\",\"selection-color\":\"rgba(118, 217, 228, 0.09)\",\"selection-outline-color\":\"#76d9e4\",\"selection-outline-casing-color\":\"#211f22\",\"row-hover-bg\":\"#4b494c\",\"selected-row-hover-bg\":\"rgba(118, 217, 228, 0.25)\",\"scroll-bar-bg\":\"#322f33\",\"scroll-bar-hover-bg\":\"#373438\",\"scroll-bar-casing-color\":\"#555356\",\"scroll-bar-corner-color\":\"#322f33\",\"scroll-bar-color\":\"#5b5a5c\",\"scroll-bar-hover-color\":\"#929192\",\"scroll-bar-active-color\":\"#c0bfbf\",\"text-color\":\"#f0f0ee\",\"positive-number-color\":\"#9edc6f\",\"negative-number-color\":\"#f95d84\",\"zero-number-color\":\"#fcd65b\",\"date-color\":\"#fcd65b\",\"pending-text-color\":\"#fde38d\",\"error-text-color\":\"#f95d84\",\"null-string-color\":\"#929192\",\"filter-bar-active-bg\":\"#425175\",\"filter-bar-active-color\":\"#4878ea\",\"filter-bar-expanded-bg\":\"#373438\",\"filter-bar-expanded-active-bg\":\"#313849\",\"filter-bar-expanded-active-cell-bg\":\"#374d80\",\"filter-bar-separator-color\":\"#929192\",\"filter-bar-error-color\":\"#f95d84\",\"filter-icon-color\":\"#4878ea\",\"scrim-color\":\"#5b5a5c\",\"context-menu-sort-icon-color\":\"#aa9af4\",\"context-menu-reverse-icon-color\":\"#548d29\",\"linker-column-hover-bg\":\"rgba(118, 217, 228, 0.09)\",\"tree-line-color\":\"#5b5a5c\",\"tree-marker-color\":\"#c0bfbf\",\"tree-marker-hover-color\":\"#fcfcfa\",\"grouped-column-divider-color\":\"#1a171a\",\"floating-grid-row-color\":\"#555356\",\"floating-row-background-colors\":\"#403e41\",\"floating-divider-inner-color\":\"#403e41\",\"floating-divider-outer-color\":\"#211f22\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"gray-100\":\"#fcfcfa\",\"gray-200\":\"#f0f0ee\",\"gray-300\":\"#c0bfbf\",\"gray-400\":\"#929192\",\"gray-500\":\"#5b5a5c\",\"gray-600\":\"#555356\",\"gray-700\":\"#403e41\",\"gray-800\":\"#373438\",\"gray-850\":\"#322f33\",\"gray-900\":\"#211f22\",\"black\":\"#1a171a\",\"white\":\"#f0f0ee\",\"yellow\":\"#fcd65b\",\"green\":\"#9edc6f\",\"blue\":\"#76d9e4\",\"purple\":\"#aa9af4\",\"orange\":\"#f37e3f\",\"red\":\"#f95d84\",\"primary\":\"#4878ea\",\"primary-hover\":\"#235de6\",\"primary-dark\":\"#343e5d\",\"secondary\":\"#5b5a5c\",\"success\":\"#9edc6f\",\"info\":\"#fcd65b\",\"warning\":\"#f37e3f\",\"danger\":\"#f95d84\",\"light\":\"#fcfcfa\",\"mid\":\"#929192\",\"dark\":\"#373438\",\"text-muted\":\"#929192\",\"interfacewhite\":\"#f0f0ee\",\"interfaceblack\":\"#1a171a\",\"interfacegray\":\"#2d2a2e\",\"content-bg\":\"#2d2a2e\",\"background\":\"#1a171a\",\"foreground\":\"#f0f0ee\",\"transition\":\"0.15s\"};"],"sourceRoot":""}