{"version":3,"sources":["models/Cookie.js","utils/StringCommaCoder.js","components/Dialog/LegacyNonMarkdownRenderer.jsx","components/Dialog/Dialog.js","utils/LocalStorageHelper.js","models/layers/LayerInfo.js","utils/DeepMerge.js","utils/customComponentsForReactMarkdown.js","components/Search/utils/FeatureStyle.js","models/Click.js","components/FeatureInfo/FeaturePropsParsing.js","components/Search/searchResults/SearchResultsDatasetFeatureDetails.js","components/HajkThemeProvider.js","components/Window.js","components/FeatureInfo/FeaturePropsFilters.js","utils/Validator.js","utils/Delay.js","components/Alert.js","utils/KMLWriter.js","components/PanelHeader.js","components/Search/Search.js","components/App.js","components/SrShortcuts/SrShortcuts.js","models/AppModel.js","models/SearchModel.js","models/Plugin.js","utils/ConfigMapper.js","utils/CoordinateSystemLoader.js","models/layers/WMSLayer.js","models/layers/WMTSLayer.js","models/layers/VectorLayer.js","models/SnapHelper.js","components/FeatureInfo/FeatureInfoContainer.js","components/CookieNotice.js","components/Introduction.js","components/Announcement/Announcement.js","components/PluginWindows.js","components/Search/SearchBar.js","components/Search/searchResults/SearchResultsContainer.js","components/Search/searchResults/SearchResultsList.js","components/Search/searchResults/SearchResultsDataset.js","components/Search/searchResults/SearchResultsDatasetFeature.js","components/Search/searchResults/SearchResultsPreview.js","components/Search/searchResults/SearchResultsDatasetSummary.js","components/Search/searchResults/SearchResultsDownloadMenu.js","components/Search/SearchTools.js","components/Search/SearchSettings.js","components/Search/MapViewModel.js","components/Search/utils/KmlExport.js","components/Search/utils/XLSXExport.js","controls/Zoom.js","controls/User.js","controls/Rotate.js","controls/ScaleLine.js","controls/Attribution.js","controls/MapCleaner.js","controls/MapResetter.js","controls/MapSwitcher.js","controls/Information.js","controls/PresetLinks.js","components/Drawer/DrawerToggleButtons.js","controls/ThemeToggler.js","reportWebVitals.js","index.js","utils/FetchWrapper.js","utils/IsMobile.js","../src lazy /^/.*/.js$/ groupOptions: {} namespace object"],"names":["CM","setConfig","settings","showCookieNotice","globalObserver","setLevel","level","publish","window","localStorage","setItem","shouldShowNotice","levelInStorage","getItem","parseInt","functionalOk","thirdPartyOk","this","encodeCommas","string","replace","decodeCommas","LegacyNonMarkdownRenderer","props","text","DialogContentText","dangerouslySetInnerHTML","__html","ResponsiveDialog","theme","useTheme","fullScreen","useMediaQuery","breakpoints","down","onAbort","onClose","open","options","abortText","allowDangerousHtml","buttonText","headerText","prompt","useLegacyNonMarkdownRenderer","useState","promptText","setPromptText","rehypePlugins","rehypeRaw","handleClose","Dialog","aria-labelledby","DialogTitle","id","DialogContent","remarkPlugins","gfm","components","customComponentsForReactMarkdown","children","noValidate","autoComplete","onSubmit","e","preventDefault","TextField","label","value","onChange","target","margin","autoFocus","DialogActions","Button","onClick","LocalStorageHelper","mapName","key","defaults","JSON","parse","error","stringify","LayerInfo","properties","attribution","caption","infoOwner","infoText","infoTitle","infoUrl","infoUrlText","infoVisible","infoClickSortType","infoClickSortDesc","infoClickSortProperty","information","legend","legendIcon","searchDisplayName","searchShortDisplayName","searchGeometryField","searchOutputFormat","searchPropertyName","searchUrl","layerType","hideExpandArrow","deepMerge","isObject","obj","objects","reduce","prev","Object","keys","forEach","pVal","oVal","Array","isArray","concat","Paragraph","styled","Typography","marginBottom","StyledTableRow","TableRow","backgroundColor","palette","action","hover","StyledTableContainer","TableContainer","StyledPaper","Paper","padding","spacing","background","default","StyledTypography","variant","fontSize","fontWeight","fontStyle","MarkdownHeaderComponent","MarkdownTableCellComponent","style","isHeader","className","align","textAlign","p","hr","a","href","title","h1","h2","h3","h4","h5","h6","table","component","size","thead","tbody","tr","td","th","type","div","blockquote","FeatureStyle","fillColor","displayFillColor","strokeColor","displayStrokeColor","selectionStrokeColor","selectionFillColor","textFillColor","selectionTextFill","textStrokeColor","selectionTextStroke","highlightStrokeColor","highlightFillColor","highlightTextFill","highlightTextStroke","getFeatureStyle","feature","isValidNumber","n","Number","isFinite","scale","markerImg","anchor","isPoint","getGeometry","Point","offsetY","iconColor","svgString","defaultMarker","btoa","multiplier","Style","fill","Fill","color","stroke","Stroke","width","image","Icon","src","length","Text","textBaseline","font","featureTitle","overflow","offsetX","rotation","getDefaultSearchResultStyle","Circle","radius","shortFeatureTitle","enableLabelOnHighlight","getSortParser","sortType","trim","sortFeatures","layer","features","layerInfo","getProperties","sortOptions","desc","prop","parser","sort","b","localeCompare","getFeaturesFromJson","response","jsonData","parsed","layerProjection","viewProjection","GeoJSON","parserOptions","crs","dataProjection","featureProjection","parsedFeatures","map","jsonFeature","parsedJsonFeature","readFeature","getId","setId","layerName","ol_uid","push","readJsonFeatures","getSource","getProjection","f","handleClick","evt","callback","document","querySelector","cursor","promises","getView","getCode","getLayers","getArray","filter","TileLayer","ImageLayer","get","promise","coordinate","resolution","getResolution","currentZoom","getZoom","referenceSystem","subLayersToQuery","layersInfo","getMinZoom","getMaxZoom","subLayers","values","visibleSubLayersArray","getParams","split","visibleSubLayersSet","Set","subLayer","queryable","has","queryableSubLayer","params","FEATURE_COUNT","INFO_FORMAT","QUERY_LAYERS","join","serverType_","FI_POINT_TOLERANCE","FI_LINE_TOLERANCE","FI_POLYGON_TOLERANCE","WITH_GEOMETRY","url","getFeatureInfoUrl","hfetch","query","then","requestResponse","Promise","all","responses","featurePromises","headers","json","undefined","catch","err","console","WMSGetFeatureInfo","readFeatures","getFeaturesFromGml","forEachFeatureAtPixel","pixel","hitTolerance","bindMapClickEvent","on","clickLock","FeaturePropsParsing","str","start","match","result","test","ex","placeholder","substring","includes","propertyName","pluginName","propertyValue","pendingPromises","FeaturePropFilters","applyFilters","getListeners","resolve","reject","payload","matched","condition","content","attributes","replaceAll","k","v","URL","encodeURI","r","extractPropertiesFromJson","property","mergeFeaturePropsWithMarkdown","markdown","resolvedPromisesWithComponents","child","index","externalComponent","hasOwnProperty","Fragment","SearchResultsDatasetFeatureDetails","state","infoBox","componentDidMount","getInfoBox","componentDidUpdate","prevProps","shouldRenderCustomInfoBox","getHtmlItemInfoBox","getDefaultInfoBox","source","infobox","setProperties","featurePropsParsing","setMarkdownAndProperties","MarkdownComponent","setState","renderDefaultInfoBox","renderTableCell","position","classes","textToRender","paddingRight","tableCell","entries","row","handleTogglerPressed","nextFeatureIndex","setActiveFeature","getFeatureIndex","findIndex","renderFeatureToggler","numFeaturesInCollection","currentFeatureIndex","buttonLeftDisabled","buttonRightDisabled","container","item","alignItems","justify","togglerButton","disabled","aria-label","renderFeatureTitle","noWrap","headerTypography","app","appModel","config","mapConfig","tools","find","t","enableFeatureToggler","shouldRenderToggler","allFeatureDetailsContainer","headerContainer","xs","md","React","PureComponent","withStyles","paddingLeft","wordBreak","maxWidth","paddingTop","minWidth","getTheme","customTheme","colorScheme","preferredColorSchemeFromMapConfig","userPreferredColorScheme","matchMedia","matches","getColorScheme","colors","preferredColorScheme","hardCodedDefaults","active","shape","borderRadius","themeFromMapConfig","primary","main","primaryColor","secondary","secondaryColor","HajkThemeProvider","activeTools","setTheme","Math","random","themeUID","setThemeUID","muiTheme","createMuiTheme","toggleMUITheme","newTheme","refreshMUITheme","Rnd","prototype","onDragStart","data","disableDrag","bounds","boundary","parent","getParent","parentRect","getBoundingClientRect","parentLeft","left","parentTop","top","bodyRect","body","offsetLeft","offsetTop","right","offsetWidth","resizable","bottom","offsetHeight","height","innerWidth","innerHeight","HTMLElement","boundaryRect","boundaryLeft","boundaryTop","updateOffsetFromParent","offset","offsetFromParent","Window","prevState","setTimeout","windowRef","current","focus","close","latestWidth","rnd","getSelfElement","clientWidth","fit","updatePosition","x","round","y","clientHeight","mode","reset","enlarge","parseFloat","h","c","parentElement","o","maximize","onMaximize","onResize","allowMaximizedWindow","getIsMobile","getElementById","minimize","onMinimize","windows","createRef","addEventListener","subscribe","layerswitcherConfig","showBreadcrumbs","spaceForBreadcrumbs","areBreadcrumbsActivated","getMaxWindowHeight","w","i","zIndex","resizingEnabled","draggingEnabled","customPanelHeaderButtons","resizeBottom","resizeBottomLeft","resizeBottomRight","resizeLeft","resizeRight","resizeTop","resizeTopLeft","resizeTopRight","isMobile","bringToFront","onMouseDown","onMouseOver","stopPropagation","ref","display","onDragStop","d","rect","getClientRects","onResizeStop","direction","delta","cancel","disableDragging","enableResizing","bottomLeft","bottomRight","topLeft","topRight","minHeight","tabIndex","clsx","panelContent","panelContentDisplayContents","customHeaderButtons","localObserver","scrollable","nonScrollable","maxHeight","onDisplay","defaultProps","paper","boxShadow","shadows","pointerEvents","flexDirection","userSelect","outline","light","flex","overflowY","fixDate","indexOf","substr","filters","input","args","shift","inFilter","argsStart","filterName","cleanString","execFilter","func","apply","warn","s","targetKey","add","numDecimals","isNaN","Error","toFixed","toLocaleString","withString","RegExp","defaultValue","addAlias","lessValue","greaterValue","trueValue","falseValue","Date","toLocaleDateString","toLocaleTimeString","days","date","setDate","getDate","hours","setTime","getTime","toUpperCase","toLowerCase","charAt","slice","i1","i2","searchFor","isValidLayerId","delay","ms","AlertView","alert","dialogTitle","message","aria-describedby","componentToHex","hex","toString","colorToArray","res","reg","exec","toKmlColor","g","rgbToHex","floor","toKmlString","strs","coords","coordinates","coordString","lines","line","point","transform","from","to","clone","getStyle","setStyle","createXML","name","header","WKT","doc","getImage","getScale","getSize","getSrc","getStroke","getColor","getWidth","getFill","getText","description","namn","template","filterProperties","writeFeature","MultiPoint","LineString","MultiLineString","multiLine","Polygon","polygon","MultiPolygon","multiPolygon","geometryType","PanelHeader","renderCustomHeaderButtons","buttonInfo","HeaderActionIcon","icon","onClickCallback","shouldRenderCustomHeaderButtons","borderColor","xsDown","Component","borderBottom","justifyContent","Search","defaultSearchOptions","searchInVisibleLayers","wildcardAtStart","wildcardAtEnd","matchCase","activeSpatialFilter","maxResultsPerDataset","searchImplementedPluginsLoaded","searchSources","searchResults","featureCollections","errors","autocompleteList","searchString","searchFromAutoComplete","searchActive","autoCompleteOpen","loading","searchOptions","failedWFSFetchMessage","resultPanelCollapsed","timer","delayBeforeAutoSearch","searchImplementedPlugins","featuresToFilter","Observer","snackbarKey","defaultSearchTools","enabled","enablePolygonSearch","toolTipTitle","onClickEventName","enableRadiusSearch","enableSelectSearch","enableExtentSearch","initMapViewModel","mapViewModel","MapViewModel","initExportHandlers","kmlExport","KmlExport","XLSXExport","resetFeaturesToFilter","setFeaturesToFilter","arrayOfFeatures","bindSubscriptions","enqueueSnackbar","anchorOrigin","vertical","horizontal","doFeaturesSearch","closeSnackbar","doSearch","getPluginsConfToUseSearchInterface","plugins","plugin","searchImplemented","searchInterface","getSearchMethods","tryBindSearchMethods","methods","getFunctionality","getResults","pluginsHavingCorrectSearchMethods","displayPluginMissingCrucialMethodsWarning","getSearchImplementedPlugins","pluginsConfToUseSearchInterface","searchBoundPlugins","getExternalSearchTools","searchImplementedSearchTools","searchImplementedPlugin","toolWithFunctionality","getSearchTools","searchTools","handlePotentialUrlQuerySearch","getSourcesByIds","sourceIds","searchModel","getSources","q","urlParams","sources","handleOnClear","showSearchResults","handleSearchInput","event","reason","autocompleteEntry","isUserInput","handleOnAutocompleteInputChange","clearTimeout","updateAutocompleteList","updateSearchOptions","refreshFeatureStyle","functionalCookieOk","set","handleOnClickOrKeyboardSearch","hasEnoughCharsForSearch","activeElement","blur","setSearchSources","handleSearchBarKeyPress","which","keyCode","getAutoCompleteFetchSettings","fetchSettings","getSearchOptions","autocompleteWildcardAtStart","getPossibleCombinations","initiator","getArrayWithSearchWords","splitAndTrimOnCommas","escapeRegExp","sortSearchFieldsOnFeature","searchFields","wordsInTextField","matchedSearchFields","word","sf","searchFieldMatch","unMatchedSearchFields","getSortedAutocompleteEntry","searchFieldOrder","featureProperty","propertyAsString","getAutocompleteDataset","featureCollection","dataset","origin","sortSearchFieldsOnFeatures","flattenAndSortAutoCompleteList","resultsPerDataset","sortAutocompleteList","flat","flatAutocompleteArray","numeric","getMergeResultsFromAllSources","results","fetchResultFromSearchModel","fetchOptions","searchStringEncapsuled","getCleanedSearchString","getVisibleSearchLayers","allSettled","fetchResultsFromPlugins","status","removeCollectionsWithoutFeatures","fc","getFeatureLabels","startsWith","endsWith","getPotentialWFSErrorMessage","reducerFn","featureTitleString","df","displayField","displayFields","shortDisplayFields","filterFeaturesWithGeometry","extractFeaturesFromFeatureCollections","getNumResults","numResults","autoCompleteResult","prepareAutocompleteList","anySearchImplementedPlugins","getSearchResultsFetchSettings","getUserCustomFetchSettings","numSourcesWithResults","spacesPerSource","max","min","autoCompleteList","shortenAutoCompleteList","shortenedAutoComplete","groupedAutoComplete","groupObjArrayByProp","group","array","grouped","searchOptionsFromModel","toggleCollapseSearchResults","clean","root","inputRoot","withSnackbar","App","canRenderCustomDrawer","activeDrawerContentFromLocalStorage","activeDrawerOnStart","some","tool","getDrawerPermanentFromLocalStorage","getActiveDrawerContentFromLocalStorage","hasAnyToolbarTools","activeTool","togglePermanent","drawerPermanent","getMap","updateSize","handleMouseEnter","drawerMouseOverLock","handleMouseLeave","renderDrawerHeader","drawerTitle","drawerButtons","db","activeDrawerContent","logoUrl","logoLight","logoDark","logo","logoBox","alt","drawerGrid","wrap","smDown","drawerLockButton","onMouseEnter","onMouseLeave","renderAllDrawerContent","drawerContentContainer","drawerContent","role","renderDrawerContent","drawerPermanentFromLocalStorage","canRenderDefaultDrawer","activeDrawerContentState","drawerVisible","drawerVisibleMobile","mapClickDataResult","setCookieConfig","AppModel","createMap","addSearchModel","addLayers","loadPlugins","getPlugins","getDrawerPlugins","ButtonIcon","MapIcon","order","bindHandlers","passive","alertMessage","button","newState","infoclickOptions","highlight","search","renderElsewhere","String","showMapResetter","mapresetter","showMapSwitcher","activeMap","maxSnack","anchorOriginBottomCenter","snackbarContainerBottom","anchorOriginTopCenter","snackbarContainerTop","containerRoot","snackBarContainerRoot","appConfig","announcements","currentMap","cslx","flexBox","shiftedLeft","pointerEventsOnChildren","initialActiveButton","renderSearchComponent","leftColumn","rightColumn","controlsColumn","showUserAvatar","userDetails","showThemeToggler","renderInformationPlugin","footer","windowsContainer","renderInfoclickWindow","getBothDrawerAndWidgetPlugins","ModalProps","hideBackdrop","disableEnforceFocus","onEscapeKeyDown","keepMounted","onBackdropClick","drawerBackground","experimentalIntroductionEnabled","experimentalIntroductionSteps","border","appBar","marginLeft","marginRight","marginTop","drawerHeader","mixins","toolbar","lineHeight","drawerLiveContent","widgetItem","SrShortcuts","shortcuts","setShortcuts","useEffect","addShortCuts","shortcutsArray","shortcut","link","decorateConfig","coordinateSystemLoader","CoordinateSystemLoader","projections","layersFromParams","cqlFiltersFromParams","register","getProj4","allResolutions","resolutions","extraPrintResolutions","windowComponent","closeWindow","currentWindow","sortOrder","dir","prom","module","toolConfig","plug","toolOptions","addPlugin","Plugin","translateConfig","interactionsOptions","altShiftDragRotate","onFocusOnly","doubleClickZoom","keyboard","mouseWheelZoom","shiftDragZoom","dragPan","pinchRotate","pinchZoom","zoomDelta","zoomDuration","Map","controls","interactions","defaultInteractions","layers","overlays","view","View","center","extent","constrainOnlyCenter","constrainResolution","constrainResolutionMobile","maxZoom","minZoom","projection","units","zoom","newZoom","snapHelper","SnapHelper","searchResultFeatures","infoclickFeatures","searchConfigIndex","SearchModel","clearing","setVisible","layerItem","layerConfig","configMapper","ConfigMapper","proxy","mapWMSConfig","WMSLayer","addLayer","mapWMTSConfig","WMTSLayer","mapVectorConfig","WFSVectorLayer","matchedLayers","layersConfig","lookupLayer","groups","expand","layerSwitcherConfig","lookup","baselayers","infoclickConfig","flattern","drawOrder","sortedKey","visibleAtStart","layerId","cqlFilter","addMapLayer","addHighlightLayer","strokeWidth","strokeColorAsArray","fillColorAsArray","highlightSource","VectorSource","highlightLayer","VectorLayer","abs","clear","addFeature","geom","setCenter","getCenter","getExtent","urlSearchParams","Boolean","z","l","decodeURIComponent","searchTool","wfslayers","configSpecificSearchLayers","editTool","wfstlayers","configSpecificEditLayers","activeServices","layerSwitcherTool","wmslayers","wmtslayers","vectorlayers","arcgislayers","allLayers","overrideGlobalSearchConfig","selectedSources","flatMap","wmslayerId","sl","pid","aliasDict","geometryField","outputFormat","serverType","visibleForGroups","as","service","overrideGlobalEditConfig","mergeConfig","fromEntries","URLSearchParams","location","searchPluginOptions","WFS","abort","controller","rawResults","searchSource","fetchResponses","fetchResponse","responsePromises","successfulResponses","olFeatures","GML2","GML3","GML32","Or","searchField","IsLike","wordsArray","OrFilters","And","isLikeFilters","getPossibleSearchCombinations","possibleSearchCombinations","numWords","joinedWord","stringArray","wordsBeforeCurrent","ii","currentWord","wordsAfterCurrent","searchCombinations","combination","srsName","geometryName","maxFeatures","comparisonFilters","spatialFilters","finalFilters","searchFilters","searchWordsForCombination","wordInCombination","Within","Intersects","geometry","getType","fromCircle","flatCoordinates","splice","featureTypes","node","writeGetFeature","xmlString","XMLSerializer","serializeToString","AbortController","request","credentials","signal","method","searchProxy","spec","getLegendUrl","legendUrl","getIndex","geoserverLegendOptions","qgisOptions","theGlue","version","projCode","Projection","code","axisOrientation","srsOrCrs","getPotentialCustomUrl","customGetMapUrl","visible","opacity","minMaxZoomAlertOnToggleOnly","singleTile","hidpi","customRatio","imageFormat","crossOrigin","LAYERS","CQL_FILTER","FORMAT","infoFormat","VERSION","tiled","layersInfoObject","mapLayersInfo","timeSliderStart","timeSliderEnd","featureType","displayName","format","wrapX","matrixSet","matrixIds","dataFormat","filterable","filterAttribute","filterComparer","filterValue","lineColor","lineStyle","lineWidth","typename","srsname","bbox","pointSize","sldStyle","sldText","sldUrl","symbolXOffset","symbolYOffset","proj4","defs","definition","proxyUrl","onTileLoadError","onTileLoadOk","onImageError","layerSource","previousErrorExtent","currentErrorExtent","equals","refresh","validInfo","attributions","cacheSize","transition","overrideLayerSourceParams","tileGrid","TileGrid","ratio","ImageWMS","TileWMS","getLayerType","featureInformationCallback","success","getLayer","feature_count","encodeURIComponent","assign","Url","wmtsLayerProperties","axisMode","WMTSTileGrid","WMTS","updateMapViewResolutions","setView","getConstrainResolution","vectorLayerProperties","showLabels","applySldTextOnLayer","sldObject","SLDReader","sldLayer","featureTypeStyle","featuretypestyles","olFunction","convertResolution","viewResolution","viewCenter","getPointResolution","imageLoadedCallback","changed","allFeatures","vectorSource","loader","loadData","createUrl","strategy","loadingStrategy","strategyAll","bboxStrategy","renderMode","createStyle","getCoordinates","setCoordinates","coord","gmlFormat","reprojectFeatures","filterMethod","usp","Infinity","getAllFeatures","addFeatures","getFilteredFeatures","forcedPointRadius","labelAlign","baseline","labelBaseline","labelSize","labelOffsetX","labelOffsetY","labelWeight","labelFont","labelFillColor","outlineColor","labelOutlineColor","outlineWidth","labelOutlineWidth","iconScale","getLineDash","dash","dot","anchorXUnits","anchorYUnits","lineDash","getStyleObj","activePlugins","updatePending","getVisible","snap","Snap","addInteraction","snapInteractions","removeInteraction","delete","FeatureInfoContainer","selectedIndex","showFeatureInMap","stepLeft","newIndex","updateFeatureInformation","stepRight","getToggler","toggler","togglerButtonRightContainer","fullWidth","typography","togglerButtonLeftContainer","getMarkdownFromLocalInfoBox","getAGSCompatibleLayer","getFeatureProperties","getValue","getFeaturesAsDefaultTable","isReadyToShowInfo","shortcodes","renderFeatureInformation","featureInfo","gutterBottom","j","tableBody","selected","columnKey","columnValue","featureInfoLoaded","alignContent","infoContainer","featureInfoContainer","verticalAlign","borderRight","divider","borderLeft","LabeledCheckbox","checked","control","useStyles","makeStyles","dialogContainer","dialogText","Transition","forwardRef","CookieNotice","setOpen","functionalChecked","setFunctionalChecked","thirdPartChecked","setThirdPartChecked","defaultCookieNoticeMessage","defaultCookieNoticeUrl","showThirdPartCheckbox","cookieUse3dPart","unsubscribe","handleAllowSelectedClick","useCallback","cookieLevel","handleAllowAllClick","TransitionComponent","underline","rel","Introduction","forceShow","initialStep","stepsEnabled","steps","predefinedSteps","intro","element","disableSteps","filteredSteps","onExit","exitOnOverlayClick","nextLabel","prevLabel","doneLabel","Announcement","useSnackbar","maps","mapFilter","browsers","detect","browserFilter","now","startTime","stopTime","validStartTime","validStopTime","timeFilter","showOnlyOnce","aShownIds","sShownIds","localStorageFilter","timeout","autoHideDuration","persist","renderSnackbar","arePropsEqual","nextProps","memo","PluginWindows","CustomPopper","smallScreen","popperOptions","modifiers","computeStyle","gpuAcceleration","preventOverflow","boundariesElement","hide","placement","CustomPaper","borderTop","SearchBar","drawActive","panelCollapsed","moreOptionsId","moreOptionsOpen","selectSourcesOpen","getOriginBasedIcon","originIconWrapper","removeCommasAndSpaces","getMatches","regex","getAllStartingIndexForOccurencesInString","toSearchFor","toSearchIn","regexp","getHighlightedAutoCompleteEntryElement","lastHighlightInformation","renderHighlightedAutocompleteEntry","highlightInformation","countOfHighlightInformation","getHighlightedACE","searchWord","autocompleteTypography","getPlaceholder","labelPostfix","searchBarPlaceholder","renderSearchResultList","renderAutoComplete","freeSolo","PopperComponent","PaperComponent","clearOnEscape","selectOnFocus","blurOnSelect","disableClearable","onInputChange","getOptionSelected","option","renderOption","getOptionLabel","renderInput","renderAutoCompleteInputField","renderFailedWFSFetchWarning","errorMessage","disableUnderline","showFailedWFSMessage","expandMessage","onKeyPress","InputLabelProps","shrink","InputProps","notched","endAdornment","searchContainer","searchCollapsed","elevation","flexWrap","withTheme","withWidth","SearchResultsContainer","activeFeature","activeFeatureCollection","filteredFeatureCollections","filteredFeatures","sumOfResults","filterInputFieldOpen","featureCollectionFilter","featureFilter","sortingMenuAnchorEl","featureCollectionSortingStrategy","featureSortingStrategy","showTools","selectedFeatures","filterInputTimer","lastFeatureFilter","lastFeatureCollectionFilter","delayBeforeFilterCommit","searchResultTools","render","renderFilterTool","enableResultsFiltering","renderSortTool","enableResultsSorting","renderClearTool","enableResultsSelectionClearing","renderDownloadTool","enableResultsDownloading","sortingStrategies","appliesTo","featureIds","showFeatureDetails","getPotentialSingleHit","componentWillUnmount","featureId","getFeatureCollectionFromFeatureId","onClickName","handleActiveFeatureChange","handleFilterTextFieldInputChange","filterInput","updateViewFilters","handleFilterUpdate","addFeatureToSelected","updateMapView","removeFeatureFromSelected","featureIndex","getSelectedFeatureIndex","getSelectedCollection","appendSelectedFeaturesCollection","updatedCollections","unshift","clearViewFilters","renderFilterInputField","showClearFilterButton","filterInputFieldContainer","getFilteredFeatureCollections","isFilterActive","getSortingStrategiesApplyingToView","handleSortingMenuItemClick","clearAllSelectedFeaturesInView","sourceId","onSelectedFeaturesView","renderSortingMenu","currentSortingStrategies","anchorEl","filterActive","filterHelpText","headerButtons","badgeContent","invisible","sortHelpText","currentTarget","collectionsToDownload","getCollectionsToDownload","allToolsDisabled","renderSearchResultListTools","in","hidden","nextFeature","nextCollection","shouldZoomToFeature","featureIsSelected","getNextFeatureInfo","setActiveFeatureCollection","showCorrespondingWMSLayers","alreadyVisibleSubLayers","subLayersToShow","values_","handleFeatureCollectionClick","sortFeatureCollections","featureCollectionsAtoZSorted","totalFeatures","reverse","keyPressIsEnter","currentFeatureIds","renderBreadCrumbs","featureCollectionTitle","shouldRenderFeatureCollectionDetails","shouldRenderFeatureDetails","separator","breadCrumbLinks","onKeyDown","renderHeaderInfoBar","renderSearchResultsHeader","shouldRenderHeaderInfoBar","tallHeaderContainer","sortedFeatureCollections","shouldRenderSelectedCollection","enableSelectedFeaturesCollection","collectionsToRender","severity","searchResultListWrapper","enableFeaturePreview","up","SearchResultsList","handleSingleSearchResult","handleOnFeatureClick","handleOnFeatureKeyPress","renderSearchResultDatasetSummary","showResultsLimitReachedWarning","renderSearchResultDataset","searchResultList","disableTouchRipple","searchResultListItem","aria-controls","SearchResultsDataset","previewFeature","previewAnchorEl","delayBeforeShowingPreview","previewTimer","shouldComponentUpdate","prevFeatureFilter","numFeatures","prevNumFeatures","setPreviewFeature","resetPreview","getSortedFeatures","featuresAtoZSorted","renderFeatureDetails","renderFeatureList","sortedFeatures","featureList","featureListItem","visibleInMap","renderSearchResultPreview","renderDatasetDetails","SearchResultsDatasetFeature","renderShowInMapCheckbox","helpText","handleCheckboxToggle","checkedIcon","renderOriginBasedIcon","shouldRenderCheckbox","SearchResultsPreview","renderFeaturePreview","preview","previewPaper","transformOrigin","disableRestoreFocus","previewHeaderContainer","previewContentContainer","datasetContainer","datasetDetailsContainer","fade","SearchResultsDatasetSummary","numberOfResultsToDisplay","shouldDisplayWarning","numberMatched","numberReturned","renderDatasetSummary","displayWarning","summaryContainer","warningChip","warning","contrastText","dark","SearchResultsDownloadMenu","handleXLSXDownloadClick","handleKMLDownloadClick","renderMenuTogglerButton","menuTogglerButton","renderDownloadMenu","enabledDownloadOptions","downloadOptions","downloadOption","menuItemIcon","SearchTools","settingsDialog","handleMenuItemClick","getEnabledTools","renderSettingsDialog","createPortal","enabledTools","aria-haspopup","getContentAnchorEl","SearchSettings","showSearchSourcesFilter","localUpdateSearchOptions","labelId","multiple","renderValue","chips","chip","ctrlKeyPressed","lastFeaturesInfo","featureStyle","resultsLayer","getDrawStyleSettings","drawStrokeColor","drawFillColor","getNewVectorSource","getNewVectorLayer","getVisibleLayers","visibleLayers","l_id","initMapLayers","resultSource","showResultFeaturesInMap","drawSource","drawLayer","getDrawStyle","clearMap","zoomToFeatures","addFeaturesToResultsLayer","setSelectedStyle","addAndHighlightFeatureInSearchResultLayer","updateFeaturesAfterFilterChange","setHighLightedStyle","zoomToFeature","searchInCurrentExtent","enableSelectFeaturesSearch","toggleDraw","forEachFeature","removeFeature","getFeatureById","fitMapToSearchResult","currentExtent","fitMapToExtent","resetStyleForFeaturesInResultSource","getFeatures","drawSourceHasFeatures","drawStyleSettings","mapFeature","getFeatureFromResultSourceById","createEmpty","extend","extentToZoomTo","isEmpty","featuresInfo","fid","removeDrawInteraction","removeSelectListeners","draw","freehand","Draw","stopClick","handleDrawFeatureAdded","calculateExtent","extentIsFinite","Feature","fromExtent","handleSearchInCurrentExtentError","un","addSelectListeners","handleSelectFeatureClick","handleKeyDown","handleKeyUp","removeEventListener","export","exportFeatures","gjFeature","Blob","info","transformed","circleRadius","setGeometry","getRadius","getGeometryName","postData","saveAs","styleObj","pointRadius","CircleStyle","pointColor","strokeDash","exportItems","workBook","XLSX","utils","book_new","fileName","sheet","sheetName","book_append_sheet","writeFile","groupedFeatures","exportArray","aoa_to_sheet","getKeys","featureProperties","ZoomControl","zoomByDelta","getAnimating","cancelAnimations","animate","duration","easing","easeOut","avatar","getTooltipString","User","RotateControl","useRef","getRotation","setRotation","subscribeToRotation","ScaleLineControl","formatScale","scaleLineControl","ScaleLine","addControl","mpu","getMetersPerUnit","scaleBadge","scaleLine","renderScaleBadge","AttributionControl","attributionControl","Attribution","tipLabel","whiteSpace","textShadow","MapCleaner","mapcleaner","MapResetter","MapSwitcher","renderMenuItems","menuItems","mapConfigurationTitle","selectedMap","mapConfigurationName","pathname","mapserviceBase","userSpecificMaps","handleLoading","resp","mapselector","aria-owns","Information","dialogOpen","handleOnClick","showInfoOnce","renderDialog","Preset","isValidMapLink","mapLink","getMapInfoFromMapLink","queryParams","handleItemClick","presetUrl","openDialog","flyTo","presetList","closeDialog","toggleMapLayers","abortDialog","layerShouldBeVisible","layerSwitcherLayers","common","white","DrawerToggleButtons","activeButton","setActiveButton","exclusive","removeItem","renderToggleButton","ThemeToggler","reportWebVitals","onPerfEntry","Function","getCLS","getFID","getFCP","getLCP","getTTFB","initHFetch","networkErrorMessage","parseErrorMessage","renderError","ReactDOM","cacheBuster","appConfigResponse","initFetchWrapper","searchParams","defaultMap","useMapService","useNewApi","experimentalNewApi","fetchMapConfig","configUrl","mapConfigResponse","customThemeResponse","setKeyName","buildConfig","layersConfigResponse","noLayerSwitcherMessage","errMsg","defaultOptions","FetchWrapper","urlRegex","isJqueryAjax","hash","process","REACT_APP_GIT_HASH","useCacheBuster","REACT_APP_USE_CACHE_BUSTER","ruleWithWildCard","partKeys","optionOverrides","matchesUrlPart","overrides","xhrFields","withCredentials","useOptionOverrides","applyOptionOverrides","translateToJqueryAjaxOptions","mapserviceBaseUri","fetchWrapper","originalFetch","updateConfig","jqueryAjaxWrapper","fetch","fw","Request","overrideOptions","originalJqueryAjax","wrapJqueryAjax","jqueryObject","ajax","xJqueryAjax","jw","webpackAsyncContext","req","__webpack_require__","ids","exports"],"mappings":"imBA+HMA,EAAK,IA7FT,aAAe,IAAD,oQASdC,UAAY,SAACC,GACX,IAAQC,EAAqCD,EAArCC,iBAAkBC,EAAmBF,EAAnBE,eAGtBD,GACF,EAAKE,SAAL,YAAc,EAAd,SACA,cAAI,GAAJ,GAAuBD,GAIvB,cAAI,GAAJ,IAAqB,GAnBX,KAyBdC,SAAW,SAACC,GACV,cAAI,GAAJ,GAAoBA,EACpB,cAAI,GAAJ,IACE,cAAI,GAAJ,GAAqBC,QAAQ,0BAA2BD,GAC1DE,OAAOC,aAAaC,QAAQ,cAA5B,YAA2C,EAA3C,QA7BY,KAiCdC,iBAAmB,WACjB,OAAO,cAAP,SAlCY,gDAsCO,WACnB,OAA6B,IAAtB,cAAI,GAAJ,MAvCK,gDA4CO,WACnB,OAA8B,IAAvB,cAAI,GAAJ,MA7CK,gDAkDU,WACtB,IAAMC,EAAiBJ,OAAOC,aAAaI,QAAQ,eACnD,OAAOD,EAAiBE,SAASF,GAAkB,KApDvC,KAwDdG,aAAe,WAEb,mBAAI,EAAJ,YAIA,YAAI,EAAJ,UAOG,cAAI,GAAJ,eAAoB,EAApB,SAAD,YAAiD,EAAjD,QArEU,KA0EdC,aAAe,WAEb,mBAAI,EAAJ,YAIA,YAAI,EAAJ,UAOG,cAAI,GAAJ,eAAoB,EAApB,SAAD,YAAiD,EAAjD,QAtFF,YAAAC,KAAA,OAAqB,EACrB,YAAAA,KAAA,MAAyB,EACzB,YAAAA,KAAA,MAAyB,EACzB,YAAAA,KAAA,MAAuB,MA4FdhB,EAAY,SAACC,GAAD,OAAcF,EAAGC,UAAUC,IACvCG,EAAW,SAACC,GAAD,OAAWN,EAAGK,SAASC,IAClCK,EAAmB,kBAAMX,EAAGW,oBAC5BI,EAAe,kBAAMf,EAAGe,gBACxBC,EAAe,kBAAMhB,EAAGgB,iB,2ECtI9B,SAASE,EAAaC,GAC3B,OAAQA,EAAkBA,EAAOC,QAAQ,KAAM,OAA9BD,EAGZ,SAASE,EAAaF,GAC3B,OAAQA,EAAkBA,EAAOC,QAAQ,OAAQ,KAAhCD,EALnB,kG,kPCGe,SAASG,EAA0BC,GAChD,IAAQC,EAASD,EAATC,KAER,MAAuB,kBAATA,EACZ,cAACC,EAAA,EAAD,UACE,sBAAMC,wBAAyB,CAAEC,OAAQH,OAG3CA,E,aCMW,SAASI,EAAiBL,GACvC,IAAMM,EAAQC,cACRC,EAAaC,YAAcH,EAAMI,YAAYC,KAAK,OAGtDC,EAYEZ,EAZFY,QACAC,EAWEb,EAXFa,QACAC,EAUEd,EAVFc,KAHF,EAaId,EATFe,QACEC,EALJ,EAKIA,UACAC,EANJ,EAMIA,mBACAC,EAPJ,EAOIA,WACAC,EARJ,EAQIA,WACAC,EATJ,EASIA,OACAnB,EAVJ,EAUIA,KACAoB,EAXJ,EAWIA,6BAMJ,EAAoCC,mBAAS,IAA7C,mBAAOC,EAAP,KAAmBC,EAAnB,KAEMC,GAAuC,IAAvBR,EAA8B,CAACS,KAAa,GAM5DC,EAAc,WAClBd,EAAQU,IAGV,OACE,eAACK,EAAA,EAAD,CACEC,kBAAgB,0BAChBrB,WAAYA,EACZK,QAASc,EACTb,KAAMA,EAJR,UAMGK,GACC,cAACW,EAAA,EAAD,CAAaC,GAAG,0BAAhB,SAA2CZ,IAE7C,eAACa,EAAA,EAAD,YACoC,IAAjCX,EACC,cAACtB,EAAD,CAA2BE,KAAMA,IAEjC,cAAC,IAAD,CACEgC,cAAe,CAACC,KAChBT,cAAeA,EACfU,WAAYC,mCACZC,SAAUpC,IAIbmB,GACC,sBACEkB,YAAU,EACVC,aAAa,MACbC,SAAU,SAACC,GAGT,OAFAA,EAAEC,iBACF1C,EAAMa,QAAQU,IACP,GANX,SASE,cAACoB,EAAA,EAAD,CACEZ,GAAG,cACHa,MAAM,GACNC,MAAOtB,EACPuB,SAAU,SAACL,GACTjB,EAAciB,EAAEM,OAAOF,QAEzBG,OAAO,SACPC,WAAW,SAKnB,eAACC,EAAA,EAAD,WACE,cAACC,EAAA,EAAD,CAAQC,QAASzB,EAAjB,SAA+BT,IAC9BF,GAAa,cAACmC,EAAA,EAAD,CAAQC,QAvDR,WAClBxC,EAAQW,IAsDU,SAA+BP,Y,4ECjE/CqC,E,iDACJC,QAAU,0B,8CAUV,WAAqC,IAA1BA,EAAyB,uDAAf,cACnB5D,KAAK4D,QAAL,sBAA8BA,K,iBAYhC,SAAIC,GAAqB,IAAhBC,EAAe,uDAAJ,GAClB,IAEE,OAAO,2BACFA,GACAC,KAAKC,MAAMzE,OAAOC,aAAaI,QAAQI,KAAK4D,UAC7CC,IAGJ,MAAOI,GAEP,OAAOH,K,iBAUX,SAAID,EAAKV,GACP5D,OAAOC,aAAaC,QAClBO,KAAK4D,QACLG,KAAKG,UAAL,2BACKH,KAAKC,MAAMzE,OAAOC,aAAaI,QAAQI,KAAK4D,WADjD,kBAEGC,EAAMV,U,KAOA,cAAIQ,G,4FCzFEQ,EACnB,WAAYC,GAAa,oBACvBpE,KAAKqE,YAAcD,EAAWC,YAC9BrE,KAAKsE,QAAUF,EAAWE,QAC1BtE,KAAKuE,UAAYH,EAAWG,UAC5BvE,KAAKwE,SAAWJ,EAAWI,SAC3BxE,KAAKyE,UAAYL,EAAWK,UAC5BzE,KAAK0E,QAAUN,EAAWM,QAC1B1E,KAAK2E,YAAcP,EAAWO,YAC9B3E,KAAK4E,YAAcR,EAAWQ,YAC9B5E,KAAK6E,kBAAoBT,EAAWS,kBACpC7E,KAAK8E,kBAAoBV,EAAWU,kBACpC9E,KAAK+E,sBAAwBX,EAAWW,sBACxC/E,KAAKgF,YAAcZ,EAAWY,YAC9BhF,KAAKiF,OAASb,EAAWa,OACzBjF,KAAKkF,WAAad,EAAWc,WAC7BlF,KAAKmF,kBAAoBf,EAAWe,kBACpCnF,KAAKoF,uBAAyBhB,EAAWgB,uBACzCpF,KAAKqF,oBAAsBjB,EAAWiB,oBACtCrF,KAAKsF,mBAAqBlB,EAAWkB,mBACrCtF,KAAKuF,mBAAqBnB,EAAWmB,mBACrCvF,KAAKwF,UAAYpB,EAAWoB,UAC5BxF,KAAKyF,UAAYrB,EAAWqB,UAC5BzF,KAAK0F,gBAAkBtB,EAAWsB,kB,8FChB/B,SAASC,IAAsB,IACpC,IAAMC,EAAW,SAACC,GAAD,OAASA,GAAsB,kBAARA,GADJ,mBAATC,EAAS,yBAATA,EAAS,gBAGpC,OAAOA,EAAQC,QAAO,SAACC,EAAMH,GAc3B,OAbAI,OAAOC,KAAKL,GAAKM,SAAQ,SAACtC,GACxB,IAAMuC,EAAOJ,EAAKnC,GACZwC,EAAOR,EAAIhC,GAEbyC,MAAMC,QAAQH,IAASE,MAAMC,QAAQF,GACvCL,EAAKnC,GAAOuC,EAAKI,OAAL,MAAAJ,EAAI,YAAWC,IAClBT,EAASQ,IAASR,EAASS,GACpCL,EAAKnC,GAAO8B,EAAUS,EAAMC,GAE5BL,EAAKnC,GAAOwC,KAITL,IACN,M,4jBC8BQS,EAAYC,YAAOC,IAAPD,EAAmB,iBAAO,CACjDE,aAAc,aAIHC,EAAiBH,YAAOI,IAAPJ,EAAiB,kBAAgB,CAC7D,sBAAuB,CACrBK,gBAF2C,EAAGnG,MAEvBoG,QAAQC,OAAOC,WAI7BC,EAAuBT,YAAOU,IAAPV,EAAuB,iBAAO,CAChEE,aAAc,aAGHS,EAAcX,YAAOY,IAAPZ,EAAc,gBAAG9F,EAAH,EAAGA,MAAH,MAAgB,CACvD2G,QAAS3G,EAAM4G,QAAQ,GACvBZ,aAAc,SACdG,gBAAiBnG,EAAMoG,QAAQS,WAAWC,QAC1C,MAAO,CACLd,aAAc,SAILe,EAAmBjB,YAAOC,IAAPD,EAAmB,YAAkB,IAAfkB,EAAc,EAAdA,QACpD,OAAO,2EACW,OAAZA,GAAoB,CACtBC,SAAU,SACVC,WAAY,MACZlB,aAAc,aAEA,OAAZgB,GAAoB,CACtBC,SAAU,SACVC,WAAY,MACZlB,aAAc,aAEA,OAAZgB,GAAoB,CACtBC,SAAU,SACVC,WAAY,QAEE,OAAZF,GAAoB,CACtBC,SAAU,OACVC,WAAY,QAEE,OAAZF,GAAoB,CACtBC,SAAU,WACVC,WAAY,QAEE,OAAZF,GAAoB,CACtBC,SAAU,WACVC,WAAY,MACZC,UAAW,cAKJC,EAA0B,SAAC,GAAyB,IAAvB3I,EAAsB,EAAtBA,MAAOsD,EAAe,EAAfA,SAC/C,OAAO,cAACgF,EAAD,CAAkBC,QAAO,WAAMvI,GAA/B,SAAyCsD,KAGrCsF,EAA6B,SAAC,GAKpC,IAJLtF,EAII,EAJJA,SACAuF,EAGI,EAHJA,MACAC,EAEI,EAFJA,SACAC,EACI,EADJA,UAEA,OACE,cAAC,IAAD,CACER,QAASO,EAAW,OAAS,OAC7BE,OAAY,OAALH,QAAK,IAALA,OAAA,EAAAA,EAAOI,YAAa,UAC3BJ,MAAOA,EACPE,UAAWA,EAJb,SAMGzF,KAMMD,EAAmC,CAC9C6F,EAAG,YAAmB,IAAhB5F,EAAe,EAAfA,SACJ,OAAQA,EAAkB,cAAC8D,EAAD,CAAWmB,QAAQ,QAAnB,SAA4BjF,IAAnC,MAErB6F,GAAI,kBAAM,cAAC,IAAD,KACVC,EAAG,YAAgC,IAA7B9F,EAA4B,EAA5BA,SAAU+F,EAAkB,EAAlBA,KAAMC,EAAY,EAAZA,MACpB,OAAOhG,EACL,cAAC,IAAD,CAAM+F,KAAMA,EAAMC,MAAOA,EAAOtF,OAAO,SAAvC,SACGV,IAED,MAENiG,GAAIZ,EACJa,GAAIb,EACJc,GAAId,EACJe,GAAIf,EACJgB,GAAIhB,EACJiB,GAAIjB,EACJkB,MAAO,YAAqC,IAAlCvG,EAAiC,EAAjCA,SAAUyF,EAAuB,EAAvBA,UAAWF,EAAY,EAAZA,MAC7B,OACE,cAACf,EAAD,CAAsBgC,UAAU,MAAhC,SACE,cAAC,IAAD,CAAOC,KAAK,QAAQhB,UAAWA,EAAWF,MAAOA,EAAjD,SACGvF,OAKT0G,MAAO,YAAmB,IAAhB1G,EAAe,EAAfA,SACR,OAAO,cAAC,IAAD,UAAYA,KAErB2G,MAAO,YAAmB,IAAhB3G,EAAe,EAAfA,SACR,OAAO,cAAC,IAAD,UAAYA,KAErB4G,GAAI,YAAmB,IAAhB5G,EAAe,EAAfA,SACL,OAAO,cAACkE,EAAD,UAAiBlE,KAE1B6G,GAAIvB,EACJwB,GAAIxB,EACJC,MAAO,YAAmB,IAAhBvF,EAAe,EAAfA,SACR,OAAO,uBAAO+G,KAAK,WAAZ,SAAwB/G,KAEjCgH,IAAK,YAAqC,IAAlChH,EAAiC,EAAjCA,SAAUyF,EAAuB,EAAvBA,UAAWF,EAAY,EAAZA,MAC3B,OACE,qBAAKE,UAAWA,EAAWF,MAAOA,EAAlC,SACGvF,KAIPiH,WAAY,SAACtJ,GACX,OAAO,cAAC+G,EAAD,CAAaO,QAAQ,WAArB,SAAiCtH,EAAMqC,c,khBCpL7BkH,EAOnB,WAAYxI,GAAU,IAAD,0WAUa,WAAO,IAAD,IAChCyI,EAAS,UAAG,cAAI,GAAJ,GAAcC,wBAAjB,QAAqC,wBAIpD,MAAO,CACLC,YAJe,UACf,cAAI,GAAJ,GAAcC,0BADC,QACqB,uBAIpCH,UAAWA,MAjBM,gDAqBe,WAAO,IAAD,QAWxC,MAAO,CACLE,YAXe,UACf,cAAI,GAAJ,GAAcE,4BADC,QACuB,uBAWtCJ,UAVa,UACb,cAAI,GAAJ,GAAcK,0BADD,QACuB,uBAUpCC,cATiB,UACjB,cAAI,GAAJ,GAAcC,yBADG,QACkB,qBASnCC,gBARmB,UACnB,cAAI,GAAJ,GAAcC,2BADK,QACkB,sBAQrC1C,SAPe,OA9BE,gDAyCe,WAAO,IAAD,QAUxC,MAAO,CACLmC,YAVe,UACf,cAAI,GAAJ,GAAcQ,4BADC,QACuB,uBAUtCV,UATa,UAAG,cAAI,GAAJ,GAAcW,0BAAjB,QAAuC,qBAUpDL,cATiB,UACjB,cAAI,GAAJ,GAAcM,yBADG,QACkB,qBASnCJ,gBARmB,UACnB,cAAI,GAAJ,GAAcK,2BADK,QACkB,sBAQrC9C,SAPe,OAjDE,KA4DrB+C,gBAAkB,SAACC,EAASnB,GAAU,IAAD,EAI7BoB,EAAgB,SAACC,GAAD,OAAOC,OAAOC,SAASpL,SAASkL,KAEtD,cAA6B,EAA7B,MAAQG,EAAR,EAAQA,MAAOC,EAAf,EAAeA,UACTC,EAAM,UAAG,cAAI,GAAJ,GAAcA,cAAjB,QAA2B,GAEjCC,GAAiB,OAAPR,QAAO,IAAPA,OAAA,EAAAA,EAASS,yBAAyBC,IAC5CjD,EAAY+C,EAAU,OAAS,SAC/BG,EAAUH,GAAW,IAAM,GAE3BpM,EACHyK,GAAiB,cAATA,EAAT,YAEI,EAFJ,kBACI,EADJ,MAQI+B,EAAYxM,EAAS6K,UAAU3J,QAAQ,YAAa,SAGpDuL,EAAS,uGAAmGD,EAAnG,uNACTE,EAAa,oCAAgCpM,OAAOqM,KAAKF,IAEzDG,EAAsB,cAATnC,EAAuB,IAAM,EAEhD,OAAO,IAAIoC,IAAJ,aACLC,KAAM,IAAIC,IAAK,CACbC,MAAOhN,EAAS6K,YAElBoC,OAAQ,IAAIC,IAAO,CACjBF,MAAOhN,EAAS+K,YAChBoC,MAAO,IAETC,MAAO,IAAIC,IAAK,CACdlB,OAAQ,CACNN,EAAcM,EAAO,IAAMA,EAAO,GAAK,GACvCN,EAAcM,EAAO,IAAMA,EAAO,GAAK,GAEzCF,OAAQJ,EAAcI,GAASA,EAAQ,GAAKW,EAC5CU,KAAc,OAATpB,QAAS,IAATA,OAAA,EAAAA,EAAWqB,QAAS,EAAIrB,EAAYQ,KAEvC,cAAI,GAAJ,IAAgC,CAClCpL,KAAM,IAAIkM,IAAK,CACbnE,UAAWA,EACXoE,aAAc,SACdC,KAAK,GAAD,OAAK1N,EAAS4I,SAAd,2BACJkE,KAAM,IAAIC,IAAK,CACbC,MAAOhN,EAASmL,gBAElB7J,KAAMsK,EAAQ+B,aACdC,UAAU,EACVX,OAAQ,IAAIC,IAAO,CACjBF,MAAOhN,EAASqL,gBAChB8B,MAAO,IAETU,QAAS,EACTtB,QAASA,EACTuB,SAAU,EACV7B,MAAO,QA3HM,KAiIrB8B,4BAA8B,SAACnC,GAC7B,IAAM5L,EAAQ,YAAG,EAAH,MAER8M,EAAO,IAAIC,IAAK,CACpBC,MAAO,cAAI,GAAJ,GAAkCnC,YAGrCoC,EAAS,IAAIC,IAAO,CACxBF,MAAO,cAAI,GAAJ,GAAkCjC,YACzCoC,MAAO,IAET,OAAO,IAAIN,IAAJ,aACLC,KAAMA,EACNG,OAAQA,EACRG,MAAO,IAAIY,IAAO,CAChBlB,KAAMA,EACNG,OAAQA,EACRgB,OAAQ,MAEN,cAAI,GAAJ,IAAgC,CAClC3M,KAAM,IAAIkM,IAAK,CACbnE,UAAW,SACXoE,aAAc,SACdC,KAAK,4BACLZ,KAAM,IAAIC,IAAK,CACbC,MAAOhN,EAASmL,gBAElB7J,KAAMsK,EAAQsC,kBACdN,UAAU,EACVX,OAAQ,IAAIC,IAAO,CACjBF,MAAOhN,EAASqL,gBAChB8B,MAAO,IAETU,QAAS,EACTtB,QAAS,EACTuB,SAAU,EACV7B,MAAO,QApKb,YAAAlL,KAAA,MAAgBqB,EAChB,YAAArB,KAAA,gBAA+BqB,EAAQ+L,8BAAvC,SACA,YAAApN,KAAA,kBAAoCA,KAApC,QACA,YAAAA,KAAA,kBACEA,KADF,QAEA,YAAAA,KAAA,kBACEA,KADF,U,sMC4DJ,SAASqN,EAAcC,GACrB,MAAiB,WAAbA,EACKzN,SACe,WAAbyN,EACF,SAAC7E,GACN,OAAOA,EAAIA,EAAE8E,OAAS,IAGjB,SAAC9E,GACN,OAAOA,GA0Bb,SAAS+E,EAAaC,EAAOC,GAAW,IAAD,EACrC,GAAKA,KAAYA,EAASlB,QAAU,GAApC,CAGA,IAAMmB,EAAYF,EAAMG,gBAAgBD,UACxC,GAAKA,EAAU5I,sBAAf,CAIA,IA9BqB1D,EA8BfiM,EAAWK,EAAU9I,mBAAqB,SAC1CgJ,EAAc,CAClBnE,KAAM4D,EACNQ,KAAI,UAAEH,EAAU7I,yBAAZ,SACJiJ,KAAMJ,EAAU5I,sBAAsBwI,OACtCS,OAAQX,EAAcC,IAGxBI,EAASO,KArCY,YADA5M,EAsCOwM,GArChBnE,KACH,SAACjB,EAAGyF,GACT,OACG7M,EAAQyM,MAAQ,EAAI,IACpBzM,EAAQ2M,OAAOvF,EAAEmF,gBAAgBvM,EAAQ0M,OACxC1M,EAAQ2M,OAAOE,EAAEN,gBAAgBvM,EAAQ0M,SAIxC,SAACtF,EAAGyF,GACT,OACG7M,EAAQyM,MAAQ,EAAI,GACrBzM,EACG2M,OAAOvF,EAAEmF,gBAAgBvM,EAAQ0M,OACjCI,cAAc9M,EAAQ2M,OAAOE,EAAEN,gBAAgBvM,EAAQ0M,YAiElE,SAASK,EAAoBC,EAAUC,GACrC,IAEMC,EAvCR,SAA0BD,EAAUE,EAAiBC,GACnD,IAAMT,EAAS,IAAIU,IAMbC,EAAgBL,EAASM,IAC3B,GACA,CACEC,eAAgBL,EAChBM,kBAAmBL,GAGnBM,EAAiB,GAmBvB,OAhBAT,EAASZ,SAASsB,KAAI,SAACC,GAErB,IAAMC,EAAoBlB,EAAOmB,YAAYF,EAAaN,GAW1D,OATKO,EAAkBE,SAIrBF,EAAkBG,MAAlB,UACKJ,EAAYK,UADjB,YAC8BJ,EAAkBK,SAI3CR,EAAeS,KAAKN,MAGtBH,EAMQU,CAAiBnB,EAFRD,EAASZ,MAAMiC,YAAYC,gBAC5BtB,EAASI,gBAEhC,OAAIF,GAAUA,EAAO/B,OAAS,GAC5B+B,EAAOpI,SAAQ,SAACyJ,GACdA,EAAEnC,MAAQY,EAASZ,SAErBD,EAAaa,EAASZ,MAAOc,GACtBA,GAEA,GAyBJ,SAASsB,EAAYC,EAAKd,EAAKe,GACpCC,SAASC,cAAc,QAAQ/H,MAAMgI,OAAS,WAC9C,IAAMC,EAAW,GACX1B,EAAiBO,EAAIoB,UAAUT,gBAAgBU,UACrDrB,EACGsB,YACAC,WAEAC,QACC,SAAC/C,GAAD,OAEGA,aAAiBgD,KAAahD,aAAiBiD,OAEvB,IAAzBjD,EAAMkD,IAAI,cAGbxK,SAAQ,SAACsH,GAGR,IAAMmD,EA3NZ,SAAe5B,EAAKvB,EAAOqC,GACzB,IAAMe,EAAaf,EAAIe,WACjBC,EAAa9B,EAAIoB,UAAUW,gBAC3BC,EAAchC,EAAIoB,UAAUa,UAC5BC,EAAkBlC,EAAIoB,UAAUT,gBAAgBU,UAClDc,EAAmB,GAKvB,GACE1D,EAAM2D,YACN3D,EAAM4D,cAAgBL,GACtBA,GAAevD,EAAM6D,aACrB,CACA,IAAMC,EAAYtL,OAAOuL,OAAO/D,EAAM2D,YAOhCK,GAHJhE,EAAMiC,YAAYgC,YAAlB,QAA2C,IAGQC,MAAM,KAGrDC,EAAsB,IAAIC,IAAIJ,GAGpCN,EAAmBI,EAChBf,QACC,SAACsB,GAAD,OACyB,IAAvBA,EAASC,WAAsBH,EAAoBI,IAAIF,EAASzP,OAEnE2M,KAAI,SAACiD,GACJ,OAAOA,EAAkB5P,MAI/B,GAAI8O,EAAiB3E,OAAS,EAAG,CAC/B,IAAI0F,EAAS,CACXC,cAAe,IACfC,YAAa3E,EAAMiC,YAAYgC,YAAYU,YAC3CC,aAAclB,EAAiBmB,KAAK,MASA,SAAlC7E,EAAMiC,YAAY6C,cACpBL,EAAM,2BACDA,GADC,IAEJM,mBAAoB,GACpBC,kBAAmB,GACnBC,qBAAsB,GACtBC,eAAe,KAInB,IAAMC,EAAMnF,EACTiC,YACAmD,kBAAkBhC,EAAYC,EAAYI,EAAiBgB,GAC9D,OAAOY,iBAAOF,GAEd,OAAO,EAyJWG,CAAM/D,EAAKvB,EAAOqC,IAElB,IAAZc,GACFT,EAASX,KACPoB,EAAQoC,MAAK,SAAC3E,GACZ,MAAO,CACLZ,MAAOA,EACPwF,gBAAiB5E,EACjBI,eAAgBA,UAO5ByE,QAAQC,IAAIhD,GAAU6C,MAAK,SAACI,GAC1B,IAAMC,EAAkB,GAClB3F,EAAW,GACjB0F,EAAUjN,SAAQ,SAACkI,GAIjB,OAHaA,EAAS4E,gBAAgBK,QACnC3C,IAAI,gBACJgB,MAAM,KAAK,IAEZ,IAAK,sBACL,IAAK,mBACH0B,EAAgB7D,KACdnB,EAAS4E,gBACNM,OACAP,MAAK,SAAC1E,QAEUkF,IAAblF,GACAA,GACAA,EAASZ,UACTY,EAASZ,SAASlB,OAAS,GAE3BkB,EAAS8B,KAAT,MAAA9B,EAAQ,YAASU,EAAoBC,EAAUC,QAGlDmF,OAAM,SAACC,GACNC,QAAQ1P,MACN,wEACAyP,OAIR,MACF,IAAK,WACL,IAAK,0BACHL,EAAgB7D,KACdnB,EAAS4E,gBACN1S,OACAyS,MAAK,SAACzS,GACLmN,EAAS8B,KAAT,MAAA9B,EAAQ,YA5FxB,SAA4BW,EAAU9N,GACpC,IAEIgO,GAFoB,IAAIqF,KAEGC,aAAatT,GAC5C,OAAIgO,GAAUA,EAAO/B,OAAS,GAC5B+B,EAAOpI,SAAQ,SAACyJ,GACdA,EAAEnC,MAAQY,EAASZ,SAErBD,EAAaa,EAASZ,MAAOc,GACtBA,GAEA,GAiFsBuF,CAAmBzF,EAAU9N,QAE/CkT,OAAM,SAACC,GACNC,QAAQ1P,MACN,kFAWdiP,QAAQC,IAAIE,GAAiBL,MAAK,WAChChE,EAAI+E,sBACFjE,EAAIkE,OACJ,SAACnJ,EAAS4C,IAENA,IAC4B,IAA3BA,EAAMkD,IAAI,cACa,sBAAtBlD,EAAMkD,IAAI,UAEZ9F,EAAQ4C,MAAQA,EAChBC,EAAS8B,KAAK3E,MAGlB,CACEoJ,aAAc,KAIlBjE,SAASC,cAAc,QAAQ/H,MAAMgI,OAAS,UAC9CH,EAAS,CACPrC,SAAUA,EACVoC,IAAKA,UAMN,SAASoE,EAAkBlF,EAAKe,GAiBrCf,EAAImF,GAAG,eAAe,SAACrE,GAGE,IAAvBd,EAAIoF,UAAUhL,MAAcyG,EAAYC,EAAKd,EAAKe,Q,8bCxUjCsE,E,WACnB,WAAYpV,GAAW,IAAD,6EA6DL,SAACqV,GAChB,GAAmB,kBAARA,EAAkB,OAAO,EACpC,IAKMC,EAAQD,EAAIE,MALA,iBAOdC,GAAS,EAEb,GAHiBF,GALA,CACf,IAAK,KACL,IAAK,MAG4BA,EAAM,IAAIG,KAAKJ,GAIhD,IACEG,EAAS1Q,KAAKC,MAAMsQ,GACpB,MAAOK,GACPF,GAAS,OAGXA,GAAS,EAGX,OAAOA,KAlFa,gDAqFY,SAACG,GAMjC,IAJAA,EAAcA,EAAYC,UAAU,EAAGD,EAAYpI,OAAS,IAI5CsI,SAAS,QAAUF,EAAYE,SAAS,OAAQ,CAE9D,MAAmCF,EAAYjD,MAAM,MAArD,mBAAOoD,EAAP,KAAqBC,EAArB,KAGMC,EAAgB,EAAK7Q,WAAW2Q,GAGtC,YACoBvB,IAAlByB,GACkB,OAAlBA,GACyB,KAAzBA,EAAc1H,OAEP,GAYD,IAAN,OACE,EAAK2H,gBAAgB1F,KAArB,YACE,EADF,MACsByF,EAAeD,IACjC,EAHN,KAMG,OAAIJ,EAAYE,SAAS,KACvBK,UAAmBC,aAAa,EAAKhR,WAAYwQ,IAWtD,YAAKxQ,kBAAL,mBAAkBwQ,UAAlB,mBAAgCzU,eAAhC,sBAA0C,KAAM,aAChD,EAAKiE,WAAWwQ,IAChB,GAVE,IAAD,SA9He,gDA6IL,SAACK,EAAeD,GAE/B,OACE,EAAK7V,eAAekW,aAApB,0BAAoDL,IAAcxI,OAClE,EAEO,IAAI0G,SAAQ,SAACoC,EAASC,GAI3B,EAAKpW,eAAeG,QAApB,0BAA+C0V,GAAc,CAC3DQ,QAASP,EACTK,UACAC,cAIG,QA9JW,gDA0KC,WAAc,IAAD,MAI5BE,GAAO,EAAQ,UAAKjJ,OAAS,GAAtB,2CAGb,OAAQiJ,EAAQC,WACd,IAAK,KAQH,GAHAD,EAAQE,SAAW,KAGnB,UAAIF,EAAQG,kBAAZ,aAAI,EAAoBd,SAAS,KAAM,CAErC,MAAaW,EAAQG,WAClBjE,MAAM,KACN3C,KAAI,SAACjM,GAAD,OAAOA,EAAE8S,WAAW,IAAK,IAAItI,UAFpC,mBAAKuI,EAAL,KAAQC,EAAR,KAMA,OAAID,GAAKC,EACAN,EAAQE,QAER,GAIN,OAAI,UAAAF,EAAQG,kBAAR,eAAoBrI,OAAOf,QAAS,EACpCiJ,EAAQE,QAIR,GAGX,QACE,OAAO,UAAP,kCAlNgB,gDAiOC,WAAc,IAAD,EAE5BF,GAAO,EAAQ,UAAKjJ,OAAS,GAAtB,2CAGPjM,EAAOkV,EAAQlV,KACfoI,EAAQ8M,EAAQ9M,MAAQ,IAAM8M,EAAQ9M,MAAQ,GAGhDD,EAAO+M,EAAQ/M,KAEnB,IAIEA,EAAO,IAAIsN,IAAItN,GACf,MAAOzE,GAMPyE,EAAOuN,UAAUvN,GAInB,IAAMwN,EAAC,WAAO3V,EAAP,aAAgBmI,GAAhB,OAAuBC,EAAvB,KACP,OAAOuN,KA5Pa,KAoQtBC,0BAA4B,SAAC/R,GAQ3B,OAPA6B,OAAOC,KAAK9B,GAAY+B,SAAQ,SAACiQ,GAC/B,IAAI9H,EAAQ,YAAG,EAAH,MAAuBlK,EAAWgS,IAC1C9H,WACKlK,EAAWgS,GAClBhS,EAAU,2BAAQA,GAAekK,OAG9BlK,GA5Qa,KAsStBiS,8BAtSsB,sBAsSU,4BAAA5N,EAAA,0DAC1B,EAAK6N,UAAqC,kBAAlB,EAAKA,SADH,wBAQ3B,EAAKA,SAAS9B,MAAM,sCAAwC,IAAIrO,SAC/D,SAACyO,GAKC,EAAK0B,SAAW,EAAKA,SAASnW,QAC5ByU,EADc,YAEd,EAFc,MAEuBA,OAmB3C,EAAK0B,SAAW,EAAKA,SAASnW,QAAd,YACd,6JADc,kDAEd,EAFc,OAgBhB,EAAKmW,SAAW,EAAKA,SAASnW,QAAd,YACd,6DADc,qCAEd,EAFc,OAQhB,EAAKmW,SAAW,EAAKA,SAASnW,QAAQ,WAAY,KA3DtB,SA+DgB+S,QAAQC,IAClD,EAAK+B,iBAhEqB,cA+D5B,EAAKqB,+BA/DuB,OAqEtBxU,EAAgB,EAAKR,mBAAqB,CAACS,KAAa,GArElC,kBA0E1B,cAAC,IAAD,CACEO,cAAe,CAACC,KAChBT,cAAeA,EACfU,WAAY,EAAKA,WACjBE,SAAU,EAAK2T,YA9ES,4CArS9BtW,KAAKb,eAAiBF,EAASE,eAC/Ba,KAAKqB,QAAUpC,EAASoC,QAGxBrB,KAAKkV,gBAAkB,GACvBlV,KAAKuW,+BAAiC,GAEtCvW,KAAKsW,SAAW,KAChBtW,KAAKoE,WAAa,KAGlBpE,KAAKuB,mBAAL,UAA0BvB,KAAKqB,QAAQE,0BAAvC,SAOAvB,KAAKyC,WAAL,2BACKC,oCADL,IAEE6F,EAAG,YAAmB,IAAhB5F,EAAe,EAAfA,SACJ,OAAKA,EAKH,cAAC,YAAD,CAAWiF,QAAQ,QAAnB,SACGjF,EAASqM,KAAI,SAACwH,EAAOC,GAGpB,IAAIC,EAAoB,KAExB,GAAIF,GAA0B,kBAAVA,EAAoB,CAKtC,IAAMhC,EAAQgC,EAAMhC,MAAM,WAExBA,GACA,EAAK+B,+BAA+BI,eAAenC,EAAM,MAGzDkC,EACE,EAAKH,+BAA+B/B,EAAM,KAIhD,OACE,cAAC,IAAMoC,SAAP,UACGF,GAAqBF,GADHC,QA3BpB,Q,4DAwPf,YAAoD,IAAzBH,EAAwB,EAAxBA,SAAUlS,EAAc,EAAdA,WAGnC,OAFApE,KAAKsW,SAAWA,EAChBtW,KAAKoE,WAAaA,EACXpE,S,0OCrPL6W,E,kDAKJ,WAAYvW,GAAQ,IAAD,gCACjB,cAAMA,IALRwW,MAAQ,CACNC,QAAS,MAGQ,EAYnBC,kBAAoB,WAClB,EAAKC,cAbY,EAgBnBC,mBAAqB,SAACC,GACA,EAAK7W,MAAjBuK,UACYsM,EAAUtM,SAE5B,EAAKoM,cApBU,EAwBnBA,WAAa,WACP,EAAKG,4BACP,EAAKC,qBAEL,EAAKC,qBA5BU,EAgCnBF,0BAA4B,WAAO,IAAD,EAE1BG,EAAM,UADQ,EAAKjX,MAAjBuK,QACe0M,cAAX,QAAqB,EAAKjX,MAAMiX,OAC5C,OAAOA,EAAOC,SAA8B,KAAnBD,EAAOC,SAnCf,EAsCnBH,mBAAqB,WAAO,IAAD,EACjBxM,EAAY,EAAKvK,MAAjBuK,QACF0M,EAAM,UAAG1M,EAAQ0M,cAAX,QAAqB,EAAKjX,MAAMiX,OAC5C1M,EAAQ4M,cACN,EAAKC,oBAAoBvB,0BACvBtL,EAAQ+C,kBAGZ,EAAK8J,oBACFC,yBAAyB,CACxBrB,SAAUiB,EAAOC,QACjBpT,WAAYyG,EAAQ+C,kBAErByI,gCACArD,MAAK,SAAC4E,GACL,EAAKC,SAAS,CAAEd,QAASa,QArDZ,EAyDnBN,kBAAoB,WAClB,EAAKO,SAAS,CAAEd,QAAS,EAAKe,0BA1Db,EA6DnBC,gBAAkB,SAACpC,EAASqC,GAC1B,IAAQC,EAAY,EAAK3X,MAAjB2X,QACFC,EAAe5R,MAAMC,QAAQoP,GAAWA,EAAQrD,KAAK,MAAQqD,EACnE,OACE,cAAC,IAAD,CACEtN,MAAO2P,EACP9P,MAAoB,UAAb8P,EAAuB,CAAEG,aAAc,GAAM,KACpD/P,UAAW6P,EAAQG,UAHrB,SAKGF,KAtEY,EA2EnBJ,qBAAuB,WACrB,IAAQjN,EAAY,EAAKvK,MAAjBuK,QACR,OACE,cAAC,IAAD,UACE,cAAC,IAAD,CAAOzB,KAAK,QAAZ,SACE,cAAC,IAAD,UACGnD,OAAOoS,QAAQxN,EAAQ+C,iBAAiBoB,KAAI,SAACsJ,GAK5C,MAAyB,kBAAXA,EAAI,IACE,kBAAXA,EAAI,IACXhS,MAAMC,QAAQ+R,EAAI,IAClB,eAAC,IAAD,WACG,EAAKP,gBAAgBO,EAAI,IACzB,EAAKP,gBAAgBO,EAAI,GAAI,WAFjBA,EAAI,IAIjB,eA7FG,EAqGnBC,qBAAuB,SAACC,GACtB,MAAuC,EAAKlY,OAE5CmY,EAFA,EAAQA,kBAAR,EAA0B/K,SACG8K,KAvGZ,EA2GnBE,gBAAkB,SAAC7N,EAAS6C,GAAc,IAAD,EACvC,wBACEA,QADF,IACEA,OADF,EACEA,EAAUiL,WAAU,SAAC/I,GACnB,OAAOA,EAAER,UAAYvE,EAAQuE,kBAFjC,SAGS,GA/GQ,EAmHnBwJ,qBAAuB,WACrB,MAAuC,EAAKtY,MAApCuK,EAAR,EAAQA,QAASoN,EAAjB,EAAiBA,QAASvK,EAA1B,EAA0BA,SACpBmL,EAA0BnL,EAASlB,OACnCsM,EAAsB,EAAKJ,gBAAgB7N,EAAS6C,GAEpDqL,EAAqBD,EAAsB,EAAI,EAC/CE,EACJF,EAAsB,GAAKD,EAE7B,OACE,eAAC,IAAD,CAAMI,WAAS,EAACC,MAAI,EAACC,WAAW,SAASC,QAAQ,gBAAjD,UACE,cAAC,IAAD,CAAMF,MAAI,EAAV,SACE,cAAC,IAAD,CACEvQ,MACGoQ,EAEG,GADA,gDAHR,SAOE,+BACE,cAAC,IAAD,CACE3P,KAAK,QACLxB,QAAQ,WACRQ,UAAW6P,EAAQoB,cACnBC,SAAUP,EACVrV,QAAS,kBACP,EAAK6U,qBAAqBO,EAAsB,IAElDS,aAAW,wBACXlX,GAAG,YATL,SAWE,cAAC,IAAD,CACEwF,SAAS,QACToE,MAAO8M,EAAqB,WAAa,mBAMnD,cAAC,IAAD,CAAMG,MAAI,EAAV,SACE,cAAC,IAAD,CACEvQ,MACGqQ,EAA6D,GAAvC,wCAF3B,SAKE,+BACE,cAAC,IAAD,CACE5P,KAAK,QACLxB,QAAQ,WACRQ,UAAW6P,EAAQoB,cACnBC,SAAUN,EACVtV,QAAS,kBACP,EAAK6U,qBAAqBO,EAAsB,IAElDS,aAAW,oBACXlX,GAAG,YATL,SAWE,cAAC,IAAD,CACEwF,SAAS,QACToE,MAAO+M,EAAsB,WAAa,uBA9KvC,EAwLnBQ,mBAAqB,WACnB,MAA6B,EAAKlZ,MAA1BuK,EAAR,EAAQA,QAASoN,EAAjB,EAAiBA,QACjB,OACE,cAAC,IAAD,CACEwB,QAAM,EACNrR,UAAW6P,EAAQyB,iBACnBvQ,UAAU,MACVvB,QAAQ,SACRS,MAAM,OALR,SAOGwC,EAAQ+B,gBA/Lb,EAAK8K,oBAAsB,IAAIrD,UAAoB,CACjDlV,eAAgBmB,EAAMqZ,IAAIxa,eAC1BkC,SACE,UAAAf,EAAMqZ,IAAIC,SAASC,OAAOC,UAAUC,MAAMC,MACxC,SAACC,GAAD,MAAkB,cAAXA,EAAEvQ,eADX,eAEGrI,UAAW,KARD,E,0CAuMnB,WACE,MAAoDrB,KAAKM,MAAjD2X,EAAR,EAAQA,QAASvK,EAAjB,EAAiBA,SAAUwM,EAA3B,EAA2BA,qBACnBnD,EAAY/W,KAAK8W,MAAjBC,QACFoD,GACJ,OAACD,QAAD,IAACA,QAAyC,OAARxM,QAAQ,IAARA,OAAA,EAAAA,EAAUlB,QAAS,EACvD,OACE,eAAC,IAAD,CAAMyM,WAAS,EAAC7Q,UAAW6P,EAAQmC,2BAAnC,UACE,eAAC,IAAD,CAAMnB,WAAS,EAACE,WAAW,SAAS/Q,UAAW6P,EAAQoC,gBAAvD,UACE,cAAC,IAAD,CACEnB,MAAI,EACJoB,GAAIH,EAAsB,EAAI,GAC9BI,GAAIJ,EAAsB,GAAK,GAHjC,SAKGna,KAAKwZ,uBAEPW,GACC,cAAC,IAAD,CAAMjB,MAAI,EAACoB,GAAI,EAAGC,GAAI,EAAtB,SACGva,KAAK4Y,4BAIX7B,GACC,cAAC,IAAD,CAAMmC,MAAI,EAACoB,GAAI,GAAf,SACGvD,W,GAnOoCyD,IAAMC,eA0OxCC,uBAlQA,SAAC9Z,GAAD,MAAY,CACzBwX,UAAW,CACTuC,YAAa,EACbC,UAAW,YACXxO,MAAO,OAETgO,2BAA4B,CAC1BS,SAAU,OACVF,YAAa/Z,EAAM4G,QAAQ,GAC3B2Q,aAAcvX,EAAM4G,QAAQ,IAE9BkS,iBAAkB,CAChBmB,SAAU,OACVhT,SAAU,IAEZwS,gBAAiB,CACfS,WAAYla,EAAM4G,QAAQ,IAE5B6R,cAAe,CACb0B,SAAU,GACVxT,QAAS,MA8OEmT,CAAmB7D,I,iHC/MlC,SAASmE,EAASnB,EAAQoB,GAAc,IAAD,EAC/BC,EAxDR,SAAwBC,EAAmCF,GAAc,IAAD,IAItE,GAAI,CAAC,QAAS,QAAQnG,SAAlB,OAA2BmG,QAA3B,IAA2BA,GAA3B,UAA2BA,EAAajU,eAAxC,aAA2B,EAAsB0C,MACnD,OAAOuR,EAAYjU,QAAQ0C,KAK7B,IAAM0R,EAA2B7b,OAAOC,aAAaI,QACnD,4BAGEsb,EAAc,KAGlB,GAAI,CAAC,QAAS,QAAQpG,SAASsG,GAC7BF,EAAcE,OAGd,OACED,GAEA,IAAK,OACHD,EAAc,OACd,MACF,IAAK,QACHA,EAAc,QACd,MACF,QAEEA,GACiE,KAAzD,QAAN,EAAA3b,cAAA,eAAQ8b,WAAW,gCAAgCC,SAC/C,OACA,QAKZ,OAAOJ,EAgBaK,CAAc,UAChC1B,EAAOC,UAAU9K,IAAIwM,cADW,aAChC,EAA6BC,qBAC7BR,GAGIS,EAAoB,CACxB1U,QAAS,CACP0C,KAAMwR,EACNjU,OAAQ,CACN0U,OAAwB,SAAhBT,EAAyB,OAAS,wBAG9CU,MAAO,CACLC,aAAc,IAKZC,EAAqB,CACzB9U,QAAS,CACP+U,QAAS,CACPC,KAAMnC,EAAOC,UAAU9K,IAAIwM,OAAOS,cAEpCC,UAAW,CACTF,KAAMnC,EAAOC,UAAU9K,IAAIwM,OAAOW,kBAYxC,OANoBxW,oBAClB+V,EACAT,EACAa,GA6EWM,UAvEW,SAAC,GAA0C,IAAxCC,EAAuC,EAAvCA,YAAaxC,EAA0B,EAA1BA,OAAQoB,EAAkB,EAAlBA,YAEhD,EAA0BrZ,mBAASoZ,EAASnB,EAAQoB,IAApD,mBAAOra,EAAP,KAAc0b,EAAd,KAMA,EAAgC1a,mBAAS2a,KAAKC,UAA9C,mBAAOC,EAAP,KAAiBC,EAAjB,KA8CMC,EAAWC,YAAehc,GAGhC,OACE,eAAC,IAAD,CAAkBA,MAAO+b,EAAzB,UACE,cAAC,IAAD,IACA,cAAC,UAAD,CACEN,YAAaA,EACbxC,OAAQA,EACRjZ,MAAO+b,EACPE,eArDiB,WAAO,IAAD,EAE3B,YAAI5B,QAAJ,IAAIA,GAAJ,UAAIA,EAAajU,eAAjB,aAAI,EAAsB0C,MAA1B,CAGA,IAAI0R,EACqB,UAAvBxa,EAAMoG,QAAQ0C,KAAmB,OAAS,QAG5CnK,OAAOC,aAAaC,QAClB,2BACA2b,GAKF,IAAM0B,EAAWnX,oBAAU/E,EAAO,CAChCoG,QAAS,CACP0C,KAAM0R,EACNnU,OAAQ,CACN0U,OAC+B,SAA7BP,EACI,OACA,0BAOZkB,EAASQ,KAwBLC,gBAhBkB,WACtBL,EAAYD,EAAWF,KAAKC,kB,qKC3IhCQ,IAAIC,UAAUC,YAAc,SAAUna,EAAGoa,GACvC,GAAInd,KAAK8W,MAAMsG,YACb,OAAO,EAMT,GAHIpd,KAAKM,MAAM4c,aACbld,KAAKM,MAAM4c,YAAYna,EAAGoa,GAEvBnd,KAAKM,MAAM+c,OAAhB,CACA,IAEIC,EAFEC,EAASvd,KAAKwd,YACdtS,EAAQlL,KAAKM,MAAM4K,MAEzB,GAA0B,WAAtBlL,KAAKM,MAAM+c,OACbC,EAAWC,MACN,IAA0B,SAAtBvd,KAAKM,MAAM+c,OAAmB,CACvC,IAAMI,EAAaF,EAAOG,wBACpBC,EAAaF,EAAWG,KACxBC,EAAYJ,EAAWK,IACvBC,EAAW/N,SAASgO,KAAKN,wBACzBE,IACFD,EAAaJ,EAAOU,WAAa/S,EAAQ6S,EAASH,MAAQ1S,EACxD4S,IAAQD,EAAYN,EAAOW,UAAYhT,EAAQ6S,EAASD,KAAO5S,EAC/DiT,GACHnO,SAASgO,KAAKI,YAAcpe,KAAKqe,UAAUjV,KAAKgD,MAAQlB,GAASA,EAClE0S,EACIU,GACHtO,SAASgO,KAAKO,aAAeve,KAAKqe,UAAUjV,KAAKoV,OAAStT,GACzDA,EACF4S,EACF,OAAO9d,KAAK6X,SAAS,CAAEwF,OAAQ,CAAES,MAAKK,QAAOG,SAAQV,UAChD,GAA0B,WAAtB5d,KAAKM,MAAM+c,OAAqB,CACzC,IAAKrd,KAAKqe,UAAW,OACrB,IAAMZ,EAAaF,EAAOG,wBACpBC,EAAaF,EAAWG,KACxBC,EAAYJ,EAAWK,IACvBF,IAASD,EAAaJ,EAAOU,WAAa/S,GAASA,EACnD4S,IAAQD,EAAYN,EAAOW,UAAYhT,GAASA,EAChDiT,GACH5e,OAAOkf,WAAaze,KAAKqe,UAAUjV,KAAKgD,MAAQlB,GAASA,EAAQ0S,EAC9DU,GACH/e,OAAOmf,YAAc1e,KAAKqe,UAAUjV,KAAKoV,OAAStT,GAASA,EAAQ4S,EACtE,OAAO9d,KAAK6X,SAAS,CAAEwF,OAAQ,CAAES,MAAKK,QAAOG,SAAQV,UAErDN,EAAWtN,SAASC,cAAcjQ,KAAKM,MAAM+c,QAE/C,GAAMC,aAAoBqB,aAAkBpB,aAAkBoB,YAA9D,CAGA,IAAMC,EAAetB,EAASI,wBACxBmB,EAAeD,EAAahB,KAC5BkB,EAAcF,EAAad,IAC3BL,EAAaF,EAAOG,wBAGpBE,GAAQiB,EAFKpB,EAAWG,MAEa1S,EACrC4S,EAAMgB,EAFMrB,EAAWK,IAG7B,GAAK9d,KAAKqe,UAAV,CACAre,KAAK+e,yBACL,IAAMC,EAAShf,KAAKif,iBACpBjf,KAAK6X,SAAS,CACZwF,OAAQ,CACNS,IAAKA,EAAMkB,EAAOlB,IAClBK,MACEP,GACCN,EAASc,YAAcpe,KAAKqe,UAAUjV,KAAKgD,OAC5C4S,EAAOpB,KAAO1S,EAChBoT,OACER,GAAOR,EAASiB,aAAeve,KAAKqe,UAAUjV,KAAKoV,QAAUQ,EAAOlB,IACtEF,KAAMA,EAAOoB,EAAOpB,KAAO1S,SAKjC,IA6CMgU,E,kDA4BJ,WAAY5e,GAAQ,IAAD,8BACjB,cAAMA,IAmBR4W,mBAAqB,SAACC,EAAWgI,IACR,IAAnBhI,EAAU/V,OAAsC,IAApB,EAAKd,MAAMc,MAGzCge,YAAW,WACT,EAAKC,UAAUC,QAAQC,UACtB,MA1BY,EAgInBC,MAAQ,SAACzc,GACP,MAA2C,EAAKzC,MAAxCa,EAAR,EAAQA,QAAShC,EAAjB,EAAiBA,eAAgBwJ,EAAjC,EAAiCA,MACjC,EAAK8W,YAAc,EAAKC,IAAIC,iBAAiBC,YACzCze,GAASA,IAEbhC,EAAeG,QAAQ,mBAAoBqJ,IArI1B,EAwInBkX,IAAM,SAACxc,GACL,EAAKqc,IAAII,eAAe,CACtBC,EAAGxD,KAAKyD,MAAM3c,EAAOqa,wBAAwBE,MAC7CqC,EAAG1D,KAAKyD,MAAM3c,EAAOqa,wBAAwBI,OAE/C,EAAK4B,IAAI7H,SAAS,CAChBuF,aAAa,IAEf,EAAKvF,SAAS,CACZzL,MAAO/I,EAAOuc,YACdpB,OAAQnb,EAAO6c,aACfC,KAAM,eAnJS,EAuJnBC,MAAQ,WACN,EAAKV,IAAII,eAAe,CACtBG,EAAG1D,KAAKyD,MAAM,EAAKlC,KACnBiC,EAAGxD,KAAKyD,MAAM,EAAKpC,QAErB,EAAK8B,IAAI7H,SAAS,CAChBuF,aAAa,IAEf,EAAKvF,SAAS,CACZzL,MAAO,EAAKA,MACZoS,OAAQ,EAAKA,OACb2B,KAAM,YAlKS,EAsKnBE,QAAU,WACR,IAAIpG,EAAIqG,WAAW,EAAKxC,KACpByC,EAAID,WAAW,EAAK9B,QACpBgC,EAAI,EAAKd,IAAIC,iBAAiBc,cAAc/C,wBAC5CgD,EAAIzG,EAAIsG,EAERG,EAAIF,EAAElC,SACR,EAAKR,IAAM,EAAKA,IAAM4C,EAAIF,EAAElC,QAG9B,EAAKoB,IAAII,eAAe,CACtBG,EAAG1D,KAAKyD,MAAM,EAAKlC,OAErB,EAAK4B,IAAI7H,SAAS,CAChBuF,aAAa,IAEf,EAAKvF,SAAS,CACZ2G,OAAQ,EAAKA,OACb2B,KAAM,YAxLS,EA4LnBQ,SAAW,WACT,MAMI,EAAKrgB,MALPnB,EADF,EACEA,eACAyhB,EAFF,EAEEA,WACAC,EAHF,EAGEA,SACAC,EAJF,EAIEA,qBACAnY,EALF,EAKEA,MAKF,OAFAoY,yBAAiB,EAAKrB,IAAII,eAAe,CAAEG,EAAG,IAEtC,EAAKnJ,MAAMqJ,MACjB,IAAK,YAEiB,YAAhB,EAAK3B,SACP,EAAKA,OAAS,QAEhB,EAAK6B,UACL,MACF,IAAK,SAEHS,GACE,EAAKjB,IAAI7P,SAASgR,eAAe,sBACnC,MACF,IAAK,YAEH,EAAKZ,MAAMpQ,SAASgR,eAAe,sBAOjB,oBAAfJ,GAA6BA,IAChB,oBAAbC,GAA2BA,IAElC1hB,EAAeG,QAAQ,sBAAuBqJ,IAhO7B,EAmOnBsY,SAAW,WACT,MAAwD,EAAK3gB,MAArDnB,EAAR,EAAQA,eAAgB+hB,EAAxB,EAAwBA,WAAYL,EAApC,EAAoCA,SAAUlY,EAA9C,EAA8CA,MAE9CoY,yBACE,EAAKrB,IAAII,eAAe,CACtBG,EAAG1D,KAAKyD,MAAMzgB,OAAOmf,YAAc,MAIvC,EAAKF,OAAS,EAAK1H,MAAM0H,OACzB,EAAK3G,SAAS,CACZ2G,OAAQ,EACR2B,KAAM,cAIc,oBAAfe,GAA6BA,IAChB,oBAAbL,GAA2BA,IAElC1hB,EAAeG,QAAQ,sBAAuBqJ,IApP9CqH,SAASmR,QAAQ3R,KAAjB,gBACA,EAAK6P,UAAY7E,IAAM4G,YACvB,EAAKtK,MAAQ,CACX8G,KAAM,EACNE,IAAK,EACL1R,MAAO,IACPoS,OAA8B,YAAtB,EAAKle,MAAMke,OAAuB,OAAS,KAGrDjf,OAAO8hB,iBAAiB,UAAU,WACR,cAApB,EAAKvK,MAAMqJ,KACb,EAAKN,IAAI7P,SAASgR,eAAe,sBAEjC,EAAKlB,oBAfQ,E,qDA8BnB,WAAqB,IAAD,OACV3gB,EAAmBa,KAAKM,MAAxBnB,eACJA,IACFA,EAAemiB,UAAU,kBAAkB,WACzC,EAAKxB,oBAEP3gB,EAAemiB,UAAU,sBAAsB,WAC7C,EAAKxB,oBAEP3gB,EAAemiB,UAAU,mBAAmB,SAAClgB,GAC3C,EAAKse,IAAI7H,SAAS,CAChBuF,YAAahc,U,qCAoBrB,WACE,SAAOpB,KAAKM,MAAMihB,sBAChBvhB,KAAKM,MAAMihB,oBAAoB5K,eAAe,aAC5C3W,KAAKM,MAAMihB,oBAAoBlgB,QAAQmgB,kB,gCAI7C,WACE,QAAiBhO,IAAbxT,KAAK0f,IAAmB,OAAO,IACnC,IAAMnC,EAASvd,KAAK0f,IAAIC,iBAAiBc,cACnCgB,EAAsBzhB,KAAK0hB,0BAA4B,GAAK,EAOlE,OALEnE,EAAO2C,aACP,GACA,GACA,GACAuB,I,4BAIJ,WAAkB,IAAD,OACf,EAAoCzhB,KAAKM,MAAjC8L,EAAR,EAAQA,MAAOoS,EAAf,EAAeA,OAAQxG,EAAvB,EAAuBA,SACjBuF,EAASvd,KAAK0f,IAAIC,iBAAiBc,cAGzCzgB,KAAK4d,KAAO,GACZ5d,KAAK8d,IAAM,GACX9d,KAAKoM,MAAQA,GAAS,IACtBpM,KAAKwe,OAASA,GAAU,IAGE,YAAtBxe,KAAKM,MAAMke,QAAwC,SAAhBxe,KAAKwe,SAC1Cxe,KAAKwe,OAASxe,KAAK2hB,sBAIJ,UAAb3J,IACFhY,KAAK4d,KAAOL,EAAOG,wBAAwBtR,MAAQA,EAAQ,GAAK,IAI9D2U,0BACF/gB,KAAK4d,KAAO,EACZ5d,KAAK8d,IAAM,EACX9d,KAAKwe,OAASjf,OAAOmf,YACrB1e,KAAKoM,MAAQ4D,SAASgO,KAAK4B,aAG7B5f,KAAK4d,UAAqBpK,IAAdxT,KAAK4d,KAAqB5d,KAAK4d,KAAO,GAElD5d,KAAK6X,SACH,CACE+F,KAAM5d,KAAK4d,KACXE,IAAK9d,KAAK8d,IACV1R,MAAOpM,KAAKoM,MACZoS,OAAQxe,KAAKwe,OACb2B,KAAM,WAER,WACE,EAAKT,IAAII,eAAe,CACtBG,EAAG1D,KAAKyD,MAAM,EAAKlC,KACnBiC,EAAGxD,KAAKyD,MAAM,EAAKpC,a,0BA+H3B,WAAgB,IAAD,OACb5N,SAASmR,QACNlT,MAAK,SAACxF,EAAGyF,GAAJ,OAAWzF,IAAM,EAAO,EAAIyF,IAAM,GAAQ,EAAI,KACnD/H,SAAQ,SAACyb,EAAGC,GACPD,EAAElC,MACJkC,EAAElC,IAAIC,iBAAiBzX,MAAM4Z,OA1ZnB,IA0Z0CD,Q,oBAK5D,WAAU,IAAD,OACP,EAWI7hB,KAAKM,MAVPqC,EADF,EACEA,SACAsV,EAFF,EAEEA,QACAhM,EAHF,EAGEA,MACAyB,EAJF,EAIEA,SACAtM,EALF,EAKEA,KACAuH,EANF,EAMEA,MACAoZ,EAPF,EAOEA,gBACAC,EARF,EAQEA,gBACAlB,EATF,EASEA,qBACAmB,EAVF,EAUEA,yBAEF,EAAqCjiB,KAAK8W,MAAlC8G,EAAR,EAAQA,KAAME,EAAd,EAAcA,IAAK1R,EAAnB,EAAmBA,MAAOoS,EAA1B,EAA0BA,OAEtB0D,GAAe,EACjBC,GAAmB,EACnBC,GAAoB,EACpBC,GAAa,EACbC,GAAc,EACdC,GAAY,EACZC,GAAgB,EAChBC,GAAiB,EAgDnB,OA9CIC,WACFR,EACEC,EACAC,EACAE,EACAE,EACAC,EACAJ,GACE,GAEoB,cAApBriB,KAAK8W,MAAMqJ,OACb+B,EACEC,EACAC,EACAE,EACAC,EACAC,EACAC,EACAJ,GACE,GAEkB,cAApBriB,KAAK8W,MAAMqJ,OACb+B,EACEC,EACAC,EACAG,EACAC,EACAC,EACAJ,GACE,GAGDN,IACHG,EACEC,EACAC,EACAE,EACAC,EACAC,EACAC,EACAJ,GACE,IAIRriB,KAAK2iB,eAEH,cAAC,IAAD,CACEC,YAAa,SAAC7f,GACZ,EAAK4f,gBAEPE,YAAa,SAAC9f,GAAD,OAAOA,EAAE+f,mBACtBC,IAAK,SAACvC,GACJ,EAAKd,IAAMc,GAEbtY,MAAO,CACL8a,QAAS5hB,EAAO,QAAU,QAE5B6hB,WAAY,SAAClgB,EAAGmgB,GACd,IAAMC,EAAO,EAAKzD,IAAIC,iBAAiByD,iBAAiB,GACpDD,IACF,EAAKvF,KAAOuF,EAAKvF,KACjB,EAAKE,IAAMqF,EAAKrF,IAChB,EAAKK,MACH5e,OAAOkf,YAAc,EAAKb,KAAO0C,WAAW,EAAKlU,UAGvDiX,aAAc,SAACtgB,EAAGugB,EAAWP,EAAKQ,EAAOvL,GACvC,EAAK5L,MAAQ2W,EAAI7a,MAAMkE,MACC,cAApB,EAAK0K,MAAMqJ,OACb,EAAK3B,OAASuE,EAAI7a,MAAMsW,QAE1B,EAAK3G,SAAS,CACZzL,MAAO2W,EAAI7a,MAAMkE,MACjBoS,OAAQuE,EAAI7a,MAAMsW,SAEhB,EAAKle,MAAMugB,UAAU,EAAKvgB,MAAMugB,YAEtC2C,OAAO,cACPnG,OAAQ,qBACRoG,iBAAkBzB,GAA4BjB,wBAC9C2C,eAAgB,CACdpF,OAAQ4D,EACRyB,WAAYxB,EACZyB,YAAaxB,EACbxE,KAAMyE,EACNlE,MAAOmE,EACPxE,IAAKyE,EACLsB,QAASrB,EACTsB,SAAUrB,GAEZra,UAAW6P,EAAQ1Y,OACnBwb,SAAU,IACVgJ,UAA+B,cAApB/jB,KAAK8W,MAAMqJ,KAAuB,GAAK,IAClD/W,KAAM,CACJgD,MAAOA,EACPoS,OAAQA,GAEV9W,QAAS,CACPqY,EAAGnC,EACHqC,EAAGnC,EACH1R,MAAOA,EACPoS,OAAQA,GAvDZ,SA0DE,sBACEwF,SAAS,IACTjB,IAAK/iB,KAAKqf,UACVjX,UAAW6b,kBACThM,EAAQiM,aACc,YAAtBlkB,KAAKM,MAAMke,OACPvG,EAAQkM,4BACR,MAPR,UAUE,cAAC,UAAD,CACErD,qBAAsBA,EACtB7U,MAAOA,EACPmY,oBAAqBnC,EACrB9iB,eAAgBa,KAAKM,MAAMnB,eAC3BklB,cAAerkB,KAAKM,MAAM+jB,cAC1BljB,QAASnB,KAAKwf,MACdoB,WAAY5gB,KAAK2gB,SACjBO,WAAYlhB,KAAKihB,SACjBd,KAAMngB,KAAK8W,MAAMqJ,KACjBxX,MAAOA,IAET,yBACEP,UAAW6b,kBACThM,EAAQtC,QACR3V,KAAKM,MAAMgkB,WAAa,KAAOrM,EAAQsM,eAEzCrc,MAAO,CAELsc,UACExkB,KAAK2hB,uBAAqC,IAAbe,WAAqB,IAAM,KAR9D,SAWGhV,GAAYA,EAASlB,OAAS,EAC7B,cAAC,UAAD,CACEkB,SAAU1N,KAAKM,MAAMoN,SACrBrM,QAASrB,KAAKM,MAAMe,QACpBojB,UAAWzkB,KAAKM,MAAMmkB,UACtBtlB,eAAgBa,KAAKM,MAAMnB,gBAEzBmH,MAAMC,QAAQvG,KAAKM,MAAMoN,WACzB1N,KAAKM,MAAMoN,SAASlB,OAAS,EACzBxM,KAAKM,MAAMoN,SAAS,GAAG0B,QACvB,GAIRzM,a,GA/cO6X,IAAMC,eAArByE,EAqBGwF,aAAe,CACpB1C,iBAAiB,EACjBD,iBAAiB,EACjBjB,sBAAsB,EACtBwD,YAAY,GA+bD5J,uBArgBA,SAAC9Z,GACd,MAAO,CACLrB,OAAO,aACLuiB,OAtFc,IAsFQ9R,SAASmR,QAAQ3U,OACvCwL,SAAU,WACVvQ,WAAY7G,EAAMoG,QAAQS,WAAWkd,MACrCC,UAAWhkB,EAAMikB,QAAQ,IACzBhJ,aAAcjb,EAAMgb,MAAMC,aAC1BhP,SAAU,SACViY,cAAe,OACdlkB,EAAMI,YAAYC,KAAK,MAAQ,CAC9B4a,aAAc,IACd7D,SAAU,qBAGdkM,aAAc,CACZlB,QAAS,OACThL,SAAU,WACV8F,IAAK,EACLF,KAAM,EACNU,OAAQ,EACRH,MAAO,EACP4G,cAAe,SACfC,WAAY,OACZC,QAAS,OACT,0BAA2B,CACzBhZ,MAAOrL,EAAMoG,QAAQ+U,QAAQmJ,QAGjCf,4BAA6B,CAC3BnB,QAAS,YAEXrN,QAAS,CACPwP,KAAM,IACNC,UAAW,OACX7d,QAAS,OACT2I,OAAQ,sBAEVqU,cAAe,CACba,UAAW,SACX7d,QAAS,UA6dAmT,CAAmBwE,I,oECrgBlC,SAASmG,EAAQliB,GAIf,OAHIA,EAAMmiB,QAAQ,OAAS,IACzBniB,EAAK,UAAMA,EAAMoiB,OAAO,EAAG,GAAtB,YAA4BpiB,EAAMoiB,OAAO,EAAG,GAA5C,YAAkDpiB,EAAMoiB,OAAO,EAAG,KAElEpiB,EAGT,IAAMqiB,EAAU,I,WAlGd,aAEE,OAFa,oBACbxlB,KAAKwlB,QAAU,GACRxlB,K,gDAGT,SAAaoE,EAAYqhB,GAAQ,IAAD,OAC1BC,EAAOD,EAAM9T,MAAM,KACjB9N,EAAM6hB,EAAKC,QAAQpY,OAErBpK,EAAQ,KAgCZ,OA9ByB,IAArBU,EAAIyhB,QAAQ,KAGdniB,EAAQU,EAAIgR,UAAU,EAAGhR,EAAI2I,OAAS,IAEtCrJ,EAAQiB,EAAWP,MAEjBV,EAAQ,IAIZuiB,EAAKvf,SAAQ,SAACyf,GAEZ,IAAMC,EAAYD,EAASN,QAAQ,KAC/BQ,EAAaF,EACbF,EAAO,GAEPG,GAAa,IACfC,EAAaF,EAASL,OAAO,EAAGM,IAChCH,EAAOE,EACJ/Q,UAAUgR,EAAY,EAAGD,EAASN,QAAQ,MAC1C3T,MAAM,MACJxL,SAAQ,SAAC4P,EAAG8L,EAAGpZ,GAClBA,EAAEoZ,GAAK,EAAKkE,YAAYhQ,EAAExI,YAI9BpK,EAAQ,EAAK6iB,WAAWF,EAAY3iB,EAAOuiB,MAGtCviB,I,wBAGT,SAAW2iB,EAAY3iB,EAAOuiB,GAC5B,IAAMlV,EAASxQ,KAAK2Q,IAAImV,GAExB,GAAItV,EACF,IACE,OAAOA,EAAOyV,KAAKC,MAAMlmB,KAAlB,CAAyBmD,GAAzB,mBAAmCuiB,KAC1C,MAAOhS,GACPC,QAAQwS,KAAR,sDACiDL,EADjD,sBACyE3iB,EADzE,sBAC4FuiB,EAD5F,KAEEhS,GAKN,OAAOvQ,I,yBAGT,SAAYijB,GAKV,OAHuB,IAAnBA,EAAEd,QAAQ,OACZc,EAAIA,EAAEvR,UAAU,EAAGuR,EAAE5Z,OAAS,IAEzB4Z,I,iBAGT,SAAIviB,GACF,OAAI7D,KAAKwlB,QAAQ3hB,GACR7D,KAAKwlB,QAAQ3hB,IAEpB8P,QAAQwS,KAAR,+DAC0DtiB,EAD1D,MAIK,Q,iBAGT,SAAIA,EAAK+L,GACP5P,KAAKwlB,QAAQ3hB,GAAO,CAClBoiB,KAAMrW,K,sBAIV,SAAS/L,EAAKwiB,GACZrmB,KAAKsmB,IAAIziB,EAAK7D,KAAK2Q,IAAI0V,GAAWJ,U,MAqBtCT,EAAQc,IAAI,mBAAmB,SAAUnjB,EAAOojB,GAC9C,GAAIC,MAAMrjB,IAAUqjB,MAAMD,GACxB,MAAM,IAAIE,MAAM,+BAElB,OAAOnG,WAAWnd,EAAMujB,QAAQ7mB,SAAS0mB,KAAeI,oBAS1DnB,EAAQc,IAAI,WAAW,SAAUnjB,EAAOhD,EAASymB,GAC/C,OAAOzjB,EAAMhD,QAAQ,IAAI0mB,OAAO1mB,EAAS,MAAOymB,MASlDpB,EAAQc,IAAI,WAAW,SAAUnjB,EAAO2jB,GACtC,MAAiB,KAAV3jB,EAAe2jB,EAAe3jB,KAEvCqiB,EAAQuB,SAAS,WAAY,WAW7BvB,EAAQc,IAAI,MAAM,SAAUnjB,EAAOuR,EAAMsS,EAAWC,GAClD,OAAIT,MAAMrjB,IAAUqjB,MAAM9R,GACjBvR,GAEoB,kBAAVA,EAAqBmd,WAAWnd,GAASA,IAClC,kBAATuR,EAAoB4L,WAAW5L,GAAQA,GAG1B,kBAAdsS,GAA+C,IAArBA,EAAUxa,OAC9CrJ,EACA6jB,EAE2B,kBAAjBC,GAAqD,IAAxBA,EAAaza,OACpDrJ,EACA8jB,KAURzB,EAAQc,IAAI,UAAU,SAAUnjB,EAAOuR,EAAMwS,EAAWC,GACtD,OAAOhkB,IAAUuR,EAAOwS,EAAYC,GAAchkB,KASpDqiB,EAAQc,IAAI,aAAa,SAAUnjB,EAAOuR,EAAMyS,EAAYD,GAC1D,OAAO/jB,IAAUuR,EAAOyS,EAAaD,GAAa/jB,KASpDqiB,EAAQc,IAAI,YAAY,SAAUnjB,GAEhC,OAD8B,kBAAVA,EAAqB,IAAIikB,KAAKjkB,GAASA,GAC/CwjB,oBASdnB,EAAQc,IAAI,QAAQ,SAAUnjB,GAG5B,OAD8B,kBAD9BA,EAAQkiB,EAAQliB,IACyB,IAAIikB,KAAKjkB,GAASA,GAC/CkkB,wBASd7B,EAAQc,IAAI,QAAQ,SAAUnjB,GAE5B,OAD8B,kBAAVA,EAAqB,IAAIikB,KAAKjkB,GAASA,GAC/CmkB,wBAUd9B,EAAQc,IAAI,eAAe,SAAUnjB,EAAOokB,GAE1C,IAAMC,EAAwB,kBAD9BrkB,EAAQkiB,EAAQliB,IACyB,IAAIikB,KAAKjkB,GAASA,EAE3D,OADAqkB,EAAKC,QAAQD,EAAKE,UAAYpH,WAAWiH,IAClCC,KAUThC,EAAQc,IAAI,gBAAgB,SAAUnjB,EAAOwkB,GAE3C,IAAMH,EAAwB,kBAD9BrkB,EAAQkiB,EAAQliB,IACyB,IAAIikB,KAAKjkB,GAASA,EAE3D,OADAqkB,EAAKI,QAAQJ,EAAKK,UAAgC,GAApBvH,WAAWqH,GAAc,GAAK,KACrDH,KASThC,EAAQc,IAAI,gBAAgB,SAAUnjB,GACpC,GAAIqjB,MAAMrjB,GACR,MAAM,IAAIsjB,MAAM,+BAElB,OAAOzb,OAAO7H,GAAOwjB,oBASvBnB,EAAQc,IAAI,WAAW,SAAUnjB,GAC/B,OAAOA,EAAM2kB,iBASftC,EAAQc,IAAI,WAAW,SAAUnjB,GAC/B,OAAOA,EAAM4kB,iBASfvC,EAAQc,IAAI,cAAc,SAAUnjB,GAClC,OAAOA,EAAM6kB,OAAO,GAAGF,cAAgB3kB,EAAM8kB,MAAM,MASrDzC,EAAQc,IAAI,UAAU,SAAUnjB,EAAO+kB,EAAIC,GACzC,OAAOhlB,EAAMoiB,OAAO2C,EAAIC,MAS1B3C,EAAQc,IAAI,aAAa,SAAUnjB,EAAO+kB,EAAIC,GAC5C,OAAOhlB,EAAM0R,UAAUqT,EAAIC,MAS7B3C,EAAQc,IAAI,QAAQ,SAAUnjB,EAAOilB,GACnC,OAAOjlB,EAAMwO,MAAMyW,GAAW,MAShC5C,EAAQc,IAAI,SAAS,SAAUnjB,EAAOilB,GACpC,IAAMvG,EAAI1e,EAAMmiB,QAAQ8C,GACxB,OAAOvG,GAAK,EAAI1e,EAAM0R,UAAUgN,EAAIuG,EAAU5b,OAAQrJ,EAAMqJ,QAAUrJ,KASxEqiB,EAAQc,IAAI,QAAQ,SAAUnjB,GAC5B,OAAOA,EAAMoK,UAGAiY,a,iCCpVf,sDAAO,IAAM6C,EAAiB,SAAChmB,GAC7B,OACG2I,OAAOwb,MAAMxb,OAAO3I,KACrB,kBAAkBqS,KAAKrS,IACvB,iBAAiBqS,KAAKrS,K,iCCJ1B,6CAAO,IAAMimB,EAAQ,SAACC,GAAD,OAAQ,IAAIrV,SAAQ,SAACoC,GAAD,OAAa8J,WAAW9J,EAASiT,Q,wJCapEC,E,4MACJ1R,MAAQ,G,EAeR7U,YAAc,SAACc,GACb,EAAKzC,MAAMid,OAAO1F,SAAS,CACzB4Q,OAAO,K,4CAIX,WACE,MAAuCzoB,KAAKM,MAApCc,EAAR,EAAQA,KAAMsnB,EAAd,EAAcA,YAAaC,EAA3B,EAA2BA,QAC3B,OACE,eAAC,IAAD,CACEvnB,KAAMA,EACND,QAASnB,KAAKiC,YACdE,kBAAgB,qBAChBymB,mBAAiB,2BAJnB,UAME,cAAC,IAAD,CAAavmB,GAAG,qBAAhB,SACGqmB,GAAe,eAElB,cAAC,IAAD,UAAgBC,IAChB,cAAC,IAAD,UACE,cAAC,IAAD,CAAQjlB,QAAS1D,KAAKiC,YAAagK,MAAM,UAAU1I,WAAS,EAA5D,yB,GApCciX,IAAMC,eAAxB+N,EAWG9D,aAAe,CACpBiE,QAAS,oBACThgB,MAAO,gBAgCI+R,uBAjDA,SAAC9Z,GACd,MAAO,KAgDM8Z,CAAmB8N,I,iCC1DlC,sLAWA,SAASK,EAAerI,GACtB,IAAIsI,EAAMtI,EAAEuI,SAAS,IACrB,OAAsB,IAAfD,EAAItc,OAAe,IAAMsc,EAAMA,EAOxC,SAASE,EAAa/c,EAAOvC,GAC3B,IAAIuf,EAAM,GACRC,EAAe,QAATxf,EAAiB,cAAgB,eAczC,OAZIpD,MAAMC,QAAQ0F,GAChBgd,EAAMhd,GAENgd,EAAMC,EACHC,KAAKld,GAAO,GACZ0F,MAAM,KACN3C,KAAI,SAACvG,GAAD,OAAO6X,WAAW7X,MACZ,QAATiB,GACFuf,EAAIzZ,KAAK,IAINyZ,EAGT,SAASG,EAAWnd,GAClB,IAAIma,EAAGlQ,EAAGmT,EAAGnb,EAAGwS,EAEVuI,EADN,GAAIhd,EAuBF,OArBI3F,MAAMC,QAAQ0F,GAChBgd,EAAMhd,EAEF,QAAQyI,KAAKzI,GACfgd,EAAMD,EAAa/c,EAAO,QACjB,OAAOyI,KAAKzI,KACrBgd,EAAMD,EAAa/c,EAAO,QAQ9BiK,GAJEkQ,EADE9f,MAAMC,QAAQ0iB,GApCtB,SAAkB/S,EAAGmT,EAAGnb,GACtB,OAAO2a,EAAe3S,GAAK2S,EAAeQ,GAAKR,EAAe3a,GAoCtDob,CAASL,EAAI,GAAIA,EAAI,GAAIA,EAAI,IAE7Bhd,EAAQA,EAAM9L,QAAQ,IAAK,KAE3BolB,OAAO,EAAG,GAChB8D,EAAIjD,EAAEb,OAAO,EAAG,GAChBrX,EAAIkY,EAAEb,OAAO,EAAG,GAChB7E,EAAI,KACAuI,GAAOA,EAAI,KACbvI,EAAInE,KAAKgN,MAAe,IAATN,EAAI,IAAUF,SAAS,KAEjCrI,EAAIxS,EAAImb,EAAInT,EAIvB,SAASsT,EAAYlV,EAAK5K,GACxB,IACEjB,EACAyF,EAFEub,EAAO,GAIX,OAAQ/f,GACN,IAAK,QAIH4K,GADAA,GADAA,GADAA,EAAMA,EAAInU,QAAQ,WAAY,IAAIA,QAAQ,MAAO,KACvCA,QAAQ,aAAc,IAAIA,QAAQ,MAAO,KACzCA,QAAQ,gBAAiB,IAAIA,QAAQ,MAAO,KAC5CA,QAAQ,kBAAmB,IAAIA,QAAQ,MAAO,IACxD,MACF,IAAK,OAEHmU,GADAA,EAAMA,EAAInU,QAAQ,gBAAiB,IAAIA,QAAQ,MAAO,KAC5CA,QAAQ,kBAAmB,IAAIA,QAAQ,MAAO,IACxD,MACF,IAAK,UACHspB,EAAOnV,EAAI3C,MAAM,OACjB2C,EAAM,GACNmV,EAAKtjB,SAAQ,SAACujB,EAAQ7H,GACV,IAANA,GAEF6H,GADAA,EAASA,EAAOvpB,QAAQ,eAAgB,IAAIA,QAAQ,MAAO,KAC3CA,QAAQ,iBAAkB,IAAIA,QAAQ,MAAO,IAC7DmU,GAAO,oBACPA,GAAO,eACPA,GAAO,gBAAkBoV,EAAS,iBAClCpV,GAAO,gBACPA,GAAO,uBAEPoV,EAASA,EAAOvpB,QAAQ,MAAO,IAC/BmU,GAAO,oBACPA,GAAO,eACPA,GAAO,gBAAkBoV,EAAS,iBAClCpV,GAAO,gBACPA,GAAO,yBAGX,MACF,IAAK,eACH7L,EAAI6L,EAAI3C,MAAM,SACd2C,EAAM,GACN7L,EAAEtC,SAAQ,SAACujB,EAAQzP,GACP,IAANA,IAEFyP,GADAA,EAASA,EAAOvpB,QAAQ,oBAAqB,IAAIA,QAAQ,MAAO,KAE7DA,QAAQ,wBAAyB,IACjCA,QAAQ,MAAO,KAGpB+N,EAAIwb,EAAO/X,MAAM,OAEjB2C,GAAO,YACPpG,EAAE/H,SAAQ,SAACwjB,EAAa9H,GACtB8H,EAAcA,EACXxpB,QAAQ,MAAO,IACfwR,MAAM,KACN3C,KAAI,SAAC4a,GACJ,IAAIF,EAASE,EAAYjY,MAAM,KAC/B,OAAO+X,EAAO,GAAK,IAAMA,EAAO,MAG1B,IAAN7H,GACFvN,GAAO,oBACPA,GAAO,eACPA,GAAO,gBAAkBqV,EAAc,iBACvCrV,GAAO,gBACPA,GAAO,uBAEPA,GAAO,oBACPA,GAAO,eACPA,GAAO,gBAAkBqV,EAAc,iBACvCrV,GAAO,gBACPA,GAAO,yBAGXA,GAAO,gBAET,MACF,IAAK,YAGH,IAAIuV,GADJvV,GADAA,EAAMA,EAAInU,QAAQ,qBAAsB,IAAIA,QAAQ,MAAO,KACjDA,QAAQ,uBAAwB,IAAIA,QAAQ,MAAO,KAC7CwR,MAAM,OACtBkY,EAAQA,EAAM7a,KAAI,SAAC8a,GACjB,OAAOA,EAAK3pB,QAAQ,QAAS,QAEzBgG,SAAQ,SAAC2jB,GACbxV,GAAG,mCAAgCwV,EAAhC,kCAOT,OAAOxV,EACJnU,QAAQ,KAAM,KACdA,QAAQ,KAAM,KACdA,QAAQ,KAAM,KACdA,QAAQ,MAAO,IACfA,QAAQ,MAAO,IAGpB,SAAS4pB,EAAMna,GACb,IAAI0E,EAAM,GAIV,OAHAA,GAAO,UACPA,GAAO,gBAAkBkV,EAAY5Z,EAAG,SAAW,iBACnD0E,GAAO,WAoDF,SAAS0V,EAAUtc,EAAUuc,EAAMC,GACxC,OAAOxc,EAASsB,KAAI,SAACnE,GACnB,IAAI2V,EAAI3V,EAAQsf,QACdjiB,EAAQ5B,MAAMC,QAAQsE,EAAQuf,YAC1Bvf,EAAQuf,WAAW,GACnBvf,EAAQuf,WAKd,OAJA5J,EAAElV,cAAc0e,UAAUC,EAAMC,GAChC1J,EAAE6J,SAASniB,GACXsY,EAAElc,QAAUuG,EAAQvG,QACpBkc,EAAEhJ,QAAU3M,EAAQ2M,QACbgJ,KAIJ,SAAS8J,EAAU5c,EAAU6c,GAClC,IAAIC,EAAS,GACXxc,EAAS,IAAIyc,IACbC,EAAM,GAiIR,OA/HAF,GACE,gLACFE,GAAO,aACPA,GAAO,SAAWH,EAAO,UAEzBG,GAAO,WACPA,GAAO,SAAWH,EAAO,UACzBG,GAAO,iBAEPhd,EAASvH,SAAQ,SAAC0E,EAASgX,GACzB,IAAI3Z,EAAQ5B,MAAMC,QAAQsE,EAAQuf,YAC9Bvf,EAAQuf,WAAW,IAAMvf,EAAQuf,WAAW,GAC5Cvf,EAAQuf,WAGZ,GADAM,GAAO,cAAgB7I,EAAI,KACvB3Z,EAAMyiB,qBAAsBre,IAAM,CAAC,IAAD,IAC9BpB,EAAK,iBACThD,QADS,IACTA,GADS,UACTA,EAAOyiB,kBADE,aACT,EAAmBC,kBADV,QACwB1iB,EAAMyiB,WAAWE,UAAU,GAAK,GACnEH,GAAO,cACPA,GAAO,UAAYxf,EAAQ,WAC3Bwf,GAAO,SACPA,GAAO,SAAWxiB,EAAMyiB,WAAWG,SAAW,UAC9CJ,GAAO,UACPA,GAAO,eAGLxiB,EAAM6iB,sBAAuB5e,MAC/Bue,GAAO,cACPA,GAAO,UAAYtB,EAAWlhB,EAAM6iB,YAAYC,YAAc,WAC9DN,GAAO,UAAYxiB,EAAM6iB,YAAYE,WAAa,WAClDP,GAAO,gBAGLxiB,EAAMgjB,oBAAqBlf,MAC7B0e,GAAO,cACPA,GAAO,UAAYtB,EAAWlhB,EAAMgjB,UAAUF,YAAc,WAC5DN,GAAO,gBAGTA,GAAO,cAGThd,EAASvH,SAAQ,SAAC0E,EAASgX,GACzB,IAAI3Z,EAAQ5B,MAAMC,QAAQsE,EAAQuf,YAC9Bvf,EAAQuf,WAAW,IAAMvf,EAAQuf,WAAW,GAC5Cvf,EAAQuf,WAER7pB,EAAO2H,EAAMijB,UAAYjjB,EAAMijB,UAAUA,UAAY,GAErDC,EAAcvgB,EAAQ+C,gBAAgBwd,aAAe,GACvDb,EACE1f,EAAQ+C,gBAAgByd,MACxBxgB,EAAQ+C,gBAAgB2c,MACxB1f,EAAQvG,SACR/D,EAEJ,IAAK6qB,GAAevgB,EAAQ+C,gBAAiB,CAC3Cwd,EAAc,UACd,IAAIhnB,EAAayG,EAAQ+C,gBAErB/C,EAAQ2M,UACVpT,EA3FR,SAA0BknB,EAAUlnB,GAClC,IAAI9D,EAAQ,GAOZ,OANA2F,OAAOC,KAAK9B,GAAY+B,SAAQ,SAACiQ,GAClB,IAAIyQ,OAAJ,kBAAsBzQ,EAAtB,MACF1B,KAAK4W,KACdhrB,EAAM8V,GAAYhS,EAAWgS,OAG1B9V,EAmFYirB,CAAiB1gB,EAAQ2M,QAASpT,IAGjD6B,OAAOC,KAAK9B,GAAY+B,SAAQ,SAACiQ,GAEZ,kBAAVjT,OACU,kBAAVA,OACU,mBAAVA,QAEPioB,GAAe,OACfA,GAAe,OAAShV,EAAW,QACnCgV,GAAe,QAAoBhnB,EAAWgS,GA1GtC2S,WACF5oB,QAAQ,oBAAqB,IAyGwB,SAC3DirB,GAAe,YAInBA,GAAe,WAGjBV,GAAO,cACPA,GAAO,UAAYH,GAAQ,cAAgB1I,EAAI,IAAM,UACrD6I,GACE,iBACCU,GAAe,cAAgBvJ,EAAI,IACpC,iBACF6I,GAAO,cAAgB7I,EAAI,cAEvBhX,EAAQS,wBAAyBC,MACnCmf,GAAOX,EAAM/b,EAAOwd,aAAa3gB,KAE/BA,EAAQS,wBAAyBmgB,MACnCf,GAAOX,EAAM/b,EAAOwd,aAAa3gB,KAE/BA,EAAQS,wBAAyBogB,MACnChB,GAlKN,SAAc9a,GACZ,IAAI0E,EAAM,GAIV,OAHAA,GAAO,eACPA,GAAO,gBAAkBkV,EAAY5Z,EAAG,QAAU,iBAClD0E,EAAO,gBA8JIwV,CAAK9b,EAAOwd,aAAa3gB,KAE9BA,EAAQS,wBAAyBqgB,MACnCjB,GA7IN,SAAmB9a,GACjB,IAAI0E,EAAM,GAIV,OAHAA,GAAO,kBACPA,GAAOkV,EAAY5Z,EAAG,aACtB0E,EAAO,mBAyIIsX,CAAU5d,EAAOwd,aAAa3gB,KAEnCA,EAAQS,wBAAyBugB,MACnCnB,GAhKN,SAAiB9a,GACf,IAAI0E,EAAM,GAIV,OAHAA,GAAO,YACPA,GAAOkV,EAAY5Z,EAAG,WACtB0E,EAAO,aA4JIwX,CAAQ9d,EAAOwd,aAAa3gB,KAEjCA,EAAQS,wBAAyBygB,MACnCrB,GA3JN,SAAsB9a,GACpB,IAAI0E,EAAM,GAIV,OAHAA,GAAO,kBACPA,GAAOkV,EAAY5Z,EAAG,gBACtB0E,EAAO,mBAuJI0X,CAAahe,EAAOwd,aAAa3gB,KAGtCA,EAAQ+C,gBAAgB1F,QAC1BwiB,GAAO,iBACPA,GAAO,sBACPA,GAAO,UAAY7f,EAAQ+C,gBAAgB1F,MAAQ,WACnDwiB,GAAO,UACH7f,EAAQ+C,gBAAgBqe,eAC1BvB,GAAO,6BACPA,GAAO,UAAY7f,EAAQ+C,gBAAgBqe,aAAe,WAC1DvB,GAAO,WAETA,GAAO,mBAETA,GAAO,kBAGTA,GAAO,YAEPF,GADAE,GAAO,cAEPF,GAAU,W,4MC1VN0B,E,4MAYJC,0BAA4B,WAE1B,OADgC,EAAK7rB,MAA7B8jB,oBACmBpV,KAAI,SAACod,EAAY3V,GAC1C,IAAM4V,EAAmBD,EAAWE,KAAK5iB,KACnC0hB,EAAcgB,EAAWhB,YAC/B,OACE,eAAC,IAAD,CAEE1nB,QAAS0oB,EAAWG,gBACpBnjB,KAAK,QAHP,UAKE,cAAC,IAAD,CAAYxB,QAAQ,SAApB,SAA8BwjB,IAC9B,cAACiB,EAAD,MALK5V,O,EAWb+V,gCAAkC,WAChC,IAAQpI,EAAwB,EAAK9jB,MAA7B8jB,oBACR,OAAOA,GAAuBA,EAAoB5X,OAAS,G,4CAG7D,WACE,MAAgDxM,KAAKM,MAA7CwgB,EAAR,EAAQA,qBAAsB7I,EAA9B,EAA8BA,QAASkI,EAAvC,EAAuCA,KACvC,OACE,yBACE/X,UAAW6P,EAAQuS,OACnBtiB,MAAO,CAAEukB,YAAazsB,KAAKM,MAAM2L,OAFnC,UAIE,cAAC,IAAD,CAAY9C,UAAU,KAAKvB,QAAQ,SAASS,MAAM,OAAOoR,QAAQ,EAAjE,SACGzZ,KAAKM,MAAMqI,QAEd,eAAC,IAAD,CAAKqa,QAAQ,OAAO7Z,UAAU,MAA9B,UACGnJ,KAAKwsB,mCACJxsB,KAAKmsB,4BACG,cAAThM,IACW,cAATA,EACC,eAAC,IAAD,CAAY/W,KAAK,QAAQ1F,QAAS1D,KAAKM,MAAMsgB,WAA7C,UACE,cAAC,IAAD,CAAYhZ,QAAQ,SAApB,iCACA,cAAC,IAAD,OAKF,eAAC,IAAD,CAAYwB,KAAK,QAAQ1F,QAAS1D,KAAKM,MAAM4gB,WAA7C,UACE,cAAC,IAAD,CAAYtZ,QAAQ,SAApB,iCACA,cAAC,IAAD,QAGN,cAAC,IAAD,CAAQ8kB,QAAM,EAAd,SACG5L,GACC,eAAC,IAAD,CAAY1X,KAAK,QAAQ1F,QAAS1D,KAAKM,MAAMsgB,WAA7C,UACE,cAAC,IAAD,CAAYhZ,QAAQ,SAApB,iCACA,cAAC,IAAD,SAKN,eAAC,IAAD,CAAYwB,KAAK,QAAQ1F,QAAS1D,KAAKM,MAAMa,QAA7C,UACE,cAAC,IAAD,CAAYyG,QAAQ,SAApB,iCACA,cAAC,IAAD,iB,GAzEc+kB,aAiFXjS,uBA/FA,SAAC9Z,GACd,MAAO,CACL4pB,OAAQ,CACNjjB,QAAQ,GAAD,OAAK3G,EAAM4G,QAAQ,GAAnB,cAA2B5G,EAAM4G,QAAQ,GAAzC,MACPolB,aAAa,aAAD,OAAehsB,EAAMoG,QAAQ+U,QAAQC,MACjDgJ,WAAY,OACZhC,QAAS,OACT7J,WAAY,SACZ0T,eAAgB,gBAChB9I,UAAW,OAsFFrJ,CAAmBwR,I,wUCjF5BY,E,kDA0FJ,WAAYxsB,GAAQ,IAAD,sCACjB,cAAMA,IA1FRysB,qBAAuB,CACrB3f,wBAAwB,EACxB4f,uBAAuB,EACvBC,iBAAiB,EACjBC,eAAe,EACfC,WAAW,EACXC,oBAAqB,aACrBC,qBAAuB7G,MAAM,EAAKlmB,MAAMe,QAAQgsB,sBAE5C,IADA,EAAK/sB,MAAMe,QAAQgsB,sBAiFN,EA7EnBvW,MAAQ,CACNwW,gCAAgC,EAChCC,cAAe,GACfC,cAAe,CAAEC,mBAAoB,GAAIC,OAAQ,IACjDC,iBAAkB,GAClBC,aAAc,GACdC,wBAAwB,EACxBC,aAAc,GACdC,kBAAkB,EAClBC,SAAS,EACTC,cAAetqB,UAAmBgN,IAChC,gBACA,EAAKoc,sBAEPmB,sBAAuB,GACvBC,sBAAsB,GA8DL,EA1DnBC,MAAQ,KA0DW,EAvDnBC,uBACsD,IAApD7H,MAAM,EAAKlmB,MAAMe,QAAQgtB,uBACrB,EAAK/tB,MAAMe,QAAQgtB,sBACnB,IAoDa,EAlDnBC,yBAA2B,GAkDR,EAjDnBC,iBAAmB,GAiDA,EAhDnBlK,cAAgBmK,MAgDG,EA9CnBC,YAAc,KA8CK,EA5CnBC,mBAAqB,CACnB,CACEnE,KAAM,qBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,UACNilB,QAAO,UAAE,EAAKruB,MAAMe,QAAQutB,2BAArB,SACPC,aACE,uEACFC,iBAAkB,iCAEpB,CACEvE,KAAM,mBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,SACNilB,QAAO,UAAE,EAAKruB,MAAMe,QAAQ0tB,0BAArB,SACPF,aAAc,qEACdC,iBAAkB,iCAEpB,CACEvE,KAAM,oBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,SACNilB,QAAO,UAAE,EAAKruB,MAAMe,QAAQ2tB,0BAArB,SACPH,aACE,mFACFC,iBAAkB,iCAEpB,CACEvE,KAAM,kBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,SACNilB,QAAO,UAAE,EAAKruB,MAAMe,QAAQ4tB,0BAArB,SACPJ,aAAc,mEACdC,iBAAkB,iCAEpB,CACEvE,KAAM,yBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,WACNmlB,aAAc,qCACdC,iBAAkB,KAIH,EAUnBI,iBAAmB,WACjB,IAAQvV,EAAQ,EAAKrZ,MAAbqZ,IACR,EAAKwV,aAAe,IAAIC,UAAa,CAGnC/tB,QAAQ,2BACH,EAAKf,MAAMe,SACX,EAAKyV,MAAMmX,eAEhB5J,cAAe,EAAKA,cACpBrV,IAAK,EAAKA,IACV2K,IAAKA,KArBU,EAyBnB0V,mBAAqB,WACnB,EAAKC,UAAY,IAAIC,UAAU,CAC7BluB,QAAS,EAAKf,MAAMe,QACpBgjB,cAAe,EAAKA,cACpBrV,IAAK,EAAKA,MAEZ,EAAKwgB,WAAa,IAAIA,UAAW,CAC/BnuB,QAAS,EAAKf,MAAMe,QACpBgjB,cAAe,EAAKA,iBAjCL,EAqCnBoL,sBAAwB,WACtB,EAAKlB,iBAAmB,IAtCP,EAyCnBmB,oBAAsB,SAACC,GACrB,EAAKpB,iBAAmBoB,GA1CP,EA6CnBC,kBAAoB,WAClB,EAAKvL,cAAc/C,UAAU,iBAAiB,SAAC5X,GAChC,WAATA,EACF,EAAK+kB,YAAc,EAAKnuB,MAAMuvB,gBAC5B,mFACA,CACEjoB,QAAS,cACTkoB,aAAc,CAAEC,SAAU,SAAUC,WAAY,YAGlC,YAATtmB,IACT,EAAK+kB,YAAc,EAAKnuB,MAAMuvB,gBAC5B,2IACA,CACEjoB,QAAS,cACTkoB,aAAc,CAAEC,SAAU,SAAUC,WAAY,aAItD,EAAKnY,SAAS,CAAEiW,aAAc,YAEhC,EAAKzJ,cAAc/C,UAAU,eAAe,SAACzW,GAC3C,EAAKolB,iBAAiB,CAACplB,OAEzB,EAAKwZ,cAAc/C,UAAU,0BAA0B,WACrD,EAAKmN,YAAc,EAAKnuB,MAAMuvB,gBAC5B,0HACA,CACEjoB,QAAS,cACTkoB,aAAc,CAAEC,SAAU,SAAUC,WAAY,YAIpD,EAAKnY,SAAS,CAAEiW,aAAc,oBAEhC,EAAKzJ,cAAc/C,UAAU,4BAA4B,SAAC5T,GACxD,EAAKuiB,iBAAiBviB,MAExB,EAAK2W,cAAc/C,UAAU,wBAAwB,SAAC5T,GACpD,EAAKmK,SAAS,CAAEiW,aAAc,iBAC9B,EAAKmC,iBAAiBviB,MAExB,EAAK2W,cAAc/C,UAAU,4BAA4B,WACvD,EAAKzJ,SAAS,CAAEsW,sBAAsB,OAExC,EAAK9J,cAAc/C,UAAU,wBAAwB,WACnD,EAAKmN,YAAc,EAAKnuB,MAAMuvB,gBAC5B,sFACA,CACEjoB,QAAS,UACTkoB,aAAc,CAAEC,SAAU,MAAOC,WAAY,gBA/FlC,EAqGnBC,iBAAmB,SAACviB,GAClB,EAAKpN,MAAM4vB,cAAc,EAAKzB,aAC9B,EAAKiB,oBAAoBhiB,GACzB,EAAKyiB,YAxGY,EA2GnBC,mCAAqC,WACnC,IAAQzW,EAAQ,EAAKrZ,MAAbqZ,IACR,OAAO1T,OAAOuL,OAAOmI,EAAIC,SAASyW,SAAS7f,QAAO,SAAC8f,GACjD,OACEA,EAAOjvB,QAAQkvB,mBACfD,EAAOE,gBAAgBC,qBAhHV,EAqHnBC,qBAAuB,SAACL,GACtB,OAAOA,EAAQrhB,KAAI,SAACshB,GAClB,OAAOA,EAAOE,gBAAgBC,iBAAiBzd,MAAK,SAAC2d,GAGnD,OAFAL,EAAOE,gBAAgBI,iBAAvB,OAA0CD,QAA1C,IAA0CA,OAA1C,EAA0CA,EAASC,iBACnDN,EAAOE,gBAAgBK,WAAvB,OAAoCF,QAApC,IAAoCA,OAApC,EAAoCA,EAASE,WACtCP,SA1HM,EA+HnBQ,kCAAoC,SAACT,GACnC,OAAOA,EAAQ7f,QAAO,SAAC8f,GACrB,IAAMO,EAAaP,EAAOE,gBAAgBK,WACpCD,EAAmBN,EAAOE,gBAAgBI,iBAIhD,OAHKC,GAAeD,GAClB,EAAKG,0CAA0CT,GAE1CO,GAAcD,MAtIN,EA0InBG,0CAA4C,SAACT,GAAY,IAAD,EACtD3c,QAAQwS,KAAR,oBAEImK,EAAO5mB,YAFX,QAEmB,wBAFnB,wcA3IiB,EA6JnBsnB,4BAA8B,WAC5B,IAAMC,EACJ,EAAKb,qCACDc,EAAqB,EAAKR,qBAC9BO,GAEF,OAAO/d,QAAQC,IAAI+d,GAAoBle,MAAK,SAACqd,GAC3C,OAAO,EAAKS,kCAAkCT,OApK/B,EAwKnBc,uBAAyB,SAACC,GAMxB,OAAOA,EACJ5gB,QAAO,SAAC6gB,GACP,OAAOA,EAAwBb,gBAAgBI,sBAEhD5hB,KAAI,SAACsiB,GACJ,OAAOA,EAAsBd,gBAAgBI,uBAnLhC,EAuLnBW,eAAiB,SAACH,GAChB,OAAO,EAAK1C,mBAAmBloB,OAC7B,EAAK2qB,uBAAuBC,KAzLb,EA6LnBpa,kBAAoB,WAClB,EAAK7X,eAAemiB,UAAU,kBAAkB,WAC9C,EAAK0P,8BAA8Bhe,MAAK,SAACsb,GACvC,EAAKzW,SACH,CACEyV,gCAAgC,EAChCgB,yBAA0BA,EAC1BkD,YAAa,EAAKD,eAAejD,KAEnC,WACE,EAAKmD,0CAvMI,EA8MnBC,gBAAkB,SAACC,GACjB,OAAO,EAAKC,YACTC,aACArhB,QAAO,SAAC+G,GAAD,OAAYoa,EAAUrM,QAAQ/N,EAAOlV,KAAO,MAjNrC,EAoNnBovB,8BAAgC,WAAO,IAAD,IAC5B7X,EAAa,EAAKtZ,MAAMqZ,IAAxBC,SAEFkY,EAAC,UAAGlY,EAASC,OAAOkY,UAAUphB,IAAI,YAAjC,aAAG,EAAoCpD,OACxC6Y,EAAC,UAAGxM,EAASC,OAAOkY,UAAUphB,IAAI,YAAjC,aAAG,EAAoCpD,OAG9C,QAAUiG,IAANse,GAAmBA,EAAEtlB,OAAS,EAAG,CAGnC,IAAIwlB,EAAU,GAGd,QAAUxe,IAAN4S,GAAmBA,EAAE5Z,OAAS,EAAG,CACnC,IAAMmlB,EAAYvL,EAAEzU,MAAM,KAC1BqgB,EAAU,EAAKN,gBAAgBC,GAIjC,EAAK9Z,SAAS,CAAE+V,aAAckE,EAAGvE,cAAeyE,IAAW,WACzD,EAAK7B,gBAxOQ,EA6OnB8B,cAAgB,WACd,EAAKpa,SAAS,CACZ+V,aAAc,GACdE,aAAc,GACdoE,mBAAmB,EACnB1E,cAAe,CAAEC,mBAAoB,GAAIC,OAAQ,IACjDQ,sBAAuB,GACvBC,sBAAsB,EACtBH,SAAS,IAEX,EAAKyB,wBACL,EAAKpL,cAAc/kB,QAAQ,iBAxPV,EA2PnB6yB,kBAAoB,SAACC,EAAOjvB,EAAOkvB,GACjC,IAAIzE,GAAoB,OAALzqB,QAAK,IAALA,OAAA,EAAAA,EAAOmvB,oBAAqBnvB,GAAS,GAEnC,KAAjByqB,EACF,EAAK/V,SACH,CACE+V,aAAcA,EACdC,wBAAwB,EACxBC,aAAc,UAEhB,WACE,EAAKqC,cAIT,EAAKtY,SAAS,CACZ+V,aAAcA,KA3QD,EAgRnB2E,YAAc,SAAC3E,EAAcyE,GAG3B,OAC2B,IAAxBzE,EAAaphB,QAA2B,UAAX6lB,GAAkC,UAAXA,GApRtC,EAwRnBG,gCAAkC,SAACJ,EAAOxE,EAAcyE,GAClD,EAAKE,YAAY3E,EAAcyE,KACjCI,aAAa,EAAKrE,OAClB,EAAKA,MAAQhP,YAAW,WACtB,EAAKiF,cAAc/kB,QAAQ,gBAC3B,EAAKuY,SACH,CACEkW,iBAAkBH,EAAaphB,QAAU,EACzCmhB,iBAAkB,GAClBK,QAASJ,EAAaphB,QAAU,EAChC0lB,mBAAmB,EACnBtE,aAAcA,EACdO,sBAAsB,IAExB,WACM,EAAKrX,MAAM8W,aAAaphB,QAAU,EACpC,EAAKkmB,uBAAuB,EAAK5b,MAAM8W,cAEvC,EAAK/V,SAAS,CACZ8V,iBAAkB,UAKzB,EAAKU,uBAGR,EAAKlvB,eAAeG,QAAQ,6BAA8BsuB,KAnT3C,EAuTnB+E,oBAAsB,SAAC1E,GAErB,EAAKpW,SAAS,CAAEoW,kBAMdA,EAAc7gB,yBACd,EAAK0J,MAAMmX,cAAc7gB,wBAIzB,EAAK+hB,aAAayD,oBAAoB,CACpCxlB,uBAAwB6gB,EAAc7gB,yBAKtCylB,0BACFlvB,UAAmBmvB,IAAI,gBAAiB7E,IA3UzB,EA+UnB8E,8BAAgC,WAC1B,EAAKC,2BACP,EAAKnb,SAAS,CAAEgW,wBAAwB,IAAS,WAE/C7d,SAASijB,cAAcC,OACvB,EAAK/C,eApVQ,EAyVnBgD,iBAAmB,SAACnB,GAClB,EAAKna,SAAS,CACZ0V,cAAeyE,KA3VA,EA+VnBoB,wBAA0B,SAAChB,GACL,KAAhBA,EAAMiB,OAAkC,KAAlBjB,EAAMkB,SACN,qBAApBlB,EAAM/uB,OAAOhB,IACf,EAAK0wB,iCAlWQ,EAuWnBQ,6BAA+B,WAC7B,IAAQlyB,EAAY,EAAKf,MAAjBe,QACJmyB,EAAa,eAAQ,EAAK5B,YAAY6B,oBAO1C,OANAD,EAAa,2BACRA,GADQ,IAEXvG,gBAAiB5rB,EAAQqyB,8BAA+B,EACxDC,yBAAyB,EACzBC,UAAW,kBA9WI,EAmXnBC,wBAA0B,SAACjG,GAEzB,OADsB,EAAKkG,qBAAqBlG,GACzBtb,KAAK,KAAKX,MAAM,MArXtB,EAwXnBmiB,qBAAuB,SAAClG,GACtB,OAAOA,EAAajc,MAAM,KAAK3C,KAAI,SAAC9O,GAClC,OAAOA,EAAOqN,WA1XC,EA8XnBwmB,aAAe,SAAC7zB,GACd,OAAOA,EAAOC,QAAQ,sBAAuB,SA/X5B,EAkYnB6zB,0BAA4B,SAACC,EAAcppB,EAASqpB,GAClD,IAAMC,EAAsB,GAI5BD,EAAiB/tB,SAAQ,SAACiuB,GAExBH,EACGzjB,QAAO,SAAC6jB,GAAD,OAASF,EAAoBrf,SAASuf,MAE7CluB,SAAQ,SAACkuB,GAER,IAAMC,EAAmBzN,OAAO,IAAD,OACzB,EAAKkN,aAAaK,GADO,QAE7B,KACA1f,KAAK7J,EAAQ8F,IAAI0jB,IAAO,IAGtBxpB,EAAQ8F,IAAI0jB,IAGVC,GACFH,EAAoB3kB,KAAK6kB,SASnC,IAAME,EAAwBN,EAAazjB,QACzC,SAAC6jB,GAAD,OAASF,EAAoBrf,SAASuf,IAAOxpB,EAAQ8F,IAAI0jB,MAG3D,OAAOF,EAAoB3tB,OAAO+tB,IArajB,EAwanBC,2BAA6B,SAAC3pB,GAC5B,IAAIynB,EAAoB,GAiBxB,OAhBAznB,EAAQ4pB,iBAAiBzlB,KAAI,SAACqlB,EAAI5d,GAChC,IAAMie,EAAkB7pB,EAAQ8F,IAAI0jB,GAC9BM,EACuB,kBAApBD,EACHA,EACAA,EAAgB3L,WACtB,OACUuJ,EADN7b,IAAU5L,EAAQ4pB,iBAAiBjoB,OAAS,EAClB8lB,EAAkB9rB,OAC5CvG,uBAAa00B,IAGarC,EAAkB9rB,OAAlB,UACvBvG,uBAAa00B,GADU,UAKzBrC,GA1bU,EA6bnBsC,uBAAyB,SAACC,GACxB,OAAOA,EAAkB1xB,MAAMuK,SAASsB,KAAI,SAACnE,GAC3C,IAAMiqB,EAAUD,EAAkBtd,OAAOjT,QACnCywB,EAASF,EAAkBE,OAEjC,MAAO,CACLD,UACAxC,kBAHwB,EAAKkC,2BAA2B3pB,GAIxDkqB,cArca,EA0cnBC,2BAA6B,SAACH,EAAmBX,GAC/CW,EAAkB1xB,MAAMuK,SAASvH,SAAQ,SAAC0E,GACxCA,EAAQ4pB,iBAAmB,EAAKT,0BAC9Ba,EAAkBtd,OAAO0c,aACzBppB,EACAqpB,OA/ca,EAodnBe,+BAAiC,SAACzH,GAChC,IAAI0G,EAAmB,EAAKL,wBAC1B,EAAK/c,MAAM8W,cAGPsH,EAAoB1H,EAAcC,mBAAmBze,KACzD,SAAC6lB,GAKC,OAJA,EAAKG,2BAA2BH,EAAmBX,GAI5C,EAAKU,uBAAuBC,GAAmBrkB,QACpD,SAACzN,GAAD,OAAOA,EAAEuvB,wBAQf,OAAO,EAAK6C,qBAAqBD,EAAkBE,SAxelC,EA2enBD,qBAAuB,SAACE,GACtB,OAAOA,EAAsBpnB,MAAK,SAACxF,EAAGyF,GAAJ,OAChC9N,uBAAaqI,EAAE6pB,mBAAmBnkB,cAChC/N,uBAAa8N,EAAEokB,wBACf9e,EACA,CAAE8hB,SAAS,QAhfE,EAqfnBC,8BAAgC,SAACC,GAC/B,OAAOA,EAAQzvB,QACb,SAACynB,EAAe/Y,GAMd,OALA+Y,EAAcC,mBACZD,EAAcC,mBAAmBjnB,OAC/BiO,EAAOtR,MAAMsqB,oBAEjBD,EAAcE,OAASF,EAAcE,OAAOlnB,OAAOiO,EAAOtR,MAAMuqB,QACzDF,IAET,CAAEE,OAAQ,GAAID,mBAAoB,MA/fnB,EAmgBnBgI,2BAngBmB,uCAmgBU,WAAOC,GAAP,mBAAAjtB,EAAA,6DAEM,EAAKktB,2BAMpCD,EAAY,2BACPA,GADO,IAEVzI,iBAAiB,EACjBC,eAAe,KAMbU,EAAe,EAAKgI,yBAIG,KAFvBrI,EAAkB,EAAKzW,MAAvByW,eAEY/gB,SAChB+gB,EAAgB,EAAKqE,YAAYC,cAG/B,EAAK/a,MAAMmX,cAAcjB,wBAC3BO,EAAgB,EAAK4B,aAAa0G,2BAGvB,EACPjlB,EAAU,EAAKghB,YAAYf,WAC/BjD,EACAL,EACAmI,GAjCyB,kBAoCpBxiB,QAAQ4iB,WAAR,CACLllB,GADK,mBAEF,EAAKmlB,wBAAwBL,MAE/B1iB,MAAK,SAACwiB,GACLA,EAAUA,EAAQhlB,QAAO,SAACiE,GAAD,MAA8B,aAAlBA,EAAOuhB,UAC5CR,EAAU,EAAKS,iCAAiCT,GAChD,IAAIhI,EAAgB,EAAK+H,8BAA8BC,GAiBvD,OAfAhI,EAAcE,OAAOlhB,OAAS,GAC5BmH,QAAQ1P,MAAM,uBAAwBupB,EAAcE,QAGtDF,EAAcC,mBAAmBtnB,SAAQ,SAAC+vB,GACxCA,EAAG/yB,MAAMuK,SAASvH,SAAQ,SAACyJ,GACzB,MAA4C,EAAKumB,iBAC/CvmB,EACAsmB,EAAG3e,QAFG3K,EAAR,EAAQA,aAAcO,EAAtB,EAAsBA,kBAItByC,EAAEhD,aAAeA,EACjBgD,EAAEzC,kBAAoBA,QAInBqgB,KAER/Z,OAAM,SAACxP,GACN0P,QAAQ1P,MAAM,uBAAwBA,GAKpC,EAAK4T,SAAS,CACZzW,MAAM,QArEa,2CAngBV,wDA+kBnBu0B,uBAAyB,WACvB,IAAQ/H,EAAiB,EAAK9W,MAAtB8W,aACR,OAAOA,EAAawI,WAAW,MAAQxI,EAAayI,SAAS,MAjlB5C,EAqlBnBT,uBAAyB,WAEvB,OADyB,EAAK9e,MAAtB8W,aACYztB,QAAQ,KAAM,KAvlBjB,EA0lBnBm2B,4BAA8B,SAAC9I,GAC7B,OAAuC,IAAhCA,EAAcE,OAAOlhB,OAArB,GAEH,0CAAoChG,OAClCgnB,EAAcE,OACX1e,KAAI,SAAC/K,EAAOwS,GACX,OAAOA,IAAU+W,EAAcE,OAAOlhB,OAAS,EAC3CvI,EAAMsT,OAAOjT,QADV,UAEAL,EAAMsT,OAAOjT,QAFb,SAIRgO,KAAK,MApmBG,EAgpBnB6jB,iBAAmB,SAACtrB,EAAS0M,GAAY,IAAD,IACtC,GAAI1M,EAAQ+B,cAAgB/B,EAAQsC,kBAClC,MAAO,CACLP,aAAc/B,EAAQ+B,aACtBO,kBAAmBtC,EAAQsC,mBAI/B,IAAMopB,EAAY,SAACC,EAAoBC,GACrC,IAAIC,EAAe7rB,EAAQ8F,IAAI8lB,GAW/B,OAVInwB,MAAMC,QAAQmwB,KAChBA,EAAeA,EAAapkB,KAAK,OAE/BokB,IAEAF,EADEA,EAAmBhqB,OAAS,EACTgqB,EAAmBhwB,OAAnB,aAAgCkwB,IAEhCA,EAAa3N,YAG/ByN,GAeT,MAAO,CAAE5pB,cAPP,UAAA2K,EAAOof,qBAAP,eAAsB5wB,OAAOwwB,EAAW,MAAO,yBAO1BppB,mBADrB,UAAAoK,EAAOqf,0BAAP,eAA2B7wB,OAAOwwB,EAAW,MAAO,KAlrBrC,EAsrBnBM,2BAA6B,SAACnpB,GAC5B,OAAOA,EAAS8C,QAAO,SAAC3F,GACtB,OAAgC,MAAzBA,EAAQS,kBAxrBA,EA4rBnBwrB,sCAAwC,SAACrJ,GAKvC,OAAOA,EACJze,KAAI,SAACknB,GACJ,OAAOA,EAAG/yB,MAAMuK,SAASsB,KAAI,SAACY,GAC5B,OAAOA,QAGVwlB,QAvsBc,EA0sBnB2B,cAAgB,SAACvJ,GACf,IAAIwJ,EAAa,EAIjB,OAHAxJ,EAAcC,mBAAmBtnB,SAAQ,SAAC+vB,GACxCc,GAAcd,EAAG/yB,MAAMuK,SAASlB,UAE3BwqB,GA/sBU,EAktBnBtE,uBAltBmB,sBAktBM,8BAAAjqB,EAAA,6DACnBitB,EAAe,EAAKnC,+BADD,SAEQ,EAAKkC,2BAClCC,GAHqB,OAEnBuB,EAFmB,OAMvB,EAAKpf,SAAS,CACZ8V,iBAAkB,EAAKuJ,wBAAwBD,GAC/CjJ,SAAS,IARY,2CAltBN,EA8tBnBmJ,4BAA8B,WAC5B,OACE,EAAKrgB,MAAMwX,0BACoC,IAA/C,EAAKxX,MAAMwX,yBAAyB9hB,QAjuBrB,EAquBnBupB,wBAA0B,SAACL,GACzB,IAAQ9H,EAAiB,EAAK9W,MAAtB8W,aACR,OAAI,EAAKuJ,8BACA,GAEF,EAAKrgB,MAAMwX,yBAAyBvoB,QAAO,SAACoK,EAAUmgB,GAC3D,OAAIA,EAAOE,gBAAgBK,YAEzB1gB,EAASX,KACP8gB,EAAOE,gBACJK,WAAWjD,EAAc8H,GACzB1iB,MAAK,SAACiW,GACL,MAAO,CACLyE,OAAQzE,EAAIyE,OACZD,mBAAoBxE,EAAIwE,wBAIzBtd,GAEFA,IACN,KA1vBc,EA6vBnB6iB,wBAA0B,WASxB,OARyB,EAAKlc,MAAtB8W,aAQYphB,QAAU,GAtwBb,EAywBnB4qB,8BAAgC,WAC9B,OAAO,2BACF,EAAKC,2BAA2B,EAAKzF,YAAY6B,qBADtD,IAEEG,UAAW,YA5wBI,EAgxBnBqC,iCAAmC,SAACT,GAClC,OAAOA,EAAQxmB,KAAI,SAACia,GAClB,IAAIwE,EAAqBxE,EAAI9lB,MAAMsqB,mBAAmBjd,QACpD,SAACqkB,GACC,OAAOA,EAAkB1xB,MAAMuK,SAASlB,OAAS,KAIrD,OADAyc,EAAI9lB,MAAMsqB,mBAAqBA,EACxBxE,MAxxBQ,EA4xBnBiO,wBAA0B,SAAC1J,GACzB,IACI8J,EAAwB9J,EAAcC,mBAAmBjhB,OAEzD8qB,EAHW,IAIb9J,EAAcC,mBAAqBD,EAAcC,mBAAmBxF,MAClE,EALW,IAUf,IAAI+O,EAAa,EACjBxJ,EAAcC,mBAAmBtnB,SAAQ,SAAC+vB,GACxCc,GAAcd,EAAG/yB,MAAMuK,SAASlB,UAGlC,IAAI+qB,EAAkBhb,KAAKib,IACzB,EACAjb,KAAKkb,IACHlb,KAAKgN,MAAMyN,EAAaM,GACxB/a,KAAKgN,MAnBM,EAmBW+N,KAIpBI,EAAmB,EAAKzC,+BAA+BzH,GAE7D,OAAIwJ,EAzBW,EA2BN,EAAKW,wBAAwBD,EAAkBH,GAEjDG,GA1zBU,EA6zBnBC,wBAA0B,SAACD,EAAkBH,GAC3C,IAAIK,EAAwB,GAEtBC,EAAsB,EAAKC,oBAC/BJ,EACA,WAGF,IAAK,IAAMK,KAASF,EAClBD,EAAqB,sBAChBA,GADgB,YAEhBC,EAAoBE,GAAO9P,MAAM,EAAGsP,KAG3C,OAAOK,GA30BU,EA80BnBE,oBAAsB,SAACE,EAAO5hB,GAC5B,OAAO4hB,EAAMjyB,QAAO,SAACkyB,EAASpyB,GAK5B,OAJKoyB,EAAQpyB,EAAIuQ,MACf6hB,EAAQpyB,EAAIuQ,IAAa,IAE3B6hB,EAAQpyB,EAAIuQ,IAAW5G,KAAK3J,GACrBoyB,IACN,KAr1Bc,EAw1BnBZ,2BAA6B,SAACa,GAC5B,MAMI,EAAKphB,MAAMmX,cALbb,EADF,EACEA,oBACAD,EAFF,EAEEA,UACAD,EAHF,EAGEA,cACAD,EAJF,EAIEA,gBACAI,EALF,EAKEA,qBAEF,OAAO,2BACF6K,GADL,IAEE9K,oBAAqBA,EACrBuG,yBAAyB,EAAK7c,MAAM+W,uBACpCU,iBAAkB,EAAKA,kBAAoB,GAC3CpB,UAAWA,EACXF,gBAAiBA,EACjBC,cAAeA,EACfG,qBAAsBA,KAx2BP,EA42BnB8K,4BAA8B,WAC5B,EAAKtgB,SAAS,CAAEsW,sBAAuB,EAAKrX,MAAMqX,wBA32BlD,EAAKnf,IAAM1O,EAAM0O,IACjB,EAAK4iB,YAActxB,EAAMqZ,IAAIC,SAASgY,YACtC,EAAKzyB,eAAiBmB,EAAMqZ,IAAIxa,eAChC,EAAK+vB,mBACL,EAAKG,qBACL,EAAKO,oBAPY,E,mFAwmBnB,oCAAAnnB,EAAA,6DACEzI,KAAK6X,SAAS,CAAEmW,SAAS,IACnB0H,EAAe11B,KAAKo3B,gCAF5B,SAG8Bp3B,KAAKy1B,2BAA2BC,GAH9D,OAGQlI,EAHR,OAIQU,EACJluB,KAAKs2B,4BAA4B9I,GAEnCxtB,KAAK6X,SAAS,CACZ2V,gBACA0E,mBAAmB,EACnBlE,SAAS,EACTD,kBAAkB,EAClBG,wBACAC,sBAAsB,IAGpBzgB,EAAW1N,KAAK82B,sCAClBtJ,EAAcC,oBAMQ,KAHxB/f,EAAW1N,KAAK62B,2BAA2BnpB,IAG9BlB,OACXxM,KAAKqkB,cAAc/kB,QAAQ,gCAAiCoO,IAIE,IAAvD1N,KAAKM,MAAMqZ,IAAIC,SAASC,OAAOC,UAAU9K,IAAIopB,QAC9CvtB,EAAU6C,EAAS,GAEzB1N,KAAKqkB,cAAc/kB,QACjB,gDACA,CACEuL,aAlCR,iD,0EAwQA,WACE,IAAQoN,EAAYjY,KAAKM,MAAjB2X,QACR,EAaIjY,KAAK8W,MAZP8W,EADF,EACEA,aACAE,EAFF,EAEEA,aACAN,EAHF,EAGEA,cACAG,EAJF,EAIEA,iBACAI,EALF,EAKEA,iBACAmE,EANF,EAMEA,kBACAlE,EAPF,EAOEA,QACAC,EARF,EAQEA,cACAV,EATF,EASEA,cACAiE,EAVF,EAUEA,YACAtD,EAXF,EAWEA,sBACAC,EAZF,EAYEA,qBAGF,OACEnuB,KAAK8W,MAAMwW,iCAC4C,IAAvDttB,KAAKM,MAAMqZ,IAAIC,SAASC,OAAOC,UAAU9K,IAAIopB,OAC3C,cAAC,UAAD,aACEngB,QAAS,CACPogB,KAAMpgB,EAAQqgB,WAEhBvE,aAAc/zB,KAAK+zB,aACnB1P,cAAerkB,KAAKqkB,cACpBmN,YAAaA,EACbhE,cAAeA,EACf2E,kBAAmBnyB,KAAKmyB,kBACxBvE,aAAcA,EACdE,aAAcA,EACdiF,8BAA+B/yB,KAAK+yB,8BACpChF,iBAAkBA,EAClBmE,kBAAmBA,EACnB/D,qBAAsBA,EACtBgK,4BAA6Bn4B,KAAKm4B,4BAClC3F,gCAAiCxyB,KAAKwyB,gCACtCP,cAAejyB,KAAKiyB,cACpBtE,iBAAkBA,EAClBiE,YAAa5xB,KAAK4xB,YAClB3D,cAAeA,EACf0E,oBAAqB3yB,KAAK2yB,oBAC1BQ,iBAAkBnzB,KAAKmzB,iBACvBnF,QAASA,EACTT,cAAeA,EACf6F,wBAAyBpzB,KAAKozB,wBAC9BS,wBAAyB7zB,KAAK6zB,wBAC9B3F,sBAAuBA,GACnBluB,KAAKM,Y,GA1/BEka,IAAMC,eAggCZC,uBAtgCA,iBAAO,CACpB4d,UAAW,CACTlsB,MAAO,WAogCIsO,CAAmB6d,YAAazL,K,+eCj+B/C9c,SAASmR,QAAU,GAEnB,IAmKMqX,G,kDAiDJ,WAAYl4B,GAAQ,IAAD,uBACjB,cAAMA,IAxCRm4B,sBAAwB,SAACC,EAAqC3e,GAkB5D,OAhBG2e,GACuC,YAAxCA,IAGAA,EACE,EAAKp4B,MAAMuZ,OAAOC,UAAU9K,IAAI2pB,qBAGK5e,EAAM6e,MAAK,SAACC,GACnD,MACiD,kBAAxCH,GACPG,EAAKnvB,KAAKqe,gBACR2Q,EAAoC3Q,kBAMxC2Q,GACwC,YAAxCA,GAkBe,EAdnBI,mCAAqC,WACnC,OAA0D,OAAnDv5B,OAAOC,aAAaI,QAAQ,mBACoB,SAAnDL,OAAOC,aAAaI,QAAQ,mBAG5B,MASa,EANnBm5B,uCAAyC,WACvC,OAA8D,OAAvDx5B,OAAOC,aAAaI,QAAQ,uBAC/BL,OAAOC,aAAaI,QAAQ,uBAC5B,MAGa,EAqGnBo5B,mBAAqB,WACnB,MAAgC,EAAK14B,MAA7BuZ,EAAR,EAAQA,OAAQwC,EAAhB,EAAgBA,YAChB,OAAOxC,EAAOC,UAAUC,MAAM6e,MAAK,SAACC,GAClC,MAC0B,YAAxBA,EAAKx3B,QAAQgC,QACbgZ,EACGrN,KAAI,SAACiqB,GAAD,OAAgBA,EAAWlR,iBAC/BjT,SAAS+jB,EAAKnvB,KAAKqe,mBA5GT,EAyUnBmR,gBAAkB,SAACn2B,GACjB,EAAK8U,SAAS,CAAEshB,iBAAkB,EAAKriB,MAAMqiB,kBAAmB,WAG9D,EAAKvf,SAASwf,SAASC,aAKvB,EAAKl6B,eAAeG,QAAQ,sBAIxBuzB,0BACFtzB,OAAOC,aAAaC,QAClB,kBACA,EAAKqX,MAAMqiB,kBASgB,IAA/B,EAAKriB,MAAMqiB,iBACT,EAAKh6B,eAAeG,QAAQ,uBAnWf,EAuWnBg6B,iBAAmB,SAACv2B,GAClB,EAAK8U,SAAS,CAAE0hB,qBAAqB,KAxWpB,EA2WnBC,iBAAmB,SAACz2B,GAClB,EAAK8U,SAAS,CAAE0hB,qBAAqB,KA5WpB,EAgZnBE,mBAAqB,WAAO,IAAD,EACzB,EAA4B,EAAKn5B,MAAzB2X,EAAR,EAAQA,QAAS4B,EAAjB,EAAiBA,OACX6f,EAAW,UAAG,EAAK5iB,MAAM6iB,cAAc3f,MAC3C,SAAC4f,GAAD,OAAQA,EAAGz2B,QAAU,EAAK2T,MAAM+iB,8BADjB,aAAG,EAEjBH,YAIGI,GAC+B,UAAlC,EAAKx5B,MAAMM,MAAMoG,QAAQ0C,KACtBmQ,EAAOC,UAAU9K,IAAI+qB,UACrBlgB,EAAOC,UAAU9K,IAAIgrB,WACzBngB,EAAOC,UAAU9K,IAAIirB,MACrB,WAEF,OACE,uCACE,eAAC,IAAD,CAAK7xB,UAAW6P,EAAQiiB,QAAxB,SACE,sBAAKC,IAAI,GAAG5tB,IAAKutB,EAAS1xB,UAAW6P,EAAQgiB,SAE/C,eAAC,IAAD,IACA,gBAAC,IAAD,CACE7xB,UAAW6P,EAAQmiB,WACnBlhB,MAAI,EACJD,WAAS,EACTohB,KAAK,SACL/W,UAAU,MACVlK,QAAQ,gBACRD,WAAW,SAPb,UASE,eAAC,IAAD,CAAMD,MAAI,EAAV,SACE,eAAC,IAAD,CAAYtR,QAAQ,SAASQ,UAAW6P,EAAQyhB,YAAhD,SACGA,MAIL,eAAC,IAAD,CAAMxgB,MAAI,EAAV,SACE,eAAC,IAAD,CAAQohB,QAAM,EAAd,SACE,eAAC,IAAD,CACE3xB,OACG,EAAKmO,MAAMqiB,gBAAkB,aAAY,eAC1C,mBAHJ,SAME,eAAC,IAAD,CACE/wB,UAAW6P,EAAQsiB,iBACnB72B,QAAS,EAAKw1B,gBACdsB,aAAc,EAAKlB,iBACnBmB,aAAc,EAAKjB,iBAJrB,SAMG,EAAK1iB,MAAMqiB,gBACV,EAAKriB,MAAMyiB,oBACT,eAAC,IAAD,IAEA,eAAC,IAAD,IAEA,EAAKziB,MAAMyiB,oBACb,eAAC,IAAD,IAEA,eAAC,IAAD,mBA3cC,EAsdnBmB,uBAAyB,WACvB,IAAQziB,EAAY,EAAK3X,MAAjB2X,QAER,OACE,uBAAK5V,GAAG,iBAAiB+F,UAAW6P,EAAQ0iB,uBAA5C,UACE,eAAC,IAAD,CAEEvyB,UAAW6P,EAAQ2iB,cACnB5X,QACqC,YAAnC,EAAKlM,MAAM+iB,oBAAoC,QAAU,OAJ7D,SAOE,sBAAKgB,KAAK,aAAax4B,GAAG,oBANtB,WAQL,EAAKyU,MAAM6iB,cAAc3qB,KAAI,SAAC4qB,GAC7B,OACE,eAAC,IAAD,CAEExxB,UAAW6P,EAAQ2iB,cACnB5X,QACE,EAAKlM,MAAM+iB,sBAAwBD,EAAGz2B,MAAQ,QAAU,OAJ5D,SAOGy2B,EAAGkB,uBANClB,EAAGz2B,cApelB,IAAM43B,EACJ,EAAKjC,qCACDJ,EACJ,EAAKK,yCACDiC,EAAyB,EAAKhC,qBAa9BiC,EAXwB,EAAKxC,sBACjCC,EACAp4B,EAAMuZ,OAAOC,UAAUC,OAUmB,OAAxC2e,GACwC,YAAxCA,EACEA,EACA,EAAKp4B,MAAMuZ,OAAOC,UAAU9K,IAAI2pB,oBAClCqC,EACA,UACA,KAQE7B,EACyB,OAA7B8B,KAEIvY,aAEoC,OAApCqY,EACAA,EACCz6B,EAAMuZ,OAAOC,UAAU9K,IAAIksB,eAC1B56B,EAAMuZ,OAAOC,UAAU9K,IAAImqB,kBAC7B,IAOA+B,EACyB,OAA7BD,IAEIvY,iBACmDlP,IAAnDlT,EAAMuZ,OAAOC,UAAU9K,IAAImsB,oBAC3B76B,EAAMuZ,OAAOC,UAAU9K,IAAImsB,oBACS,OAApCJ,EACAA,EACAz6B,EAAMuZ,OAAOC,UAAU9K,IAAIksB,gBAAiB,GA3DjC,OA6DjB,EAAKpkB,MAAQ,CACX2R,OAAO,EACPkR,cAAe,GACf3L,SAAS,EACToN,mBAAoB,GACpBF,cAAeA,EACf/B,gBAAiBA,EACjBU,oBAAqBoB,EACrB1B,qBAAqB,GAKnB2B,GAAiB/B,GAAgD,OAA7B8B,GAClCpI,0BACFtzB,OAAOC,aAAaC,QAClB,sBACAw7B,GAKN,EAAK97B,eAAiB,IAAIqvB,IAM1B6M,oBAAgB,CACdn8B,iBAAkBoB,EAAMuZ,OAAOC,UAAU9K,IAAI9P,iBAC7CC,eAAgB,EAAKA,iBAGvB,EAAKya,SAAW,IAAI0hB,UAAS,CAC3BzhB,OAAQvZ,EAAMuZ,OACd1a,eAAgB,EAAKA,eACrB4d,gBAAiBzc,EAAMyc,kBAjGR,E,qDAiHnB,WAAqB,IAAD,OACd5M,EAAWnQ,KAAK4Z,SACjB2hB,YACAC,iBACAC,YACAC,YAAY17B,KAAKM,MAAM+b,aAC1BnJ,QAAQC,IAAIhD,GAAU6C,MAAK,WACzB,EAAK6E,SACH,CACEkC,MAAO,EAAKH,SAAS+hB,eAEvB,WAGE,EAAK/hB,SAASgiB,mBAAmBpvB,OAAS,GACxC,EAAKrN,eAAeG,QAAQ,6BAA8B,CACxD6D,MAAO,UACP04B,WAAYC,IACZx3B,QAAS,cACTo1B,YAAa,cACbqC,MAAO,EACPjB,oBAAqB,WACnB,OAAO,QAKb,EAAK37B,eAAeG,QAAQ,wBAIlCU,KAAKg8B,iB,+BAGP,SAAkB/3B,M,0BAElB,WAAgB,IAAD,OAEb+L,SAASgO,KAAKqD,iBACZ,aACA,SAAC+Q,QAIqB5e,IAAhB4e,EAAMlnB,OAAuC,IAAhBknB,EAAMlnB,OAErCknB,EAAMpvB,mBAKV,CAAEi5B,SAAS,IAKbj8B,KAAKb,eAAemiB,UAAU,sBAAsB,SAACkU,GACnD,EAAK3d,SAAS,CACZujB,mBAAoB5F,OAIxBx1B,KAAKb,eAAemiB,UAAU,cAAc,SAACqH,GAC3C,EAAK9Q,SAAS,CACZ4Q,OAAO,EACPyT,aAAcvT,OAIlB3oB,KAAKb,eAAemiB,UAAU,mBAAmB,WAM3C,EAAKxK,MAAMqiB,gBACb,EAAKD,mBAEL,EAAKrhB,SAAS,CAAEqjB,eAAe,IAG/B,EAAK/7B,eAAeG,QAAQ,8BAIhCU,KAAKb,eAAemiB,UAAU,+BAA+B,YAQxB,IAA/B,EAAKxK,MAAMqiB,kBACb,EAAKthB,SAAS,CAAEqjB,eAAe,IAE/B,EAAK/7B,eAAeG,QAAQ,8BAIhCU,KAAKb,eAAemiB,UAAU,6BAA6B,SAACvL,GAChD,OAANA,EACF,EAAK8B,SAAS,CAAEqjB,eAAe,EAAMrB,oBAAqB9jB,IAE1D,EAAK5W,eAAeG,QAAQ,sBAIhCU,KAAKb,eAAemiB,UAAU,8BAA8B,SAAC6a,GAC3D,IAAMC,EAAQ,sBAAO,EAAKtlB,MAAM6iB,eAAlB,CAAiCwC,IAC/C,EAAKtkB,SAAS,CAAE8hB,cAAeyC,OA+BjCp8B,KAAK4Z,SACFwf,SACA9oB,YACAC,WACApK,SAAQ,SAACsH,GACRA,EAAM0G,GAAG,kBAAkB,SAACpR,GAC1B,EAAK5D,eAAeG,QAAQ,8BAA+ByD,W,mCAKnE,WAAyB,IAAD,iBAEhBs5B,EAAgB,UAAGr8B,KAAKM,MAAMuZ,OAAOC,UAAUC,MAAMC,MACzD,SAACC,GAAD,MAAkB,cAAXA,EAAEvQ,eADW,aAAG,EAEtBrI,QAsBH,YACuBmS,IAArB6oB,GACE,eAAC,UAAD,CACEj7B,MAAM,UAAApB,KAAK8W,MAAMskB,0BAAX,mBAA+B1tB,gBAA/B,eAAyClB,QAAS,EACxDrN,eAAgBa,KAAKb,eACrBwJ,MAAO0zB,EAAiB1zB,OAAS,YACjCqP,SAAUqkB,EAAiBrkB,UAAY,QACvCmI,KAAK,SACL/T,MAAOiwB,EAAiBjwB,OAAS,IACjCoS,OAAQ6d,EAAiB7d,QAAU,IACnC9Q,SAAQ,UAAE1N,KAAK8W,MAAMskB,0BAAb,aAAE,EAA+B1tB,SACzCrM,QAAO,UACLrB,KAAK4Z,SAASC,OAAOC,UAAUC,MAAMC,MACnC,SAACC,GAAD,MAAkB,cAAXA,EAAEvQ,eAFN,aACL,EAEGrI,QAEL2N,IAAKhP,KAAK4Z,SAASwf,SACnB3U,UAAW,SAAC5Z,GACV,EAAK+O,SAAS0iB,UAAUzxB,IAE1B1J,QAAS,WACP,EAAKyY,SAAS0iB,WAAU,GACxB,EAAKzkB,SAAS,CACZujB,wBAAoB5nB,S,mCAqDhC,WAEE,OACExT,KAAK4Z,SAASyW,QAAQkM,SACmC,IAAzDv8B,KAAK4Z,SAASyW,QAAQkM,OAAOl7B,QAAQm7B,gBAGnC,eAAC,UAAD,CACExtB,IAAKhP,KAAK4Z,SAASwf,SACnBzf,IAAK3Z,KACLqB,QAASrB,KAAK4Z,SAASyW,QAAQkM,OAAOl7B,UAInC,O,qCAIX,WACE,IAAMmf,EAAIxgB,KAAK4Z,SAASC,OAAOC,UAAUC,MAAMC,MAC7C,SAACC,GAAD,MAAkB,gBAAXA,EAAEvQ,QAGX,YACQ8J,IAANgN,GACAA,EAAE7J,eAAe,YAAc,eAAC,UAAD,CAAatV,QAASmf,EAAEnf,Y,sBAI3D,SAAS+kB,GACP,OAAOA,aAAaqW,QAAuB,kBAANrW,I,oBAwGvC,WAAU,IAAD,SACP,EAA4BpmB,KAAKM,MAAzB2X,EAAR,EAAQA,QAAS4B,EAAjB,EAAiBA,OAGXue,EAAQve,EAAOC,UAAU9K,IAAIopB,MAI7BsE,GAA4B,IAAVtE,GAAkBve,EAAOC,UAAU9K,IAAI2tB,YAEzDC,GACM,IAAVxE,GAAwC,oBAArBve,EAAOgjB,UAE5B,OACE,eAAC,IAAD,CACEC,SAAU,EACV7kB,QAAS,CACP8kB,yBAA0B9kB,EAAQ+kB,wBAClCC,sBAAuBhlB,EAAQilB,qBAC/BC,cAAellB,EAAQmlB,uBAEzBtN,aAAc,CACZC,SAAU,MACVC,WAAY,UAThB,SAYE,wCACG,UAAAhwB,KAAKM,MAAMuZ,OAAOwjB,iBAAlB,eAA6BC,gBAC5Bh3B,MAAMC,QAAQvG,KAAKM,MAAMuZ,OAAOwjB,UAAUC,gBAC1Ct9B,KAAKM,MAAMuZ,OAAOwjB,UAAUC,cAAc9wB,OAAS,GACjD,eAAC,UAAD,CACE8wB,cAAet9B,KAAKM,MAAMuZ,OAAOwjB,UAAUC,cAC3CC,WAAYv9B,KAAKM,MAAMuZ,OAAOgjB,aAGzB,IAAVzE,GACC,eAAC,UAAD,CACEj5B,eAAgBa,KAAKb,eACrBya,SAAU5Z,KAAK4Z,WAGnB,eAAC,UAAD,CACExY,KAAMpB,KAAK8W,MAAM2R,MACjBE,QAAS3oB,KAAK8W,MAAMolB,aACpB3e,OAAQvd,KACR2I,MAAM,eAER,eAAC,UAAD,CAAaxJ,eAAgBa,KAAKb,iBAClC,uBACEkD,GAAG,SACH+F,UAAWo1B,kBAAKvlB,EAAQwlB,QAAT,eACZxlB,EAAQylB,YACP19B,KAAK8W,MAAMqiB,kBAA6B,IAAVf,IAJpC,UAOE,0BACE/1B,GAAG,SACH+F,UAAWo1B,kBAAKvlB,EAAQuS,OAAQvS,EAAQ0lB,yBAF1C,WAIa,IAAVvF,GACC,eAAC,UAAD,CACEuB,cAAe35B,KAAK8W,MAAM6iB,cAC1Bx6B,eAAgBa,KAAKb,eACrBy+B,oBACE59B,KAAK8W,MAAMokB,cACPl7B,KAAK8W,MAAM+iB,oBACX,OAKT75B,KAAK69B,2BAER,wBAAMz1B,UAAW6P,EAAQ+D,KAAzB,UACE,sBACE3Z,GAAG,cACH+F,UAAWo1B,kBACTvlB,EAAQ6lB,WACR7lB,EAAQ0lB,2BAGZ,sBACEt7B,GAAG,eACH+F,UAAWo1B,kBACTvlB,EAAQ8lB,YACR9lB,EAAQ0lB,2BAIZ,uBACEt7B,GAAG,kBACH+F,UAAWo1B,kBACTvlB,EAAQ+lB,eACR/lB,EAAQ0lB,yBAJZ,UAOE,eAAC,UAAD,CAAM3uB,IAAKhP,KAAK4Z,SAASwf,YACd,IAAVhB,IAEG,IADFp4B,KAAK4Z,SAASC,OAAOC,UAAU9K,IAAIivB,gBAEjC,eAAC,UAAD,CAAMC,YAAal+B,KAAK4Z,SAASC,OAAOqkB,cAE5C,sBAAK77B,GAAG,2BACPq6B,GACC,eAAC,UAAD,CACE5iB,UAAW9Z,KAAK4Z,SAASC,OAAOC,UAChC9K,IAAKhP,KAAK4Z,SAASwf,WAGvB,eAAC,UAAD,CAAQpqB,IAAKhP,KAAK4Z,SAASwf,WAC1BwD,GAAmB,eAAC,UAAD,CAAahjB,SAAU5Z,KAAK4Z,YACrC,IAAVwe,GAAmB,eAAC,UAAD,CAAYxe,SAAU5Z,KAAK4Z,YACpC,IAAVwe,GAAmB,eAAC,UAAD,CAAaxe,SAAU5Z,KAAK4Z,YACrC,IAAVwe,GACC,eAAC,UAAD,CACE+F,iBACEn+B,KAAK4Z,SAASC,OAAOC,UAAU9K,IAAImvB,iBAErCthB,eAAgB7c,KAAKM,MAAMuc,kBAGpB,IAAVub,GAAmBp4B,KAAKo+B,gCAG7B,0BACEh2B,UAAWo1B,kBAAKvlB,EAAQomB,OAAQpmB,EAAQ0lB,yBAD1C,UAGE,eAAC,UAAD,CAAW3uB,IAAKhP,KAAK4Z,SAASwf,WAC9B,eAAC,UAAD,CAAapqB,IAAKhP,KAAK4Z,SAASwf,iBAGpC,sBACE/2B,GAAG,MACH2hB,SAAS,IACT6W,KAAK,cACLzyB,UAAWo1B,kBAAKvlB,EAAQjJ,IAAT,eACZiJ,EAAQylB,YACP19B,KAAK8W,MAAMqiB,kBAA6B,IAAVf,MAGpC,uBACE/1B,GAAG,oBACH+F,UAAWo1B,kBACTvlB,EAAQ0lB,wBACR1lB,EAAQqmB,iBAFK,eAIVrmB,EAAQylB,YACP19B,KAAK8W,MAAMqiB,kBAA6B,IAAVf,IAPtC,UAWGp4B,KAAKu+B,wBACN,eAAC,UAAD,CACElO,QAASrwB,KAAK4Z,SAAS4kB,sCAGhB,IAAVpG,GACC,gBAAC,IAAD,CACEh3B,KAAMpB,KAAK8W,MAAMokB,cACjBuD,WAAY,CACVC,aAAc1+B,KAAK8W,MAAMqiB,gBACzBwF,qBAAqB,EACrBC,gBAAiB,WACf,EAAKz/B,eAAeG,QAAQ,oBAE9B4I,MAAO,CAEL8P,SAAUhY,KAAK8W,MAAMqiB,gBAAkB,UAAY,SAErD0F,aAAa,EACbC,gBAAiB,WACf,EAAK3/B,eAAeG,QAAQ,qBAGhCsI,QAAQ,YACRqQ,QAAS,CACP0M,MAAO1M,EAAQ8mB,kBAnBnB,UAsBG/+B,KAAKy5B,qBACN,eAAC,IAAD,IACCz5B,KAAK06B,6BAGC,IAAVtC,GACC,eAAC,UAAD,CACE4G,gCACEh/B,KAAK4Z,SAASC,OAAOwjB,UAAU2B,gCAEjCC,8BACEj/B,KAAK4Z,SAASC,OAAOwjB,UAAU4B,8BAEjC9/B,eAAgBa,KAAKb,0B,GAtuBjBqb,IAAMC,eA+uBTC,uBAh5BA,SAAC9Z,GACd,MAAO,CACLoO,IAAK,CACH8S,OAAQ,EACR9J,SAAU,WACV4F,KAAM,EACNO,MAAO,EACPG,OAAQ,EACRR,IAAK,EACLohB,OAAQ,wBACR,kBAAmB,CACjBA,OAAQ,oBAGZzB,QAAS,CACPzlB,SAAU,WACV4F,KAAM,EACNO,MAAO,EACPG,OAAQ,EACRR,IAAK,EACLvW,QAAS3G,EAAM4G,QAAQ,GACvBwb,QAAS,OACT+B,cAAe,SACfD,cAAe,QAEjBwZ,iBAAkB,CAChBtmB,SAAU,WACV4F,KAAM,EACNO,MAAO,EACPG,OAAQ,EACRR,IAAK,GAEP6f,wBAAyB,CACvB,QAAS,CACP7Y,cAAe,SAGnB8V,cAAe,CACbpc,OAAQ,WAEVgM,OAAO,aACL1I,OAAQlhB,EAAMkhB,OAAOqd,OACrB3a,UAAW5jB,EAAM4G,QAAQ,GACzBwb,QAAS,OACT6J,eAAgB,gBAChB1T,WAAY,aACZ,QAAS,CACPvS,aAAchG,EAAM4G,QAAQ,KAE7B5G,EAAMI,YAAYC,KAAK,MAAQ,CAC9B6gB,OAAQ,EACRsd,YAAax+B,EAAM4G,QAAQ,GAC3B63B,aAAcz+B,EAAM4G,QAAQ,GAC5B83B,WAAY1+B,EAAM4G,QAAQ,GAC1Bgd,UAAW5jB,EAAM4G,QAAQ,GACzBod,UAAWhkB,EAAMikB,QAAQ,GACzB9d,gBAAiBnG,EAAMoG,QAAQS,WAAWkd,QAG9C3I,KAAM,CACJ8F,OAAQ,EACRqD,KAAM,EACNnC,QAAS,QAEX8a,WAAY,CACV3Y,KAAM,GAER4Y,YAAa,CACXpjB,YAAa/Z,EAAM4G,QAAQ,GAC3B2Q,aAAcvX,EAAM4G,QAAQ,IAE9Bw2B,eAAe,aACbhb,QAAS,OACT+B,cAAe,UACdnkB,EAAMI,YAAYC,KAAK,MAAQ,CAC9Bq+B,UAAW1+B,EAAM4G,QAAQ,KAG7B62B,OAAQ,CACNvc,OAAQ,EACRkB,QAAS,OACT6J,eAAgB,WAChBrO,OAAQ,GACR,QAAS,CACP4gB,WAAYx+B,EAAM4G,QAAQ,KAG9Bu3B,iBAAkB,CAChB3yB,MA1Fe,IA2FfrF,gBAAiBnG,EAAMoG,QAAQS,WAAWC,SAE5C63B,aAAa,yBACXvc,QAAS,OACT7J,WAAY,SACZ5R,QAAS3G,EAAM4G,QAAQ,EAAG,IACvB5G,EAAM4+B,OAAOC,SAJN,IAKV5S,eAAgB,gBAChB9lB,gBAAiBnG,EAAMoG,QAAQS,WAAWkd,QAE5CgW,uBAAwB,CACtB5zB,gBAAiBnG,EAAMoG,QAAQS,WAAWkd,MAC1CnG,OAAQ,OACR3R,SAAU,QAEZ0tB,iBAAkB,CAChBj3B,QAAS,IAEX42B,QAAS,CACP3yB,QAAS3G,EAAM4G,QAAQ,EAAG,GAC1BgX,OAAQ5d,EAAM4G,QAAQ,IAExByyB,KAAM,CACJzb,OAAQ5d,EAAM4G,QAAQ,IAExB4yB,WAAY,CACV7yB,QAAS3G,EAAM4G,QAAQ,EAAG,GAC1BT,gBAAiBnG,EAAMoG,QAAQS,WAAWkd,MAC1CZ,UAAWnjB,EAAM4G,QAAQ,IAE3BkyB,YAAa,CACXnyB,QAAS3G,EAAM4G,QAAQ,EAAG,GAC1Bk4B,WAAY,GAEdC,kBAAmB,CACjB54B,gBAAiBnG,EAAMoG,QAAQS,WAAWC,SAE5Ck4B,WAAY,CACVxzB,MAAO,SAETgxB,sBAAsB,eACnBx8B,EAAMI,YAAYC,KAAK,MAAQ,CAC9B6jB,cAAe,OAEf,0BAA2B,CACzBA,cAAe,UAIrBkY,wBAAwB,eACrBp8B,EAAMI,YAAYC,KAAK,MAAQ,CAC9Bqd,OAAQ,SAGZ4e,qBAAqB,eAClBt8B,EAAMI,YAAYC,KAAK,MAAQ,CAC9B6c,IAAK,SAIT4f,YAAa,CACX9f,KAxJe,QAk5BNlD,CAAmB8d,K,qGCr6BnBqH,UAvBK,SAAC,GAAwB,IAAtB1gC,EAAqB,EAArBA,eACrB,EAAkCyC,mBAAS,IAA3C,mBAAOk+B,EAAP,KAAkBC,EAAlB,KACAC,qBAAU,WACR7gC,EAAemiB,UAAU,sBAAuB2e,MAGlD,IAAMA,EAAe,SAACC,GACpBH,EAAa,GAAD,mBAAKD,GAAL,YAAmBI,MAGjC,OACE,cAAC,IAAD,CAAM93B,UAAU,UAAhB,SACG03B,EAAU9wB,KAAI,SAACmxB,GACd,OACE,cAAC,IAAD,UACE,cAAC,IAAD,CAAMz3B,KAAMy3B,EAASC,KAArB,SAA4BD,EAASx3B,SADxBw3B,EAASC,a,2TCM5B9E,E,WAMJ,WAAYr8B,GAAW,oEAyEF,SAACgb,GAEpB,MAAO,CAAC,UAAW,OAAQ,QAAS,UAAW,UAAUnF,SAASmF,MA1ElE,IAAQJ,EAA4C5a,EAA5C4a,OAAQ1a,EAAoCF,EAApCE,eAAgB4d,EAAoB9d,EAApB8d,gBAChC/c,KAAKgP,SAAMwE,EACXxT,KAAKmhB,QAAU,GACfnhB,KAAKqwB,QAAU,GACfrwB,KAAKi5B,gBAAazlB,EAClBxT,KAAK6Z,OAASA,EACd7Z,KAAKqgC,iBACLrgC,KAAKsgC,uBAAyB,IAAIC,UAChC1mB,EAAOC,UAAU0mB,aAEnBxgC,KAAKb,eAAiBA,EACtBa,KAAKygC,iBAAmB,GACxBzgC,KAAK0gC,qBAAuB,GAC5BC,YAAS3gC,KAAKsgC,uBAAuBM,YACrC5gC,KAAK8S,OAASA,SACd9S,KAAK+c,gBAAkBA,E,kDAGzB,WAAkB,IAAD,EAGf/c,KAAK6Z,OAAOC,UAAU9K,IAAI6xB,eAA1B,sBACK7gC,KAAK6Z,OAAOC,UAAU9K,IAAI8xB,aAD/B,sBAEM9gC,KAAK6Z,OAAOC,UAAU9K,IAAI+xB,6BAFhC,QAEyD,O,kCAI3D,SAAqBC,GACnBhhC,KAAKmhB,QAAQ3R,KAAKwxB,K,2CAGpB,WACEhhC,KAAKmhB,QAAQhb,SAAQ,SAAC5G,GACpBA,EAAO0hC,mB,0BAIX,SAAaC,GACXlhC,KAAKmhB,QACF3Q,QAAO,SAACjR,GAAD,OAAYA,IAAW2hC,KAC9B/6B,SAAQ,SAAC5G,IACJA,EAAOyY,WAAakpB,EAAclpB,UAAY0K,aAChDnjB,EAAO0hC,mB,uBASf,SAAU3Q,GACRtwB,KAAKqwB,QAAQC,EAAO5mB,MAAQ4mB,I,wBAO9B,WAAc,IAAD,OACX,OAAOrqB,OAAOC,KAAKlG,KAAKqwB,SAAStqB,QAAO,SAACgQ,EAAGlS,GAC1C,MAAM,GAAN,mBAAWkS,GAAX,CAAc,EAAKsa,QAAQxsB,OAC1B,M,2CAkCL,WAAiC,IAAD,OAc9B,OAbU7D,KAAK27B,aACZnrB,QAAO,SAAC8f,GAAY,IAAD,IAClB,OAKE,aAAAA,EAAOjvB,SAAQu3B,YAAf,uBAAsB,SAACrwB,GAAD,mBAAO,EAAP,MAA+BA,EAAElF,aAAvD,YAEA,EAFA,MAEwBitB,EAAOjvB,QAAQgC,WAG1C4K,MAAK,SAACxF,EAAGyF,GAAJ,OAAUzF,EAAE04B,UAAYjzB,EAAEizB,e,8BAIpC,WACE,OAAOnhC,KAAK27B,aAAanrB,QAAO,SAAC8f,GAC/B,MAAO,CAAC,WAAWxb,SAASwb,EAAOjvB,QAAQgC,a,yBAW/C,SAAYgtB,GAAU,IAAD,OACblgB,EAAW,GAoCjB,OAnCAkgB,EAAQlqB,SAAQ,SAACmqB,GACf,IAAM8Q,EAAM,CAAC,UAAUtsB,SAASwb,GAAU,aAAe,UACnD+Q,EAAO,OAAO,YAAMD,EAAb,YAAoB9Q,EAApB,YAA8BA,EAA9B,QACVtd,MAAK,SAACsuB,GACL,IAAMC,EACJ,EAAK1nB,OAAOC,UAAUC,MAAMC,MAC1B,SAACwnB,GAAD,OAAUA,EAAK93B,KAAKqe,gBAAkBuI,EAAOvI,kBAC1C,GAED0Z,EACJF,GAAcA,EAAWlgC,QAAUkgC,EAAWlgC,QAAU,GAEpD8/B,EAAYI,EAAW5qB,eAAe,SACxC3L,OAAOu2B,EAAW9qB,OAClB,EAEAxQ,OAAOC,KAAKq7B,GAAY/0B,OAAS,GACnC,EAAKk1B,UACH,IAAIC,UAAO,CACT3yB,IAAK,EAAKA,IACV2K,IAAK,EACLjQ,KAAM4mB,EAAOvI,cACbyI,gBAAiB,GACjB2Q,UAAWA,EACX9/B,QAASogC,EACTt4B,UAAWm4B,EAAO55B,cAKzB+L,OAAM,SAACC,GACNC,QAAQ1P,MAAMyP,MAElBvD,EAASX,KAAK6xB,MAETlxB,I,uBAOT,WAAa,IAAD,OACJ0J,EAAS7Z,KAAK4hC,kBAMdC,EAAmB,uIACnBhoB,EAAO7K,IAAI2H,eAAe,uBAAyB,CACrDmrB,mBAAoBjoB,EAAO7K,IAAI8yB,qBAE7BjoB,EAAO7K,IAAI2H,eAAe,gBAAkB,CAC9CorB,YAAaloB,EAAO7K,IAAI+yB,cAEtBloB,EAAO7K,IAAI2H,eAAe,oBAAsB,CAClDqrB,gBAAiBnoB,EAAO7K,IAAIgzB,kBAE1BnoB,EAAO7K,IAAI2H,eAAe,aAAe,CAC3CsrB,SAAUpoB,EAAO7K,IAAIizB,WAEnBpoB,EAAO7K,IAAI2H,eAAe,mBAAqB,CACjDurB,eAAgBroB,EAAO7K,IAAIkzB,iBAEzBroB,EAAO7K,IAAI2H,eAAe,kBAAoB,CAChDwrB,cAAetoB,EAAO7K,IAAImzB,gBAExBtoB,EAAO7K,IAAI2H,eAAe,YAAc,CAC1CyrB,QAASvoB,EAAO7K,IAAIozB,UAElBvoB,EAAO7K,IAAI2H,eAAe,gBAAkB,CAC9C0rB,YAAaxoB,EAAO7K,IAAIqzB,cAEtBxoB,EAAO7K,IAAI2H,eAAe,cAAgB,CAC5C2rB,UAAWzoB,EAAO7K,IAAIszB,aAEnBt3B,OAAOwb,MAAMxb,OAAOnL,SAASga,EAAO7K,IAAIuzB,aAAe,CAC1DA,UAAW1oB,EAAO7K,IAAIuzB,aAEnBv3B,OAAOwb,MAAMxb,OAAOnL,SAASga,EAAO7K,IAAIwzB,gBAAkB,CAC7DA,aAAc3oB,EAAO7K,IAAIwzB,eAI7BxiC,KAAKgP,IAAM,IAAIyzB,IAAI,CACjBC,SAAU,GAaVC,aAAcC,YAAoBf,GAClCgB,OAAQ,GACRx/B,OAAQwW,EAAO7K,IAAI3L,OACnBy/B,SAAU,GACVC,KAAM,IAAIC,IAAK,CACbC,OAAQppB,EAAO7K,IAAIi0B,OACnBC,OAAQrpB,EAAO7K,IAAIk0B,OAAO12B,OAAS,EAAIqN,EAAO7K,IAAIk0B,YAAS1vB,EAC3D2vB,oBAAqBtpB,EAAO7K,IAAIm0B,oBAChCC,oBACE1gB,iBAAqDlP,IAAzCqG,EAAO7K,IAAIq0B,0BACnBxpB,EAAO7K,IAAIq0B,0BACXxpB,EAAO7K,IAAIo0B,oBACjBE,QAASzpB,EAAO7K,IAAIs0B,SAAW,GAC/BC,QAAS1pB,EAAO7K,IAAIu0B,SAAW,EAC/BC,WAAY3pB,EAAO7K,IAAIw0B,WACvB1C,YAAajnB,EAAO7K,IAAI8xB,YACxB2C,MAAO,IACPC,KAAM7pB,EAAO7K,IAAI00B,SAKrB,IAAI1yB,EAAchR,KAAKgP,IAAIoB,UAAUa,UA+DrC,OA7DAjR,KAAKgP,IAAImF,GAAG,WAAW,SAACpR,GAGtB,IAAM4gC,EAAU,EAAK30B,IAAIoB,UAAUa,UAC/BD,IAAgB2yB,IAClB,EAAKxkC,eAAeG,QAAQ,eAAgB,CAAEokC,KAAMC,IACpD3yB,EAAc2yB,MAKlB3jC,KAAKgP,IAAI40B,WAAa,IAAIC,UAAW7jC,MAUrCA,KAAKgP,IAAIoF,UAAY,IAAIvC,IAMrBgI,EAAOE,MAAM6e,MAAK,SAACC,GAAD,MAAwB,cAAdA,EAAKnvB,SACnCwK,4BAAkBlU,KAAKgP,KAAK,SAACosB,GAI3B,IAAM0I,EAAuB1I,EAAmB1tB,SAAS8C,QACvD,SAAC3F,GACC,MAAsC,uBAAxB,OAAPA,QAAO,IAAPA,OAAA,EAAAA,EAAS4C,MAAMkD,IAAI,YAGxBozB,EAAoB3I,EAAmB1tB,SAAS8C,QACpD,SAAC3F,GACC,MAAsC,uBAAxB,OAAPA,QAAO,IAAPA,OAAA,EAAAA,EAAS4C,MAAMkD,IAAI,YAK1BmzB,EAAqBt3B,OAAS,GAChC,EAAKrN,eAAeG,QAClB,mCACAwkC,GAKAC,EAAkBv3B,OAAS,GAE7B,EAAKrN,eAAeG,QAAQ,qBAA5B,2BACK87B,GADL,IAEE1tB,SAAUq2B,QAKX/jC,O,oBAGT,WACE,OAAOA,KAAKgP,M,4BAGd,WAIE,IAAMg1B,EAAoBhkC,KAAK6Z,OAAOC,UAAUC,MAAMpB,WACpD,SAACsB,GAAD,MAAkB,WAAXA,EAAEvQ,QAaX,OAT2B,IAAvBs6B,IACFhkC,KAAK4xB,YAAc,IAAIqS,UACrBjkC,KAAK6Z,OAAOC,UAAUC,MAAMiqB,GAAmB3iC,QAC/CrB,KAAKo5B,SACLp5B,OAKGA,O,mBAGT,WAAS,IAAD,OACNA,KAAKkkC,UAAW,EAChBlkC,KAAKs8B,WAAU,GACft8B,KAAKgP,IACFsB,YACAC,WACApK,SAAQ,SAACsH,GAENA,EAAMG,eACNH,EAAMG,gBAAgBD,WACwB,UAA9CF,EAAMG,gBAAgBD,UAAUlI,YAER,UAApBgI,EAAMhI,UACR,EAAKtG,eAAeG,QAAQ,0BAA2BmO,GAEvDA,EAAM02B,YAAW,OAIzB/kB,YAAW,WACT,EAAK8kB,UAAW,IACf,O,yBAGL,SAAYz2B,GACV,IACI22B,EAAWC,EADTC,EAAe,IAAIC,UAAavkC,KAAK6Z,OAAOwjB,UAAUmH,OAE5D,OAAQ/2B,EAAM/D,MACZ,IAAK,MACH26B,EAAcC,EAAaG,aAAah3B,EAAOzN,KAAK6Z,QACpDuqB,EAAY,IAAIM,UACdL,EAAYhjC,QACZrB,KAAK6Z,OAAOwjB,UAAUmH,MACtBxkC,KAAKb,gBAEPa,KAAKgP,IAAI21B,SAASP,EAAU32B,OAC5B,MACF,IAAK,OACH42B,EAAcC,EAAaM,cAAcn3B,EAAOzN,KAAK6Z,QACrDuqB,EAAY,IAAIS,UACdR,EAAYhjC,QACZrB,KAAK6Z,OAAOwjB,UAAUmH,MACtBxkC,KAAKgP,KAEPhP,KAAKgP,IAAI21B,SAASP,EAAU32B,OAC5B,MACF,IAAK,SACH42B,EAAcC,EAAaQ,gBAAgBr3B,GAC3C22B,EAAY,IAAIW,UACdV,EAAYhjC,QACZrB,KAAK6Z,OAAOwjB,UAAUmH,MACtBxkC,KAAKgP,KAEPhP,KAAKgP,IAAI21B,SAASP,EAAU32B,U,oBAelC,SAAOo1B,EAAQn5B,GAAO,IAAD,OACfs7B,EAAgB,GAiBpB,OAhBAnC,EAAO18B,SAAQ,SAACsH,GACd,IAAM42B,EAAc,EAAKxqB,OAAOorB,aAAajrB,MAC3C,SAACkrB,GAAD,OAAiBA,EAAY7iC,KAAOoL,EAAMpL,MAE5CoL,EAAMhI,UAAYiE,OAEE8J,IAAhB6wB,GAAkD,WAArBA,EAAY36B,OACtC+D,EAAM+J,SAAW6sB,IACpB52B,EAAM+J,QAAU6sB,EAAY7sB,SAGhCwtB,EAAcx1B,KAAd,2BACK60B,GACA52B,OAGAu3B,I,oBAGT,SAAOG,GAAS,IAAD,OACT1wB,EAAS,GAOb,OANA0wB,EAAOh/B,SAAQ,SAAC4xB,GACdtjB,EAAM,sBAAOA,GAAP,YAAkBsjB,EAAM8K,SAC1B9K,EAAMoN,SACR1wB,EAAM,sBAAOA,GAAP,YAAkB,EAAK2wB,OAAOrN,EAAMoN,cAGvC1wB,I,sBAGT,SAAS4wB,GAMP,MALY,sBACPrlC,KAAKslC,OAAOD,EAAoBhkC,QAAQkkC,WAAY,SAD7C,YAEPvlC,KAAKslC,OAAOtlC,KAAKolC,OAAOC,EAAoBhkC,QAAQ8jC,QAAS,a,uBAMpE,WAAa,IAAD,OACJE,EAAsBrlC,KAAK6Z,OAAOC,UAAUC,MAAMC,MACpD,SAAC6e,GAAD,MAAwB,kBAAdA,EAAKnvB,QAEjB87B,EAAkBxlC,KAAK6Z,OAAOC,UAAUC,MAAMC,MAC5C,SAACC,GAAD,MAAkB,cAAXA,EAAEvQ,QAwBb,OApBA1J,KAAK6iC,OAAS7iC,KAAKylC,SAASJ,GAE5Bp/B,OAAOC,KAAKlG,KAAK6iC,QACd50B,MAAK,SAACxF,EAAGyF,GAAJ,OAAU,EAAK20B,OAAOp6B,GAAGi9B,UAAY,EAAK7C,OAAO30B,GAAGw3B,aACzD12B,KAAI,SAAC22B,GAAD,OAAe,EAAK9C,OAAO8C,MAC/Bx/B,SAAQ,SAACsH,GACJ,EAAKgzB,iBAAiBj0B,OAAS,IACjCiB,EAAMm4B,eAAiB,EAAKnF,iBAAiB7H,MAC3C,SAACiN,GAAD,OAAaA,IAAYp4B,EAAMpL,OAGnCoL,EAAMq4B,UAAY,EAAKpF,qBAAqBjzB,EAAMpL,KAAO,KACzD,EAAK0jC,YAAYt4B,WAIG+F,IAApBgyB,GACFxlC,KAAKgmC,kBAAkBR,EAAgBnkC,SAGlCrB,O,+BAGT,SAAkBqB,GAChB,IAAQ+J,EAA4D/J,EAA5D+J,OAAQF,EAAoD7J,EAApD6J,MAAOqB,EAA6ClL,EAA7CkL,IAAKvC,EAAwC3I,EAAxC2I,YAAai8B,EAA2B5kC,EAA3B4kC,YAAan8B,EAAczI,EAAdyI,UAChDo8B,EAAqBl8B,GAAe,CACxCA,EAAYkM,EACZlM,EAAYqf,EACZrf,EAAYkE,EACZlE,EAAYvB,GAER09B,EAAmBr8B,GAAa,CACpCA,EAAUoM,EACVpM,EAAUuf,EACVvf,EAAUoE,EACVpE,EAAUrB,GAEZzI,KAAKomC,gBAAkB,IAAIC,IAC3BrmC,KAAKsmC,eAAiB,IAAIC,IAAY,CACpChvB,OAAQvX,KAAKomC,gBACbl+B,MAAO,IAAI4D,IAAM,CACfI,OAAQ,IAAIC,IAAO,CACjBF,MAAOi6B,GAAsB,CAAC,IAAK,EAAG,EAAG,IACzC95B,MAAO65B,GAAe,IAExBl6B,KAAM,IAAIC,IAAK,CACbC,MAAOk6B,GAAoB,CAAC,IAAK,EAAG,EAAG,MAEzC95B,MAAO,IAAIC,IAAK,CACdlB,OAAQ,CAACA,EAAO,IAAM,GAAKA,EAAO,IAAM,GACxCF,MAAOA,GAAS,IAChBqB,IAAKA,GAAO,mBAIlBvM,KAAKgP,IAAI21B,SAAS3kC,KAAKsmC,kB,uBAGzB,SAAUvjC,GACR,MAAO,CAACA,EAAE,GAAKwZ,KAAKiqB,IAAIzjC,EAAE,GAAKA,EAAE,IAAM,EAAGA,EAAE,GAAKwZ,KAAKiqB,IAAIzjC,EAAE,GAAKA,EAAE,IAAM,K,uBAG3E,SAAU8H,GACR,GAAI7K,KAAKomC,kBACPpmC,KAAKomC,gBAAgBK,QACjB57B,IACF7K,KAAKomC,gBAAgBM,WAAW77B,GAC5BtL,OAAOkf,WAAa,MAAK,CAC3B,IAAIkoB,EAAO97B,EAAQS,cACfq7B,GACF3mC,KAAKgP,IAAIoB,UAAUw2B,UAAU5mC,KAAK6mC,UAAUF,EAAKG,iB,yBAe3D,SAAYhtB,EAAWitB,GAErB,IAAM3O,EACJ4O,QAAQD,EAAgBpwB,eAAe,WACb,UAA1BowB,EAAgB3O,OACU,MAA1B2O,EAAgB3O,MAGZxoB,EAAIm3B,EAAgBn3B,EAGtBmQ,EAAIO,WAAWymB,EAAgBhnB,GACjCE,EAAIK,WAAWymB,EAAgB9mB,GAC/BgnB,EAAIpnC,SAASknC,EAAgBE,EAAG,IAChCC,OAAI1zB,EA6BN,MA5BiC,kBAAtBuzB,EAAgBG,IACzBA,EAAIH,EAAgBG,EAAEv1B,MAAM,MAG1B3G,OAAOwb,MAAMzG,KACfA,EAAIjG,EAAU9K,IAAIi0B,OAAO,IAEvBj4B,OAAOwb,MAAMvG,KACfA,EAAInG,EAAU9K,IAAIi0B,OAAO,IAEvBj4B,OAAOwb,MAAMygB,KACfA,EAAIntB,EAAU9K,IAAI00B,MAGpB5pB,EAAU9K,IAAIopB,MAAQA,EACtBte,EAAU9K,IAAIi0B,OAAO,GAAKljB,EAC1BjG,EAAU9K,IAAIi0B,OAAO,GAAKhjB,EAC1BnG,EAAU9K,IAAI00B,KAAOuD,EAEjBC,IACFlnC,KAAKygC,iBAAmByG,GAGtBt3B,IAEF5P,KAAK0gC,qBAAuB38B,KAAKC,MAAMmjC,mBAAmBv3B,KAGrDkK,I,qCAST,SAAwB/D,GACtB,MAAoB,kBAANA,GAAkBA,EAAExI,OAAOf,OAAS,EAAIuJ,OAAIvC,I,wCAG5D,SAA2B4zB,EAAYC,GACrC,IAAMC,EAA6BF,EAAW/lC,QAAQwhC,OAQtD,OAPqBwE,EAAU72B,QAAO,SAAC/C,GACrC,OAAI65B,EAA2BttB,MAAK,SAAC+F,GAAD,OAAOA,EAAE1d,KAAOoL,EAAMpL,MACjDoL,OAEP,O,sCAMN,SAAyB85B,EAAUC,GACjC,IAAMC,EAA2BF,EAASlmC,QAAQqmC,eAQlD,OAPmBF,EAAWh3B,QAAO,SAAC/C,GACpC,OAAIg6B,EAAyBztB,MAAK,SAAC+F,GAAD,OAAOA,EAAE1d,KAAOoL,EAAMpL,MAC/CoL,OAEP,O,6BAMN,WAEIzN,KAAK6Z,OAAOC,UAAUnD,eAAe,QACrC3W,KAAK6Z,OAAOC,UAAU9K,IAAI2H,eAAe,WAEzC3G,SAASrH,MAAQ3I,KAAK6Z,OAAOC,UAAU9K,IAAIrG,OAG7C,IAAMg/B,EAAoB3nC,KAAK6Z,OAAOC,UAAUC,MAAMC,MAAK,SAAC6e,GAC1D,MAAqB,kBAAdA,EAAKnvB,QAGR09B,EAAapnC,KAAK6Z,OAAOC,UAAUC,MAAMC,MAAK,SAAC6e,GACnD,MAAqB,WAAdA,EAAKnvB,QAGR69B,EAAWvnC,KAAK6Z,OAAOC,UAAUC,MAAMC,MAAK,SAAC6e,GACjD,MAAqB,SAAdA,EAAKnvB,QAGVm5B,EAAS,GAEb,GAAI8E,EAAmB,CACrB9E,EAAO+E,UAAY5nC,KAAK6Z,OAAOorB,aAAa2C,WAAa,GACzD/E,EAAOwE,UAAYrnC,KAAK6Z,OAAOorB,aAAaoC,WAAa,GACzDxE,EAAO2E,WAAaxnC,KAAK6Z,OAAOorB,aAAauC,YAAc,GAC3D3E,EAAOgF,WAAa7nC,KAAK6Z,OAAOorB,aAAa4C,YAAc,GAC3DhF,EAAOiF,aAAe9nC,KAAK6Z,OAAOorB,aAAa6C,cAAgB,GAC/DjF,EAAOkF,aAAe/nC,KAAK6Z,OAAOorB,aAAa8C,cAAgB,GAE/DlF,EAAO+E,UAAUzhC,SAAQ,SAAC+gC,GAAD,OAAQA,EAAEx9B,KAAO,SAC1Cm5B,EAAOgF,WAAW1hC,SAAQ,SAAC+gC,GAAD,OAAQA,EAAEx9B,KAAO,UAC3Cm5B,EAAO2E,WAAWrhC,SAAQ,SAAC+gC,GAAD,OAAQA,EAAEx9B,KAAO,UAC3Cm5B,EAAOiF,aAAa3hC,SAAQ,SAAC+gC,GAAD,OAAQA,EAAEx9B,KAAO,YAC7Cm5B,EAAOkF,aAAa5hC,SAAQ,SAAC+gC,GAAD,OAAQA,EAAEx9B,KAAO,YAE7C,IAAIs+B,EAAS,sBACRnF,EAAO+E,WADC,YAER/E,EAAOgF,YAFC,YAGRhF,EAAOiF,cAHC,YAIRjF,EAAO2E,YAJC,YAKR3E,EAAOkF,eAGZ/nC,KAAK6Z,OAAOorB,aAAe+C,EAG7B,GAAIZ,EAAY,CAAC,IAAD,EAGRC,EAAYrnC,KAAKioC,2BACrBb,EACAvE,EAAOwE,WAQHO,EAAS,UAAGR,EAAW/lC,QAAQ6mC,uBAAtB,aAAG,EAAoCC,SACpD,SAACC,GAEC,IAAM36B,EAAQo1B,EAAO+E,UAAU5tB,MAAK,SAACktB,GAAD,OAAOA,EAAE7kC,KAAO+lC,KAIpD,OAAO36B,EAAM2D,WAAWpC,KAAI,SAACq5B,GAC3B,MAAO,CACLhmC,GAAIgmC,EAAGhmC,GACPimC,IAAK76B,EAAMpL,GACXiC,QAAS+jC,EAAG/jC,QACZsO,IAAKy1B,EAAG7iC,WAAaiI,EAAMmF,IAC3BiwB,OAAQ,CAACwF,EAAGhmC,IACZ4xB,aACmC,kBAA1BoU,EAAG9iC,mBACN8iC,EAAG9iC,mBAAmBoM,MAAM,KAC5B,GACN6F,QAAS6wB,EAAG7wB,SAAW,GACvB+wB,UAAW,GACX5R,cACkC,kBAAzB0R,EAAGljC,kBACNkjC,EAAGljC,kBAAkBwM,MAAM,KAC3B,GACNilB,mBACuC,kBAA9ByR,EAAGjjC,uBACNijC,EAAGjjC,uBAAuBuM,MAAM,KAChC,GACN62B,cAAeH,EAAGhjC,qBAAuB,OACzCojC,aAAcJ,EAAG/iC,oBAAsB,OACvCojC,WAAYj7B,EAAMi7B,YAAc,mBAQxCpiC,MAAMC,QAAQqhC,IAAcP,EAAU73B,KAAV,MAAA63B,EAAS,YAASO,IAE9CR,EAAW/lC,QAAQ2wB,QAAUqV,EAK/B,GAAIE,EACF,GAAwC,OAApCA,EAASlmC,QAAQqmC,eACnBH,EAASlmC,QAAQ2wB,QAAU,QAE3B,GACEuV,EAASlmC,QAAQqmC,gBAC0B,IAA3CH,EAASlmC,QAAQqmC,eAAel7B,OAChC,CACA,GAEE,qBADO+6B,EAASlmC,QAAQqmC,eAAe,GAAGiB,iBAE1C,CAGA,IADA,IAAIC,EAAK,GACA/mB,EAAI,EAAGA,EAAI0lB,EAASlmC,QAAQqmC,eAAel7B,OAAQqV,IAAK,CAC/D,IAAIgnB,EAAU,CACZxmC,GAAIklC,EAASlmC,QAAQqmC,eAAe7lB,GACpC8mB,iBAAkB,IAEpBC,EAAGp5B,KAAKq5B,GAEVtB,EAASlmC,QAAQqmC,eAAiBkB,EAGpC,IAAIpB,EAAaxnC,KAAK8oC,yBACpBvB,EACA1E,EAAO2E,YAETD,EAASlmC,QAAQ2wB,QAAUwV,EAC3B3E,EAAO2E,WAAaA,OAEpBD,EAASlmC,QAAQ2wB,QAAU,GAKjC,OAAOhyB,KAAK+oC,YACV/oC,KAAK6Z,OAAOC,UACZ7T,OAAO+iC,YAAY,IAAIC,gBAAgBj5B,SAASk5B,SAAS3M,c,KAKhDjB,a,o1BCzQA2I,UAzfb,WAAYkF,EAAqBn6B,EAAK2K,GAAM,IAAD,OAEzC,GAFyC,oEAlB1B,CACfyT,oBAAqB,aACrBmB,iBAAkB,GAClBlB,qBAAsB,IACtBF,WAAW,EACXF,iBAAiB,EACjBC,eAAe,KAY0B,oRAJ5B,KAI4B,gDAH9B,IAAIkc,MAG0B,gDAFb,IAAI3G,MAES,KAsB3C5R,WAtB2C,uCAsB9B,WACXjD,GADW,mCAAAnlB,EAAA,6DAEX8kB,EAFW,+BAEK,EAAKsE,aACrB5D,EAHW,+BAGK,EAAKwF,mBAHV,qBAKkC,EALlC,MAMT7F,EAAargB,OACbggB,EACAU,GARS,uBAKHR,EALG,EAKHA,mBAAoBC,EALjB,EAKiBA,OALjB,kBAWJ,CAAED,qBAAoBC,WAXlB,2CAtB8B,2DAoC3C2b,MAAQ,WASN,OARI,cAAI,GAAJ,GAAkB78B,OAAS,GAC7B,cAAI,GAAJ,GAAkBrG,SAAQ,SAACmjC,GACzBA,EAAWD,WAKf,cAAI,GAAJ,GAAoB,IACb,GA7CkC,KAgD3C5V,iBAAmB,WACjB,OAAO,cAAP,OAjDyC,KAoD3C5B,WAAa,WACX,OAAO,cAAP,OArDyC,uFAwD1B,0DAAAppB,EAAA,yDACfmlB,EADe,+BACA,GACfL,EAFe,+BAEC,EAAKsE,aACrB5D,EAHe,+BAGC,MAGZ3nB,MAAMC,QAAQgnB,IAA2C,IAAzBA,EAAc/gB,OANnC,sBAOP,IAAIia,MAAM,yCAPH,cAWsB,IAAjCngB,MAAMC,QAAQgnB,KAChB5Z,QAAQwS,KAAK,6CAA8CoH,GAC3DA,EAAgB,EAAKsE,cAIjB1hB,EAAW,GAGbo5B,EAAa,KAGjB,cAAI,GAAJ,GAAoB,GAEd96B,EAAiB,cAAI,GAAJ,GAAU2B,UAAUT,gBAAgBU,UAG3Dkd,EAAcpnB,SAAQ,SAACqjC,GAErB,kBAAgC,EAAhC,MACE5b,EACA4b,EACAvb,GAHMrd,EAAR,EAAQA,QAAS04B,EAAjB,EAAiBA,WASD,OAAZ14B,GAAmC,OAAf04B,IAEtBn5B,EAASX,KAAKoB,GAGd,cAAI,GAAJ,GAAkBpB,KAAK85B,OA5CZ,UAiDcp2B,QAAQ4iB,WAAW3lB,GAjDjC,eAiDTs5B,EAjDS,iBAqDgBv2B,QAAQ4iB,WACrC2T,EAAez6B,KAAI,SAAC06B,EAAe7nB,GAEjC,GAA6B,aAAzB6nB,EAAc1T,OAChB,OAAO9iB,QAAQqC,OAAO,mBAGxB,OAAQgY,EAAc1L,GAAG4mB,cACvB,IAAK,mBACL,IAAK,2BACH,OAAOiB,EAAcvmC,MAAMoQ,OAG7B,IAAK,OACL,IAAK,OACL,IAAK,QACH,OAAOm2B,EAAcvmC,MAAM5C,OAC7B,QACE,OAAO2S,QAAQqC,OAAO,kCAvEf,eAqDTo0B,EArDS,OA8ETC,EAAsB,GACtBlc,EAAS,GAIfic,EAAiBxjC,SAAQ,SAAC+P,EAAG2L,GACV,cAAb3L,EAAE8f,QACJ9f,EAAEqB,OAASgW,EAAc1L,GACzB3L,EAAE6e,OAAS,MACX6U,EAAoBp6B,KAAK0G,IAChB,SAACA,GAAD,MAAoB,aAAbA,EAAE8f,UAClB9f,EAAEqB,OAASgW,EAAc1L,GACzB3L,EAAE6e,OAAS,MACXrH,EAAOle,KAAK0G,OAKhB0zB,EAAoBzjC,SAAQ,SAAC+P,GAc3B,OAAQA,EAAEqB,OAAOkxB,cACf,IAAK,mBACL,IAAK,2BAIH,IAAM95B,EAAgBuH,EAAE/S,MAAMyL,IAC1B,GACA,CACEC,eAAgB,YAChBC,kBAAmBL,GAInBo7B,GAAa,IAAIn7B,KAAUmF,aAAaqC,EAAE/S,MAAOwL,GACvDuH,EAAE/S,MAAQ,CAAEuK,SAAUm8B,GACtB,MAEF,IAAK,OACL,IAAK,OACL,IAAK,QACH,IAAI77B,EAAS,KACiB,SAA1BkI,EAAEqB,OAAOkxB,aACXz6B,EAAS,IAAI87B,IACsB,SAA1B5zB,EAAEqB,OAAOkxB,aAClBz6B,EAAS,IAAI+7B,IACsB,UAA1B7zB,EAAEqB,OAAOkxB,eAClBz6B,EAAS,IAAIg8B,KAEf,IAAMH,EAAa77B,EAAO6F,aAAaqC,EAAE/S,OACzC+S,EAAE/S,MAAQ,CAAEuK,SAAUm8B,GACtB,MAGF,QACE,MAAM,IAAIpjB,MAAM,6BAKtB8iB,EAAa,CAAE9b,mBAAoBmc,EAAqBlc,UAtJzC,kBAwJR6b,GAxJQ,4CAxD0B,uGAmN5B,SAACnV,EAAMoV,EAAcvb,GAMlC,OALY,YAAOgc,IAAP,YACPT,EAAavV,aAAajlB,KAAI,SAACk7B,GAChC,OAAO,cAAP,MAA6BA,EAAa9V,EAAMnG,WAtNX,gDA4NxB,SAACic,EAAa9V,EAAMnG,GACrC,OAAO,IAAIkc,IACTD,EACA9V,EAvPgB,IADF,IADA,IA6PdnG,EAAcd,cAnOyB,gDAuOvB,SAACid,EAAYZ,EAAcvb,GAC7C,GAAIub,EAAavV,aAAaznB,OAAS,EAAG,CACxC,IAAI69B,EAAYD,EAAWp7B,KAAI,SAAColB,GAC9B,OAAO,cAAP,MAAyBA,EAAMoV,EAAcvb,MAE/C,OAAIoc,EAAU79B,OAAS,EACd,YAAI89B,IAAX,YAAkBD,IAEXA,EAAU,GAGnB,IAAIE,EAAgBH,EAAWp7B,KAAI,SAAColB,GAClC,OAAO,cAAP,MACEoV,EAAavV,aAAa,GAC1BG,EACAnG,MAGJ,OAAIsc,EAAc/9B,OAAS,EAClB,YAAI89B,IAAX,YAAkBC,IAEXA,EAAc,MA5PgB,gDAiQzB,SAAC3c,GAEjB,OADmB,YAAG,EAAH,MAA8BA,GAC1Btb,KAAK,KAAKX,MAAM,QAnQE,gDAsQnB,SAACic,GACvB,OAAOA,EAAajc,MAAM,KAAK3C,KAAI,SAAC9O,GAClC,OAAOA,EAAOqN,aAxQyB,gDA4QrB,SAACrN,GACrB,OAAOA,EAAOC,QAAQ,sBAAuB,UA7QJ,KAgR3CqqC,8BAAgC,SAAC5c,GAG/B,GAAI,cAAI,GAAJ,GAAiC5b,IAAI4b,GACvC,OAAOtnB,MAAM2jB,KAAK,cAAI,GAAJ,GAAiCtZ,IAAIid,IAKzD,IAAM6c,EAA6B,IAAI54B,IACjCqiB,EAAgB,YAAG,EAAH,MAAwBtG,GACxC8c,EAAWxW,EAAiB1nB,OAYlC,GAPIohB,EAAa9Y,SAAS,MACxB21B,EAA2BnkB,IAAI,CAACsH,IAM9B8c,EAAW,EAAG,CAChB,IAAMC,EAAazW,EAAiB5hB,OAAOnS,QAAQ,KAAM,KAEzD,OADAsqC,EAA2BnkB,IAAI,CAACqkB,IACzBrkC,MAAM2jB,KAAKwgB,GAKpB,GAFAA,EAA2BnkB,IAAI4N,GAE3BwW,EAAW,EACb,IAAK,IAAI7oB,EAAI,EAAGA,EAAI6oB,EAAU7oB,IAC5B,cAAI,GAAJ,GACEA,EACAqS,EACAuW,GAYN,OALA,cAAI,GAAJ,GAAiC3X,IAC/BlF,EACA6c,GAGKnkC,MAAM2jB,KAAKwgB,IAhUuB,gDAmUT,SAChCh0B,EACAm0B,EACAH,GAIA,IAFA,IAAMI,EAAqBD,EAAY3iB,MAAM,EAAGxR,GAEvCq0B,EAAKr0B,EAAOq0B,EAAKF,EAAYp+B,OAAS,EAAGs+B,IAAM,CACtD,IAAMC,EAAcH,EACjB3iB,MAAMxR,EAAOq0B,EAAK,GAClBx4B,OACAnS,QAAQ,KAAM,KAEX6qC,EAAoBJ,EAAY3iB,MAAM6iB,EAAK,GAEjDL,EAA2BnkB,IAA3B,sBACKukB,GADL,CAEEE,GAFF,YAGKC,SArVkC,gDA0VlB,SAAC5W,EAAMnG,GAG9B,OAFAmG,EAAOnG,EAAchB,gBAAd,WAAoCmH,GAASA,EACpDA,EAAOnG,EAAcf,cAAd,UAAiCkH,EAAjC,KAA2CA,KA5VT,gDAgWZ,SAAC6W,GAC9B,OAAOA,EAAmBj8B,KAAI,SAACk8B,GAC7B,OAAOA,EAAYl8B,KAAI,SAAColB,GAItB,OAAOh0B,uBAAag0B,GAAMj0B,QAAQ,MAAO,iBAtWJ,gDA2WjC,SAACytB,EAAc4b,EAAcvb,GACrC,IAAMkd,EAAU,cAAI,GAAJ,GAAU/6B,UAAUT,gBAAgBU,UAC9C+6B,EACJ5B,EAAahB,eAAiBgB,EAAa4B,cAAgB,OACvDC,EAAcpd,EAAcZ,qBAC9Bie,EAAoB,KACpBC,EAAiB,KACjBC,EAAe,KACff,EAA6B,GAIjC,GAAqB,KAAjB7c,GAAuB4b,EAAavV,aAAaznB,OAAS,EAAG,CAC3DyhB,EAAc0F,wBAChB8W,EACE,EAAKD,8BAA8B5c,GAErC6c,EAA2Bj7B,KAA3B,YACE,EADF,MAC6Boe,IAQ/B,IAAM6d,GAJNhB,EAA0B,YAAG,EAAH,MACxBA,IAG+Cz7B,KAAI,SAACk8B,GACpD,IAAIQ,EAA4BR,EAAYl8B,KAAI,SAAC28B,GAM/C,OALAA,EAAiB,YAAG,EAAH,MAA4BA,GAC7CA,EAAiB,YAAG,EAAH,MACfA,EACA1d,MAIJ,OAAO,cAAP,MACEyd,EACAlC,EACAvb,MAIJqd,EACEG,EAAcj/B,OAAS,EAAvB,YAA+By9B,IAA/B,YAAqCwB,IAAiBA,EAAc,GAKxE,GAAIxd,EAAcM,iBAAiB/hB,OAAS,EAAG,CAE7C,IAAM4gB,EACkC,WAAtCa,EAAcb,oBAAmCwe,IAASC,IAyB5DN,GAvBAA,EAAiBtd,EAAcM,iBAAiBvf,KAAI,SAACnE,GAOnD,IAAMihC,EACgC,WAApCjhC,EAAQS,cAAcygC,UAClBC,YAAWnhC,EAAQS,eACnBT,EAAQS,cAAc6e,QAQ5B,MAF4B,SAA5Bqf,EAAad,YACXoD,EAASG,gBAAgBC,QAAQ,EAAG,GAC/B,IAAI9e,EAAoBge,EAAcU,EAAUX,OAMxC3+B,OAAS,EAAxB,YACQy9B,IADR,YACcsB,IACVA,EAAe,GAyBvB,GApB0B,OAAtBD,GAAiD,OAAnBC,EAEhCC,EAAe,IAAIlB,IAAIgB,EAAmBC,GACX,OAAtBD,EACTE,EAAeF,EACa,OAAnBC,IACTC,EAAeD,GAcI,OAAjBC,EACF,MAAO,CAAE56B,QAAS,KAAM04B,WAAY,MAItC,IAAMjoC,EAAU,CACd8qC,aAAc3C,EAAa3G,OAC3BsI,QAASA,EACT1C,aAAce,EAAaf,aAC3B2C,aAAcA,EACdC,YAAaA,EACb76B,OAAQg7B,GAGJY,EAAO,cAAI,GAAJ,GAAgBC,gBAAgBhrC,GAEvCirC,GADgB,IAAIC,eACMC,kBAAkBJ,GAC5C9C,EAAa,IAAImD,gBAGjBC,EAAU,CACdC,YAAa,cACbC,OAJatD,EAAWsD,OAKxBC,OAAQ,OACRv5B,QAAS,CACP,eAAgB,YAElB0K,KAAMsuB,GAOR,MAAO,CAAE17B,QALOkC,iBACd,cAAI,GAAJ,GAAU+G,OAAOwjB,UAAUyP,YAActD,EAAa52B,IACtD85B,GAGgBpD,kBAnfbH,IAAwBn6B,IAAQ2K,EACnC,MAAM,IAAI8M,MACR,8DAIJ,YAAAzmB,KAAA,MAAyBmpC,EACzB,YAAAnpC,KAAA,MAAYgP,EACZ,YAAAhP,KAAA,MAAY2Z,EACZ,YAAA3Z,KAAA,MAAsB,YAAAA,KAAA,MAAuBgyB,U,oDCzClC2P,UAXb,WAAYoL,GAAO,oBACjB/sC,KAAKwwB,gBAAkBuc,EAAKvc,gBAC5BxwB,KAAKgP,IAAM+9B,EAAK/9B,IAChBhP,KAAK2Z,IAAMozB,EAAKpzB,IAChB3Z,KAAK0J,KAAOqjC,EAAKrjC,KACjB1J,KAAKqB,QAAU0rC,EAAK1rC,QACpBrB,KAAKmJ,UAAY4jC,EAAK5jC,UACtBnJ,KAAKmhC,UAAY4L,EAAK5L,WAAa,I,2HCNlBoD,E,WACnB,WAAYC,GAAQ,oBAClBxkC,KAAKwkC,MAAQA,E,gDAGf,SAAa9e,EAAMthB,GAAa,IAAD,EAC7B,SAAS4oC,EAAav/B,GACpB,IAAIw/B,EAAY,GAGhB,GAAoB,KAAhBvnB,EAAKzgB,OAAe,CAOtB,IAAIioC,EACkB,OAApBxnB,EAAKtU,WACDsU,EAAKtU,WAAWuH,WAAU,SAACuuB,GAAD,OAAOA,EAAE7kC,KAAOoL,KAC1C,KAEFvF,EACkB,OAApBwd,EAAKtU,YACL87B,GAAY,GACZxnB,EAAKtU,WAAW87B,GAAUhlC,MAExBilC,EAAyB,GACzBC,EAAc,GAEM,cAApB1nB,EAAKgjB,aAMPyE,EAAyB/oC,EAAW0V,UAAU9K,IAAI2H,eAChD,0BAEE,mBACAvS,EAAW0V,UAAU9K,IAAIm+B,uBACzB,IAIkB,SAApBznB,EAAKgjB,aACP0E,EAAc,gBAKhB,IAAMC,EAAU3nB,EAAK9S,IAAIkC,SAAS,KAAO,IAAM,IAE/Cm4B,EAAS,UAAMzI,GAAN,OAAc9e,EAAK9S,KAAnB,OAAyBy6B,EAAzB,yEAAiG5/B,EAAjG,kBAAgHvF,GAAhH,OAAwHilC,GAAxH,OAAiJC,QAI1JH,EAAYvnB,EAAKzgB,OAKnB,OADiB,QAAQyP,KAAKu4B,GAAa,GAAK,YAC9BA,EA4BpB,IAAIzI,EAAQxkC,KAAKwkC,OAAS,GAItBhB,EACkB,OAApB9d,EAAK8d,WACD9d,EAAK8d,WACLp/B,EAAW0V,UAAU9K,IAAIw0B,WAG/B,GAAqB,UAAjB9d,EAAK4nB,QAAqB,CAE5B,IAAIC,EAAW/J,EACfA,EAAa,IAAIgK,IAAW,CAC1BC,KAAMF,EACNG,gBAAiB,MACjBxK,OAAQ9+B,EAAW0V,UAAU9K,IAAIk0B,SAMrC,IAAMyK,EAA4B,UAAjBjoB,EAAK4nB,QAAsB,MAAQ,MAE/B,IAAjB5nB,EAAK6d,SAAkC,IAAjB7d,EAAK4d,UAE7B5d,EAAK6d,aAAU/vB,EACfkS,EAAK4d,aAAU9vB,GAGjB,IAAIqG,EAAS,CACXnQ,KAAM,MACNrI,QAAS,CACPgB,GAAIqjB,EAAKrjB,GACTuQ,KACG5S,KAAKwkC,OAAS,KACdxkC,KAAK4tC,sBAAsBloB,EAAKmoB,kBAAoBnoB,EAAK9S,KAC5D2X,KAAM7E,EAAKrjB,GACXoD,UAAWigB,EAAKjgB,UAChBnB,QAASohB,EAAKphB,QACdwpC,QAASpoB,EAAKkgB,eACdmI,QAASroB,EAAKqoB,SAAW,EACzBzK,QAAS5d,EAAK4d,QACdC,QAAS7d,EAAK6d,QACdyK,4BAA6BtoB,EAAKsoB,4BAClCnpC,kBAAmB6gB,EAAK7gB,kBACxBC,kBAAmB4gB,EAAK5gB,kBACxBC,sBAAuB2gB,EAAK3gB,sBAC5BC,YAAa0gB,EAAKlO,QAClBspB,YAAa18B,EAAW0V,UAAU9K,IAAI6xB,eACtC2C,WAAYA,GAAc,YAC1BzO,OAAQ3wB,EAAW0V,UAAU9K,IAAI+lB,OACjCmO,OAAQ9+B,EAAW0V,UAAU9K,IAAIk0B,OACjC+K,WAAYvoB,EAAKuoB,aAAc,EAC/BC,MAAOxoB,EAAKwoB,MACZC,YAAazoB,EAAKyoB,YAClBC,YAAa1oB,EAAK0oB,aAAe,YACjC1F,WACsB,WAApBhjB,EAAKgjB,WACD,YACAhjB,EAAKgjB,YAAc,YACzB2F,YAAajqC,EAAW0V,UAAU9K,IAAIq/B,aAAe,YACrDhqC,YAAaqhB,EAAKrhB,YAClBmB,UAAWkgB,EAAKlgB,UAChBD,mBAAoBmgB,EAAKngB,mBACzBJ,kBAAmBugB,EAAKvgB,kBACxBC,uBAAwBsgB,EAAKtgB,uBAC7BE,mBAAoBogB,EAAKpgB,mBACzBD,oBAAqBqgB,EAAKrgB,oBAC1BJ,OA7FKygB,EAAKmd,OAAO7zB,KAAI,SAACvB,GACtB,MAAO,CACLmF,IAAKo6B,EAAav/B,GAClB2d,YAAa,0BA2FflmB,WAAYwgB,EAAKxgB,WACjBgN,OAAO,yBACLo8B,OAAQ5oB,EAAKmd,OAAOvwB,KAAK,MACrBoT,EAAKogB,WAAa,CAAEyI,WAAY7oB,EAAKogB,YAFrC,OAGJ0I,OAAQ9oB,EAAK0oB,YACbh8B,YAAasT,EAAK+oB,WAClBC,QAAShpB,EAAK4nB,SAAW,SALrB,cAMHK,EAAWnK,GAAc,aANtB,sBAOG9d,EAAKipB,OAPR,uBAQIroC,MAAMC,QAAQmf,EAAKtU,YACvBsU,EAAKtU,WAAWpC,KAAI,SAACk4B,GAAD,OAAOA,EAAEh/B,OAAS,MAAIoK,KAAK,KAC/C,MAVA,IAYNlB,WAnGJ,SAAuBA,EAAYoG,GACjC,GAAIlR,MAAMC,QAAQ6K,GAChB,OAAOA,EAAWrL,QAAO,SAAC6oC,EAAkBjhC,GAS1C,OARAihC,EAAiBjhC,EAAUtL,IAAMsL,EAC5BA,EAAU1I,SACb2pC,EAAiBjhC,EAAUtL,IAAI4C,OAAS+nC,EAAar/B,EAAUtL,MAEjE,OAAImV,QAAJ,IAAIA,OAAJ,EAAIA,EAAShL,UACXoiC,EAAiBjhC,EAAUtL,IAAImV,QAAUA,GAGpCo3B,IACN,IAuFSC,CAAcnpB,EAAKtU,WAAYsU,EAAKlO,SAChD5S,YAAa8gB,EAAK9gB,cAAe,EACjCH,UAAWihB,EAAKjhB,UAChBD,SAAUkhB,EAAKlhB,SACfE,QAASghB,EAAKhhB,QACdC,YAAa+gB,EAAK/gB,YAClBJ,UAAWmhB,EAAKnhB,UAChBmB,gBAAiBggB,EAAKhgB,gBACtBopC,gBAAiBppB,EAAKopB,gBACtBC,cAAerpB,EAAKqpB,gBAkBxB,OAdIrpB,EAAKuO,cAAgBvO,EAAKuO,aAAa,KACzCpa,EAAOxY,QAAQk7B,OAAS,CACtB3pB,KAAM5S,KAAKwkC,OAAS,IAAM9e,EAAK9S,IAAIzS,QAAQ,MAAO,OAClD6uC,YACEtpB,EAAKmd,OAAO,GAAGlxB,MAAM,KAAK,IAAM+T,EAAKmd,OAAO,GAAGlxB,MAAM,KAAK,GAC5DoD,aAAc2Q,EAAKuO,aAAa3hB,KAAK,KACrC28B,YAAavpB,EAAKiR,cACdjR,EAAKiR,cACLjR,EAAKuO,aAAa,IAAM,iBAC5BkX,QAAS/mC,EAAW0V,UAAU9K,IAAIw0B,YAAc,YAChDkF,WAAY7uB,EAAOxY,QAAQqnC,aAIxB7uB,I,mCAMT,SAAsBg0B,GACpB,OAAsB,OAAfA,QAAe,IAAfA,OAAA,EAAAA,EAAiBtgC,OAAOf,QAAS,EAAIqhC,EAAkB,O,2BAGhE,SAAcnoB,EAAMthB,GA4ClB,OA3CqB,IAAjBshB,EAAK6d,SAAkC,IAAjB7d,EAAK4d,UAC7B5d,EAAK6d,aAAU/vB,EACfkS,EAAK4d,aAAU9vB,GAGJ,CACX9J,KAAM,OACNrI,QAAS,CACPgB,GAAIqjB,EAAKrjB,GACTkoB,KAAM7E,EAAKrjB,GACXoD,UAAWigB,EAAKjgB,UAChBnB,QAASohB,EAAKphB,QACdwpC,SAAiC,IAAxBpoB,EAAKkgB,eACd1C,OAAQ9+B,EAAW0V,UAAU9K,IAAIk0B,OACjCnxB,WAAW,EACXg8B,QAASroB,EAAKqoB,SAAW,EACzBzK,QAAS5d,EAAK4d,QACdC,QAAS7d,EAAK6d,QACd2L,OAAQ,YACRb,YAAajqC,EAAW0V,UAAU9K,IAAIq/B,aAAe,YACrDc,OAAO,EACPv8B,IAAK8S,EAAK9S,IACVnF,MAAOiY,EAAKjY,MACZ2hC,UAAW1pB,EAAK0pB,UAChBlnC,MAAOwd,EAAKxd,MACZs7B,WAAY9d,EAAK8d,WACjBzO,OAAQrP,EAAKqP,OACb+L,YAAapb,EAAKob,YAClBuO,UAAW3pB,EAAK2pB,UAChBhrC,YAAaqhB,EAAKrhB,YAClBY,OAAQygB,EAAKzgB,OACbC,WAAYwgB,EAAKxgB,WACjBN,YAAa8gB,EAAK9gB,cAAe,EACjCH,UAAWihB,EAAKjhB,UAChBD,SAAUkhB,EAAKlhB,SACfE,QAASghB,EAAKhhB,QACdC,YAAa+gB,EAAK/gB,YAClBJ,UAAWmhB,EAAKnhB,UAChBmB,gBAAiBggB,EAAKhgB,gBACtBopC,gBAAiBppB,EAAKopB,gBACtBC,cAAerpB,EAAKqpB,kB,2BAM1B,SAAcrpB,GAiBZ,MAhBa,CACXhc,KAAM,OACNrI,QAAS,CACPgB,GAAIqjB,EAAKrjB,GACTuQ,KAAM5S,KAAKwkC,OAAS,IAAM9e,EAAK9S,IAC/B2X,KAAM7E,EAAKrjB,GACXoD,UAAWigB,EAAKjgB,UAChBnB,QAASohB,EAAKphB,QACdwpC,QAASpoB,EAAKkgB,eACdmI,QAAS,EACTh8B,WAA8B,IAAnB2T,EAAK3T,UAChBmxB,OAAQxd,EAAKwd,OACbM,WAAY9d,EAAK8d,e,6BAOvB,SAAgB9d,GAqEd,MApEa,CACXhc,KAAM,SACNrI,QAAS,CACPgD,YAAaqhB,EAAKrhB,YAClBC,QAASohB,EAAKphB,QACdqR,QAAS+P,EAAK/P,QACd25B,WAAY5pB,EAAK4pB,WACjBxlC,UAAW4b,EAAK5b,UAChBylC,WAAY7pB,EAAK6pB,WACjBC,gBAAiB9pB,EAAK8pB,gBACtBC,eAAgB/pB,EAAK+pB,eACrBC,YAAahqB,EAAKgqB,YAClBpjB,KAAM5G,EAAK4G,KACXjqB,GAAIqjB,EAAKrjB,GACTkC,UAAWmhB,EAAKnhB,UAChBS,YAAa0gB,EAAKlO,QAClBhT,SAAUkhB,EAAKlhB,SACfC,UAAWihB,EAAKjhB,UAChBC,QAASghB,EAAKhhB,QACdC,YAAa+gB,EAAK/gB,YAClBC,YAAa8gB,EAAK9gB,cAAe,EACjCC,kBAAmB6gB,EAAK7gB,kBACxBC,kBAAmB4gB,EAAK5gB,kBACxBC,sBAAuB2gB,EAAK3gB,sBAC5BU,UAAWigB,EAAKjgB,UAChBR,OAAQ,CACN,CACE2N,IAAK8S,EAAKzgB,OACVmmB,YAAa1F,EAAKphB,UAGtBY,WAAYwgB,EAAKxgB,WACjByqC,UAAWjqB,EAAKiqB,UAChBC,UAAWlqB,EAAKkqB,UAChBC,UAAWnqB,EAAKmqB,UAChBvM,QAAS5d,EAAK4d,QACdC,QAAS7d,EAAK6d,QACdhZ,KAAM7E,EAAKrjB,GACX0rC,QAASroB,EAAKqoB,QACd77B,OAAQ,CACN22B,QAAS,MACT6D,QAAS,aACTY,QAAS5nB,EAAK4nB,SAAW,QACzB7E,aACsB,YAApB/iB,EAAK4pB,WACD,mBACiB,UAAjB5pB,EAAK4nB,QACL,OACA,OACNwC,SAAUpqB,EAAKjY,MACfsiC,QAASrqB,EAAK8d,WACdwM,KAAM,IAERC,UAAWvqB,EAAKuqB,UAChBzM,WAAY9d,EAAK8d,WACjBzxB,UAAW2T,EAAK3T,UAChBm+B,SAAUxqB,EAAKwqB,SACfC,QAASzqB,EAAKyqB,QACdC,OAAQ1qB,EAAK0qB,OACbC,cAAe3qB,EAAK2qB,cACpBC,cAAe5qB,EAAK4qB,cACpB19B,IAAK8S,EAAK9S,IACVk7B,QAASpoB,EAAKkgB,eACdkJ,gBAAiBppB,EAAKopB,gBACtBC,cAAerpB,EAAKqpB,kB,6BAO1B,SAAgBrpB,GAiDd,MArCa,CACXhc,KAAM,SACNrI,QAAS,CACPgB,GAAIqjB,EAAKrjB,GACTuQ,IAAK8S,EAAK9S,IACV2X,KAAM7E,EAAKrjB,GACXoD,UAAWigB,EAAKjgB,UAChBnB,QAASohB,EAAKphB,QACdwpC,QAASpoB,EAAKkgB,eACd7zB,WAA8B,IAAnB2T,EAAK3T,UAChBk8B,YAAgC,IAApBvoB,EAAKuoB,WACjB/K,OAAQxd,EAAKwd,OACbl+B,YAAa0gB,EAAKlO,QAClBgsB,WAAY9d,EAAK8d,WACjBuK,QAASroB,EAAKqoB,QACd1pC,YAAaqhB,EAAKrhB,YAClB6N,OAAQ,CACNo8B,OAAQ,QAAU5oB,EAAKmd,OAAOvwB,KAAK,MAErCrN,OAAQ,CACN,CACE2N,KA/BDtM,MAAMC,QAAQmf,EAAKzgB,UAClB,QAAQyP,KAAKgR,EAAKzgB,QACpBygB,EAAKzgB,OAASygB,EAAKzgB,OAAO0M,MAAM,KACtB,QAAQ+C,KAAKgR,EAAKzgB,UAC5BygB,EAAKzgB,OAAS,WAAaygB,EAAKzgB,SAG7BygB,EAAKzgB,QAyBNmmB,YAAa,wBAGjBxmB,YAAa8gB,EAAK9gB,cAAe,EACjCH,UAAWihB,EAAKjhB,UAChBD,SAAUkhB,EAAKlhB,SACfE,QAASghB,EAAKhhB,QACdC,YAAa+gB,EAAK/gB,YAClBJ,UAAWmhB,EAAKnhB,UAChBmB,gBAAiBggB,EAAKhgB,gBACtBopC,gBAAiBppB,EAAKopB,gBACtBC,cAAerpB,EAAKqpB,oB,uHCtYPxO,E,WACnB,WAAY1mB,GAAS,oBACfvT,MAAMC,QAAQsT,IAChBA,EAAO1T,SAAQ,SAACq9B,IAPtB,SAAaA,GACX+M,IAAMC,KAAKhN,EAAWiK,KAAMjK,EAAWiN,YAOjCnqB,CAAIkd,M,4CAKV,WACE,OAAO+M,Q,mLCLL7L,E,WACJ,WAAY7qB,EAAQ62B,EAAUvxC,GAAiB,IAAD,gCAiI9CwxC,gBAAkB,WAChB,EAAKxxC,eAAeG,QAAQ,mCAAoC,CAC9D+C,GAAI,EAAKoL,MAAMkD,IAAI,QACnBqlB,OAAQ,eApIkC,KA4I9C4a,aAAe,WACb,EAAKzxC,eAAeG,QAAQ,mCAAoC,CAC9D+C,GAAI,EAAKoL,MAAMkD,IAAI,QACnBqlB,OAAQ,QA/IkC,KAwJ9C6a,aAxJ8C,uCAwJ/B,WAAO9tC,GAAP,mBAAA0F,EAAA,yDACPqoC,EAAc,EAAKrjC,MAAMiC,YACzBqhC,EAAsBhuC,EAAEM,OAAOsN,IAAI,wBAA0B,GAC7DqgC,EAAqBjuC,EAAEsJ,MAAM62B,OAC9B+N,iBAAOF,EAAqBC,GAJpB,gCAKL1oB,gBAAM,KALD,OAMXwoB,EAAYI,UAND,OAQbnuC,EAAEM,OAAOyvB,IAAI,sBAAuBke,GARvB,2CAxJ+B,sDAC5ChxC,KAAK0wC,SAAWA,EAChB1wC,KAAKb,eAAiBA,EACtBa,KAAKmxC,WAAY,EACjBnxC,KAAKiF,OAAS4U,EAAO5U,OACrBjF,KAAKqE,YAAcwV,EAAOxV,YAC1BrE,KAAK2N,UAAY,IAAIxJ,UAAU0V,GAC/B7Z,KAAKuR,UAAYsI,EAAO3H,OAAP,OAAwBP,MAAM,KAE/C,IAAI4F,EAAS,CACX3E,IAAKiH,EAAOjH,IACZV,OAAQ2H,EAAO3H,OACfsxB,WAAY3pB,EAAO2pB,WACnBkF,WAAY7uB,EAAO6uB,WACnB2F,YAAax0B,EAAOw0B,YACpBD,YAAav0B,EAAOu0B,YACpBgD,aAAcv3B,EAAOxV,YACrBgtC,UAAWrxC,KAAKuR,UAAU/E,OAAS,EAAI,GAAK,KAC5C8kC,WAAYtxC,KAAKuR,UAAU/E,OAAS,EAAI,EAAI,KAGzB,OAAjBqN,EAAOq0B,QACT32B,EAAO22B,MAAQr0B,EAAOq0B,OAGxBqD,oCAA0Bh6B,GAE1B,IAAMgsB,GAAgB,OAAN1pB,QAAM,IAANA,OAAA,EAAAA,EAAQ0pB,UAAW,EAAI1pB,EAAO0pB,aAAU/vB,EAClD8vB,GAAgB,OAANzpB,QAAM,IAANA,OAAA,EAAAA,EAAQypB,UAAW,EAAIzpB,EAAOypB,aAAU9vB,EAGtDqG,EAAOinB,aACPjnB,EAAOinB,YAAYt0B,OAAS,GAC5BqN,EAAOkb,QACPlb,EAAOkb,OAAOvoB,OAAS,IAEvB+K,EAAOi6B,SAAW,IAAIC,IAAS,CAC7B3Q,YAAajnB,EAAOinB,YACpB/L,OAAQlb,EAAOkb,SAEjBxd,EAAO2rB,OAASrpB,EAAOqpB,QAGrBrpB,EAAOo0B,YACLp0B,EAAOs0B,aAAe,IACxB52B,EAAOm6B,MAAQ73B,EAAOs0B,aAExBnuC,KAAKyN,MAAQ,IAAIiD,IAAW,CAC1B6Z,KAAM1Q,EAAO0Q,KACbujB,QAASj0B,EAAOi0B,QAChBxpC,QAASuV,EAAOvV,QAChBypC,QAASl0B,EAAOk0B,QAChBx2B,OAAQ,IAAIo6B,IAASp6B,GACrB5J,UAAW3N,KAAK2N,UAChBiF,IAAKiH,EAAOjH,IACZk8B,gBAAe,OAAEj1B,QAAF,IAAEA,OAAF,EAAEA,EAAQi1B,gBACzBC,cAAa,OAAEl1B,QAAF,IAAEA,OAAF,EAAEA,EAAQk1B,cACvBxL,QAASA,EACTD,QAASA,EACT0K,4BACEn0B,EAAOm0B,8BAA+B,KAG1ChuC,KAAKyN,MAAQ,IAAIgD,IAAU,CACzB8Z,KAAM1Q,EAAO0Q,KACbujB,QAASj0B,EAAOi0B,QAChBxpC,QAASuV,EAAOvV,QAChBypC,QAASl0B,EAAOk0B,QAChBx2B,OAAQ,IAAIq6B,IAAQr6B,GACpB5J,UAAW3N,KAAK2N,UAChBiF,IAAKiH,EAAOjH,IACZk8B,gBAAe,OAAEj1B,QAAF,IAAEA,OAAF,EAAEA,EAAQi1B,gBACzBC,cAAa,OAAEl1B,QAAF,IAAEA,OAAF,EAAEA,EAAQk1B,cACvBxL,QAASA,EACTD,QAASA,EACT0K,4BACEn0B,EAAOm0B,8BAA+B,IAI5ChuC,KAAKyN,MAAM2D,WAAayI,EAAOzI,WAC/BpR,KAAKyN,MAAM8D,UAAYvR,KAAKuR,UAC5BvR,KAAKyN,MAAMhI,UAAYzF,KAAK6xC,eAC5B7xC,KAAKyN,MAAMiC,YAAYojB,IAAI,MAAOjZ,EAAOjH,KACzC5S,KAAK0J,KAAO,MACZ1J,KAAKg8B,e,gDAWP,WAOE,MAAqB,SALCh8B,KAAK2N,UAAnBlI,UAMJ,OACAzF,KAAKuR,UAAU/E,OAAS,EACxB,QACA,U,0BAON,WACE,IAAMskC,EAAc9wC,KAAKyN,MAAMiC,YAC3BohC,aAAuBc,MACzBd,EAAY38B,GAAG,gBAAiBnU,KAAK2wC,iBACrCG,EAAY38B,GAAG,cAAenU,KAAK4wC,eAEjCE,aAAuBa,KACzBb,EAAY38B,GAAG,iBAAkBnU,KAAK6wC,gB,mCAgD1C,SAAsB3+B,GAAS,IAAD,OAC5B,IACElS,KAAKmxC,WAAY,EACjBnxC,KAAK8xC,2BAA6B5/B,EAAO6/B,QAEzC,IAAIn/B,EAAM5S,KAAKgyC,WACZtiC,YACAmD,kBACCX,EAAOrB,WACPqB,EAAOpB,WACPoB,EAAOsxB,WACP,CACEpxB,YAC6B,WAA3BpS,KAAK2Q,IAAI,eACkB,cAA3B3Q,KAAK2Q,IAAI,cACL,sBACA,mBACNshC,cAAe,MAIjBr/B,IACE5S,KAAK0wC,WACP99B,EAAMs/B,mBAAmBt/B,IAG3BE,iBAAO9S,KAAK0wC,SAAW99B,GACpBI,MAAK,SAAC3E,GACLA,EAASkF,OAAOP,MAAK,SAACmK,GACpB,IAAIzP,GAAW,IAAIgB,KAAUmF,aAAasJ,GAC1C,EAAK20B,2BAA2BpkC,EAAU,EAAKskC,kBAGlDv+B,OAAM,SAACC,GACNxB,EAAOjO,MAAMyP,OAGnB,MAAO3Q,GACPmP,EAAOjO,MAAMlB,M,0BAUjB,SAAauM,GACX,IAAIrK,EAASgB,OAAOksC,OAAO,GAAInyC,KAAKiF,QAEpC,OADAA,EAAO,GAAGmtC,IAAMntC,EAAO,GAAGmtC,IAAIjyC,QAAQ,WAAY,SAAWmP,GACtDrK,M,KAUIy/B,a,yHC3OX2N,EAAsB,CACxBz/B,IAAK,GACL4wB,WAAY,YACZ/1B,MAAO,GACPsgC,QAAS,EACTqB,UAAW,OACXlnC,MAAO,UACPoqC,SAAU,UACVvd,OAAQ,EAAE,KAAS,MACnB+L,YAAa,CAAC,KAAM,KAAM,KAAM,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,IACvEuO,UAAW,CACT,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,KACA,KACA,MAEFhrC,YAAa,IAGTwgC,E,WACJ,WAAYhrB,EAAQ62B,EAAU1hC,GAAM,IAAD,wBACjC6K,EAAM,2BACDw4B,GACAx4B,GAEL7Z,KAAK0wC,SAAWA,EAChB1wC,KAAKgP,IAAMA,EACXhP,KAAK8gC,YAAc9gC,KAAK8gC,YAAcjnB,EAAOinB,YAAY9xB,KAAI,SAACkH,GAAD,OAC3DlL,OAAOkL,MAETlW,KAAKwjC,WAAa3pB,EAAO2pB,WAEzB,IAAIjsB,EAAS,CACX65B,aAAcv3B,EAAOxV,YACrB6qC,OAAQ,YACRC,OAAO,EACPv8B,IAAKiH,EAAOjH,IACZy7B,YAAax0B,EAAOw0B,YACpBiE,SAAUz4B,EAAOy4B,SACjB7kC,MAAOoM,EAAOpM,MACd2hC,UAAWv1B,EAAOu1B,UAClBlnC,MAAO2R,EAAO3R,MACds7B,WAAYxjC,KAAKwjC,WACjBgO,SAAU,IAAIe,IAAa,CACzBxd,OAAQlb,EAAOkb,OAAO/lB,KAAI,SAAC0R,GAAD,OAAO1V,OAAO0V,MACxCogB,YAAa9gC,KAAK8gC,YAClBuO,UAAWx1B,EAAOw1B,UAClBnM,OAAQrpB,EAAOqpB,UAInBqO,oCAA0Bh6B,GAE1B,IAAMgsB,GAAgB,QAAN,EAAA1pB,SAAA,eAAQ0pB,UAAW,EAAI1pB,EAAO0pB,aAAU/vB,EAClD8vB,GAAgB,QAAN,EAAAzpB,SAAA,eAAQypB,UAAW,EAAIzpB,EAAOypB,aAAU9vB,EAExDxT,KAAKyN,MAAQ,IAAIgD,IAAU,CACzB8Z,KAAM1Q,EAAO0Q,KACbujB,QAASj0B,EAAOi0B,QAChB/7B,UAAW8H,EAAO9H,UAClBg8B,QAASl0B,EAAOk0B,QAChBx2B,OAAQ,IAAIi7B,IAAKj7B,GACjB5J,UAAW,IAAIxJ,UAAU0V,GACzB0pB,QAASA,EACTD,QAASA,IAEXtjC,KAAKyyC,2BACLzyC,KAAK0J,KAAO,O,4DAGd,WACE,IAAIq5B,EAAO/iC,KAAKgP,IAAIoB,UACpBpQ,KAAKgP,IAAI0jC,QACP,IAAI1P,IAAK,CACPU,KAAMX,EAAK9xB,UACXgyB,OAAQF,EAAK8D,YACb/F,YAAa9gC,KAAK8gC,YAClB0C,WAAYxjC,KAAKwjC,WACjBJ,oBAAqBL,EAAK4P,gC,KAMnB9N,a,yNCrFT+N,EAAwB,CAC5BhgC,IAAK,GACLV,OAAQ,CACN22B,QAAS,MACTyE,QAAS,QACTZ,QAAS,aACToD,SAAU,GACVrH,aAAc,OACdsH,QAAS,GACTC,KAAM,IAER6C,YAAY,GAER9N,E,WACJ,WAAYlrB,EAAQ62B,EAAU1hC,GAAM,IAAD,oCAmFnC8jC,oBAAsB,SAACvyC,GACrB,IAAMwyC,EAAYC,SAAiBzyC,GAC7B0yC,EAAWD,WAAmBD,GAE9BG,EADQF,WAAmBC,EAAU,EAAK/C,UACjBiD,kBAAkB,GAE3C1kC,EAAiB,EAAKO,IAAIoB,UAAUT,gBACpCyjC,EAAaJ,wBAAgCE,EAAkB,CAEnEG,kBAAmB,SAACC,GAClB,IAAMC,EAAa,EAAKvkC,IAAIoB,UAAUy2B,YACtC,OAAO2M,YAAmB/kC,EAAgB6kC,EAAgBC,IAK5DE,oBAAqB,WACnB,EAAKhmC,MAAMimC,aAGf,EAAKjmC,MAAM4c,SAAS+oB,IAtGpBpzC,KAAK6Z,OAAL,2BACK+4B,GACA/4B,GAEL7Z,KAAK0wC,SAAWA,EAChB1wC,KAAKgP,IAAMA,EACXhP,KAAK0J,KAAO,SACZ1J,KAAK2zC,YAAc,GAGnB3zC,KAAKwvC,gBAAkB31B,EAAO21B,gBAC9BxvC,KAAKyvC,eAAiB51B,EAAO41B,eAC7BzvC,KAAK0vC,YAAc71B,EAAO61B,YAE1B1vC,KAAK4zC,aAAe,IAAIvN,IAAa,CAEnC+K,aAAcv3B,EAAOxV,YAGrBwvC,OAAQ,SAAC3Q,EAAQpyB,EAAY0yB,GAC3B,EAAKsQ,SAAS,EAAKC,UAAU7Q,EAAQM,EAAWnzB,aAIlD2jC,SACmC,SAAjC,UAAAh0C,KAAK6Z,cAAL,eAAao6B,iBAA4BC,IAAcC,MAG3Dn0C,KAAKyN,MAAQ,IAAI84B,IAAY,CAC3BvhC,YAAa6U,EAAO7U,YACpBV,QAASuV,EAAOvV,QAChBimB,KAAM1Q,EAAO0Q,KACbujB,QAASj0B,EAAOi0B,QAChBC,QAASl0B,EAAOk0B,QAChBh8B,UAAW8H,EAAO9H,UAClBw9B,WAAY11B,EAAO01B,WACnBC,gBAAiB31B,EAAO21B,gBACxBC,eAAgB51B,EAAO41B,eACvBC,YAAa71B,EAAO61B,YACpB/hC,UAAW,IAAIxJ,UAAU0V,GACzBu6B,WAAY,QACZ78B,OAAQvX,KAAK4zC,aACbhhC,IAAKiH,EAAOjH,IACZo8B,YAAan1B,EAAO3H,OAAO49B,SAASn+B,MAAM,KAAK,GAC/C4xB,SAAe,OAAN1pB,QAAM,IAANA,OAAA,EAAAA,EAAQ0pB,UAAW,EAAI1pB,EAAO0pB,aAAU/vB,EACjD8vB,SAAe,OAANzpB,QAAM,IAANA,OAAA,EAAAA,EAAQypB,UAAW,EAAIzpB,EAAOypB,aAAU9vB,EACjDs7B,gBAAe,OAAEj1B,QAAF,IAAEA,OAAF,EAAEA,EAAQi1B,gBACzBC,cAAa,OAAEl1B,QAAF,IAAEA,OAAF,EAAEA,EAAQk1B,gBAKzB/uC,KAAKowC,OAAL,OAAcv2B,QAAd,IAAcA,OAAd,EAAcA,EAAQu2B,OACtBpwC,KAAKmwC,QAAL,OAAet2B,QAAf,IAAeA,OAAf,EAAeA,EAAQs2B,QACvBnwC,KAAKkwC,SAAL,iBAAgBr2B,QAAhB,IAAgBA,OAAhB,EAAgBA,EAAQq2B,gBAAxB,QAAoC,iBAGT,kBAAhBlwC,KAAKowC,QAAuBpwC,KAAKowC,OAAO7iC,OAAOf,OAAS,EACjEsG,iBAAO9S,KAAKowC,QACTp9B,MAAK,SAAC3E,GAAD,OAAcA,EAAS9N,UAC5ByS,MAAK,SAACzS,GAAD,OAAU,EAAKuyC,oBAAoBvyC,MAInB,kBAAjBP,KAAKmwC,SACZnwC,KAAKmwC,QAAQ5iC,OAAOf,OAAS,GAE7BxM,KAAK8yC,oBAAoB9yC,KAAKmwC,UAI9Bt2B,EAAOyS,MACPzS,EAAO81B,WACP91B,EAAOg2B,WACPh2B,EAAO/P,WACP+P,EAAO+1B,YAEP5vC,KAAKyN,MAAM4c,SAASrqB,KAAKq0C,e,qDA4B7B,SAAkB3mC,EAAUuc,EAAMC,GAC5B5jB,MAAMC,QAAQmH,IAChBA,EAASvH,SAAQ,SAAC0E,GAChB,GAAIA,EAAQS,eAAiBT,EAAQS,cAAcgpC,eAAgB,CACjE,IAAI5qB,EAAS7e,EAAQS,cAAcgpC,iBACnC,IACE,OAAQzpC,EAAQS,cAAcygC,WAC5B,IAAK,QACHlhC,EACGS,cACAipC,eAAevqB,YAAUN,EAAQO,EAAMC,IAC1C,MACF,IAAK,aACHrf,EACGS,cACAipC,eACC7qB,EAAO1a,KAAI,SAACwlC,GAAD,OAAWxqB,YAAUwqB,EAAOvqB,EAAMC,OAEjD,MACF,IAAK,UACHrf,EACGS,cACAipC,eAAe,CACd7qB,EAAO,GAAG1a,KAAI,SAACwlC,GAAD,OAAWxqB,YAAUwqB,EAAOvqB,EAAMC,QAEpD,MACF,QACE,MAAM,IAAIzD,MAAM,2BAEpB,MAAO1jB,GACP4Q,QAAQ1P,MAAM,mCAAoClB,U,4BAO5D,SAAeoa,GACb,IAAIzP,EAAW,GACXM,EAAS,KACPkc,EAAKlqB,KAAKgP,IAAIoB,UAAUT,gBAAgBU,UACxC4Z,EAAOjqB,KAAK6Z,OAAO2pB,WACnBiF,EAAezoC,KAAK6Z,OAAO3H,OAAOu2B,aAwBxC,OAtBIA,EAAarS,WAAW,SAI1BpoB,EAAS,IAAIo7B,IAAI,CACfqL,UACiC,UAA/Bz0C,KAAK6Z,OAAO3H,OAAOo7B,QAAsB,IAAIxD,IAAS,IAAIC,OAI3C,qBAAjBtB,IACFz6B,EAAS,IAAIU,KAGXV,IACFN,EAAWM,EAAO6F,aAAasJ,IAG7B+M,IAAOD,GACTjqB,KAAK00C,kBAAkBhnC,EAAUuc,EAAMC,GAGlCxc,I,iCAUT,SAAoBkC,GAAI,IAAD,OACrB,OAAI5P,KAAKyN,MAAMkD,IAAI,oBAAsB3Q,KAAKyN,MAAMkD,IAAI,eAC/Cf,EAAEY,QAAO,SAAC3F,GAAD,OAAa,EAAK8pC,aAAa9pC,MAExC+E,I,0BAYX,SAAa/E,GACX,IAAM2kC,EAAkBxvC,KAAKyN,MAAMkD,IAAI,mBACjC++B,EAAc1vC,KAAKyN,MAAMkD,IAAI,eAGnC,OAFuB3Q,KAAKyN,MAAMkD,IAAI,mBAGpC,IAAK,KACH,OACE3F,OAAOH,EAAQ+C,gBAAgB4hC,IAAoBxkC,OAAO0kC,GAE9D,IAAK,KACH,OACE1kC,OAAOH,EAAQ+C,gBAAgB4hC,IAAoBxkC,OAAO0kC,GAE9D,IAAK,KACH,OAAK1kC,OAAOwb,MAAMxb,OAAO0kC,IAMlB7kC,EAAQ+C,gBAAgB4hC,KAAqBE,EAJhD1kC,OAAOH,EAAQ+C,gBAAgB4hC,MAC/BxkC,OAAO0kC,GAIb,IAAK,MACH,OAAK1kC,OAAOwb,MAAMxb,OAAO0kC,IAMlB7kC,EAAQ+C,gBAAgB4hC,KAAqBE,EAJhD1kC,OAAOH,EAAQ+C,gBAAgB4hC,MAC/BxkC,OAAO0kC,GAIb,QACE,OAAO,K,uBAIb,WAAyC,IAA/BxM,EAA8B,uDAArB,GAAIM,EAAiB,uDAAJ,GAE5BljC,EAAQN,KAAK6Z,OAAO3H,cAGnB5R,EAAM0vC,KAGb,IAAM4E,EAAM,IAAI3L,gBAAgB3oC,GAAOyoB,WAGjCinB,EACc,IAAlB9M,EAAO12B,SAA8C,IAA9B02B,EAAOpuB,SAAS+/B,KAAvC,gBACa3R,EAAO5wB,KAAK,KADzB,YACiCkxB,GAC7B,GAEA5wB,EAAM5S,KAAK6Z,OAAOjH,IAAM,IAAMgiC,EAAM5E,EAC1C,OAAOp9B,I,sBAGT,SAASA,GAAM,IAAD,OACZA,EAAM5S,KAAK0wC,SAAW99B,EAEtBE,iBAAOF,GAAKI,MAAK,SAAC3E,GAChBA,EAAS9N,OAAOyS,MAAK,SAACtF,GAEpB,EAAKimC,YAAc,EAAKmB,eAAepnC,GAGvC,EAAKkmC,aAAamB,YAChB,EAAKC,oBAAoB,EAAKrB,sB,yBAMtC,SAAYsB,GACV,IAAM3oB,EAAOtsB,KAAK6Z,OAAOyS,MAAQ,GAC3BxiB,EAAY9J,KAAK6Z,OAAO/P,WAAa,wBACrC6lC,EAAY3vC,KAAK6Z,OAAO81B,WAAa,UACrCC,EAAY5vC,KAAK6Z,OAAO+1B,WAAa,GACrCC,EAAY7vC,KAAK6Z,OAAOg2B,WAAa,GACrCQ,EAAgBrwC,KAAK6Z,OAAOw2B,eAAiB,GAC7CC,EAAgBtwC,KAAK6Z,OAAOy2B,eAAiB,GAE7CjoC,EAAQrI,KAAK6Z,OAAOq7B,WACpBC,EAAWn1C,KAAK6Z,OAAOu7B,cACvBhsC,EAAOpJ,KAAK6Z,OAAOw7B,UACnBvoC,EAAU9M,KAAK6Z,OAAOy7B,aACtB9pC,EAAUxL,KAAK6Z,OAAO07B,aAEtB5oC,EADS3M,KAAK6Z,OAAO27B,YACL,IAAMpsC,EAAO,IAAMpJ,KAAK6Z,OAAO47B,UAC/CC,EAAiB11C,KAAK6Z,OAAO67B,eAC7BC,EAAe31C,KAAK6Z,OAAO+7B,kBAC3BC,EAAe71C,KAAK6Z,OAAOi8B,kBAC3BjD,EAAa7yC,KAAK6Z,OAAOg5B,WACzB5C,EAAYgF,GAAqBj1C,KAAK6Z,OAAOo2B,WAAa,EAC1D8F,EAAY9F,EAAY,EAE9B,SAAS+F,IACP,IAAI9qC,EAAQ,SAACzC,EAAGmH,GAAJ,OAAUnH,EAAEuG,KAAI,SAACd,GAAD,OAAO0B,EAAI1B,MACrC9B,EAAQyjC,EAERoG,EAAO,CAAC,GAAI,GACZC,EAAM,CAAC,EAAG,GACZ,OAHUtG,GAIR,IAAK,OACH,OAAOxjC,EAAQ,EAAIlB,EAAM+qC,EAAM,GAAKA,EACtC,IAAK,MACH,OAAO7pC,EAAQ,EAAIlB,EAAMgrC,EAAK,GAAKA,EACrC,QACE,QAIN,SAAShrB,IACP,OAAO,IAAIlf,IAAK,CACdC,MAAOnC,IAuBX,SAAS6gB,IACP,MAAgB,KAAT2B,EAcA,IAAIrf,IAAO,CAChBlB,KAAMmf,IACNhf,OAAQ6e,IACR7d,OAAQrN,SAASowC,EAAW,KAAO,IAb9B,IAAI3jC,IAAK,CACdC,IAAK+f,EACLphB,MAAO6qC,EACPI,aAAc,SACdC,aAAc,SACdhrC,OAAQ,CAACilC,EAAeC,KAY5B,SAASvlB,IACP,OAAO,IAAI5e,IAAO,CAChBF,MAAO0jC,EACPvjC,MAAOyjC,EACPwG,SAAUL,MAiBd,MAAO,CAAC,IAAIlqC,IAbZ,WACE,IAAIjG,EAAM,CACRkG,KAAMmf,IACN7e,MAAOse,IACPze,OAAQ6e,KAMV,OAJI8nB,IACFhtC,EAAItF,KAvDC,IAAIkM,IAAK,CACdnE,UAAWD,EACXqE,aAAcyoC,EACdxoC,KAAMA,EACNpM,KAAM,GACNwL,KAAM,IAAIC,IAAK,CACbC,MAAOypC,IAETxpC,OAAQ,IAAIC,IAAO,CACjBF,MAAO0pC,EACPvpC,MAAOypC,IAET/oC,QAASA,EACTtB,QAASA,EACTuB,SApDa,KAgGRlH,EAGSywC,S,KAIPvR,a,0SCvZMlB,E,WACnB,WAAYlqB,GAAM,IAAD,2EA+DC,SAACpC,GACjB,MAAwC,oBAA1BA,EAAM,eAhEL,gDAyEe,SAACxU,GAED,IAA5B,EAAKwzC,cAAcntC,OACI,IAAvB,EAAKotC,gBAC0C,IAA/C,cAAI,GAAJ,GAAqBzzC,EAAEM,OAAOqM,eAKhC,EAAK8mC,eAAgB,EAGrBp3B,YAAW,WAET,cAAI,GAAJ,KACA,cAAI,GAAJ,KAEA,EAAKo3B,eAAgB,IACpB,SA3FY,gDA8FY,WACL,EAAKxnC,IACxBsB,YACAC,WACAC,QAAO,SAAC02B,GAAD,OAAOA,EAAEuP,gBAChBznC,KAAI,SAACk4B,GAAD,OAAOA,EAAEx3B,eACbc,OALmB,YAKZ,EALY,OAQRrK,SAAQ,SAACoR,GACrB,IAAMm/B,EAAO,IAAIC,IAAK,CACpBp/B,WAEF,EAAKvI,IAAI4nC,eAAeF,GAGxB,EAAKG,iBAAiBrnC,KAAKknC,SA9Gd,gDAkHY,WAC3B,GAAqC,IAAjC,EAAKG,iBAAiBrqC,OAA1B,CADiC,oBAIjB,EAAKqqC,kBAJY,IAIjC,2BAAuC,CAAC,IAA7Bh1B,EAA4B,QAErC,EAAK7S,IAAI8nC,kBAAkBj1B,IANI,8BAUjC,EAAKg1B,iBAAmB,OA3HxB72C,KAAKgP,IAAM2K,EAAI3K,IACfhP,KAAKb,eAAiBwa,EAAIxa,eAE1Ba,KAAK62C,iBAAmB,GAGxB72C,KAAKu2C,cAAgB,IAAI1kC,IAGzB7R,KAAKw2C,eAAgB,EAKrBx2C,KAAKb,eAAegV,GAClB,8BADF,YAEEnU,KAFF,O,uCAaF,SAAIswB,GAI0B,IAA5BtwB,KAAKu2C,cAAcntC,MAAnB,YAAiCpJ,KAAjC,QAGAA,KAAKu2C,cAAcjwB,IAAIgK,K,oBAUzB,SAAOA,GACLtwB,KAAKu2C,cAAcQ,OAAOzmB,GAGE,IAA5BtwB,KAAKu2C,cAAcntC,MAAnB,YAAiCpJ,KAAjC,Y,qQCAEg3C,E,kDAWJ,WAAY12C,GAAQ,IAAD,8BACjB,cAAMA,IAXRwW,MAAQ,CACNmgC,cAAe,GASE,EAYnBC,iBAAmB,WACjB,MAAgC,EAAK52C,OACrCmkB,EADA,EAAQA,WAAR,EAAmB/W,SACA,EAAKoJ,MAAMmgC,iBAdb,EAiBnBE,SAAW,WACT,GAAI,EAAKrgC,MAAMmgC,cAAgB,GAAK,EAAG,CACrC,IAAIG,EAAW,EAAKtgC,MAAMmgC,cAAgB,EAC1C,EAAKI,yBAAyBD,KApBf,EAwBnBE,UAAY,WACV,IAAQ5pC,EAAa,EAAKpN,MAAlBoN,SACR,GAAI,EAAKoJ,MAAMmgC,cAAgB,EAAIvpC,EAASlB,OAAQ,CAClD,IAAI4qC,EAAW,EAAKtgC,MAAMmgC,cAAgB,EAC1C,EAAKI,yBAAyBD,KA5Bf,EAgCnBG,WAAa,WACX,MAA8B,EAAKj3C,MAA3BoN,EAAR,EAAQA,SAAUuK,EAAlB,EAAkBA,QAClB,OACE,eAAC,IAAD,CACEkB,WAAW,SACXC,QAAQ,gBACRhR,UAAW6P,EAAQu/B,QACnBv+B,WAAS,EAJX,UAME,cAAC,IAAD,CAAMC,MAAI,EAAC9Q,UAAW6P,EAAQw/B,4BAA9B,SACE,cAAC,IAAD,CACEC,WAAS,EACTp+B,SAAU,EAAKxC,MAAMmgC,cAAgB,EAAI,EACzCvzC,QAAS,EAAKyzC,SACd59B,aAAW,WACXlX,GAAG,YALL,SAOE,cAAC,IAAD,CAAe4J,MAAM,kBAGzB,cAAC,IAAD,CAAMiN,MAAI,EAAV,SACE,eAAC,IAAD,CACEtR,QAAQ,SACRqE,MAAM,YACN7D,UAAW6P,EAAQ0/B,WAHrB,UAKG,EAAK7gC,MAAMmgC,cAAgB,EAL9B,OAKqCvpC,EAASlB,YAGhD,cAAC,IAAD,CAAM0M,MAAI,EAAC9Q,UAAW6P,EAAQ2/B,2BAA9B,SACE,cAAC,IAAD,CACEF,WAAS,EACTp+B,SAAU,EAAKxC,MAAMmgC,cAAgB,GAAKvpC,EAASlB,OACnD9I,QAAS,EAAK4zC,UACd/9B,aAAW,OACXlX,GAAG,aALL,SAOE,cAAC,IAAD,CAAgB4J,MAAM,sBArEb,EAyInB4rC,4BAA8B,SAAChtC,EAAS4C,EAAO6I,GAAc,IAAD,MAI1D,OACS,OAAPzL,QAAO,IAAPA,OAAA,EAAAA,EAAS2M,WAAT,UACA3M,EAAQ4C,aADR,iBACA,EAAe2D,kBADf,iBACA,EAA4B3D,UAD5B,aACA,EAAoC+J,UACpClB,GAhJe,EAoJnBwhC,sBAAwB,SAACjtC,GACvB,OAAO5E,OAAOC,KAAK2E,EAAQ4C,MAAM2D,YAAY4I,MAAK,SAAC3X,GAGjD,OAFYwI,EAAQuE,QAAQuC,MAAM,KAAK,MACE,IAAzBtP,EAAGsP,MAAM,KAAKnF,OAAenK,EAAGsP,MAAM,KAAK,GAAKtP,OAvJjD,EA4JnB01C,qBAAuB,SAACltC,GACtB,IAAIzG,EAAayG,EAAQ+C,gBAGzB,OAFAxJ,EAAa,EAAKsT,oBAAoBvB,0BAA0B/R,GAChEyG,EAAQ4M,cAAcrT,GACfA,GAhKU,EAyNnB4zC,SAzNmB,uCAyNR,WAAO1hC,EAAUlS,EAAYE,GAA7B,SAAAmE,EAAA,0DACL6N,EADK,gCAEM,EAAKoB,oBACfC,yBAAyB,CAAErB,WAAUlS,eACrCiS,gCAJI,wEAMA,EAAK4hC,0BAA0B7zC,EAAYE,IAN3C,2CAzNQ,4DAoPnB4zC,kBAAoB,WAClB,MAAgD,EAAKphC,MAA7CxS,EAAR,EAAQA,QAASnB,EAAjB,EAAiBA,MAAO6qB,EAAxB,EAAwBA,QAASmqB,EAAjC,EAAiCA,WACjC,OAAO7zC,IAAY0pB,GAAW7qB,GAASg1C,GAtPtB,EAyPnBC,yBAA2B,WAEzB,MAA2B,EAAKthC,MAAxBxS,EAAR,EAAQA,QAASnB,EAAjB,EAAiBA,MACT8U,EAAY,EAAK3X,MAAjB2X,QAER,OACE,eAAC,IAAD,CAAM7P,UAAW6P,EAAQogC,YAAan/B,MAAI,EAA1C,UACE,cAAC,IAAD,CAAYtR,QAAQ,SAASS,MAAM,SAASc,UAAU,KAAKmvC,cAAY,EAAvE,SACGh0C,IAEFnB,MAjQL,EAAKuU,oBAAsB,IAAIrD,UAAoB,CACjDlV,eAAgBmB,EAAMnB,eACtBkC,QAASf,EAAMe,UAJA,E,qDAQnB,WACErB,KAAKq3C,yBAAyB,K,uCAmEhC,SAA0Bl6B,EAAM7Y,GAC9B,IAAQ2T,EAAYjY,KAAKM,MAAjB2X,QAIJsgC,EAAI,EACFC,EAAYvyC,OAAOC,KAAKiX,GAAMnO,KAAI,SAACnL,EAAKge,GAC5C,MAAyB,kBAAd1E,EAAKtZ,MACZ00C,EAEA,eAAC,IAAD,CAAkBE,SAAUF,EAAI,IAAM,EAAtC,UACE,cAAC,IAAD,CAAWnwC,UAAW6P,EAAQygC,UAAW9wC,QAAQ,OAAjD,SACG/D,IAEH,cAAC,IAAD,CAAWuE,UAAW6P,EAAQ0gC,YAA9B,SAA4Cx7B,EAAKtZ,OAJpCge,IAQV,QAIX,OACE,cAAC,IAAD,CAAgB1Y,UAAU,MAA1B,SACE,cAAC,IAAD,CAAOC,KAAK,QAAQmQ,aAAW,+BAA/B,SACE,cAAC,IAAD,UAAYi/B,U,6EA8DpB,WAA+BpB,GAA/B,0CAAA3uC,EAAA,6DACMoC,EAAU7K,KAAKM,MAAMoN,SAAS0pC,GAC5BzpC,EAAY9C,EAAQ4C,MAAMkD,IAAI,aAEhC2F,EAJN,OAIiB3I,QAJjB,IAIiBA,OAJjB,EAIiBA,EAAW3I,YACxBV,EALJ,OAKcqJ,QALd,IAKcA,OALd,EAKcA,EAAWrJ,QAErB6zC,EAAa,GAGXttC,EAAQ4C,MAAM2D,YAAcvG,EAAQuE,UACtC3B,EAAQzN,KAAK83C,sBAAsBjtC,IAUrCvG,GAAU,UAAAuG,EAAQ4C,aAAR,mBAAe2D,kBAAf,mBAA4B3D,UAA5B,eAAoCnJ,UAAWA,EACzDgS,EAAWtW,KAAK63C,4BAA4BhtC,EAAS4C,EAAO6I,GAY5DtW,KAAK6X,SAAS,CAAEmW,SAAS,IAErB5pB,EAAapE,KAAK+3C,qBAAqBltC,GApC7C,UAqCsB7K,KAAKg4C,SAAS1hC,EAAUlS,EAAYE,GArC1D,QAqCQnB,EArCR,OAuCEnD,KAAK6X,SACH,CACE1U,MAAOA,EACP6qB,SAAS,EACT1pB,QAASA,EACT6zC,WAAYA,EACZlB,cAAeG,EACf9gC,SAAUA,IAEZ,WACE,EAAK4gC,sBAjDX,iD,2EAqGA,WACE,MAA8Bl3C,KAAKM,MAA3B2X,EAAR,EAAQA,QAASvK,EAAjB,EAAiBA,SACXkrC,EAAoB54C,KAAKk4C,oBAC/B,OACE,eAAC,IAAD,CACEW,aAAa,aACbzwC,UAAW6P,EAAQ6gC,cACnB7/B,WAAS,EACTzR,QAAS,EAJX,UAMGkG,EAASlB,OAAS,GACjB,cAAC,IAAD,CAAM8N,GAAI,GAAIpB,MAAI,EAAlB,SACGlZ,KAAKu3C,eAGV,cAAC,IAAD,CACEn+B,QAAQ,SACRy/B,aAAcD,EAAoB,aAAe,SACjDxwC,UAAW6P,EAAQ8gC,qBACnB7/B,MAAI,EACJD,WAAS,EALX,SAOG2/B,EACC54C,KAAKo4C,2BAEL,cAAC,IAAD,a,GA5SuB59B,IAAMC,eAoT1BC,uBApVA,SAAC9Z,GAAD,MAAY,CACzB42C,QAAS,CACPzwC,gBAAiBnG,EAAMoG,QAAQ+U,QAAQC,MAEzC88B,cAAe,CACbt6B,OAAQ,OACRtO,OAAQ,OACR8U,WAAY,QAEd2yB,WAAY,CACVrvC,UAAW,UAEbqwC,YAAa,CACX/9B,UAAW,aAEb89B,UAAW,CACTM,cAAe,OAEjBD,qBAAsB,CACpB5zB,KAAM,QAERkzB,YAAa,CACXjsC,MAAO,QAETqrC,4BAA6B,CAC3BwB,YAAY,GAAD,OAAKr4C,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,UAE9DtB,2BAA4B,CAC1BuB,WAAW,GAAD,OAAKv4C,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,aAwThDx+B,CAAmBs8B,I,qLClV5BoC,EAAkB,SAAC,GAA4C,IAA1CC,EAAyC,EAAzCA,QAAS//B,EAAgC,EAAhCA,SAAUpW,EAAsB,EAAtBA,MAAOE,EAAe,EAAfA,SACnD,OACE,cAAC,IAAD,CACEk2C,QACE,cAAC,IAAD,CACErtC,MAAM,UACNqN,SAAQ,OAAEA,QAAF,IAAEA,KACV+/B,QAASA,EACTj2C,SAAUA,IAGdF,MAAOA,KAKPq2C,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvC64C,gBAAiB,CACf,yBAA0B,CACxBtgC,WAAY,aAGhBugC,WAAY,CACVztC,MAAOrL,EAAMoG,QAAQzG,KAAKwb,aAIxB49B,EAAan/B,IAAMo/B,YAAW,SAAoBt5C,EAAOyiB,GAC7D,OAAO,cAAC,IAAD,aAAOO,UAAU,KAAKP,IAAKA,GAASziB,OA6I9Bu5C,UA1If,YAAqD,IAAD,cAA5B16C,EAA4B,EAA5BA,eAAgBya,EAAY,EAAZA,SAChC3B,EAAUshC,IACR1/B,EAAWD,EAAXC,OAGR,EAAwBW,IAAM5Y,SAASlC,8BAAvC,mBAAO0B,EAAP,KAAa04C,EAAb,KACA,EAAkDt/B,IAAM5Y,UAAS,GAAjE,mBAAOm4C,EAAP,KAA0BC,EAA1B,KACA,EAAgDx/B,IAAM5Y,UAAS,GAA/D,mBAAOq4C,EAAP,KAAyBC,EAAzB,KAEMC,GACE,OAANtgC,QAAM,IAANA,GAAA,UAAAA,EAAQC,iBAAR,mBAAmB9K,WAAnB,eAAwBmrC,6BA9C1B,8PA+CMC,GACE,OAANvgC,QAAM,IAANA,GAAA,UAAAA,EAAQC,iBAAR,mBAAmB9K,WAAnB,eAAwBorC,yBA9C1B,yFA+CMC,EAAqB,iBACzBxgC,QADyB,IACzBA,GADyB,UACzBA,EAAQC,iBADiB,iBACzB,EAAmB9K,WADM,aACzB,EAAwBsrC,uBADC,SAK3B9/B,IAAMwlB,WAAU,WAMd,OAHA7gC,EAAemiB,UAAU,yBAAyB,WAChDw4B,GAAQ,MAEH,WACL36C,EAAeo7C,YAAY,4BAE5B,CAACp7C,IAIJ,IAAMq7C,EAA2BhgC,IAAMigC,aAAY,WAGjD,IAAIC,EAAc,EAEdX,IACFW,GAA4B,GAG1BT,IACFS,GAA4B,GAG9Bt7C,mBAASs7C,GAETZ,GAAQ,KACP,CAACC,EAAmBE,IAIjBU,EAAsBngC,IAAMigC,aAAY,WAG5C,IAAIC,EAAc,EAGdL,IACFK,GAA4B,GAG9Bt7C,mBAASs7C,GAETZ,GAAQ,KACP,CAACO,IAEJ,OACE,cAAC,IAAD,CACE3C,WAAW,EACX78B,SAAU,KACVzS,UAAW6P,EAAQwhC,gBACnBr4C,KAAMA,EACNw5C,oBAAqBjB,EACrB9a,aAAW,EACXjW,mBAAiB,6BAPnB,SASE,eAAC,IAAD,WACE,eAAC,IAAD,CACExgB,UAAW6P,EAAQyhC,WACnBr3C,GAAG,6BAFL,oBAIM83C,EAJN,KAKE,cAAC,IAAD,CACEzxC,KAAM0xC,EACNS,UAAU,SACVC,IAAI,aACJz3C,OAAO,SAJT,SAMG,gCAGL,eAAC,IAAD,CAAM4V,WAAS,EAACqK,UAAU,MAAMnK,WAAW,SAASC,QAAQ,WAA5D,UACE,eAAC,IAAD,CAAMF,MAAI,EAAV,UACE,cAACkgC,EAAD,CACE9/B,UAAU,EACV+/B,SAAS,EACTn2C,MAAO,qBAET,cAACk2C,EAAD,CACEh2C,SAAU,SAACgvB,GACT4nB,EAAqB5nB,EAAM/uB,OAAOg2C,UAEpCA,QAASU,EACT72C,MAAO,iBAERm3C,GACC,cAACjB,EAAD,CACEh2C,SAAU,SAACgvB,GACT8nB,EAAoB9nB,EAAM/uB,OAAOg2C,UAEnCA,QAASY,EACT/2C,MAAO,kBAIb,eAAC,IAAD,CAAMgW,MAAI,EAAV,UACE,cAAC,IAAD,CACEjN,MAAM,UACNrE,QAAQ,YACRlE,QAAS82C,EAHX,SAKG,oBAEH,cAAC,IAAD,CACEvuC,MAAM,UACNrE,QAAQ,YACRlE,QAASi3C,EACTzyC,MAAO,CAAEk3B,WAAY,GAJvB,SAMG,gC,uICtKT2b,E,kDA8DJ,WAAYz6C,GAAQ,IAAD,8BACjB,cAAMA,IA9DRwW,MAAQ,CACNkkC,WAAW,EACXC,YAAa,EACbC,cAAc,EACdC,MAAO,IAyDU,EA1CnBC,gBAAkB,CAChB,CACEzyC,MAAO,uCACP0yC,MACE,4FAEJ,CACE1yC,MAAO,gBACP2yC,QAAS,2BACTD,MAAO,oEAET,CACE1yC,MAAO,aACP2yC,QAAS,6BACTD,MACE,+HAEJ,CACE1yC,MAAO,qBACP2yC,QAAS,yBACTD,MAAO,wEAET,CACE1yC,MAAO,iBACP2yC,QAAS,mBACTD,MACE,2HAEJ,CACE1yC,MAAO,aACP2yC,QAAS,oDACTD,MACE,6IAEJ,CACE1yC,MAAO,eACP2yC,QAAS,8BACTD,MACE,qMAIa,EAwCnBE,aAAe,WAKT1oB,0BACFtzB,OAAOC,aAAaC,QAAQ,oBAAqB,IArCnD,EAAKa,MAAMnB,eAAemiB,UAAU,kBAAkB,WAEpDlC,YAAW,WAET,IAAQ6f,EAAkC,EAAK3+B,MAAvC2+B,8BAOFuc,GAJJvc,EAA8BzyB,QAAU,EACpCyyB,EACA,EAAKmc,iBAEiB5qC,QAAO,SAAC4V,GAClC,YACgB5S,IAAd4S,EAAEk1B,SACqC,OAAvCtrC,SAASC,cAAT,OAAuBmW,QAAvB,IAAuBA,OAAvB,EAAuBA,EAAGk1B,YAI9B,EAAKzjC,SAAS,CAAEsjC,MAAOK,MACtB,QAGL,EAAKl7C,MAAMnB,eAAemiB,UAAU,yBAAyB,WAC3D,EAAKzJ,SAAS,CACZojC,YAAa,EACbC,cAAc,EACdF,WAAW,OAnCE,E,0CAkDnB,WACE,IAAQhc,EAAoCh/B,KAAKM,MAAzC0+B,gCACR,EAA6Ch/B,KAAK8W,MAA1CmkC,EAAR,EAAQA,YAAaE,EAArB,EAAqBA,MAAOD,EAA5B,EAA4BA,aAE5B,OAEElc,GAEAmc,EAAM3uC,QAAU,IAEgD,IAA/D3M,SAASN,OAAOC,aAAaI,QAAQ,wBACX,IAAzBI,KAAK8W,MAAMkkC,YACX,cAAC,QAAD,CACErsB,QAASusB,EACTC,MAAOA,EACPF,YAAaA,EACbQ,OAAQz7C,KAAKu7C,aACbl6C,QAAS,CACPq6C,oBAAoB,EACpBC,UAAW,WACXC,UAAW,mBACXC,UAAW,gB,GArIIrhC,IAAMC,eAA3BsgC,EAcGr2B,aAAe,CACpBsa,iCAAiC,EACjCC,8BAA+B,GAC/B9/B,eAAgB,IA4HL47C,a,wHC5Hf,SAASe,EAAT,GAA2D,IAAD,IAAlCxe,qBAAkC,MAAlB,GAAkB,EAAdC,EAAc,EAAdA,WAC1C,EAA2Cwe,cAAnClsB,EAAR,EAAQA,gBAAiBK,EAAzB,EAAyBA,cAoJzB,OAxIA8P,qBAAU,WA2HS1C,EACd9sB,QAAO,SAAC/H,GAAD,OAzDQ,SAACA,GAEjB,YAAgB+K,KAAX,OAAD/K,QAAC,IAADA,OAAA,EAAAA,EAAGuzC,OAAiC,QAAXvzC,EAAEuzC,QAG3B11C,MAAMC,QAAQkC,EAAEuzC,OAAcvzC,EAAEuzC,KAAKlnC,SAASyoB,GAoDnC0e,CAAUxzC,MACxB+H,QAAO,SAAC/H,GAAD,OAAoB,IAAbA,EAAEkT,UAChBnL,QAAO,SAAC/H,GAAD,OAzCY,SAACA,GACrB,IAAMyzC,EAAQ,OAAGzzC,QAAH,IAAGA,OAAH,EAAGA,EAAGyzC,SACpB,YAAiB1oC,IAAb0oC,GAAuC,QAAbA,KAC1B51C,MAAMC,QAAQ21C,IAAkBA,EAASpnC,SAASqnC,cAAS5xB,MAsChD6xB,CAAc3zC,MAC5B+H,QAAO,SAAC/H,GAAD,OAvHS,SAACA,GAClB,IAAM4zC,GAAM,IAAIj1B,MAAOS,UACjBy0B,EAAYl1B,KAAKpjB,MAAMyE,EAAE6zC,WACzBC,EAAWn1B,KAAKpjB,MAAMyE,EAAE8zC,UAExBC,GAAkBxxC,OAAOwb,MAAM81B,GAC/BG,GAAiBzxC,OAAOwb,MAAM+1B,GAEpC,OAAIC,GAAkBC,EAEbH,EAAYD,GAAOA,EAAME,EACvBC,IAAmBC,EAErBH,EAAYD,KACTG,GAAkBC,IAErBJ,EAAME,EAuGAG,CAAWj0C,MACzB+H,QAAO,SAAC/H,GAAD,OA1FiB,SAACA,GAE1B,IAAuB,IAAnBA,EAAEk0C,aAAuB,OAAO,EAKpC,IAEMC,GADJr9C,OAAOC,aAAaI,QAAQ,yBAA2B,IAC9B+R,MAAM,KAAKnB,OAAOw2B,SAC7C,GAAI4V,EAAU9nC,SAASrM,EAAEpG,GAAG0mB,YAE1B,OAAO,EAMT6zB,EAAUptC,KAAK/G,EAAEpG,IACjB,IAAMw6C,EAAYD,EAAUtqC,OAE5B,OADA/S,OAAOC,aAAaC,QAAQ,uBAAwBo9C,IAC7C,EAqEQC,CAAmBr0C,MAI3BtC,SAAQ,SAACyJ,GAAD,OApCM,SAACA,IAClB,OAACA,QAAD,IAACA,OAAD,EAACA,EAAGrP,OAgBRsvB,EAAe,OAACjgB,QAAD,IAACA,OAAD,EAACA,EAAGrP,KAAJ,YAAC,aACdqH,SAAU,OAADgI,QAAC,IAADA,OAAA,EAAAA,EAAGlG,OAAQ,WAChBsB,OAAOC,SAAP,OAAgB2E,QAAhB,IAAgBA,OAAhB,EAAgBA,EAAGmtC,UAAY,CAAEC,iBAAgB,OAAEptC,QAAF,IAAEA,OAAF,EAAEA,EAAGmtC,WACrD/xC,OAAOC,SAAP,OAAgB2E,QAAhB,IAAgBA,OAAhB,EAAgBA,EAAGmtC,UAAY,CAAEE,SAAS,EAAMh2C,OAhBxC,SAACpD,GACd,OACE,cAAC,IAAD,CACEuF,KAAK,QACLmQ,aAAW,QACXtN,MAAM,UACNvI,QAAS,kBAAMwsB,EAAcrsB,IAJ/B,SAME,cAAC,IAAD,CAAWgE,SAAS,gBAwBJq1C,CAAettC,QACtC,CAAC0tB,EAAeC,EAAY1N,EAAiBK,IAGzC,KAIT,SAASitB,EAAchmC,EAAWimC,GAChC,OAAOjmC,EAAUmmB,cAAc9wB,SAAW4wC,EAAU9f,cAAc9wB,OAGrDgO,cAAM6iC,KAAKvB,EAAcqB,I,iCC9LxC,kCAaA,SAASG,EAAT,GACE,OADkC,EAAXjtB,QACRrhB,KAAI,SAAC6pB,EAAMhX,GACxB,OACE,cAACgX,EAAK1vB,UAAN,CAEE6F,IAAK6pB,EAAK7pB,IACV2K,IAAKkf,EAAKlf,IACV6W,gBAAiBqI,EAAKrI,gBACtBnvB,QAASw3B,EAAKx3B,SAJTwgB,MAmBb,SAASs7B,EAAchmC,EAAWimC,GAChC,OAAOjmC,EAAUkZ,QAAQ7jB,SAAW4wC,EAAU/sB,QAAQ7jB,OAGzCgO,cAAM6iC,KAAKC,EAAeH,I,uaCcnCI,EAAe,SAACj9C,GACpB,IAAMM,EAAQC,cACR28C,EAAcz8C,YAAcH,EAAMI,YAAYC,KAAK,OACnDiH,EAAQs1C,EAAc,CAAEpxC,MAAO,QAAW,CAAEA,MAAO,KACzD,OACE,cAAC,IAAD,2BACM9L,GADN,IAEE4H,MAAOA,EACPu1C,cAAe,CACbC,UAAW,CACTC,aAAc,CAAEC,iBAAiB,GACjCC,gBAAiB,CACflvB,QAAS6uB,EACTM,kBAAmB,QAErBC,KAAM,CAAEpvB,QAAS6uB,KAGrBQ,UAAU,iBAKVC,EAAc,SAAC39C,GACnB,IAAMM,EAAQC,cAERqH,EADcnH,YAAcH,EAAMI,YAAYC,KAAK,OAErD,CACEqC,OAAQ,EACR46C,UAAU,GAAD,OAAKt9C,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,UAE5D,CAAE51C,OAAQ,GACd,OAAO,cAAC,IAAD,2BAAWhD,GAAX,IAAkB4H,MAAOA,MAG5Bi2C,E,4MACJrnC,MAAQ,CACNsnC,YAAY,EACZC,gBAAgB,EAChBC,mBAAe9qC,EACf+qC,iBAAiB,EACjBC,mBAAmB,G,EAGrBC,mBAAqB,SAAC1pB,GACpB,IACIzI,EADIrU,EAAY,EAAK3X,MAAjB2X,QAER,OAAQ8c,GACN,IAAK,MACHzI,EAAO,cAAC,IAAD,CAAUrgB,MAAM,aACvB,MACF,IAAK,WACHqgB,EAAO,cAAC,IAAD,CAAiBrgB,MAAM,aAC9B,MACF,IAAK,aACHqgB,EAAO,cAAC,IAAD,CAAWrgB,MAAM,aACxB,MACF,QACEqgB,EAAO,cAAC,IAAD,CAAUrgB,MAAM,aAE3B,OAAO,qBAAK7D,UAAW6P,EAAQymC,kBAAxB,SAA4CpyB,K,EAGrDqyB,sBAAwB,SAACz+C,GACvB,OAAOA,EAAOC,QAAQ,KAAM,IAAIA,QAAQ,KAAM,K,EAIhDy+C,WAAa,SAAC1+C,EAAQ2+C,EAAOpoC,GAI3B,IAHA,IAAI6E,EAAU,GACV9G,EAAQqqC,EAAM11B,KAAKjpB,GAEP,MAATsU,GAA8B,KAAbA,EAAM,IAC5B8G,EAAQ9L,KAAKgF,GACbA,EAAQqqC,EAAM11B,KAAKjpB,GAErB,OAAOob,G,EAGTwjC,yCAA2C,SAACC,EAAaC,GACvD,IAAIC,EAAS,IAAIp4B,OAAO,EAAKvmB,MAAMyzB,aAAairB,GAAa,MAG7D,OAFc,EAAKJ,WAAWG,EAAaE,GACdjwC,KAAI,SAACwF,GAAD,OAAWA,EAAMiC,U,EAIpDyoC,uCAAyC,SACvCC,EACA7sB,GAEA,IAAM7b,EAAkB0oC,EAAlB1oC,MAAOjK,EAAW2yC,EAAX3yC,OACb,OACE,qCACE,iCAAS8lB,EAAkBrK,MAAM,EAAGxR,EAAQjK,KAC3C8lB,EAAkBrK,MAAMxR,EAAQjK,O,EAMvC4yC,mCAAqC,SACnCC,EACA/sB,GAEA,IAAMgtB,EAA8BD,EAAqB7yC,OAEnD2yC,EACJE,EAAqBC,EAA8B,GAErD,GAAIA,EAA8B,EAChC,OAAO,EAAKJ,uCACVC,EACA7sB,I,EAKNitB,kBAAoB,SAAC3xB,EAAc0E,GACjC,MAA6C,EAAKhyB,MAA1CuzB,EAAR,EAAQA,wBAAyB5b,EAAjC,EAAiCA,QAG7BonC,EAFkBxrB,EAAwBjG,GAG3C5e,KAAI,SAACwwC,GACJ,OAAO,EAAKV,yCACVxsB,EACAktB,GACAxwC,KAAI,SAACyH,GACL,MAAO,CACLA,MAAOA,EACPjK,OAAQgzC,EAAWhzC,cAIxB4oB,OAEH,OACE,cAAC,IAAD,CAAY3b,QAAQ,EAAMrR,UAAW6P,EAAQwnC,uBAA7C,SACGJ,EAAqB7yC,OAAS,EAC3B,EAAK4yC,mCACHC,EACA/sB,GAEFA,K,EASVotB,eAAiB,WACf,MAII,EAAKp/C,MAHPe,EADF,EACEA,QACAysB,EAFF,EAEEA,aAII6xB,EANN,EAGE1xB,cAAiBjB,sBAIf,4BACA,GAEJ,MAAwB,iBAAjBc,GAAoD,SAAjBA,EAAnC,6BACgB6xB,GACF,iBAAjB7xB,EAAA,+BACkB6xB,GAClBt+C,EAAQu+C,qBAAR,UACGv+C,EAAQu+C,sBADX,OACkCD,GADlC,gBAEMA,I,EAGZE,uBAAyB,WACvB,MAQI,EAAKv/C,MAPPktB,EADF,EACEA,cACA7T,EAFF,EAEEA,IACA3K,EAHF,EAGEA,IACAqV,EAJF,EAIEA,cACA8J,EALF,EAKEA,qBACAgK,EANF,EAMEA,4BACA92B,EAPF,EAOEA,QAGF,OACE,cAAC,UAAD,CACEmsB,cAAeA,EACfnJ,cAAeA,EACf1K,IAAKA,EACL8kC,mBAAoB,EAAKA,mBACzBhxB,mBAAoBD,EAAcC,mBAClCze,IAAKA,EACLqvC,eAAgBlwB,EAChBgK,4BAA6BA,EAC7B92B,QAASA,K,EAKfy+C,mBAAqB,WACnB,MASI,EAAKx/C,MARPqtB,EADF,EACEA,iBACAI,EAFF,EAEEA,iBACAH,EAHF,EAGEA,aACAE,EAJF,EAIEA,aACA7V,EALF,EAKEA,QACA+V,EANF,EAMEA,QACAwE,EAPF,EAOEA,gCACAL,EARF,EAQEA,kBAEF,OACE,cAAC,IAAD,CACE9vB,GAAG,mBACH09C,UAAQ,EACR32C,KAAM,QACN6O,QAAS,CACPqgB,UAAWrgB,EAAQqgB,WAErB0nB,gBAAiBzC,EACjB0C,eAAgBhC,EAChBiC,eAAa,EACb5mC,SACmB,iBAAjBwU,GACiB,iBAAjBA,GACiB,SAAjBA,EAEFjrB,cAAY,EACZM,MAAO/C,uBAAawtB,GACpBuyB,eAAa,EACbC,cAAY,EACZh/C,KAAM2sB,EACNsyB,kBAAgB,EAChBj9C,SAAU+uB,EACVmuB,cAAe9tB,EACf+tB,kBAAmB,SAACC,EAAQr9C,GAAT,OACjBq9C,EAAOluB,oBAAsBnvB,EAAMmvB,mBAErCmuB,aAAc,SAACD,GACb,GAAI5yB,EAAaphB,OAAS,EACxB,OACE,eAAC,IAAD,CAAMyM,WAAS,EAACE,WAAW,SAA3B,UACE,cAAC,IAAD,CAAMD,MAAI,EAACoB,GAAI,EAAf,SACG,EAAKmkC,mBAAmB+B,EAAOzrB,UAElC,eAAC,IAAD,CAAM9b,WAAS,EAACC,MAAI,EAACoB,GAAI,GAAzB,UACE,cAAC,IAAD,CAAMpB,MAAI,EAACoB,GAAI,GAAf,SACG,EAAKilC,kBACJ3xB,EACAxtB,uBAAaogD,EAAOluB,sBAGxB,cAAC,IAAD,CAAMpZ,MAAI,EAACoB,GAAI,GAAf,SACE,cAAC,IAAD,UAAiBkmC,EAAO1rB,mBAOpC4rB,eAAgB,SAACF,GAAY,IAAD,EAC1B,OAAa,OAANA,QAAM,IAANA,GAAA,UAAAA,EAAQluB,yBAAR,eAA2B9lB,QAAS,EACvCpM,uBAAY,OAACogD,QAAD,IAACA,OAAD,EAACA,EAAQluB,mBACrBkuB,GAENn/C,QAASssB,EACTK,QAASA,EACT2yB,YAAa,EAAKC,gC,EAKxBC,4BAA8B,SAACC,GAC7B,OACE,cAAC,IAAD,CAASn4C,MAAOm4C,EAAhB,SACE,cAAC,IAAD,CAAa70C,MAAM,QAAnB,SACE,cAAC,IAAD,CAAYrE,QAAQ,SAApB,SAA8Bk5C,S,EAMtCF,6BAA+B,SAAC1uC,GAC9B,MAmBI,EAAK5R,MAlBPstB,EADF,EACEA,aACAI,EAFF,EAEEA,QACA5hB,EAHF,EAGEA,MACA0hB,EAJF,EAIEA,aACA9e,EALF,EAKEA,IACA2K,EANF,EAMEA,IACAsY,EAPF,EAOEA,cACAC,EARF,EAQEA,kBACAiG,EATF,EASEA,4BACAhK,EAVF,EAUEA,qBACAiF,EAXF,EAWEA,wBACAnF,EAZF,EAYEA,cACAV,EAbF,EAaEA,cACAoF,EAdF,EAcEA,oBACAf,EAfF,EAeEA,YACAmB,EAhBF,EAgBEA,8BACAI,EAjBF,EAiBEA,iBACAjF,EAlBF,EAkBEA,sBAEI6yB,EAA6B,OAAV30C,EAAiB,CAAE20C,kBAAkB,GAAS,KACjEC,EACJ9yB,EAAsB1hB,OAAS,GAAK0lB,EAChC+uB,EAAgB9yB,EAClB,sBACA,yBACEvZ,EAAc,EAAK8qC,iBACzB,OACE,cAAC,IAAD,2BACMxtC,GADN,IAEEhP,MACE,cAAC,IAAD,CAAY0E,QAAQ,SAApB,+CAEFA,QAAmB,OAAVwE,EAAiB,WAAa,WACvCwI,YAAaA,EACbssC,WAAY9tB,EACZ+tB,gBAAiB,CAAEC,QAAQ,GAC3BC,WAAU,uCACLnvC,EAAOmvC,YACPN,GAFK,IAGR74C,MAAO,CAAE5E,OAAQ,GACjBg+C,QAAmB,OAAVl1C,GAAiB,KAC1Bm1C,aACE,qCACGvzB,EAAU,cAAC,IAAD,CAAkB/hB,MAAM,UAAU7C,KAAM,KAAS,KAC3D8I,EAAOmvC,WAAWE,aAClBP,GACC,EAAKH,4BAA4B3yB,GACjCgE,EAWA,cAAC,IAAD,CAASvpB,MAAOs4C,EAAhB,SACE,eAAC,IAAD,CACEv9C,QAAS,SAACX,GACRA,EAAE+f,kBACFqV,KAEF/uB,KAAK,QALP,UAOE,cAAC,IAAD,CAAYxB,QAAQ,SAApB,SAA8Bq5C,IAC7B9yB,EACC,cAAC,IAAD,IAEA,cAAC,IAAD,SAtBN,cAAC,IAAD,CAASxlB,MAAM,sBAAf,SACE,eAAC,IAAD,CACES,KAAK,QACL1F,QAASqvB,EAFX,UAIE,cAAC,IAAD,CAAYnrB,QAAQ,SAApB,iCACA,cAAC,IAAD,SAqBLgmB,EAAaphB,OAAS,GACvB0lB,GACiB,KAAjBpE,EACE,cAAC,IAAD,CAASnlB,MAAM,mBAAf,SACE,eAAC,IAAD,CAAYjF,QAASuuB,EAAe7oB,KAAK,QAAzC,UACE,cAAC,IAAD,CAAYxB,QAAQ,SAApB,8BACA,cAAC,IAAD,SAIJ,cAAC,UAAD,CACEoH,IAAKA,EACLue,cAAeA,EACf4F,iBAAkBA,EAClBxZ,IAAKA,EACLsU,cAAeA,EACfuD,YAAa,EAAKlxB,MAAMkxB,YACxBI,YAAaA,EACbe,oBAAqBA,a,4CAUrC,WACE,MAA8C3yB,KAAKM,MAA3C2X,EAAR,EAAQA,QAASia,EAAjB,EAAiBA,kBAAmB9lB,EAApC,EAAoCA,MAC5BiyC,EAAmBr+C,KAAK8W,MAAxBunC,eAER,OACE,eAAC,IAAD,CACEj2C,UAAWo1B,kBAAKvlB,EAAQupC,gBAAT,eACZvpC,EAAQwpC,gBAAkBpD,IAF/B,UAKE,cAAC,IAAD,CAAMnlC,MAAI,EAAV,SACE,cAAC,IAAD,CAAOwoC,UAAqB,OAAVt1C,EAAiB,EAAI,EAAvC,SACGpM,KAAK8/C,yBAGT5tB,GAAqBlyB,KAAK6/C,gC,GA5WXrlC,IAAMC,eAkXfC,uBA9aA,SAAC9Z,GAAD,MAAY,CACzB4gD,gBAAiB,CACfp1C,MAAO,IACPoS,OAAQ5d,EAAM4G,QAAQ,IAExBi6C,gBAAiB,CACf7jC,MAAO,KAGT6hC,uBAAwB,CACtB5kC,SAAU,QAGZyd,UAAW,CACT9Z,OAAQ5d,EAAM4G,QAAQ,IAExBk3C,kBAAmB,CACjB17B,QAAS,OACT2+B,SAAU,OACVxpC,aAAcvX,EAAM4G,QAAQ,OA2ZjBkT,CAAmBknC,YAAUC,cAAY1D,M,yeCzXlD2D,E,oNACJhrC,MAAQ,CACNirC,cAAe,KACfC,wBAAyB,KACzBC,2BAA4B,KAC5BC,iBAAkB,KAClBC,aAAc,EAAK7hD,MAAMktB,cAAcC,mBACpCze,KAAI,SAACknB,GAAD,uBAAQA,EAAG/yB,MAAMuK,SAASlB,cAA1B,QAAoC,KACxCzG,QAAO,SAAC0C,EAAGyF,GAAJ,OAAUzF,EAAIyF,IAAG,GAC3Bk0C,sBAAsB,EACtBC,wBAAyB,GACzBC,cAAe,GACfC,oBAAqB,KACrBC,iCAAkC,OAClCC,uBAAwB,OACxBC,WAAW,EACXC,iBAAkB,I,EAIpBC,iBAAmB,K,EACnBC,kBAAoB,G,EACpBC,4BAA8B,G,EAG9BC,wBAA0B,I,EAE1BC,kBAAoB,CAClB,CACEz4B,KAAM,WACN7gB,KAAM,SACNu5C,OAAQ,kBAAM,EAAKC,oBACnBv0B,QAAO,UAAE,EAAKruB,MAAMe,QAAQ8hD,8BAArB,UAET,CACE54B,KAAM,UACN7gB,KAAM,OACNu5C,OAAQ,kBAAM,EAAKG,kBACnBz0B,QAAO,UAAE,EAAKruB,MAAMe,QAAQgiD,4BAArB,UAET,CACE94B,KAAM,QACN7gB,KAAM,QACNu5C,OAAQ,kBAAM,EAAKK,mBACnB30B,QAAO,UAAE,EAAKruB,MAAMe,QAAQkiD,sCAArB,UAET,CACEh5B,KAAM,YACN7gB,KAAM,WACNu5C,OAAQ,kBAAM,EAAKO,sBACnB70B,QAAO,UAAE,EAAKruB,MAAMe,QAAQoiD,gCAArB,W,EAIXC,kBAAoB,CAClB,CACEh6C,KAAM,OACN6gB,KAAM,sBACNo5B,UAAW,CAAC,qBAAsB,aAEpC,CACEj6C,KAAM,OACN6gB,KAAM,sBACNo5B,UAAW,CAAC,qBAAsB,aAEpC,CACEj6C,KAAM,UACN6gB,KAAM,mBACNo5B,UAAW,CAAC,wB,EAIhB3sC,kBAAoB,WACF,EAAK1W,MAAbqZ,IACJxa,eAAemiB,UACjB,oCACA,SAAC5T,GACC,IAAMk2C,EAAal2C,EAASsB,KAAI,SAACnE,GAC/B,OAAOA,EAAQuE,WAEjB,EAAKy0C,mBAAmBD,MAG5B,EAAKE,yB,EAGPC,qBAAuB,WACL,EAAKzjD,MAAbqZ,IACJxa,eAAeo7C,YAAY,qC,EAGjCsJ,mBAAqB,SAACD,GACpB,IAAQzrB,EAAgC,EAAK73B,MAArC63B,4BACF6rB,EAAYJ,EAAW,GAGzB,EAAKtjD,MAAM+9C,gBAAgBlmB,IAG/B,IAAMtD,EAAoB,EAAKovB,kCAAkCD,GAGjE,IAAInvB,EAAkBtd,OAAO2sC,YAA7B,CAKA,IAAMr5C,EAAUgqB,EAAkB1xB,MAAMuK,SAASsM,MAC/C,SAACnP,GAAD,OAAaA,EAAQuE,UAAY40C,KAI/Bn5C,EAAQq5C,aAIZ,EAAKC,0BAA0Bt5C,EAASgqB,EAAmB,e,EAG7DovB,kCAAoC,SAACD,GAEnC,OAD+B,EAAK1jD,MAA5BmtB,mBACkBzT,MAAK,SAAC6a,GAC9B,OACEA,EAAkB1xB,MAAMuK,SAASiL,WAC/B,SAAC9N,GAAD,OAAaA,EAAQuE,UAAY40C,MAC9B,M,EAKXF,sBAAwB,WAAO,IAAD,EACpBr2B,EAAuB,EAAKntB,MAA5BmtB,mBAEFu0B,EAC0B,IAA9Bv0B,EAAmBjhB,OAAeihB,EAAmB,QAAKja,EACtDuuC,EAAgBC,GACgC,IAAlDA,EAAwB7+C,MAAMuK,SAASlB,OACrCw1C,EAAwB7+C,MAAMuK,SAAS,QAEzC8F,IAI8D,OAAvBwuC,QAAuB,IAAvBA,GAAA,UAAAA,EAAyBzqC,cAAzB,eACvC2sC,cAKF,EAAKrsC,SAAS,CACZmqC,wBAAyBA,EACzBD,cAAeA,K,EAKrBqC,iCAAmC,SAACrhD,GAClC,IAAMshD,EAActhD,EAAEM,OAAOF,MAC7B,EAAKmhD,kBAAkBD,GAEvB5xB,aAAa,EAAKmwB,kBAClB,EAAKA,iBAAmBxjC,YAAW,WACjC,EAAKmlC,uBACJ,EAAKxB,0B,EAGVyB,qBAAuB,SAAC35C,GACtB,IAAM83C,EAAgB,YAAO,EAAK7rC,MAAM6rC,kBACxCA,EAAiBnzC,KAAK3E,GACtB,EAAKgN,SAAS,CAAE8qC,iBAAkBA,IAClC,EAAK8B,cAAc9B,I,EAGrB+B,0BAA4B,SAAC75C,GAC3B,IAAQm3C,EAA4B,EAAKlrC,MAAjCkrC,wBACFW,EAAgB,YAAO,EAAK7rC,MAAM6rC,kBAElCgC,EAAe,EAAKC,wBAAwB/5C,EAAQuE,SAC1DuzC,EAAiBzW,OAAOyY,EAAc,GAEE,gBAAb,OAAvB3C,QAAuB,IAAvBA,OAAA,EAAAA,EAAyBjtB,QAC3B,EAAKld,SAAS,CACZ8qC,iBAAkBA,EAClBX,wBAC8B,IAA5BW,EAAiBn2C,OACb,KACA,EAAKq4C,sBAAsBlC,KAGnC,EAAK9qC,SAAS,CAAE8qC,iBAAkBA,IAEpC,EAAK8B,cAAc9B,I,EAGrB8B,cAAgB,SAAC9B,GACf,IAAQt+B,EAAkB,EAAK/jB,MAAvB+jB,cACRA,EAAc/kB,QAAQ,uBAAwBqjD,GAC9Ct+B,EAAc/kB,QAAQ,qBAAsBqjD,I,EAG9CiC,wBAA0B,SAACZ,GACzB,OAAO,EAAKltC,MAAM6rC,iBAAiBhqC,WAAU,SAAC0/B,GAC5C,OAAOA,EAAYxtC,QAAQuE,UAAY40C,M,EAI3Cc,iCAAmC,SAACr3B,GAClC,IAAQk1B,EAAqB,EAAK7rC,MAA1B6rC,iBACR,GAA2C,IAAvC,EAAK7rC,MAAM6rC,iBAAiBn2C,OAC9B,OAAOihB,EAET,IAAMs3B,EAAkB,YAAOt3B,GAK/B,OAJAs3B,EAAmBv0C,QAAO,SAAC0lB,GACzB,MAAqB,eAAdA,EAAGnB,UAEZgwB,EAAmBC,QAAQ,EAAKH,sBAAsBlC,IAC/CoC,G,EAGTF,sBAAwB,SAAClC,GAKvB,MAAO,CACL5tB,OAAQ,aACRxd,OAAQ,CAAElV,GAAI,eAAgBiC,QAAS,oBACvCnB,MAAO,CACLuG,KAAM,oBACNgE,SATai1C,EAAiB58C,QAChC,SAAC2H,EAAU2qC,GAAX,4BAA+B3qC,GAA/B,CAAyC2qC,EAAYxtC,YACrD,O,EAYJy5C,kBAAoB,SAACD,GAGd,EAAKvtC,MAAMkrC,wBAQd,EAAKnqC,SAAS,CACZyqC,cAAe+B,IARjB,EAAKxsC,SAAS,CACZwqC,wBAAyBgC,K,EAY/BY,iBAAmB,WACZ,EAAKnuC,MAAMkrC,wBAUd,EAAKnqC,SACH,CACEyqC,cAAe,KAEjB,WACE,EAAKiC,wBAdT,EAAK1sC,SACH,CACEwqC,wBAAyB,KAE3B,WACE,EAAKkC,yB,EAebW,uBAAyB,WACvB,IAAQjtC,EAAY,EAAK3X,MAAjB2X,QACR,EACE,EAAKnB,MADCkrC,EAAR,EAAQA,wBAAyBM,EAAjC,EAAiCA,cAAeD,EAAhD,EAAgDA,wBAE1C8C,EACJ7C,EAAc91C,OAAS,GAAK61C,EAAwB71C,OAAS,EAC/D,OACE,eAAC,IAAD,CAAM0M,MAAI,EAAC9Q,UAAW6P,EAAQmtC,0BAA2B9qC,GAAI,GAA7D,UACE,cAAC,IAAD,CAAY1S,QAAQ,SAApB,wDAGA,cAAC,IAAD,CACErE,WAAS,EACTH,SAAU,EAAKghD,iCACfjhD,MACE6+C,EAA0BM,EAAgBD,EAE5C3K,WAAS,EACTtuC,KAAK,QACLxB,QAAQ,WACR1E,MAAM,4BACNm+C,WAAY,CACVE,aAAc4D,GACZ,cAAC,IAAD,CAASx8C,MAAM,gBAAf,SACE,eAAC,IAAD,CAAYjF,QAAS,EAAKuhD,iBAAkB77C,KAAK,QAAjD,UACE,cAAC,IAAD,CAAYxB,QAAQ,SAApB,2BACA,cAAC,IAAD,gB,EAUhBy9C,8BAAgC,WAC9B,MAAgE,EAAKvuC,MAA7DurC,EAAR,EAAQA,wBAAyBJ,EAAjC,EAAiCA,2BACzBx0B,EAAuB,EAAKntB,MAA5BmtB,mBAER,OAAI,EAAKq1B,8BAAgCT,EAEhC50B,EAAmBjd,QAAO,SAACqkB,GAAuB,IAAD,EAEtD,cAAOA,QAAP,IAAOA,GAAP,UAAOA,EAAmBtd,cAA1B,aAAO,EAA2BjT,QAC/ByjB,cACAjT,SAASutC,EAAwBt6B,mBAIR,OAA1Bk6B,QAA0B,IAA1BA,OAAA,EAAAA,EAA4Bz1C,QAAS,EAChCy1C,EAEFx0B,G,EAMX63B,eAAiB,WACf,MACE,EAAKxuC,MADCkrC,EAAR,EAAQA,wBAAyBM,EAAjC,EAAiCA,cAAeD,EAAhD,EAAgDA,wBAKhD,SAAOL,GAA2BM,EAAc91C,OAAS,KAKtDw1C,GAA2BK,EAAwB71C,OAAS,G,EAMjE+4C,mCAAqC,SAACxiB,GACpC,OAAO,EAAK2gB,kBAAkBlzC,QAAO,SAACwjC,GAAD,OACnCA,EAAS2P,UAAU7uC,SAASiuB,O,EAIhCyiB,2BAA6B,SAAC97C,GACQ,EAAKoN,MAAjCkrC,wBAGN,EAAKnqC,SAAS,CACZ4qC,uBAAwB/4C,EACxB64C,oBAAqB,OAGvB,EAAK1qC,SAAS,CACZ2qC,iCAAkC94C,EAClC64C,oBAAqB,Q,EAK3BkD,+BAAiC,WAAO,IAAD,EAC7BphC,EAAkB,EAAK/jB,MAAvB+jB,cACA29B,EAA4B,EAAKlrC,MAAjCkrC,wBACF0D,EAAQ,OAAG1D,QAAH,IAAGA,GAAH,UAAGA,EAAyBzqC,cAA5B,aAAG,EAAiClV,GAC5CsjD,EAAsC,iBAAbD,EAEzB/C,GACH+C,GAAYC,EACT,GACA,YAAI,EAAK7uC,MAAM6rC,kBAAkBnyC,QAAO,SAAC6nC,GAAiB,IAAD,EACvD,OAAO,UAAAA,EAAYxtC,eAAZ,eAAqB0M,OAAOlV,MAAOqjD,KAElD,EAAK7tC,SAAS,CACZ8qC,iBAAkBA,EAClBX,wBAAyB2D,EACrB,KACA3D,IAEN39B,EAAc/kB,QAAQ,uBAAwBqjD,I,EAGhDiD,kBAAoB,WAClB,MAKI,EAAK9uC,MAJP0rC,EADF,EACEA,iCACAC,EAFF,EAEEA,uBACAF,EAHF,EAGEA,oBACAP,EAJF,EAIEA,wBAGI6D,EAA2B,EAAKN,mCACpCvD,EAA0B,WAAa,sBAEzC,OACE,cAAC,IAAD,CACE8D,SAAUvD,EACVnhD,KAAM4lC,QAAQub,GACdphD,QAAS,kBAAM,EAAK0W,SAAS,CAAE0qC,oBAAqB,QAHtD,SAKGsD,EAAyB72C,KAAI,SAACglC,EAAUv9B,GACvC,OACE,cAAC,IAAD,CACEgiC,SACEzE,EAAStqC,QACRs4C,EACGS,EACAD,GAEN9+C,QAAS,kBAAM,EAAK8hD,2BAA2BxR,EAAStqC,OAExDvG,MAAO6wC,EAAStqC,KATlB,mBAWMsqC,EAASzpB,KAAK,GAAGzC,eAXvB,OAWuCksB,EAASzpB,KAAKtC,MAAM,KAHpDxR,S,EAWjBysC,iBAAmB,WACjB,IAAQjrC,EAAY,EAAK3X,MAAjB2X,QACF8tC,EAAe,EAAKT,iBACpBU,EAAiBD,EACnB,uBACA,sBACJ,OACE,cAAC,IAAD,CAASp9C,MAAOq9C,EAAhB,SACE,cAAC,IAAD,CACE59C,UAAW6P,EAAQguC,cACnBviD,QAAS,kBACP,EAAKmU,SAAS,CACZuqC,sBAAuB,EAAKtrC,MAAMsrC,wBAJxC,SAQE,cAAC,IAAD,CACEn2C,MAAM,UACNi6C,aAAa,IACbt+C,QAAQ,MACRu+C,WAAYJ,EAJd,SAME,cAAC,IAAD,W,EAOV3C,eAAiB,WACf,IAAQnrC,EAAY,EAAK3X,MAAjB2X,QACR,EAII,EAAKnB,MAHPkrC,EADF,EACEA,wBACAQ,EAFF,EAEEA,iCACAC,EAHF,EAGEA,uBAGI2D,EAAY,iDAEhB,EAAK1C,kBAAkB1pC,MAErB,SAACg6B,GAAD,OAEEA,EAAStqC,QAGRs4C,EACGS,EACAD,MACNj4B,MAGJ,OACE,cAAC,IAAD,CAAS5hB,MAAOy9C,EAAhB,SACE,cAAC,IAAD,CACEh+C,UAAW6P,EAAQguC,cACnBviD,QAAS,SAACX,GAAD,OACP,EAAK8U,SAAS,CAAE0qC,oBAAqBx/C,EAAEsjD,iBAH3C,SAME,cAAC,IAAD,S,EAMR/C,gBAAkB,WAChB,IAAQrrC,EAAY,EAAK3X,MAAjB2X,QACR,OACE,cAAC,IAAD,CAAStP,MAAM,gCAAf,SACE,cAAC,IAAD,CACEP,UAAW6P,EAAQguC,cACnBviD,QAAS,EAAK+hD,+BAFhB,SAIE,cAAC,IAAD,S,EAMRjC,mBAAqB,WACnB,IAAM8C,EAAwB,EAAKC,2BACnC,OACE,cAAC,UAAD,CACE94B,mBAAoB64B,EACpBjiC,cAAe,EAAK/jB,MAAM+jB,iB,EAKhCkiC,yBAA2B,WACzB,MAII,EAAKzvC,MAHPkrC,EADF,EACEA,wBACAC,EAFF,EAEEA,2BACAK,EAHF,EAGEA,cAEM70B,EAAuB,EAAKntB,MAA5BmtB,mBAER,GAAIu0B,EAAyB,CAC3B,GAA0C,iBAAtCA,EAAwBzqC,OAAOlV,GACjC,MAAO,CAAC2/C,GAEV,GAAsB,KAAlBM,EACF,MAAO,CAACN,GAEV,IAAME,EAAmB,EAAKlN,oBAAoB,CAChDgN,IAMF,MAAO,CAJmB,2BACrBA,GADqB,IAExB7+C,MAAO,CAAEuK,SAAUw0C,MAIvB,OAAID,GAIGx0B,G,EAGT+4B,iBAAmB,WACjB,OAAwE,IAAjE,EAAKxD,kBAAkBxyC,QAAO,SAACqoB,GAAD,OAAUA,EAAKlK,WAASniB,Q,EAG/Di6C,4BAA8B,WAC5B,IAAQxuC,EAAY,EAAK3X,MAAjB2X,QACR,OAAI,EAAKuuC,mBACA,KAGL,eAAC,IAAD,CAAMttC,MAAI,EAACD,WAAS,EAAC5Q,MAAM,SAAS+Q,QAAQ,WAA5C,UACE,cAAC,IAAD,CAAMstC,GAAI,EAAK5vC,MAAM4rC,UAAW3F,QAAS,IAAzC,SACE,cAAC,IAAD,CACE7jC,MAAI,EACJ9Q,UAAY,EAAK0O,MAAM4rC,UAA6B,KAAjBzqC,EAAQ0uC,OAF7C,SAIG,EAAK3D,kBAAkBh0C,KAAI,SAAC6pB,EAAMpiB,GACjC,OACEoiB,EAAKlK,SACH,cAAC,IAAM/X,SAAP,UAA6BiiB,EAAKoqB,UAAbxsC,UAM/B,cAAC,IAAD,CAAMyC,MAAI,EAAV,SACE,cAAC,IAAD,CACEvQ,MAAK,UAAK,EAAKmO,MAAM4rC,UAAY,UAAS,OAArC,YADP,SAGE,cAAC,IAAD,CACEt6C,UAAW6P,EAAQguC,cACnBviD,QAAS,kBACP,EAAKmU,SAAS,CACZ6qC,WAAY,EAAK5rC,MAAM4rC,UACvBN,sBAAsB,KAL5B,SASG,EAAKtrC,MAAM4rC,UAAY,cAAC,IAAD,IAAgB,cAAC,IAAD,c,EAStDjqC,iBAAmB,SAAC5N,GAClB,IAAQm3C,EAA4B,EAAKlrC,MAAjCkrC,wBACR,EAAKmC,0BAA0Bt5C,EAASm3C,I,EAG1CmC,0BAA4B,SAACyC,EAAaC,EAAgBjzB,GACxD,IAAQvP,EAAkB,EAAK/jB,MAAvB+jB,cACA09B,EAAkB,EAAKjrC,MAAvBirC,cACFY,EAAgB,YAAO,EAAK7rC,MAAM6rC,kBAClCmE,EAAoC,cAAdlzB,EAE5B,GAAImuB,EAAe,CACjB,IAAM4C,EAAehC,EAAiBhqC,WAAU,SAAC0/B,GAC/C,OACEA,EAAYxtC,QAAQuE,UAAY2yC,EAAc3yC,SACpB,eAA1BipC,EAAYzkB,cAGE,IAAlB+wB,GAAuBhC,EAAiBzW,OAAOyY,EAAc,GAC7DtgC,EAAc/kB,QAAQ,uBAAwBqjD,GAG5CiE,KAC0B,EAAKG,kBAAkBH,IAEjDjE,EAAiBnzC,KACf,EAAKw3C,mBAAmBJ,EAAaC,EAAgBjzB,KAG3D,EAAK/b,SACH,CACE8qC,iBAAkBA,EAClBX,wBAAyB6E,EACzB9E,cAAe6E,EACfxE,sBAAsB,EACtBE,cAAgBuE,EAAsB,EAAK/vC,MAAMwrC,cAAhB,KAEnC,YACGuE,GAAkB,EAAKtC,wBAGxBqC,GACEE,GACFziC,EAAc/kB,QAAQ,oBAAqBsnD,GAE7CviC,EAAc/kB,QAAQ,0BAA2BsnD,IAEjDviC,EAAc/kB,QAAQ,uBAAwBqjD,I,EAIlDoE,kBAAoB,SAACl8C,GAEnB,OAD6B,EAAKiM,MAA1B6rC,iBACgB/pB,MAAK,SAACyf,GAC5B,OAAOA,EAAYxtC,QAAQuE,UAAYvE,EAAQuE,Y,EAInD43C,mBAAqB,SAACJ,EAAaC,EAAgBjzB,GAAe,IAAD,EAK/D,OAJKgzB,EAAYrvC,SACfqvC,EAAYrvC,OAASsvC,EAAetvC,QAG/B,CACL1M,QAAS+7C,EACTlB,SAAQ,UAAEkB,EAAYrvC,cAAd,QAAwBsvC,EAAetvC,OAAOlV,GACtDuxB,UAAWA,I,EAIfqzB,2BAA6B,SAACpyB,GAC5B,EAAKhd,SACH,CACEmqC,wBAAyBntB,EACzButB,sBAAsB,EACtBE,cAAe,KAEjB,WACE,EAAKiC,qBACL,iCAAiC1vB,O,0DAKT,SAACA,GAE7B,IAAsD,IAAlD,EAAKv0B,MAAMe,QAAQ6lD,2BAAvB,CAEA,IAAMz5C,EAAK,iCAAsBonB,EAAkBtd,OAAO+wB,KAE1D,GAAwB,UAApB76B,EAAMhI,UAAuB,CAM/B,IAAM0hD,EAA0B15C,EAC7BiC,YACAgC,YAF6B,OAGnBC,MAAM,KAChBnB,QAAO,SAACzN,GAAD,OAAoB,IAAbA,EAAEyJ,UAMb46C,EAAkB35C,EAAM8D,UAAUf,QAAO,SAAC02B,GAC9C,OACEigB,EAAwBryC,SAASoyB,IACjCA,IAAMrS,EAAkBtd,OAAOlV,MAKnC,EAAK/B,MAAMqZ,IAAIxa,eAAeG,QAAQ,0BAA2B,CAC/DmO,QACA25C,yBAEQ35C,EAAMgpC,cAGhBhpC,EAAM02B,YAAW,O,0DAIL,SAAC0B,GACf,OAAO,EAAKvlC,MAAM0O,IACfsB,YACAC,WACAyJ,MAAK,SAACvM,GACL,OAAOo4B,IAAYp4B,EAAM45C,QAAQ98B,W,EAIvC+8B,6BAA+B,SAACzyB,GAAuB,IAAD,EAC5Clb,EAAQ,EAAKrZ,MAAbqZ,IACFuqC,EAAW,OAAGrvB,QAAH,IAAGA,GAAH,UAAGA,EAAmBtd,cAAtB,aAAG,EAA2B2sC,YAC3CA,EACFvqC,EAAIxa,eAAeG,QAAnB,0CACqC4kD,GACnCrvB,GAGF,EAAKoyB,2BAA2BpyB,I,EAIpC0yB,uBAAyB,SAAC95B,GACxB,IAAQ+0B,EAAqC,EAAK1rC,MAA1C0rC,iCAEFgF,EAA+B/5B,EAAmBxf,MAAK,SAACxF,EAAGyF,GAAJ,OAC3DzF,EAAE8O,OAAOjT,QAAQ6J,cAAcD,EAAEqJ,OAAOjT,YAG1C,OAAQk+C,GACN,IAAK,UACH,OAAO/0B,EAAmBxf,MAAK,SAACxF,EAAGyF,GAAJ,OAC7BzF,EAAEtF,MAAMskD,cAAgBv5C,EAAE/K,MAAMskD,eAAiB,EAAI,KAEzD,IAAK,OACH,OAAOD,EAA6BE,UACtC,QAEE,OAAOF,I,EAIbG,gBAAkB,SAACv1B,GACjB,OAAuB,KAAhBA,EAAMiB,OAAkC,KAAlBjB,EAAMkB,S,EAGrC0hB,oBAAsB,SAACvnB,GACrB,MAAmD,EAAK3W,MAAhDkrC,EAAR,EAAQA,wBAAyBM,EAAjC,EAAiCA,cACjC,OAAO70B,EACJze,KAAI,SAACknB,GACJ,OAAI8rB,GACE9rB,EAAG3e,OAAOlV,KAAO2/C,EAAwBzqC,OAAOlV,GAC3C6zB,EAAG/yB,MAAMuK,SAAS8C,QAAO,SAACZ,GAC/B,OAAOA,EAAEhD,aACNmb,cACAjT,SAASwtC,EAAcv6B,kBAIzBmO,EAAG/yB,MAAMuK,YAEjB0nB,Q,EAGLmvB,mBAAqB,WACnB,MAAmD,EAAKztC,MAAhDurC,EAAR,EAAQA,wBAAyBC,EAAjC,EAAiCA,cACjC,EAA8C,EAAKhiD,MAA3C+jB,EAAR,EAAQA,cAAeoJ,EAAvB,EAAuBA,mBAEvB,GACE,EAAKo1B,oBAAsBP,GAC3B,EAAKQ,8BAAgCT,EAFvC,CAOA,IAAMJ,EACJ,EAAKoD,8BAA8B53B,GAC/By0B,EAAmB,EAAKlN,oBAC5BiN,GAEI2F,EAAoB1F,EAAiBlzC,KAAI,SAACnE,GAC9C,OAAOA,EAAQuE,WAGjB,EAAKyI,SAAS,CACZoqC,2BAA4BA,EAC5BC,iBAAkBA,IAGpB,EAAKW,kBAAoBP,EACzB,EAAKQ,4BAA8BT,EAEnCh+B,EAAc/kB,QAAQ,sCAAuC,CAC3DoO,SAAUw0C,EACV0B,WAAYgE,M,EAIhBC,kBAAoB,SAACC,EAAwBl7C,GAC3C,IAAQqL,EAAY,EAAK3X,MAAjB2X,QACR,EAAmD,EAAKnB,MAAhDkrC,EAAR,EAAQA,wBAAyBD,EAAjC,EAAiCA,cAC3BgG,EACJ/F,IAA4BA,EAAwBzqC,OAAO2sC,YACvD8D,EACJjG,IAAkBA,EAAcmC,YAClC,OAAI6D,EAEA,eAAC,IAAD,CAAaxuC,aAAW,aAAa0uC,UAAU,IAA/C,UACE,cAAC,IAAD,CAASt/C,MAAM,oCAAf,SACE,cAAC,IAAD,CACEP,UAAW6P,EAAQiwC,gBACnBlkC,SAAU,EACV/X,MAAM,cACNrE,QAAQ,UACRlE,QAAS,SAACX,GACRA,EAAE+f,kBACF,EAAKqhC,6BAEPgE,UAAW,SAAC/1B,GACN,EAAKu1B,gBAAgBv1B,IACvB,EAAK+xB,6BAGT/gD,SAAU,EAAK+gD,0BAdjB,8BAmBF,cAAC,IAAD,CAASx7C,MAAOm/C,EAAhB,SACE,cAAC,IAAD,CACE1/C,UAAW6P,EAAQiwC,gBACnBlkC,SAAU,EACV/X,MAAM,cACNrE,QAAQ,UACRlE,QAAS,SAACX,GACRA,EAAE+f,kBACF,EAAKrK,sBAAiBjF,IAExB20C,UAAW,SAAC/1B,GACN,EAAKu1B,gBAAgBv1B,IACvB,EAAK3Z,sBAAiBjF,IAX5B,SAeGs0C,MAGJE,GACC,cAAC,IAAD,CAASr/C,MAAOiE,EAAhB,SACE,cAAC,IAAD,CACEoX,SAAU,EACV5b,UAAW6P,EAAQiwC,gBACnBj8C,MAAM,cACNrE,QAAQ,UAJV,SAMGgF,SAOJ,M,EAIXw7C,oBAAsB,SAACN,GACrB,IAAQ9F,EAA4B,EAAKlrC,MAAjCkrC,wBACA/pC,EAAY,EAAK3X,MAAjB2X,QACR,OACE,eAAC,IAAD,CACEgB,WAAS,EACTC,MAAI,EACJE,QAAQ,gBACRD,WAAW,SACXkhB,KAAK,SACL/f,GAAI,GANN,UAQE,cAAC,IAAD,CACErB,WAAS,EACTC,MAAI,EACJmhB,KAAK,SACLlhB,WAAW,SACXmB,GAAI,EAAKxD,MAAM4rC,UAAY,EAAI,GALjC,SAOE,cAAC,IAAD,CACE/5C,MACEq5C,EAA0B8F,EAAyB,iBAFvD,SAKE,cAAC,IAAD,CACElgD,QAAQ,SACRuB,UAAU,MACVsQ,QAAM,EACNrR,UAAW6P,EAAQyB,iBAJrB,mBAOIsoC,EAA0B8F,EAAyB,wBAK3D,cAAC,IAAD,CACE7uC,WAAS,EACTC,MAAI,EACJE,QAAQ,WACRkB,GAAI,EAAKxD,MAAM4rC,UAAY,EAAI,EAJjC,SAMG,EAAK+D,oC,EAMd4B,0BAA4B,WAC1B,IAAQpwC,EAAY,EAAK3X,MAAjB2X,QACR,EAAmD,EAAKnB,MAAhDkrC,EAAR,EAAQA,wBAAyBD,EAAjC,EAAiCA,cAE3B+F,EAAyB9F,EAC3BA,EAAwBzqC,OAAOjT,QAC/B,GACEsI,EAAem1C,EAAgBA,EAAcn1C,aAAe,GAC5D07C,GACHvG,IAAD,OAAkBA,QAAlB,IAAkBA,OAAlB,EAAkBA,EAAemC,aAEnC,OACE,eAAC,IAAD,CACE97C,UACEkgD,EACIrwC,EAAQswC,oBACRtwC,EAAQoC,gBAEdpB,WAAS,EACTC,MAAI,EACJoB,GAAI,GARN,UAUE,cAAC,IAAD,CAAMpB,MAAI,EAACoB,GAAI,GAAf,SACG,EAAKutC,kBAAkBC,EAAwBl7C,KAEjD07C,GACC,EAAKF,oBAAoBN,EAAwBl7C,O,4CAKzD,WAAU,IAAD,MACP,EAOI5M,KAAKM,MANP2X,EADF,EACEA,QACA0B,EAFF,EAEEA,IACA8kC,EAHF,EAGEA,mBACAp6B,EAJF,EAIEA,cACAg6B,EALF,EAKEA,eACAh9C,EANF,EAMEA,QAEF,EAQIrB,KAAK8W,MAPPqrC,EADF,EACEA,aACAH,EAFF,EAEEA,wBACAD,EAHF,EAGEA,cACAK,EAJF,EAIEA,qBACAE,EALF,EAKEA,cACAE,EANF,EAMEA,iCACAC,EAPF,EAOEA,uBAGIh1B,EAEJu0B,EAEI,CAACA,GAEDhiD,KAAKqlD,8BAA8BrlD,KAAKM,MAAMmtB,oBAE9C+6B,EACJxoD,KAAKunD,uBAAuB95B,GAExBg7B,EAA8B,UAClCpnD,EAAQqnD,wCAD0B,SAG9BC,EAAsB3G,EACxB,CAACA,GACDyG,EACAzoD,KAAK8kD,iCAAiC0D,GACtCA,EAEJ,OACE,cAAC,IAAD,CAAU9B,IAAKrI,EAAf,SACoB,IAAjB8D,EACC,cAAC,IAAD,CAAO/5C,UAAW6P,EAAQogB,KAA1B,SACE,cAAC,IAAD,CAAOuwB,SAAS,UAAhB,gDAGF,cAAC,IAAD,CAAOxgD,UAAW6P,EAAQogB,KAA1B,SACE,eAAC,IAAD,CAAMpf,WAAS,EAAC7Q,UAAW6P,EAAQ4wC,wBAAnC,UACG7oD,KAAKqoD,4BACLjG,GAAwBpiD,KAAKklD,yBAC7BllD,KAAK4lD,oBACN,cAAC,IAAD,CAAM1sC,MAAI,EAACoB,GAAI,GAAf,SACE,cAAC,UAAD,CACE+J,cAAeA,EACfo6B,mBAAoBA,EACpBhxB,mBAAoBk7B,EACpBhvC,IAAKA,EACL2tC,6BACEtnD,KAAKsnD,6BAEP7uC,iBAAkBzY,KAAKyY,iBACvBupC,wBAAyBA,EACzBD,cAAeA,EACfO,cAAeA,EACfE,iCACEA,EAEFC,uBAAwBA,EACxBqG,qBAAoB,UAAEznD,EAAQynD,4BAAV,SACpB5uC,qBAAoB,UAAE7Y,EAAQ6Y,4BAAV,SACpBsqC,qBAAsBxkD,KAAKwkD,qBAC3BE,0BAA2B1kD,KAAK0kD,0BAChC/B,iBAAkB3iD,KAAK8W,MAAM6rC,iBAC7B8F,+BACEA,EAEFpnD,QAASA,iB,GAphCUmZ,IAAMC,eA+hC5BC,uBArlCA,SAAC9Z,GAAD,cAAY,CACzB+lD,OAAQ,CACN3jC,QAAS,QAEX6lC,yBAAuB,mBACpBjoD,EAAMI,YAAYC,KAAK,MAAQ,CAC9BujB,UAAW,SAFQ,cAIpB5jB,EAAMI,YAAY+nD,GAAG,MAAQ,CAC5BvkC,UAAW,SALQ,GAQvB6T,MAAI,GACF7T,UAAW,OACX3X,SAAU,OACVkO,SAAU,KAHR,cAIDna,EAAMI,YAAY+nD,GAAG,MAAQ,CAC5BluC,SAAU,MALV,cAODja,EAAMI,YAAYC,KAAK,MAAQ,CAC9B8Z,SAAU,OACVF,SAAU,OACV7C,SAAU,WACV4F,KAAM,EACNsgC,UAAU,GAAD,OAAKt9C,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,WAZ1D,GAeJkM,0BAA2B,CACzB79C,QAAS3G,EAAM4G,QAAQ,GACvBolB,aAAa,GAAD,OAAKhsB,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,UAE/D7+B,gBAAiB,CACflC,aAAcvX,EAAM4G,QAAQ,GAC5BmT,YAAa/Z,EAAM4G,QAAQ,IAE7B+gD,oBAAqB,CACnBxkC,UAAW,GACX5L,aAAcvX,EAAM4G,QAAQ,GAC5BmT,YAAa/Z,EAAM4G,QAAQ,GAC3BolB,aAAa,GAAD,OAAKhsB,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,UAE/Dx/B,iBAAkB,CAChBmB,SAAU,OACVhT,SAAU,IAEZo+C,cAAe,CACblrC,SAAU,IAEZmtC,gBAAiB,CACfhpB,OAAQ,OACRhvB,OAAQ,cAmiCGwK,CAAmBonC,I,uJC7lC5BkH,E,4MACJhyC,kBAAoB,WACQ,EAAK1W,MAAvByhD,eAIN,EAAKkH,4B,EAITA,yBAA2B,WACzB,MAMI,EAAK3oD,MALPqZ,EADF,EACEA,IACAooC,EAFF,EAEEA,cACAC,EAHF,EAGEA,wBACA39B,EAJF,EAIEA,cACAmgC,EALF,EAKEA,qBAGF,GAAIzC,EAAcmC,YAChBvqC,EAAIxa,eAAeG,QAAnB,gCAC2ByiD,EAAcmC,aACvCnC,OAEG,CACL,IAAMxqC,EAAM,OAAGyqC,QAAH,IAAGA,OAAH,EAAGA,EAAyBzqC,OAExCwqC,EAAcxqC,OAASA,EACvBitC,EAAqB,CACnB35C,QAASk3C,EACT2D,SAAQ,OAAEnuC,QAAF,IAAEA,OAAF,EAAEA,EAAQlV,GAClBuxB,UAAW,gBAEY,OAArB,EAAKtzB,MAAM8L,OAAuC,OAArB,EAAK9L,MAAM8L,OAC1CiY,EAAc/kB,QAAQ,4BAExB+kB,EAAc/kB,QAAQ,gDAAiD,CACrEuL,QAASk3C,M,EAKfmH,qBAAuB,SAACr+C,GACtB,MAAkC,EAAKvK,MAA/BqZ,EAAR,EAAQA,IAAKlB,EAAb,EAAaA,iBACT5N,EAAQq5C,YACVvqC,EAAIxa,eAAeG,QAAnB,gCAC2BuL,EAAQq5C,aACjCr5C,GAGF4N,EAAiB5N,I,EAIrBs+C,wBAA0B,SAAC/2B,EAAOvnB,GACZ,KAAhBunB,EAAMiB,OAAkC,KAAlBjB,EAAMkB,SAC9B,EAAK41B,qBAAqBr+C,I,EAI9Bu+C,iCAAmC,SAACv0B,GAAuB,IAAD,IAChD4pB,EAAuB,EAAKn+C,MAA5Bm+C,mBACR,OACE,cAAC,UAAD,CACE5pB,kBAAmBA,EACnB4pB,mBAAoBA,EACpBpxB,qBAAoB,UAAE,EAAK/sB,MAAMe,QAAQgsB,4BAArB,QAA6C,IACjEg8B,+BAA8B,UAC5B,EAAK/oD,MAAMe,QAAQgoD,sCADS,Y,EAOpCC,0BAA4B,SAACz0B,GAC3B,MAgBI,EAAKv0B,MAfPm+C,EADF,EACEA,mBACA9kC,EAFF,EAEEA,IACAqoC,EAHF,EAGEA,wBACAD,EAJF,EAIEA,cACAtpC,EALF,EAKEA,iBACA6uC,EANF,EAMEA,6BACAhF,EAPF,EAOEA,cACAG,EARF,EAQEA,uBACAqG,EATF,EASEA,qBACAzkC,EAVF,EAUEA,cACAnK,EAXF,EAWEA,qBACAyoC,EAZF,EAYEA,iBACA6B,EAbF,EAaEA,qBACAE,EAdF,EAcEA,0BACA+D,EAfF,EAeEA,+BAEF,OACE,cAAC,UAAD,CACE9uC,IAAKA,EACLkb,kBAAmBA,EACnB4pB,mBAAoBA,EACpBkE,iBAAkBA,EAClBX,wBAAyBA,EACzBD,cAAeA,EACfuF,6BAA8BA,EAC9B7uC,iBAAkBA,EAClBywC,qBAAsB,EAAKA,qBAC3BC,wBAAyB,EAAKA,wBAC9B7G,cAAeA,EACfG,uBAAwBA,EACxBqG,qBAAsBA,EACtBzkC,cAAeA,EACfnK,qBAAsBA,EACtBsqC,qBAAsBA,EACtBE,0BAA2BA,EAC3B+D,+BAAgCA,K,EAKtC5I,uBAAyB,WACvB,MACE,EAAKv/C,MADCmtB,EAAR,EAAQA,mBAAoBxV,EAA5B,EAA4BA,QAASqvC,EAArC,EAAqCA,6BAErC,OACE,cAAC,IAAD,CAAMl/C,UAAW6P,EAAQsxC,iBAAzB,SACG97B,EAAmBze,KAAI,SAAC6lB,GAAD,OACtB,cAAC,IAAD,CACE20B,oBAAkB,EAElBphD,UAAW6P,EAAQwxC,qBACnBpnD,GAAE,gCAA2BwyB,EAAkBtd,OAAOlV,IACtDqnD,gBAAA,wCAAgD70B,EAAkBtd,OAAOlV,IACzEqB,QAAS,kBAAM4jD,EAA6BzyB,IAC5CsH,QAAM,EACN+c,SAAO,EART,SAUG,EAAKkQ,iCAAiCv0B,IARlCA,EAAkBtd,OAAOlV,U,4CAexC,WACE,IAAQ2/C,EAA4BhiD,KAAKM,MAAjC0hD,wBAER,OAAOA,EACHhiD,KAAKspD,0BAA0BtH,GAC/BhiD,KAAK6/C,6B,GAhJmBrlC,IAAMC,eAoJvBC,uBAlKA,iBAAO,CACpB6uC,iBAAkB,CAChBhiD,QAAS,EACT6E,MAAO,OACPklC,WAAY,QAEdmY,qBAAsB,CACpBr9C,MAAO,OACP4W,QAAS,OACTzb,QAAS,EACT+pC,WAAY,WAwJD52B,CAAmBmnC,cAAYmH,K,uKClJxCW,E,4MAEJ7yC,MAAQ,CACN8yC,eAAgB,KAChBC,gBAAiB,M,EAGnBC,0BAA4B,I,EAC5BC,aAAe,K,EAEfC,sBAAwB,SAAC7yC,GACvB,MAA6C,EAAK7W,MAA1CgiD,EAAR,EAAQA,cAAeztB,EAAvB,EAAuBA,kBACjBo1B,EAAoB9yC,EAAUmrC,cAC9B4H,EAAcr1B,EAAkB1xB,MAAMuK,SAASlB,OAC/C29C,EAAkBhzC,EAAU0d,kBAAkB1xB,MAAMuK,SAASlB,OACnE,OACE81C,IAAkB2H,GAClBC,IAAgBC,IAEhB13B,aAAa,EAAKs3B,cAClB,EAAKlyC,SAAS,CAAEgyC,qBAAiBr2C,EAAWo2C,oBAAgBp2C,KACrD,I,EAKXuwC,qBAAuB,WACrBtxB,aAAa,EAAKs3B,e,EAGpBK,kBAAoB,SAACrnD,EAAG8H,GACtB,IAAMxH,EAASN,EAAEsjD,cACjB5zB,aAAa,EAAKs3B,cAClB,EAAKA,aAAe3qC,YAAW,WAC7B,EAAKvH,SAAS,CACZgyC,gBAAiBxmD,EACjBumD,eAAgB/+C,MAEjB,EAAKi/C,4B,EAGVO,aAAe,WACb53B,aAAa,EAAKs3B,cACd,EAAKjzC,MAAM8yC,gBACb,EAAK/xC,SAAS,CACZgyC,qBAAiBr2C,EACjBo2C,oBAAgBp2C,K,EAItBwhC,oBAAsB,WAAO,IAAD,EAClBsN,EAAkB,EAAKhiD,MAAvBgiD,cACFztB,EAAiB,eAAQ,EAAKv0B,MAAMu0B,mBAE1C,GAAIytB,EAAc91C,OAAS,EAAG,CAE5B,IAAM01C,EAAmBrtB,EAAkB1xB,MAAMuK,SAAS8C,QACxD,SAAC3F,GAGC,OAAOA,EAAQ+B,aACZmb,cACAjT,SAASwtC,EAAcv6B,kBAG9B,cAAOm6B,QAAP,IAAOA,IAAoB,GAG7B,iBAAOrtB,EAAkB1xB,MAAMuK,gBAA/B,QAA2C,I,EAG7C48C,kBAAoB,SAAC58C,GACnB,IAAQ+0C,EAA2B,EAAKniD,MAAhCmiD,uBAEF8H,EAAqB78C,EAASO,MAAK,SAACxF,EAAGyF,GAAJ,OACvCzF,EAAEmE,aAAauB,cAAcD,EAAEtB,kBAAc4G,EAAW,CACtD8hB,SAAS,OAIb,OAAQmtB,GACN,IAAK,OACH,OAAO8H,EAAmB7C,UAC5B,QAEE,OAAO6C,I,EAIbC,qBAAuB,SAAC98C,GACtB,MAQI,EAAKpN,MAPPu0B,EADF,EACEA,kBACAlb,EAFF,EAEEA,IACAqoC,EAHF,EAGEA,wBACAD,EAJF,EAIEA,cACA19B,EALF,EAKEA,cACA5L,EANF,EAMEA,iBACAyB,EAPF,EAOEA,qBAEF,OACE,cAAC,UAAD,CACErP,QAASk3C,EACTr0C,SAAUA,EACV+K,iBAAkBA,EAClBoc,kBAAmBA,EACnBlb,IAAKA,EACLpC,OAAQyqC,EAAwBzqC,OAChC8M,cAAeA,EACfnK,qBAAsBA,K,EAK5BuwC,kBAAoB,SAAC/8C,GACnB,MAYI,EAAKpN,MAXPu0B,EADF,EACEA,kBACA5c,EAFF,EAEEA,QACA0B,EAHF,EAGEA,IACAgpC,EAJF,EAIEA,iBACAZ,EALF,EAKEA,cACAmH,EANF,EAMEA,qBACAC,EAPF,EAOEA,wBACA1K,EARF,EAQEA,mBACA+F,EATF,EASEA,qBACAE,EAVF,EAUEA,0BACA+D,EAXF,EAWEA,+BAGIiC,EAAiB,EAAKJ,kBAAkB58C,GAC9C,OACE,qCACE,cAAC,IAAD,CACEtF,UAAW6P,EAAQ0yC,YACnBtoD,GAAE,wCAAmCwyB,EAAkBtd,OAAOlV,IAFhE,SAIGqoD,EAAe17C,KAAI,SAACY,GACnB,OACE,cAAC,IAAD,CACE45C,oBAAkB,EAClBphD,UAAW6P,EAAQ2yC,gBAEnB1R,SAAO,EACP/c,QAAM,EACNz4B,QAAS,WACP,EAAK2mD,eACLnB,EAAqBt5C,IAEvBu4C,UAAW,SAAC/1B,GAAD,OAAW+2B,EAAwB/2B,EAAOxiB,IACrD4qB,aACG9X,WAAiD,KAAtC,SAAC3f,GAAD,OAAO,EAAKqnD,kBAAkBrnD,EAAG6M,IAE/C6qB,aAAe/X,WAA+B,KAApB,EAAK2nC,aAdjC,SAgBE,cAAC,UAAD,CACEx/C,QAAS+E,EACT+J,IAAKA,EACLpC,OAAQsd,EAAkBtd,OAC1Bwd,OAAQF,EAAkBE,OAC1B81B,aACElI,EAAiBhqC,WACf,SAACO,GAAD,OAAUA,EAAKrO,QAAQuE,UAAYQ,EAAER,YAClC,EAEPo1C,qBAAsBA,EACtBE,0BAA2BA,EAC3B3C,cAAeA,EACftD,mBAAoBA,EACpBgK,+BACEA,KA5BC74C,EAAER,cAmCd,EAAK07C,gC,EAKZC,qBAAuB,WACrB,IAAQhJ,EAAkB,EAAKzhD,MAAvByhD,cAKFiG,EACJjG,IAAkBA,EAAcmC,YAE5Bx2C,EAAW,EAAKsnC,sBAEtB,OAAOgT,EACH,EAAKwC,qBAAqB98C,GAC1B,EAAK+8C,kBAAkB/8C,I,EAG7Bo9C,0BAA4B,WAC1B,MAA4C,EAAKh0C,MAAzC8yC,EAAR,EAAQA,eAAgBC,EAAxB,EAAwBA,gBACxB,EAA0D,EAAKvpD,MAAvD0hD,EAAR,EAAQA,wBAMR,SANA,EAAiC8G,sBAENpmC,aAAY,OAACknC,QAAD,IAACA,OAAD,EAACA,EAAgB1F,cAMpD,cAAC,UAAD,CACE0F,eAAgBA,EAChB5H,wBAAyBA,EACzBroC,IAAK,EAAKrZ,MAAMqZ,IAChBmsC,SAAU+D,IAIP,M,4CAIX,WACE,OAAO7pD,KAAK+qD,2B,GA3NmBvwC,IAAMmS,WA+N1BjS,uBA7OA,iBAAO,CACpBiwC,YAAa,CACXpjD,QAAS,EACT6E,MAAO,OACPklC,WAAY,QAEdsZ,gBAAiB,CACfx+C,MAAO,OACP4W,QAAS,OACTzb,QAAS,EACT+pC,WAAY,WAmOD52B,CAAmBivC,I,+KClO5BqB,E,4MACJC,wBAA0B,WACxB,IAAQJ,EAAiB,EAAKvqD,MAAtBuqD,aACFK,EAAYL,EAAqC,wBAAtB,uBAEjC,OACE,cAAC,IAAD,CAAM3xC,MAAI,EAAC7Q,MAAM,SAAjB,SACE,cAAC,IAAD,CAASM,MAAOuiD,EAAhB,SACE,cAAC,IAAD,CACEj/C,MAAM,UACNotC,QAASwR,EACTnnD,QAAS,SAACX,GAAD,OAAOA,EAAE+f,mBAClB1f,SAAU,EAAK+nD,qBACf7+B,KAAM,cAAC,IAAD,IACN8+B,YAAa,cAAC,IAAD,W,EAOvBD,qBAAuB,WACrB,MAMI,EAAK7qD,MALPuK,EADF,EACEA,QACA0M,EAFF,EAEEA,OACAszC,EAHF,EAGEA,aACArG,EAJF,EAIEA,qBACAE,EALF,EAKEA,0BAEEmG,EACFnG,EAA0B75C,IAE1BA,EAAQ0M,OAASA,EACjBitC,EAAqB,CACnB35C,QAASA,EACT66C,SAAQ,OAAEnuC,QAAF,IAAEA,OAAF,EAAEA,EAAQlV,GAClBuxB,UAAW,iB,EAKjBy3B,sBAAwB,WACtB,MAAgD,EAAK/qD,MAA7Cm+C,EAAR,EAAQA,mBAAoB1pB,EAA5B,EAA4BA,OAAQ9c,EAApC,EAAoCA,QACpC,OACE,cAAC,IAAD,CAAM7P,UAAW6P,EAAQymC,kBAAzB,SACGD,EAAmB1pB,M,4CAK1B,WACE,MAA6D/0B,KAAKM,MAA1DuK,EAAR,EAAQA,QAASoN,EAAjB,EAAiBA,QAASwwC,EAA1B,EAA0BA,+BACpB6C,EACJzgD,EAAQS,eAAiBm9C,EAC3B,OAAI59C,EAAQ+B,aAAaJ,OAAS,EAE9B,eAAC,IAAD,CAAMyM,WAAS,EAACE,WAAW,SAAS/Q,UAAW6P,EAAQogB,KAAvD,UACGizB,EACGtrD,KAAKirD,0BACLjrD,KAAKqrD,wBACT,cAAC,IAAD,CAAMnyC,MAAI,EAACoB,GAAI,EAAf,SACE,cAAC,IAAD,CAAYb,QAAM,EAACpR,MAAM,OAAOD,UAAW6P,EAAQ0/B,WAAnD,SACG9sC,EAAQ+B,iBAGb,cAAC,IAAD,CAAMsM,MAAI,EAACoB,GAAI,OAIZ,S,GArE6BE,IAAMC,eAyEjCC,uBAtFA,SAAC9Z,GAAD,MAAY,CACzBy3B,KAAM,CACJtU,UAAW,GACX3X,MAAO,QAETsyC,kBAAmB,CACjB/jC,YAAa/Z,EAAM4G,QAAQ,IAE7BmwC,WAAY,CACV98B,SAAU,WA6ECH,CAAmBswC,I,qJCpD5BO,E,4MACJC,qBAAuB,WACrB,MACE,EAAKlrD,MADC2X,EAAR,EAAQA,QAAS+pC,EAAjB,EAAiBA,wBAAyB4H,EAA1C,EAA0CA,eAAgB9D,EAA1D,EAA0DA,SAAUnsC,EAApE,EAAoEA,IAGpE,OACE,cAAC,IAAD,CACEtX,GAAG,qBACHjB,OAAM0kD,EACNA,SAAUA,EACV7tC,QAAS,CACPogB,KAAMpgB,EAAQwzC,QACd9mC,MAAO1M,EAAQyzC,cAEjB57B,aAAc,CACZC,SAAU,SACVC,WAAY,QAEd27B,gBAAiB,CACf57B,SAAU,MACVC,WAAY,SAEd47B,qBAAmB,EAhBrB,SAkBE,eAAC,IAAD,CAAM3yC,WAAS,EAAf,UACE,cAAC,IAAD,CACEC,MAAI,EACJ7Q,MAAM,SACND,UAAW6P,EAAQ4zC,uBACnBvxC,GAAI,GAJN,SAME,cAAC,IAAD,CAAY1S,QAAQ,SAApB,kCAEF,cAAC,IAAD,CAAMsR,MAAI,EAAC9Q,UAAW6P,EAAQ6zC,wBAAyBxxC,GAAI,GAA3D,SACE,cAAC,UAAD,CACEzP,QAAS++C,EACTjwC,IAAKA,EACLpC,OAAQyqC,EAAwBzqC,iB,4CAQ5C,WAEE,OAD2BvX,KAAKM,MAAxBspD,eACgB5pD,KAAKwrD,uBAAyB,S,GA/CvBhxC,IAAMC,eAmD1BC,uBAtFA,SAAC9Z,GAAD,MAAY,CACzBmrD,iBAAkB,CAChBnnC,UAAW,OACX/X,SAAU,UAEZqsC,QAAS,CACPnyC,gBAAiBnG,EAAMoG,QAAQkyC,QAC/B9sC,MAAO,QAET4/C,wBAAyB,CACvBzkD,QAAS,GAEXL,MAAO,CACLgJ,OAAQ,UACR,UAAW,CACTnJ,gBAAiBnG,EAAMoG,QAAQC,OAAOC,QAG1CukD,QAAS,CACP3mC,cAAe,QAEjB4mC,aAAc,CACZt/C,MAAO,IACPoY,UAAW,IACX3X,SAAU,SACVpF,WAAYwkD,YAAKrrD,EAAMoG,QAAQS,WAAWkd,MAAO,KAEnDknC,uBAAwB,CACtB/wC,WAAYla,EAAM4G,QAAQ,KAE5BskD,wBAAyB,CACvB5N,UAAU,GAAD,OAAKt9C,EAAM4G,QAAQ,IAAnB,oBAAmC5G,EAAMoG,QAAQkyC,aAuD/Cx+B,CAAmB6wC,I,2ICrE5BW,E,4MAEJp1C,MAAQ,CACNq1C,yBACE,EAAK7rD,MAAMu0B,kBAAkB1xB,MAAMuK,SAASlB,Q,EAGhD4/C,qBAAuB,WACrB,IAAQD,EAA6B,EAAKr1C,MAAlCq1C,yBACR,EAII,EAAK7rD,MAHP+sB,EADF,EACEA,qBACAwH,EAFF,EAEEA,kBACAw0B,EAHF,EAGEA,+BAEF,EAA0Cx0B,EAAkB1xB,MAApDkpD,EAAR,EAAQA,cAAeC,EAAvB,EAAuBA,eAEvB,QAAKjD,IAIDiD,EAAiBD,GAIdh/B,GAAwB8+B,I,EAGjCI,qBAAuB,WACrB,IAAQJ,EAA6B,EAAKr1C,MAAlCq1C,yBACR,EAA2D,EAAK7rD,MAAxDu0B,EAAR,EAAQA,kBAAmB4pB,EAA3B,EAA2BA,mBAAoBxmC,EAA/C,EAA+CA,QAEzCu0C,EAAiB,EAAKJ,uBACtBv9B,EAAe29B,EAAc,4JAEtBL,EAFsB,aAInC,OACE,mCACE,eAAC,IAAD,CACEhzC,WAAW,SACXF,WAAS,EACT7Q,UAAW6P,EAAQw0C,iBAHrB,UAKE,cAAC,IAAD,CAAMvzC,MAAI,EAACoB,GAAI,EAAf,SACGmkC,EAAmB5pB,EAAkBE,UAExC,cAAC,IAAD,CAAM7b,MAAI,EAACoB,GAAI,EAAf,SACE,cAAC,IAAD,CACEb,QAAM,EACN7R,QAAQ,SACRuB,UAAU,MACVf,UAAW6P,EAAQ0/B,WAJrB,SAMG9iB,EAAkBtd,OAAOjT,YAG9B,cAAC,IAAD,CAAM2U,WAAS,EAACC,MAAI,EAACE,QAAQ,WAAWkB,GAAI,EAA5C,SACE,cAAC,IAAD,CAAS3R,MAAOkmB,EAAhB,SACE,cAAC,IAAD,CACEzlB,KAAK,QACL6C,MAAM,UACN7D,UAAWokD,EAAiBv0C,EAAQy0C,YAAc,KAClDxpD,MAAK,UAAKipD,GAAL,OACHK,EAAiB,IAAM,gB,4CAUvC,WACE,IAAQL,EAA6BnsD,KAAK8W,MAAlCq1C,yBACR,OAAOtsD,SAASssD,GAA4B,EACxCnsD,KAAKusD,uBACL,S,GA7EkC/xC,IAAMC,eAiFjCC,uBAnGA,SAAC9Z,GAAD,MAAY,CACzB6rD,iBAAkB,CAChB1oC,UAAW,GACX5L,aAAcvX,EAAM4G,QAAQ,GAC5BmT,YAAa/Z,EAAM4G,QAAQ,IAE7BmwC,WAAY,CACV98B,SAAU,QAEZ6xC,YAAa,CACXzgD,MAAOrL,EAAMoG,QAAQ2lD,QAAQC,aAC7B7lD,gBACyB,SAAvBnG,EAAMoG,QAAQ0C,KACV9I,EAAMoG,QAAQ2lD,QAAQE,KACtBjsD,EAAMoG,QAAQ2lD,QAAQznC,UAqFjBxK,CAAmBwxC,I,0MCvF5BY,E,kDACJ,WAAYxsD,GAAQ,IAAD,8BACjB,cAAMA,IAwBRysD,wBAA0B,WACxB,MAAyD,EAAKzsD,MAAtD+jB,EAAR,EAAQA,cAAeoJ,EAAvB,EAAuBA,mBAAoBu2B,EAA3C,EAA2CA,UAC3C3/B,EAAc/kB,QAAQ,+BAAgC,CACpDmuB,mBAAoBA,EACpBu2B,UAAWA,IAEb,EAAKnsC,SAAS,CAAEiuC,SAAU,QA/BT,EAkCnBkH,uBAAyB,WACvB,MAA8C,EAAK1sD,MAA3C+jB,EAAR,EAAQA,cAAeoJ,EAAvB,EAAuBA,mBACvBpJ,EAAc/kB,QAAQ,8BAA+BmuB,GACrD,EAAK5V,SAAS,CAAEiuC,SAAU,QArCT,EAwCnBmH,wBAA0B,WACxB,IAAQh1C,EAAY,EAAK3X,MAAjB2X,QACR,OACE,cAAC,IAAD,CAAStP,MAAM,qBAAf,SACE,cAAC,IAAD,CACEP,UAAW6P,EAAQi1C,kBACnBxpD,QAAS,SAACX,GAAD,OACP,EAAK8U,SAAS,CACZiuC,SAAU/iD,EAAEsjD,iBAJlB,SAQE,cAAC,IAAD,SApDW,EA0DnB8G,mBAAqB,WACnB,IAAQl1C,EAAY,EAAK3X,MAAjB2X,QACA6tC,EAAa,EAAKhvC,MAAlBgvC,SACFsH,EAAyB,EAAKC,gBAAgB78C,QAAO,SAACgwC,GAC1D,OAAOA,EAAO7xB,WAEhB,OACE,cAAC,IAAD,CACEm3B,SAAUA,EACV1kD,KAAM4lC,QAAQ8e,GACd3kD,QAAS,kBAAM,EAAK0W,SAAS,CAAEiuC,SAAU,QAH3C,SAKGsH,EAAuBp+C,KAAI,SAACs+C,EAAgB72C,GAC3C,OACE,cAAC,IAAD,CAAsB/S,QAAS4pD,EAAe5pD,QAA9C,SACE,eAAC,IAAD,CAAMuV,WAAS,EAAf,UACE,cAAC,IAAD,CAAMC,MAAI,EAAC9Q,UAAW6P,EAAQs1C,aAA9B,SACGD,EAAehhC,OAElB,cAAC,IAAD,CAAMpT,MAAI,EAAV,SAAYo0C,EAAe/iC,WALhB9T,SArEvB,EAAKK,MAAQ,CACXgvC,SAAU,MAGZ,EAAKuH,gBAAkB,CACrB,CACE9iC,KAAM,uBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,QACNilB,SAAS,EACTjrB,QAAS,EAAKqpD,yBAEhB,CACExiC,KAAM,qBACN+B,KAAM,cAAC,IAAD,IACN5iB,KAAM,MACNilB,SAAS,EACTjrB,QAAS,EAAKspD,yBApBD,E,0CAsFnB,WAAU,IAAD,OACC/0C,EAAYjY,KAAKM,MAAjB2X,QACR,OACE,qCACE,cAAC,IAAD,CAAStP,MAAM,qBAAf,SACE,cAAC,IAAD,CACEP,UAAW6P,EAAQi1C,kBACnBxpD,QAAS,SAACX,GAAD,OACP,EAAK8U,SAAS,CACZiuC,SAAU/iD,EAAEsjD,iBAJlB,SAQE,cAAC,IAAD,QAGHrmD,KAAKmtD,4B,GAvG0B3yC,IAAMC,eA6G/BC,uBAtHA,SAAC9Z,GAAD,MAAY,CACzBssD,kBAAmB,CACjBnyC,SAAU,IAEZwyC,aAAc,CACZp1C,aAAcvX,EAAM4G,QAAQ,OAiHjBkT,CAAmBoyC,I,mNC1G5BU,E,kDAMJ,WAAYltD,GAAQ,IAAD,8BACjB,cAAMA,IANRwW,MAAQ,CACNgvC,cAAUtyC,EACVi6C,gBAAgB,GAGC,EAKnBC,oBAAsB,SAACt7B,EAAO3b,EAAO+pC,GAEtB,aADAA,EAAO92C,KAElB,EAAKmO,SAAS,CAAE41C,gBAAgB,IAEhC,EAAKntD,MAAMqZ,IAAIxa,eAAeG,QAAQkhD,EAAM,iBAAsBA,GAEpE,EAAK3oC,SAAS,CAAEiuC,cAAUtyC,KAZT,EAenBm6C,gBAAkB,WAEhB,OADwB,EAAKrtD,MAArBkxB,YACWhhB,QAAO,SAACqoB,GAAD,uBAAUA,EAAKlK,eAAf,aAjBT,EAoBnBi/B,qBAAuB,WACrB,IAAQH,EAAmB,EAAK32C,MAAxB22C,eACR,EAMI,EAAKntD,MALP2tB,EADF,EACEA,cACAV,EAFF,EAEEA,cACAoF,EAHF,EAGEA,oBACAf,EAJF,EAIEA,YACAuB,EALF,EAKEA,iBAEF,OAAIs6B,EACKI,uBACL,cAAC,UAAD,CACExsD,QAAS,CACPd,KACE,cAAC,UAAD,CACE0tB,cAAeA,EACfV,cAAeA,EACfoF,oBAAqBA,EACrBQ,iBAAkBA,EAClBvB,YAAaA,IAGjBnwB,WAAY,yBACZD,WAAY,KACZG,8BAA8B,GAEhCP,KAAMqsD,EACNtsD,QAAS,WACP,EAAK0W,SAAS,CACZ41C,gBAAgB,OAItBz9C,SAASgR,eAAe,sBAGnB,MAtDT,EAAKhS,IAAM1O,EAAM0O,IAFA,E,0CA4DnB,WAAU,IAAD,OACC82C,EAAa9lD,KAAK8W,MAAlBgvC,SACFgI,EAAe9tD,KAAK2tD,kBAC1B,OACE,qCACG3tD,KAAK4tD,uBACN,cAAC,IAAD,CAASjlD,MAAM,0CAAf,SACE,eAAC,IAAD,CACEolD,gBAAc,OACdrE,gBAAc,YACdn/B,KAAK,gBACLnhB,KAAK,QACL1F,QAAS,SAACX,GAAD,OACP,EAAK8U,SAAS,CACZiuC,SAAU/iD,EAAEsjD,iBAPlB,UAWE,cAAC,IAAD,CAAYz+C,QAAQ,SAApB,uDAGA,cAAC,IAAD,SAGJ,cAAC,IAAD,UACE,cAAC,IAAD,CACEvF,GAAG,YACHkB,WAAW,EACXuiD,SAAUA,EACVkI,mBAAoB,KACpBl+B,aAAc,CAAEC,SAAU,SAAUC,WAAY,SAChD27B,gBAAiB,CAAE57B,SAAU,MAAOC,WAAY,UAChD6O,aAAW,EACXz9B,KAAM4lC,QAAQ8e,GACd3kD,QAAS,kBACP,EAAK0W,SAAS,CACZiuC,cAAUtyC,KAXhB,SAeGs6C,EAAa9+C,KAAI,SAACwxC,EAAQ/pC,GAAT,aAChB,cAAC,IAAD,CAAqB9N,MAAK,UAAE63C,EAAO3xB,oBAAT,QAAyB,GAAnD,SACE,eAAC,IAAD,CACEnrB,QAAS,SAAC0uB,GAAD,OACP,EAAKs7B,oBAAoBt7B,EAAO3b,EAAO+pC,IAF3C,UAKGA,EAAOl0B,KACN,cAAC,IAAD,UAAek0B,EAAOl0B,OACpB,KACJ,cAAC,IAAD,CAAY1kB,QAAQ,SAAS6R,QAAM,EAAnC,SACG+mC,EAAOj2B,OAEV,cAAC,IAAD,CAAY3iB,QAAQ,UAAU6R,QAAM,EAApC,SACG+mC,EAAOj2B,WAbA9T,iB,GA3GF+D,IAAMC,eAoIjBC,uBAtIA,SAAC9Z,GAAD,MAAY,KAsIZ8Z,CAAmB8yC,I,2NC5H5BS,E,4MACJn3C,MAAQ,CACNo3C,wBAAyB,EAAK5tD,MAAMitB,cAAc/gB,OAAS,G,EAG7D2hD,yBAA2B,SAAC5jC,EAAMpnB,GAChC,IAAQ8qB,EAAkB,EAAK3tB,MAAvB2tB,cAER,EAAK3tB,MAAMqyB,oBAAX,2BAAoC1E,GAApC,kBAAoD1D,EAAOpnB,M,4CAG7D,WAAU,IAAD,OACP,EAA+DnD,KAAKM,MAA5D2X,EAAR,EAAQA,QAASgW,EAAjB,EAAiBA,cAAeV,EAAhC,EAAgCA,cAAeqE,EAA/C,EAA+CA,YAC/C,OACE,eAAC,IAAD,CAAM3Y,WAAS,EAACzR,QAAS,EAAG8b,UAAU,SAAtC,UACE,cAAC,IAAD,CAAMpK,MAAI,EAACoB,IAAE,EAAb,SACE,eAAC,IAAD,CAAanR,UAAU,WAAvB,UACE,cAAC,IAAD,CAAWA,UAAU,SAArB,8CACA,eAAC,IAAD,WACE,cAAC,IAAD,CAASR,MAAM,+LAAf,SACE,cAAC,IAAD,CACEzF,MAAM,8BACNo2C,QACE,cAAC,IAAD,CACED,QAASr5C,KAAK8W,MAAMo3C,wBACpB9qD,SAAU,SAACL,GAET,IAAMmrD,EAA0BnrD,EAAEM,OAAOg2C,QAGzC,EAAKxhC,SAAS,CACZq2C,6BAK8B,IAA5BA,GACF,EAAK5tD,MAAM6yB,iBAAiB,KAEhClnB,MAAM,gBAKbjM,KAAK8W,MAAMo3C,yBACV,cAAC,IAAD,CAAMj1C,WAAS,EAACzR,QAAS,EAAzB,SACE,cAAC,IAAD,CAAM0R,MAAI,EAACoB,IAAE,EAAb,SACE,cAAC,IAAD,CACEo9B,WAAS,EACT0W,QAAQ,0BACRC,UAAQ,EACRlrD,MAAOoqB,EACPnqB,SAAU,SAACgvB,GAAD,OACR,EAAK9xB,MAAM6yB,iBAAiBf,EAAM/uB,OAAOF,QAE3CsiB,MAAO,cAAC,IAAD,CAAOpjB,GAAG,yBACjBisD,YAAa,SAAC7V,GAAD,OACX,qBAAKrwC,UAAW6P,EAAQs2C,MAAxB,SACG9V,EAASzpC,KAAI,SAACwxC,GAAD,OACZ,cAAC,IAAD,CAEEt9C,MAAOs9C,EAAOl8C,QACd8D,UAAW6P,EAAQu2C,MAFdhO,EAAOn+C,UAbtB,SAqBGuvB,EAAYC,aAAa7iB,KAAI,SAACuI,GAAD,OAC5B,cAAC,IAAD,CAEEpU,MAAOoU,EAFT,SAKGA,EAAOjT,SAJHiT,EAAOlV,gBAY1B,cAAC,IAAD,UACE,cAAC,IAAD,CAASsG,MAAM,4IAAf,SACE,cAAC,IAAD,CACEzF,MAAM,gCACNo2C,QACE,cAAC,IAAD,CACED,QAASprB,EAAcjB,sBACvB5pB,SAAU,WACR,EAAK+qD,yBACH,yBACClgC,EAAcjB,wBAGnB/gB,MAAM,uBASpB,cAAC,IAAD,CAAMiN,MAAI,EAACoB,IAAE,EAAb,SACE,eAAC,IAAD,CAAanR,UAAU,WAAvB,UACE,cAAC,IAAD,CAAWA,UAAU,SAArB,oDAGA,eAAC,IAAD,WACE,cAAC,IAAD,CAASR,MAAM,qGAAf,SACE,cAAC,IAAD,CACEzF,MAAM,mBACNo2C,QACE,cAAC,IAAD,CACED,QAASprB,EAAchB,gBACvB7pB,SAAU,kBACR,EAAK+qD,yBACH,mBACClgC,EAAchB,kBAGnBhhB,MAAM,gBAKd,cAAC,IAAD,CAAStD,MAAM,mGAAf,SACE,cAAC,IAAD,CACEzF,MAAM,iBACNo2C,QACE,cAAC,IAAD,CACED,QAASprB,EAAcf,cACvB9pB,SAAU,kBACR,EAAK+qD,yBACH,iBACClgC,EAAcf,gBAGnBjhB,MAAM,gBAKd,cAAC,IAAD,CAAStD,MAAM,sIAAf,SACE,cAAC,IAAD,CACEzF,MAAM,6BACNo2C,QACE,cAAC,IAAD,CACED,QAASprB,EAAcd,UACvB/pB,SAAU,kBACR,EAAK+qD,yBACH,aACClgC,EAAcd,YAGnBlhB,MAAM,wBASpB,cAAC,IAAD,CAAMiN,MAAI,EAACoB,IAAE,EAAb,SACE,eAAC,IAAD,CAAanR,UAAU,WAAvB,UACE,cAAC,IAAD,CAAWA,UAAU,SAArB,6CACA,cAAC,IAAD,UACE,cAAC,IAAD,CAASR,MAAM,oPAAf,SACE,cAAC,IAAD,CACEzF,MAAM,sDACNo2C,QACE,cAAC,IAAD,CACED,QAA+C,WAAtCprB,EAAcb,oBACvBhqB,SAAU,kBACR,EAAK+qD,yBACH,sBACsC,eAAtClgC,EAAcb,oBACV,SACA,eAGRnhB,MAAM,uBASpB,cAAC,IAAD,CAAMiN,MAAI,EAACoB,IAAE,EAAb,SACE,eAAC,IAAD,CAAanR,UAAU,WAAvB,UACE,cAAC,IAAD,CAAWA,UAAU,SAArB,iCACA,cAAC,IAAD,UACE,cAAC,IAAD,CAASR,MAAM,uFAAf,SACE,cAAC,IAAD,CACEzF,MAAM,4BACNo2C,QACE,cAAC,IAAD,CACED,QAASprB,EAAc7gB,uBACvBhK,SAAU,kBACR,EAAK+qD,yBACH,0BACClgC,EAAc7gB,yBAGnBnB,MAAM,8B,GAhNCuO,IAAMC,eA6NpBC,uBAvOA,SAAC9Z,GAAD,MAAY,CACzB2tD,MAAO,CACLvrC,QAAS,OACT2+B,SAAU,QAEZ6M,KAAM,CACJlrD,OAAQ,MAiOGoX,CAAmBuzC,I,iMCkLnB7+B,UA3Zb,WAAYnwB,GAAW,IAAD,gCAWtBwvD,gBAAiB,EAXK,KAetBC,iBAAmB,GAfG,KAiBtB97B,oBAAsB,SAACvxB,GACrB,EAAKstD,aAAe,IAAI9kD,UAAalE,oBAAU,EAAKtE,QAASA,IAG7D,EAAKutD,aAAavkC,SAAS,EAAKskC,aAAa3hD,8BArBzB,KAwBtB6hD,qBAAuB,WAAO,IAAD,IAI3B,MAAO,CAAE7kD,YAHQ,UAAG,EAAK3I,QAAQytD,uBAAhB,QAAmC,qBAGjBhlD,UAFpB,UAAG,EAAKzI,QAAQ0tD,qBAAhB,QAAiC,2BA1B5B,KA+BtBC,mBAAqB,WACnB,OAAO,IAAI3oB,IAAa,CAAE8I,OAAO,KAhCb,KAmCtB8f,kBAAoB,SAAC13C,EAAQrP,GAC3B,OAAO,IAAIq+B,IAAY,CACrBhvB,OAAQA,EACRrP,MAAOA,KAtCW,KA0CtBgnD,iBAAmB,WACjB,OAAO,EAAKlgD,IACTsB,YACAC,WACAC,QAAO,SAAC/C,GACP,OACGA,aAAiBgD,KAAahD,aAAiBiD,WAC3B8C,IAArB/F,EAAM2D,YAEN3D,EAAMgpC,cACNhpC,EAAMiC,YAAYgC,YAAlB,QACAjE,EAAMG,gBAAgB2c,MACtBlC,yBAAe5a,EAAMG,gBAAgB2c,SAGxCvb,KAAI,SAACvB,GAAD,OAAWA,EAAMiC,YAAYgC,YAAlB,UACfY,KAAK,KACLX,MAAM,MA3DW,KA8DtBkkB,uBAAyB,WACvB,IAAMtI,EAAgB,EAAKlsB,QAAQ2wB,QAC7Bm9B,EAAgB,EAAKD,mBAI3B,OAH4B3hC,EAAc/c,QAAO,SAAC4V,GAChD,OAAO+oC,EAAcn1C,MAAK,SAACo1C,GAAD,OAAUA,IAAShpC,EAAE/jB,UAlE7B,KAuEtBgtD,cAAgB,WAAO,IAAD,EACpB,EAAKC,aAAe,EAAKN,qBACzB,EAAKJ,aAAe,EAAKK,kBACvB,EAAKK,aACL,YAAKjuD,QAAQkuD,+BAAb,SACI,EAAKZ,aAAa3hD,4BAClB,MAIN,EAAK4hD,aAAa97B,IAAI,OAAQ,qBAC9B,EAAK87B,aAAa97B,IAAI,OAAQ,uBAC9B,EAAK08B,WAAa,EAAKR,qBACvB,EAAKS,UAAY,EAAKR,kBACpB,EAAKO,WACL,EAAKE,gBAEP,EAAKD,UAAU38B,IAAI,OAAQ,oBAC3B,EAAK9jB,IAAI21B,SAAS,EAAK8qB,WACvB,EAAKzgD,IAAI21B,SAAS,EAAKiqB,eA1FH,KA6FtBh/B,kBAAoB,WAElB,EAAKvL,cAAc/C,UAAU,eAAgB,EAAKquC,UAClD,EAAKtrC,cAAc/C,UAAU,qBAAsB,EAAKsuC,gBACxD,EAAKvrC,cAAc/C,UACjB,gCACA,EAAKuuC,2BAEP,EAAKxrC,cAAc/C,UAAU,uBAAwB,EAAKwuC,kBAC1D,EAAKzrC,cAAc/C,UACjB,gDACA,EAAKyuC,2CAEP,EAAK1rC,cAAc/C,UACjB,sCACA,EAAK0uC,iCAEP,EAAK3rC,cAAc/C,UACjB,0BACA,EAAK2uC,qBAEP,EAAK5rC,cAAc/C,UAAU,oBAAqB,EAAK4uC,eAEvD,EAAKv2C,IAAIxa,eAAemiB,UACtB,iCACA,SAACjgB,GACsB,WAAjBA,EAAQqI,KACV,EAAKymD,wBACqB,WAAjB9uD,EAAQqI,KACjB,EAAK0mD,6BAEL,EAAKC,YAAW,EAAMhvD,EAAQqI,MAOhCsG,SAASijB,cAAcC,WAnIP,KAwItB88B,gCAAkC,SAAC3X,GACjC,IAAQ3qC,EAAyB2qC,EAAzB3qC,SAAUk2C,EAAevL,EAAfuL,WAClB,EAAK0L,aAAagB,gBAAe,SAACzlD,IACa,IAAzC+4C,EAAWt+B,QAAQza,EAAQuE,UAC7B,EAAKkgD,aAAaiB,cAAc1lD,MAGpC6C,EAASvH,SAAQ,SAAC0E,GACX,EAAKykD,aAAakB,eAAe3lD,EAAQuE,UAC5C,EAAKkgD,aAAa5oB,WAAW77B,MAGjC,EAAKilD,iBAAiB,EAAKpB,kBAC3B,EAAKkB,eAAe,EAAKlB,mBArJL,KAwJtB+B,qBAAuB,WACrB,IAAMC,EAAgB,EAAKpB,aAAaxoB,aACmB,IAAvD4pB,EAAc1hD,IAAIhE,OAAOC,UAAU6J,UAAS,IAC9C,EAAK67C,eAAeD,IA3JF,KA+JtBC,eAAiB,SAACztB,GAChB,EAAKl0B,IAAIoB,UAAUyP,IAAIqjB,EAAQ,CAC7B95B,KAAM,EAAK4F,IAAI6b,UACftjB,QAAS,CAAC,GAAI,GAAI,GAAI,IACtB+7B,QAAS,KAnKS,KAuKtBusB,0BAA4B,SAACniD,GAC3B,EAAK4hD,aAAa7oB,QAClB,EAAK6oB,aAAava,YAAYrnC,GAE1B,EAAKrM,QAAQkuD,yBACf,EAAKkB,wBA5Ka,KAgLtBG,oCAAsC,WACpC,EAAKtB,aAAauB,cAAc7hD,KAAI,SAACY,GAAD,OAAOA,EAAEya,SAAS,UAjLlC,KAoLtBymC,sBAAwB,WACtB,OAAO,EAAKtB,WAAWqB,cAAcrkD,OAAS,GArL1B,KAwLtBkjD,aAAe,WACb,OAAO,IAAI5jD,IAAM,CACfI,OAAQ,IAAIC,IAAO,CACjBF,MAAO,EAAK8kD,kBAAkB/mD,YAC9BoC,MAAO,IAETL,KAAM,IAAIC,IAAK,CACbC,MAAO,EAAK8kD,kBAAkBjnD,YAEhCuC,MAAO,IAAIY,IAAO,CAChBC,OAAQ,EACRhB,OAAQ,IAAIC,IAAO,CACjBF,MAAO,EAAK8kD,kBAAkB/mD,YAC9BoC,MAAO,SArMO,KA2MtB6jD,oBAAsB,SAACplD,GACrB,GAAKA,EAAL,CAGA,IAAMmmD,EAAa,EAAKC,+BAA+BpmD,EAAQuE,SAC/D,cAAO4hD,QAAP,IAAOA,OAAP,EAAOA,EAAY3mC,SACjB,EAAKskC,aAAa/jD,gBAAgBomD,EAAY,gBAjN5B,KAqNtBd,cAAgB,SAACrlD,GACf,GAAKA,EAAL,CAGA,IAAMq4B,EAASguB,wBACTF,EAAa,EAAKC,+BAA+BpmD,EAAQuE,SAC/D+hD,iBAAOjuB,EAAD,OAAS8tB,QAAT,IAASA,OAAT,EAASA,EAAY1lD,cAAcw7B,aACzC,IAAMsqB,EAAiBC,kBAAQnuB,GAC3B,EAAKosB,aAAaxoB,YAClB5D,EACJ,EAAKytB,eAAeS,KA/NA,KAkOtBtB,iBAAmB,SAACwB,GAClB,EAAK5C,iBAAmB4C,EACxB,EAAKV,sCACLU,EAAatiD,KAAI,SAACqpC,GAChB,IAAMxtC,EAAU,EAAKomD,+BACnB5Y,EAAYxtC,QAAQuE,SAEtB,cAAOvE,QAAP,IAAOA,OAAP,EAAOA,EAASwf,SACd,EAAKskC,aAAa/jD,gBAAgBC,EAAS,kBA1O3B,KA+OtBklD,0CAA4C,SAAC1X,GAC3C,IAAMxtC,EAAUwtC,EAAYxtC,QAC5BA,EAAQwf,SAAS,EAAKskC,aAAa/jD,gBAAgBC,EAAS,cAC5D,EAAKykD,aAAa5oB,WAAW77B,GAC7B,EAAK4lD,wBAnPe,KAsPtBQ,+BAAiC,SAACM,GAChC,OAAO,EAAKjC,aAAakB,eAAee,IAvPpB,KA0PtB3B,eAAiB,SAAC0B,GAChB,IAAIpuB,EAASguB,wBAGbI,EAAanrD,SAAQ,SAACkyC,GACJ,EAAK4Y,+BACnB5Y,EAAYxtC,QAAQuE,UAGpB+hD,iBACEjuB,EACA,EAAK+tB,+BAA+B5Y,EAAYxtC,QAAQuE,SACrD9D,cACAw7B,gBAIT,IAAMsqB,EAAiBC,kBAAQnuB,GAC3B,EAAKosB,aAAaxoB,YAClB5D,EAEJ,EAAKytB,eAAeS,IA/QA,KAkRtBzB,SAAW,WACL,EAAKH,YACP,EAAKA,WAAW/oB,QAEd,EAAK6oB,cACP,EAAKA,aAAa7oB,QAEpB,EAAK+qB,wBACL,EAAKC,wBACL,EAAK/C,iBAAmB,IA3RJ,KA8RtB8C,sBAAwB,WAClB,EAAKE,MACP,EAAK1iD,IAAI8nC,kBAAkB,EAAK4a,OAhSd,KAoStBrB,WAAa,SAAC10C,EAAQjS,GAA4B,IAAtBioD,EAAqB,wDAC/C,EAAKttC,cAAc/kB,QAAQ,gBAAiBoK,GACxCiS,GACF,EAAK+1C,KAAO,IAAIE,IAAK,CACnBr6C,OAAQ,EAAKi4C,WACb9lD,KAAMA,EACNioD,SAAmB,WAATjoD,GAA2BioD,EACrCE,WAAW,EACX3pD,MAAO,EAAKwnD,iBAGd,EAAK1gD,IAAIoF,UAAUkS,IAAI,UACvB,EAAKtX,IAAI4nC,eAAe,EAAK8a,MAC7B,EAAKlC,WAAW/oB,QAChB,EAAK+oB,WAAWr7C,GAAG,aAAc,EAAK29C,0BAEtC,EAAK9iD,IAAI8nC,kBAAkB,EAAK4a,MAChC,EAAK1iD,IAAIoF,UAAU2iC,OAAO,UAE1B,EAAKyY,WAAW/oB,UAvTE,KA2TtBqrB,uBAAyB,SAAC/uD,GAOxBqc,YAAW,WACT,EAAKpQ,IAAI8nC,kBAAkB,EAAK4a,MAChC,EAAK1iD,IAAIoF,UAAU2iC,OAAO,YACzB,GACH,EAAK1yB,cAAc/kB,QAAQ,cAAeyD,EAAE8H,UAtUxB,KAyUtBslD,sBAAwB,WACtB,IACE,IAAMO,EAAgB,EAAK1hD,IACxBoB,UACA2hD,gBAAgB,EAAK/iD,IAAI6b,WAE5B,IAAK,EAAKmnC,eAAetB,GACvB,MAAM,IAAIjqC,MAAM,qDAElB,IAAM5b,EAAU,IAAIonD,IAAQC,YAAWxB,IACvC,EAAKlB,WAAW9oB,WAAW77B,GAC3B,EAAKwZ,cAAc/kB,QAAQ,uBAAwB,CAACuL,IACpD,MAAO5G,GACP,EAAKkuD,iCAAiCluD,KAtVpB,KA0VtB+tD,eAAiB,SAAC9uB,GAChB,OAAuD,IAAhDA,EAAOl0B,IAAIhE,OAAOC,UAAU6J,UAAS,IA3VxB,KA8VtBq9C,iCAAmC,SAACluD,GAClC,EAAKogB,cAAc/kB,QAAQ,wBAC3BqU,QAAQwS,KAAK,yBAA0BliB,IAhWnB,KAmWtBmsD,2BAA6B,WAC3B,EAAKZ,WAAW4C,GAAG,aAAc,EAAKN,wBACtC,EAAKrD,gBAAiB,EACtB,EAAKpqC,cAAc/kB,QAAQ,0BAC3B,EAAK+yD,sBAvWe,KA0WtBA,mBAAqB,WACnB,EAAKrjD,IAAIoF,UAAUkS,IAAI,UACvB,EAAKtX,IAAImF,GAAG,cAAe,EAAKm+C,0BAChCtiD,SAASqR,iBAAiB,UAAW,EAAKkxC,eAC1CviD,SAASqR,iBAAiB,QAAS,EAAKmxC,cA9WpB,KAiXtBf,sBAAwB,WACtB,EAAKziD,IAAIoF,UAAU2iC,OAAO,UAC1B,EAAK/nC,IAAIojD,GAAG,cAAe,EAAKE,0BAChCtiD,SAASyiD,oBAAoB,UAAW,EAAKF,eAC7CviD,SAASyiD,oBAAoB,QAAS,EAAKD,cArXvB,KAwXtBF,yBAA2B,SAAClgC,GAC1BviB,sBAAYuiB,EAAOA,EAAMpjB,KAAK,SAACX,GAE7B,GAAwB,IADPA,EAASX,SACblB,SAGb,EAAKgjD,WAAWza,YAAY1mC,EAASX,WAChC,EAAK+gD,gBAAgB,CACxB,IAAM9a,EAAc,EAAK6b,WAAWqB,cACpC,EAAKxsC,cAAc/kB,QAAQ,2BAA4Bq0C,GACvD,EAAK8d,6BAlYW,KAuYtBc,cAAgB,SAACngC,GAEC,KADIA,EAAZkB,SACe,EAAKm7B,iBAC1B,EAAKA,gBAAiB,IA1YJ,KA8YtB+D,YAAc,SAACpgC,GAEb,GAAgB,KADIA,EAAZkB,UAEN,EAAKm7B,gBAAiB,EAClB,EAAKqC,yBAAyB,CAChC,IAAMpjD,EAAW,EAAK8hD,WAAWqB,cACjC,EAAKxsC,cAAc/kB,QAAQ,2BAA4BoO,GACvD,EAAK+jD,0BApZTzxD,KAAKgP,IAAM/P,EAAS+P,IACpBhP,KAAK2Z,IAAM1a,EAAS0a,IACpB3Z,KAAKqB,QAAUpC,EAASoC,QACxBrB,KAAK+wD,kBAAoB/wD,KAAK6uD,uBAC9B7uD,KAAK2uD,aAAe,IAAI9kD,UAAa5K,EAASoC,SAC9CrB,KAAKqkB,cAAgBplB,EAASolB,cAC9BrkB,KAAKqvD,gBACLrvD,KAAK4vB,sB,2UCfYL,EAGnB,WAAYtwB,GAAW,IAAD,yFAOtB2wB,kBAAoB,WAClB,EAAKvL,cAAc/C,UAAU,8BAA+B,EAAKoxC,SAR7C,KAiBtBA,OAAS,SAACjlC,GACR,IAAMklC,EAAc,YAAG,EAAH,MAA2BllC,GAC/C,cAAI,GAAJ,GAAqBklC,IAnBD,gDAsBD,SAACllC,GACpB,OAAOA,EACJze,KAAI,SAAC6lB,GACJ,OAAOA,EAAkB1xB,MAAMuK,SAASsB,KAAI,SAACnE,GAI3C,OAAO,cAAP,MAA8BA,SAGjCuqB,UAhCiB,gDAmCF,SAACvqB,GAEnB,IAAM+nD,EAAY/nD,EAAQsf,QAY1B,OARAyoC,EAAUhmD,aAAe/B,EAAQ+B,aACjCgmD,EAAUzlD,kBAAoBtC,EAAQsC,kBAGtCylD,EAAUvoC,WACVuoC,EAAUvoC,SACR,cAAI,GAAJ,GAAmBzf,gBAAgBgoD,EAAW,cAEzCA,KAjDa,gDAoDJ,SAACllD,GACjB,IACE,IAAImlD,KACJ,SAEA,YADAl/C,QAAQm/C,KAAK,iDAIf,IAAMC,EAAc,GA+BpB,GA7BArlD,EAASvH,SAAQ,SAAC0E,GAChB,IAAImoD,GAAe,EACnB,GAAInoD,EAAQS,wBAAyB2B,IAAQ,CAC3C,IAAM05B,EAAOqF,YAAWnhC,EAAQS,cAAe,IAC/CT,EAAQooD,YAAYtsB,GACpBqsB,EAAenoD,EAAQS,cAAc4nD,YAEvCroD,EACGS,cACA0e,UAAU,EAAKhb,IAAIoB,UAAUT,gBAAiB,aAE7C9E,EAAQuf,WAAW,IACrBvf,EAAQ4M,cAAc,CACpBvP,MAAOnE,KAAKG,UAAL,YACL,EADK,MAEH2G,EAAQuf,WAAW,IAAMvf,EAAQuf,WAAW,GAC5C4oC,IAGJ/mC,aACgC,aAA9BphB,EAAQsoD,kBACJtoD,EAAQ+C,gBAAgBqe,aACxBphB,EAAQsoD,oBAIlBJ,EAAYvjD,KAAK3E,MAGf6C,EAASlB,OAAS,EAAG,CACvB,IAAM4mD,EAAW9oC,oBAAUyoC,EAAa,gBACxCM,iBACE,IAAIR,KAAK,CAACO,GAAW,CACnB1pD,KAAM,uDAFJ,0BAIW,IAAI0d,MAAOT,iBAJtB,aA7FY,gDAsGN,SAACze,EAAO8qD,GAAkB,IAAD,IACjCM,EAAW,GAoBjB,OAlBAA,EAAS/yD,KAAT,iBAAgB2H,QAAhB,IAAgBA,GAAhB,UAAgBA,EAAOijB,iBAAvB,aAAgB,EAAkBA,iBAAlC,QAA+C,GAC/CmoC,EAASjnD,MACPinD,EAAS3oC,qBAAsBre,IAAOpE,EAAMyiB,WAAWG,SAAW,GACpEwoC,EAASC,YACPrrD,EAAMyiB,qBAAsB6oC,IACxBtrD,EAAMyiB,WAAWuoC,YACjB,GACFF,IACFM,EAASpmD,OAAS8lD,GAEpBM,EAASG,WACPvrD,EAAMyiB,qBAAsB6oC,IACxBtrD,EAAMyiB,WAAWO,UAAUF,WAC3B,GACNsoC,EAASxpD,UAAY5B,EAAMgjB,UAAUF,WACrCsoC,EAAStpD,YAAc9B,EAAM6iB,YAAYC,WACzCsoC,EAASrtB,YAAc/9B,EAAM6iB,YAAYE,WACzCqoC,EAASI,WAAaxrD,EAAM6iB,YAAYirB,cACjCsd,KA1HP,YAAAtzD,KAAA,MAAqB,IAAI6J,UAAa5K,EAASoC,SAC/CrB,KAAKqkB,cAAgBplB,EAASolB,cAC9BrkB,KAAKgP,IAAM/P,EAAS+P,IACpBhP,KAAK4vB,sB,qWCbYJ,EACnB,WAAYvwB,GAAW,IAAD,gCAKtB2wB,kBAAoB,WAClB,EAAKvL,cAAc/C,UAAU,+BAAgC,EAAKoxC,SAN9C,KAStBA,OAAS,SAACiB,GACR,IACE,IAAQlmC,EAAuBkmC,EAAvBlmC,mBACFmmC,EAAWC,IAAKC,MAAMC,WACtBC,EAAQ,YAAG,EAAH,MAAqBvmC,GAEnC,OACiC,KAAb,OAAlBA,QAAkB,IAAlBA,OAAA,EAAAA,EAAoBjhB,SACa,eAAjCihB,EAAmB,GAAGsH,OAEf,cAAP,MAAsCtH,EAAmB,GAAIumC,IAG/DvmC,EAAmBtnB,SAAQ,SAAC+vB,GAC1B,IAAM+9B,EAAK,YAAG,EAAH,MAAyB/9B,GACpC,GAAI+9B,EAAO,CACT,IAAMC,EAAS,YAAG,EAAH,MAAsBh+B,GACrC29B,IAAKC,MAAMK,kBAAkBP,EAAUK,EAAOC,OAI3CL,IAAKO,UAAUR,EAAUI,IAChC,MAAO/vD,GACP0P,QAAQwS,KAAK,2BAA4BliB,KAhCvB,gDAoCP,SAACwpB,GACd,OAAsC,KAAb,OAAlBA,QAAkB,IAAlBA,OAAA,EAAAA,EAAoBjhB,QAApB,sBACA,EADA,MAEDihB,EAAmB,IAFlB,aAGE,IAAIrG,MAAOT,iBAHb,iCAIU,IAAIS,MAAOT,iBAJrB,YArCa,gDA4CM,SAACkO,EAAmBm/B,GAC9C,IACE,IAAMJ,EAAWC,IAAKC,MAAMC,WACtBM,EAAe,YAAG,EAAH,MAA4Bx/B,GAWjD,OATA5uB,OAAOC,KAAKmuD,GAAiBluD,SAAQ,SAACtC,GACpC,IAAMqwD,EAAYrwD,EAAIokB,MAAM,EAAG,IACzBqsC,EAAW,YAAG,EAAH,MACfD,EAAgBxwD,IAEZowD,EAAQJ,IAAKC,MAAMS,aAAaD,GACtCT,IAAKC,MAAMK,kBAAkBP,EAAUK,EAAOC,MAGzCL,IAAKO,UAAUR,EAAUI,GAChC,MAAO/vD,GACP0P,QAAQwS,KAAK,yCAA0CliB,OA5DrC,gDAgEA,SAAC4wB,GACrB,OAAOA,EAAkB1xB,MAAMuK,SAAS3H,QAAO,SAAC0O,EAAQ7E,GAAO,IAAD,EAE5D,OADA,UAAC6E,EAAO7E,EAAE2H,OAAOjT,gBAAjB,QAA8BmQ,EAAO7E,EAAE2H,OAAOjT,SAAW,IAAKkL,KAAKI,GAC5D6E,IACN,OApEiB,gDAuEQ,SAAC/G,GAC7B,IAAM4mD,EAAc,GAEdpuD,EAAOD,OAAOC,KAAKwH,EAAS,GAAGE,iBAKrC,OAJA0mD,EAAY9kD,KAAKtJ,GACjBwH,EAASvH,SAAQ,SAAC0E,GAChBypD,EAAY9kD,KAAKvJ,OAAOuL,OAAO3G,EAAQ+C,qBAElC0mD,KA/Ea,gDAkFH,SAACz/B,GAAuB,IAAD,IACxC,IAAqB,OAAjBA,QAAiB,IAAjBA,GAAA,UAAAA,EAAmB1xB,aAAnB,mBAA0BuK,gBAA1B,eAAoClB,QAAS,EAAG,CAElD,IAAQkB,EAAamnB,EAAkB1xB,MAA/BuK,SAGFxH,EAAO,IAAI2L,IAIXyiD,EAAc,GA2CpB,OAvCA5mD,EAASvH,SAAQ,SAAC0E,GAGhB,IAAMugC,EAAevgC,EAAQsoD,kBAEJtoD,EACtB2pD,UACAhkD,QAAO,SAAC3M,GAAD,OAASA,IAAQunC,KAEVjlC,SAAQ,SAACtC,GACxBqC,EAAKogB,IAAIziB,SAMbywD,EAAY9kD,KAAZ,YAAqBtJ,IAIrBwH,EAASvH,SAAQ,SAAC0E,GAEhB,IAF4B,EAEtB4pD,EAAoB5pD,EAAQ+C,gBAE5B4D,EAAS,GAJa,cASVtL,GATU,IAS5B,2BAAwB,CAAC,IAAD,EAEhB/C,EAAK,UAAGsxD,EAFQ,gBAEX,QAA6B,GAExCjjD,EAAOhC,KAAKrM,IAbc,8BAgB5BmxD,EAAY9kD,KAAKgC,MAGZqiD,IAAKC,MAAMS,aAAaD,GAE/B,OAAO,QAzIW,gDA6IN,SAACz/B,GAAuB,IAAD,IAGrC,OAFe,iBAAGA,QAAH,IAAGA,GAAH,UAAGA,EAAmBtd,cAAtB,aAAG,EAA2BjT,eAA9B,QAAyC,eAEvC2jB,MAAM,EAAG,OA/I1BjoB,KAAKqkB,cAAgBplB,EAASolB,cAC9BrkB,KAAK4vB,sB,iCCLT,uGAOM2pB,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvC+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,GAC5Bwb,QAAS,OACT+B,cAAe,UAEjBoX,OAAQ,CACNphB,SAAU,aAIR25C,EAAcl6C,IAAM6iC,MAAK,SAAC/8C,GAC9B,IAAM2X,EAAUshC,IAEhB,SAASob,EAAYpxC,GACnB,GAAKjjB,EAAM0O,IAAX,CACA,IAAM+zB,EAAOziC,EAAM0O,IAAIoB,UAEvB,GAAK2yB,EAAL,CACA,IAAM/xB,EAAc+xB,EAAK9xB,UAEzB,QAAoBuC,IAAhBxC,EAA2B,CAC7B,IAAM2yB,EAAU3yB,EAAcuS,EAKxBwf,EAAK6xB,gBACP7xB,EAAK8xB,mBAEP9xB,EAAK+xB,QAAQ,CACXpxB,KAAMC,EACNoxB,SAPa,IAQbC,OAAQC,SAQhB,YACgBzhD,IAAdlT,EAAM0O,KACJ,eAAC,IAAD,CAAO5G,UAAW6P,EAAQ0M,MAA1B,UACE,cAAC,IAAD,CACEpL,aAAW,WACXnR,UAAW6P,EAAQkkB,OACnBz4B,QAAS,WACPixD,EAAY,IAJhB,SAOE,cAAC,IAAD,MAEF,cAAC,IAAD,CACEp7C,aAAW,WACXnR,UAAW6P,EAAQkkB,OACnBz4B,QAAS,WACPixD,GAAa,IAJjB,SAOE,cAAC,IAAD,YAOKD,a,iCC1Ef,6EAKMnb,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvC+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,SAEZm6C,OAAQ,CACN9oD,MAAO,GACPoS,OAAQ,GACR3W,SAAU,SACVd,gBAAiBnG,EAAMoG,QAAQzG,KAAKwb,aAwBlCo5C,EAAmB,SAACj3B,GAKxB,MAH0B,CAACA,EAAY+Q,YAAa/Q,EAAY9S,aAGvC5a,QAAO,SAACuF,GAAD,YAAavC,IAANuC,KAAiBzD,KAAK,OASzD8iD,EAAO56C,IAAM6iC,MAAK,YAAsB,IA5BVpO,EA4BT/Q,EAAkB,EAAlBA,YACnBjmB,EAAUshC,IAEhB,OACGrb,GACC,cAAC,IAAD,CAASv1B,MAAOwsD,EAAiBj3B,GAAjC,SACE,cAAC,IAAD,CAAO91B,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAY2kB,EAAY+Q,YACxB7mC,UAAW6P,EAAQkkB,OAFrB,SAIE,cAAC,IAAD,CAAQhC,IAAK+D,EAAY+Q,YAAa7mC,UAAW6P,EAAQi9C,OAAzD,UAvCwBjmB,EAwCM/Q,EAAY+Q,YAvC7CA,EACJt9B,MAAM,KACN3C,KAAI,SAACub,GAAD,OAAUA,EAAK,MACnBjY,KAAK,IACLwV,wBAyCD,QAIWstC,a,sICtET7b,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvC+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,aAIRs6C,EAAgB76C,IAAM6iC,MAAK,SAAC/8C,GAAW,IAAD,EACpC2X,EAAUshC,IACVxW,EAAOuyB,mBACb,EAAgC1zD,oBAAS,UAAAmhC,EAAKzjB,eAAL,eAAci2C,gBAAiB,GAAxE,mBAAOxoD,EAAP,KAAiByoD,EAAjB,KAsBA,SAASC,IACPD,EAAYzyB,EAAKzjB,QAAQi2C,eAwB3B,OA7CAv1B,qBAAU,WAER,GAAK1/B,EAAM0O,IAQX,OALA+zB,EAAKzjB,QAAUhf,EAAM0O,IAAIoB,UAIzB2yB,EAAKzjB,QAAQnL,GAAG,kBAAmBshD,GAC5B,WAKL1yB,EAAKzjB,QAAQ8yC,GAAG,kBAAmBqD,MAEpC,CAACn1D,IA6BDA,EAAM0O,KAAoB,IAAbjC,GACZ,cAAC,IAAD,CAASpE,MAAM,2BAAf,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAW,2BACXnR,UAAW6P,EAAQkkB,OACnBz4B,QA3BV,WAIOq/B,EAAKzjB,cAEO9L,IAAbzG,GAGAg2B,EAAKzjB,QAAQw1C,QAAQ,CACnB/nD,SAAU,EACVgoD,SATW,IAUXC,OAAQC,OAYR,SAKE,cAAC,IAAD,CAAgB/sD,MAAO,CAAE8hB,UAAU,UAAD,OAAYjd,EAAZ,kBAK1C,QAIWsoD,a,mIC/CTK,E,kDAKJ,WAAYp1D,GAAQ,IAAD,8BACjB,cAAMA,IALRwW,MAAQ,CACN5L,MAAO,GAKP,EAAK6X,IAAMvI,IAAM4G,YAFA,E,sDAKnB,WAAsB,IAAD,OAEnB,GAAIphB,KAAKM,MAAM0O,KAA4C,IAArChP,KAAK+iB,IAAIzD,QAAQ3c,SAAS6J,OAAc,CAE5DxM,KAAK6X,SAAS,CACZ3M,MAAOlL,KAAK21D,YAAY31D,KAAK4qB,cAI/B,IAAMgrC,EAAmB,IAAIC,IAAU,CACrCxyD,OAAQrD,KAAK+iB,IAAIzD,UAEnBtf,KAAKM,MAAM0O,IAAI8mD,WAAWF,GAI1B51D,KAAKM,MAAM0O,IAAIoB,UAAU+D,GAAG,qBAAqB,WAC/C,EAAK0D,SAAS,CACZ3M,MAAO,EAAKyqD,YAAY,EAAK/qC,oB,sBAWrC,WACE,IACEmrC,EAAM/1D,KAAKM,MAAM0O,IAAIoB,UAAUT,gBAAgBqmD,mBAIjD,OAFQh2D,KAAKM,MAAM0O,IAAIoB,UAAUW,gBAEpBglD,EAHM,OAFP,KAAO,O,yBAcrB,SAAY7qD,GACV,OAAOqR,KAAKyD,MAAM9U,GACf6d,WACA5oB,QAAQ,wBAAyB,O,8BAGtC,WACE,IAAQ8X,EAAYjY,KAAKM,MAAjB2X,QACR,OACE,cAAC,IAAD,CAAStP,MAAM,kBAAf,SACE,eAAC,IAAD,CAAO+4C,UAAW,EAAGt5C,UAAW6P,EAAQg+C,WAAxC,eACKj2D,KAAK8W,MAAM5L,a,oBAMtB,WACE,IAAQ+M,EAAYjY,KAAKM,MAAjB2X,QACR,OACE,qCACE,qBAAK8K,IAAK/iB,KAAK+iB,IAAK3a,UAAW6P,EAAQi+C,YACtCl2D,KAAKm2D,0B,GA5EiB37C,IAAMC,eAkFtBC,uBAjHA,SAAC9Z,GACd,MAAO,CACLs1D,UAAW,CACT,mBAAoB,CAClBl+C,SAAU,SACVmG,MAAO,UACPG,OAAQ,UACR/W,QAAS,MACTE,WAAY7G,EAAMoG,QAAQS,WAAWkd,MACrCC,UAAWhkB,EAAMikB,QAAQ,GACzBhJ,aAAcjb,EAAMgb,MAAMC,cAE5B,yBAA0B,CACxB3L,OAAQ,UACRuc,YAAa7rB,EAAMoG,QAAQzG,KAAKwb,QAChC9P,MAAOrL,EAAMoG,QAAQzG,KAAKwb,QAC1BlU,SAAU,QACV63B,WAAY,UAGhBu2B,WAAY,CACV1uD,QAAS,QACT0E,MAAOrL,EAAMoG,QAAQzG,KAAKwb,QAC1BlU,SAAU,QACV63B,WAAY,OACZ7jB,aAAcjb,EAAMgb,MAAMC,aAC1B3L,OAAQ,cAuFCwK,CAAmBg7C,I,2HCnF5BU,E,kDACJ,WAAY91D,GAAQ,IAAD,8BACjB,cAAMA,IACDyiB,IAAMvI,IAAM4G,YAFA,E,sDAKnB,WAIE,GAAIphB,KAAKM,MAAM0O,KAA4C,IAArChP,KAAK+iB,IAAIzD,QAAQ3c,SAAS6J,OAAc,CAC5D,IAAM6pD,EAAqB,IAAIC,IAAY,CACzCjzD,OAAQrD,KAAK+iB,IAAIzD,QACjBi3C,SAAU,oDACVrzD,MAAO,SAETlD,KAAKM,MAAM0O,IAAI8mD,WAAWO,M,oBAI9B,WACE,IAAQp+C,EAAYjY,KAAKM,MAAjB2X,QACR,OAAO,qBAAK8K,IAAK/iB,KAAK+iB,IAAK3a,UAAW6P,EAAQm5B,mB,GAtBjB52B,IAAMC,eA0BxBC,uBAzDA,SAAC9Z,GACd,MAAO,CACLwwC,aAAc,CACZ,gBAAiB,CACfp5B,SAAU,SACV6C,SAAU,QAEZ,oBAAoB,aAClBpT,WAAY7G,EAAMoG,QAAQS,WAAWkd,MACrCC,UAAWhkB,EAAMikB,QAAQ,GACzBhJ,aAAcjb,EAAMgb,MAAMC,aAC1B2C,OAAQ,OACR3R,SAAU,OACV2pD,WAAY,UACX51D,EAAMI,YAAYC,KAAK,MAAQ,CAC9B4Z,SAAU,UAGd,uBAAwB,CACtB5O,MAAO,QACPwqD,WAAY,SAEd,WAAY,CACVvmD,OAAQ,UACR0U,UAAW,OACXK,QAAS,YAgCFvK,CAAmB07C,I,iCC7DlC,qFAMM7c,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvC+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,aAUR27C,EAAal8C,IAAM6iC,MAAK,SAAC/8C,GAC7B,IAAM2X,EAAUshC,IAEhB,OACEj5C,EAAMsZ,SAASC,OAAOC,UAAU9K,IAAI2nD,YAClC,cAAC,IAAD,CAAShuD,MAAM,4BAAf,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAW,eACXnR,UAAW6P,EAAQkkB,OACnBz4B,QAAS,SAACX,GACRzC,EAAMsZ,SAAS6sB,SAJnB,SAOE,cAAC,IAAD,aAQGiwB,a,oJCtBTE,E,4MAEJ/mD,YAAc,SAAC9M,GACb,IAAQiM,EAAQ,EAAK1O,MAAb0O,IACR,QAAYwE,IAARxE,EAAmB,CACrB,IAAM+zB,EAAO/zB,EAAIoB,UACjB,EAAyB,EAAK9P,MAAMwZ,UAAU9K,IAAtC00B,EAAR,EAAQA,KAAMT,EAAd,EAAcA,OACdF,EAAK+xB,QAAQ,CAAEpxB,OAAMT,a,4CAIzB,WACE,IAAQhrB,EAAYjY,KAAKM,MAAjB2X,QAER,OACE,cAAC,IAAD,CAAStP,MAAM,4CAAf,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAW,4CACXnR,UAAW6P,EAAQkkB,OACnBz4B,QAAS1D,KAAK6P,YAHhB,SAKE,cAAC,IAAD,c,GAtBc2K,IAAMC,eA8BjBC,uBA7CA,SAAC9Z,GAAD,MAAY,CACzB+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,YAwCCL,CAAmBk8C,I,8KCpC5BC,E,kDASJ,WAAYv2D,GAAQ,IAAD,8BACjB,cAAMA,IARR07C,KAAO,GAOY,EALnBllC,MAAQ,CACNgvC,SAAU,KACV7O,cAAe,MAGE,EAqCnB6f,gBAAkB,WAChB,IAAIC,EAAY,GAahB,OAZA,EAAK/a,KAAK71C,SAAQ,SAAC+S,EAAMzC,GACvBsgD,EAAUvnD,KACR,cAAC,IAAD,CAGEipC,SAAUhiC,IAAU,EAAKK,MAAMmgC,cAC/BvzC,QAAS,SAAC0uB,GAAD,OAAW,EAAKs7B,oBAAoBt7B,EAAO3b,IAJtD,SAMGyC,EAAK89C,uBALDvgD,OASJsgD,GAnDU,EAuDnBlnD,YAAc,SAACuiB,GACb,EAAKva,SAAS,CAAEiuC,SAAU1zB,EAAMi0B,iBAxDf,EA2DnBqH,oBAAsB,SAACt7B,EAAO3b,GAC5B,IAAMwgD,EAAc,EAAKjb,KAAKvlC,GAAOygD,qBAC/Bn3C,EAAI,EAAK/Q,IAAIoB,UAAUy2B,YAAY,GACnC5mB,EAAI,EAAKjR,IAAIoB,UAAUy2B,YAAY,GACnCI,EAAI,EAAKj4B,IAAIoB,UAAUa,UAK7B1R,OAAO2pC,SAASiJ,OAAhB,UACK5yC,OAAO2pC,SAASnU,QADrB,OAC8Bx1B,OAAO2pC,SAASiuB,SAD9C,cAC4DF,EAD5D,cAC6El3C,EAD7E,cACoFE,EADpF,cAC2FgnB,KArE1E,EA6EnBhlC,YAAc,WACZ,EAAK4V,SAAS,CAAEiuC,SAAU,QA5E1B,EAAKlsC,SAAW,EAAKtZ,MAAMsZ,SAC3B,EAAK5K,IAAM,EAAK1O,MAAMsZ,SAASwf,SAHd,E,iDAMnB,SAAc4iB,GACZ,IAAMnf,EAAc78B,KAAK4Z,SAASC,OAA5BgjB,UAEN78B,KAAKg8C,KAAOA,EAGZ,IAAI/E,EAAgBj3C,KAAKg8C,KAAKrjC,WAAU,SAAC3J,GACvC,OAAOA,EAAIkoD,uBAAyBr6B,KAEtC78B,KAAK6X,SAAS,CAAEo/B,oB,+BAGlB,WAAqB,IAAD,OAClB,EAAgCj3C,KAAK4Z,SAASC,OAAOwjB,UAA/CmH,EAAN,EAAMA,MAAO4yB,EAAb,EAAaA,oBAMiC5jD,IAA1CxT,KAAK4Z,SAASC,OAAOw9C,iBACvBr3D,KAAKs3D,cAAct3D,KAAK4Z,SAASC,OAAOw9C,kBAExCvkD,iBAAO,GAAD,OAAI0xB,GAAJ,OAAY4yB,EAAZ,6BACHpkD,MAAK,SAACukD,GAAD,OAAUA,EAAKhkD,UACpBP,MAAK,SAACgpC,GAAD,OAAU,EAAKsb,cAActb,MAClCvoC,OAAM,SAACC,GACN,MAAM,IAAI+S,MAAM/S,Q,oBAiDxB,WACE,IAAQoyC,EAAa9lD,KAAK8W,MAAlBgvC,SACA7tC,EAAYjY,KAAKM,MAAjB2X,QACF7W,EAAO4lC,QAAQ8e,GAEfn9C,EACJ3I,KAAKM,MAAMsZ,SAASC,OAAOC,UAAU9K,IAAIrG,OAAS,mBAEpD,OAEE3I,KAAKM,MAAMsZ,SAASC,OAAOC,UAAU9K,IAAIwoD,aACvC,qCACE,cAAC,IAAD,CAAS7uD,MAAK,2BAAsBA,GAApC,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAW,YACXk+C,YAAWr2D,EAAO,yBAAsBoS,EACxCu6C,gBAAc,OACd3lD,UAAW6P,EAAQkkB,OACnBz4B,QAAS1D,KAAK6P,YALhB,SAOE,cAAC,IAAD,UAIN,cAAC,IAAD,CACExN,GAAG,oBACHyjD,SAAUA,EACV1kD,KAAMA,EACND,QAASnB,KAAKiC,YAJhB,SAMGjC,KAAK82D,2B,GAzHQt8C,IAAMC,eAiIjBC,uBA1IA,SAAC9Z,GAAD,MAAY,CACzB+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,YAqICL,CAAmBm8C,I,8KCzH5Ba,E,kDAMJ,WAAYp3D,GAAQ,IAAD,8BACjB,cAAMA,IAmCRa,QAAU,WACR,EAAK0W,SAAS,CACZ8/C,YAAY,KAtCG,EA0CnBC,cAAgB,WACd,EAAK//C,SAAS,CACZ8/C,YAAY,KA1Cd,EAAKjuD,KAAO,cACZ,EAAKrI,QAAUf,EAAMe,QACrB,EAAKsH,MAAQ,EAAKtH,QAAQsH,OAAS,YACnC,EAAKmO,MAAQ,CACX6gD,YAAY,GANG,E,qDAUnB,WACE,IAAIA,EAAa33D,KAAKqB,QAAQukC,gBAEM,IAAhC5lC,KAAKqB,QAAQukC,gBAEiB,IAA9B5lC,KAAKqB,QAAQw2D,cAGP,IAFNh4D,SACEN,OAAOC,aAAaI,QAAQ,kCAG9B+3D,GAAa,IAEqB,IAA9B33D,KAAKqB,QAAQw2D,cAAyBhlC,0BACxCtzB,OAAOC,aAAaC,QAAQ,gCAAiC,GAE/Dk4D,GAAa,GAGfA,GAAa,EAGf33D,KAAK6X,SAAS,CACZ8/C,iB,0BAgBJ,WACE,MAAyC33D,KAAKM,MAAMe,QAA5CI,EAAR,EAAQA,WAAYlB,EAApB,EAAoBA,KAAMiB,EAA1B,EAA0BA,WAE1B,OAAOqsD,uBACL,cAAC,UAAD,CACExsD,QAAS,CACPI,aACAlB,OACAiB,aACAG,8BAA8B,GAEhCP,KAAMpB,KAAK8W,MAAM6gD,WACjBx2D,QAASnB,KAAKmB,UAEhB6O,SAASgR,eAAe,wB,oBAI5B,WACE,IAAQ/I,EAAYjY,KAAKM,MAAjB2X,QACR,OACE,qCACGjY,KAAK83D,eACN,cAAC,IAAD,CAASnvD,MAAO3I,KAAK2I,MAArB,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAYvZ,KAAK2I,MACjBP,UAAW6P,EAAQkkB,OACnBz4B,QAAS1D,KAAK43D,cAHhB,SAKE,cAAC,IAAD,iB,GApFYp9C,IAAMC,eA6FjBC,uBAxGA,SAAC9Z,GACd,MAAO,CACL+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,YAkGDL,CAAmBg9C,I,kNC9F5BK,E,kDAWJ,WAAYz3D,GAAQ,IAAD,EAWjB,OAXiB,qBACjB,cAAMA,IANRwW,MAAQ,CACNgvC,SAAU,KACV6R,YAAY,GAGK,EAwBnB9nD,YAAc,SAACuiB,GACb,EAAKva,SAAS,CAAEiuC,SAAU1zB,EAAMi0B,iBAzBf,EA4BnBpkD,YAAc,WACZ,EAAK4V,SAAS,CAAEiuC,SAAU,QA7BT,EAkCnBkS,eAAiB,SAACC,GAChB,OACGA,EAAQnjD,SAAS,OAASmjD,EAAQnjD,SAAS,OAC5CmjD,EAAQnjD,SAAS,OArCF,EA2CnBojD,sBAAwB,SAACD,GACvB,IAAME,EAAc,IAAIlvB,gBAAgBgvB,GAClCl4C,EAAIo4C,EAAYxnD,IAAI,KACpBsP,EAAIk4C,EAAYxnD,IAAI,KACpBs2B,EAAIkxB,EAAYxnD,IAAI,KAGpBu4B,EAAWnpB,GAAKE,EAAI,CAACF,EAAGE,GAAK,KAEnC,MAAO,CAAEipB,WAAUxF,KADNwF,EAAWjC,EAAI,KACHpE,OAJfs1B,EAAYxnD,IAAI,OAhDT,EAuDnBynD,gBAAkB,SAAChmC,EAAOlZ,GACxB,IAAMtG,EAAMsG,EAAKm/C,UAAUtwC,cAE3B,GAAI,EAAKiwC,eAAeplD,GAAM,CAC5B,EAAK3Q,cACL,MAAmC,EAAKi2D,sBAAsBtlD,GAAtDs2B,EAAR,EAAQA,SAAUxF,EAAlB,EAAkBA,KAAMb,EAAxB,EAAwBA,OACxB,EAAKqG,SAAWA,EAChB,EAAKxF,KAAOwF,EAAWxF,GAAQ,EAAK10B,IAAIoB,UAAUa,UAAY,KAE9D,EAAK4xB,OAASA,EAIVA,EACF,EAAKy1B,aAIL,EAAKC,MAAM,EAAKvpD,IAAIoB,UAAW,EAAK84B,SAAU,EAAKxF,WAIrD,EAAKpjC,MAAMuvB,gBACT,kIACA,CACEjoB,QAAS,YAGb+L,QAAQ1P,MACN,+CACEiV,EAAKqR,KACL,KACArR,EAAKm/C,UACL,kHAxFW,EA6FnBvB,gBAAkB,WAChB,IAAMC,EAAY,GAWlB,OAVA,EAAK11D,QAAQm3D,WAAWryD,SAAQ,SAAC+S,EAAMzC,GACrCsgD,EAAUvnD,KACR,cAAC,IAAD,CAEE9L,QAAS,SAAC0uB,GAAD,OAAW,EAAKgmC,gBAAgBhmC,EAAOlZ,IAFlD,SAIGA,EAAKqR,MAHD9T,OAOJsgD,GAzGU,EAwHnBuB,WAAa,WACX,EAAKzgD,SAAS,CACZ8/C,YAAY,KA1HG,EA8HnBc,YAAc,WACZ,IAAMtJ,EAAgB,EAAKtsB,OAAOlxB,MAAM,KACxC,EAAKkG,SAAS,CACZ8/C,YAAY,IAEd,EAAKe,gBAAgBvJ,GACrB,EAAKoJ,MAAM,EAAKvpD,IAAIoB,UAAW,EAAK84B,SAAU,EAAKxF,OApIlC,EAuInBi1B,YAAc,WACZ,EAAK9gD,SAAS,CACZ8/C,YAAY,KAzIG,EA6InBiB,qBAAuB,SAACnrD,EAAO0hD,GAC7B,OAAOA,EAAcv2B,MACnB,SAACiN,GAAD,OAAaA,IAAYp4B,EAAMG,gBAAN,SA/IV,EAmJnB8qD,gBAAkB,SAACvJ,GACjB,IADmC,EAC7B0J,EAAsB,EAAK7pD,IAC9BsB,YACAC,WACAC,QAAO,SAAC/C,GAAD,OAAWA,EAAMkD,IAAI,gBAJI,cAMnBkoD,GANmB,IAMnC,2BAAqC,CAAC,IAA3B3xB,EAA0B,QAC/B,EAAK0xB,qBAAqB1xB,EAAGioB,IAC/B,EAAKhwD,eAAeG,QAAQ,0BAA2B4nC,GACvDA,EAAE/C,YAAW,KAEb,EAAKhlC,eAAeG,QAAQ,0BAA2B4nC,GACvDA,EAAE/C,YAAW,KAZkB,gCAjJnC,EAAKz6B,KAAO,SACZ,EAAKmQ,OAASvZ,EAAMsZ,SAASC,OAAOC,UAAUC,MAAMC,MAClD,SAACC,GAAD,MAAkB,WAAXA,EAAEvQ,QAGX,EAAKkQ,SAAWtZ,EAAMsZ,SACtB,EAAKza,eAAiBmB,EAAMsZ,SAASza,oBAGjBqU,IAAhB,EAAKqG,OAAsB,gBAG/B,EAAKxY,QAAU,EAAKwY,OAAOxY,QAC3B,EAAK2N,IAAM1O,EAAMsZ,SAASwf,SAC1B,EAAKzwB,MAAQ,EAAKtH,QAAQsH,OAAS,WAEnC,EAAKugC,SAAW,KAChB,EAAKxF,KAAO,KACZ,EAAKb,OAAS,KApBG,G,yCA4GnB,SAAME,EAAMmG,EAAUxF,GACpB,GAAKwF,EAAL,CAIAnG,EAAK+xB,QAAQ,CACX7xB,OAAQiG,EACRxF,KAAMA,EACNqxB,SAJe,U,0BAoDnB,WACE,OAAI/0D,KAAK8W,MAAM6gD,WACN9J,uBACL,cAAC,UAAD,CACExsD,QAAS,CACPd,KAAM,mHACNkB,WAAY,gBACZD,WAAY,KACZF,UAAW,SACXK,8BAA8B,GAEhCP,KAAMpB,KAAK8W,MAAM6gD,WACjBx2D,QAASnB,KAAKy4D,YACdv3D,QAASlB,KAAK24D,cAEhB3oD,SAASgR,eAAe,sBAGnB,O,oBAIX,WAEE,QACkBxN,IAAhBxT,KAAK6Z,QACJ7Z,KAAK6Z,OAAOlD,eAAe,YAC1B3W,KAAK6Z,OAAOxY,QAAQm3D,WAAWhsD,OAAS,EAE1C,OAAO,KAEP,IAAQs5C,EAAa9lD,KAAK8W,MAAlBgvC,SACA7tC,EAAYjY,KAAKM,MAAjB2X,QACF7W,EAAO4lC,QAAQ8e,GACrB,OACE,qCACE,cAAC,IAAD,CAASn9C,MAAO3I,KAAK2I,MAArB,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAYvZ,KAAK2I,MACjBP,UAAW6P,EAAQkkB,OACnBz4B,QAAS1D,KAAK6P,YAHhB,SAKE,cAAC,IAAD,UAIN,cAAC,IAAD,CACExN,GAAG,oBACHyjD,SAAUA,EACV1kD,KAAMA,EACND,QAASnB,KAAKiC,YAJhB,SAMGjC,KAAK82D,oBAEP92D,KAAK83D,sB,GAtOKt9C,IAAMC,eA6OZC,uBAxPA,SAAC9Z,GACd,MAAO,CACL+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,YAkPDL,CAAmB6d,YAAaw/B,K,6JCvPzCxe,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvCy3B,KAAK,aACHgH,YAAaz+B,EAAM4G,QAAQ,IAC1B5G,EAAMI,YAAYC,KAAK,MAAQ,CAC9B2jB,UAAW,SAGfuX,OAAQ,CACN+C,OAAQ,EACRjzB,MACyB,SAAvBrL,EAAMoG,QAAQ0C,KACV9I,EAAMoG,QAAQ8xD,OAAOC,MACrBn4D,EAAMoG,QAAQC,OAAO0U,QAE7B2Q,KAAK,eACF1rB,EAAMI,YAAY+nD,GAAG,MAAQ,CAC5B1pB,YAAaz+B,EAAM4G,QAAQ,KAG/BywB,QAAQ,eACLr3B,EAAMI,YAAYC,KAAK,MAAQ,CAC9Bi+B,OAAQ,aAKd,SAAS85B,EAAT,GAII,IAHFr/B,EAGC,EAHDA,cACAx6B,EAEC,EAFDA,eACAy+B,EACC,EADDA,oBAEM3lB,EAAUshC,IAKhB,EAAwC33C,mBAASg8B,GAAjD,mBAAOq7B,EAAP,KAAqBC,EAArB,KAQAv/B,EAAgBA,EAAc1rB,MAAK,SAACxF,EAAGyF,GAAJ,OAAW,OAADzF,QAAC,IAADA,OAAA,EAAAA,EAAGszB,QAAH,OAAW7tB,QAAX,IAAWA,OAAX,EAAWA,EAAG6tB,UAG3DiE,qBAAU,WACR7gC,EAAemiB,UAAU,0BAA0B,WACjD43C,EAAgB,WAEjB,CAAC/5D,IAyCJ,OACEw6B,EAAcntB,OAAS,GACrB,cAAC,IAAD,CAAOpE,UAAW6P,EAAQogB,KAA1B,SACE,cAAC,IAAD,CACEl1B,MAAO81D,EACPE,WAAS,EACT/1D,SA7C0B,SAACL,EAAGgT,GACpCmjD,EAAgBnjD,GAEN,OAANA,EACFxW,OAAOC,aAAa45D,WAAW,uBAE3BvmC,0BACFtzB,OAAOC,aAAaC,QAAQ,sBAAuBsW,GAMvD5W,EAAeG,QAAQ,4BAA6ByW,IAiC9CwD,aAAW,iBACXtB,QAAS,CAAEggB,QAAShgB,EAAQggB,SAL9B,SAOG0B,EAAc3qB,KAAI,SAACd,GAAD,OAjCA,SAAC,GAAoC,IAAlC2tB,EAAiC,EAAjCA,WAAY14B,EAAqB,EAArBA,MAAOmB,EAAc,EAAdA,QAEzCgoB,EACJnpB,IAAU81D,EACR,cAAC,IAAD,CAAW7wD,UAAW6P,EAAQqU,OAE9B,cAACuP,EAAD,CAAYzzB,UAAW6P,EAAQqU,OAInC,OACE,eAAC,IAAD,CACEjqB,GAAIc,EAEJA,MAAOA,EACPiF,UAAW6P,EAAQkkB,OAJrB,UAMG7P,EACD,cAAC,IAAD,CAAQgO,QAAM,EAAd,SAAgBh2B,MALXnB,GAoBuBk2D,CAAmBnrD,UAOvD,SAASivC,EAAchmC,EAAWimC,GAEhC,OAAOjmC,EAAUwiB,cAAcntB,SAAW4wC,EAAUzjB,cAAcntB,OAGrDgO,cAAM6iC,KAAK2b,EAAqB7b,I,iCC9H/C,qFAMM5D,EAAYC,aAAW,SAAC54C,GAAD,MAAY,CACvC+jB,MAAO,CACL/d,aAAchG,EAAM4G,QAAQ,IAE9B20B,OAAQ,CACNphB,SAAU,aAURu+C,EAAe9+C,IAAM6iC,MAAK,SAAC/8C,GAC/B,IAAM2X,EAAUshC,IAEhB,OACGj5C,EAAM69B,kBACL,cAAC,IAAD,CAASx1B,MAAM,iDAAf,SACE,cAAC,IAAD,CAAOP,UAAW6P,EAAQ0M,MAA1B,SACE,cAAC,IAAD,CACEpL,aAAW,uBACXnR,UAAW6P,EAAQkkB,OACnBz4B,QAAS,SAACX,GACRzC,EAAMuc,kBAJV,SAOE,cAAC,IAAD,WAKR,QAIWy8C,a,iCC5Cf,OAYeC,UAZS,SAACC,GACnBA,GAAeA,aAAuBC,UACxC,iCAAqBzmD,MAAK,YAAkD,IAA/C0mD,EAA8C,EAA9CA,OAAQC,EAAsC,EAAtCA,OAAQC,EAA8B,EAA9BA,OAAQC,EAAsB,EAAtBA,OAAQC,EAAc,EAAdA,QAC3DJ,EAAOF,GACPG,EAAOH,GACPI,EAAOJ,GACPK,EAAOL,GACPM,EAAQN,Q,i4BCkCdO,uBAEA,IAAIC,EACF,qGACEC,EACF,6HAEIC,EAAc,SAACvxC,EAASjV,GAC5BC,QAAQ1P,MAAMyP,GACdymD,IAASlX,OACP,sBAAK76C,UAAU,cAAf,UACE,8BACE,cAAC,IAAD,MAEF,8BAAMugB,OAER3Y,SAASgR,eAAe,UAY5BlO,iBAAO,iBAAkB,CAAEsnD,aAAa,IACrCpnD,MAAK,SAACqnD,GACLA,EAAkB9mD,OAAOP,MAAK,SAACqqB,GAE7Bi9B,2BAAiBj9B,GAEbA,EAAU28B,sBACZA,EAAsB38B,EAAU28B,qBAC9B38B,EAAU48B,oBACZA,EAAoB58B,EAAU48B,mBAGhC,IAAMloC,EAAY,IAAI/b,IAAIzW,OAAO2pC,UAAUqxB,aAIvC19B,EAAY9K,EAAU/f,IAAI,KAC1B+f,EAAUphB,IAAI,KACd0sB,EAAUm9B,WAIRC,EACJp9B,EAAU+5B,gBAAkB/5B,EAAU+5B,eAAe7pD,OAAOf,OAAS,EAEjEkuD,GAA6C,IAAjCr9B,EAAUs9B,mBAYtBC,EAAc,uCAAG,8BAAAnyD,EAAA,6DAGf2uD,GACU,IAAdsD,EACIr9B,EAAU+5B,eAAej3D,QAAQ,KAAM,MACvCk9B,EAAU+5B,eAGVyD,EATe,UASAx9B,EAAUmH,OATV,OASkB4yB,EATlB,6BAYNtkD,iBAAO,GAAD,OAAI+nD,EAAJ,YAAiBh+B,IAZjB,+EAenBA,EAAYQ,EAAUm9B,WAfH,UAiBN1nD,iBAAO,GAAD,OAAI+nD,EAAJ,YAAiBh+B,IAjBjB,kGAAH,sDAqBF,IAAd69B,EACFxnD,QAAQC,IAAI,CACVynD,IACA9nD,iBAAO,mBAAoB,CAAEsnD,aAAa,MAEzCpnD,MAAK,YAA+C,IAAD,mBAA5C8nD,EAA4C,KAAzBC,EAAyB,KAClD7nD,QAAQC,IAAI,CAAC2nD,EAAkBvnD,OAAQwnD,EAAoBxnD,SACxDP,MAAK,YAA+B,IAAD,mBAA5B8G,EAA4B,KAAjBmB,EAAiB,KAC5BpB,EAAS,CACbgjB,UAAW49B,EAAgB59B,EAAY,kBACvCQ,UAAWA,EACX4H,aAAcnrB,EAAUmrB,aACxBnrB,UAAWA,EAAUA,UACrBokB,YAAapkB,EAAUokB,YACvBm5B,iBAAkBv9C,EAAUu9C,iBAC5BtlC,aAIFpuB,UAAmBq3D,WAAWnhD,EAAOgjB,WAGrCs9B,IAASlX,OACP,cAAC,UAAD,CACE5mC,YAAa4+C,EAAY5+C,YACzBxC,OAAQA,EACRoB,YAAaA,IAEfjL,SAASgR,eAAe,YAG3BvN,OAAM,SAACC,GAAD,OAASwmD,EAAYD,EAAmBvmD,SAElDD,OAAM,SAACC,GAAD,OAASwmD,EAAYF,EAAqBtmD,MAGnDR,QAAQC,IAAI,CAGVsnD,EACI3nD,iBAAO,GAAD,OACDuqB,EAAUmH,OADT,OACiBnH,EAAU+5B,eAD3B,mBAGNtkD,iBAAO,0BAA2B,CAAEsnD,aAAa,IAGrDK,EACIG,IACA9nD,iBAAO,uBAAwB,CAAEsnD,aAAa,IAGlDtnD,iBAAO,mBAAoB,CAAEsnD,aAAa,MAEzCpnD,MACC,YAIO,IAAD,mBAHJkoD,EAGI,KAFJJ,EAEI,KADJC,EACI,KACJ7nD,QAAQC,IAAI,CACV+nD,EAAqB3nD,OACrBunD,EAAkBvnD,OAClBwnD,EAAoBxnD,SAEnBP,MAAK,YAA6C,IAAD,mBAA1CiyB,EAA0C,KAA5BnrB,EAA4B,KAAjBmB,EAAiB,KAG1CpB,EAAS,CACbgjB,UAAW49B,EAAgB59B,EAAY,kBACvCQ,UAAWA,EACX4H,aAAcA,EACdnrB,UAAWA,EACXiY,aAUF,GANApuB,UAAmBq3D,WAAWnhD,EAAOgjB,gBAMTrpB,IAHAqG,EAAOC,UAAUC,MAAMC,MACjD,SAAC6e,GAAD,MAAwB,kBAAdA,EAAKnvB,QAGf,MAAM,IAAI+c,MACR,0BAC+CjT,IAA5CqG,EAAOwjB,UAAU89B,uBACd,qFACAthD,EAAOwjB,UAAU89B,yBAK3BhB,IAASlX,OACP,cAAC,UAAD,CACE5mC,YAAa4+C,EAAY5+C,YACzBxC,OAAQA,EACRoB,YAAaA,IAEfjL,SAASgR,eAAe,YAG3BvN,OAAM,SAACC,GACNC,QAAQ1P,MAAM,gBAAiByP,EAAIiV,SACnC,IAAIyyC,EAASnB,EACTvmD,EAAIiV,QAAQyN,WAAW,sBACzBglC,EAAS1nD,EAAIiV,QAAQpD,OAAO7R,EAAIiV,QAAQrD,QAAQ,KAAO,IAEzD40C,EAAYkB,EAAQ1nD,SAI3BD,OAAM,SAACC,GACNwmD,EAAYF,EAAqBtmD,YAK1CD,OAAM,SAACC,GACNwmD,EAAYF,EAAqBtmD,MAMrC6lD,qB,2TCzPI1/C,EAAS,CACX/G,OAAQ,CACNuoD,eAAgB,CAAE1uB,YAAa,iBAyB7B2uB,E,WAKJ,aAAwC,IAAD,QAA3Bj6D,EAA2B,uDAAjB,GAAIwY,EAAa,uDAAJ,GAAI,yBAFvC0hD,SAAW,8BAGTv7D,KAAKw7D,cAAwC,IAAzBn6D,EAAQm6D,aAC5Bx7D,KAAK6Z,OAASA,EACd7Z,KAAK4S,IAAM,GACX5S,KAAKqB,QAAU,GAGfrB,KAAKy7D,MAAc,QAAP,EAAAC,SAAA,mXAAcC,qBAAsB,KAChD37D,KAAK47D,eAC0C,UAAtC,QAAP,EAAAF,SAAA,mXAAcG,8BAAyC,E,kDAG3D,SAAejpD,EAAKkpD,GAAmB,IAAD,OAOpC,OAAO,IAAIj1C,OACT,IAAMi1C,EAAiBnqD,MAAM,KAAK3C,KAFhB,SAAC4D,GAAD,OAASA,EAAIzS,QAAQ,EAAKo7D,SAAU,WAEHjpD,KAAK,MAAQ,KAChEoC,KAAK9B,K,kCAGT,WAAwB,IAAD,OAChB5S,KAAK+7D,WACR/7D,KAAK+7D,SAAW91D,OAAOC,KAAKlG,KAAK6Z,OAAO/G,OAAOkpD,iBAAmB,IAClEh8D,KAAK+7D,SAAS9tD,MAAK,SAACxF,EAAGyF,GAAJ,OAAUA,EAAE1B,OAAS/D,EAAE+D,WAG5C,IAAM3I,EAAM7D,KAAK+7D,SAAS/hD,MAAK,SAACnW,GAC9B,OAAO,EAAKo4D,eAAe,EAAKrpD,IAAK/O,MAGvC,GAAIA,EAAK,CAEP,IAAIq4D,EAAYl8D,KAAK6Z,OAAO/G,OAAOkpD,gBAAgBn4D,IAAQ,GAC3D7D,KAAKqB,QAAU4E,OAAOksC,OAAOnyC,KAAKqB,QAAS66D,M,0CAI/C,WAGMl8D,KAAKqB,QAAQsrC,aAA4C,YAA7B3sC,KAAKqB,QAAQsrC,cAC3C3sC,KAAKqB,QAAQ86D,UAAY,CAAEC,iBAAiB,UACrCp8D,KAAKqB,QAAQsrC,e,6BAIxB,WAgBE,GAfA3sC,KAAKqB,QAAU4E,OAAOksC,OAAPlsC,OAAA,IAAAA,CAAA,GACRjG,KAAK6Z,OAAO/G,OAAOuoD,gBACxBr7D,KAAKqB,SAGHrB,KAAK6Z,OAAO/G,OAAOupD,oBACrBr8D,KAAKs8D,uBAGHt8D,KAAKw7D,cAGPx7D,KAAKu8D,gCAGqB,IAAxBv8D,KAAK47D,kBAMwB,IAA7B57D,KAAKqB,QAAQ+4D,aACZp6D,KAAKw8D,mBACyC,IAA7Cx8D,KAAK4S,IAAI0S,QAAQtlB,KAAKw8D,oBACxB,CACA,IAAIpC,EAAW,WACc,IAA3Bp6D,KAAK4S,IAAI0S,QAAQ,KAAc,IAAM,KADxB,OAnFM,cAmFN,YAEYtlB,KAAKy7D,MAChCz7D,KAAK4S,IAAL,UAAc5S,KAAK4S,KAAnB,OAAyBwnD,M,0BAK/B,SAAavgD,GACX7Z,KAAK6Z,OAASA,EACd7Z,KAAKo3D,eAAiBp3D,KAAK6Z,OAAOu9C,gBAAkB,GACpDp3D,KAAKwkC,MAAQxkC,KAAK6Z,OAAO2qB,OAAS,GAClCxkC,KAAKw8D,kBAAL,UAA4Bx8D,KAAKwkC,OAAjC,OAAyCxkC,KAAKo3D,kB,mBAGhD,WACEp3D,KAAKqB,QAAU,GACfrB,KAAK4S,IAAM,O,KAIX6pD,EAAe,KACfC,EAAgB,KAEpB,SAASpC,EAAiBj9B,GACxBxjB,EAAS5T,OAAOksC,OAAOt4B,EAAQwjB,GAC3Bo/B,GACFA,EAAaE,aAAa9iD,GAExB+iD,GACFA,EAAkBD,aAAa9iD,GAInC,SAASkgD,IACP,GAAI0C,EACF,MAAM,IAAIh2C,MAAM,2CAKlB,OAHAg2C,EAAe,IAAInB,EAAa,GAAIzhD,GACpC6iD,EAAgBG,MAET/pD,EAGT,SAASy+B,EAA0Bh6B,GAAS,IAAD,EACrCulD,EAAKL,EACTK,EAAG18C,QACH08C,EAAGlqD,IAAM2E,EAAO3E,IAChBkqD,EAAGz7D,QAAH,eAAkBkW,GACdulD,EAAGjjD,OAAO/G,OAAOupD,oBACnBS,EAAGR,uBAE2B,aAA5B,UAAAQ,EAAGz7D,eAAH,eAAYsrC,cACVp1B,EAAO82B,cAET92B,EAAO82B,YAAc,mBAK3B,SAASv7B,IACP,IAAIgqD,EAAKL,EACTK,EAAG18C,QAFoB,2BAANsF,EAAM,yBAANA,EAAM,gBAwBvB,OApBAo3C,EAAGz7D,QAAUqkB,EAAK,IAAM,GAMD,kBAAZA,EAAK,GACdo3C,EAAGlqD,IAAM8S,EAAK,GACLA,EAAK,aAAc1P,IAC5B8mD,EAAGlqD,IAAM8S,EAAK,GAAGhd,KACRgd,EAAK,aAAcq3C,SAE5BD,EAAGlqD,IAAM8S,EAAK,GAAG9S,IACjBkqD,EAAGz7D,QAAUqkB,EAAK,IAElBo3C,EAAGlqD,IAAM8S,EAAK,GAAGqD,WAGnB+zC,EAAGE,kBAEIN,EAAcI,EAAGlqD,IAAKkqD,EAAGz7D,SAGlC,IAAIu7D,EAAoB,KACpBK,EAAqB,KAEzB,SAASC,EAAeC,GACtB,GAAIP,EACF,MAAM,IAAIn2C,MAAM,gDAElBm2C,EAAoB,IAAItB,EAAa,CAAEE,cAAc,GAAQ3hD,GAC7DojD,EAAqBE,EAAaC,KAClCD,EAAaC,KAAOC,EAGtB,SAASA,IACP,IAAIC,EAAKV,EAIT,OAHAU,EAAGl9C,QACHk9C,EAAG1qD,IAAH,wCAEoB,IAAhB,UAAKpG,QAEP8wD,EAAGj8D,QAAU4E,OAAOksC,OAAO,GAAd,yCACbmrB,EAAGN,kBACIC,EAAmBK,EAAGj8D,UACJ,IAAhB,UAAKmL,QAEd8wD,EAAGj8D,QAAH,wCACAi8D,EAAGN,kBACIC,EAAmBK,EAAG1qD,IAAK0qD,EAAGj8D,eAJhC,I,uEC3NT,4FAKO,IAAMqhB,EAAW3B,IAEjB,SAASA,IACd,OAAOxhB,OAAOkf,WAAa,M,0CCR7B,IAAIzP,EAAM,CACT,wBAAyB,CACxB,KAED,4CAA6C,CAC5C,KAED,sBAAuB,CACtB,KAED,uBAAwB,CACvB,KACA,KAED,+BAAgC,CAC/B,KAED,0BAA2B,CAC1B,KACA,EACA,GACA,KAED,gCAAiC,CAChC,KAED,6CAA8C,CAC7C,KAED,mDAAoD,CACnD,KAED,kDAAmD,CAClD,KAED,kDAAmD,CAClD,KAED,oCAAqC,CACpC,KAED,+BAAgC,CAC/B,KAED,8BAA+B,CAC9B,KAED,sCAAuC,CACtC,KACA,KAED,gCAAiC,CAChC,KAED,2BAA4B,CAC3B,KACA,KAED,sCAAuC,CACtC,KAED,gCAAiC,CAChC,KAED,mCAAoC,CACnC,KAED,wCAAyC,CACxC,KAED,qCAAsC,CACrC,KAED,8DAA+D,CAC9D,KAED,4DAA6D,CAC5D,KAED,mEAAoE,CACnE,KAED,0EAA2E,CAC1E,KAED,mEAAoE,CACnE,KAED,iEAAkE,CACjE,KAED,yDAA0D,CACzD,KAED,4DAA6D,CAC5D,KAED,4CAA6C,CAC5C,KAED,yCAA0C,CACzC,KAED,0CAA2C,CAC1C,KAED,0CAA2C,CAC1C,KAED,wBAAyB,CACxB,KACA,KAED,yBAA0B,CACzB,KAED,4BAA6B,CAC5B,KAED,4BAA6B,CAC5B,KAED,2BAA4B,CAC3B,KAED,4BAA6B,CAC5B,KAED,4BAA6B,CAC5B,KAED,4BAA6B,CAC5B,KAED,uBAAwB,CACvB,KAED,0BAA2B,CAC1B,KAED,6BAA8B,CAC7B,KAED,qBAAsB,CACrB,KAED,qBAAsB,CACrB,KAED,6BAA8B,CAC7B,KACA,KAED,aAAc,CACb,KAED,uBAAwB,CACvB,KAED,oBAAqB,CACpB,KAED,qBAAsB,CACrB,KAED,mBAAoB,CACnB,KACA,KAED,wBAAyB,CACxB,KACA,GACA,IACA,KAED,oBAAqB,CACpB,KACA,KAED,uBAAwB,CACvB,KACA,EACA,KAED,qBAAsB,CACrB,KAED,0BAA2B,CAC1B,KAED,yBAA0B,CACzB,KAED,+BAAgC,CAC/B,KAED,iCAAkC,CACjC,KAED,8BAA+B,CAC9B,KAED,+BAAgC,CAC/B,KAED,6BAA8B,CAC7B,KACA,IAED,kCAAmC,CAClC,KACA,KAED,iCAAkC,CACjC,KACA,IAED,gCAAiC,CAChC,KACA,IAED,mCAAoC,CACnC,KACA,IAED,wCAAyC,CACxC,KACA,KAED,uCAAwC,CACvC,KACA,KAED,6BAA8B,CAC7B,KACA,EACA,GACA,IAED,kCAAmC,CAClC,KACA,EACA,KAED,iCAAkC,CACjC,KACA,IAED,mCAAoC,CACnC,KACA,EACA,GACA,GACA,KAED,wCAAyC,CACxC,KACA,KAED,uCAAwC,CACvC,KACA,EACA,GACA,IAED,kDAAmD,CAClD,KACA,EACA,IAED,yCAA0C,CACzC,KACA,EACA,IAED,4CAA6C,CAC5C,KACA,EACA,KAED,uCAAwC,CACvC,KACA,GACA,IAED,4CAA6C,CAC5C,KACA,KAED,mDAAoD,CACnD,KACA,GACA,KAED,2CAA4C,CAC3C,KACA,GACA,KAED,kCAAmC,CAClC,KACA,IAED,+CAAgD,CAC/C,KACA,EACA,GACA,GACA,GACA,IAED,oDAAqD,CACpD,KACA,IAED,4CAA6C,CAC5C,KACA,KAED,kEAAmE,CAClE,KACA,KAED,0DAA2D,CAC1D,KACA,KAED,uDAAwD,CACvD,KACA,KAED,6DAA8D,CAC7D,KACA,EACA,IAED,iEAAkE,CACjE,KACA,EACA,GACA,GACA,IAED,8DAA+D,CAC9D,KACA,KAED,uDAAwD,CACvD,KACA,KAED,0DAA2D,CAC1D,KACA,KAED,8DAA+D,CAC9D,KACA,KAED,uDAAwD,CACvD,KACA,KAED,mDAAoD,CACnD,KACA,IAED,gEAAiE,CAChE,KACA,EACA,IAED,2DAA4D,CAC3D,KACA,IAED,wDAAyD,CACxD,KACA,KAED,mDAAoD,CACnD,KACA,IAED,uDAAwD,CACvD,KACA,IAED,sDAAuD,CACtD,KACA,KAED,qDAAsD,CACrD,KACA,GACA,KAED,yDAA0D,CACzD,KACA,KAED,6DAA8D,CAC7D,KACA,KAED,6CAA8C,CAC7C,KACA,KAED,4DAA6D,CAC5D,KACA,KAED,oDAAqD,CACpD,KACA,KAED,yBAA0B,CACzB,KACA,EACA,EACA,EACA,EACA,IAED,8BAA+B,CAC9B,KACA,EACA,GACA,KAED,6BAA8B,CAC7B,KACA,EACA,EACA,EACA,IAED,yCAA0C,CACzC,KACA,EACA,EACA,KAED,2BAA4B,CAC3B,KACA,IAED,gCAAiC,CAChC,KACA,KAED,+BAAgC,CAC/B,KACA,KAED,yBAA0B,CACzB,KACA,EACA,GACA,GACA,IACA,IAED,8BAA+B,CAC9B,KACA,GACA,KAED,6BAA8B,CAC7B,KACA,EACA,GACA,KAED,+CAAgD,CAC/C,KACA,KAED,uCAAwC,CACvC,KACA,EACA,IAED,6BAA8B,CAC7B,KACA,GACA,IAED,kCAAmC,CAClC,KACA,KAED,mDAAoD,CACnD,KACA,KAED,uBAAwB,CACvB,KACA,EACA,EACA,EACA,EACA,IAED,oCAAqC,CACpC,KACA,IAED,6CAA8C,CAC7C,KACA,IAED,6CAA8C,CAC7C,KACA,IAED,iCAAkC,CACjC,KACA,IAED,4BAA6B,CAC5B,KACA,KAED,6BAA8B,CAC7B,KACA,EACA,KAED,sCAAuC,CACtC,KACA,EACA,KAED,4BAA6B,CAC5B,KACA,KAED,yCAA0C,CACzC,KACA,EACA,EACA,IAED,2CAA4C,CAC3C,KACA,KAED,wCAAyC,CACxC,KACA,GACA,KAED,iCAAkC,CACjC,KACA,GACA,KAED,6BAA8B,CAC7B,KACA,KAED,kCAAmC,CAClC,KACA,KAED,2BAA4B,CAC3B,KACA,EACA,EACA,EACA,GACA,IAED,iCAAkC,CACjC,KACA,KAED,uBAAwB,CACvB,KACA,EACA,IAED,4BAA6B,CAC5B,KACA,KAED,2BAA4B,CAC3B,KACA,EACA,KAED,mCAAoC,CACnC,KACA,EACA,GACA,IACA,GACA,IAED,uCAAwC,CACvC,KACA,EACA,GACA,IAED,gDAAiD,CAChD,KACA,KAED,uDAAwD,CACvD,KACA,KAED,oDAAqD,CACpD,KACA,KAED,+CAAgD,CAC/C,KACA,KAED,sDAAuD,CACtD,KACA,EACA,KAED,yCAA0C,CACzC,KACA,KAED,2CAA4C,CAC3C,KACA,KAED,oDAAqD,CACpD,KACA,KAED,+CAAgD,CAC/C,KACA,KAED,6CAA8C,CAC7C,KACA,KAED,6CAA8C,CAC7C,KACA,GACA,GACA,GACA,GACA,IAED,kDAAmD,CAClD,KACA,GACA,IAED,iDAAkD,CACjD,KACA,GACA,IAED,kDAAmD,CAClD,KACA,KAED,qDAAsD,CACrD,KACA,KAED,qCAAsC,CACrC,KACA,IAED,uCAAwC,CACvC,KACA,IAED,4CAA6C,CAC5C,KACA,KAED,2CAA4C,CAC3C,KACA,IAED,kDAAmD,CAClD,KACA,KAED,uBAAwB,CACvB,KACA,EACA,EACA,EACA,EACA,IAED,iCAAkC,CACjC,KACA,IAED,sCAAuC,CACtC,KACA,EACA,KAED,4BAA6B,CAC5B,KACA,KAED,2CAA4C,CAC3C,KACA,KAED,wCAAyC,CACxC,KACA,GACA,KAED,iCAAkC,CACjC,KACA,EACA,GACA,KAED,2BAA4B,CAC3B,KACA,EACA,EACA,GACA,GACA,KAED,iCAAkC,CACjC,KACA,KAED,2CAA4C,CAC3C,KACA,EACA,EACA,EACA,GACA,IAED,gDAAiD,CAChD,KACA,KAED,+CAAgD,CAC/C,KACA,EACA,EACA,EACA,GACA,IAED,2DAA4D,CAC3D,KACA,EACA,EACA,KAED,mDAAoD,CACnD,KACA,KAED,oDAAqD,CACpD,KACA,EACA,GACA,KAED,kDAAmD,CAClD,KACA,KAED,qDAAsD,CACrD,KACA,KAED,mDAAoD,CACnD,KACA,EACA,EACA,IAED,uDAAwD,CACvD,KACA,EACA,EACA,KAED,kDAAmD,CAClD,KACA,EACA,EACA,KAED,sDAAuD,CACtD,KACA,EACA,KAED,qDAAsD,CACrD,KACA,KAED,gDAAiD,CAChD,KACA,KAED,iCAAkC,CACjC,KACA,GACA,IAED,sCAAuC,CACtC,KACA,KAED,qCAAsC,CACrC,KACA,KAED,+BAAgC,CAC/B,KACA,IACA,IAED,oCAAqC,CACpC,KACA,KAED,mCAAoC,CACnC,KACA,KAED,qCAAsC,CACrC,KACA,EACA,EACA,KAED,oCAAqC,CACpC,KACA,KAED,2BAA4B,CAC3B,KACA,EACA,EACA,EACA,GACA,IAED,iCAAkC,CACjC,KACA,KAED,gCAAiC,CAChC,KACA,GACA,IAED,+BAAgC,CAC/B,KACA,EACA,EACA,EACA,IAED,+BAAgC,CAC/B,KACA,GACA,IAED,oCAAqC,CACpC,KACA,KAED,mCAAoC,CACnC,KACA,GACA,KAED,6BAA8B,CAC7B,KACA,EACA,EACA,EACA,EACA,IAED,8CAA+C,CAC9C,KACA,KAED,kDAAmD,CAClD,KACA,KAED,mDAAoD,CACnD,KACA,KAED,6CAA8C,CAC7C,KACA,KAED,8CAA+C,CAC9C,KACA,KAED,oEAAqE,CACpE,KACA,EACA,EACA,EACA,IAED,iEAAkE,CACjE,KACA,EACA,EACA,EACA,GACA,KAED,mEAAoE,CACnE,KACA,EACA,EACA,EACA,IAED,iEAAkE,CACjE,KACA,KAED,sCAAuC,CACtC,KACA,KAED,yCAA0C,CACzC,KACA,KAED,oCAAqC,CACpC,KACA,EACA,EACA,EACA,GACA,KAED,uCAAwC,CACvC,KACA,KAED,qCAAsC,CACrC,KACA,EACA,EACA,EACA,GACA,KAED,qCAAsC,CACrC,KACA,KAED,qCAAsC,CACrC,KACA,IAED,yCAA0C,CACzC,KACA,IAED,uCAAwC,CACvC,KACA,EACA,EACA,EACA,GACA,IAED,uCAAwC,CACvC,KACA,IAED,qCAAsC,CACrC,KACA,IAED,0CAA2C,CAC1C,KACA,KAED,yCAA0C,CACzC,KACA,KAED,+BAAgC,CAC/B,KACA,KAED,qCAAsC,CACrC,KACA,EACA,IAED,yCAA0C,CACzC,KACA,EACA,IAED,wDAAyD,CACxD,KACA,KAED,qCAAsC,CACrC,KACA,KAED,oCAAqC,CACpC,KACA,KAED,gEAAiE,CAChE,KACA,EACA,KAED,wDAAyD,CACxD,KACA,EACA,KAED,sDAAuD,CACtD,KACA,KAED,mEAAoE,CACnE,KACA,EACA,EACA,IAED,sDAAuD,CACtD,KACA,EACA,KAED,kDAAmD,CAClD,KACA,EACA,KAED,0DAA2D,CAC1D,KACA,EACA,KAED,6CAA8C,CAC7C,KACA,GACA,KAED,0CAA2C,CAC1C,KACA,KAED,0CAA2C,CAC1C,KACA,IAED,iCAAkC,CACjC,KACA,EACA,EACA,GACA,GACA,IAED,uBAAwB,CACvB,KAED,uBAAwB,CACvB,KACA,KAED,0BAA2B,CAC1B,KAED,oCAAqC,CACpC,KAED,uBAAwB,CACvB,KAED,mBAAoB,CACnB,KAED,0BAA2B,CAC1B,IAED,sBAAuB,CACtB,IAED,uBAAwB,CACvB,KAED,gCAAiC,CAChC,KAED,8BAA+B,CAC9B,KAED,uBAAwB,CACvB,KAED,8CAA+C,CAC9C,MAGF,SAASuuD,EAAoBC,GAC5B,IAAIC,EAAoB/8C,EAAE1R,EAAKwuD,GAC9B,OAAOtqD,QAAQoC,UAAUtC,MAAK,WAC7B,IAAIjQ,EAAI,IAAI0jB,MAAM,uBAAyB+2C,EAAM,KAEjD,MADAz6D,EAAE0qC,KAAO,mBACH1qC,KAIR,IAAI26D,EAAM1uD,EAAIwuD,GAAMn7D,EAAKq7D,EAAI,GAC7B,OAAOxqD,QAAQC,IAAIuqD,EAAIz1C,MAAM,GAAGjZ,IAAIyuD,EAAoB16D,IAAIiQ,MAAK,WAChE,OAAOyqD,EAAoBp7D,MAG7Bk7D,EAAoBr3D,KAAO,WAC1B,OAAOD,OAAOC,KAAK8I,IAEpBuuD,EAAoBl7D,GAAK,IACzBi/B,EAAOq8B,QAAUJ,I","file":"static/js/main.9ed002c7.chunk.js","sourcesContent":["// A simple class used to manage user-cookie-preferences. The default export from this module is\n// an instance of the class, hence it should be seen as a singleton. The \"setConfig\"-method should\n// be run early in the application-load-process, setting wether the cookie-notice should be shown to\n// the users at all. If the \"setConfig\"-method is not run, the cookie-notice will never be shown to the users.\n\n// The manager manages cookie-allowance using bitwise-checks, and there are six \"allow-cookie-states\" (this.#cookieLevel):\n// - (-1): The application is set to not care about cookies at all, and all cookies will be allowed.\n// - (0): The application is set to care about cookies, but the user has not made their decision yet. In this state,\n// the user should be prompted with the cookie-notice, so that they can make their choice. The application should\n// be unusable until they've made their choice. \"functionalOk\" and \"thirdPartyOk\" will obviously return false.\n// - (1): The application is set to care about cookies, but only required cookies are accepted. We do not expose a method\n// that checks if required-cookies are accepted, since if the user has made it passed the cookie-notice (changed\n// this.#cookieLevel from 0 to 1) they have accepted the required cookies.\n// - (2): The application allows for functional cookies. If set, the \"functionalOk\"-method will return true.\n// - (4): The application allows for third-party-cookies. If set, the \"thirdPartyOk\"-method will return true.\n// - (7): The application allows for both functional- and third-party-cookies. If set, both methods above will return true.\n\n// The manager exposes a couple of methods that can be used trough-out the application to make sure we only use cookies\n// that the user has accepted:\n// - functionalOk(): Returns wether it is OK to store functional-cookies or not.\n// - thirdPartyOk(): Returns wether it is OK to store third-party-cookies or not.\n// - setLevel( level): Updates this.#cookieLevel, should be used in the cookie-notice. Emits an event on the globalObserver (core.cookieLevelChanged).\n// - setConfig(): Used to \"initiate\" the manager. Should be run early on application load so that we can catch if the application\n// should care about cookies at all.\n// - shouldShowNotice(): Returns wether the cookie-notice should be shown or not.\nclass CookieManager {\n #cookieLevel;\n #functionalCookie;\n #thirdPartyCookie;\n #globalObserver;\n\n // We have to initiate the cookie-level (let's set it to -1 since we're not sure if we care about cookies yet).\n // We also have to set the functional- and third-party-cookie-levels. Remember that we're using bitwise-operators\n // to check which level is OK.\n constructor() {\n this.#cookieLevel = -1;\n this.#functionalCookie = 2;\n this.#thirdPartyCookie = 4;\n this.#globalObserver = null;\n }\n\n // Used to make sure we're allowing all cookies if \"showCookieNotice\" is set to false in\n // (or missing from) the map-configuration. This method should only be run once.\n setConfig = (settings) => {\n const { showCookieNotice, globalObserver } = settings;\n // If \"showCookieNotice\" is set to true in the map-configuration we'll check if the user has\n // interacted with the cookie-notice earlier. (If they did, a cookie-level will be set in LS).\n if (showCookieNotice) {\n this.setLevel(this.#getStoredCookieLevel());\n this.#globalObserver = globalObserver;\n } else {\n // Otherwise we set the level to -1, stating that all cookies are allowed, and that the cookie-notice\n // shouldn't be shown.\n this.#cookieLevel = -1;\n }\n };\n\n // Updates the cookie-level (both internally and in the store). It also emits an event on the\n // globalObserver so that the components can re-render when the level is changed.\n setLevel = (level) => {\n this.#cookieLevel = level;\n this.#globalObserver &&\n this.#globalObserver.publish(\"core.cookieLevelChanged\", level);\n window.localStorage.setItem(\"cookieLevel\", this.#cookieLevel);\n };\n\n // Returns wether the cookie-notice should be shown or not.\n shouldShowNotice = () => {\n return this.#cookieLevelNotSet();\n };\n\n // Returns wether the cookie-level has been set yet or not.\n #cookieLevelNotSet = () => {\n return this.#cookieLevel === 0;\n };\n\n // Returns wether any cookies are allowed or not. Remember, if the cookie-level is set to -1\n // we don't care about cookies at all in this application. (This is set in the map-configuration).\n #allCookiesAllowed = () => {\n return this.#cookieLevel === -1;\n };\n\n // Returns potentially stored cookie-level from LS. If nothing is set in LS, we return 0 (stating that\n // the cookie-level has not been set yet).\n #getStoredCookieLevel = () => {\n const levelInStorage = window.localStorage.getItem(\"cookieLevel\");\n return levelInStorage ? parseInt(levelInStorage) : 0;\n };\n\n // Returns wether functional-cookies are OK to store or not.\n functionalOk = () => {\n // If the cookie-level is not set yet, we cannot store them.\n if (this.#cookieLevelNotSet()) {\n return false;\n }\n // If we don't care about cookies, we can do whatever we want.\n if (this.#allCookiesAllowed()) {\n return true;\n }\n // Otherwise we do a bitwise-comparison between the current cookie-level and a functional-\n // cookie-level. Remember that if both functional- and third-party-cookies are allowed (level 7)\n // this will return true, since 0111 & 0010 => 0010.\n return (\n (this.#cookieLevel & this.#functionalCookie) === this.#functionalCookie\n );\n };\n\n // Returns wether third-party-cookies are OK to store or not.\n thirdPartyOk = () => {\n // If the cookie-level is not set yet, we cannot store them.\n if (this.#cookieLevelNotSet()) {\n return false;\n }\n // If we don't care about cookies, we can do whatever we want.\n if (this.#allCookiesAllowed()) {\n return true;\n }\n // Otherwise we do a bitwise-comparison between the current cookie-level and a third-party-\n // cookie-level. Remember that if both functional- and third-party-cookies are allowed (level 7)\n // this will return true, since 0111 & 0101 => 0101.\n return (\n (this.#cookieLevel & this.#thirdPartyCookie) === this.#thirdPartyCookie\n );\n };\n}\n\n// Initiate the singleton. Note: it never gets exported from this module.\nconst CM = new CookieManager();\n// Setup the exports that allow us to modify certain aspects of the singleton-instance.\n// Usage: e.g. import { setLevel } from \"./Cookie\";\nexport const setConfig = (settings) => CM.setConfig(settings);\nexport const setLevel = (level) => CM.setLevel(level);\nexport const shouldShowNotice = () => CM.shouldShowNotice();\nexport const functionalOk = () => CM.functionalOk();\nexport const thirdPartyOk = () => CM.thirdPartyOk();\n","export function encodeCommas(string) {\n return !string ? string : string.replace(/,/g, \"%2C\");\n}\n\nexport function decodeCommas(string) {\n return !string ? string : string.replace(/%2C/g, \",\");\n}\n","import React from \"react\";\nimport DialogContentText from \"@material-ui/core/DialogContentText\";\n\nexport default function LegacyNonMarkdownRenderer(props) {\n const { text } = props;\n\n return typeof text === \"string\" ? (\n \n \n \n ) : (\n text\n );\n}\n","import React, { useState } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport rehypeRaw from \"rehype-raw\";\nimport gfm from \"remark-gfm\";\n\nimport Button from \"@material-ui/core/Button\";\nimport Dialog from \"@material-ui/core/Dialog\";\nimport DialogActions from \"@material-ui/core/DialogActions\";\nimport DialogContent from \"@material-ui/core/DialogContent\";\nimport DialogTitle from \"@material-ui/core/DialogTitle\";\nimport TextField from \"@material-ui/core/TextField\";\nimport useMediaQuery from \"@material-ui/core/useMediaQuery\";\nimport { useTheme } from \"@material-ui/core/styles\";\n\nimport LegacyNonMarkdownRenderer from \"./LegacyNonMarkdownRenderer\";\nimport { customComponentsForReactMarkdown } from \"utils/customComponentsForReactMarkdown\";\n\nexport default function ResponsiveDialog(props) {\n const theme = useTheme();\n const fullScreen = useMediaQuery(theme.breakpoints.down(\"xs\"));\n\n const {\n onAbort,\n onClose,\n open,\n options: {\n abortText,\n allowDangerousHtml, // ReactMarkdown disables HTML by default but we let the Admin decide\n buttonText,\n headerText,\n prompt,\n text,\n useLegacyNonMarkdownRenderer, // Admin can choose to pass-by the ReactMarkdown and just use dangerouslySetInnerHtml\n },\n } = props;\n\n // Will hold a return value for those Dialogs that are ment to be\n // used as prompt input fields.\n const [promptText, setPromptText] = useState(\"\");\n\n const rehypePlugins = allowDangerousHtml === true ? [rehypeRaw] : [];\n\n const handleAbort = () => {\n onAbort(promptText);\n };\n\n const handleClose = () => {\n onClose(promptText);\n };\n\n return (\n \n {headerText && (\n {headerText}\n )}\n \n {useLegacyNonMarkdownRenderer === true ? (\n \n ) : (\n \n )}\n\n {prompt && (\n {\n e.preventDefault();\n props.onClose(promptText);\n return false;\n }}\n >\n {\n setPromptText(e.target.value);\n }}\n margin=\"normal\"\n autoFocus={true}\n />\n \n )}\n \n \n \n {abortText && }\n \n \n );\n}\n","/**\n * HOW TO USE THIS HELPER\n * Import this helper wherever you want to use the get/set methods.\n * This helper is initiated once, on export, and we set the key name\n * once (in index.js), so you don't have to worry about the details.\n * Just get/set whatever you want.\n *\n * Please not however that THERE IS A TWIST HERE TO THE USUAL LOCALSTORAGE\n * behavior!\n *\n * A. This helper is map-specific. That means that ALL SETTINGS RELEATED TO A\n * MAPCONFIG WILL BE HELD IN ONE KEY/VALUE PAIR IN LOCALSTOREGE.\n * B. Because we only have one value to play with for all the settings, and\n * LocalStorage stores values as string, we utilized JSON.stringify and JSON.parse.\n *\n * === Example for map config 'map_1' ===\n * We can use this helper as follows.\n *\n * === Storing map-specific data ===\n * LocalStorageHelper.set(\"foobar\", [1,2,3]);\n *\n * This will create/modify the following in browser's LocalStorage:\n * map_options_map_1: \"{\\\"foobar\\\":[1,2,3]}\"\n * If there were any other keys (except \"foobar\") THEY WON'T BE TOUCHED!\n *\n * === Retrieving map-specific data ===\n * LocalStorageHelper.get(\"foobar\", \"default value\")\n *\n * This can do one of two things:\n * - if there was a key named \"foobar\" for current entry, we'll get the JSON.parsed results\n * - if there was no entry named \"foobar\", we'll get \"default value\" back\n */\nclass LocalStorageHelper {\n mapName = \"map_options_unknown_map\";\n /**\n * @summary We want each map to have its own settings in LS, so we use mapConfig's name\n * as a key for the LS property.\n * @description This will normally be called once, when the map is initiated. All subsequent\n * use (getting and setting values) will read this key's value.\n *\n * @param {string} [mapName=\"unknown_map\"]\n * @memberof LocalStorageHelper\n */\n setKeyName(mapName = \"unknown_map\") {\n this.mapName = `map_options_${mapName}`;\n }\n\n /**\n * @summary Get map-specific settings from LocalStorage for the given key, fallback to supplied default\n * if parsing not possible.\n *\n * @param {*} key\n * @param {*} [defaults={}]\n * @returns\n * @memberof\n */\n get(key, defaults = {}) {\n try {\n // Return a shallow merged objects with\n return {\n ...defaults, // …supplied defaults, that can be overwritten by…\n ...JSON.parse(window.localStorage.getItem(this.mapName))[\n key // …whatever exists in local storage for the specified key\n ],\n };\n } catch (error) {\n // If parsing failed, return defaults\n return defaults;\n }\n }\n /**\n * @summary Save any JSON-able value to a specified key in a local storage object specific to current map\n *\n * @param {*} key Name of the key inside the JSON object\n * @param {*} value Value that the key will be set to\n * @memberof\n */\n set(key, value) {\n window.localStorage.setItem(\n this.mapName, // Use a map-specific name as key for LocalStorage setting\n JSON.stringify({\n ...JSON.parse(window.localStorage.getItem(this.mapName)),\n [key]: value,\n })\n );\n }\n}\n\n// Export singleton instance\nexport default new LocalStorageHelper();\n","export default class LayerInfo {\n constructor(properties) {\n this.attribution = properties.attribution;\n this.caption = properties.caption;\n this.infoOwner = properties.infoOwner;\n this.infoText = properties.infoText;\n this.infoTitle = properties.infoTitle;\n this.infoUrl = properties.infoUrl;\n this.infoUrlText = properties.infoUrlText;\n this.infoVisible = properties.infoVisible;\n this.infoClickSortType = properties.infoClickSortType;\n this.infoClickSortDesc = properties.infoClickSortDesc;\n this.infoClickSortProperty = properties.infoClickSortProperty;\n this.information = properties.information;\n this.legend = properties.legend;\n this.legendIcon = properties.legendIcon;\n this.searchDisplayName = properties.searchDisplayName;\n this.searchShortDisplayName = properties.searchShortDisplayName;\n this.searchGeometryField = properties.searchGeometryField;\n this.searchOutputFormat = properties.searchOutputFormat;\n this.searchPropertyName = properties.searchPropertyName;\n this.searchUrl = properties.searchUrl;\n this.layerType = properties.layerType;\n this.hideExpandArrow = properties.hideExpandArrow;\n }\n}\n","/**\n * Performs a deep merge of objects and returns new object. Does not modify\n * objects (immutable) and merges arrays via concatenation.\n *\n * @param {...object} objects - Objects to merge\n * @returns {object} New object with merged key/values\n */\nexport function deepMerge(...objects) {\n const isObject = (obj) => obj && typeof obj === \"object\";\n\n return objects.reduce((prev, obj) => {\n Object.keys(obj).forEach((key) => {\n const pVal = prev[key];\n const oVal = obj[key];\n\n if (Array.isArray(pVal) && Array.isArray(oVal)) {\n prev[key] = pVal.concat(...oVal);\n } else if (isObject(pVal) && isObject(oVal)) {\n prev[key] = deepMerge(pVal, oVal);\n } else {\n prev[key] = oVal;\n }\n });\n\n return prev;\n }, {});\n}\n","/**\n * README\n * The purpose of this components library is to consolidate the mapping\n * between Markdown and MUI Components.\n *\n * This library has one main export, customComponentsForReactMarkdown, which\n * is an object formatted accordingly to the requirements set in react-markdown.\n *\n * customComponentsForReactMarkdown makes use of other styled components defined\n * in this library. To make it possible for other implementations to override\n * customComponentsForReactMarkdown even further, we export all the other styled\n * components as well.\n *\n * To use in your code with the default styled components, you basically:\n *\n * ```\n * import { customComponentsForReactMarkdown } from \"utils/customComponentsForReactMarkdown\";\n * \n * ```\n * To override a specific part, use the spread operator on the exported object:\n *\n * ```\n * import { customComponentsForReactMarkdown, Paragraph } from \"utils/customComponentsForReactMarkdown\";\n * const evenMoreComponentsComponents = {\n * ...customComponentsForReactMarkdown, // spread the imported\n * p: (props) => {props.children} // override definition of P\n * };\n * \n * ```\n *\n * For reference and to see which other components can be provided,\n * please refer to https://github.com/remarkjs/react-markdown#appendix-b-components.\n */\n\nimport {\n Divider,\n Link,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Typography,\n} from \"@material-ui/core\";\n\nimport { styled } from \"@material-ui/core/styles\";\n\nexport const Paragraph = styled(Typography)(() => ({\n marginBottom: \"1.1rem\",\n}));\n\n// Styled Table Row Component, makes every second row in a Table colored\nexport const StyledTableRow = styled(TableRow)(({ theme }) => ({\n \"&:nth-of-type(even)\": {\n backgroundColor: theme.palette.action.hover,\n },\n}));\n\nexport const StyledTableContainer = styled(TableContainer)(() => ({\n marginBottom: \"1.1rem\",\n}));\n\nexport const StyledPaper = styled(Paper)(({ theme }) => ({\n padding: theme.spacing(1),\n marginBottom: \"1.1rem\",\n backgroundColor: theme.palette.background.default,\n \"& p\": {\n marginBottom: \"0\",\n },\n}));\n\nexport const StyledTypography = styled(Typography)(({ variant }) => {\n return {\n ...(variant === \"h1\" && {\n fontSize: \"1.6rem\",\n fontWeight: \"500\",\n marginBottom: \"0.375rem\",\n }),\n ...(variant === \"h2\" && {\n fontSize: \"1.4rem\",\n fontWeight: \"500\",\n marginBottom: \"0.018rem\",\n }),\n ...(variant === \"h3\" && {\n fontSize: \"1.2rem\",\n fontWeight: \"500\",\n }),\n ...(variant === \"h4\" && {\n fontSize: \"1rem\",\n fontWeight: \"500\",\n }),\n ...(variant === \"h5\" && {\n fontSize: \"0.875rem\",\n fontWeight: \"500\",\n }),\n ...(variant === \"h6\" && {\n fontSize: \"0.875rem\",\n fontWeight: \"400\",\n fontStyle: \"italic\",\n }),\n };\n});\n\nexport const MarkdownHeaderComponent = ({ level, children }) => {\n return {children};\n};\n\nexport const MarkdownTableCellComponent = ({\n children,\n style,\n isHeader,\n className,\n}) => {\n return (\n \n {children}\n \n );\n};\n\n// Here we define the components used by ReactMarkdown, see https://github.com/remarkjs/react-markdown#appendix-b-components\nexport const customComponentsForReactMarkdown = {\n p: ({ children }) => {\n return !children ? null : {children};\n },\n hr: () => ,\n a: ({ children, href, title }) => {\n return children ? (\n \n {children}\n \n ) : null;\n },\n h1: MarkdownHeaderComponent,\n h2: MarkdownHeaderComponent,\n h3: MarkdownHeaderComponent,\n h4: MarkdownHeaderComponent,\n h5: MarkdownHeaderComponent,\n h6: MarkdownHeaderComponent,\n table: ({ children, className, style }) => {\n return (\n \n \n {children}\n
\n
\n );\n },\n thead: ({ children }) => {\n return {children};\n },\n tbody: ({ children }) => {\n return {children};\n },\n tr: ({ children }) => {\n return {children};\n },\n td: MarkdownTableCellComponent,\n th: MarkdownTableCellComponent,\n style: ({ children }) => {\n return ;\n },\n div: ({ children, className, style }) => {\n return (\n
\n {children}\n
\n );\n },\n blockquote: (props) => {\n return {props.children};\n },\n};\n","import { Stroke, Style, Circle, Fill, Text, Icon } from \"ol/style\";\nimport { Point } from \"ol/geom.js\";\n\nexport default class FeatureStyle {\n #options;\n #defaultDisplayStyleSettings;\n #defaultSelectionStyleSettings;\n #defaultHighlightStyleSettings;\n #enableLabelOnHighlight;\n\n constructor(options) {\n this.#options = options;\n this.#enableLabelOnHighlight = options.enableLabelOnHighlight ?? true;\n this.#defaultDisplayStyleSettings = this.#getDefaultDisplayStyleSettings();\n this.#defaultSelectionStyleSettings =\n this.#getDefaultSelectionStyleSettings();\n this.#defaultHighlightStyleSettings =\n this.#getDefaultHighlightStyleSettings();\n }\n\n #getDefaultDisplayStyleSettings = () => {\n const fillColor = this.#options.displayFillColor ?? \"rgba(74,144,226,0.15)\";\n const strokeColor =\n this.#options.displayStrokeColor ?? \"rgba(74,144,226,0.4)\";\n\n return {\n strokeColor: strokeColor,\n fillColor: fillColor,\n };\n };\n\n #getDefaultSelectionStyleSettings = () => {\n const strokeColor =\n this.#options.selectionStrokeColor ?? \"rgba(74,144,226,0.8)\";\n const fillColor =\n this.#options.selectionFillColor ?? \"rgba(74,144,226,0.3)\";\n const textFillColor =\n this.#options.selectionTextFill ?? \"rgba(63,122,190,1)\";\n const textStrokeColor =\n this.#options.selectionTextStroke ?? \"rgba(255,255,255,1)\";\n const fontSize = 12;\n\n return {\n strokeColor: strokeColor,\n fillColor: fillColor,\n textFillColor: textFillColor,\n textStrokeColor: textStrokeColor,\n fontSize: fontSize,\n };\n };\n\n #getDefaultHighlightStyleSettings = () => {\n const strokeColor =\n this.#options.highlightStrokeColor ?? \"rgba(245,166,35,0.8)\";\n const fillColor = this.#options.highlightFillColor ?? \"rgba(245,166,35,0)\";\n const textFillColor =\n this.#options.highlightTextFill ?? \"rgba(214,143,28,1)\";\n const textStrokeColor =\n this.#options.highlightTextStroke ?? \"rgba(255,255,255,1)\";\n const fontSize = 15;\n\n return {\n strokeColor: strokeColor,\n fillColor: fillColor,\n textFillColor: textFillColor,\n textStrokeColor: textStrokeColor,\n fontSize: fontSize,\n };\n };\n\n getFeatureStyle = (feature, type) => {\n // Helper for the cumbersome type check: scale and anchor values, when unset in admin,\n // will consist of empty strings, perfectly legal but unusable in our case. So we must ensure\n // that the value we get can be parsed to a finite number, else fallback to something else.\n const isValidNumber = (n) => Number.isFinite(parseInt(n));\n\n const { scale, markerImg } = this.#options;\n const anchor = this.#options.anchor ?? [];\n\n const isPoint = feature?.getGeometry() instanceof Point;\n const textAlign = isPoint ? \"left\" : \"center\";\n const offsetY = isPoint ? -50 : -10;\n\n const settings =\n !type || type === \"selection\"\n ? this.#defaultSelectionStyleSettings\n : this.#defaultHighlightStyleSettings;\n\n // Create new color to be used for icons: start with fill color but make sure that it's\n // _not_ transparent by setting the alpha channel value to 0.8. Unfortunately Safari doesn't\n // support lookbehind, so we must do it this way. Basically we do:\n // \"rgba(x,y,z,ź)\" => \"rgba(x,y,z,0.8)\"\n const iconColor = settings.fillColor.replace(/,[\\d.]*\\)/, \",0.8)\");\n\n // Default SVG icon to be used as marker. Placed here so we can grab the current style's fill color.\n const svgString = ``;\n const defaultMarker = `data:image/svg+xml;base64,${window.btoa(svgString)}`; // We need base64 for kml-exports to work.\n // For the 'highlight' style, we want the marker icon to be 30% larger than other styles\n const multiplier = type === \"highlight\" ? 1.3 : 1;\n\n return new Style({\n fill: new Fill({\n color: settings.fillColor,\n }),\n stroke: new Stroke({\n color: settings.strokeColor,\n width: 2,\n }),\n image: new Icon({\n anchor: [\n isValidNumber(anchor[0]) ? anchor[0] : 0.5,\n isValidNumber(anchor[1]) ? anchor[1] : 1,\n ],\n scale: (isValidNumber(scale) ? scale : 1) * multiplier,\n src: markerImg?.length > 0 ? markerImg : defaultMarker,\n }),\n ...(this.#enableLabelOnHighlight && {\n text: new Text({\n textAlign: textAlign,\n textBaseline: \"middle\",\n font: `${settings.fontSize}pt \"Roboto\", sans-serif`,\n fill: new Fill({\n color: settings.textFillColor,\n }),\n text: feature.featureTitle,\n overflow: true,\n stroke: new Stroke({\n color: settings.textStrokeColor,\n width: 3,\n }),\n offsetX: 0,\n offsetY: offsetY,\n rotation: 0,\n scale: 1,\n }),\n }),\n });\n };\n\n getDefaultSearchResultStyle = (feature) => {\n const settings = this.#defaultSelectionStyleSettings;\n\n const fill = new Fill({\n color: this.#defaultDisplayStyleSettings.fillColor,\n });\n\n const stroke = new Stroke({\n color: this.#defaultDisplayStyleSettings.strokeColor,\n width: 2,\n });\n return new Style({\n fill: fill,\n stroke: stroke,\n image: new Circle({\n fill: fill,\n stroke: stroke,\n radius: 10,\n }),\n ...(this.#enableLabelOnHighlight && {\n text: new Text({\n textAlign: \"center\",\n textBaseline: \"middle\",\n font: `10pt \"Roboto\", sans-serif`,\n fill: new Fill({\n color: settings.textFillColor,\n }),\n text: feature.shortFeatureTitle,\n overflow: true,\n stroke: new Stroke({\n color: settings.textStrokeColor,\n width: 3,\n }),\n offsetX: 0,\n offsetY: 0,\n rotation: 0,\n scale: 1,\n }),\n }),\n });\n };\n}\n","import GeoJSON from \"ol/format/GeoJSON\";\nimport TileLayer from \"ol/layer/Tile\";\nimport ImageLayer from \"ol/layer/Image\";\nimport WMSGetFeatureInfo from \"ol/format/WMSGetFeatureInfo\";\nimport { hfetch } from \"utils/FetchWrapper\";\n\nfunction query(map, layer, evt) {\n const coordinate = evt.coordinate;\n const resolution = map.getView().getResolution();\n const currentZoom = map.getView().getZoom();\n const referenceSystem = map.getView().getProjection().getCode();\n let subLayersToQuery = [];\n\n // Query only those layers that a) have a layersInfo property, and\n // b) are currently displayed. Please note that checking for visibility\n // is not enough, we must also respect the min/max zoom level settings, #836.\n if (\n layer.layersInfo &&\n layer.getMinZoom() <= currentZoom &&\n currentZoom <= layer.getMaxZoom()\n ) {\n const subLayers = Object.values(layer.layersInfo);\n // First we must get the string containing the active sub-layers in this\n // group-layer.\n const visibleSubLayersString =\n layer.getSource().getParams()[\"LAYERS\"] || \"\";\n // The string will contain the layers, separated with a comma. We'll split\n // the string to get an array.\n const visibleSubLayersArray = visibleSubLayersString.split(\",\");\n // Then we'll create a Set from the array. The Set will allow us to\n // check wether a sub-layer should be queried or not in a simple manner.\n const visibleSubLayersSet = new Set(visibleSubLayersArray);\n // Then we'll loop trough the subLayers that should be queried, and make sure\n // to remove layers that are 1. Not queryable, or 2. Not visible.\n subLayersToQuery = subLayers\n .filter(\n (subLayer) =>\n subLayer.queryable === true && visibleSubLayersSet.has(subLayer.id)\n ) // QUERY_LAYERS must not include anything that's not in LAYERS, see https://github.com/hajkmap/Hajk/issues/211\n .map((queryableSubLayer) => {\n return queryableSubLayer.id;\n });\n }\n\n if (subLayersToQuery.length > 0) {\n let params = {\n FEATURE_COUNT: 100,\n INFO_FORMAT: layer.getSource().getParams().INFO_FORMAT,\n QUERY_LAYERS: subLayersToQuery.join(\",\"),\n };\n\n // See #852. Without this, it's almost impossible to get a result from QGIS Server.\n // TODO: This could be expanded and made an admin setting - I'm not sure that 50 px\n // will work for everyone.\n // The WITH_GEOMETRY is necessary to make QGIS Server send back the feature's geometry\n // in the response.\n // See: https://docs.qgis.org/3.16/en/docs/server_manual/services.html#wms-withgeometry.\n if (layer.getSource().serverType_ === \"qgis\") {\n params = {\n ...params,\n FI_POINT_TOLERANCE: 50,\n FI_LINE_TOLERANCE: 50,\n FI_POLYGON_TOLERANCE: 50,\n WITH_GEOMETRY: true,\n };\n }\n\n const url = layer\n .getSource()\n .getFeatureInfoUrl(coordinate, resolution, referenceSystem, params);\n return hfetch(url);\n } else {\n return false;\n }\n}\n\nfunction getSortParser(sortType) {\n if (sortType === \"number\") {\n return parseInt;\n } else if (sortType === \"string\") {\n return (a) => {\n return a ? a.trim() : \"\";\n };\n } else {\n return (a) => {\n return a;\n };\n }\n}\n\nfunction getSortMethod(options) {\n if (options.type === \"number\") {\n return (a, b) => {\n return (\n (options.desc ? -1 : 1) *\n (options.parser(a.getProperties()[options.prop]) -\n options.parser(b.getProperties()[options.prop]))\n );\n };\n } else {\n return (a, b) => {\n return (\n (options.desc ? -1 : 1) *\n options\n .parser(a.getProperties()[options.prop])\n .localeCompare(options.parser(b.getProperties()[options.prop]))\n );\n };\n }\n}\n\nfunction sortFeatures(layer, features) {\n if (!features || features.length <= 1) {\n return;\n }\n const layerInfo = layer.getProperties().layerInfo;\n if (!layerInfo.infoClickSortProperty) {\n return;\n }\n\n const sortType = layerInfo.infoClickSortType || \"string\";\n const sortOptions = {\n type: sortType,\n desc: layerInfo.infoClickSortDesc ?? true,\n prop: layerInfo.infoClickSortProperty.trim(),\n parser: getSortParser(sortType),\n };\n\n features.sort(getSortMethod(sortOptions));\n}\n\n// Function similar to GeoJSON().readFeatures, with the subtle difference that we set an\n// id if it is missing on the parsed feature. The missing id occurs when parsing features from\n// arcGis for some reason.\nfunction readJsonFeatures(jsonData, layerProjection, viewProjection) {\n const parser = new GeoJSON();\n\n // If the response from WMS service contains a CRS (GeoServer), the feature parser\n // will use it be default to determine the features' projection.\n // However, if it's empty (QGIS Server), we must tell the parser which projection\n // should be used for the features and which projection our View is in.\n const parserOptions = jsonData.crs\n ? {}\n : {\n dataProjection: layerProjection,\n featureProjection: viewProjection,\n };\n\n const parsedFeatures = [];\n // jsonData will always be a featureCollection, hence we must map over all\n // features in the collection.\n jsonData.features.map((jsonFeature) => {\n // Lets parse the feature...\n const parsedJsonFeature = parser.readFeature(jsonFeature, parserOptions);\n // And check if we have an id...\n if (!parsedJsonFeature.getId()) {\n // If we don't, we set the id to the layerName, and a random id\n // so that featureInfo knows when we clicked a new feature in\n // the same layer.\n parsedJsonFeature.setId(\n `${jsonFeature.layerName}.${parsedJsonFeature.ol_uid}`\n );\n }\n // Push the feature to the array of parsed features\n return parsedFeatures.push(parsedJsonFeature);\n });\n // And return it\n return parsedFeatures;\n}\n\nfunction getFeaturesFromJson(response, jsonData) {\n const layerProjection = response.layer.getSource().getProjection();\n const viewProjection = response.viewProjection;\n const parsed = readJsonFeatures(jsonData, layerProjection, viewProjection);\n if (parsed && parsed.length > 0) {\n parsed.forEach((f) => {\n f.layer = response.layer;\n });\n sortFeatures(response.layer, parsed);\n return parsed;\n } else {\n return [];\n }\n}\n\nfunction getFeaturesFromGml(response, text) {\n let wmsGetFeatureInfo = new WMSGetFeatureInfo();\n //let doc = new DOMParser().parseFromString(text, \"text/xml\");\n let parsed = wmsGetFeatureInfo.readFeatures(text);\n if (parsed && parsed.length > 0) {\n parsed.forEach((f) => {\n f.layer = response.layer;\n });\n sortFeatures(response.layer, parsed);\n return parsed;\n } else {\n return [];\n }\n}\n\n/**\n * Query the map for features when the user clicks the map.\n * The approach is to stack all the queryable WMS-requests and return a promise with a pointer to the referring layer.\n * When the requests are done the features are parsed and given the original layer reference.\n * Vector layers are added with the features at pixel method and given the original layer reference as well.\n */\nexport function handleClick(evt, map, callback) {\n document.querySelector(\"body\").style.cursor = \"progress\";\n const promises = [];\n const viewProjection = map.getView().getProjection().getCode();\n map\n .getLayers()\n .getArray()\n // Now we have an array with all layers added to our map, let's narrow down a bit\n .filter(\n (layer) =>\n // Only certain layer types are relevant\n (layer instanceof TileLayer || layer instanceof ImageLayer) &&\n // And only if they're currently visible (no reason to query hidden layers)\n layer.get(\"visible\") === true\n )\n // For each layer that's left in the array\n .forEach((layer) => {\n // Query the layer, will return a Promise (Fetch call)\n // or false, if there was no need to fetch.\n const promise = query(map, layer, evt);\n // If query() didn't return false, we have a real Promise\n if (promise !== false) {\n promises.push(\n promise.then((response) => {\n return {\n layer: layer,\n requestResponse: response,\n viewProjection: viewProjection,\n };\n })\n );\n }\n });\n\n Promise.all(promises).then((responses) => {\n const featurePromises = [];\n const features = [];\n responses.forEach((response) => {\n const type = response.requestResponse.headers\n .get(\"Content-Type\")\n .split(\";\")[0];\n switch (type) {\n case \"application/geojson\":\n case \"application/json\":\n featurePromises.push(\n response.requestResponse\n .json()\n .then((jsonData) => {\n if (\n jsonData !== undefined &&\n jsonData &&\n jsonData.features &&\n jsonData.features.length > 0\n ) {\n features.push(...getFeaturesFromJson(response, jsonData));\n }\n })\n .catch((err) => {\n console.error(\n \"GetFeatureInfo couldn't retrieve correct data for the clicked object.\",\n err\n );\n })\n );\n break;\n case \"text/xml\":\n case \"application/vnd.ogc.gml\": {\n featurePromises.push(\n response.requestResponse\n .text()\n .then((text) => {\n features.push(...getFeaturesFromGml(response, text));\n })\n .catch((err) => {\n console.error(\n \"GetFeatureInfo couldn't retrieve correct data for the clicked object. \"\n );\n })\n );\n break;\n }\n default:\n break;\n }\n });\n\n Promise.all(featurePromises).then(() => {\n map.forEachFeatureAtPixel(\n evt.pixel,\n (feature, layer) => {\n if (\n layer &&\n (layer.get(\"queryable\") === true ||\n layer.get(\"type\") === \"searchResultLayer\")\n ) {\n feature.layer = layer;\n features.push(feature);\n }\n },\n {\n hitTolerance: 10,\n }\n );\n\n document.querySelector(\"body\").style.cursor = \"initial\";\n callback({\n features: features,\n evt: evt,\n });\n });\n });\n}\n\nexport function bindMapClickEvent(map, callback) {\n // We must use a custom \"clickLock\" mechanism, as opposed to the\n // previous attempts (map.getInteraction().getArray() and looking\n // for certain values in each Interaction's constructor.name).\n //\n // The previous method (checking prototype's name) was\n // unreliable as Webpack uglifies the class names,\n // hence the constructors we're comparing against\n // don't have their usual names.\n //\n // Please see issue #591 for more info.\n //\n // The 'clickLock' Set is added to Map in appModel.createMap(),\n // so by the time we bind this handler, we can be sure that\n // map.clickLock already exists.\n\n // Bind the \"singleclick\" event of OL Map\n map.on(\"singleclick\", (evt) => {\n // Handle click only if there no plugin wants to lock\n // the click interaction currently\n map.clickLock.size === 0 && handleClick(evt, map, callback);\n });\n}\n","import React from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport rehypeRaw from \"rehype-raw\";\nimport gfm from \"remark-gfm\";\nimport FeaturePropFilters from \"./FeaturePropsFilters\";\n\nimport {\n customComponentsForReactMarkdown,\n Paragraph,\n} from \"utils/customComponentsForReactMarkdown\";\n\nexport default class FeaturePropsParsing {\n constructor(settings) {\n this.globalObserver = settings.globalObserver;\n this.options = settings.options;\n\n // Two arrays that will hold pending promises and their resolved values, respectively.\n this.pendingPromises = [];\n this.resolvedPromisesWithComponents = [];\n\n this.markdown = null;\n this.properties = null; // Will hold the property values from the clicked feature\n\n // Default to true to ensure backwards compatibility with old configs that predominately use HTML\n this.allowDangerousHtml = this.options.allowDangerousHtml ?? true;\n\n // Here we define the components used by ReactMarkdown, see https://github.com/remarkjs/react-markdown#appendix-b-components\n // Note that we import customComponentsForReactMarkdown from our shared library, spread those\n // objects and finally override the definition of \"p\", as it differs in this case (we want to\n // import external components in FeatureInfo, while the normal \"p\" implementation just maps P to\n // a MUI Typography component).\n this.components = {\n ...customComponentsForReactMarkdown,\n p: ({ children }) => {\n if (!children) {\n return null;\n }\n\n return (\n \n {children.map((child, index) => {\n // Initiate a holder for external components. If a regex matches below,\n // this variable will be filled with correct value.\n let externalComponent = null;\n\n if (child && typeof child === \"string\") {\n // This helper is passed to ReactMarkdown at render. At this stage,\n // we expect that the only remaining {stuff} will contain digits, and\n // that those numbers represent element index in this.resolvedPromisesWithComponents.\n // Let's try to match the regex for a number within curly brackets.\n const match = child.match(/{(\\d+)}/);\n if (\n match &&\n this.resolvedPromisesWithComponents.hasOwnProperty(match[1])\n ) {\n // If matched, replace the placeholder with the corresponding component.\n externalComponent =\n this.resolvedPromisesWithComponents[match[1]];\n }\n }\n // If externalComponent isn't null anymore, render it. Else, just render the children.\n return (\n \n {externalComponent || child}\n \n );\n })}\n \n );\n },\n };\n }\n\n #valueFromJson = (str) => {\n if (typeof str !== \"string\") return false;\n const jsonStart = /^\\[|^\\{(?!\\{)/;\n const jsonEnds = {\n \"[\": /]$/,\n \"{\": /}$/,\n };\n const start = str.match(jsonStart);\n const jsonLike = start && jsonEnds[start[0]].test(str);\n var result = false;\n\n if (jsonLike) {\n try {\n result = JSON.parse(str);\n } catch (ex) {\n result = false;\n }\n } else {\n result = false;\n }\n\n return result;\n };\n\n #getPropertyValueForPlaceholder = (placeholder) => {\n // First strip the curly brackets, e.g. {foobar} -> foobar\n placeholder = placeholder.substring(1, placeholder.length - 1);\n\n // Placeholders to be fetch from external components will include \"@@\", and\n // they need to be treated differently from \"normal\" placeholders (sans @@).\n if (placeholder.includes(\"@@\") && !placeholder.includes(\"@@@\")) {\n // Extract the property and plugins names from the placeholder.\n const [propertyName, pluginName] = placeholder.split(\"@@\");\n\n // Grab the actual value of this placeholder from the properties collections\n const propertyValue = this.properties[propertyName];\n\n // If they key was not found in the properties object, or the value is empty, we can't go on.\n if (\n propertyValue === undefined ||\n propertyValue === null ||\n propertyValue.trim() === \"\"\n ) {\n return \"\";\n } else {\n // Now we know 1) property value of the placeholder and 2) which plugin will take care of it.\n // Next we want to call #fetchExternal, that immediately returns a Promise, and push that\n // promise into an array of promises. Later on, we will want to get the value from this\n // fulfilled promise, so one key aspect here is to keep track of which promise value should\n // go where. We will do it the easy way: when the promise is pushed into an array, push\n // returns the new array length. That means that this recently pushed element will have\n // an index of n-1. We use this fact by returning a string, \"{n-1}\" back to the Markdown string.\n // That way, in the final step of Markdown parsing, we will be able to replace each \"{n-1}\" with\n // the contents of the correct element in the resolved promises array.\n\n return `{${\n this.pendingPromises.push(\n this.#fetchExternal(propertyValue, pluginName)\n ) - 1\n }}`;\n }\n } else if (placeholder.includes(\"|\")) {\n return FeaturePropFilters.applyFilters(this.properties, placeholder);\n }\n // Just a \"normal\" placeholder, e.g. {foobar}\n else {\n // Attempt to grab the actual value from the Properties collection, if not found, fallback to empty string.\n // Note that we must replace equal sign in property value, else we'd run into trouble, see #812.\n\n return (\n // What you see on the next line is what we call \"hängslen och livrem\" in Sweden.\n // (The truth is it's all needed - this.properties may not be an Array, it may not have a key named\n // \"placeholder\", but if it does, we can't be sure that it will have the replace() method (as only Strings have it).)\n this.properties?.[placeholder]?.replace?.(/=/g, \"&equal;\") || // If replace() exists, it's a string, so we can revert our equal signs.\n this.properties[placeholder] || // If not a string, return the value as-is…\n \"\" // …unless it's undefined - in that case, return an empty string.\n );\n }\n };\n\n #fetchExternal = (propertyValue, pluginName) => {\n // If there are listeners for the current plugin that we parsed out here…\n if (\n this.globalObserver.getListeners(`core.info-click-${pluginName}`).length >\n 0\n ) {\n return new Promise((resolve, reject) => {\n // …let's return a Promise that will publish an event to the\n // requested plugin. The listening plugin will use the payload,\n // together with resolve/reject to fulfill the Promise.\n this.globalObserver.publish(`core.info-click-${pluginName}`, {\n payload: propertyValue,\n resolve,\n reject,\n });\n });\n } else {\n return null;\n }\n };\n\n /**\n * @summary The evaluator helper used in the final stage of markdown string\n * parsing. Extracts tags and either keeps the content (if value evaluates)\n * to true, or removes it from the markdown string.\n *\n * @param {*} args\n * @returns {string} Value inside the condition (if evaluated to true), or an empty string.\n */\n #conditionalReplacer = (...args) => {\n // Extract the regex named capture groups, they will be the last argument\n // when .replace() calls this helper.\n // Expect matched to contain 'condition', 'attributes' and 'content'.\n const matched = args[args.length - 1];\n\n // Do different things, depending on 'condition'\n switch (matched.condition) {\n case \"if\":\n // Append a new line to the content that (perhaps)\n // will be returned. If we return a content, we must\n // ensure that new line is added, because we stripped\n // all ending new lines (after ) in the regex.\n matched.content += \"\\n\";\n\n // Handle or \n if (matched.attributes?.includes(\"=\")) {\n // Turn \"FOO=\\\"BAR\\\"\" into k = \"FOO\" and v = \"BAR\"\n let [k, v] = matched.attributes\n .split(\"=\") // Create an array\n .map((e) => e.replaceAll('\"', \"\").trim()); // Remove double quotes and whitespace\n\n // Using truthy equal below: we want 2 and \"2\" to be seen as equal.\n // eslint-disable-next-line eqeqeq\n if (k == v) {\n return matched.content;\n } else {\n return \"\";\n }\n }\n // Handle - if it exits, evaluate to true and show content\n else if (matched.attributes?.trim().length > 0) {\n return matched.content;\n }\n // Handle (i.e. do not render because the attribute to evaluate is falsy)\n else {\n return \"\";\n }\n // For any other condition, leave as-is (could be HTML tag)\n default:\n return args[0];\n }\n };\n\n /**\n * @summary Ensure that the href part in Markdown links is well-formatted\n * @description Href in Markdown should be UTF8 formatted and have whitespace\n * escaped (with %20). The easiest way to ensure proper formatting is using the\n * URL object. But the constructor of URL will crash if the string provided is\n * not a proper path (e.g. lacks the protocol part). So we use try-catch to\n * catch such occurrences, and in those cases, we return the anchor pretty much unchanged.\n *\n * @param {*} args\n * @returns\n */\n #markdownHrefEncoder = (...args) => {\n // The named capture groups will be the last parameter\n const matched = args[args.length - 1];\n\n // Anchor text and title are simple\n const text = matched.text;\n const title = matched.title ? \" \" + matched.title : \"\";\n\n // Anchor href will require some more work.\n let href = matched.href;\n\n try {\n // Try creating a new URL from the matched href.\n // Invoking new URL will escape any special characters and ensure\n // that we provide a well-formatted URL to the MarkDown.\n href = new URL(href);\n } catch (error) {\n // If the URL creation failed for some reason (e.g. if a.href was empty,\n // or if it was a relative path), fall back to using the provided\n // string as-is, but remember to remove the leading and closing parentheses\n // that our regex included in the match and encode the URL (i.e. still\n // transform 'dir/file åäö.pdf' to 'dir/file%20%C3%A5%C3%A4%C3%B6.pdf').\n href = encodeURI(href);\n }\n\n // Prepare a nice MD Anchor string\n const r = `[${text}](${href}${title})`;\n return r;\n };\n\n /**\n * Converts a JSON-string of properties into a properties object\n * @param {str} properties\n * @returns {object}\n */\n extractPropertiesFromJson = (properties) => {\n Object.keys(properties).forEach((property) => {\n var jsonData = this.#valueFromJson(properties[property]);\n if (jsonData) {\n delete properties[property];\n properties = { ...properties, ...jsonData };\n }\n });\n return properties;\n };\n\n setMarkdownAndProperties({ markdown, properties }) {\n this.markdown = markdown;\n this.properties = properties;\n return this;\n }\n\n /**\n * @summary Use Markdown from settings, apply conditional rendering and\n * values from properties, and return a React component.\n *\n * @description There are three things going on here:\n * 1. The markdown is used as a template, anything between { and } gets replaced\n * with the real value from properties object, or is left empty.\n * 2. Next we apply conditional rendering, where conditions are between {{ and }} while\n * content is between {{condition}} and {{/condition}}.\n * Currently, if-condition is the only one supported, but more might become available.\n * Depending on the condition value, replacing can occur within our markdown string.\n * 3. The final markdown string is passed to the ReactMarkdown component.\n *\n * @param {str} markdown\n * @param {object} properties\n * @returns {object} ReactMarkdown component\n */\n mergeFeaturePropsWithMarkdown = async () => {\n if (this.markdown && typeof this.markdown === \"string\") {\n // this.markdown is a string that contains placeholders for our future values.\n // The placeholders are surrounded by curly brackets ({ & }).\n // The regex below will match all placeholders.\n // The loop below extracts all placeholders and replaces them with actual values\n // current feature's property collection.\n // Match any word character, range of unicode characters (åäö etc), @ sign, dash or dot\n (this.markdown.match(/{[\\s\\w\\u00C0-\\u00ff@\\-|,'.():]+}/g) || []).forEach(\n (placeholder) => {\n // placeholder is a string, e.g. \"{intern_url_1@@documenthandler}\" or \"{foobar}\"\n // Let's replace all occurrences of the placeholder like this:\n // {foobar} -> Some nice FoobarValue\n // {intern_url_1@@documenthandler} -> {n} // n is element index in the array that will hold Promises from external components\n this.markdown = this.markdown.replace(\n placeholder,\n this.#getPropertyValueForPlaceholder(placeholder)\n );\n }\n );\n\n // this.markdown will now contain actual values instead of properties, OR\n // references to elements in the this.resolvedPromises array. The latter will\n // be the only remaining occurrences of numbers surrounded by curly brackets.\n\n // Next step is to find all \"conditional tags\" (i.e. {{if foo=\"bar\"}}baz{{/if}})\n // and apply the replacer function on all matches.\n // The regex string below does the following:\n // Split each match into 3 named capture groups:\n // - \"condition\": the word between {{ and whitespace, \"if\" in this example\n // - \"attributes\": whatever follows the condition, until we see a }}, 'foo=\"bar\"'\n // - \"content\": anything after }} but before {{/ and whatever was the result in group one, \"baz\"\n // Note that the match will include one line ending. That's because _if_ we find a match\n // and will remove it, we must remove the line ending too, otherwise we would break the Markdown\n // formatting if only certain strings were to be removed, but all line endings would remain.\n this.markdown = this.markdown.replace(\n /{{(?\\w+)[\\s/]?(?[^}}]+)?}}(?[^{{]+)?(?:{{\\/\\1}}\\n?)/gi,\n this.#conditionalReplacer\n );\n\n // Special precautious must be taken to accommodate white space in Markdown links. We can\n // of course force our Hajk admins to write correctly formatted links (with URL encoded spaces),\n // but many times we can not control the URL if it comes from outside source. E.g. imagine this\n // infoclick setup:\n // [{anchorText}]({anchorLink})\n // Depending on values in the database, this can end up as something like this:\n // [This is a link](https://www.example.com/Some PDF file we link to.pdf)\n // This will not render correctly, only \"https://www.example.com/Some\" will become the\n // href part of the anchor. What we want instead is our MarkDown to contain:\n // [This is a link](https://www.example.com/Some%20PDF%20file%20we%20link%20to.pdf)\n // The following regex does just that.\n this.markdown = this.markdown.replace(\n /\\[(?[^[]+)\\]\\((?[^\")]+)(?\".*\")?\\)/gm,\n this.#markdownHrefEncoder\n );\n\n // Back in #getPropertyValueForPlaceholder we encode all equal signs (\"=\") as \"&equal;\",\n // to ensure we don't run into the issue described in #812 when we do the conditional check.\n // Now is a good time to revert that encoding back into an equal sign.\n this.markdown = this.markdown.replace(/&equal;/g, \"=\");\n\n // The final step is to await for all promises that might exist (if we fetch from\n // external components) to fulfill. We can't render before that!\n this.resolvedPromisesWithComponents = await Promise.all(\n this.pendingPromises\n );\n\n // If admin wants to allow HTML in Markdown, add rehypeRaw plugin.\n // Note that the gfm plugin is always added: it gives access to Table syntax.\n const rehypePlugins = this.allowDangerousHtml ? [rehypeRaw] : [];\n\n // Now, when promises are fulfilled, we can render. One of the render's helpers\n // will make use of the results in this.resolvedPromises, so that's why we had to wait.\n return (\n <ReactMarkdown\n remarkPlugins={[gfm]} // GitHub Formatted Markdown adds support for Tables in MD\n rehypePlugins={rehypePlugins} // Needed to parse HTML, activated in admin\n components={this.components} // Custom renderers for components, see definition in this.components\n children={this.markdown} // Our MD, as a text string\n />\n );\n }\n };\n}\n","import React from \"react\";\nimport FeaturePropsParsing from \"../../FeatureInfo/FeaturePropsParsing\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport {\n Table,\n TableBody,\n TableRow,\n TableCell,\n TableContainer,\n Typography,\n Grid,\n Button,\n Tooltip,\n} from \"@material-ui/core\";\nimport ArrowLeftIcon from \"@material-ui/icons/ArrowLeft\";\nimport ArrowRightIcon from \"@material-ui/icons/ArrowRight\";\n\nconst styles = (theme) => ({\n tableCell: {\n paddingLeft: 0,\n wordBreak: \"break-all\",\n width: \"50%\",\n },\n allFeatureDetailsContainer: {\n maxWidth: \"100%\",\n paddingLeft: theme.spacing(1),\n paddingRight: theme.spacing(1),\n },\n headerTypography: {\n maxWidth: \"100%\",\n fontSize: 18,\n },\n headerContainer: {\n paddingTop: theme.spacing(1),\n },\n togglerButton: {\n minWidth: 26,\n padding: 0,\n },\n});\n\nclass SearchResultsDatasetFeatureDetails extends React.PureComponent {\n state = {\n infoBox: null,\n };\n\n constructor(props) {\n super(props);\n\n this.featurePropsParsing = new FeaturePropsParsing({\n globalObserver: props.app.globalObserver,\n options:\n props.app.appModel.config.mapConfig.tools.find(\n (t) => t.type === \"infoclick\"\n )?.options || [], // featurePropsParsing needs to know if FeatureInfo is configured to allow HTML or not, so we pass on its' options\n });\n }\n\n componentDidMount = () => {\n this.getInfoBox();\n };\n\n componentDidUpdate = (prevProps) => {\n const { feature } = this.props;\n const prevFeature = prevProps.feature;\n if (feature !== prevFeature) {\n this.getInfoBox();\n }\n };\n\n getInfoBox = () => {\n if (this.shouldRenderCustomInfoBox()) {\n this.getHtmlItemInfoBox();\n } else {\n this.getDefaultInfoBox();\n }\n };\n\n shouldRenderCustomInfoBox = () => {\n const { feature } = this.props;\n const source = feature.source ?? this.props.source;\n return source.infobox && source.infobox !== \"\";\n };\n\n getHtmlItemInfoBox = () => {\n const { feature } = this.props;\n const source = feature.source ?? this.props.source;\n feature.setProperties(\n this.featurePropsParsing.extractPropertiesFromJson(\n feature.getProperties()\n )\n );\n this.featurePropsParsing\n .setMarkdownAndProperties({\n markdown: source.infobox,\n properties: feature.getProperties(),\n })\n .mergeFeaturePropsWithMarkdown()\n .then((MarkdownComponent) => {\n this.setState({ infoBox: MarkdownComponent });\n });\n };\n\n getDefaultInfoBox = () => {\n this.setState({ infoBox: this.renderDefaultInfoBox() });\n };\n\n renderTableCell = (content, position) => {\n const { classes } = this.props;\n const textToRender = Array.isArray(content) ? content.join(\", \") : content;\n return (\n <TableCell\n align={position}\n style={position === \"right\" ? { paddingRight: 0 } : null}\n className={classes.tableCell}\n >\n {textToRender}\n </TableCell>\n );\n };\n\n renderDefaultInfoBox = () => {\n const { feature } = this.props;\n return (\n <TableContainer>\n <Table size=\"small\">\n <TableBody>\n {Object.entries(feature.getProperties()).map((row) => {\n // feature.getProperties() can contain values of any data type\n // (whatever is set on the current feature). But since we can not\n // render e.g. Date or Point objects, we must do the following check\n // and only allow String, Number or Array:\n return typeof row[1] === \"string\" ||\n typeof row[1] === \"number\" ||\n Array.isArray(row[1]) ? (\n <TableRow key={row[0]}>\n {this.renderTableCell(row[0])}\n {this.renderTableCell(row[1], \"right\")}\n </TableRow>\n ) : null;\n })}\n </TableBody>\n </Table>\n </TableContainer>\n );\n };\n\n handleTogglerPressed = (nextFeatureIndex) => {\n const { setActiveFeature, features } = this.props;\n const nextFeature = features[nextFeatureIndex];\n setActiveFeature(nextFeature);\n };\n\n getFeatureIndex = (feature, features) => {\n return (\n features?.findIndex((f) => {\n return f.getId() === feature.getId();\n }) ?? -1\n );\n };\n\n renderFeatureToggler = () => {\n const { feature, classes, features } = this.props;\n const numFeaturesInCollection = features.length;\n const currentFeatureIndex = this.getFeatureIndex(feature, features);\n\n const buttonLeftDisabled = currentFeatureIndex - 1 < 0;\n const buttonRightDisabled =\n currentFeatureIndex + 1 >= numFeaturesInCollection;\n\n return (\n <Grid container item alignItems=\"center\" justify=\"space-between\">\n <Grid item>\n <Tooltip\n title={\n !buttonLeftDisabled\n ? \"Visa föregående objekt i resultatlistan\"\n : \"\"\n }\n >\n <span>\n <Button\n size=\"small\"\n variant=\"outlined\"\n className={classes.togglerButton}\n disabled={buttonLeftDisabled}\n onClick={() =>\n this.handleTogglerPressed(currentFeatureIndex - 1)\n }\n aria-label=\"show-previous-feature\"\n id=\"step-left\"\n >\n <ArrowLeftIcon\n fontSize=\"small\"\n color={buttonLeftDisabled ? \"disabled\" : \"action\"}\n />\n </Button>\n </span>\n </Tooltip>\n </Grid>\n <Grid item>\n <Tooltip\n title={\n !buttonRightDisabled ? \"Visa nästa objekt i resultatlistan\" : \"\"\n }\n >\n <span>\n <Button\n size=\"small\"\n variant=\"outlined\"\n className={classes.togglerButton}\n disabled={buttonRightDisabled}\n onClick={() =>\n this.handleTogglerPressed(currentFeatureIndex + 1)\n }\n aria-label=\"show-next-feature\"\n id=\"step-left\"\n >\n <ArrowRightIcon\n fontSize=\"small\"\n color={buttonRightDisabled ? \"disabled\" : \"action\"}\n />\n </Button>\n </span>\n </Tooltip>\n </Grid>\n </Grid>\n );\n };\n\n renderFeatureTitle = () => {\n const { feature, classes } = this.props;\n return (\n <Typography\n noWrap\n className={classes.headerTypography}\n component=\"div\"\n variant=\"button\"\n align=\"left\"\n >\n {feature.featureTitle}\n </Typography>\n );\n };\n\n render() {\n const { classes, features, enableFeatureToggler } = this.props;\n const { infoBox } = this.state;\n const shouldRenderToggler =\n (enableFeatureToggler ?? true) && features?.length > 1;\n return (\n <Grid container className={classes.allFeatureDetailsContainer}>\n <Grid container alignItems=\"center\" className={classes.headerContainer}>\n <Grid\n item\n xs={shouldRenderToggler ? 9 : 12}\n md={shouldRenderToggler ? 10 : 12}\n >\n {this.renderFeatureTitle()}\n </Grid>\n {shouldRenderToggler && (\n <Grid item xs={3} md={2}>\n {this.renderFeatureToggler()}\n </Grid>\n )}\n </Grid>\n {infoBox && (\n <Grid item xs={12}>\n {infoBox}\n </Grid>\n )}\n </Grid>\n );\n }\n}\nexport default withStyles(styles)(SearchResultsDatasetFeatureDetails);\n","import React, { useState } from \"react\";\nimport { MuiThemeProvider, createMuiTheme } from \"@material-ui/core/styles\";\nimport CssBaseline from \"@material-ui/core/CssBaseline\";\nimport App from \"./App\";\n\nimport { deepMerge } from \"../utils/DeepMerge\";\n\n/**\n * @summary Helper, used to determine if user's browser prefers dark mode.\n *\n * @param {*} preferredColorSchemeFromMapConfig\n * @returns {String} \"dark\" or \"light\"\n */\nfunction getColorScheme(preferredColorSchemeFromMapConfig, customTheme) {\n // First of all, see if admins have provided a customTheme.json, where\n // the light/dark mode value is set. If it is, this will override any\n // other logic, which means we're not interested in user's or OS's preference.\n if ([\"light\", \"dark\"].includes(customTheme?.palette?.type)) {\n return customTheme.palette.type;\n }\n\n // If there's no global override, we can go on and\n // check if there already is a user preferred value in local storage.\n const userPreferredColorScheme = window.localStorage.getItem(\n \"userPreferredColorScheme\"\n );\n\n let colorScheme = null; // Will hold the return value\n\n // If there's already a valid user preference in local storage…\n if ([\"light\", \"dark\"].includes(userPreferredColorScheme)) {\n colorScheme = userPreferredColorScheme; // …use it.\n } else {\n // Else, find out what admin has set in map config…\n switch (\n preferredColorSchemeFromMapConfig // If setting in admin is…\n ) {\n case \"dark\": // …dark, use it,\n colorScheme = \"dark\";\n break;\n case \"light\": // …light, use it.\n colorScheme = \"light\";\n break;\n default:\n // If there's no preference yet in neither local storage nor admin…\n colorScheme =\n window?.matchMedia(\"(prefers-color-scheme: dark)\").matches === true // …check if browser prefers dark mode…\n ? \"dark\" // …if so, use dark mode…\n : \"light\"; // … else go for light.\n break;\n }\n }\n\n return colorScheme;\n}\n\n/**\n * Helper function that creates a MUI theme by merging\n * hard-coded values (in this function), with custom values\n * (obtained from customTheme.json in /public).\n * This way, user can customize look and feel of application\n * AFTER it has been build with webpack, by simply tweaking\n * values in customTheme.json.\n *\n * @param {Object} config Map config that, among other objects, contains the default MUI theme\n * @param {Object} customTheme An object with the custom theme, obtained via fetch from customTheme.json\n * @returns {Object} A complete, ready to used theme object\n */\nfunction getTheme(config, customTheme) {\n const colorScheme = getColorScheme(\n config.mapConfig.map.colors?.preferredColorScheme,\n customTheme\n );\n // Setup some app-wide defaults that differ from MUI's defaults:\n const hardCodedDefaults = {\n palette: {\n type: colorScheme,\n action: {\n active: colorScheme === \"dark\" ? \"#fff\" : \"rgba(0, 0, 0, 0.87)\",\n },\n },\n shape: {\n borderRadius: 2,\n },\n };\n\n // Allow even more customization by reading values from each map config\n const themeFromMapConfig = {\n palette: {\n primary: {\n main: config.mapConfig.map.colors.primaryColor, // primary: blue // <- Can be done like this (don't forget to import blue from \"@material-ui/core/colors/blue\"!)\n },\n secondary: {\n main: config.mapConfig.map.colors.secondaryColor, // secondary: { main: \"#11cb5f\" } // <- Or like this\n },\n },\n };\n\n // Create the merged theme object by:\n const mergedTheme = deepMerge(\n hardCodedDefaults, // Using the hardcoded default…\n customTheme, // … overriding them with stuff from customTheme.json (app-wide customizations, common for each maps)…\n themeFromMapConfig // … and finally overriding them with map-specific customizations.\n );\n\n return mergedTheme;\n}\n\nconst HajkThemeProvider = ({ activeTools, config, customTheme }) => {\n // Keep the app's theme in state so it can be changed dynamically.\n const [theme, setTheme] = useState(getTheme(config, customTheme));\n\n // We need a state-variable so that we are able to re-render the theme-provider\n // without changing the theme. Why, you might ask? Since we're using a custom theme\n // when invoking the document-handler-print we must be able to reset the theme back\n // to the original one (which requires a re-render).\n const [themeUID, setThemeUID] = useState(Math.random());\n\n // Handles theme toggling\n const toggleMUITheme = () => {\n // If there's a override in customTheme.json, toggling is not possible.\n if (customTheme?.palette?.type) return;\n\n // Toggle the current value from theme's palette\n let userPreferredColorScheme =\n theme.palette.type === \"light\" ? \"dark\" : \"light\";\n\n // Save for later in browser's local storage\n window.localStorage.setItem(\n \"userPreferredColorScheme\",\n userPreferredColorScheme\n );\n\n // Create a new theme object by taking the current theme\n // and merging with the latest theme type value\n const newTheme = deepMerge(theme, {\n palette: {\n type: userPreferredColorScheme,\n action: {\n active:\n userPreferredColorScheme === \"dark\"\n ? \"#fff\"\n : \"rgba(0, 0, 0, 0.87)\",\n },\n },\n });\n\n // Finally, save the new theme object in state. This will cause re-render,\n // and effectively take the new theme type value into action.\n setTheme(newTheme);\n };\n\n // This will cause a re-render, allowing for the \"standard\" theme to be injected\n // again - which will make sure that the \"standard\" theme has the highest css-specificity.\n // Useful for those rare occasions where you might have used a custom theme inside components.\n // An example of this is in the document-handler print solution, where we're injecting a custom\n // print theme, which we want to get rid of.\n const refreshMUITheme = () => {\n setThemeUID(themeUID + Math.random());\n };\n\n // Take the theme object from state and generate a MUI-theme\n const muiTheme = createMuiTheme(theme);\n\n // Render, pass through some stuff into App.\n return (\n <MuiThemeProvider theme={muiTheme}>\n <CssBaseline />\n <App\n activeTools={activeTools}\n config={config}\n theme={muiTheme}\n toggleMUITheme={toggleMUITheme}\n refreshMUITheme={refreshMUITheme}\n />\n </MuiThemeProvider>\n );\n};\n\nexport default HajkThemeProvider;\n","import React from \"react\";\nimport propTypes from \"prop-types\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport PanelHeader from \"./PanelHeader\";\nimport { Rnd } from \"react-rnd\";\nimport { isMobile, getIsMobile } from \"../utils/IsMobile.js\";\nimport FeatureInfoContainer from \"./FeatureInfo/FeatureInfoContainer.js\";\nimport clsx from \"clsx\";\n\nconst zIndexStart = 1000;\n// Patch the RND component's onDragStart method with the ability to disable drag by its internal state.\n// This is necessary so we can disable/enable drag at any time.\n//\n// Please note that since we override the onDragStart on prototype level, we must ensure that it's\n// kept up-to-date with the current version, see https://github.com/bokuweb/react-rnd/blob/master/src/index.tsx\n// for latest version of this method.\n//\n// TODO: Perhaps there's no need to disable drag at any time anymore, so this override could be removed?\n//\nRnd.prototype.onDragStart = function (e, data) {\n if (this.state.disableDrag) {\n return false;\n }\n\n if (this.props.onDragStart) {\n this.props.onDragStart(e, data);\n }\n if (!this.props.bounds) return;\n const parent = this.getParent();\n const scale = this.props.scale;\n let boundary;\n if (this.props.bounds === \"parent\") {\n boundary = parent;\n } else if (this.props.bounds === \"body\") {\n const parentRect = parent.getBoundingClientRect();\n const parentLeft = parentRect.left;\n const parentTop = parentRect.top;\n const bodyRect = document.body.getBoundingClientRect();\n const left =\n -(parentLeft - parent.offsetLeft * scale - bodyRect.left) / scale;\n const top = -(parentTop - parent.offsetTop * scale - bodyRect.top) / scale;\n const right =\n (document.body.offsetWidth - this.resizable.size.width * scale) / scale +\n left;\n const bottom =\n (document.body.offsetHeight - this.resizable.size.height * scale) /\n scale +\n top;\n return this.setState({ bounds: { top, right, bottom, left } });\n } else if (this.props.bounds === \"window\") {\n if (!this.resizable) return;\n const parentRect = parent.getBoundingClientRect();\n const parentLeft = parentRect.left;\n const parentTop = parentRect.top;\n const left = -(parentLeft - parent.offsetLeft * scale) / scale;\n const top = -(parentTop - parent.offsetTop * scale) / scale;\n const right =\n (window.innerWidth - this.resizable.size.width * scale) / scale + left;\n const bottom =\n (window.innerHeight - this.resizable.size.height * scale) / scale + top;\n return this.setState({ bounds: { top, right, bottom, left } });\n } else {\n boundary = document.querySelector(this.props.bounds);\n }\n if (!(boundary instanceof HTMLElement) || !(parent instanceof HTMLElement)) {\n return;\n }\n const boundaryRect = boundary.getBoundingClientRect();\n const boundaryLeft = boundaryRect.left;\n const boundaryTop = boundaryRect.top;\n const parentRect = parent.getBoundingClientRect();\n const parentLeft = parentRect.left;\n const parentTop = parentRect.top;\n const left = (boundaryLeft - parentLeft) / scale;\n const top = boundaryTop - parentTop;\n if (!this.resizable) return;\n this.updateOffsetFromParent();\n const offset = this.offsetFromParent;\n this.setState({\n bounds: {\n top: top - offset.top,\n right:\n left +\n (boundary.offsetWidth - this.resizable.size.width) -\n offset.left / scale,\n bottom:\n top + (boundary.offsetHeight - this.resizable.size.height) - offset.top,\n left: left - offset.left / scale,\n },\n });\n};\n\nconst styles = (theme) => {\n return {\n window: {\n zIndex: zIndexStart + document.windows.length,\n position: \"absolute\",\n background: theme.palette.background.paper,\n boxShadow: theme.shadows[24],\n borderRadius: theme.shape.borderRadius,\n overflow: \"hidden\",\n pointerEvents: \"all\",\n [theme.breakpoints.down(\"xs\")]: {\n borderRadius: \"0\",\n position: \"fixed !important\",\n },\n },\n panelContent: {\n display: \"flex\",\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n right: 0,\n flexDirection: \"column\",\n userSelect: \"none\",\n outline: \"none\",\n '& a:not([class*=\"Mui\"])': {\n color: theme.palette.primary.light,\n },\n },\n panelContentDisplayContents: {\n display: \"contents\",\n },\n content: {\n flex: \"1\",\n overflowY: \"auto\",\n padding: \"10px\",\n cursor: \"default !important\",\n },\n nonScrollable: {\n overflowY: \"hidden\",\n padding: \"0px\",\n },\n };\n};\n\nclass Window extends React.PureComponent {\n static propTypes = {\n children: propTypes.object,\n classes: propTypes.object.isRequired,\n color: propTypes.string,\n features: propTypes.array,\n globalObserver: propTypes.object.isRequired,\n height: propTypes.oneOfType([propTypes.number, propTypes.string])\n .isRequired,\n layerswitcherConfig: propTypes.object,\n map: propTypes.object,\n mode: propTypes.string.isRequired,\n onClose: propTypes.func.isRequired,\n onDisplay: propTypes.func,\n onResize: propTypes.func,\n open: propTypes.bool.isRequired,\n position: propTypes.string.isRequired,\n title: propTypes.string.isRequired,\n width: propTypes.number.isRequired,\n };\n\n static defaultProps = {\n draggingEnabled: true,\n resizingEnabled: true,\n allowMaximizedWindow: false,\n scrollable: true,\n };\n\n constructor(props) {\n super(props);\n document.windows.push(this);\n this.windowRef = React.createRef();\n this.state = {\n left: 0,\n top: 0,\n width: 300,\n height: this.props.height === \"dynamic\" ? \"auto\" : 400,\n };\n\n window.addEventListener(\"resize\", () => {\n if (this.state.mode === \"maximized\") {\n this.fit(document.getElementById(\"windows-container\"));\n } else {\n this.updatePosition();\n }\n });\n }\n\n componentDidUpdate = (prevProps, prevState) => {\n if (prevProps.open === false && this.props.open === true) {\n //This is ugly but there is a timing problem further down somewhere (i suppose?).\n //componentDidUpdate is run before the render is actually fully completed and the DOM is ready\n setTimeout(() => {\n this.windowRef.current.focus();\n }, 200);\n }\n };\n\n componentDidMount() {\n const { globalObserver } = this.props;\n if (globalObserver) {\n globalObserver.subscribe(\"core.appLoaded\", () => {\n this.updatePosition();\n });\n globalObserver.subscribe(\"core.drawerToggled\", () => {\n this.updatePosition();\n });\n globalObserver.subscribe(\"core.dialogOpen\", (open) => {\n this.rnd.setState({\n disableDrag: open,\n });\n });\n }\n }\n\n /**\n * In LayerSwitcher plugin's settings, there's an option that allows\n * user to show or hide the so called \"breadcrumbs\": small boxes, one\n * for each active layer, that show up at the bottom of the screen.\n *\n * If breadcrumbs are activated, we should ensure that our Windows\n * don't hide breadcrumbs, by reducing Windows' default height slightly.\n *\n * This helper is used to determine whether breadcrumbs are activated\n * or not.\n *\n * @returns boolean\n * @memberof Window\n */\n areBreadcrumbsActivated() {\n return this.props.layerswitcherConfig &&\n this.props.layerswitcherConfig.hasOwnProperty(\"options\")\n ? this.props.layerswitcherConfig.options.showBreadcrumbs\n : false;\n }\n\n getMaxWindowHeight() {\n if (this.rnd === undefined) return 400;\n const parent = this.rnd.getSelfElement().parentElement;\n const spaceForBreadcrumbs = this.areBreadcrumbsActivated() ? 42 : 0;\n const h =\n parent.clientHeight - // Maximum height of parent element\n 16 - // Reduce height with top margin\n 16 - // Reduce height with bottom margin\n 62 - // Reduce with space for Search bar\n spaceForBreadcrumbs; // If Breadcrumbs are active, make space for them as well\n return h;\n }\n\n updatePosition() {\n const { width, height, position } = this.props;\n const parent = this.rnd.getSelfElement().parentElement;\n\n //FIXME: JW - Not the best solution for parent resize to set top/left to 0/0, but it ensures we don't get a window outside of the parent\n this.left = 16; // Make sure we respect padding\n this.top = 16 + 62; // Respect top padding + don't overlap Drawer Toggle buttons\n this.width = width || 400;\n this.height = height || 300;\n\n // If \"auto\" height is set, it means we want the Window to take up maximum space available\n if (this.props.height !== \"dynamic\" && this.height === \"auto\") {\n this.height = this.getMaxWindowHeight();\n }\n\n // If Window renders on the right, there are some things that we need to compensate for\n if (position === \"right\") {\n this.left = parent.getBoundingClientRect().width - width - 16 - 56; // -16 to take care of usual right padding, -56 to not cover the Control buttons that are on the right\n }\n\n // Mobile screens are another special case: here our Window should take up max space available\n if (getIsMobile()) {\n this.left = 0;\n this.top = 0;\n this.height = window.innerHeight;\n this.width = document.body.clientWidth;\n }\n\n this.left = this.left !== undefined ? this.left : 16;\n\n this.setState(\n {\n left: this.left,\n top: this.top,\n width: this.width,\n height: this.height,\n mode: \"window\",\n },\n () => {\n this.rnd.updatePosition({\n y: Math.round(this.top),\n x: Math.round(this.left),\n });\n }\n );\n }\n\n close = (e) => {\n const { onClose, globalObserver, title } = this.props;\n this.latestWidth = this.rnd.getSelfElement().clientWidth;\n if (onClose) onClose();\n\n globalObserver.publish(\"core.closeWindow\", title);\n };\n\n fit = (target) => {\n this.rnd.updatePosition({\n x: Math.round(target.getBoundingClientRect().left),\n y: Math.round(target.getBoundingClientRect().top),\n });\n this.rnd.setState({\n disableDrag: true,\n });\n this.setState({\n width: target.clientWidth,\n height: target.clientHeight,\n mode: \"maximized\",\n });\n };\n\n reset = () => {\n this.rnd.updatePosition({\n y: Math.round(this.top),\n x: Math.round(this.left),\n });\n this.rnd.setState({\n disableDrag: false,\n });\n this.setState({\n width: this.width,\n height: this.height,\n mode: \"window\",\n });\n };\n\n enlarge = () => {\n let t = parseFloat(this.top);\n let h = parseFloat(this.height);\n let c = this.rnd.getSelfElement().parentElement.getBoundingClientRect();\n let o = t + h;\n\n if (o > c.bottom) {\n this.top = this.top - o + c.bottom;\n }\n\n this.rnd.updatePosition({\n y: Math.round(this.top),\n });\n this.rnd.setState({\n disableDrag: false,\n });\n this.setState({\n height: this.height,\n mode: \"window\",\n });\n };\n\n maximize = () => {\n const {\n globalObserver,\n onMaximize,\n onResize,\n allowMaximizedWindow,\n title,\n } = this.props;\n\n getIsMobile() && this.rnd.updatePosition({ y: 0 });\n\n switch (this.state.mode) {\n case \"minimized\":\n // Enlarge back to \"window\" mode\n if (this.height === \"dynamic\") {\n this.height = \"auto\";\n }\n this.enlarge();\n break;\n case \"window\":\n // If already in \"window\" mode, fill the viewport\n allowMaximizedWindow &&\n this.fit(document.getElementById(\"windows-container\"));\n break;\n case \"maximized\":\n // If already \"maximized\" mode, switch back to \"window\"\n this.reset(document.getElementById(\"windows-container\"));\n break;\n default:\n break;\n }\n\n // Run callbacks\n typeof onMaximize === \"function\" && onMaximize();\n typeof onResize === \"function\" && onResize();\n\n globalObserver.publish(\"core.maximizeWindow\", title);\n };\n\n minimize = () => {\n const { globalObserver, onMinimize, onResize, title } = this.props;\n\n getIsMobile() &&\n this.rnd.updatePosition({\n y: Math.round(window.innerHeight - 42),\n });\n\n // Don't matter the current mode – just collapse\n this.height = this.state.height;\n this.setState({\n height: 0,\n mode: \"minimized\",\n });\n\n // Run callbacks\n typeof onMinimize === \"function\" && onMinimize();\n typeof onResize === \"function\" && onResize();\n\n globalObserver.publish(\"core.minimizeWindow\", title);\n };\n\n bringToFront() {\n document.windows\n .sort((a, b) => (a === this ? 1 : b === this ? -1 : 0))\n .forEach((w, i) => {\n if (w.rnd) {\n w.rnd.getSelfElement().style.zIndex = zIndexStart + i;\n }\n });\n }\n\n render() {\n const {\n children,\n classes,\n color,\n features,\n open,\n title,\n resizingEnabled,\n draggingEnabled,\n allowMaximizedWindow,\n customPanelHeaderButtons,\n } = this.props;\n const { left, top, width, height } = this.state;\n\n let resizeBottom = true,\n resizeBottomLeft = true,\n resizeBottomRight = true,\n resizeLeft = true,\n resizeRight = true,\n resizeTop = true,\n resizeTopLeft = true,\n resizeTopRight = true;\n\n if (isMobile) {\n resizeBottom =\n resizeBottomLeft =\n resizeBottomRight =\n resizeRight =\n resizeTopLeft =\n resizeTopRight =\n resizeLeft =\n false;\n } else {\n if (this.state.mode === \"maximized\") {\n resizeBottom =\n resizeBottomLeft =\n resizeBottomRight =\n resizeRight =\n resizeTop =\n resizeTopLeft =\n resizeTopRight =\n resizeLeft =\n false;\n }\n if (this.state.mode === \"minimized\") {\n resizeBottom =\n resizeBottomLeft =\n resizeBottomRight =\n resizeTop =\n resizeTopLeft =\n resizeTopRight =\n resizeLeft =\n false;\n }\n\n if (!resizingEnabled) {\n resizeBottom =\n resizeBottomLeft =\n resizeBottomRight =\n resizeRight =\n resizeTop =\n resizeTopLeft =\n resizeTopRight =\n resizeLeft =\n false;\n }\n }\n\n this.bringToFront();\n return (\n <Rnd\n onMouseDown={(e) => {\n this.bringToFront();\n }}\n onMouseOver={(e) => e.stopPropagation()} // If this bubbles, we'll have Tooltip show up even when we're only on Window. FIXME: Not needed when we change the rendering order.\n ref={(c) => {\n this.rnd = c;\n }}\n style={{\n display: open ? \"block\" : \"none\",\n }}\n onDragStop={(e, d) => {\n const rect = this.rnd.getSelfElement().getClientRects()[0];\n if (rect) {\n this.left = rect.left;\n this.top = rect.top;\n this.right =\n window.innerWidth - (this.left + parseFloat(this.width));\n }\n }}\n onResizeStop={(e, direction, ref, delta, position) => {\n this.width = ref.style.width;\n if (this.state.mode !== \"minimized\") {\n this.height = ref.style.height;\n }\n this.setState({\n width: ref.style.width,\n height: ref.style.height,\n });\n if (this.props.onResize) this.props.onResize();\n }}\n cancel=\"section,nav\"\n bounds={\"#windows-container\"}\n disableDragging={!draggingEnabled || false || getIsMobile()}\n enableResizing={{\n bottom: resizeBottom,\n bottomLeft: resizeBottomLeft,\n bottomRight: resizeBottomRight,\n left: resizeLeft,\n right: resizeRight,\n top: resizeTop,\n topLeft: resizeTopLeft,\n topRight: resizeTopRight,\n }}\n className={classes.window}\n minWidth={200}\n minHeight={this.state.mode === \"minimized\" ? 42 : 100}\n size={{\n width: width,\n height: height,\n }}\n default={{\n x: left,\n y: top,\n width: width,\n height: height,\n }}\n >\n <div\n tabIndex=\"0\"\n ref={this.windowRef}\n className={clsx(\n classes.panelContent,\n this.props.height === \"dynamic\"\n ? classes.panelContentDisplayContents\n : null\n )}\n >\n <PanelHeader\n allowMaximizedWindow={allowMaximizedWindow}\n color={color}\n customHeaderButtons={customPanelHeaderButtons}\n globalObserver={this.props.globalObserver}\n localObserver={this.props.localObserver}\n onClose={this.close}\n onMaximize={this.maximize}\n onMinimize={this.minimize}\n mode={this.state.mode}\n title={title}\n />\n <section\n className={clsx(\n classes.content,\n this.props.scrollable ? null : classes.nonScrollable\n )}\n style={{\n // Ensure to set maxHeight to ensure that we can scroll inside the container\n maxHeight:\n this.getMaxWindowHeight() - (isMobile === false ? 50 : -30), // Super-hack special case for small screens\n }}\n >\n {features && features.length > 0 ? (\n <FeatureInfoContainer\n features={this.props.features}\n options={this.props.options}\n onDisplay={this.props.onDisplay}\n globalObserver={this.props.globalObserver}\n key={\n Array.isArray(this.props.features) &&\n this.props.features.length > 0\n ? this.props.features[0].getId()\n : 0\n }\n />\n ) : (\n children\n )}\n </section>\n </div>\n </Rnd>\n );\n }\n}\n\nexport default withStyles(styles)(Window);\n","class PropFilters {\n constructor() {\n this.filters = {};\n return this;\n }\n\n applyFilters(properties, input) {\n let args = input.split(\"|\");\n const key = args.shift().trim();\n\n let value = null;\n\n if (key.indexOf(\"'\") === 0) {\n // handle raw data, not from props. Can be good to have, especially when testing.\n // example: {'2021-06-03T13:04:12Z'|date}\n value = key.substring(1, key.length - 1);\n } else {\n value = properties[key];\n if (!value) {\n value = \"\";\n }\n }\n\n args.forEach((inFilter) => {\n // This is where we handle chained filters.\n const argsStart = inFilter.indexOf(\"(\");\n let filterName = inFilter;\n let args = [];\n\n if (argsStart > -1) {\n filterName = inFilter.substr(0, argsStart);\n args = inFilter\n .substring(argsStart + 1, inFilter.indexOf(\")\"))\n .split(\",\");\n args.forEach((v, i, a) => {\n a[i] = this.cleanString(v.trim());\n });\n }\n\n value = this.execFilter(filterName, value, args);\n });\n\n return value;\n }\n\n execFilter(filterName, value, args) {\n const filter = this.get(filterName);\n\n if (filter) {\n try {\n return filter.func.apply(this, [value, ...args]);\n } catch (err) {\n console.warn(\n `FeaturePropFilters: Could not apply filter '${filterName}' on value ${value} with args ${args},`,\n err\n );\n }\n }\n\n return value;\n }\n\n cleanString(s) {\n // Free the strings contained inside ''\n if (s.indexOf(\"'\") === 0) {\n s = s.substring(1, s.length - 1);\n }\n return s;\n }\n\n get(key) {\n if (this.filters[key]) {\n return this.filters[key];\n } else {\n console.warn(\n `FeaturePropFilters: Could not find filter with name '${key}'`\n );\n }\n return null;\n }\n\n add(key, f) {\n this.filters[key] = {\n func: f,\n };\n }\n\n addAlias(key, targetKey) {\n this.add(key, this.get(targetKey).func);\n }\n}\n\nfunction fixDate(value) {\n if (value.indexOf(\"-\") <= -1) {\n value = `${value.substr(0, 4)}-${value.substr(4, 2)}-${value.substr(6, 2)}`;\n }\n return value;\n}\n\nconst filters = new PropFilters();\n\n// ---- Add filters below -----------------------------------------------------\n\n/*\n roundToDecimals\n Example:\n {'45.32465456'|roundToDecimals(2)}\n outputs: 45,32\n*/\nfilters.add(\"roundToDecimals\", function (value, numDecimals) {\n if (isNaN(value) || isNaN(numDecimals)) {\n throw new Error(\"Arguments should be numbers\");\n }\n return parseFloat(value.toFixed(parseInt(numDecimals))).toLocaleString();\n});\n\n/*\n replace\n Example:\n {'This is working BAD!!'|replace('BAD','GOOD')}\n outputs: This is working GOOD!!\n*/\nfilters.add(\"replace\", function (value, replace, withString) {\n return value.replace(new RegExp(replace, \"gm\"), withString);\n});\n\n/*\n default/fallback\n Example:\n {''|default('No value found')}\n outputs: No value\n*/\nfilters.add(\"default\", function (value, defaultValue) {\n return value === \"\" ? defaultValue : value;\n});\nfilters.addAlias(\"fallback\", \"default\");\n\n/*\n lt - lessThan\n If lessValue or greaterValue is an empty string the original value will be returned\n Example:\n {10.3|lt(11, 'LessThan', 'GreaterThan')}\n outputs: 'LessThan'\n {10.3|lt(11, '', 'GreaterThan')}\n outputs: 10.3\n*/\nfilters.add(\"lt\", function (value, test, lessValue, greaterValue) {\n if (isNaN(value) || isNaN(test)) {\n return value;\n }\n const val = typeof value === \"string\" ? parseFloat(value) : value;\n const t = typeof test === \"string\" ? parseFloat(test) : test;\n\n if (val < t) {\n return typeof lessValue === \"string\" && lessValue.length === 0\n ? value\n : lessValue;\n } else {\n return typeof greaterValue === \"string\" && greaterValue.length === 0\n ? value\n : greaterValue;\n }\n});\n\n/*\n equals\n Example:\n {'true'|equals('true', 'yes', 'no')}\n outputs: yes\n*/\nfilters.add(\"equals\", function (value, test, trueValue, falseValue) {\n return value === test ? trueValue : falseValue || value;\n});\n\n/*\n notEquals\n Example:\n {'false'|notEquals('true', 'This value is not true', 'This value is true')}\n outputs: This value is not false\n*/\nfilters.add(\"notEquals\", function (value, test, falseValue, trueValue) {\n return value !== test ? falseValue : trueValue || value;\n});\n\n/*\n datetime\n Example:\n {'2021-06-03T13:04:12Z'|datetime}\n outputs: 2021-06-03 13:04:12\n*/\nfilters.add(\"datetime\", function (value) {\n const date = typeof value === \"string\" ? new Date(value) : value;\n return date.toLocaleString();\n});\n\n/*\n date\n Example:\n {'2021-06-03T13:04:12Z'|date}\n outputs: 2021-06-03\n*/\nfilters.add(\"date\", function (value) {\n value = fixDate(value);\n const date = typeof value === \"string\" ? new Date(value) : value;\n return date.toLocaleDateString();\n});\n\n/*\n time\n Example:\n {'2021-06-03T13:04:12Z'|time}\n outputs: 13:04:12\n*/\nfilters.add(\"time\", function (value) {\n const date = typeof value === \"string\" ? new Date(value) : value;\n return date.toLocaleTimeString();\n});\n\n/*\n dateAddDays\n Example:\n {'2021-06-03T13:04:12Z'|dateAddDays(1)|datetime}\n outputs: 2021-06-04 13:04\n Note: negative value will substract days\n*/\nfilters.add(\"dateAddDays\", function (value, days) {\n value = fixDate(value);\n const date = typeof value === \"string\" ? new Date(value) : value;\n date.setDate(date.getDate() + parseFloat(days));\n return date;\n});\n\n/*\n dateAddHours\n Example:\n {'2021-06-03T13:04:12Z'|dateAddHours(1)|datetime}\n outputs: 2021-06-03 14:04\n Note: negative value will substract hours\n*/\nfilters.add(\"dateAddHours\", function (value, hours) {\n value = fixDate(value);\n const date = typeof value === \"string\" ? new Date(value) : value;\n date.setTime(date.getTime() + parseFloat(hours) * 60 * 60 * 1000);\n return date;\n});\n\n/*\n formatNumber\n Example:\n {'98000'|formatNumber}\n outputs: 98 000\n*/\nfilters.add(\"formatNumber\", function (value) {\n if (isNaN(value)) {\n throw new Error(\"Argument should be a number\");\n }\n return Number(value).toLocaleString();\n});\n\n/*\n toUpper\n Example:\n {'testing'|toUpper}\n outputs: TESTING\n*/\nfilters.add(\"toUpper\", function (value) {\n return value.toUpperCase();\n});\n\n/*\n toLower\n Example:\n {'TESTING'|toLower}\n outputs: testing\n*/\nfilters.add(\"toLower\", function (value) {\n return value.toLowerCase();\n});\n\n/*\n capitalize\n Example:\n {'testing'|capitalize}\n outputs: Testing\n*/\nfilters.add(\"capitalize\", function (value) {\n return value.charAt(0).toUpperCase() + value.slice(1);\n});\n\n/*\n substr\n Example:\n {'abcdef'|substr(2,4)}\n outputs: cdef\n*/\nfilters.add(\"substr\", function (value, i1, i2) {\n return value.substr(i1, i2);\n});\n\n/*\n substring\n Example:\n {'abcdef'|substring(2,4)}\n outputs: cd\n*/\nfilters.add(\"substring\", function (value, i1, i2) {\n return value.substring(i1, i2);\n});\n\n/*\n left\n Example:\n {'probably_useful'|left('_')}\n outputs: probably\n*/\nfilters.add(\"left\", function (value, searchFor) {\n return value.split(searchFor)[0];\n});\n\n/*\n left\n Example:\n {'probably_useful'|right('_')}\n outputs: useful\n*/\nfilters.add(\"right\", function (value, searchFor) {\n const i = value.indexOf(searchFor);\n return i > -1 ? value.substring(i + searchFor.length, value.length) : value;\n});\n\n/*\n trim\n Example:\n {' padded string '|trim}\n outputs: 'padded string'\n*/\nfilters.add(\"trim\", function (value) {\n return value.trim();\n});\n\nexport default filters;\n","export const isValidLayerId = (id) => {\n return (\n !Number.isNaN(Number(id)) || // … and the name is either a Number…\n /^[a-f0-9]{32}$/i.test(id) || // … or an MD5 string (which was used in the NodeJS backend)\n /^[a-z0-9]{6}$/i.test(id) // … or a 6 characters long alphanumeric string (which is the new default for layers created in NodeJS backend)\n );\n};\n","export const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n","import React from \"react\";\nimport propTypes from \"prop-types\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport Button from \"@material-ui/core/Button\";\nimport Dialog from \"@material-ui/core/Dialog\";\nimport DialogTitle from \"@material-ui/core/DialogTitle\";\nimport DialogActions from \"@material-ui/core/DialogActions\";\nimport DialogContent from \"@material-ui/core/DialogContent\";\n\nconst styles = (theme) => {\n return {};\n};\n\nclass AlertView extends React.PureComponent {\n state = {};\n\n static propTypes = {\n classes: propTypes.object.isRequired,\n message: propTypes.any.isRequired,\n open: propTypes.bool.isRequired,\n parent: propTypes.object.isRequired,\n title: propTypes.string.isRequired,\n };\n\n static defaultProps = {\n message: \"Meddelande saknas\",\n title: \"Titel saknas\",\n };\n\n handleClose = (e) => {\n this.props.parent.setState({\n alert: false,\n });\n };\n\n render() {\n const { open, dialogTitle, message } = this.props;\n return (\n <Dialog\n open={open}\n onClose={this.handleClose}\n aria-labelledby=\"alert-dialog-title\"\n aria-describedby=\"alert-dialog-description\"\n >\n <DialogTitle id=\"alert-dialog-title\">\n {dialogTitle || \"Meddelande\"}\n </DialogTitle>\n <DialogContent>{message}</DialogContent>\n <DialogActions>\n <Button onClick={this.handleClose} color=\"primary\" autoFocus>\n Ok\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n}\n\nexport default withStyles(styles)(AlertView);\n","import WKT from \"ol/format/WKT.js\";\nimport { Icon, Stroke, Fill } from \"ol/style.js\";\nimport {\n Point,\n MultiPoint,\n Polygon,\n MultiPolygon,\n LineString,\n MultiLineString,\n} from \"ol/geom.js\";\n\nfunction componentToHex(c) {\n var hex = c.toString(16);\n return hex.length === 1 ? \"0\" + hex : hex;\n}\n\nfunction rgbToHex(r, g, b) {\n return componentToHex(r) + componentToHex(g) + componentToHex(b);\n}\n\nfunction colorToArray(color, type) {\n var res = [],\n reg = type === \"rgb\" ? /rgb\\((.+)\\)/ : /rgba\\((.+)\\)/;\n\n if (Array.isArray(color)) {\n res = color;\n } else {\n res = reg\n .exec(color)[1]\n .split(\",\")\n .map((a) => parseFloat(a));\n if (type === \"rgb\") {\n res.push(1);\n }\n }\n\n return res;\n}\n\nfunction toKmlColor(color) {\n var s, r, g, b, o;\n if (color) {\n let res;\n if (Array.isArray(color)) {\n res = color;\n } else {\n if (/^rgba/.test(color)) {\n res = colorToArray(color, \"rgba\");\n } else if (/^rgb/.test(color)) {\n res = colorToArray(color, \"rgb\");\n }\n }\n if (Array.isArray(res)) {\n s = rgbToHex(res[0], res[1], res[2]);\n } else {\n s = color = color.replace(\"#\", \"\");\n }\n r = s.substr(0, 2);\n g = s.substr(2, 2);\n b = s.substr(4, 2);\n o = \"ff\";\n if (res && res[3]) {\n o = Math.floor(res[3] * 255).toString(16);\n }\n return o + b + g + r;\n }\n}\n\nfunction toKmlString(str, type) {\n var strs = [],\n a,\n b;\n\n switch (type) {\n case \"point\":\n str = str.replace(/^POINT\\(/, \"\").replace(/\\)$/, \"\");\n str = str.replace(/^POINT Z\\(/, \"\").replace(/\\)$/, \"\");\n str = str.replace(/^MULTIPOINT\\(/, \"\").replace(/\\)$/, \"\");\n str = str.replace(/^MULTIPOINT Z\\(/, \"\").replace(/\\)$/, \"\");\n break;\n case \"line\":\n str = str.replace(/^LINESTRING\\(/, \"\").replace(/\\)$/, \"\");\n str = str.replace(/^LINESTRING Z\\(/, \"\").replace(/\\)$/, \"\");\n break;\n case \"polygon\":\n strs = str.split(\"),(\");\n str = \"\";\n strs.forEach((coords, i) => {\n if (i === 0) {\n coords = coords.replace(/^POLYGON\\(\\(/, \"\").replace(/\\)$/, \"\");\n coords = coords.replace(/^POLYGON Z\\(\\(/, \"\").replace(/\\)$/, \"\");\n str += \"<outerBoundaryIs>\";\n str += \"<LinearRing>\";\n str += \"<coordinates>\" + coords + \"</coordinates>\";\n str += \"</LinearRing>\";\n str += \"</outerBoundaryIs>\";\n } else {\n coords = coords.replace(/\\)/g, \"\");\n str += \"<innerBoundaryIs>\";\n str += \"<LinearRing>\";\n str += \"<coordinates>\" + coords + \"</coordinates>\";\n str += \"</LinearRing>\";\n str += \"</innerBoundaryIs>\";\n }\n });\n break;\n case \"multiPolygon\":\n a = str.split(\")),((\");\n str = \"\";\n a.forEach((coords, t) => {\n if (t === 0) {\n coords = coords.replace(/^MULTIPOLYGON\\(\\(/, \"\").replace(/\\)$/, \"\");\n coords = coords\n .replace(/^MULTIPOLYGON Z\\(\\(\\(/, \"\")\n .replace(/\\)$/, \"\");\n }\n\n b = coords.split(\"),(\");\n\n str += \"<Polygon>\";\n b.forEach((coordinates, i) => {\n coordinates = coordinates\n .replace(/\\)/g, \"\")\n .split(\",\")\n .map((coordString) => {\n var coords = coordString.split(\" \");\n return coords[0] + \" \" + coords[1];\n });\n\n if (i === 0) {\n str += \"<outerBoundaryIs>\";\n str += \"<LinearRing>\";\n str += \"<coordinates>\" + coordinates + \"</coordinates>\";\n str += \"</LinearRing>\";\n str += \"</outerBoundaryIs>\";\n } else {\n str += \"<innerBoundaryIs>\";\n str += \"<LinearRing>\";\n str += \"<coordinates>\" + coordinates + \"</coordinates>\";\n str += \"</LinearRing>\";\n str += \"</innerBoundaryIs>\";\n }\n });\n str += \"</Polygon>\";\n });\n break;\n case \"multiLine\":\n str = str.replace(/^MULTILINESTRING\\(/, \"\").replace(/\\)$/, \"\");\n str = str.replace(/^MULTILINESTRING Z\\(/, \"\").replace(/\\)$/, \"\");\n let lines = str.split(\"),\");\n lines = lines.map((line) => {\n return line.replace(/[()]/g, \"\");\n });\n lines.forEach((line) => {\n str += `<LineString><coordinates>${line}</coordinates></LineString>`;\n });\n break;\n default:\n break;\n }\n\n return str\n .replace(/ /g, \"_\")\n .replace(/,/g, \" \")\n .replace(/_/g, \",\")\n .replace(/\\(/g, \"\")\n .replace(/\\)/g, \"\");\n}\n\nfunction point(f) {\n var str = \"\";\n str += \"<Point>\";\n str += \"<coordinates>\" + toKmlString(f, \"point\") + \"</coordinates>\";\n str += \"</Point>\";\n return str;\n}\n\nfunction line(f) {\n var str = \"\";\n str += \"<LineString>\";\n str += \"<coordinates>\" + toKmlString(f, \"line\") + \"</coordinates>\";\n str += \"</LineString>\";\n return str;\n}\n\nfunction polygon(f) {\n var str = \"\";\n str += \"<Polygon>\";\n str += toKmlString(f, \"polygon\");\n str += \"</Polygon>\";\n return str;\n}\n\nfunction multiPolygon(f) {\n var str = \"\";\n str += \"<MultiGeometry>\";\n str += toKmlString(f, \"multiPolygon\");\n str += \"</MultiGeometry>\";\n return str;\n}\n\nfunction multiLine(f) {\n var str = \"\";\n str += \"<MultiGeometry>\";\n str += toKmlString(f, \"multiLine\");\n str += \"</MultiGeometry>\";\n return str;\n}\n\nfunction safeInject(string) {\n string = string.toString();\n return string.replace(/<\\/?[^>]+(>|$)|&/g, \"\");\n}\n\nfunction filterProperties(template, properties) {\n var props = {};\n Object.keys(properties).forEach((property) => {\n var regExp = new RegExp(`{export:${property}}`);\n if (regExp.test(template)) {\n props[property] = properties[property];\n }\n });\n return props;\n}\n\nexport function transform(features, from, to) {\n return features.map((feature) => {\n var c = feature.clone(),\n style = Array.isArray(feature.getStyle())\n ? feature.getStyle()[1]\n : feature.getStyle();\n c.getGeometry().transform(from, to);\n c.setStyle(style);\n c.caption = feature.caption;\n c.infobox = feature.infobox;\n return c;\n });\n}\n\nexport function createXML(features, name) {\n var header = \"\",\n parser = new WKT(),\n doc = \"\";\n\n header +=\n '<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">';\n doc += \"<Document>\";\n doc += \"<name>\" + name + \"</name>\";\n\n doc += \"<Folder>\";\n doc += \"<name>\" + name + \"</name>\";\n doc += \"<open>0</open>\";\n\n features.forEach((feature, i) => {\n var style = Array.isArray(feature.getStyle())\n ? feature.getStyle()[1] || feature.getStyle()[0]\n : feature.getStyle();\n\n doc += '<Style id=\"' + i + '\">';\n if (style.getImage() instanceof Icon) {\n const scale =\n style?.getImage()?.getScale() ?? style.getImage().getSize()[0] / 32;\n doc += \"<IconStyle>\";\n doc += \"<scale>\" + scale + \"</scale>\";\n doc += \"<Icon>\";\n doc += \"<href>\" + style.getImage().getSrc() + \"</href>\";\n doc += \"</Icon>\";\n doc += \"</IconStyle>\";\n }\n\n if (style.getStroke() instanceof Stroke) {\n doc += \"<LineStyle>\";\n doc += \"<color>\" + toKmlColor(style.getStroke().getColor()) + \"</color>\";\n doc += \"<width>\" + style.getStroke().getWidth() + \"</width>\";\n doc += \"</LineStyle>\";\n }\n\n if (style.getFill() instanceof Fill) {\n doc += \"<PolyStyle>\";\n doc += \"<color>\" + toKmlColor(style.getFill().getColor()) + \"</color>\";\n doc += \"</PolyStyle>\";\n }\n\n doc += \"</Style>\";\n });\n\n features.forEach((feature, i) => {\n var style = Array.isArray(feature.getStyle())\n ? feature.getStyle()[1] || feature.getStyle()[0]\n : feature.getStyle();\n\n var text = style.getText() ? style.getText().getText() : \"\";\n\n var description = feature.getProperties().description || \"\",\n name =\n feature.getProperties().namn ||\n feature.getProperties().name ||\n feature.caption ||\n text;\n\n if (!description && feature.getProperties()) {\n description = \"<table>\";\n let properties = feature.getProperties();\n\n if (feature.infobox) {\n properties = filterProperties(feature.infobox, properties);\n }\n\n Object.keys(properties).forEach((property) => {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n description += \"<tr>\";\n description += \"<td>\" + property + \"</td>\";\n description += \"<td>\" + safeInject(properties[property]) + \"</td>\";\n description += \"</tr>\";\n }\n });\n\n description += \"</table>\";\n }\n\n doc += \"<Placemark>\";\n doc += \"<name>\" + (name || \"Ritobjekt \" + (i + 1)) + \"</name>\";\n doc +=\n \"<description>\" +\n (description || \"Ritobjekt \" + (i + 1)) +\n \"</description>\";\n doc += \"<styleUrl>#\" + i + \"</styleUrl>\";\n\n if (feature.getGeometry() instanceof Point) {\n doc += point(parser.writeFeature(feature));\n }\n if (feature.getGeometry() instanceof MultiPoint) {\n doc += point(parser.writeFeature(feature));\n }\n if (feature.getGeometry() instanceof LineString) {\n doc += line(parser.writeFeature(feature));\n }\n if (feature.getGeometry() instanceof MultiLineString) {\n doc += multiLine(parser.writeFeature(feature));\n }\n if (feature.getGeometry() instanceof Polygon) {\n doc += polygon(parser.writeFeature(feature));\n }\n if (feature.getGeometry() instanceof MultiPolygon) {\n doc += multiPolygon(parser.writeFeature(feature));\n }\n\n if (feature.getProperties().style) {\n doc += \"<ExtendedData>\";\n doc += '<Data name=\"style\">';\n doc += \"<value>\" + feature.getProperties().style + \"</value>\";\n doc += \"</Data>\";\n if (feature.getProperties().geometryType) {\n doc += '<Data name=\"geometryType\">';\n doc += \"<value>\" + feature.getProperties().geometryType + \"</value>\";\n doc += \"</Data>\";\n }\n doc += \"</ExtendedData>\";\n }\n doc += \"</Placemark>\";\n });\n\n doc += \"</Folder>\";\n doc += \"</Document>\";\n header += doc;\n header += \"</kml>\";\n\n return header;\n}\n","import React, { Component } from \"react\";\nimport propTypes from \"prop-types\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport CloseIcon from \"@material-ui/icons/Close\";\nimport FullscreenIcon from \"@material-ui/icons/Fullscreen\";\nimport FullscreenExitIcon from \"@material-ui/icons/FullscreenExit\";\nimport AspectRatioIcon from \"@material-ui/icons/AspectRatio\";\nimport { Hidden, Typography, IconButton, Box } from \"@material-ui/core\";\n\nconst styles = (theme) => {\n return {\n header: {\n padding: `${theme.spacing(1)}px ${theme.spacing(2)}px`,\n borderBottom: `4px solid ${theme.palette.primary.main}`,\n userSelect: \"none\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n minHeight: 46,\n },\n };\n};\n\nclass PanelHeader extends Component {\n static propTypes = {\n allowMaximizedWindow: propTypes.bool.isRequired,\n classes: propTypes.object.isRequired,\n color: propTypes.string,\n mode: propTypes.oneOf([\"window\", \"maximized\", \"minimized\"]),\n onClose: propTypes.func.isRequired,\n onMaximize: propTypes.func.isRequired,\n onMinimize: propTypes.func.isRequired,\n title: propTypes.string.isRequired,\n };\n\n renderCustomHeaderButtons = () => {\n const { customHeaderButtons } = this.props;\n return customHeaderButtons.map((buttonInfo, index) => {\n const HeaderActionIcon = buttonInfo.icon.type;\n const description = buttonInfo.description;\n return (\n <IconButton\n key={index}\n onClick={buttonInfo.onClickCallback}\n size=\"small\"\n >\n <Typography variant=\"srOnly\">{description}</Typography>\n <HeaderActionIcon />\n </IconButton>\n );\n });\n };\n\n shouldRenderCustomHeaderButtons = () => {\n const { customHeaderButtons } = this.props;\n return customHeaderButtons && customHeaderButtons.length > 0;\n };\n\n render() {\n const { allowMaximizedWindow, classes, mode } = this.props;\n return (\n <header\n className={classes.header}\n style={{ borderColor: this.props.color }} // Allow for dynamic override of accent border color\n >\n <Typography component=\"h1\" variant=\"button\" align=\"left\" noWrap={true}>\n {this.props.title}\n </Typography>\n <Box display=\"flex\" component=\"nav\">\n {this.shouldRenderCustomHeaderButtons() &&\n this.renderCustomHeaderButtons()}\n {mode !== \"maximized\" && // If window isn't in fit screen mode currently…\n (mode === \"minimized\" ? ( // … but it's minimized…\n <IconButton size=\"small\" onClick={this.props.onMaximize}>\n <Typography variant=\"srOnly\">Maximera fönster</Typography>\n <FullscreenIcon // …render the maximize icon.\n />\n </IconButton>\n ) : (\n // If it's already in \"window\" mode though, render the minimize icon.\n <IconButton size=\"small\" onClick={this.props.onMinimize}>\n <Typography variant=\"srOnly\">Minimera fönster</Typography>\n <FullscreenExitIcon />\n </IconButton>\n ))}\n <Hidden xsDown>\n {allowMaximizedWindow && ( // If we're not on mobile and config allows fit-to-screen…\n <IconButton size=\"small\" onClick={this.props.onMaximize}>\n <Typography variant=\"srOnly\">Maximera fönster</Typography>\n <AspectRatioIcon // … render the action button. Note: it will remain the same…\n />\n </IconButton>\n )}\n </Hidden>\n <IconButton size=\"small\" onClick={this.props.onClose}>\n <Typography variant=\"srOnly\">Stäng fönster</Typography>\n <CloseIcon />\n </IconButton>\n </Box>\n </header>\n );\n }\n}\n\nexport default withStyles(styles)(PanelHeader);\n","import React from \"react\";\nimport SearchBar from \"./SearchBar\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { withSnackbar } from \"notistack\";\nimport Observer from \"react-event-observer\";\nimport EditIcon from \"@material-ui/icons/Edit\";\nimport Crop54Icon from \"@material-ui/icons/Crop54\";\nimport TouchAppIcon from \"@material-ui/icons/TouchApp\";\nimport RadioButtonUncheckedIcon from \"@material-ui/icons/RadioButtonUnchecked\";\nimport SettingsIcon from \"@material-ui/icons/Settings\";\nimport MapViewModel from \"./MapViewModel\";\nimport KmlExport from \"./utils/KmlExport\";\nimport XLSXExport from \"./utils/XLSXExport\";\nimport { encodeCommas, decodeCommas } from \"../../utils/StringCommaCoder\";\nimport LocalStorageHelper from \"../../utils/LocalStorageHelper\";\nimport { functionalOk as functionalCookieOk } from \"models/Cookie\";\n\nconst styles = () => ({\n inputRoot: {\n width: \"100%\",\n },\n});\n\nclass Search extends React.PureComponent {\n defaultSearchOptions = {\n enableLabelOnHighlight: true,\n searchInVisibleLayers: false,\n wildcardAtStart: false,\n wildcardAtEnd: true,\n matchCase: false,\n activeSpatialFilter: \"intersects\",\n maxResultsPerDataset: !isNaN(this.props.options.maxResultsPerDataset)\n ? this.props.options.maxResultsPerDataset\n : 100,\n };\n\n state = {\n searchImplementedPluginsLoaded: false,\n searchSources: [],\n searchResults: { featureCollections: [], errors: [] },\n autocompleteList: [],\n searchString: \"\",\n searchFromAutoComplete: false,\n searchActive: \"\",\n autoCompleteOpen: false,\n loading: false,\n searchOptions: LocalStorageHelper.get(\n \"searchOptions\",\n this.defaultSearchOptions\n ),\n failedWFSFetchMessage: \"\",\n resultPanelCollapsed: false,\n };\n\n // Used for setTimeout/clearTimeout, in order to delay update of autocomplete when user is typing\n timer = null;\n\n // Amount of time before autocomplete is updated\n delayBeforeAutoSearch =\n isNaN(this.props.options.delayBeforeAutoSearch) === false\n ? this.props.options.delayBeforeAutoSearch\n : 500;\n\n searchImplementedPlugins = [];\n featuresToFilter = [];\n localObserver = Observer();\n\n snackbarKey = null;\n\n defaultSearchTools = [\n {\n name: \"Sök med polygon\",\n icon: <EditIcon />,\n type: \"Polygon\",\n enabled: this.props.options.enablePolygonSearch ?? true,\n toolTipTitle:\n \"Genomför en sökning i ett område genom att rita en polygon.\",\n onClickEventName: \"search.spatialSearchActivated\",\n },\n {\n name: \"Sök med radie\",\n icon: <RadioButtonUncheckedIcon />,\n type: \"Circle\",\n enabled: this.props.options.enableRadiusSearch ?? true,\n toolTipTitle: \"Genomför en sökning i ett område genom att rita en cirkel\",\n onClickEventName: \"search.spatialSearchActivated\",\n },\n {\n name: \"Sök med objekt\",\n icon: <TouchAppIcon />,\n type: \"Select\",\n enabled: this.props.options.enableSelectSearch ?? true,\n toolTipTitle:\n \"Genomför en sökning genom att välja en eller flera områden i kartan.\",\n onClickEventName: \"search.spatialSearchActivated\",\n },\n {\n name: \"Sök inom vyn\",\n icon: <Crop54Icon />,\n type: \"Extent\",\n enabled: this.props.options.enableExtentSearch ?? true,\n toolTipTitle: \"Genomför en sökning i hela det område som kartan visar.\",\n onClickEventName: \"search.spatialSearchActivated\",\n },\n {\n name: \"Sökinställningar\",\n icon: <SettingsIcon />,\n type: \"SETTINGS\",\n toolTipTitle: \"Ändra sökinställningarna.\",\n onClickEventName: \"\",\n },\n ];\n\n constructor(props) {\n super(props);\n this.map = props.map;\n this.searchModel = props.app.appModel.searchModel;\n this.globalObserver = props.app.globalObserver;\n this.initMapViewModel();\n this.initExportHandlers();\n this.bindSubscriptions();\n }\n\n initMapViewModel = () => {\n const { app } = this.props;\n this.mapViewModel = new MapViewModel({\n // Init the MapViewModel using merged options from both\n // Admin UI (\"options\") and user's setting (\"this.state.options\")\n options: {\n ...this.props.options,\n ...this.state.searchOptions,\n },\n localObserver: this.localObserver,\n map: this.map,\n app: app,\n });\n };\n\n initExportHandlers = () => {\n this.kmlExport = new KmlExport({\n options: this.props.options,\n localObserver: this.localObserver,\n map: this.map,\n });\n this.XLSXExport = new XLSXExport({\n options: this.props.options,\n localObserver: this.localObserver,\n });\n };\n\n resetFeaturesToFilter = () => {\n this.featuresToFilter = [];\n };\n\n setFeaturesToFilter = (arrayOfFeatures) => {\n this.featuresToFilter = arrayOfFeatures;\n };\n\n bindSubscriptions = () => {\n this.localObserver.subscribe(\"on-draw-start\", (type) => {\n if (type === \"Circle\") {\n this.snackbarKey = this.props.enqueueSnackbar(\n \"Tryck i kartan där du vill ha centrumpunkten, dra sedan utåt och släpp.\",\n {\n variant: \"information\",\n anchorOrigin: { vertical: \"bottom\", horizontal: \"center\" },\n }\n );\n } else if (type === \"Polygon\") {\n this.snackbarKey = this.props.enqueueSnackbar(\n \"Tryck en gång i kartan för varje nod i polygonen. Genomför sökningen genom att trycka på den sista noden en gång till.\",\n {\n variant: \"information\",\n anchorOrigin: { vertical: \"bottom\", horizontal: \"center\" },\n }\n );\n }\n this.setState({ searchActive: \"draw\" });\n });\n this.localObserver.subscribe(\"on-draw-end\", (feature) => {\n this.doFeaturesSearch([feature]);\n });\n this.localObserver.subscribe(\"on-select-search-start\", () => {\n this.snackbarKey = this.props.enqueueSnackbar(\n \"Tryck på den yta i kartan där du vill genomföra en sökning. Håll in CTRL för att välja flera ytor.\",\n {\n variant: \"information\",\n anchorOrigin: { vertical: \"bottom\", horizontal: \"center\" },\n }\n );\n\n this.setState({ searchActive: \"selectSearch\" });\n });\n this.localObserver.subscribe(\"on-search-selection-done\", (features) => {\n this.doFeaturesSearch(features);\n });\n this.localObserver.subscribe(\"search-within-extent\", (features) => {\n this.setState({ searchActive: \"extentSearch\" });\n this.doFeaturesSearch(features);\n });\n this.localObserver.subscribe(\"minimizeSearchResultList\", () => {\n this.setState({ resultPanelCollapsed: false });\n });\n this.localObserver.subscribe(\"extent-search-failed\", () => {\n this.snackbarKey = this.props.enqueueSnackbar(\n \"Ett problem uppstod vid sökning i området. Kontakta systemadministratören.\",\n {\n variant: \"warning\",\n anchorOrigin: { vertical: \"top\", horizontal: \"center\" },\n }\n );\n });\n };\n\n doFeaturesSearch = (features) => {\n this.props.closeSnackbar(this.snackbarKey);\n this.setFeaturesToFilter(features);\n this.doSearch();\n };\n\n getPluginsConfToUseSearchInterface = () => {\n const { app } = this.props;\n return Object.values(app.appModel.plugins).filter((plugin) => {\n return (\n plugin.options.searchImplemented &&\n plugin.searchInterface.getSearchMethods\n );\n });\n };\n\n tryBindSearchMethods = (plugins) => {\n return plugins.map((plugin) => {\n return plugin.searchInterface.getSearchMethods.then((methods) => {\n plugin.searchInterface.getFunctionality = methods?.getFunctionality;\n plugin.searchInterface.getResults = methods?.getResults;\n return plugin;\n });\n });\n };\n\n pluginsHavingCorrectSearchMethods = (plugins) => {\n return plugins.filter((plugin) => {\n const getResults = plugin.searchInterface.getResults;\n const getFunctionality = plugin.searchInterface.getFunctionality;\n if (!getResults || !getFunctionality) {\n this.displayPluginMissingCrucialMethodsWarning(plugin);\n }\n return getResults && getFunctionality;\n });\n };\n\n displayPluginMissingCrucialMethodsWarning = (plugin) => {\n console.warn(\n `${\n plugin.type ?? \"<Plugin type missing>\"\n } is marked as a search-plugin, but is missing the getResults() and/or getFunctionality() method(s) in it's searchInterface.\n\n Because of this, the search component will not make use of this plugin. \n \n If you intend to use this plugin as a search-plugin, make sure to implement both methods. \n If you do not intend to use this plugin within the search component, please update plugin-config so that searchImplemented = false.`\n );\n };\n\n //For a plugin to use the searchInterface, following must be met\n //Must have option searchImplemented = true in tool-config\n //Must \"inject\" a method called getSearchMethods returning a promise on the object plugin.searchInterface\n //The object searchInterface is put onto the plugin upon loading in App.js\n //Promise must be resolved into object with two methods getResults and getFunctionality\n\n getSearchImplementedPlugins = () => {\n const pluginsConfToUseSearchInterface =\n this.getPluginsConfToUseSearchInterface();\n const searchBoundPlugins = this.tryBindSearchMethods(\n pluginsConfToUseSearchInterface\n );\n return Promise.all(searchBoundPlugins).then((plugins) => {\n return this.pluginsHavingCorrectSearchMethods(plugins);\n });\n };\n\n getExternalSearchTools = (searchImplementedSearchTools) => {\n // TODO (To discuss)\n // We demand that getFunctionality is implemented, but we do not demand that\n // the method returns a \"correct\" object. If the method return a null-ish\n // value we simply discard the extra functionality. Maybe we shouldn't demand that\n // getFunctionality is implemented?\n return searchImplementedSearchTools\n .filter((searchImplementedPlugin) => {\n return searchImplementedPlugin.searchInterface.getFunctionality();\n })\n .map((toolWithFunctionality) => {\n return toolWithFunctionality.searchInterface.getFunctionality();\n });\n };\n\n getSearchTools = (searchImplementedSearchTools) => {\n return this.defaultSearchTools.concat(\n this.getExternalSearchTools(searchImplementedSearchTools)\n );\n };\n\n componentDidMount = () => {\n this.globalObserver.subscribe(\"core.appLoaded\", () => {\n this.getSearchImplementedPlugins().then((searchImplementedPlugins) => {\n this.setState(\n {\n searchImplementedPluginsLoaded: true,\n searchImplementedPlugins: searchImplementedPlugins,\n searchTools: this.getSearchTools(searchImplementedPlugins),\n },\n () => {\n this.handlePotentialUrlQuerySearch();\n }\n );\n });\n });\n };\n\n getSourcesByIds = (sourceIds) => {\n return this.searchModel\n .getSources()\n .filter((source) => sourceIds.indexOf(source.id) > -1);\n };\n\n handlePotentialUrlQuerySearch = () => {\n const { appModel } = this.props.app;\n // Grab the (already decoded) URL param values\n const q = appModel.config.urlParams.get(\"q\")?.trim(); // Use of \"?.\" will return either a String or undefined\n const s = appModel.config.urlParams.get(\"s\")?.trim(); // (As opposed to null which would be the return value of get() otherwise!).\n\n // Check so that we have a searchString in the url (q)\n if (q !== undefined && q.length > 0) {\n // Initializing sources to an empty array\n // (The model will search in all sources if searchSources is set to [])\n let sources = [];\n // If source parameter is set in url (s)\n // Get the sources corresponding to the ids\n if (s !== undefined && s.length > 0) {\n const sourceIds = s.split(\",\");\n sources = this.getSourcesByIds(sourceIds);\n }\n // Update state according to searchString and sources from url\n // and do a search.\n this.setState({ searchString: q, searchSources: sources }, () => {\n this.doSearch();\n });\n }\n };\n\n handleOnClear = () => {\n this.setState({\n searchString: \"\",\n searchActive: \"\",\n showSearchResults: false,\n searchResults: { featureCollections: [], errors: [] },\n failedWFSFetchMessage: \"\",\n resultPanelCollapsed: false,\n loading: false,\n });\n this.resetFeaturesToFilter();\n this.localObserver.publish(\"clearMapView\");\n };\n\n handleSearchInput = (event, value, reason) => {\n let searchString = value?.autocompleteEntry || value || \"\";\n\n if (searchString !== \"\") {\n this.setState(\n {\n searchString: searchString,\n searchFromAutoComplete: true,\n searchActive: \"input\",\n },\n () => {\n this.doSearch();\n }\n );\n } else {\n this.setState({\n searchString: searchString,\n });\n }\n };\n\n isUserInput = (searchString, reason) => {\n // Reason equals \"reset\" when input is changed programmatically\n // This catches user click on clear (searchString === 0)\n return (\n (searchString.length === 0 && reason === \"reset\") || reason === \"input\"\n );\n };\n\n handleOnAutocompleteInputChange = (event, searchString, reason) => {\n if (this.isUserInput(searchString, reason)) {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.localObserver.publish(\"clearMapView\");\n this.setState(\n {\n autoCompleteOpen: searchString.length >= 3,\n autocompleteList: [],\n loading: searchString.length >= 3,\n showSearchResults: false,\n searchString: searchString,\n resultPanelCollapsed: false,\n },\n () => {\n if (this.state.searchString.length >= 3) {\n this.updateAutocompleteList(this.state.searchString);\n } else {\n this.setState({\n autocompleteList: [],\n });\n }\n }\n );\n }, this.delayBeforeAutoSearch);\n\n // Announce the input change, so other plugins can be notified\n this.globalObserver.publish(\"search.searchPhraseChanged\", searchString);\n }\n };\n\n updateSearchOptions = (searchOptions) => {\n // Ensure that the latest search options are in state\n this.setState({ searchOptions });\n\n // We need to re-initiate the FeatureStyle only if some specific\n // settings have changed (those that effect the style that renders\n // result features to the OL searchResults source).\n const isStyleRefreshNeeded =\n searchOptions.enableLabelOnHighlight !==\n this.state.searchOptions.enableLabelOnHighlight;\n\n // Refresh the Feature Style, if needed\n isStyleRefreshNeeded &&\n this.mapViewModel.refreshFeatureStyle({\n enableLabelOnHighlight: searchOptions.enableLabelOnHighlight,\n });\n\n // If functional cookies are allowed, we'll save the current settings\n // to local storage, so it can be retrieved on app reload.\n if (functionalCookieOk()) {\n LocalStorageHelper.set(\"searchOptions\", searchOptions);\n }\n };\n\n handleOnClickOrKeyboardSearch = () => {\n if (this.hasEnoughCharsForSearch()) {\n this.setState({ searchFromAutoComplete: false }, () => {\n // Get rid of the on-screen keyboard on mobile devices\n document.activeElement.blur();\n this.doSearch();\n });\n }\n };\n\n setSearchSources = (sources) => {\n this.setState({\n searchSources: sources,\n });\n };\n\n handleSearchBarKeyPress = (event) => {\n if (event.which === 13 || event.keyCode === 13) {\n if (event.target.id === \"searchInputField\") {\n this.handleOnClickOrKeyboardSearch();\n }\n }\n };\n\n getAutoCompleteFetchSettings = () => {\n const { options } = this.props;\n let fetchSettings = { ...this.searchModel.getSearchOptions() }; //Getting default-options when fetching auto\n fetchSettings = {\n ...fetchSettings,\n wildcardAtStart: options.autocompleteWildcardAtStart || false,\n getPossibleCombinations: true,\n initiator: \"autocomplete\",\n };\n return fetchSettings;\n };\n\n getArrayWithSearchWords = (searchString) => {\n let tempStringArray = this.splitAndTrimOnCommas(searchString);\n return tempStringArray.join(\" \").split(\" \");\n };\n\n splitAndTrimOnCommas = (searchString) => {\n return searchString.split(\",\").map((string) => {\n return string.trim();\n });\n };\n\n escapeRegExp = (string) => {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n };\n\n sortSearchFieldsOnFeature = (searchFields, feature, wordsInTextField) => {\n const matchedSearchFields = [];\n\n // We loop over each word in the input field first to ensure\n // that we don't mess upp the order of the displayFields...\n wordsInTextField.forEach((word) => {\n // then we get the searchFields that has not been matched yet\n searchFields\n .filter((sf) => !matchedSearchFields.includes(sf))\n // and loop over these...\n .forEach((sf) => {\n // to find searchFields matching the current word...\n const searchFieldMatch = RegExp(\n `^${this.escapeRegExp(word)}\\\\W*`,\n \"i\"\n ).test(feature.get(sf) || \"\");\n // If we find a match, and the matched searchField\n // returns a feature prop which is not undefined...\n if (feature.get(sf)) {\n // we add the searchField to the array of matched\n // searchFields.\n if (searchFieldMatch) {\n matchedSearchFields.push(sf);\n }\n }\n });\n });\n\n // The function should return ALL searchField (no matter if\n // they have been matched or not. Therefore we get the searchFields\n // that have not been matched)...\n const unMatchedSearchFields = searchFields.filter(\n (sf) => !matchedSearchFields.includes(sf) && feature.get(sf)\n );\n // And concatenate the matched searchFields with the unMatched searchFields.\n return matchedSearchFields.concat(unMatchedSearchFields);\n };\n\n getSortedAutocompleteEntry = (feature) => {\n let autocompleteEntry = \"\";\n feature.searchFieldOrder.map((sf, index) => {\n const featureProperty = feature.get(sf);\n const propertyAsString =\n typeof featureProperty === \"string\"\n ? featureProperty\n : featureProperty.toString();\n if (index === feature.searchFieldOrder.length - 1) {\n return (autocompleteEntry = autocompleteEntry.concat(\n encodeCommas(propertyAsString)\n ));\n } else {\n return (autocompleteEntry = autocompleteEntry.concat(\n `${encodeCommas(propertyAsString)}, `\n ));\n }\n });\n return autocompleteEntry;\n };\n\n getAutocompleteDataset = (featureCollection) => {\n return featureCollection.value.features.map((feature) => {\n const dataset = featureCollection.source.caption;\n const origin = featureCollection.origin;\n const autocompleteEntry = this.getSortedAutocompleteEntry(feature);\n return {\n dataset,\n autocompleteEntry,\n origin,\n };\n });\n };\n\n sortSearchFieldsOnFeatures = (featureCollection, wordsInTextField) => {\n featureCollection.value.features.forEach((feature) => {\n feature.searchFieldOrder = this.sortSearchFieldsOnFeature(\n featureCollection.source.searchFields,\n feature,\n wordsInTextField\n );\n });\n };\n\n flattenAndSortAutoCompleteList = (searchResults) => {\n let wordsInTextField = this.getArrayWithSearchWords(\n this.state.searchString\n );\n\n const resultsPerDataset = searchResults.featureCollections.map(\n (featureCollection) => {\n this.sortSearchFieldsOnFeatures(featureCollection, wordsInTextField);\n // The final filter is to ensure that we get rid of objects that lack\n // the 'autocompleteEntry' property, which is necessary for the\n // MUI Autocomplete component.\n return this.getAutocompleteDataset(featureCollection).filter(\n (e) => e.autocompleteEntry\n );\n }\n );\n\n // Now we have an Array of Arrays, one per dataset. For the Autocomplete component\n // however, we need just one Array, so let's flatten the results:\n\n return this.sortAutocompleteList(resultsPerDataset.flat());\n };\n\n sortAutocompleteList = (flatAutocompleteArray) => {\n return flatAutocompleteArray.sort((a, b) =>\n decodeCommas(a.autocompleteEntry).localeCompare(\n decodeCommas(b.autocompleteEntry),\n undefined,\n { numeric: true }\n )\n );\n };\n\n getMergeResultsFromAllSources = (results) => {\n return results.reduce(\n (searchResults, result) => {\n searchResults.featureCollections =\n searchResults.featureCollections.concat(\n result.value.featureCollections\n );\n searchResults.errors = searchResults.errors.concat(result.value.errors);\n return searchResults;\n },\n { errors: [], featureCollections: [] }\n );\n };\n\n fetchResultFromSearchModel = async (fetchOptions) => {\n // Check if the searchString is encapsuled with quotation marks\n const searchStringIsEncapsuled = this.searchStringEncapsuled();\n\n // If the searchString is encapsuled with quotation marks (meaning that the user is\n // searching for an exacts phrase, we want to disable potential wildcards in the\n // fetchOptions.\n if (searchStringIsEncapsuled) {\n fetchOptions = {\n ...fetchOptions,\n wildcardAtStart: false,\n wildcardAtEnd: false,\n };\n }\n\n // Potential quotation marks in the searchString must be removed before\n // we perform the search.\n const searchString = this.getCleanedSearchString();\n\n let { searchSources } = this.state;\n\n if (searchSources.length === 0) {\n searchSources = this.searchModel.getSources();\n }\n\n if (this.state.searchOptions.searchInVisibleLayers) {\n searchSources = this.mapViewModel.getVisibleSearchLayers();\n }\n\n let active = true;\n const promise = this.searchModel.getResults(\n searchString,\n searchSources,\n fetchOptions\n );\n\n return Promise.allSettled([\n promise,\n ...this.fetchResultsFromPlugins(fetchOptions),\n ])\n .then((results) => {\n results = results.filter((result) => result.status !== \"rejected\");\n results = this.removeCollectionsWithoutFeatures(results);\n let searchResults = this.getMergeResultsFromAllSources(results);\n // It's possible to handle any errors in the UI by checking if Search Model returned any\n searchResults.errors.length > 0 &&\n console.error(\"Autocomplete error: \", searchResults.errors);\n\n // Prepare all features so that they do have titles/short titles\n searchResults.featureCollections.forEach((fc) => {\n fc.value.features.forEach((f) => {\n const { featureTitle, shortFeatureTitle } = this.getFeatureLabels(\n f,\n fc.source\n );\n f.featureTitle = featureTitle;\n f.shortFeatureTitle = shortFeatureTitle;\n });\n });\n\n return searchResults;\n })\n .catch((error) => {\n console.error(\"Autocomplete error: \", error);\n\n // Also, set \"open\" state variable to false, which\n // abort the \"loading\" state of Autocomplete.\n if (active) {\n this.setState({\n open: false,\n });\n }\n });\n };\n\n // Returns true if the searchString is encapsuled in quotation marks.\n searchStringEncapsuled = () => {\n const { searchString } = this.state;\n return searchString.startsWith('\"') && searchString.endsWith('\"');\n };\n\n // Removes potential quotation marks from the searchString\n getCleanedSearchString = () => {\n const { searchString } = this.state;\n return searchString.replace(/\"/g, \"\");\n };\n\n getPotentialWFSErrorMessage = (searchResults) => {\n return searchResults.errors.length === 0\n ? ``\n : `OBS: Kunde inte hämta data från: `.concat(\n searchResults.errors\n .map((error, index) => {\n return index === searchResults.errors.length - 1\n ? error.source.caption\n : `${error.source.caption}, `;\n })\n .join(\"\")\n );\n };\n\n async doSearch() {\n this.setState({ loading: true });\n const fetchOptions = this.getSearchResultsFetchSettings();\n const searchResults = await this.fetchResultFromSearchModel(fetchOptions);\n const failedWFSFetchMessage =\n this.getPotentialWFSErrorMessage(searchResults);\n\n this.setState({\n searchResults,\n showSearchResults: true,\n loading: false,\n autoCompleteOpen: false,\n failedWFSFetchMessage,\n resultPanelCollapsed: false,\n });\n\n let features = this.extractFeaturesFromFeatureCollections(\n searchResults.featureCollections\n );\n\n features = this.filterFeaturesWithGeometry(features);\n\n // If we got more than 1 result, publish event below\n if (features.length !== 1) {\n this.localObserver.publish(\"map.addFeaturesToResultsLayer\", features);\n }\n // If we get a single search-result, we add it to the map in the searchResultList-component instead,\n // unless clean mode is true. In that case, there's another event we want to publish.\n else if (this.props.app.appModel.config.mapConfig.map.clean === true) {\n const feature = features[0];\n\n this.localObserver.publish(\n \"map.addAndHighlightFeatureInSearchResultLayer\",\n {\n feature,\n }\n );\n }\n }\n\n getFeatureLabels = (feature, source) => {\n if (feature.featureTitle && feature.shortFeatureTitle) {\n return {\n featureTitle: feature.featureTitle,\n shortFeatureTitle: feature.shortFeatureTitle,\n };\n }\n\n const reducerFn = (featureTitleString, df) => {\n let displayField = feature.get(df);\n if (Array.isArray(displayField)) {\n displayField = displayField.join(\", \");\n }\n if (displayField) {\n if (featureTitleString.length > 0) {\n featureTitleString = featureTitleString.concat(` | ${displayField}`);\n } else {\n featureTitleString = displayField.toString();\n }\n }\n return featureTitleString;\n };\n\n // Prepare the title be using the defined displayFields. Note that this\n // can not be left empty: it is used as input to the MUI Autocomplete component\n // and supplying an empty string is not allowed here. See also the\n // comment on shortFeatureTitle below.\n const featureTitle =\n source.displayFields?.reduce(reducerFn, \"\") || \"Visningsfält saknas\";\n\n // Also, try to prepare the short title. It's possible that\n // this array is not defined though, and in that case, we want\n // an empty label as shortFeatureTitle.\n const shortFeatureTitle =\n source.shortDisplayFields?.reduce(reducerFn, \"\") || \"\";\n return { featureTitle, shortFeatureTitle };\n };\n\n filterFeaturesWithGeometry = (features) => {\n return features.filter((feature) => {\n return feature.getGeometry() != null;\n });\n };\n\n extractFeaturesFromFeatureCollections = (featureCollections) => {\n // Let's return an Array of features. While we're on it,\n // let's also decorate each feature with two properties,\n // featureTitle and shortFeature title, so they're ready to\n // use when we're styling the features in the ol.Source.\n return featureCollections\n .map((fc) => {\n return fc.value.features.map((f) => {\n return f;\n });\n })\n .flat();\n };\n\n getNumResults = (searchResults) => {\n let numResults = 0;\n searchResults.featureCollections.forEach((fc) => {\n numResults += fc.value.features.length;\n });\n return numResults;\n };\n\n updateAutocompleteList = async () => {\n let fetchOptions = this.getAutoCompleteFetchSettings();\n let autoCompleteResult = await this.fetchResultFromSearchModel(\n fetchOptions\n );\n\n this.setState({\n autocompleteList: this.prepareAutocompleteList(autoCompleteResult),\n loading: false,\n });\n };\n\n anySearchImplementedPlugins = () => {\n return (\n this.state.searchImplementedPlugins &&\n this.state.searchImplementedPlugins.length === 0\n );\n };\n\n fetchResultsFromPlugins = (fetchOptions) => {\n const { searchString } = this.state;\n if (this.anySearchImplementedPlugins()) {\n return [];\n }\n return this.state.searchImplementedPlugins.reduce((promises, plugin) => {\n if (plugin.searchInterface.getResults) {\n //Had to make a deep clone to not directly manipulate the reference from plugin\n promises.push(\n plugin.searchInterface\n .getResults(searchString, fetchOptions)\n .then((res) => {\n return {\n errors: res.errors,\n featureCollections: res.featureCollections,\n };\n })\n );\n return promises;\n }\n return promises;\n }, []);\n };\n\n hasEnoughCharsForSearch = () => {\n const { searchString } = this.state;\n // It may seem small with 1 character, but we must allow users to force\n // a search. Please note that this will not be invoked for autocomplete\n // searches (they still need to be at least 3 characters to start searching).\n // This will however allow for search terms such as \"K4*\", which can well\n // be a valid prefix for some attribute value, and users must be able to\n // search for that.\n // However, >=1 means that we don't allow completely empty searches.\n return searchString.length >= 1;\n };\n\n getSearchResultsFetchSettings = () => {\n return {\n ...this.getUserCustomFetchSettings(this.searchModel.getSearchOptions()),\n initiator: \"search\",\n };\n };\n\n removeCollectionsWithoutFeatures = (results) => {\n return results.map((res) => {\n let featureCollections = res.value.featureCollections.filter(\n (featureCollection) => {\n return featureCollection.value.features.length > 0;\n }\n );\n res.value.featureCollections = featureCollections;\n return res;\n });\n };\n\n prepareAutocompleteList = (searchResults) => {\n let maxSlots = 7;\n let numSourcesWithResults = searchResults.featureCollections.length;\n\n if (numSourcesWithResults > maxSlots) {\n searchResults.featureCollections = searchResults.featureCollections.slice(\n 0,\n maxSlots\n );\n }\n\n let numResults = 0;\n searchResults.featureCollections.forEach((fc) => {\n numResults += fc.value.features.length;\n });\n\n let spacesPerSource = Math.max(\n 1,\n Math.min(\n Math.floor(numResults / numSourcesWithResults),\n Math.floor(maxSlots / numSourcesWithResults)\n )\n );\n\n const autoCompleteList = this.flattenAndSortAutoCompleteList(searchResults);\n\n if (numResults > maxSlots) {\n // The list must be shortened before we return\n return this.shortenAutoCompleteList(autoCompleteList, spacesPerSource);\n }\n return autoCompleteList;\n };\n\n shortenAutoCompleteList = (autoCompleteList, spacesPerSource) => {\n let shortenedAutoComplete = [];\n\n const groupedAutoComplete = this.groupObjArrayByProp(\n autoCompleteList,\n \"dataset\"\n );\n\n for (const group in groupedAutoComplete) {\n shortenedAutoComplete = [\n ...shortenedAutoComplete,\n ...groupedAutoComplete[group].slice(0, spacesPerSource),\n ];\n }\n return shortenedAutoComplete;\n };\n\n groupObjArrayByProp = (array, property) => {\n return array.reduce((grouped, obj) => {\n if (!grouped[obj[property]]) {\n grouped[obj[property]] = [];\n }\n grouped[obj[property]].push(obj);\n return grouped;\n }, {});\n };\n\n getUserCustomFetchSettings = (searchOptionsFromModel) => {\n const {\n activeSpatialFilter,\n matchCase,\n wildcardAtEnd,\n wildcardAtStart,\n maxResultsPerDataset,\n } = this.state.searchOptions;\n return {\n ...searchOptionsFromModel,\n activeSpatialFilter: activeSpatialFilter,\n getPossibleCombinations: this.state.searchFromAutoComplete ? false : true,\n featuresToFilter: this.featuresToFilter || [],\n matchCase: matchCase,\n wildcardAtStart: wildcardAtStart,\n wildcardAtEnd: wildcardAtEnd,\n maxResultsPerDataset: maxResultsPerDataset,\n };\n };\n\n toggleCollapseSearchResults = () => {\n this.setState({ resultPanelCollapsed: !this.state.resultPanelCollapsed });\n };\n\n render() {\n const { classes } = this.props;\n const {\n searchString,\n searchActive,\n searchResults,\n autocompleteList,\n autoCompleteOpen,\n showSearchResults,\n loading,\n searchOptions,\n searchSources,\n searchTools,\n failedWFSFetchMessage,\n resultPanelCollapsed,\n } = this.state;\n\n return (\n this.state.searchImplementedPluginsLoaded &&\n this.props.app.appModel.config.mapConfig.map.clean === false && (\n <SearchBar\n classes={{\n root: classes.inputRoot,\n }}\n escapeRegExp={this.escapeRegExp}\n localObserver={this.localObserver}\n searchTools={searchTools}\n searchResults={searchResults}\n handleSearchInput={this.handleSearchInput}\n searchString={searchString}\n searchActive={searchActive}\n handleOnClickOrKeyboardSearch={this.handleOnClickOrKeyboardSearch}\n autoCompleteOpen={autoCompleteOpen}\n showSearchResults={showSearchResults}\n resultPanelCollapsed={resultPanelCollapsed}\n toggleCollapseSearchResults={this.toggleCollapseSearchResults}\n handleOnAutocompleteInputChange={this.handleOnAutocompleteInputChange}\n handleOnClear={this.handleOnClear}\n autocompleteList={autocompleteList}\n searchModel={this.searchModel}\n searchOptions={searchOptions}\n updateSearchOptions={this.updateSearchOptions}\n setSearchSources={this.setSearchSources}\n loading={loading}\n searchSources={searchSources}\n handleSearchBarKeyPress={this.handleSearchBarKeyPress}\n getArrayWithSearchWords={this.getArrayWithSearchWords}\n failedWFSFetchMessage={failedWFSFetchMessage}\n {...this.props}\n />\n )\n );\n }\n}\nexport default withStyles(styles)(withSnackbar(Search));\n","import React from \"react\";\n\nimport PropTypes from \"prop-types\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport cslx from \"clsx\";\nimport { SnackbarProvider } from \"notistack\";\nimport Observer from \"react-event-observer\";\nimport { isMobile } from \"../utils/IsMobile\";\nimport SrShortcuts from \"../components/SrShortcuts/SrShortcuts\";\nimport AppModel from \"../models/AppModel.js\";\nimport {\n setConfig as setCookieConfig,\n functionalOk as functionalCookieOk,\n} from \"models/Cookie\";\n\nimport Window from \"./Window.js\";\nimport CookieNotice from \"./CookieNotice\";\nimport Introduction from \"./Introduction\";\nimport Announcement from \"./Announcement/Announcement\";\nimport Alert from \"./Alert\";\nimport PluginWindows from \"./PluginWindows\";\n\nimport Search from \"./Search/Search.js\";\n\nimport Zoom from \"../controls/Zoom\";\nimport User from \"../controls/User\";\nimport Rotate from \"../controls/Rotate\";\nimport ScaleLine from \"../controls/ScaleLine\";\nimport Attribution from \"../controls/Attribution.js\";\nimport MapCleaner from \"../controls/MapCleaner\";\nimport MapResetter from \"../controls/MapResetter\";\nimport MapSwitcher from \"../controls/MapSwitcher\";\nimport Information from \"../controls/Information\";\nimport PresetLinks from \"../controls/PresetLinks\";\n\nimport DrawerToggleButtons from \"../components/Drawer/DrawerToggleButtons\";\n\nimport {\n Box,\n Divider,\n Drawer,\n Grid,\n Hidden,\n IconButton,\n Tooltip,\n Typography,\n} from \"@material-ui/core\";\n\nimport LockIcon from \"@material-ui/icons/Lock\";\nimport LockOpenIcon from \"@material-ui/icons/LockOpen\";\nimport MapIcon from \"@material-ui/icons/Map\";\nimport ThemeToggler from \"../controls/ThemeToggler\";\n\n// A global that holds our windows, for use see components/Window.js\ndocument.windows = [];\n\nconst DRAWER_WIDTH = 250;\n\nconst styles = (theme) => {\n return {\n map: {\n zIndex: 1,\n position: \"absolute\",\n left: 0,\n right: 0,\n bottom: 0,\n top: 0,\n border: \"2px solid transparent\",\n \"&:focus-visible\": {\n border: \"2px solid black\",\n },\n },\n flexBox: {\n position: \"absolute\",\n left: 0,\n right: 0,\n bottom: 0,\n top: 0,\n padding: theme.spacing(2),\n display: \"flex\",\n flexDirection: \"column\",\n pointerEvents: \"none\",\n },\n windowsContainer: {\n position: \"absolute\",\n left: 0,\n right: 0,\n bottom: 0,\n top: 0,\n },\n pointerEventsOnChildren: {\n \"& > *\": {\n pointerEvents: \"auto\",\n },\n },\n drawerContent: {\n height: \"inherit\",\n },\n header: {\n zIndex: theme.zIndex.appBar,\n maxHeight: theme.spacing(8),\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n \"& > *\": {\n marginBottom: theme.spacing(2),\n },\n [theme.breakpoints.down(\"xs\")]: {\n zIndex: 3,\n marginLeft: -theme.spacing(2),\n marginRight: -theme.spacing(2),\n marginTop: -theme.spacing(2),\n maxHeight: theme.spacing(6),\n boxShadow: theme.shadows[3],\n backgroundColor: theme.palette.background.paper,\n },\n },\n main: {\n zIndex: 2,\n flex: 1,\n display: \"flex\",\n },\n leftColumn: {\n flex: 1,\n },\n rightColumn: {\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2),\n },\n controlsColumn: {\n display: \"flex\",\n flexDirection: \"column\",\n [theme.breakpoints.down(\"xs\")]: {\n marginTop: theme.spacing(2),\n },\n },\n footer: {\n zIndex: 3,\n display: \"flex\",\n justifyContent: \"flex-end\",\n height: 25,\n \"& > *\": {\n marginLeft: theme.spacing(1),\n },\n },\n drawerBackground: {\n width: DRAWER_WIDTH,\n backgroundColor: theme.palette.background.default,\n },\n drawerHeader: {\n display: \"flex\",\n alignItems: \"center\",\n padding: theme.spacing(0, 2),\n ...theme.mixins.toolbar,\n justifyContent: \"space-between\",\n backgroundColor: theme.palette.background.paper,\n },\n drawerContentContainer: {\n backgroundColor: theme.palette.background.paper,\n height: \"100%\",\n overflow: \"auto\",\n },\n drawerLockButton: {\n margin: -12,\n },\n logoBox: {\n padding: theme.spacing(1, 2),\n height: theme.spacing(6),\n },\n logo: {\n height: theme.spacing(4),\n },\n drawerGrid: {\n padding: theme.spacing(1, 2),\n backgroundColor: theme.palette.background.paper,\n minHeight: theme.spacing(6),\n },\n drawerTitle: {\n padding: theme.spacing(1, 0),\n lineHeight: 0,\n },\n drawerLiveContent: {\n backgroundColor: theme.palette.background.default,\n },\n widgetItem: {\n width: \"220px\",\n },\n snackBarContainerRoot: {\n [theme.breakpoints.down(\"xs\")]: {\n pointerEvents: \"none\",\n // Getting around notistack bug, can't reach snackItem.\n \"& div > div > div > div\": {\n pointerEvents: \"auto\",\n },\n },\n },\n snackbarContainerBottom: {\n [theme.breakpoints.down(\"xs\")]: {\n bottom: \"35px\",\n },\n },\n snackbarContainerTop: {\n [theme.breakpoints.down(\"xs\")]: {\n top: \"18px\",\n },\n },\n // IMPORTANT: shiftedLeft definition must be the last one, as styles are applied in that order via JSS\n shiftedLeft: {\n left: DRAWER_WIDTH,\n },\n };\n};\n\n/**\n * The main React Component of Hajk. Rendered by index.js.\n *\n * @class App\n * @extends {React.PureComponent}\n */\nclass App extends React.PureComponent {\n static propTypes = {\n /** List of plugins that has been activated in this instance of Hajk */\n activeTools: PropTypes.array.isRequired,\n /** CSS class declarations used in this component */\n classes: PropTypes.object.isRequired,\n /** Contains activeMap, layersConfig as well as objects that hold appConfig and mapConfig*/\n config: PropTypes.object.isRequired,\n };\n\n canRenderCustomDrawer = (activeDrawerContentFromLocalStorage, tools) => {\n if (\n !activeDrawerContentFromLocalStorage ||\n activeDrawerContentFromLocalStorage === \"plugins\"\n ) {\n // If nothing was found in local storage, fall back to map config setting\n activeDrawerContentFromLocalStorage =\n this.props.config.mapConfig.map.activeDrawerOnStart;\n }\n\n const localStorageToolFoundInMapConfig = tools.some((tool) => {\n return (\n typeof activeDrawerContentFromLocalStorage === \"string\" &&\n tool.type.toLowerCase() ===\n activeDrawerContentFromLocalStorage.toLowerCase()\n );\n });\n\n return (\n localStorageToolFoundInMapConfig &&\n activeDrawerContentFromLocalStorage &&\n activeDrawerContentFromLocalStorage !== \"plugins\"\n );\n };\n\n getDrawerPermanentFromLocalStorage = () => {\n return window.localStorage.getItem(\"drawerPermanent\") !== null\n ? window.localStorage.getItem(\"drawerPermanent\") === \"true\"\n ? true\n : false\n : null;\n };\n\n getActiveDrawerContentFromLocalStorage = () => {\n return window.localStorage.getItem(\"activeDrawerContent\") !== null\n ? window.localStorage.getItem(\"activeDrawerContent\")\n : null;\n };\n\n constructor(props) {\n super(props);\n\n const drawerPermanentFromLocalStorage =\n this.getDrawerPermanentFromLocalStorage();\n const activeDrawerContentFromLocalStorage =\n this.getActiveDrawerContentFromLocalStorage();\n const canRenderDefaultDrawer = this.hasAnyToolbarTools();\n\n const canRenderCustomDrawer = this.canRenderCustomDrawer(\n activeDrawerContentFromLocalStorage,\n props.config.mapConfig.tools\n );\n\n //Check if we have customContent to render in drawer\n //if we can render customContent, use it set the drawer content.\n //if we cant render customContent fall back to mapconfig\n //Finally, fall back to 'plugins', the standard tools panel.\n //This fall back avoids rendering an empty drawer in the case that draw is set to visible but there is no drawer content in local storage.\n\n const activeDrawerContentState = canRenderCustomDrawer\n ? activeDrawerContentFromLocalStorage !== null &&\n activeDrawerContentFromLocalStorage !== \"plugins\"\n ? activeDrawerContentFromLocalStorage\n : this.props.config.mapConfig.map.activeDrawerOnStart\n : canRenderDefaultDrawer\n ? \"plugins\"\n : null;\n\n // First check if we have anything to render at all and in case we haven't -> do not show drawer\n // If on a mobile device, the drawer should never be permanent.\n // If not on mobile, if cookie is not null, use it to show/hide Drawer.\n // If cookie is not null, use it to show/hide Drawer.\n // If cookie however is null, fall back to the values from config.\n // Finally, fall back to \"false\" if no cookie or config is found.\n const drawerPermanent =\n activeDrawerContentState === null\n ? false\n : isMobile\n ? false\n : drawerPermanentFromLocalStorage !== null\n ? drawerPermanentFromLocalStorage\n : (props.config.mapConfig.map.drawerVisible &&\n props.config.mapConfig.map.drawerPermanent) ||\n false;\n\n // First check if we have anything to render at all and in case we haven't -> do not show drawer\n // If on a mobile device, and a config property for if the drawer should initially be open is set, base the drawer state on this.\n // Otherwise if cookie for \"drawerPermanent\" is not null, use it to control Drawer visibility,\n // If there a no cookie settings, use the config drawVisible setting.\n // Finally, don't show the drawer.\n const drawerVisible =\n activeDrawerContentState === null\n ? false\n : isMobile &&\n props.config.mapConfig.map.drawerVisibleMobile !== undefined\n ? props.config.mapConfig.map.drawerVisibleMobile\n : drawerPermanentFromLocalStorage !== null\n ? drawerPermanentFromLocalStorage\n : props.config.mapConfig.map.drawerVisible || false;\n\n this.state = {\n alert: false,\n drawerButtons: [],\n loading: false,\n mapClickDataResult: {},\n drawerVisible: drawerVisible,\n drawerPermanent: drawerPermanent,\n activeDrawerContent: activeDrawerContentState,\n drawerMouseOverLock: false,\n };\n\n // If the drawer is set to be visible at start - ensure the activeDrawerContent\n // is set to current content. If we don't allow functional cookies, we cannot do that obviously.\n if (drawerVisible && drawerPermanent && activeDrawerContentState !== null) {\n if (functionalCookieOk()) {\n window.localStorage.setItem(\n \"activeDrawerContent\",\n activeDrawerContentState\n );\n }\n }\n\n this.globalObserver = new Observer();\n\n // We have to initialize the cookie-manager so we know how cookies should be managed.\n // The manager should ideally only be initialized once, since the initialization determines\n // wether the cookie-notice has to be shown or not. Running setConfig() again will not lead\n // to a new prompt.\n setCookieConfig({\n showCookieNotice: props.config.mapConfig.map.showCookieNotice,\n globalObserver: this.globalObserver,\n });\n\n this.appModel = new AppModel({\n config: props.config,\n globalObserver: this.globalObserver,\n refreshMUITheme: props.refreshMUITheme,\n });\n }\n\n hasAnyToolbarTools = () => {\n const { config, activeTools } = this.props;\n return config.mapConfig.tools.some((tool) => {\n return (\n tool.options.target === \"toolbar\" &&\n activeTools\n .map((activeTool) => activeTool.toLowerCase())\n .includes(tool.type.toLowerCase())\n );\n });\n };\n\n componentDidMount() {\n var promises = this.appModel\n .createMap()\n .addSearchModel()\n .addLayers()\n .loadPlugins(this.props.activeTools);\n Promise.all(promises).then(() => {\n this.setState(\n {\n tools: this.appModel.getPlugins(),\n },\n () => {\n // If there's at least one plugin that renders in the Drawer Map Tools List,\n // tell the Drawer to add a toggle button for the map tools\n this.appModel.getDrawerPlugins().length > 0 &&\n this.globalObserver.publish(\"core.addDrawerToggleButton\", {\n value: \"plugins\",\n ButtonIcon: MapIcon,\n caption: \"Kartverktyg\",\n drawerTitle: \"Kartverktyg\",\n order: 0,\n renderDrawerContent: function () {\n return null; // Nothing specific should be rendered - this is a special case!\n },\n });\n\n // Tell everyone that we're done loading (in case someone listens)\n this.globalObserver.publish(\"core.appLoaded\");\n }\n );\n });\n this.bindHandlers();\n }\n\n componentDidCatch(error) {}\n\n bindHandlers() {\n // Register a handle to prevent pinch zoom on mobile devices.\n document.body.addEventListener(\n \"touchmove\",\n (event) => {\n // If this event would result in changing scale …\n // scale is always undefined on Android so we need to handle it, otherwise we loose the ability to scroll.\n // For the prevention pinch-zoom on Android. Check index.css\n if (event.scale !== undefined && event.scale !== 1) {\n // …cancel it.\n event.preventDefault();\n }\n // Else, allow all non-scale-changing touch events, e.g.\n // we still want scroll to work.\n },\n { passive: false } // Explicitly tell the browser that we will preventDefault inside this handler,\n // which is important for smooth scrolling to work correctly.\n );\n\n // Register various global listeners.\n this.globalObserver.subscribe(\"infoClick.mapClick\", (results) => {\n this.setState({\n mapClickDataResult: results,\n });\n });\n\n this.globalObserver.subscribe(\"core.alert\", (message) => {\n this.setState({\n alert: true,\n alertMessage: message,\n });\n });\n\n this.globalObserver.subscribe(\"core.hideDrawer\", () => {\n // If Drawer is currently permanent,\n // flip the permanent toggle. Please note that\n // this will do some fixes, flip the state value\n // and, finally, invoke this function (core.hideDrawer) again\n // (but with new value for drawerPermanent this time!).\n if (this.state.drawerPermanent) {\n this.togglePermanent();\n } else {\n this.setState({ drawerVisible: false });\n\n // Also, tell the Drawer Buttons Component to unset active button\n this.globalObserver.publish(\"core.unsetActiveButton\");\n }\n });\n\n this.globalObserver.subscribe(\"core.onlyHideDrawerIfNeeded\", () => {\n // Invoked when user clicks any of the Plugin buttons in Drawer,\n // this is needed as we don't want to toggle the Drawer in this\n // case, but only hide it IF it's not permanent.\n // This differs from the \"normal\" hideDrawer event, that will\n // ensure that Drawer is hidden - no matter the permanent state -\n // as it will first flip the drawerPermanent value (if needed), prior\n // to closing.\n if (this.state.drawerPermanent === false) {\n this.setState({ drawerVisible: false });\n // Also, tell the Drawer Buttons Component to unset active button\n this.globalObserver.publish(\"core.unsetActiveButton\");\n }\n });\n\n this.globalObserver.subscribe(\"core.drawerContentChanged\", (v) => {\n if (v !== null) {\n this.setState({ drawerVisible: true, activeDrawerContent: v });\n } else {\n this.globalObserver.publish(\"core.hideDrawer\");\n }\n });\n\n this.globalObserver.subscribe(\"core.addDrawerToggleButton\", (button) => {\n const newState = [...this.state.drawerButtons, button];\n this.setState({ drawerButtons: newState });\n });\n\n /**\n * TODO: Implement correctly a way to remove features from map click\n * results when layer visibility is changed. The current implementation\n * has problems with group layers: if we have a group layer and toggle\n * its visibility, the features are not removed from infoclick window.\n */\n // this.appModel\n // .getMap()\n // .getLayers()\n // .getArray()\n // .forEach((layer) => {\n // layer.on(\"change:visible\", (e) => {\n // const layer = e.target;\n // if (Array.isArray(this.state.mapClickDataResult.features)) {\n // this.state.mapClickDataResult.features.forEach((feature) => {\n // if (feature.layer === layer) {\n // const o = { ...this.state.mapClickDataResult };\n // o.features = o.features.filter((f) => f !== feature);\n // this.setState({\n // mapClickDataResult: o,\n // });\n // }\n // });\n // }\n // });\n // });\n\n // TODO: More plugins could use this - currently only Snap helper registers though\n this.appModel\n .getMap()\n .getLayers()\n .getArray()\n .forEach((layer) => {\n layer.on(\"change:visible\", (e) => {\n this.globalObserver.publish(\"core.layerVisibilityChanged\", e);\n });\n });\n }\n\n renderInfoclickWindow() {\n // Check if admin wants Infoclick to be active\n const infoclickOptions = this.props.config.mapConfig.tools.find(\n (t) => t.type === \"infoclick\"\n )?.options;\n\n // The 'open' prop, below, will control whether the Window is\n // currently visible or not. The 'open' property itself\n // depends on whether there are Features to display or not.\n //\n // That, in turn, depends on what's in the current state of 'mapClickDataResult'.\n //\n // It will be changed each time user clicks on map (as we have it registered\n // like that in Click.js), so we can be confident that __after each user\n // click we do have the most current results in our state__.\n //\n // Note however that which layers are included is controlled by\n // __layer visibility at the time the click event happens!__\n //\n // As soon as user starts to show/hide layers __after__ the click, our\n // 'mapClickDataResult' may contain results from hidden layers (or not\n // contain results from layers activated after the click occurred).\n //\n // This may or may not be a bug (depending on how we see it), and may\n // be fixed in the future.\n\n return (\n infoclickOptions !== undefined && (\n <Window\n open={this.state.mapClickDataResult?.features?.length > 0} // Will show window only if there are any features to show\n globalObserver={this.globalObserver}\n title={infoclickOptions.title || \"Infoclick\"}\n position={infoclickOptions.position || \"right\"}\n mode=\"window\"\n width={infoclickOptions.width || 400}\n height={infoclickOptions.height || 300}\n features={this.state.mapClickDataResult?.features}\n options={\n this.appModel.config.mapConfig.tools.find(\n (t) => t.type === \"infoclick\"\n )?.options\n }\n map={this.appModel.getMap()}\n onDisplay={(feature) => {\n this.appModel.highlight(feature);\n }}\n onClose={() => {\n this.appModel.highlight(false);\n this.setState({\n mapClickDataResult: undefined,\n });\n }}\n />\n )\n );\n }\n\n /**\n * Flip the @this.state.drawerPermanent switch, then preform some\n * more work to ensure the OpenLayers canvas has the correct\n * canvas size.\n *\n * @memberof App\n */\n togglePermanent = (e) => {\n this.setState({ drawerPermanent: !this.state.drawerPermanent }, () => {\n // Viewport size has changed, hence we must tell OL\n // to refresh canvas size.\n this.appModel.getMap().updateSize();\n\n // If Drawer has been \"(un)permanented\", our #windows-container size has changed.\n // To ensure that our Windows still are inside the container, we dispach an\n // event that all Windows subscribe to.\n this.globalObserver.publish(\"core.drawerToggled\");\n\n // If we allow functional cookies, let's save the current state of drawerPermanent\n // to LocalStorage, so that the application can reload to the same state.\n if (functionalCookieOk()) {\n window.localStorage.setItem(\n \"drawerPermanent\",\n this.state.drawerPermanent\n );\n }\n\n // If user clicked on Toggle Permanent and the result is,\n // that this.state.drawerPermanent===false, this means that we\n // have exited the permanent mode. In this case, we also\n // want to ensure that Drawer is hidden (otherwise we would\n // just \"un-permanent\" the Drawer, but it would still be visible).\n this.state.drawerPermanent === false &&\n this.globalObserver.publish(\"core.hideDrawer\");\n });\n };\n\n handleMouseEnter = (e) => {\n this.setState({ drawerMouseOverLock: true });\n };\n\n handleMouseLeave = (e) => {\n this.setState({ drawerMouseOverLock: false });\n };\n\n renderSearchComponent() {\n // FIXME: We should get config from somewhere else now when Search is part of Core\n if (\n this.appModel.plugins.search &&\n this.appModel.plugins.search.options.renderElsewhere !== true\n ) {\n return (\n <Search\n map={this.appModel.getMap()}\n app={this}\n options={this.appModel.plugins.search.options} // FIXME: We should get config from somewhere else now when Search is part of Core\n />\n );\n } else {\n return null;\n }\n }\n\n renderInformationPlugin() {\n const c = this.appModel.config.mapConfig.tools.find(\n (t) => t.type === \"information\"\n );\n\n return (\n c !== undefined &&\n c.hasOwnProperty(\"options\") && <Information options={c.options} />\n );\n }\n\n isString(s) {\n return s instanceof String || typeof s === \"string\";\n }\n\n renderDrawerHeader = () => {\n const { classes, config } = this.props;\n const drawerTitle = this.state.drawerButtons.find(\n (db) => db.value === this.state.activeDrawerContent\n )?.drawerTitle;\n\n // We need to be able to grab different logos depending\n // on light/dark mode theme\n const logoUrl =\n (this.props.theme.palette.type === \"light\" // If light theme active…\n ? config.mapConfig.map.logoLight // …grab light logo,\n : config.mapConfig.map.logoDark) || // …else grab dark logo.\n config.mapConfig.map.logo || // If neither was set, try to see if we have the legacy admin parameter.\n \"logo.png\"; // If we didn't have this either, fallback to hard-coded value.\n\n return (\n <>\n <Box className={classes.logoBox}>\n <img alt=\"\" src={logoUrl} className={classes.logo} />\n </Box>\n <Divider />\n <Grid\n className={classes.drawerGrid}\n item\n container\n wrap=\"nowrap\"\n direction=\"row\"\n justify=\"space-between\"\n alignItems=\"center\"\n >\n <Grid item>\n <Typography variant=\"button\" className={classes.drawerTitle}>\n {drawerTitle}\n </Typography>\n </Grid>\n {/** Hide Lock button in mobile mode - there's not screen estate to permanently lock Drawer on mobile viewports*/}\n <Grid item>\n <Hidden smDown>\n <Tooltip\n title={\n (this.state.drawerPermanent ? \"Lås upp\" : \"Lås fast\") +\n \" verktygspanelen\"\n }\n >\n <IconButton\n className={classes.drawerLockButton}\n onClick={this.togglePermanent}\n onMouseEnter={this.handleMouseEnter}\n onMouseLeave={this.handleMouseLeave}\n >\n {this.state.drawerPermanent ? (\n this.state.drawerMouseOverLock ? (\n <LockOpenIcon />\n ) : (\n <LockIcon />\n )\n ) : this.state.drawerMouseOverLock ? (\n <LockIcon />\n ) : (\n <LockOpenIcon />\n )}\n </IconButton>\n </Tooltip>\n </Hidden>\n </Grid>\n </Grid>\n </>\n );\n };\n\n renderAllDrawerContent = () => {\n const { classes } = this.props;\n\n return (\n <div id=\"drawer-content\" className={classes.drawerContentContainer}>\n <Box\n key=\"plugins\"\n className={classes.drawerContent}\n display={\n this.state.activeDrawerContent === \"plugins\" ? \"unset\" : \"none\"\n }\n >\n <nav role=\"navigation\" id=\"plugin-buttons\" />\n </Box>\n {this.state.drawerButtons.map((db) => {\n return (\n <Box\n key={db.value}\n className={classes.drawerContent}\n display={\n this.state.activeDrawerContent === db.value ? \"unset\" : \"none\"\n }\n >\n {db.renderDrawerContent()}\n </Box>\n );\n })}\n </div>\n );\n };\n\n render() {\n const { classes, config } = this.props;\n\n // If clean===true, some components won't be rendered below\n const clean = config.mapConfig.map.clean;\n\n // Let admin decide whether MapResetter should be shown, but show it\n // always on clean mode maps.\n const showMapResetter = clean === true || config.mapConfig.map.mapresetter;\n\n const showMapSwitcher =\n clean === false && config.activeMap !== \"simpleMapConfig\";\n\n return (\n <SnackbarProvider\n maxSnack={3}\n classes={{\n anchorOriginBottomCenter: classes.snackbarContainerBottom,\n anchorOriginTopCenter: classes.snackbarContainerTop,\n containerRoot: classes.snackBarContainerRoot,\n }}\n anchorOrigin={{\n vertical: \"top\",\n horizontal: \"center\",\n }}\n >\n <>\n {this.props.config.appConfig?.announcements &&\n Array.isArray(this.props.config.appConfig.announcements) &&\n this.props.config.appConfig.announcements.length > 0 && (\n <Announcement\n announcements={this.props.config.appConfig.announcements}\n currentMap={this.props.config.activeMap}\n />\n )}\n {clean === false && (\n <CookieNotice\n globalObserver={this.globalObserver}\n appModel={this.appModel}\n />\n )}\n <Alert\n open={this.state.alert}\n message={this.state.alertMessage}\n parent={this}\n title=\"Meddelande\"\n />\n <SrShortcuts globalObserver={this.globalObserver}></SrShortcuts>\n <div\n id=\"appBox\"\n className={cslx(classes.flexBox, {\n [classes.shiftedLeft]:\n this.state.drawerPermanent && clean === false,\n })}\n >\n <header\n id=\"header\"\n className={cslx(classes.header, classes.pointerEventsOnChildren)}\n >\n {clean === false && (\n <DrawerToggleButtons\n drawerButtons={this.state.drawerButtons}\n globalObserver={this.globalObserver}\n initialActiveButton={\n this.state.drawerVisible\n ? this.state.activeDrawerContent\n : null\n }\n />\n )}\n {/* Render Search even if clean === false: Search contains logic to handle clean inside the component. */}\n {this.renderSearchComponent()}\n </header>\n <main className={classes.main}>\n <div\n id=\"left-column\"\n className={cslx(\n classes.leftColumn,\n classes.pointerEventsOnChildren\n )}\n ></div>\n <div\n id=\"right-column\"\n className={cslx(\n classes.rightColumn,\n classes.pointerEventsOnChildren\n )}\n ></div>\n\n <div\n id=\"controls-column\"\n className={cslx(\n classes.controlsColumn,\n classes.pointerEventsOnChildren\n )}\n >\n <Zoom map={this.appModel.getMap()} />\n {clean === false &&\n this.appModel.config.mapConfig.map.showUserAvatar ===\n true && (\n <User userDetails={this.appModel.config.userDetails} />\n )}\n <div id=\"plugin-control-buttons\"></div>\n {showMapResetter && (\n <MapResetter\n mapConfig={this.appModel.config.mapConfig}\n map={this.appModel.getMap()}\n />\n )}\n <Rotate map={this.appModel.getMap()} />\n {showMapSwitcher && <MapSwitcher appModel={this.appModel} />}\n {clean === false && <MapCleaner appModel={this.appModel} />}\n {clean === false && <PresetLinks appModel={this.appModel} />}\n {clean === false && (\n <ThemeToggler\n showThemeToggler={\n this.appModel.config.mapConfig.map.showThemeToggler\n }\n toggleMUITheme={this.props.toggleMUITheme}\n />\n )}\n {clean === false && this.renderInformationPlugin()}\n </div>\n </main>\n <footer\n className={cslx(classes.footer, classes.pointerEventsOnChildren)}\n >\n <ScaleLine map={this.appModel.getMap()} />\n <Attribution map={this.appModel.getMap()} />\n </footer>\n </div>\n <div\n id=\"map\"\n tabIndex=\"0\"\n role=\"application\"\n className={cslx(classes.map, {\n [classes.shiftedLeft]:\n this.state.drawerPermanent && clean === false,\n })}\n ></div>\n <div\n id=\"windows-container\"\n className={cslx(\n classes.pointerEventsOnChildren,\n classes.windowsContainer,\n {\n [classes.shiftedLeft]:\n this.state.drawerPermanent && clean === false,\n }\n )}\n >\n {this.renderInfoclickWindow()}\n <PluginWindows\n plugins={this.appModel.getBothDrawerAndWidgetPlugins()}\n />\n </div>\n {clean !== true && ( // NB: Special case here, important with !== true, because there is an edge-case where clean===undefined, and we don't want to match on that!\n <Drawer\n open={this.state.drawerVisible}\n ModalProps={{\n hideBackdrop: this.state.drawerPermanent, //Don't show backdrop if drawer is permanent\n disableEnforceFocus: true, //Dont enforce focus to be able to handle elements underneath modal\n onEscapeKeyDown: () => {\n this.globalObserver.publish(\"core.hideDrawer\");\n },\n style: {\n //Needs to be set to be able to handle elements underneath modal\n position: this.state.drawerPermanent ? \"initial\" : \"fixed\",\n },\n keepMounted: true, //Ensure we dont have to render plugins more than once - UnMounting every time is slow\n onBackdropClick: () => {\n this.globalObserver.publish(\"core.hideDrawer\");\n },\n }}\n variant=\"temporary\"\n classes={{\n paper: classes.drawerBackground,\n }}\n >\n {this.renderDrawerHeader()}\n <Divider />\n {this.renderAllDrawerContent()}\n </Drawer>\n )}\n {clean === false && (\n <Introduction\n experimentalIntroductionEnabled={\n this.appModel.config.appConfig.experimentalIntroductionEnabled\n }\n experimentalIntroductionSteps={\n this.appModel.config.appConfig.experimentalIntroductionSteps\n }\n globalObserver={this.globalObserver}\n />\n )}\n </>\n </SnackbarProvider>\n );\n }\n}\n\nexport default withStyles(styles)(App);\n","import React, { useEffect, useState } from \"react\";\nimport { List, ListItem, Link } from \"@material-ui/core\";\n\n/*\n * @summary Small component to render a shortcut-menu high up in the DOM for screen readers\n * @description The purpose of the component is to make the site more accessible by giving screen readers\n * the option to skip \"forward\" to any interesting sections instead of reading the DOM from the top\n *\n * Using globalobserver anyone can add shortcuts for screen readers high up in the DOM\n * publish array of objects [{title : {title of shortcut}, link : {link to nodeId}}] to core.addSrShortcuts\n * to add shortcuts.\n *\n * @class SrShortcuts\n */\nconst SrShortcuts = ({ globalObserver }) => {\n const [shortcuts, setShortcuts] = useState([]);\n useEffect(() => {\n globalObserver.subscribe(\"core.addSrShortcuts\", addShortCuts);\n });\n\n const addShortCuts = (shortcutsArray) => {\n setShortcuts([...shortcuts, ...shortcutsArray]);\n };\n\n return (\n <List className=\"sr-only\">\n {shortcuts.map((shortcut) => {\n return (\n <ListItem key={shortcut.link}>\n <Link href={shortcut.link}>{shortcut.title}</Link>\n </ListItem>\n );\n })}\n </List>\n );\n};\n\nexport default SrShortcuts;\n","import SearchModel from \"./SearchModel\";\nimport Plugin from \"./Plugin.js\";\nimport ConfigMapper from \"./../utils/ConfigMapper.js\";\nimport CoordinateSystemLoader from \"./../utils/CoordinateSystemLoader.js\";\nimport { isMobile } from \"./../utils/IsMobile.js\";\n// import ArcGISLayer from \"./layers/ArcGISLayer.js\";\n// import DataLayer from \"./layers/DataLayer.js\";\nimport WMSLayer from \"./layers/WMSLayer.js\";\nimport WMTSLayer from \"./layers/WMTSLayer.js\";\nimport WFSVectorLayer from \"./layers/VectorLayer.js\";\nimport { bindMapClickEvent } from \"./Click.js\";\nimport { defaults as defaultInteractions } from \"ol/interaction\";\nimport { Map, View } from \"ol\";\n// TODO: Uncomment and ensure they show as expected\n// import {\n// defaults as defaultControls,\n// Attribution,\n// Control,\n// FullScreen, // TODO: Consider implementation\n// MousePosition, // TODO: Consider implementation, perhaps in a separate plugin\n// OverviewMap // TODO: Consider implementation\n// Rotate,\n// ScaleLine\n// Zoom,\n// ZoomSlider,\n// ZoomToExtent\n// } from \"ol/control\";\nimport { register } from \"ol/proj/proj4\";\nimport VectorLayer from \"ol/layer/Vector\";\nimport VectorSource from \"ol/source/Vector\";\nimport { Icon, Fill, Stroke, Style } from \"ol/style.js\";\nimport SnapHelper from \"./SnapHelper\";\nimport { hfetch } from \"utils/FetchWrapper\";\n\nclass AppModel {\n /**\n * Initialize new AddModel\n * @param object Config\n * @param Observer observer\n */\n constructor(settings) {\n const { config, globalObserver, refreshMUITheme } = settings;\n this.map = undefined;\n this.windows = [];\n this.plugins = {};\n this.activeTool = undefined;\n this.config = config;\n this.decorateConfig();\n this.coordinateSystemLoader = new CoordinateSystemLoader(\n config.mapConfig.projections\n );\n this.globalObserver = globalObserver;\n this.layersFromParams = [];\n this.cqlFiltersFromParams = {};\n register(this.coordinateSystemLoader.getProj4());\n this.hfetch = hfetch;\n this.refreshMUITheme = refreshMUITheme;\n }\n\n decorateConfig() {\n // .allResolutions should be used when creating layers etc\n // It will also be used in the print plugin to be able to print in higher resolutions.\n this.config.mapConfig.map.allResolutions = [\n ...this.config.mapConfig.map.resolutions,\n ...(this.config.mapConfig.map.extraPrintResolutions ?? []),\n ];\n }\n\n registerWindowPlugin(windowComponent) {\n this.windows.push(windowComponent);\n }\n\n invokeCloseOnAllWindowPlugins() {\n this.windows.forEach((window) => {\n window.closeWindow();\n });\n }\n\n onWindowOpen(currentWindow) {\n this.windows\n .filter((window) => window !== currentWindow)\n .forEach((window) => {\n if (window.position === currentWindow.position || isMobile) {\n window.closeWindow();\n }\n });\n }\n\n /**\n * Add plugin to this tools property of loaded plugins.\n * @internal\n */\n addPlugin(plugin) {\n this.plugins[plugin.type] = plugin;\n }\n\n /**\n * Get loaded plugins\n * @returns Array<Plugin>\n */\n getPlugins() {\n return Object.keys(this.plugins).reduce((v, key) => {\n return [...v, this.plugins[key]];\n }, []);\n }\n\n /**\n * @summary Helper used by getBothDrawerAndWidgetPlugins(), checks\n * that the supplied parameter has one of the valid \"target\" values.\n *\n * @param {string} t Target to be tested\n * @returns {boolean}\n */\n #validPluginTarget = (t) => {\n // FIXME: Why is \"hidden\" included in this list, anyone?\n return [\"toolbar\", \"left\", \"right\", \"control\", \"hidden\"].includes(t);\n };\n\n /**\n * A plugin may have the 'target' option. Currently we use four\n * targets: toolbar, control, left and right. Toolbar means it's a\n * plugin that will be visible in Drawer list. Left and right\n * are Widget plugins, that on large displays show on left/right\n * side of the map viewport, while on small screens change its\n * appearance and end up as Drawer list plugins too. Control buttons\n * are displayed in the same area as map controls, e.g. zoom buttons.\n *\n * This method filters out those plugins that should go into\n * the Drawer, Widget or Control list and returns them.\n *\n * It is used in AppModel to initiate all plugins' Components,\n * so whatever is returned here will result in a render() for\n * that plugin.\n *\n * @returns array of Plugins\n * @memberof AppModel\n */\n getBothDrawerAndWidgetPlugins() {\n const r = this.getPlugins()\n .filter((plugin) => {\n return (\n // If \"options\" is an Array (of plugin entities) we must\n // look for the \"target\" property inside that array. As soon\n // as one of the entities has a valid \"target\" value, we\n // consider the entire plugin to be valid and included in this list.\n plugin.options.some?.((p) => this.#validPluginTarget(p.target)) ||\n // If \"options\" isn't an array, we can grab the \"target\" directly.\n this.#validPluginTarget(plugin.options.target)\n );\n })\n .sort((a, b) => a.sortOrder - b.sortOrder);\n return r;\n }\n\n getDrawerPlugins() {\n return this.getPlugins().filter((plugin) => {\n return [\"toolbar\"].includes(plugin.options.target);\n });\n }\n\n /**\n * Dynamically load plugins from the configured plugins folder.\n * Assumed that a folder exists with the same name as the requested plugin.\n * There must also be a file present with the same name as well.\n * @param {Array} - List of plugins to be loaded.\n * @returns {Array} - List of promises to be resolved for.\n */\n loadPlugins(plugins) {\n const promises = [];\n plugins.forEach((plugin) => {\n const dir = [\"Search\"].includes(plugin) ? \"components\" : \"plugins\";\n const prom = import(`../${dir}/${plugin}/${plugin}.js`)\n .then((module) => {\n const toolConfig =\n this.config.mapConfig.tools.find(\n (plug) => plug.type.toLowerCase() === plugin.toLowerCase()\n ) || {};\n\n const toolOptions =\n toolConfig && toolConfig.options ? toolConfig.options : {};\n\n const sortOrder = toolConfig.hasOwnProperty(\"index\")\n ? Number(toolConfig.index)\n : 0;\n\n if (Object.keys(toolConfig).length > 0) {\n this.addPlugin(\n new Plugin({\n map: this.map,\n app: this,\n type: plugin.toLowerCase(),\n searchInterface: {},\n sortOrder: sortOrder,\n options: toolOptions,\n component: module.default,\n })\n );\n }\n })\n .catch((err) => {\n console.error(err);\n });\n promises.push(prom);\n });\n return promises;\n }\n\n /**\n * Initialize open layers map\n * @return {ol.Map} map\n */\n createMap() {\n const config = this.translateConfig();\n\n // Prepare OL interactions options, refer to https://openlayers.org/en/latest/apidoc/module-ol_interaction.html#.defaults.\n // We use conditional properties to ensure that only existing keys are set. The rest\n // will fallback to defaults from OL. (The entire interactionsOptions object, as well as all its properties are optional\n // according to OL documentation, so there's no need to set stuff that won't be needed.)\n const interactionsOptions = {\n ...(config.map.hasOwnProperty(\"altShiftDragRotate\") && {\n altShiftDragRotate: config.map.altShiftDragRotate,\n }),\n ...(config.map.hasOwnProperty(\"onFocusOnly\") && {\n onFocusOnly: config.map.onFocusOnly,\n }),\n ...(config.map.hasOwnProperty(\"doubleClickZoom\") && {\n doubleClickZoom: config.map.doubleClickZoom,\n }),\n ...(config.map.hasOwnProperty(\"keyboard\") && {\n keyboard: config.map.keyboard,\n }),\n ...(config.map.hasOwnProperty(\"mouseWheelZoom\") && {\n mouseWheelZoom: config.map.mouseWheelZoom,\n }),\n ...(config.map.hasOwnProperty(\"shiftDragZoom\") && {\n shiftDragZoom: config.map.shiftDragZoom,\n }),\n ...(config.map.hasOwnProperty(\"dragPan\") && {\n dragPan: config.map.dragPan,\n }),\n ...(config.map.hasOwnProperty(\"pinchRotate\") && {\n pinchRotate: config.map.pinchRotate,\n }),\n ...(config.map.hasOwnProperty(\"pinchZoom\") && {\n pinchZoom: config.map.pinchZoom,\n }),\n ...(!Number.isNaN(Number.parseInt(config.map.zoomDelta)) && {\n zoomDelta: config.map.zoomDelta,\n }),\n ...(!Number.isNaN(Number.parseInt(config.map.zoomDuration)) && {\n zoomDuration: config.map.zoomDuration,\n }),\n };\n\n this.map = new Map({\n controls: [\n // new FullScreen({ target: document.getElementById(\"controls-column\") }),\n // new Rotate({ target: document.getElementById(\"controls-column\") }),\n // new MousePosition({\n // target: document.querySelector(\"#root > div > footer\")\n // }),\n // new OverviewMap({\n // target: document.querySelector(\"#root > div > footer\"),\n // view: new View({\n // projection: config.map.projection\n // })\n // })\n ],\n interactions: defaultInteractions(interactionsOptions),\n layers: [],\n target: config.map.target,\n overlays: [],\n view: new View({\n center: config.map.center,\n extent: config.map.extent.length > 0 ? config.map.extent : undefined, // backend will always write extent as an Array, so basic \"config.map.extent || undefined\" wouldn't work here\n constrainOnlyCenter: config.map.constrainOnlyCenter, // If true, the extent constraint will only apply to the view center and not the whole extent.\n constrainResolution:\n isMobile && config.map.constrainResolutionMobile !== undefined\n ? config.map.constrainResolutionMobile\n : config.map.constrainResolution, // If true, the view will always animate to the closest zoom level after an interaction; false means intermediary zoom levels are allowed.\n maxZoom: config.map.maxZoom || 24,\n minZoom: config.map.minZoom || 0,\n projection: config.map.projection,\n resolutions: config.map.resolutions,\n units: \"m\",\n zoom: config.map.zoom,\n }),\n });\n\n // Create throttled zoomEnd event\n let currentZoom = this.map.getView().getZoom();\n\n this.map.on(\"moveend\", (e) => {\n // using moveend to create a throttled zoomEnd event\n // instead of using change:resolution to minimize events being fired.\n const newZoom = this.map.getView().getZoom();\n if (currentZoom !== newZoom) {\n this.globalObserver.publish(\"core.zoomEnd\", { zoom: newZoom });\n currentZoom = newZoom;\n }\n });\n\n // Add Snap Helper to the Map\n this.map.snapHelper = new SnapHelper(this);\n\n // Add the clickLock set. Its primary use is to disable infoclick action\n // when some other plugin (such as Draw or Measure) is active (in that case\n // we want the plugin to handle click - not to show infoclick).\n // It's easy to think that this is only needed if Infoclick plugin is active\n // in map config - but that is not the case:\n // A lot of plugins rely on the 'clickLock' property to exist on Map,\n // and to be a Set (we use .has()).\n // So, we create the Set no matter what:\n this.map.clickLock = new Set();\n\n // FIXME: Potential miss here: don't we want to register click on search results\n // But we register the Infoclick handler only if the plugin exists in map config:\n // even if Infoclick plugin is inactive? Currently search won't register clicks in\n // map without infoclick, which seems as an unnecessary limitation.\n if (config.tools.some((tool) => tool.type === \"infoclick\")) {\n bindMapClickEvent(this.map, (mapClickDataResult) => {\n // We have to separate features coming from the searchResult-layer\n // from the rest, since we want to render this information in the\n // search-component rather than in the featureInfo-component.\n const searchResultFeatures = mapClickDataResult.features.filter(\n (feature) => {\n return feature?.layer.get(\"type\") === \"searchResultLayer\";\n }\n );\n const infoclickFeatures = mapClickDataResult.features.filter(\n (feature) => {\n return feature?.layer.get(\"type\") !== \"searchResultLayer\";\n }\n );\n\n // If there are any results from search layer, send an event about that.\n if (searchResultFeatures.length > 0) {\n this.globalObserver.publish(\n \"infoClick.searchResultLayerClick\",\n searchResultFeatures // Clicked features sent to the search-component for display\n );\n }\n\n // Do the same for regular infoclick results from WMS layers\n if (infoclickFeatures.length > 0) {\n // Note that infoclick.mapClick seems to have a different interface…\n this.globalObserver.publish(\"infoClick.mapClick\", {\n ...mapClickDataResult, // as it requires the entire object, not just \"features\", like infoClick.searchResultLayerClick.\n features: infoclickFeatures, // Hence, we send everything from mapClickDataResult, but replace the features property.\n });\n }\n });\n }\n return this;\n }\n\n getMap() {\n return this.map;\n }\n\n addSearchModel() {\n // TODO: Move configuration somewhere else, shouldn't be plugin-dependent.\n\n // See if Search is configured in map config\n const searchConfigIndex = this.config.mapConfig.tools.findIndex(\n (t) => t.type === \"search\"\n );\n\n // If it is, go on and add the search model to App model\n if (searchConfigIndex !== -1) {\n this.searchModel = new SearchModel(\n this.config.mapConfig.tools[searchConfigIndex].options,\n this.getMap(),\n this\n );\n }\n\n // Either way, return self, so we can go on and chain more methods on App model\n return this;\n }\n\n clear() {\n this.clearing = true;\n this.highlight(false);\n this.map\n .getLayers()\n .getArray()\n .forEach((layer) => {\n if (\n layer.getProperties &&\n layer.getProperties().layerInfo &&\n layer.getProperties().layerInfo.layerType === \"layer\"\n ) {\n if (layer.layerType === \"group\") {\n this.globalObserver.publish(\"layerswitcher.hideLayer\", layer);\n } else {\n layer.setVisible(false);\n }\n }\n });\n setTimeout(() => {\n this.clearing = false;\n }, 100);\n }\n\n addMapLayer(layer) {\n const configMapper = new ConfigMapper(this.config.appConfig.proxy);\n let layerItem, layerConfig;\n switch (layer.type) {\n case \"wms\":\n layerConfig = configMapper.mapWMSConfig(layer, this.config);\n layerItem = new WMSLayer(\n layerConfig.options,\n this.config.appConfig.proxy,\n this.globalObserver\n );\n this.map.addLayer(layerItem.layer);\n break;\n case \"wmts\":\n layerConfig = configMapper.mapWMTSConfig(layer, this.config);\n layerItem = new WMTSLayer(\n layerConfig.options,\n this.config.appConfig.proxy,\n this.map\n );\n this.map.addLayer(layerItem.layer);\n break;\n case \"vector\":\n layerConfig = configMapper.mapVectorConfig(layer);\n layerItem = new WFSVectorLayer(\n layerConfig.options,\n this.config.appConfig.proxy,\n this.map\n );\n this.map.addLayer(layerItem.layer);\n break;\n // case \"arcgis\":\n // layerConfig = configMapper.mapArcGISConfig(layer);\n // layer = new ArcGISLayer(layerConfig);\n // break;\n // case \"data\":\n // layerConfig = configMapper.mapDataConfig(layer);\n // layer = new DataLayer(layerConfig);\n // break;\n default:\n break;\n }\n }\n\n lookup(layers, type) {\n var matchedLayers = [];\n layers.forEach((layer) => {\n const layerConfig = this.config.layersConfig.find(\n (lookupLayer) => lookupLayer.id === layer.id\n );\n layer.layerType = type;\n // Use the general value for infobox if not present in map config.\n if (layerConfig !== undefined && layerConfig.type === \"vector\") {\n if (!layer.infobox && layerConfig) {\n layer.infobox = layerConfig.infobox;\n }\n }\n matchedLayers.push({\n ...layerConfig,\n ...layer,\n });\n });\n return matchedLayers;\n }\n\n expand(groups) {\n var result = [];\n groups.forEach((group) => {\n result = [...result, ...group.layers];\n if (group.groups) {\n result = [...result, ...this.expand(group.groups)];\n }\n });\n return result;\n }\n\n flattern(layerSwitcherConfig) {\n const layers = [\n ...this.lookup(layerSwitcherConfig.options.baselayers, \"base\"),\n ...this.lookup(this.expand(layerSwitcherConfig.options.groups), \"layer\"),\n ];\n\n return layers;\n }\n\n addLayers() {\n const layerSwitcherConfig = this.config.mapConfig.tools.find(\n (tool) => tool.type === \"layerswitcher\"\n ),\n infoclickConfig = this.config.mapConfig.tools.find(\n (t) => t.type === \"infoclick\"\n );\n\n // Prepare layers\n this.layers = this.flattern(layerSwitcherConfig);\n // FIXME: Use map instead?\n Object.keys(this.layers)\n .sort((a, b) => this.layers[a].drawOrder - this.layers[b].drawOrder)\n .map((sortedKey) => this.layers[sortedKey])\n .forEach((layer) => {\n if (this.layersFromParams.length > 0) {\n layer.visibleAtStart = this.layersFromParams.some(\n (layerId) => layerId === layer.id\n );\n }\n layer.cqlFilter = this.cqlFiltersFromParams[layer.id] || null;\n this.addMapLayer(layer);\n });\n\n // FIXME: Move to infoClick instead. All other plugins create their own layers.\n if (infoclickConfig !== undefined) {\n this.addHighlightLayer(infoclickConfig.options);\n }\n\n return this;\n }\n\n addHighlightLayer(options) {\n const { anchor, scale, src, strokeColor, strokeWidth, fillColor } = options;\n const strokeColorAsArray = strokeColor && [\n strokeColor.r,\n strokeColor.g,\n strokeColor.b,\n strokeColor.a,\n ];\n const fillColorAsArray = fillColor && [\n fillColor.r,\n fillColor.g,\n fillColor.b,\n fillColor.a,\n ];\n this.highlightSource = new VectorSource();\n this.highlightLayer = new VectorLayer({\n source: this.highlightSource,\n style: new Style({\n stroke: new Stroke({\n color: strokeColorAsArray || [200, 0, 0, 0.7],\n width: strokeWidth || 4,\n }),\n fill: new Fill({\n color: fillColorAsArray || [255, 0, 0, 0.1],\n }),\n image: new Icon({\n anchor: [anchor[0] || 0.5, anchor[1] || 1],\n scale: scale || 0.15,\n src: src || \"marker.png\",\n }),\n }),\n });\n this.map.addLayer(this.highlightLayer);\n }\n\n getCenter(e) {\n return [e[0] + Math.abs(e[2] - e[0]) / 2, e[1] + Math.abs(e[3] - e[1]) / 2];\n }\n\n highlight(feature) {\n if (this.highlightSource) {\n this.highlightSource.clear();\n if (feature) {\n this.highlightSource.addFeature(feature);\n if (window.innerWidth < 600) {\n let geom = feature.getGeometry();\n if (geom) {\n this.map.getView().setCenter(this.getCenter(geom.getExtent()));\n }\n }\n }\n }\n }\n\n /**\n * @summary Merges two objects.\n *\n * @param {*} mapConfig\n * @param {*} urlSearchParams\n * @returns {*} a Result of overwriting a with values from b\n * @memberof AppModel\n */\n mergeConfig(mapConfig, urlSearchParams) {\n // clean is used to strip the UI of all elements so we get a super clean viewport back, without any plugins\n const clean =\n Boolean(urlSearchParams.hasOwnProperty(\"clean\")) &&\n urlSearchParams.clean !== \"false\" &&\n urlSearchParams.clean !== \"0\";\n\n // f contains our CQL Filters\n const f = urlSearchParams.f;\n\n // Merge query params to the map config from JSON\n let x = parseFloat(urlSearchParams.x),\n y = parseFloat(urlSearchParams.y),\n z = parseInt(urlSearchParams.z, 10),\n l = undefined;\n if (typeof urlSearchParams.l === \"string\") {\n l = urlSearchParams.l.split(\",\");\n }\n\n if (Number.isNaN(x)) {\n x = mapConfig.map.center[0];\n }\n if (Number.isNaN(y)) {\n y = mapConfig.map.center[1];\n }\n if (Number.isNaN(z)) {\n z = mapConfig.map.zoom;\n }\n\n mapConfig.map.clean = clean;\n mapConfig.map.center[0] = x;\n mapConfig.map.center[1] = y;\n mapConfig.map.zoom = z;\n\n if (l) {\n this.layersFromParams = l;\n }\n\n if (f) {\n // Filters come as a URI encoded JSON object, so we must parse it first\n this.cqlFiltersFromParams = JSON.parse(decodeURIComponent(f));\n }\n\n return mapConfig;\n }\n /**\n * @summary If supplied argument, v, is a string and is longer then 0, return an encoded value of v. Else return undefined.\n *\n * @param {*} v\n * @returns\n * @memberof AppModel\n */\n returnStringOrUndefined(v) {\n return typeof v === \"string\" && v.trim().length > 0 ? v : undefined;\n }\n\n overrideGlobalSearchConfig(searchTool, wfslayers) {\n const configSpecificSearchLayers = searchTool.options.layers;\n const searchLayers = wfslayers.filter((layer) => {\n if (configSpecificSearchLayers.find((x) => x.id === layer.id)) {\n return layer;\n } else {\n return undefined;\n }\n });\n return searchLayers;\n }\n\n overrideGlobalEditConfig(editTool, wfstlayers) {\n const configSpecificEditLayers = editTool.options.activeServices;\n const editLayers = wfstlayers.filter((layer) => {\n if (configSpecificEditLayers.find((x) => x.id === layer.id)) {\n return layer;\n } else {\n return undefined;\n }\n });\n return editLayers;\n }\n\n translateConfig() {\n if (\n this.config.mapConfig.hasOwnProperty(\"map\") &&\n this.config.mapConfig.map.hasOwnProperty(\"title\")\n ) {\n document.title = this.config.mapConfig.map.title; // TODO: add opt-out in admin to cancel this override behaviour.\n }\n\n const layerSwitcherTool = this.config.mapConfig.tools.find((tool) => {\n return tool.type === \"layerswitcher\";\n });\n\n const searchTool = this.config.mapConfig.tools.find((tool) => {\n return tool.type === \"search\";\n });\n\n const editTool = this.config.mapConfig.tools.find((tool) => {\n return tool.type === \"edit\";\n });\n\n let layers = {};\n\n if (layerSwitcherTool) {\n layers.wmslayers = this.config.layersConfig.wmslayers || [];\n layers.wfslayers = this.config.layersConfig.wfslayers || [];\n layers.wfstlayers = this.config.layersConfig.wfstlayers || [];\n layers.wmtslayers = this.config.layersConfig.wmtslayers || [];\n layers.vectorlayers = this.config.layersConfig.vectorlayers || [];\n layers.arcgislayers = this.config.layersConfig.arcgislayers || [];\n\n layers.wmslayers.forEach((l) => (l.type = \"wms\"));\n layers.wmtslayers.forEach((l) => (l.type = \"wmts\"));\n layers.wfstlayers.forEach((l) => (l.type = \"edit\"));\n layers.vectorlayers.forEach((l) => (l.type = \"vector\"));\n layers.arcgislayers.forEach((l) => (l.type = \"arcgis\"));\n\n let allLayers = [\n ...layers.wmslayers,\n ...layers.wmtslayers,\n ...layers.vectorlayers,\n ...layers.wfstlayers,\n ...layers.arcgislayers,\n ];\n\n this.config.layersConfig = allLayers;\n }\n\n if (searchTool) {\n // Take a look at all available wfslayers in layers repository,\n // but let the search tool only see those that are specified in searchTool.options\n const wfslayers = this.overrideGlobalSearchConfig(\n searchTool,\n layers.wfslayers\n );\n\n // See if admin wants to expose any WMS layers. selectedSources will\n // in that case be an array that will hold the IDs of corresponding layers\n // (that can be found in our layers.wmslayers array). In there, a properly\n // configured WMS layer that is to be searchable will have certain search-related\n // settings active (such as name of the geometry column or URL to the WFS service).\n const wmslayers = searchTool.options.selectedSources?.flatMap(\n (wmslayerId) => {\n // Find the corresponding layer\n const layer = layers.wmslayers.find((l) => l.id === wmslayerId);\n\n // Look into the layersInfo array - it will contain sublayers. We must\n // expose each one of them as a WFS service.\n return layer.layersInfo.map((sl) => {\n return {\n id: sl.id,\n pid: layer.id, // Relevant for group layers: will hold the actual OL layer name, not only current sublayer\n caption: sl.caption,\n url: sl.searchUrl || layer.url,\n layers: [sl.id],\n searchFields:\n typeof sl.searchPropertyName === \"string\"\n ? sl.searchPropertyName.split(\",\")\n : [],\n infobox: sl.infobox || \"\",\n aliasDict: \"\",\n displayFields:\n typeof sl.searchDisplayName === \"string\"\n ? sl.searchDisplayName.split(\",\")\n : [],\n shortDisplayFields:\n typeof sl.searchShortDisplayName === \"string\"\n ? sl.searchShortDisplayName.split(\",\")\n : [],\n geometryField: sl.searchGeometryField || \"geom\",\n outputFormat: sl.searchOutputFormat || \"GML3\",\n serverType: layer.serverType || \"geoserver\",\n };\n });\n }\n );\n\n // Spread the WMS search layers onto the array with WFS search sources,\n // from now on they're equal to our code.\n Array.isArray(wmslayers) && wfslayers.push(...wmslayers);\n\n searchTool.options.sources = wfslayers;\n }\n\n // This is for backwards compatibility prior to adding locking WFST edit layers with AD.\n // This code handles if activeServices does not have an object with \"id\", \"visibleForGroups\"\n if (editTool) {\n if (editTool.options.activeServices === null) {\n editTool.options.sources = [];\n } else {\n if (\n editTool.options.activeServices &&\n editTool.options.activeServices.length !== 0\n ) {\n if (\n typeof editTool.options.activeServices[0].visibleForGroups ===\n \"undefined\"\n ) {\n // If activeService does not have an object with \"id\", \"visibleForGroups\", add it\n let as = [];\n for (let i = 0; i < editTool.options.activeServices.length; i++) {\n let service = {\n id: editTool.options.activeServices[i],\n visibleForGroups: [],\n };\n as.push(service);\n }\n editTool.options.activeServices = as;\n }\n\n let wfstlayers = this.overrideGlobalEditConfig(\n editTool,\n layers.wfstlayers\n );\n editTool.options.sources = wfstlayers;\n layers.wfstlayers = wfstlayers;\n } else {\n editTool.options.sources = [];\n }\n }\n }\n\n return this.mergeConfig(\n this.config.mapConfig,\n Object.fromEntries(new URLSearchParams(document.location.search))\n );\n }\n}\n\nexport default AppModel;\n","import { GeoJSON, WFS } from \"ol/format\";\nimport GML2 from \"ol/format/GML2\";\nimport GML3 from \"ol/format/GML3\";\nimport GML32 from \"ol/format/GML32\";\n\nimport IsLike from \"ol/format/filter/IsLike\";\nimport Or from \"ol/format/filter/Or\";\nimport And from \"ol/format/filter/And\";\nimport Intersects from \"ol/format/filter/Intersects\";\nimport Within from \"ol/format/filter/Within\";\nimport { fromCircle } from \"ol/geom/Polygon\";\n\n// import { arraySort } from \"../utils/ArraySort\";\nimport { decodeCommas } from \"../utils/StringCommaCoder\";\nimport { hfetch } from \"utils/FetchWrapper\";\n\nconst ESCAPE_CHAR = \"!\";\nconst SINGLE_CHAR = \".\";\nconst WILDCARD_CHAR = \"*\";\n\nclass SearchModel {\n // Public field declarations (why? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Defining_classes)\n\n // Private fields (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_fields#Private_fields)\n #searchOptions = {\n activeSpatialFilter: \"intersects\", // Make it possible to control which filter is used\n featuresToFilter: [], // features, who's geometries will be read and used to limit the search extent\n maxResultsPerDataset: 100, // how many results to get (at most), per dataset\n matchCase: false, // should search be case sensitive?\n wildcardAtStart: false, // should the search string start with the wildcard character?\n wildcardAtEnd: true, // should the search string be end with the wildcard character?\n };\n\n #componentOptions;\n #searchSources;\n #map;\n #app;\n\n #controllers = []; // Holder Array for Promises' AbortControllers\n #wfsParser = new WFS();\n #possibleSearchCombinations = new Map(); // Will hold a set of possible search combinations, so we don't have to re-create them for each source\n\n constructor(searchPluginOptions, map, app) {\n // Validate\n if (!searchPluginOptions || !map || !app) {\n throw new Error(\n \"One of the required parameters for SearchModel is missing.\"\n );\n }\n\n this.#componentOptions = searchPluginOptions; // FIXME: Options, currently from search plugin\n this.#map = map; // The OpenLayers map instance\n this.#app = app; // Supplies appConfig and globalObserver\n this.#searchSources = this.#componentOptions.sources;\n }\n\n /**\n * @summary The main public method of the Search model. Ensures that the search string\n * is trimmed form whitespace and that the return value is standardized (object of collections and errors).\n *\n * @returns {Object} Contains feature collections and error\n *\n * @memberof SearchModel\n */\n getResults = async (\n searchString,\n searchSources = this.getSources(),\n searchOptions = this.getSearchOptions()\n ) => {\n const { featureCollections, errors } = await this.#getRawResults(\n searchString.trim(), // Ensure that the search string isn't surrounded by whitespace\n searchSources,\n searchOptions\n );\n\n return { featureCollections, errors };\n };\n\n abort = () => {\n if (this.#controllers.length > 0) {\n this.#controllers.forEach((controller) => {\n controller.abort();\n });\n }\n\n // Clean up our list of AbortControllers\n this.#controllers = [];\n return true;\n };\n\n getSearchOptions = () => {\n return this.#searchOptions;\n };\n\n getSources = () => {\n return this.#searchSources;\n };\n\n #getRawResults = async (\n searchString = \"\",\n searchSources = this.getSources(),\n searchOptions = null\n ) => {\n // If searchSources is explicitly provided as an empty Array, something's wrong. Abort.\n if (Array.isArray(searchSources) && searchSources.length === 0) {\n throw new Error(\"No search sources selected, aborting.\");\n }\n\n // If searchSources is something else than an Array, use the default search sources.\n if (Array.isArray(searchSources) === false) {\n console.warn(\"searchSources empty, resetting to default.\", searchSources);\n searchSources = this.getSources();\n }\n\n // Will hold our Promises, one for each search source\n const promises = [];\n\n // Will hold the end results\n let rawResults = null;\n\n // Ensure that we've cleaned obsolete AbortControllers before we put new ones there\n this.#controllers = [];\n\n const viewProjection = this.#map.getView().getProjection().getCode();\n\n // Loop through all defined search sources\n searchSources.forEach((searchSource) => {\n // Expect the Promise and an AbortController from each Source\n const { promise, controller } = this.#lookup(\n searchString,\n searchSource,\n searchOptions\n );\n\n // If #lookup returned actual Promise and Controller objects, push\n // them to our array of promises. Important that we don't push empty\n // values to the array, hence this check!\n if (promise !== null && controller !== null) {\n // Push promises to local Array so we can act when all Promises have resolved\n promises.push(promise);\n\n // Also, put AbortController to the global collection of controllers, so we can abort searches at any time\n this.#controllers.push(controller);\n }\n });\n\n // Start fetching, allow both fulfilled and rejected Promises\n const fetchResponses = await Promise.allSettled(promises);\n\n // fetchedResponses will be an array of Promises in object form.\n // Each object will have a \"status\" and a \"value\" property.\n const responsePromises = await Promise.allSettled(\n fetchResponses.map((fetchResponse, i) => {\n // We look at the status and filter out only those that fulfilled.\n if (fetchResponse.status === \"rejected\")\n return Promise.reject(\"Could not fetch\");\n // If we requested GeoJSON, we can try parsing it with\n // the Promise's body's .json() method.\n switch (searchSources[i].outputFormat) {\n case \"application/json\":\n case \"application/vnd.geo+json\":\n return fetchResponse.value.json();\n // Otherwise we should expect XML, which needs to be parsed\n // as text\n case \"GML2\":\n case \"GML3\":\n case \"GML32\":\n return fetchResponse.value.text();\n default:\n return Promise.reject(\"Output format now allowed\");\n }\n })\n );\n\n // Prepare two arrays that will hold our successful and\n // failed responses\n const successfulResponses = [];\n const errors = [];\n\n // Investigate each response and put in the correct collection,\n // depending on if it succeeded or failed.\n responsePromises.forEach((r, i) => {\n if (r.status === \"fulfilled\") {\n r.source = searchSources[i];\n r.origin = \"WFS\";\n successfulResponses.push(r);\n } else if ((r) => r.status === \"rejected\") {\n r.source = searchSources[i];\n r.origin = \"WFS\";\n errors.push(r);\n }\n });\n\n // Do some magic on our valid results\n successfulResponses.forEach((r) => {\n // FIXME: Investigate if this sorting is really needed, and if so,\n // if we can find some Unicode variant and not only for Swedish characters.\n // FIXME: NB: This can't be done like this as it only works for GeoJSON\n // responses. GML won't have an object assigned to r.value, so there won't\n // be any \"features\" that can be sorted like this (in GML response, the r.value\n // is a XML string).\n // if (r.value?.features?.length > 0) {\n // arraySort({\n // array: r.value.features,\n // index: r.source.searchFields[0],\n // });\n // }\n\n switch (r.source.outputFormat) {\n case \"application/json\":\n case \"application/vnd.geo+json\": {\n // If the CRS object is lacking in the GeoJSON response, we can\n // safely assume that the geometries are in the standard-compilant\n // WGS84 (EPSG:4326).\n const parserOptions = r.value.crs\n ? {}\n : {\n dataProjection: \"EPSG:4326\", //FIXME: Only valid for GeoJSON responses!\n featureProjection: viewProjection,\n };\n\n // Parse the GeoJSON object, optionally supplying the options if needed (see above ^)\n const olFeatures = new GeoJSON().readFeatures(r.value, parserOptions);\n r.value = { features: olFeatures };\n break;\n }\n case \"GML2\":\n case \"GML3\":\n case \"GML32\": {\n let parser = null;\n if (r.source.outputFormat === \"GML2\") {\n parser = new GML2();\n } else if (r.source.outputFormat === \"GML3\") {\n parser = new GML3();\n } else if (r.source.outputFormat === \"GML32\") {\n parser = new GML32();\n }\n const olFeatures = parser.readFeatures(r.value);\n r.value = { features: olFeatures };\n break;\n }\n\n default:\n throw new Error(\"Unknown output format\");\n }\n });\n\n // Return an object with out results and errors\n rawResults = { featureCollections: successfulResponses, errors };\n\n return rawResults;\n };\n\n #getOrFilter = (word, searchSource, searchOptions) => {\n let orFilter = new Or(\n ...searchSource.searchFields.map((searchField) => {\n return this.#getIsLikeFilter(searchField, word, searchOptions);\n })\n );\n return orFilter;\n };\n\n #getIsLikeFilter = (searchField, word, searchOptions) => {\n return new IsLike(\n searchField,\n word,\n WILDCARD_CHAR, // wildcard char\n SINGLE_CHAR, // single char\n ESCAPE_CHAR, // escape char\n searchOptions.matchCase // match case\n );\n };\n\n #getSearchFilters = (wordsArray, searchSource, searchOptions) => {\n if (searchSource.searchFields.length > 1) {\n let OrFilters = wordsArray.map((word) => {\n return this.#getOrFilter(word, searchSource, searchOptions);\n });\n if (OrFilters.length > 1) {\n return new And(...OrFilters);\n } else {\n return OrFilters[0];\n }\n } else {\n let isLikeFilters = wordsArray.map((word) => {\n return this.#getIsLikeFilter(\n searchSource.searchFields[0],\n word,\n searchOptions\n );\n });\n if (isLikeFilters.length > 1) {\n return new And(...isLikeFilters);\n } else {\n return isLikeFilters[0];\n }\n }\n };\n\n #getStringArray = (searchString) => {\n let tempStringArray = this.#splitAndTrimOnCommas(searchString);\n return tempStringArray.join(\" \").split(\" \");\n };\n\n #splitAndTrimOnCommas = (searchString) => {\n return searchString.split(\",\").map((string) => {\n return string.trim();\n });\n };\n\n #escapeSpecialChars = (string) => {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"!$&\"); // $& means the whole matched string\n };\n\n getPossibleSearchCombinations = (searchString) => {\n // See if we've already created possible search combos for the specified string,\n // if so, do an early return\n if (this.#possibleSearchCombinations.has(searchString)) {\n return Array.from(this.#possibleSearchCombinations.get(searchString));\n }\n\n // Looks like the specified string hasn't been requested yet: let's create\n // an array of possible combos.\n const possibleSearchCombinations = new Set();\n const wordsInTextField = this.#getStringArray(searchString);\n const numWords = wordsInTextField.length;\n\n // If the string contains a comma, we must add the string as is\n // otherwise we might miss cases where the user wants to search\n // for a property with a comma.\n if (searchString.includes(\",\")) {\n possibleSearchCombinations.add([searchString]);\n }\n\n // If the user has typed more than five words, we only create\n // one string containing all words to avoid sending humongous\n // requests to geoServer.\n if (numWords > 5) {\n const joinedWord = wordsInTextField.join().replace(/,/g, \" \");\n possibleSearchCombinations.add([joinedWord]);\n return Array.from(possibleSearchCombinations);\n }\n\n possibleSearchCombinations.add(wordsInTextField);\n\n if (numWords > 1) {\n for (let i = 0; i < numWords; i++) {\n this.#getPossibleForwardCombinations(\n i,\n wordsInTextField,\n possibleSearchCombinations\n );\n }\n }\n\n // Let's save the results for later use - we don't want to re-create\n // the possible combos array for the same search string\n this.#possibleSearchCombinations.set(\n searchString,\n possibleSearchCombinations\n );\n\n return Array.from(possibleSearchCombinations);\n };\n\n #getPossibleForwardCombinations = (\n index,\n stringArray,\n possibleSearchCombinations\n ) => {\n const wordsBeforeCurrent = stringArray.slice(0, index);\n\n for (let ii = index; ii < stringArray.length - 1; ii++) {\n const currentWord = stringArray\n .slice(index, ii + 2)\n .join()\n .replace(/,/g, \" \");\n\n const wordsAfterCurrent = stringArray.slice(ii + 2);\n\n possibleSearchCombinations.add([\n ...wordsBeforeCurrent,\n currentWord,\n ...wordsAfterCurrent,\n ]);\n }\n };\n\n #addPotentialWildCards = (word, searchOptions) => {\n word = searchOptions.wildcardAtStart ? `*${word}` : word;\n word = searchOptions.wildcardAtEnd ? `${word}*` : word;\n return word;\n };\n\n #decodePotentialSpecialChars = (searchCombinations) => {\n return searchCombinations.map((combination) => {\n return combination.map((word) => {\n // Replace all occurrences of a backslash with 2 backslashes (which will be seen\n // by GeoServer as \"one escaped backslash\"). Hence the 4 backslashes in replacement string,\n // they are basically two escaped backslashes after each other.\n return decodeCommas(word).replace(/\\\\/g, \"\\\\\\\\\");\n });\n });\n };\n\n #lookup = (searchString, searchSource, searchOptions) => {\n const srsName = this.#map.getView().getProjection().getCode();\n const geometryName =\n searchSource.geometryField || searchSource.geometryName || \"geom\";\n const maxFeatures = searchOptions.maxResultsPerDataset;\n let comparisonFilters = null;\n let spatialFilters = null;\n let finalFilters = null;\n let possibleSearchCombinations = [];\n\n // In order to do a textual search, we must have both a search phrase\n // and at least one search field (else there's no way to know where to search!)\n if (searchString !== \"\" && searchSource.searchFields.length > 0) {\n if (searchOptions.getPossibleCombinations) {\n possibleSearchCombinations =\n this.getPossibleSearchCombinations(searchString);\n } else {\n possibleSearchCombinations.push(\n this.#splitAndTrimOnCommas(searchString)\n );\n }\n\n possibleSearchCombinations = this.#decodePotentialSpecialChars(\n possibleSearchCombinations\n );\n\n const searchFilters = possibleSearchCombinations.map((combination) => {\n let searchWordsForCombination = combination.map((wordInCombination) => {\n wordInCombination = this.#escapeSpecialChars(wordInCombination);\n wordInCombination = this.#addPotentialWildCards(\n wordInCombination,\n searchOptions\n );\n return wordInCombination;\n });\n return this.#getSearchFilters(\n searchWordsForCombination,\n searchSource,\n searchOptions\n );\n });\n\n comparisonFilters =\n searchFilters.length > 1 ? new Or(...searchFilters) : searchFilters[0];\n }\n\n // If searchOptions contain any features, we should filter the results\n // using those features.\n if (searchOptions.featuresToFilter.length > 0) {\n // First determine which spatial filter should be used:\n const activeSpatialFilter =\n searchOptions.activeSpatialFilter === \"within\" ? Within : Intersects;\n // Next, loop through supplied features and create the desired filter\n spatialFilters = searchOptions.featuresToFilter.map((feature) => {\n // If the drawn feature that we want to use as a filter happens to be an\n // OpenLayers Circle feature, we must convert it to a polygon. (GML only\n // accepts the following operands: Point, LineString, Polygon, Envelope.)\n // If it's not a Circle however, let's clone the geometry, to avoid\n // modifying the geometry that belongs to the feature that will be used\n // throughout the loop (see also \"Fix for QGIS\" below).\n const geometry =\n feature.getGeometry().getType() === \"Circle\"\n ? fromCircle(feature.getGeometry())\n : feature.getGeometry().clone();\n\n // Fix for QGIS Server: for some unknown reasons QGIS doesn't want the Polygon\n // to be closed. We fix it by basically removing the last two elements of the\n // flatCoordinates array, effectively eliminating the last point of the polygon.\n // See also: https://github.com/hajkmap/Hajk/issues/882#issuecomment-956099289\n searchSource.serverType === \"qgis\" &&\n geometry.flatCoordinates.splice(-2, 2);\n return new activeSpatialFilter(geometryName, geometry, srsName);\n });\n\n // If one feature was supplied, we end up with one filter. Let's use it.\n // But if more features were supplied, we must combine them into an Or filter.\n spatialFilters =\n spatialFilters.length > 1\n ? new Or(...spatialFilters)\n : spatialFilters[0];\n }\n\n // Finally, let's combine the text and spatial filters into\n // one filter that will be sent with the request.\n if (comparisonFilters !== null && spatialFilters !== null) {\n // We have both text and spatial filters - let's combine them with an And filter.\n finalFilters = new And(comparisonFilters, spatialFilters);\n } else if (comparisonFilters !== null) {\n finalFilters = comparisonFilters;\n } else if (spatialFilters !== null) {\n finalFilters = spatialFilters;\n }\n\n // Before we actually send a fetch request, we must ensure\n // that it won't be empty, i.e. we must have at least one filter.\n // The reason where this can be empty is if _user tries to do a\n // textual search on a layer that lacks searchFields_. Those layers\n // are still usable (we don't need to defined searchFields for spatial\n // searches), so admins may have setup a layer like this. And in that\n // case, it's crucial that we don't do a GetFeature to the WFS that doesn't\n // contain any filters.\n // The return value of this method must be an object that contains a promise\n // and controller property (because the return value is used in a destruction\n // assignment later on), hence this odd return, instead of just a null value.\n if (finalFilters === null) {\n return { promise: null, controller: null };\n }\n\n // Prepare the options for the upcoming request.\n const options = {\n featureTypes: searchSource.layers,\n srsName: srsName,\n outputFormat: searchSource.outputFormat,\n geometryName: geometryName,\n maxFeatures: maxFeatures,\n filter: finalFilters,\n };\n\n const node = this.#wfsParser.writeGetFeature(options);\n const xmlSerializer = new XMLSerializer();\n const xmlString = xmlSerializer.serializeToString(node);\n const controller = new AbortController();\n const signal = controller.signal;\n\n const request = {\n credentials: \"same-origin\",\n signal: signal,\n method: \"POST\",\n headers: {\n \"Content-Type\": \"text/xml\",\n },\n body: xmlString,\n };\n const promise = hfetch(\n this.#app.config.appConfig.searchProxy + searchSource.url,\n request\n );\n\n return { promise, controller };\n };\n}\n\nexport default SearchModel;\n","class Plugin {\n constructor(spec) {\n this.searchInterface = spec.searchInterface;\n this.map = spec.map;\n this.app = spec.app;\n this.type = spec.type;\n this.options = spec.options;\n this.component = spec.component;\n this.sortOrder = spec.sortOrder || 0;\n }\n}\n\nexport default Plugin;\n","import { Projection } from \"ol/proj\";\n\nexport default class ConfigMapper {\n constructor(proxy) {\n this.proxy = proxy;\n }\n\n mapWMSConfig(args, properties) {\n function getLegendUrl(layer) {\n let legendUrl = \"\";\n\n // If there's no legend URL specified, we'll need to get it from our WMS\n if (args.legend === \"\") {\n /**\n * A layer can have multiple styles, so when getting Legend Graphic, it's important\n * to get it for the currently selected style.\n */\n\n // First get index if we're dealing with array\n let getIndex =\n args.layersInfo !== null\n ? args.layersInfo.findIndex((l) => l.id === layer)\n : null;\n // Next, use that index to grab correct style and save its name for later use\n let style =\n args.layersInfo !== null &&\n getIndex >= 0 &&\n args.layersInfo[getIndex].style;\n\n let geoserverLegendOptions = \"\";\n let qgisOptions = \"\";\n\n if (args.serverType === \"geoserver\") {\n /**\n * GeoServer allows finer control over the legend appearance via the vendor parameter LEGEND_OPTIONS.\n * See: https://docs.geoserver.org/latest/en/user/services/wms/get_legend_graphic/index.html#controlling-legend-appearance-with-legend-options\n */\n // Use custom legend options if specified by admin\n geoserverLegendOptions = properties.mapConfig.map.hasOwnProperty(\n \"geoserverLegendOptions\"\n )\n ? \"&LEGEND_OPTIONS=\" +\n properties.mapConfig.map.geoserverLegendOptions\n : \"\";\n }\n\n // QGIS Server requires the SERVICE parameter to be set, see issue #880.\n if (args.serverType === \"qgis\") {\n qgisOptions = \"&SERVICE=WMS\";\n }\n\n // If layers URL already includes a query string separator (ie question mark), we want\n // to append the remaining values with &.\n const theGlue = args.url.includes(\"?\") ? \"&\" : \"?\";\n\n legendUrl = `${proxy}${args.url}${theGlue}REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&LAYER=${layer}&STYLE=${style}${geoserverLegendOptions}${qgisOptions}`;\n }\n // If there's a legend URL specified in admin, use it as is\n else {\n legendUrl = args.legend;\n }\n\n // If 'legend' URL doesn't start with \"http\", add \"https://\" prior 'legend', else let it be as is\n const protocol = /^http/.test(legendUrl) ? \"\" : \"https://\";\n return protocol + legendUrl;\n }\n\n function getLegends() {\n return args.layers.map((layer) => {\n return {\n url: getLegendUrl(layer),\n description: \"Teckenförklaring\",\n };\n });\n }\n\n function mapLayersInfo(layersInfo, infobox) {\n if (Array.isArray(layersInfo)) {\n return layersInfo.reduce((layersInfoObject, layerInfo) => {\n layersInfoObject[layerInfo.id] = layerInfo;\n if (!layerInfo.legend) {\n layersInfoObject[layerInfo.id].legend = getLegendUrl(layerInfo.id);\n }\n if (infobox?.length) {\n layersInfoObject[layerInfo.id].infobox = infobox;\n }\n\n return layersInfoObject;\n }, {});\n }\n }\n\n let proxy = this.proxy || \"\";\n\n // We can not assume that args.projection is sat,\n // and if it's not, we should fall back to map config's projection.\n let projection =\n args.projection !== null\n ? args.projection\n : properties.mapConfig.map.projection;\n\n // WMS 1.3.0 requires a custom Projection object, as we need to specify 'axisOrientation'\n if (args.version === \"1.3.0\") {\n // Create a new Projection\n let projCode = projection;\n projection = new Projection({\n code: projCode,\n axisOrientation: \"neu\",\n extent: properties.mapConfig.map.extent,\n });\n }\n\n // In the GetMap operation the srs parameter is called crs in 1.3.0,\n // see: https://docs.geoserver.org/latest/en/user/services/wms/basics.html#differences-between-wms-versions\n const srsOrCrs = args.version === \"1.3.0\" ? \"CRS\" : \"SRS\";\n\n if (args.minZoom === 0 && args.maxZoom === 0) {\n // backend returns 0 if not set in past\n args.minZoom = undefined;\n args.maxZoom = undefined;\n }\n\n let config = {\n type: \"wms\",\n options: {\n id: args.id,\n url:\n (this.proxy || \"\") +\n (this.getPotentialCustomUrl(args.customGetMapUrl) || args.url),\n name: args.id, // FIXME: Should this be \"args.caption\"?\n layerType: args.layerType,\n caption: args.caption,\n visible: args.visibleAtStart,\n opacity: args.opacity || 1,\n maxZoom: args.maxZoom,\n minZoom: args.minZoom,\n minMaxZoomAlertOnToggleOnly: args.minMaxZoomAlertOnToggleOnly,\n infoClickSortType: args.infoClickSortType,\n infoClickSortDesc: args.infoClickSortDesc,\n infoClickSortProperty: args.infoClickSortProperty,\n information: args.infobox,\n resolutions: properties.mapConfig.map.allResolutions,\n projection: projection || \"EPSG:3006\",\n origin: properties.mapConfig.map.origin,\n extent: properties.mapConfig.map.extent,\n singleTile: args.singleTile || false,\n hidpi: args.hidpi,\n customRatio: args.customRatio,\n imageFormat: args.imageFormat || \"image/png\",\n serverType:\n args.serverType === \"arcgis\"\n ? \"mapserver\"\n : args.serverType || \"geoserver\",\n crossOrigin: properties.mapConfig.map.crossOrigin || \"anonymous\",\n attribution: args.attribution,\n searchUrl: args.searchUrl,\n searchPropertyName: args.searchPropertyName,\n searchDisplayName: args.searchDisplayName,\n searchShortDisplayName: args.searchShortDisplayName,\n searchOutputFormat: args.searchOutputFormat,\n searchGeometryField: args.searchGeometryField,\n legend: getLegends(),\n legendIcon: args.legendIcon,\n params: {\n LAYERS: args.layers.join(\",\"),\n ...(args.cqlFilter && { CQL_FILTER: args.cqlFilter }), // nice way to add property only if needed\n FORMAT: args.imageFormat,\n INFO_FORMAT: args.infoFormat,\n VERSION: args.version || \"1.1.1\",\n [srsOrCrs]: projection || \"EPSG:3006\",\n TILED: args.tiled,\n STYLES: Array.isArray(args.layersInfo)\n ? args.layersInfo.map((l) => l.style || \"\").join(\",\")\n : null,\n },\n layersInfo: mapLayersInfo(args.layersInfo, args.infobox),\n infoVisible: args.infoVisible || false,\n infoTitle: args.infoTitle,\n infoText: args.infoText,\n infoUrl: args.infoUrl,\n infoUrlText: args.infoUrlText,\n infoOwner: args.infoOwner,\n hideExpandArrow: args.hideExpandArrow,\n timeSliderStart: args.timeSliderStart,\n timeSliderEnd: args.timeSliderEnd,\n },\n };\n\n if (args.searchFields && args.searchFields[0]) {\n config.options.search = {\n url: (this.proxy || \"\") + args.url.replace(\"wms\", \"wfs\"),\n featureType:\n args.layers[0].split(\":\")[1] || args.layers[0].split(\":\")[0],\n propertyName: args.searchFields.join(\",\"),\n displayName: args.displayFields\n ? args.displayFields\n : args.searchFields[0] || \"Sökträff\",\n srsName: properties.mapConfig.map.projection || \"EPSG:3006\",\n serverType: config.options.serverType,\n };\n }\n\n return config;\n }\n\n // There might be a custom getMap-url provided in the config. If there\n // is, we have to make sure to override the url-value with the custom getMap-url.\n // See #345 for more information.\n getPotentialCustomUrl(customGetMapUrl) {\n return customGetMapUrl?.trim().length > 0 ? customGetMapUrl : null;\n }\n\n mapWMTSConfig(args, properties) {\n if (args.minZoom === 0 && args.maxZoom === 0) {\n args.minZoom = undefined;\n args.maxZoom = undefined;\n }\n\n var config = {\n type: \"wmts\",\n options: {\n id: args.id,\n name: args.id,\n layerType: args.layerType,\n caption: args.caption,\n visible: args.visibleAtStart !== false,\n extent: properties.mapConfig.map.extent,\n queryable: false,\n opacity: args.opacity || 1,\n maxZoom: args.maxZoom,\n minZoom: args.minZoom,\n format: \"image/png\",\n crossOrigin: properties.mapConfig.map.crossOrigin || \"anonymous\",\n wrapX: false,\n url: args.url,\n layer: args.layer,\n matrixSet: args.matrixSet,\n style: args.style,\n projection: args.projection,\n origin: args.origin,\n resolutions: args.resolutions,\n matrixIds: args.matrixIds,\n attribution: args.attribution,\n legend: args.legend,\n legendIcon: args.legendIcon,\n infoVisible: args.infoVisible || false,\n infoTitle: args.infoTitle,\n infoText: args.infoText,\n infoUrl: args.infoUrl,\n infoUrlText: args.infoUrlText,\n infoOwner: args.infoOwner,\n hideExpandArrow: args.hideExpandArrow,\n timeSliderStart: args.timeSliderStart,\n timeSliderEnd: args.timeSliderEnd,\n },\n };\n return config;\n }\n\n mapDataConfig(args) {\n var config = {\n type: \"data\",\n options: {\n id: args.id,\n url: (this.proxy || \"\") + args.url,\n name: args.id,\n layerType: args.layerType,\n caption: args.caption,\n visible: args.visibleAtStart,\n opacity: 1,\n queryable: args.queryable !== false,\n extent: args.extent,\n projection: args.projection,\n },\n };\n\n return config;\n }\n\n mapVectorConfig(args) {\n var config = {\n type: \"vector\",\n options: {\n attribution: args.attribution,\n caption: args.caption,\n content: args.content,\n dataFormat: args.dataFormat,\n fillColor: args.fillColor,\n filterable: args.filterable,\n filterAttribute: args.filterAttribute,\n filterComparer: args.filterComparer,\n filterValue: args.filterValue,\n icon: args.icon,\n id: args.id,\n infoOwner: args.infoOwner,\n information: args.infobox,\n infoText: args.infoText,\n infoTitle: args.infoTitle,\n infoUrl: args.infoUrl,\n infoUrlText: args.infoUrlText,\n infoVisible: args.infoVisible || false,\n infoClickSortType: args.infoClickSortType,\n infoClickSortDesc: args.infoClickSortDesc,\n infoClickSortProperty: args.infoClickSortProperty,\n layerType: args.layerType,\n legend: [\n {\n url: args.legend,\n description: args.caption,\n },\n ],\n legendIcon: args.legendIcon,\n lineColor: args.lineColor,\n lineStyle: args.lineStyle,\n lineWidth: args.lineWidth,\n maxZoom: args.maxZoom,\n minZoom: args.minZoom,\n name: args.id,\n opacity: args.opacity,\n params: {\n service: \"WFS\",\n request: \"GetFeature\",\n version: args.version || \"1.1.0\",\n outputFormat:\n args.dataFormat === \"GeoJSON\" // If GeoJSON,\n ? \"application/json\" // set correct outputFormat (see https://docs.geoserver.org/latest/en/user/services/wfs/outputformats.html)\n : args.version === \"1.0.0\" // else (if dataFormat is not GeoJSON), check which WFS version we have and\n ? \"GML2\" // use the GML2 parser for WFS 1.0.0, or\n : \"GML3\", // GML3 for version > 1.0.0 (again, see above link).\n typename: args.layer,\n srsname: args.projection,\n bbox: \"\",\n },\n pointSize: args.pointSize,\n projection: args.projection,\n queryable: args.queryable,\n sldStyle: args.sldStyle,\n sldText: args.sldText,\n sldUrl: args.sldUrl,\n symbolXOffset: args.symbolXOffset,\n symbolYOffset: args.symbolYOffset,\n url: args.url,\n visible: args.visibleAtStart,\n timeSliderStart: args.timeSliderStart,\n timeSliderEnd: args.timeSliderEnd,\n },\n };\n\n return config;\n }\n\n mapArcGISConfig(args) {\n function getLegendUrl() {\n if (!Array.isArray(args.legend)) {\n if (/^data/.test(args.legend)) {\n args.legend = args.legend.split(\"#\");\n } else if (!/^http/.test(args.legend)) {\n args.legend = \"https://\" + args.legend;\n }\n }\n return args.legend;\n }\n\n var config = {\n type: \"arcgis\",\n options: {\n id: args.id,\n url: args.url,\n name: args.id,\n layerType: args.layerType,\n caption: args.caption,\n visible: args.visibleAtStart,\n queryable: args.queryable !== false,\n singleTile: args.singleTile !== false,\n extent: args.extent,\n information: args.infobox,\n projection: args.projection,\n opacity: args.opacity,\n attribution: args.attribution,\n params: {\n LAYERS: \"show:\" + args.layers.join(\",\"),\n },\n legend: [\n {\n url: getLegendUrl(args),\n description: \"Teckenförklaring\",\n },\n ],\n infoVisible: args.infoVisible || false,\n infoTitle: args.infoTitle,\n infoText: args.infoText,\n infoUrl: args.infoUrl,\n infoUrlText: args.infoUrlText,\n infoOwner: args.infoOwner,\n hideExpandArrow: args.hideExpandArrow,\n timeSliderStart: args.timeSliderStart,\n timeSliderEnd: args.timeSliderEnd,\n },\n };\n\n return config;\n }\n}\n","import proj4 from \"proj4\";\n\nfunction add(projection) {\n proj4.defs(projection.code, projection.definition);\n}\n\nexport default class CoordinateSystemLoader {\n constructor(config) {\n if (Array.isArray(config)) {\n config.forEach((projection) => {\n add(projection);\n });\n }\n }\n\n getProj4() {\n return proj4;\n }\n}\n","import TileGrid from \"ol/tilegrid/TileGrid\";\nimport ImageLayer from \"ol/layer/Image\";\nimport TileLayer from \"ol/layer/Tile\";\nimport ImageWMS from \"ol/source/ImageWMS\";\nimport TileWMS from \"ol/source/TileWMS\";\nimport GeoJSON from \"ol/format/GeoJSON\";\nimport LayerInfo from \"./LayerInfo.js\";\nimport { equals } from \"ol/extent\";\nimport { delay } from \"../../utils/Delay\";\nimport { hfetch, overrideLayerSourceParams } from \"utils/FetchWrapper\";\n\nclass WMSLayer {\n constructor(config, proxyUrl, globalObserver) {\n this.proxyUrl = proxyUrl;\n this.globalObserver = globalObserver;\n this.validInfo = true;\n this.legend = config.legend;\n this.attribution = config.attribution;\n this.layerInfo = new LayerInfo(config);\n this.subLayers = config.params[\"LAYERS\"].split(\",\");\n\n let source = {\n url: config.url,\n params: config.params,\n projection: config.projection,\n serverType: config.serverType,\n crossOrigin: config.crossOrigin,\n imageFormat: config.imageFormat,\n attributions: config.attribution,\n cacheSize: this.subLayers.length > 1 ? 32 : 2048,\n transition: this.subLayers.length > 1 ? 0 : 100,\n };\n\n if (config.hidpi !== null) {\n source.hidpi = config.hidpi;\n }\n\n overrideLayerSourceParams(source);\n\n const minZoom = config?.minZoom >= 0 ? config.minZoom : undefined;\n const maxZoom = config?.maxZoom >= 0 ? config.maxZoom : undefined;\n\n if (\n config.resolutions &&\n config.resolutions.length > 0 &&\n config.origin &&\n config.origin.length > 0\n ) {\n source.tileGrid = new TileGrid({\n resolutions: config.resolutions,\n origin: config.origin,\n });\n source.extent = config.extent;\n }\n\n if (config.singleTile) {\n if (config.customRatio >= 1) {\n source.ratio = config.customRatio;\n }\n this.layer = new ImageLayer({\n name: config.name,\n visible: config.visible,\n caption: config.caption,\n opacity: config.opacity,\n source: new ImageWMS(source),\n layerInfo: this.layerInfo,\n url: config.url,\n timeSliderStart: config?.timeSliderStart,\n timeSliderEnd: config?.timeSliderEnd,\n minZoom: minZoom,\n maxZoom: maxZoom,\n minMaxZoomAlertOnToggleOnly:\n config.minMaxZoomAlertOnToggleOnly || false,\n });\n } else {\n this.layer = new TileLayer({\n name: config.name,\n visible: config.visible,\n caption: config.caption,\n opacity: config.opacity,\n source: new TileWMS(source),\n layerInfo: this.layerInfo,\n url: config.url,\n timeSliderStart: config?.timeSliderStart,\n timeSliderEnd: config?.timeSliderEnd,\n minZoom: minZoom,\n maxZoom: maxZoom,\n minMaxZoomAlertOnToggleOnly:\n config.minMaxZoomAlertOnToggleOnly || false,\n });\n }\n\n this.layer.layersInfo = config.layersInfo;\n this.layer.subLayers = this.subLayers;\n this.layer.layerType = this.getLayerType();\n this.layer.getSource().set(\"url\", config.url);\n this.type = \"wms\";\n this.bindHandlers();\n }\n\n // If the layerType is set as a base-layer in the config-mapper,\n // it should be kept as a base-layer, *even if it has sub-layers*.\n // The old behavior (before this commit) was that the base-layer was\n // \"transformed\" to a \"group-layer\" if it had more than one subLayer.\n // Since base-layers might be constructed with several subLayers, we\n // shouldn't do that transformation... If the baseLayer is transformed\n // to a \"group-layer\" we will get several errors, since the baseLayers\n // does not contain all necessary information to render a \"group-layer\".\n getLayerType() {\n // Destruct the layerType from the layerInfo\n const { layerType } = this.layerInfo;\n // Check if the type is set to \"base\", and if it is,\n // return \"base\". If it is not, we check if we have more than\n // one subLayer; if we do, we return \"group\", and otherwise it is\n // a regular \"layer\".\n return layerType === \"base\"\n ? \"base\"\n : this.subLayers.length > 1\n ? \"group\"\n : \"layer\";\n }\n\n /**\n * Bind handlers for TileWMS and ImageWMS\n * @instance\n */\n bindHandlers() {\n const layerSource = this.layer.getSource();\n if (layerSource instanceof TileWMS) {\n layerSource.on(\"tileloaderror\", this.onTileLoadError);\n layerSource.on(\"tileloadend\", this.onTileLoadOk);\n }\n if (layerSource instanceof ImageWMS) {\n layerSource.on(\"imageloaderror\", this.onImageError);\n }\n }\n\n /**\n * Triggers when a tile fails to load.\n * @instance\n */\n onTileLoadError = () => {\n this.globalObserver.publish(\"layerswitcher.wmsLayerLoadStatus\", {\n id: this.layer.get(\"name\"),\n status: \"loaderror\",\n });\n };\n\n /**\n * Triggers when a tile loads.\n * @instance\n */\n onTileLoadOk = () => {\n this.globalObserver.publish(\"layerswitcher.wmsLayerLoadStatus\", {\n id: this.layer.get(\"name\"),\n status: \"ok\",\n });\n };\n\n /**\n * If we get an error while loading Image we try to refresh it once per extent.\n * This check is needed because we don't want to get stuck in an endless loop in case image repeatedly fails\n * @instance\n */\n onImageError = async (e) => {\n const layerSource = this.layer.getSource();\n const previousErrorExtent = e.target.get(\"previousErrorExtent\") || [];\n const currentErrorExtent = e.image.extent;\n if (!equals(previousErrorExtent, currentErrorExtent)) {\n await delay(300); //Delay refresh of layers who caused error to not throttle the canvas and get new errors\n layerSource.refresh();\n }\n e.target.set(\"previousErrorExtent\", currentErrorExtent);\n };\n\n /**\n * Load feature information.\n * @instance\n * @param {external:\"ol.feature\"} feature\n * @return {external:\"ol.style\"} style\n */\n getFeatureInformation(params) {\n try {\n this.validInfo = true;\n this.featureInformationCallback = params.success;\n\n let url = this.getLayer()\n .getSource()\n .getFeatureInfoUrl(\n params.coordinate,\n params.resolution,\n params.projection,\n {\n INFO_FORMAT:\n this.get(\"serverType\") === \"arcgis\" ||\n this.get(\"serverType\") === \"mapserver\"\n ? \"application/geojson\"\n : \"application/json\",\n feature_count: 100,\n }\n );\n\n if (url) {\n if (this.proxyUrl) {\n url = encodeURIComponent(url);\n }\n\n hfetch(this.proxyUrl + url)\n .then((response) => {\n response.json().then((data) => {\n var features = new GeoJSON().readFeatures(data);\n this.featureInformationCallback(features, this.getLayer());\n });\n })\n .catch((err) => {\n params.error(err);\n });\n }\n } catch (e) {\n params.error(e);\n }\n }\n\n /**\n * Get legend url.\n * @instance\n * @param {string} layerName\n * @return {object} legend\n */\n getLegendUrl(layerName) {\n var legend = Object.assign({}, this.legend);\n legend[0].Url = legend[0].Url.replace(/LAYER=.*/, \"LAYER=\" + layerName);\n return legend;\n }\n}\n\n/**\n * WmsLayer module.<br>\n * Use <code>require('layer/wmslayer')</code> for instantiation.\n * @module WMSLayer-module\n * @returns {WMSLayer}\n */\nexport default WMSLayer;\n","import View from \"ol/View\";\nimport TileLayer from \"ol/layer/Tile\";\nimport WMTS from \"ol/source/WMTS\";\nimport WMTSTileGrid from \"ol/tilegrid/WMTS\";\nimport LayerInfo from \"./LayerInfo.js\";\nimport { overrideLayerSourceParams } from \"utils/FetchWrapper\";\n\nvar wmtsLayerProperties = {\n url: \"\",\n projection: \"EPSG:3006\",\n layer: \"\",\n opacity: 1,\n matrixSet: \"3006\",\n style: \"default\",\n axisMode: \"natural\",\n origin: [-1200000, 8500000],\n resolutions: [4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5],\n matrixIds: [\n \"0\",\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"10\",\n \"11\",\n \"12\",\n ],\n attribution: \"\",\n};\n\nclass WMTSLayer {\n constructor(config, proxyUrl, map) {\n config = {\n ...wmtsLayerProperties,\n ...config,\n };\n this.proxyUrl = proxyUrl;\n this.map = map;\n this.resolutions = this.resolutions = config.resolutions.map((r) =>\n Number(r)\n );\n this.projection = config.projection;\n\n let source = {\n attributions: config.attribution,\n format: \"image/png\",\n wrapX: false,\n url: config.url,\n crossOrigin: config.crossOrigin,\n axisMode: config.axisMode,\n layer: config.layer,\n matrixSet: config.matrixSet,\n style: config.style,\n projection: this.projection,\n tileGrid: new WMTSTileGrid({\n origin: config.origin.map((o) => Number(o)),\n resolutions: this.resolutions,\n matrixIds: config.matrixIds,\n extent: config.extent,\n }),\n };\n\n overrideLayerSourceParams(source);\n\n const minZoom = config?.minZoom >= 0 ? config.minZoom : undefined;\n const maxZoom = config?.maxZoom >= 0 ? config.maxZoom : undefined;\n\n this.layer = new TileLayer({\n name: config.name,\n visible: config.visible,\n queryable: config.queryable,\n opacity: config.opacity,\n source: new WMTS(source),\n layerInfo: new LayerInfo(config),\n minZoom: minZoom,\n maxZoom: maxZoom,\n });\n this.updateMapViewResolutions();\n this.type = \"wmts\";\n }\n\n updateMapViewResolutions() {\n var view = this.map.getView();\n this.map.setView(\n new View({\n zoom: view.getZoom(),\n center: view.getCenter(),\n resolutions: this.resolutions,\n projection: this.projection,\n constrainResolution: view.getConstrainResolution(),\n })\n );\n }\n}\n\nexport default WMTSLayer;\n","import VectorSource from \"ol/source/Vector\";\nimport VectorLayer from \"ol/layer/Vector\";\nimport GeoJSON from \"ol/format/GeoJSON\";\nimport GML2 from \"ol/format/GML2\";\nimport GML3 from \"ol/format/GML3\";\nimport WFS from \"ol/format/WFS\";\nimport { Fill, Text, Stroke, Icon, Circle, Style } from \"ol/style\";\nimport { all as strategyAll, bbox as bboxStrategy } from \"ol/loadingstrategy\";\nimport { getPointResolution, transform } from \"ol/proj\";\n\nimport * as SLDReader from \"@nieuwlandgeo/sldreader\";\n\nimport LayerInfo from \"./LayerInfo.js\";\nimport { hfetch } from \"utils/FetchWrapper\";\n\nconst vectorLayerProperties = {\n url: \"\",\n params: {\n service: \"WFS\",\n version: \"1.1.0\",\n request: \"GetFeature\",\n typename: \"\",\n outputFormat: \"GML3\",\n srsname: \"\",\n bbox: \"\",\n },\n showLabels: true,\n};\nclass WFSVectorLayer {\n constructor(config, proxyUrl, map) {\n this.config = {\n ...vectorLayerProperties,\n ...config,\n };\n this.proxyUrl = proxyUrl;\n this.map = map;\n this.type = \"vector\"; // We're dealing with a vector layer\n this.allFeatures = [];\n\n // Read the three filter properties from config to allow filter on load\n this.filterAttribute = config.filterAttribute;\n this.filterComparer = config.filterComparer;\n this.filterValue = config.filterValue;\n\n this.vectorSource = new VectorSource({\n // Ensure we display copyright attributions\n attributions: config.attribution,\n // Loader function makes \"url\" and \"format\" parameters ignored as it\n // provides an own loading procedure. \"strategy\" is still respected, see below.\n loader: (extent, resolution, projection) => {\n this.loadData(this.createUrl(extent, projection.getCode()));\n },\n // The loading strategy to use. By default the BBox strategy is used,\n // loading features based on the view's extent and resolution.\n strategy:\n this.config?.loadingStrategy === \"all\" ? strategyAll : bboxStrategy,\n });\n\n this.layer = new VectorLayer({\n information: config.information,\n caption: config.caption,\n name: config.name,\n visible: config.visible,\n opacity: config.opacity,\n queryable: config.queryable,\n filterable: config.filterable,\n filterAttribute: config.filterAttribute,\n filterComparer: config.filterComparer,\n filterValue: config.filterValue,\n layerInfo: new LayerInfo(config),\n renderMode: \"image\",\n source: this.vectorSource,\n url: config.url,\n featureType: config.params.typename.split(\":\")[1],\n minZoom: config?.minZoom >= 0 ? config.minZoom : undefined,\n maxZoom: config?.maxZoom >= 0 ? config.maxZoom : undefined,\n timeSliderStart: config?.timeSliderStart,\n timeSliderEnd: config?.timeSliderEnd,\n });\n\n // Styling section starts here.\n // First read some values from config\n this.sldUrl = config?.sldUrl;\n this.sldText = config?.sldText;\n this.sldStyle = config?.sldStyle ?? \"Default Styler\";\n\n // Try fetching the URL, if specified, and style with the resulting SLD\n if (typeof this.sldUrl === \"string\" && this.sldUrl.trim().length > 0) {\n hfetch(this.sldUrl)\n .then((response) => response.text())\n .then((text) => this.applySldTextOnLayer(text));\n }\n // …else use supplied SLD text to style\n else if (\n typeof this.sldText === \"string\" &&\n this.sldText.trim().length > 10\n ) {\n this.applySldTextOnLayer(this.sldText);\n }\n // ...else use OpenLayer's style if specified in config\n else if (\n config.icon ||\n config.lineColor ||\n config.lineWidth ||\n config.fillColor ||\n config.lineStyle\n ) {\n this.layer.setStyle(this.createStyle());\n }\n // …or just fall back to OpenLayer's default styling if no SLD/SLD URL or OpenLayers style was specified.\n }\n\n applySldTextOnLayer = (text) => {\n const sldObject = SLDReader.Reader(text);\n const sldLayer = SLDReader.getLayer(sldObject);\n const style = SLDReader.getStyle(sldLayer, this.sldStyle);\n const featureTypeStyle = style.featuretypestyles[0];\n\n const viewProjection = this.map.getView().getProjection();\n const olFunction = SLDReader.createOlStyleFunction(featureTypeStyle, {\n // Use the convertResolution option to calculate a more accurate resolution.\n convertResolution: (viewResolution) => {\n const viewCenter = this.map.getView().getCenter();\n return getPointResolution(viewProjection, viewResolution, viewCenter);\n },\n // If you use point icons with an ExternalGraphic, you have to use imageLoadCallback to\n // to update the vector layer when an image finishes loading.\n // If you do not do this, the image will only become visible after the next pan/zoom of the layer.\n imageLoadedCallback: () => {\n this.layer.changed();\n },\n });\n this.layer.setStyle(olFunction);\n };\n\n reprojectFeatures(features, from, to) {\n if (Array.isArray(features)) {\n features.forEach((feature) => {\n if (feature.getGeometry() && feature.getGeometry().getCoordinates) {\n let coords = feature.getGeometry().getCoordinates();\n try {\n switch (feature.getGeometry().getType()) {\n case \"Point\":\n feature\n .getGeometry()\n .setCoordinates(transform(coords, from, to));\n break;\n case \"LineString\":\n feature\n .getGeometry()\n .setCoordinates(\n coords.map((coord) => transform(coord, from, to))\n );\n break;\n case \"Polygon\":\n feature\n .getGeometry()\n .setCoordinates([\n coords[0].map((coord) => transform(coord, from, to)),\n ]);\n break;\n default:\n throw new Error(\"Unknown geometry type.\");\n }\n } catch (e) {\n console.error(\"Coordinate transformation error.\", e);\n }\n }\n });\n }\n }\n\n getAllFeatures(data) {\n let features = [];\n let parser = null;\n const to = this.map.getView().getProjection().getCode();\n const from = this.config.projection;\n const outputFormat = this.config.params.outputFormat;\n\n if (outputFormat.startsWith(\"GML\")) {\n // If output format starts with GML, create a GML parser.\n // For WFS version 1.0.0 the GML2 parser should be used,\n // else GML3.\n parser = new WFS({\n gmlFormat:\n this.config.params.version === \"1.0.0\" ? new GML2() : new GML3(),\n });\n }\n\n if (outputFormat === \"application/json\") {\n parser = new GeoJSON();\n }\n\n if (parser) {\n features = parser.readFeatures(data);\n }\n\n if (to !== from) {\n this.reprojectFeatures(features, from, to);\n }\n\n return features;\n }\n\n /**\n * @summary If filtering is activated, filter feature collection, f. Else return all features.\n *\n * @param {*} f Feature collection to be filtered.\n * @returns\n * @memberof WFSVectorLayer\n */\n getFilteredFeatures(f) {\n if (this.layer.get(\"filterAttribute\") && this.layer.get(\"filterValue\")) {\n return f.filter((feature) => this.filterMethod(feature));\n } else {\n return f;\n }\n }\n\n /**\n * @summary A predicate method (returns either true of false), used to determine\n * whether current feature should be included in the filtered result.\n *\n * @param {*} feature Feature to check.\n * @returns {boolean}\n * @memberof WFSVectorLayer\n */\n filterMethod(feature) {\n const filterAttribute = this.layer.get(\"filterAttribute\");\n const filterValue = this.layer.get(\"filterValue\");\n const filterComparer = this.layer.get(\"filterComparer\");\n\n switch (filterComparer) {\n case \"gt\":\n return (\n Number(feature.getProperties()[filterAttribute]) > Number(filterValue)\n );\n case \"lt\":\n return (\n Number(feature.getProperties()[filterAttribute]) < Number(filterValue)\n );\n case \"eq\":\n if (!Number.isNaN(Number(filterValue))) {\n return (\n Number(feature.getProperties()[filterAttribute]) ===\n Number(filterValue)\n );\n }\n return feature.getProperties()[filterAttribute] === filterValue;\n case \"not\":\n if (!Number.isNaN(Number(filterValue))) {\n return (\n Number(feature.getProperties()[filterAttribute]) !==\n Number(filterValue)\n );\n }\n return feature.getProperties()[filterAttribute] !== filterValue;\n default:\n return false;\n }\n }\n\n createUrl(extent = [], projection = \"\") {\n // Grab params needed for URL creation\n const props = this.config.params;\n\n // Get rid of bbox that comes from config\n delete props.bbox;\n\n // Turn params into URLSearchParams string\n const usp = new URLSearchParams(props).toString();\n\n // If extent doesn't contain Infinity values, append it to the URL\n const bbox =\n extent.length === 4 && extent.includes(Infinity) === false\n ? `&bbox=${extent.join(\",\")},${projection}`\n : \"\";\n\n const url = this.config.url + \"?\" + usp + bbox;\n return url;\n }\n\n loadData(url) {\n url = this.proxyUrl + url;\n\n hfetch(url).then((response) => {\n response.text().then((features) => {\n // Load all features (no filter active - only bbox limitation)\n this.allFeatures = this.getAllFeatures(features);\n\n // See if filtering is needed and populate the source with resulting features\n this.vectorSource.addFeatures(\n this.getFilteredFeatures(this.allFeatures)\n );\n });\n });\n }\n\n createStyle(forcedPointRadius) {\n const icon = this.config.icon || \"\";\n const fillColor = this.config.fillColor || \"rgba(255,255,255,0.4)\"; // OpenLayers default\n const lineColor = this.config.lineColor || \"#3399CC\"; // OpenLayers default\n const lineStyle = this.config.lineStyle || \"\";\n const lineWidth = this.config.lineWidth || \"\";\n const symbolXOffset = this.config.symbolXOffset || \"\";\n const symbolYOffset = this.config.symbolYOffset || \"\";\n const rotation = 0.0;\n const align = this.config.labelAlign;\n const baseline = this.config.labelBaseline;\n const size = this.config.labelSize;\n const offsetX = this.config.labelOffsetX;\n const offsetY = this.config.labelOffsetY;\n const weight = this.config.labelWeight;\n const font = weight + \" \" + size + \" \" + this.config.labelFont;\n const labelFillColor = this.config.labelFillColor;\n const outlineColor = this.config.labelOutlineColor;\n const outlineWidth = this.config.labelOutlineWidth;\n const showLabels = this.config.showLabels;\n const pointSize = forcedPointRadius || this.config.pointSize || 4; // OpenLayers default Circle use point size\n const iconScale = pointSize / 8; // OpenLayers icon use scale. Medium size (8) => icon scale 1\n\n function getLineDash() {\n var scale = (a, f) => a.map((b) => f * b),\n width = lineWidth,\n style = lineStyle,\n dash = [12, 7],\n dot = [2, 7];\n switch (style) {\n case \"dash\":\n return width > 3 ? scale(dash, 2) : dash;\n case \"dot\":\n return width > 3 ? scale(dot, 2) : dot;\n default:\n return undefined;\n }\n }\n\n function getFill() {\n return new Fill({\n color: fillColor,\n });\n }\n\n function getText() {\n return new Text({\n textAlign: align,\n textBaseline: baseline,\n font: font,\n text: \"\",\n fill: new Fill({\n color: labelFillColor,\n }),\n stroke: new Stroke({\n color: outlineColor,\n width: outlineWidth,\n }),\n offsetX: offsetX,\n offsetY: offsetY,\n rotation: rotation,\n });\n }\n\n function getImage() {\n return icon === \"\" ? getPoint() : getIcon();\n }\n\n function getIcon() {\n return new Icon({\n src: icon,\n scale: iconScale,\n anchorXUnits: \"pixels\",\n anchorYUnits: \"pixels\",\n anchor: [symbolXOffset, symbolYOffset],\n });\n }\n\n function getPoint() {\n return new Circle({\n fill: getFill(),\n stroke: getStroke(),\n radius: parseInt(pointSize, 10) || 4,\n });\n }\n\n function getStroke() {\n return new Stroke({\n color: lineColor,\n width: lineWidth,\n lineDash: getLineDash(),\n });\n }\n\n function getStyleObj() {\n var obj = {\n fill: getFill(),\n image: getImage(),\n stroke: getStroke(),\n };\n if (showLabels) {\n obj.text = getText();\n }\n\n return obj;\n }\n\n return [new Style(getStyleObj())];\n }\n}\n\nexport default WFSVectorLayer;\n","import Snap from \"ol/interaction/Snap\";\n\nexport default class SnapHelper {\n constructor(app) {\n this.map = app.map;\n this.globalObserver = app.globalObserver;\n\n this.snapInteractions = []; // Will hold snap interactions\n\n // Initiate a new set that will hold active plugins\n this.activePlugins = new Set();\n\n // Initiate a variable that keeps track of pending updates\n this.updatePending = false;\n\n // When layer visibility is changed, check if there was a\n // vector source. If so, refresh the snap interactions to\n // reflect the visibility change.\n this.globalObserver.on(\n \"core.layerVisibilityChanged\",\n this.#handleLayerVisibilityChanged\n );\n }\n /**\n * @summary Adds a given plugin to the set of plugins interested of\n * snap interaction. As long as this set isn't empty, Snap helper knows\n * that interactions should be added.\n *\n * @param {string} plugin\n * @memberof SnapHelper\n */\n add(plugin) {\n // If this is the first plugin that wants to activate Snap,\n // ensure that we add the interactions to map. Else, they've\n // already been added and there's no need to do it again.\n this.activePlugins.size === 0 && this.#addSnapToAllVectorSources();\n\n // Add the plugin to our stack\n this.activePlugins.add(plugin);\n }\n /**\n * @summary Does the opposite of add() by deleting a plugin from the Set.\n * When the set is empty, Snap helper knows that no one is interested in snapping\n * anyway, and it can remove all snap interactions (when the last plugin leaves the list).\n *\n * @param {string} plugin\n * @memberof SnapHelper\n */\n delete(plugin) {\n this.activePlugins.delete(plugin);\n\n // If there are no active plugins left, remove interactions\n this.activePlugins.size === 0 && this.#removeAllSnapInteractions();\n }\n /**\n * @summary Helper used to determine if a given source is ol.VectorSource.\n * @description Ideally, we would look into the prototype, to see if\n * constructor.name is \"VectorSource\". But, because Webpack uglifies the\n * class names, we can't do that. This is the best I came up with regarding\n * finding out whether the source appears to be a vector source or not: we\n * look for the getFeatures() method. It only exists on vector sources, so\n * it should be safe to use this way.\n *\n * @param {object} source\n * @returns {*} isVectorSource\n */\n #isVectorSource = (source) => {\n return typeof source[\"getFeatures\"] === \"function\";\n };\n\n /**\n * @summary Called when a layer's visibility is changed. Ensures that\n * snapping is always enabled for all visible vector sources.\n *\n * @param {*} e Event that contains the layer who's visibility has changed.\n */\n #handleLayerVisibilityChanged = (e) => {\n if (\n this.activePlugins.size === 0 || // Abort if no plugin is interested of snap interactions\n this.updatePending === true || // Abort if there already is a pending update\n this.#isVectorSource(e.target.getSource()) === false // Abort if event was triggered on a non-vector source\n )\n return;\n\n // Switch the pending flag to true, this will avoid multiple invokations\n this.updatePending = true;\n\n // After 250 ms…\n setTimeout(() => {\n // Reload sources\n this.#removeAllSnapInteractions();\n this.#addSnapToAllVectorSources();\n // Reset the flag\n this.updatePending = false;\n }, 250);\n };\n\n #addSnapToAllVectorSources = () => {\n const vectorSources = this.map\n .getLayers() // Get layers\n .getArray() // as arrays\n .filter((l) => l.getVisible()) // and only currently visible.\n .map((l) => l.getSource()) // Get each layer's source\n .filter(this.#isVectorSource); // but only if it is a VectorSource (which we'll know by checking for \"getFeatures\").\n\n // Add the snap interaction for each found source\n vectorSources.forEach((source) => {\n const snap = new Snap({\n source,\n });\n this.map.addInteraction(snap);\n\n // And save each interaction into a local stack (so we can remove them later)\n this.snapInteractions.push(snap);\n });\n };\n\n #removeAllSnapInteractions = () => {\n if (this.snapInteractions.length === 0) return;\n\n // Loop through the local stack of snap interactions\n for (const i of this.snapInteractions) {\n // And remove each one of them from the map\n this.map.removeInteraction(i);\n }\n\n // Important: purge the local stack!\n this.snapInteractions = [];\n };\n}\n","import React from \"react\";\nimport propTypes from \"prop-types\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport ArrowLeftIcon from \"@material-ui/icons/ArrowLeft\";\nimport ArrowRightIcon from \"@material-ui/icons/ArrowRight\";\nimport FeaturePropsParsing from \"./FeaturePropsParsing\";\n// import Diagram from \"../Diagram\";\n// import HajkTable from \"../Table\";\nimport {\n Table,\n TableContainer,\n CircularProgress,\n TableRow,\n TableCell,\n TableBody,\n Button,\n Typography,\n Grid,\n} from \"@material-ui/core\";\n\nconst styles = (theme) => ({\n toggler: {\n backgroundColor: theme.palette.primary.main,\n },\n infoContainer: {\n height: \"100%\",\n cursor: \"auto\",\n userSelect: \"text\",\n },\n typography: {\n textAlign: \"center\",\n },\n columnValue: {\n wordBreak: \"break-all\",\n },\n columnKey: {\n verticalAlign: \"top\",\n },\n featureInfoContainer: {\n flex: \"auto\",\n },\n featureInfo: {\n width: \"100%\",\n },\n togglerButtonRightContainer: {\n borderRight: `${theme.spacing(0.2)}px solid ${theme.palette.divider}`,\n },\n togglerButtonLeftContainer: {\n borderLeft: `${theme.spacing(0.2)}px solid ${theme.palette.divider}`,\n },\n});\n\nclass FeatureInfoContainer extends React.PureComponent {\n state = {\n selectedIndex: 0,\n };\n\n static propTypes = {\n classes: propTypes.object.isRequired,\n features: propTypes.array.isRequired,\n onDisplay: propTypes.func.isRequired,\n };\n\n constructor(props) {\n super(props);\n this.featurePropsParsing = new FeaturePropsParsing({\n globalObserver: props.globalObserver,\n options: props.options,\n });\n }\n\n componentDidMount() {\n this.updateFeatureInformation(0);\n }\n\n showFeatureInMap = () => {\n const { onDisplay, features } = this.props;\n onDisplay(features[this.state.selectedIndex]);\n };\n\n stepLeft = () => {\n if (this.state.selectedIndex - 1 > -1) {\n let newIndex = this.state.selectedIndex - 1;\n this.updateFeatureInformation(newIndex);\n }\n };\n\n stepRight = () => {\n const { features } = this.props;\n if (this.state.selectedIndex + 1 < features.length) {\n let newIndex = this.state.selectedIndex + 1;\n this.updateFeatureInformation(newIndex);\n }\n };\n\n getToggler = () => {\n const { features, classes } = this.props;\n return (\n <Grid\n alignItems=\"center\"\n justify=\"space-between\"\n className={classes.toggler}\n container\n >\n <Grid item className={classes.togglerButtonRightContainer}>\n <Button\n fullWidth\n disabled={this.state.selectedIndex - 1 < 0}\n onClick={this.stepLeft}\n aria-label=\"previous\"\n id=\"step-left\"\n >\n <ArrowLeftIcon color=\"secondary\" />\n </Button>\n </Grid>\n <Grid item>\n <Typography\n variant=\"button\"\n color=\"secondary\"\n className={classes.typography}\n >\n {this.state.selectedIndex + 1} av {features.length}\n </Typography>\n </Grid>\n <Grid item className={classes.togglerButtonLeftContainer}>\n <Button\n fullWidth\n disabled={this.state.selectedIndex + 1 >= features.length}\n onClick={this.stepRight}\n aria-label=\"next\"\n id=\"step-right\"\n >\n <ArrowRightIcon color=\"secondary\" />\n </Button>\n </Grid>\n </Grid>\n );\n };\n\n getFeaturesAsDefaultTable(data, caption) {\n const { classes } = this.props;\n // We can't use \"i\" for coloring every second row, as some rows\n // will be removed (Objects are not printed), so there's a need\n // for a separate counter of rows that actually get printed.\n let j = 0;\n const tableBody = Object.keys(data).map((key, i) => {\n if (typeof data[key] !== \"object\") {\n ++j;\n return (\n <TableRow key={i} selected={j % 2 === 0}>\n <TableCell className={classes.columnKey} variant=\"head\">\n {key}\n </TableCell>\n <TableCell className={classes.columnValue}>{data[key]}</TableCell>\n </TableRow>\n );\n } else {\n return null;\n }\n });\n\n return (\n <TableContainer component=\"div\">\n <Table size=\"small\" aria-label=\"Table with infoclick details\">\n <TableBody>{tableBody}</TableBody>\n </Table>\n </TableContainer>\n );\n }\n\n // shortcode(str) {\n // const codes = [];\n // let shortcodes = str.match(/\\[(.*?)\\]/g);\n // shortcodes = shortcodes === null ? [] : shortcodes;\n\n // if (shortcodes) {\n // shortcodes.forEach((code) => {\n // str = str.replace(code, \"\");\n // var params = code.replace(\"[\", \"\").replace(\"]\", \"\").split(\" \");\n // var c = {};\n\n // params.forEach((param, i) => {\n // if (i === 0) {\n // c.shortcode = param;\n // } else {\n // let parts = param.split(\"=\");\n // c[parts[0]] = param.replace(parts[0] + \"=\", \"\").replace(/\"/g, \"\");\n // }\n // });\n // codes.push(c);\n // });\n // return {\n // str: str,\n // codes: codes,\n // };\n // } else {\n // return;\n // }\n // }\n\n getMarkdownFromLocalInfoBox = (feature, layer, markdown) => {\n // Same goes for infobox, I'm shortening the code significantly using the optional chaining.\n // Features coming from search result have infobox set on Feature instead of Layer due to\n // different features sharing same vector layer.\n return (\n feature?.infobox ||\n feature.layer?.layersInfo?.[layer]?.infobox ||\n markdown\n );\n };\n\n getAGSCompatibleLayer = (feature) => {\n return Object.keys(feature.layer.layersInfo).find((id) => {\n const fid = feature.getId().split(\".\")[0];\n const layerId = id.split(\":\").length === 2 ? id.split(\":\")[1] : id;\n return fid === layerId;\n });\n };\n\n getFeatureProperties = (feature) => {\n let properties = feature.getProperties();\n properties = this.featurePropsParsing.extractPropertiesFromJson(properties);\n feature.setProperties(properties);\n return properties;\n };\n\n async updateFeatureInformation(newIndex) {\n let feature = this.props.features[newIndex];\n const layerInfo = feature.layer.get(\"layerInfo\");\n\n let markdown = layerInfo?.information,\n caption = layerInfo?.caption,\n layer,\n shortcodes = [];\n\n //Problem with geojson returned from AGS - Missing id on feature - how to handle?\n if (feature.layer.layersInfo && feature.getId()) {\n layer = this.getAGSCompatibleLayer(feature);\n }\n\n // Deal with layer groups that have a caption on sublayer. Layer groups will\n // have a 'layersInfo' (NB pluralis on layerSInfo), and if it exists,\n // let's overwrite the previously saved caption.\n // Below I'm using the new optional chaining operator (\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining),\n // which will return the new caption, if exists, or a falsy value. If falsy value is returned,\n // just fall back to the previous value of caption.\n caption = feature.layer?.layersInfo?.[layer]?.caption || caption;\n markdown = this.getMarkdownFromLocalInfoBox(feature, layer, markdown);\n\n // Disabled shortcodes for now as they mess with Markdown tags\n // for Links and Imgs that use \"[\" and \"]\".\n // if (markdown) {\n // let transformed = this.shortcode(markdown);\n // if (transformed) {\n // shortcodes = transformed.codes;\n // markdown = transformed.str;\n // }\n // }\n\n this.setState({ loading: true });\n\n let properties = this.getFeatureProperties(feature);\n const value = await this.getValue(markdown, properties, caption);\n\n this.setState(\n {\n value: value,\n loading: false,\n caption: caption,\n shortcodes: shortcodes,\n selectedIndex: newIndex,\n markdown: markdown,\n },\n () => {\n this.showFeatureInMap();\n }\n );\n }\n\n getValue = async (markdown, properties, caption) => {\n if (markdown) {\n return await this.featurePropsParsing\n .setMarkdownAndProperties({ markdown, properties })\n .mergeFeaturePropsWithMarkdown();\n } else {\n return this.getFeaturesAsDefaultTable(properties, caption);\n }\n };\n\n // renderShortcodes(shortcodes, feature) {\n // return shortcodes.map((shortcode, i) => {\n // switch (shortcode.shortcode) {\n // case \"diagram\":\n // return (\n // <Diagram key={i} source={shortcode.source} feature={feature} />\n // );\n // case \"table\":\n // return (\n // <HajkTable key={i} source={shortcode.source} feature={feature} />\n // );\n // default:\n // return null;\n // }\n // });\n // }\n\n isReadyToShowInfo = () => {\n const { caption, value, loading, shortcodes } = this.state;\n return caption && !loading && value && shortcodes;\n };\n\n renderFeatureInformation = () => {\n // const { caption, value, shortcodes, markdown } = this.state;\n const { caption, value } = this.state;\n const { classes } = this.props;\n\n return (\n <Grid className={classes.featureInfo} item>\n <Typography variant=\"button\" align=\"center\" component=\"h6\" gutterBottom>\n {caption}\n </Typography>\n {value}\n </Grid>\n );\n };\n\n render() {\n const { classes, features } = this.props;\n const featureInfoLoaded = this.isReadyToShowInfo();\n return (\n <Grid\n alignContent=\"flex-start\"\n className={classes.infoContainer}\n container\n spacing={1}\n >\n {features.length > 1 && (\n <Grid xs={12} item>\n {this.getToggler()}\n </Grid>\n )}\n <Grid\n justify=\"center\"\n alignContent={featureInfoLoaded ? \"flex-start\" : \"center\"}\n className={classes.featureInfoContainer}\n item\n container\n >\n {featureInfoLoaded ? (\n this.renderFeatureInformation()\n ) : (\n <CircularProgress />\n )}\n </Grid>\n </Grid>\n );\n }\n}\n\nexport default withStyles(styles)(FeatureInfoContainer);\n","import React from \"react\";\nimport {\n Button,\n Checkbox,\n Dialog,\n DialogContent,\n DialogContentText,\n FormControlLabel,\n Grid,\n Link,\n Slide,\n} from \"@material-ui/core\";\nimport { makeStyles } from \"@material-ui/styles\";\nimport { setLevel, shouldShowNotice } from \"models/Cookie\";\n\n// Default settings for the cookie-notice text and url if none is supplied from the configuration.\nconst DEFAULT_MESSAGE =\n \"Vi använder nödvändiga kakor (cookies) för att webbplatsen ska fungera på ett bra sätt för dig. Vi använder också funktionella kakor för att ge dig bästa möjliga funktion om du godkänner användningen av dessa.\";\nconst DEFAULT_URL =\n \"https://pts.se/sv/bransch/regler/lagar/lag-om-elektronisk-kommunikation/kakor-cookies/\";\n\n// We're using several labeled checkboxes, let's create a component so that we keep DRY.\nconst LabeledCheckbox = ({ checked, disabled, label, onChange }) => {\n return (\n <FormControlLabel\n control={\n <Checkbox\n color=\"primary\"\n disabled={disabled ?? false}\n checked={checked}\n onChange={onChange}\n />\n }\n label={label}\n />\n );\n};\n\nconst useStyles = makeStyles((theme) => ({\n dialogContainer: {\n \"& .MuiDialog-container\": {\n alignItems: \"flex-end\",\n },\n },\n dialogText: {\n color: theme.palette.text.primary,\n },\n}));\n\nconst Transition = React.forwardRef(function Transition(props, ref) {\n return <Slide direction=\"up\" ref={ref} {...props} />;\n});\n\nfunction CookieNotice({ globalObserver, appModel }) {\n const classes = useStyles();\n const { config } = appModel;\n\n // We should initialize the dialog:s open-state to whatever the manager states.\n const [open, setOpen] = React.useState(shouldShowNotice());\n const [functionalChecked, setFunctionalChecked] = React.useState(false);\n const [thirdPartChecked, setThirdPartChecked] = React.useState(false);\n\n const defaultCookieNoticeMessage =\n config?.mapConfig?.map?.defaultCookieNoticeMessage || DEFAULT_MESSAGE;\n const defaultCookieNoticeUrl =\n config?.mapConfig?.map?.defaultCookieNoticeUrl || DEFAULT_URL;\n const showThirdPartCheckbox =\n config?.mapConfig?.map?.cookieUse3dPart ?? false;\n\n // We're subscribing to the globalObserver-events in an useEffect so that we can\n // make sure to clean up subscriptions on unMount. (The return-statement of useEffect).\n React.useEffect(() => {\n // An event that allows other components to show the cookie-notice so that\n // the user can re-think their decision...\n globalObserver.subscribe(\"core.showCookieBanner\", () => {\n setOpen(true);\n });\n return () => {\n globalObserver.unsubscribe(\"core.showCookieBanner\");\n };\n }, [globalObserver]);\n\n // Handler for when the user clicks \"Allow selected\", i.e. we should\n // check which boxes are ticked, and set the cookie-level accordingly.\n const handleAllowSelectedClick = React.useCallback(() => {\n // Required cookies are selected \"automatically\", so if they clicked\n // \"Allow selected\" they have at least accepted that (cookie-level 1).\n let cookieLevel = 1;\n // If the checkbox for functional-cookies is checked we bump the cookie-level.\n if (functionalChecked) {\n cookieLevel = cookieLevel | 2;\n }\n // If the checkbox for third-part-cookies is checked we bump the cookie-level.\n if (thirdPartChecked) {\n cookieLevel = cookieLevel | 4;\n }\n // Then we'll set the cookie-level in the manager.\n setLevel(cookieLevel);\n // Make sure to close the dialog when the user has made the choice.\n setOpen(false);\n }, [functionalChecked, thirdPartChecked]);\n\n // Handler for when the user clicks \"Allow all\", i.e. we should\n // ignore which boxes are ticked, and set the cookie-level to allow all.\n const handleAllowAllClick = React.useCallback(() => {\n // IF the user accepts all they are at least accepting required- and\n // functional-cookies. (Cookie-level 3).\n let cookieLevel = 3;\n // If we are showing the option for third-part-cookies, they are obviously\n // accepting that as well.\n if (showThirdPartCheckbox) {\n cookieLevel = cookieLevel | 4;\n }\n // Then we'll set the cookie-level in the manager.\n setLevel(cookieLevel);\n // Make sure to close the dialog when the user has made the choice.\n setOpen(false);\n }, [showThirdPartCheckbox]);\n\n return (\n <Dialog\n fullWidth={true}\n maxWidth={\"md\"}\n className={classes.dialogContainer}\n open={open}\n TransitionComponent={Transition}\n keepMounted\n aria-describedby=\"cookie-dialog-content-text\"\n >\n <DialogContent>\n <DialogContentText\n className={classes.dialogText}\n id=\"cookie-dialog-content-text\"\n >\n {`${defaultCookieNoticeMessage} `}\n <Link\n href={defaultCookieNoticeUrl}\n underline=\"always\"\n rel=\"noreferrer\"\n target=\"_blank\"\n >\n {\"Mer information om kakor\"}\n </Link>\n </DialogContentText>\n <Grid container direction=\"row\" alignItems=\"center\" justify=\"flex-end\">\n <Grid item>\n <LabeledCheckbox\n disabled={true}\n checked={true}\n label={\"Nödvändiga\"}\n />\n <LabeledCheckbox\n onChange={(event) => {\n setFunctionalChecked(event.target.checked);\n }}\n checked={functionalChecked}\n label={\"Funktionella\"}\n />\n {showThirdPartCheckbox && (\n <LabeledCheckbox\n onChange={(event) => {\n setThirdPartChecked(event.target.checked);\n }}\n checked={thirdPartChecked}\n label={\"Tredjepart\"}\n />\n )}\n </Grid>\n <Grid item>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={handleAllowSelectedClick}\n >\n {\"Tillåt valda\"}\n </Button>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={handleAllowAllClick}\n style={{ marginLeft: 8 }}\n >\n {\"Tillåt Alla\"}\n </Button>\n </Grid>\n </Grid>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport default CookieNotice;\n","import React from \"react\";\nimport { Steps } from \"intro.js-react\";\nimport PropTypes from \"prop-types\";\n\nimport \"intro.js/introjs.css\";\nimport \"intro.js/themes/introjs-modern.css\";\n\nimport { functionalOk as functionalCookieOk } from \"models/Cookie\";\n\n/**\n * @summary Renders a guide that introduces new users to features present in Hajk.\n * @description The introduction will only be rendered once. This is achieved by setting\n * a flag in the browser's local storage.\n *\n * @returns React.Component\n */\nclass Introduction extends React.PureComponent {\n state = {\n forceShow: false, // Used to force showing the Intro, overrides the LocalStorage value\n initialStep: 0,\n stepsEnabled: true,\n steps: [],\n };\n\n static propTypes = {\n experimentalIntroductionEnabled: PropTypes.bool.isRequired,\n experimentalIntroductionSteps: PropTypes.array,\n globalObserver: PropTypes.object.isRequired,\n };\n\n static defaultProps = {\n experimentalIntroductionEnabled: false,\n experimentalIntroductionSteps: [],\n globalObserver: {},\n };\n\n predefinedSteps = [\n {\n title: \"Välkommen till Hajk! 👋\",\n intro:\n \"Här kommer en kort guide som visar dig runt i applikationen. <br /><br />Häng med!\",\n },\n {\n title: \"Verktygspanel\",\n element: \"header > div:first-child\",\n intro: \"Med hjälp av knappen här uppe tar du fram verktygspanelen.\",\n },\n {\n title: \"Sökruta\",\n element: '[class*=\"searchContainer\"]',\n intro:\n \"Sökrutan hittar du här.<br /><br /> Med hjälp av sökverktyget hittar du enkelt till rätt ställe i kartan.\",\n },\n {\n title: \"Fler sökverktyg\",\n element: '[name=\"searchOptions\"]',\n intro: \"Under den här knappen hittar du fler avancerade sökalternativ.\",\n },\n {\n title: \"Kartkontroller\",\n element: \"#controls-column\",\n intro:\n \"Längst ut i den högra delen av skärmen finns olika kontroller som du använder för att navigera i kartan.\",\n },\n {\n title: \"Fönster\",\n element: '#windows-container > div[style*=\"display: block\"]', // My favorite selector. Selects the first visible Window, so if there's a plugin Window open, we can add intro text to it.\n intro:\n \"Varje verktyg ritar ut ett eget fönster. Du kan flytta på fönstret och ändra dess storlek genom att dra i fönstrets sidor.\",\n },\n {\n title: \"Widget-knapp\",\n element: \"#left-column > div > button\",\n intro:\n \"Det här är en Widget-knapp. Genom att klicka på den öppnar du det verktyget som knappen är kopplad till. <br><br>Det var det hela. Hoppas du kommer tycka om att använda Hajk!\",\n },\n ];\n\n constructor(props) {\n super(props);\n\n /**\n * When appLoaded is fired, let's filter through the provided 'steps'.\n * We must remove any steps that don't have corresponding DOM elements.\n * Otherwise, we would show intro steps even for non-existing elements,\n * which wouldn't be nice.\n */\n this.props.globalObserver.subscribe(\"core.appLoaded\", () => {\n // Allow a short wait so that everything renders first\n setTimeout(() => {\n // First check if we have any steps in our config\n const { experimentalIntroductionSteps } = this.props;\n // We must have at least 2 elements in the array in order to properly show intro guide\n const steps =\n experimentalIntroductionSteps.length >= 2\n ? experimentalIntroductionSteps\n : this.predefinedSteps;\n\n const filteredSteps = steps.filter((s) => {\n return (\n s.element === undefined ||\n document.querySelector(s?.element) !== null\n );\n });\n\n this.setState({ steps: filteredSteps });\n }, 100);\n });\n\n this.props.globalObserver.subscribe(\"core.showIntroduction\", () => {\n this.setState({\n initialStep: 0,\n stepsEnabled: true,\n forceShow: true,\n });\n });\n }\n\n disableSteps = () => {\n // Upon completion/closing, set a flag that won't show this guide again.\n // Remember that the user must allow for functional cookies for this to be possible.\n // If the user has chosen to allow only the required cookies, the introduction will\n // show on every page load.\n if (functionalCookieOk()) {\n window.localStorage.setItem(\"introductionShown\", 1);\n }\n };\n\n render() {\n const { experimentalIntroductionEnabled } = this.props;\n const { initialStep, steps, stepsEnabled } = this.state;\n\n return (\n // TODO: Remove check once the experimental flag is lifted. Remember to remove the unneeded prop from here and App.js too.\n experimentalIntroductionEnabled &&\n // Don't show unless we have 2 or more elements in array - too short guides are not meaningful!\n steps.length >= 2 &&\n // Show only once per browser, or override if forced by a user action.\n (parseInt(window.localStorage.getItem(\"introductionShown\")) !== 1 ||\n this.state.forceShow === true) && (\n <Steps\n enabled={stepsEnabled}\n steps={steps}\n initialStep={initialStep}\n onExit={this.disableSteps}\n options={{\n exitOnOverlayClick: false,\n nextLabel: \"Nästa\",\n prevLabel: \"Föregående\",\n doneLabel: \"Klart!\",\n }}\n />\n )\n );\n }\n}\n\nexport default Introduction;\n","import React, { useEffect } from \"react\";\nimport { detect } from \"detect-browser\";\n\nimport { useSnackbar } from \"notistack\";\n\nimport { IconButton } from \"@material-ui/core\";\nimport CloseIcon from \"@material-ui/icons/Close\";\n\n/**\n * You should have something like this in your appConfig.json in\n * order for this to work:\n * \n * \"announcements\": [\n {\n \"id\": 1, // Numeric. Must be a unique ID for this item in array of objects.\n \"text\": \"Message to show to the user. Keep it short.\", // String. Self-documenting. \n \"active\": true, // Boolean. Makes it possible to turn off messages completely without removing them.\n \"showOnlyOnce\": true, // Boolean. If true, a cookie will be saved on users browser and message will show only once.\n \"maps\": [\"jw\", \"map_1\"], // Array. Only specified maps will show message.\n \"timeout\": null, // null or Numeric. Snackbar will auto hide after specified amount of millisecond, or be persistent (if null).\n \"startTime\": \"2020-01-01\", // DateTime. Earliest timestamp for this to be visible. Must be a string parsable by Date.parse().\n \"stopTime\": \"2020-12-31\", // DateTime. Last timestamp when this will be visible.\n \"browsers\": [\"ie\"], // Array of browsers (see https://github.com/DamonOehlman/detect-browser for valid names)\n \"type\": \"info\" // String. See Notistack docs for allowed options, usually \"default\", \"info\", \"warning\", \"success\" and \"error\".\n }, {\n \"id\": 2, \n // ... and so on\n }, \n // ... and more objects here\n ]\n * \n */\n\nfunction Announcement({ announcements = [], currentMap }) {\n const { enqueueSnackbar, closeSnackbar } = useSnackbar();\n\n /**\n * Runs once. Filters the supplied announcements according to some conditions:\n * - should this be shown for current map?\n * - is it set to be activated?\n * - does it fit within the (optional) date/time limitations?\n * - is it set to only show up once, and if so, has it already been shown?\n *\n * All items that make it through all these tests are then sent to the\n * snackbar, which shows a nice message to the user.\n */\n useEffect(() => {\n // First, we define some helper filter functions.\n\n /**\n * Time filter. If an item has start/stop restrictions,\n * compare those to the current timestamp. Show only if the restrictions\n * are met.\n */\n const timeFilter = (a) => {\n const now = new Date().getTime();\n const startTime = Date.parse(a.startTime);\n const stopTime = Date.parse(a.stopTime);\n\n const validStartTime = !Number.isNaN(startTime);\n const validStopTime = !Number.isNaN(stopTime);\n\n if (validStartTime && validStopTime) {\n // If both start and stop are sat, now must be within\n return startTime < now && now < stopTime;\n } else if (validStartTime && !validStopTime) {\n // There's only a start time - show indefinitely if we're past it\n return startTime < now;\n } else if (!validStartTime && validStopTime) {\n // There's only a stop time, show if we haven't got there yet\n return now < stopTime;\n }\n\n // Finally, if none of the date strings parsed, it\n // means there are no time restrictions, let's show this.\n return true;\n };\n\n /**\n * See if ID of a given item exists in an array retrieved from local storage.\n * If the item is set to be shown only once, and it exists in the array already,\n * don't show it again. If it, on the other hand, is missing from the array,\n * show it _and_ add its ID to the array, so it won't show up again.\n */\n const localStorageFilter = (a) => {\n // If local storage flag is off, show this item.\n if (a.showOnlyOnce !== true) return true;\n\n // If we got this far, admin wants to use local storage.\n\n // First, see if we've already shown this item.\n const shownIds =\n window.localStorage.getItem(\"shownAnnouncementIds\") || \"\"; // Avoid null value - it can't be parsed to array easily\n const aShownIds = shownIds.split(\",\").filter(Boolean); // Create an array by splitting on commas; remove empty values by comparing to a Boolean\n if (aShownIds.includes(a.id.toString())) {\n // If ID is in array, item has already been shown\n return false;\n }\n\n // If we got this far, admin want's to show this item,\n // but only once - so let's return true, but also add\n // current id to the cookie array.\n aShownIds.push(a.id);\n const sShownIds = aShownIds.join();\n window.localStorage.setItem(\"shownAnnouncementIds\", sShownIds);\n return true;\n };\n\n /**\n * If \"maps\" property exists and current map exists in the \"maps\" array\n * or if \"maps\" is a string with value \"all\", show this notification.\n * Else, don't show it.\n */\n const mapFilter = (a) => {\n // If \"all\" is specified, no filtering is needed\n if (a?.maps === undefined || a.maps === \"all\") return true;\n\n // Else if an array is provided, check and see that current map exists in the array\n if (Array.isArray(a.maps)) return a.maps.includes(currentMap);\n\n // If anything else is provided, it is an invalid value. Just exit.\n return false;\n };\n\n /**\n * If \"browsers\" property exists and is an Array, return true only\n * if current browsers is included in the array.\n * If \"browsers\" is a string with value \"all\", or if it's undefined,\n * return true too.\n * For any other (invalid) value, return false.\n */\n const browserFilter = (a) => {\n const browsers = a?.browsers;\n if (browsers === undefined || browsers === \"all\") return true;\n if (Array.isArray(browsers)) return browsers.includes(detect().name);\n return false;\n };\n\n /**\n * Helper method: whatever is left in the announcements array after\n * all checks will be mapped to this render method.\n */\n const renderSnackbar = (f) => {\n if (!f?.text) return; // A text is required. If there's nothing to display, get out of here\n\n // Persistent snackbars will need an action that displays a close button.\n const action = (key) => {\n return (\n <IconButton\n size=\"small\"\n aria-label=\"close\"\n color=\"inherit\"\n onClick={() => closeSnackbar(key)}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n );\n };\n\n enqueueSnackbar(f?.text, {\n variant: f?.type || \"default\", // Allowed variants are \"default\", \"info\", \"warning\", \"success\" and \"error\"\n ...(Number.isFinite(f?.timeout) && { autoHideDuration: f?.timeout }), // If timeout is Numeric, auto hide\n ...(!Number.isFinite(f?.timeout) && { persist: true, action }), // If timeout isn't Numeric, snackbar is persistent\n });\n };\n\n // Now we're done defining helpers and can proceed with the actual filtration.\n // Let's oop through all announcements and do some checks to filter out those\n // that should be displayed.\n const filtered = announcements\n .filter((a) => mapFilter(a)) // Show only announcements for the current map\n .filter((a) => a.active === true) // Only active announcements\n .filter((a) => browserFilter(a)) // Show only for some browsers if admin said so\n .filter((a) => timeFilter(a)) // Respect possible date/time restrictions\n .filter((a) => localStorageFilter(a)); // Show only once if admin said so, by checking a local storage setting\n\n // Filtering is done, now let's invoke render for those\n // items that made it this far.\n filtered.forEach((f) => renderSnackbar(f));\n }, [announcements, currentMap, enqueueSnackbar, closeSnackbar]);\n\n // Finally, React's render _must_ return something…\n return null;\n}\n\n// Prevent unnecessary re-runs by explicitly comparing the relevant prop\nfunction arePropsEqual(prevProps, nextProps) {\n return prevProps.announcements.length === nextProps.announcements.length;\n}\n\nexport default React.memo(Announcement, arePropsEqual);\n","import React from \"react\";\nimport { array } from \"prop-types\";\n\nPluginWindows.propTypes = {\n plugins: array.isRequired,\n};\n\n/**\n * *\n * @export\n * @param {*} props\n * @returns React.Component\n */\nfunction PluginWindows({ plugins }) {\n return plugins.map((tool, i) => {\n return (\n <tool.component\n key={i}\n map={tool.map}\n app={tool.app}\n searchInterface={tool.searchInterface}\n options={tool.options}\n />\n );\n });\n}\n\n/**\n * The arePropsEqual() function is defined with two parameters:\n * prevProps and nextProps respectively.\n * The arePropsEqual() function returns true when the props are\n * compared to be equal, thereby preventing the component from\n * re-rendering, and returns false when the props are not equal.\n * @param {*} prevProps\n * @param {*} nextProps\n */\nfunction arePropsEqual(prevProps, nextProps) {\n return prevProps.plugins.length === nextProps.plugins.length;\n}\n\nexport default React.memo(PluginWindows, arePropsEqual);\n","import React from \"react\";\nimport cslx from \"clsx\";\nimport Grid from \"@material-ui/core/Grid\";\nimport ClearIcon from \"@material-ui/icons/Clear\";\nimport withWidth from \"@material-ui/core/withWidth\";\nimport Autocomplete from \"@material-ui/lab/Autocomplete\";\nimport SearchIcon from \"@material-ui/icons/Search\";\nimport RoomIcon from \"@material-ui/icons/Room\";\nimport CheckIcon from \"@material-ui/icons/Check\";\nimport DescriptionIcon from \"@material-ui/icons/Description\";\nimport ExpandLessIcon from \"@material-ui/icons/ExpandLess\";\nimport ExpandMoreIcon from \"@material-ui/icons/ExpandMore\";\nimport WarningIcon from \"@material-ui/icons/Warning\";\nimport SearchResultsContainer from \"./searchResults/SearchResultsContainer\";\nimport SearchTools from \"./SearchTools\";\nimport { withTheme, useTheme, withStyles } from \"@material-ui/core/styles\";\nimport { decodeCommas } from \"../../utils/StringCommaCoder\";\nimport {\n CircularProgress,\n IconButton,\n Paper,\n TextField,\n Typography,\n FormHelperText,\n useMediaQuery,\n Popper,\n Tooltip,\n} from \"@material-ui/core\";\n\nconst styles = (theme) => ({\n searchContainer: {\n width: 400,\n height: theme.spacing(6),\n },\n searchCollapsed: {\n left: -440,\n },\n\n autocompleteTypography: {\n maxWidth: \"100%\",\n },\n\n inputRoot: {\n height: theme.spacing(6),\n },\n originIconWrapper: {\n display: \"flex\",\n flexWrap: \"wrap\",\n paddingRight: theme.spacing(1),\n },\n});\n\n//Needed to make a CustomPopper with inline styling to be able to override width,\n//Popper.js didn't work as expected\nconst CustomPopper = (props) => {\n const theme = useTheme();\n const smallScreen = useMediaQuery(theme.breakpoints.down(\"xs\"));\n const style = smallScreen ? { width: \"100%\" } : { width: 400 };\n return (\n <Popper\n {...props}\n style={style}\n popperOptions={{\n modifiers: {\n computeStyle: { gpuAcceleration: false },\n preventOverflow: {\n enabled: smallScreen,\n boundariesElement: \"root\",\n },\n hide: { enabled: smallScreen },\n },\n }}\n placement=\"bottom-end\"\n />\n );\n};\n\nconst CustomPaper = (props) => {\n const theme = useTheme();\n const smallScreen = useMediaQuery(theme.breakpoints.down(\"xs\"));\n const style = smallScreen\n ? {\n margin: 0,\n borderTop: `${theme.spacing(0.2)}px solid ${theme.palette.divider}`,\n }\n : { margin: 0 };\n return <Paper {...props} style={style} />;\n};\n\nclass SearchBar extends React.PureComponent {\n state = {\n drawActive: false,\n panelCollapsed: false,\n moreOptionsId: undefined,\n moreOptionsOpen: false,\n selectSourcesOpen: false,\n };\n\n getOriginBasedIcon = (origin) => {\n const { classes } = this.props;\n let icon;\n switch (origin) {\n case \"WFS\":\n icon = <RoomIcon color=\"disabled\" />;\n break;\n case \"DOCUMENT\":\n icon = <DescriptionIcon color=\"disabled\" />;\n break;\n case \"USERSELECT\":\n icon = <CheckIcon color=\"disabled\" />;\n break;\n default:\n icon = <RoomIcon color=\"disabled\" />;\n }\n return <div className={classes.originIconWrapper}>{icon}</div>;\n };\n\n removeCommasAndSpaces = (string) => {\n return string.replace(/,/g, \"\").replace(/ /g, \"\");\n };\n\n //Can't use string.prototype.matchAll because of Edge (Polyfill not working atm)\n getMatches = (string, regex, index) => {\n var matches = [];\n var match = regex.exec(string);\n\n while (match != null && match[0] !== \"\") {\n matches.push(match);\n match = regex.exec(string);\n }\n return matches;\n };\n\n getAllStartingIndexForOccurencesInString = (toSearchFor, toSearchIn) => {\n let regexp = new RegExp(this.props.escapeRegExp(toSearchIn), \"gi\");\n let matches = this.getMatches(toSearchFor, regexp);\n let matchedIndexes = matches.map((match) => match.index);\n return matchedIndexes;\n };\n\n getHighlightedAutoCompleteEntryElement = (\n lastHighlightInformation,\n autocompleteEntry\n ) => {\n let { index, length } = lastHighlightInformation;\n return (\n <>\n <strong>{autocompleteEntry.slice(0, index + length)}</strong>\n {autocompleteEntry.slice(index + length)}\n </>\n );\n };\n\n //Highlights everything in autocomplete entry up until the last occurrence of a match in string.\n renderHighlightedAutocompleteEntry = (\n highlightInformation,\n autocompleteEntry\n ) => {\n const countOfHighlightInformation = highlightInformation.length;\n //We get lastHighlightInformation because we want to highlight everything up to last word that matches\n const lastHighlightInformation =\n highlightInformation[countOfHighlightInformation - 1];\n\n if (countOfHighlightInformation > 0) {\n return this.getHighlightedAutoCompleteEntryElement(\n lastHighlightInformation,\n autocompleteEntry\n );\n }\n };\n\n getHighlightedACE = (searchString, autocompleteEntry) => {\n const { getArrayWithSearchWords, classes } = this.props;\n const stringArraySS = getArrayWithSearchWords(searchString);\n\n let highlightInformation = stringArraySS\n .map((searchWord) => {\n return this.getAllStartingIndexForOccurencesInString(\n autocompleteEntry,\n searchWord\n ).map((index) => {\n return {\n index: index,\n length: searchWord.length,\n };\n });\n })\n .flat();\n\n return (\n <Typography noWrap={true} className={classes.autocompleteTypography}>\n {highlightInformation.length > 0\n ? this.renderHighlightedAutocompleteEntry(\n highlightInformation,\n autocompleteEntry\n )\n : autocompleteEntry}\n </Typography>\n );\n };\n\n /**\n * @summary Prepare a label to show as the placeholder in the Search bar\n * @returns {string} placeholder text\n */\n getPlaceholder = () => {\n const {\n options,\n searchActive,\n searchOptions: { searchInVisibleLayers },\n } = this.props;\n\n const labelPostfix = searchInVisibleLayers\n ? \" (endast i synliga lager)\"\n : \"\";\n\n return searchActive === \"selectSearch\" || searchActive === \"draw\"\n ? `Söker med objekt${labelPostfix}`\n : searchActive === \"extentSearch\"\n ? `Söker i området${labelPostfix}`\n : options.searchBarPlaceholder\n ? `${options.searchBarPlaceholder}${labelPostfix}`\n : `Sök${labelPostfix}`;\n };\n\n renderSearchResultList = () => {\n const {\n searchResults,\n app,\n map,\n localObserver,\n resultPanelCollapsed,\n toggleCollapseSearchResults,\n options,\n } = this.props;\n\n return (\n <SearchResultsContainer\n searchResults={searchResults}\n localObserver={localObserver}\n app={app}\n getOriginBasedIcon={this.getOriginBasedIcon}\n featureCollections={searchResults.featureCollections}\n map={map}\n panelCollapsed={resultPanelCollapsed}\n toggleCollapseSearchResults={toggleCollapseSearchResults}\n options={options}\n />\n );\n };\n\n renderAutoComplete = () => {\n const {\n autocompleteList,\n autoCompleteOpen,\n searchString,\n searchActive,\n classes,\n loading,\n handleOnAutocompleteInputChange,\n handleSearchInput,\n } = this.props;\n return (\n <Autocomplete\n id=\"searchInputField\"\n freeSolo\n size={\"small\"}\n classes={{\n inputRoot: classes.inputRoot,\n }}\n PopperComponent={CustomPopper}\n PaperComponent={CustomPaper}\n clearOnEscape\n disabled={\n searchActive === \"extentSearch\" ||\n searchActive === \"selectSearch\" ||\n searchActive === \"draw\"\n }\n autoComplete\n value={decodeCommas(searchString)}\n selectOnFocus\n blurOnSelect\n open={autoCompleteOpen}\n disableClearable\n onChange={handleSearchInput}\n onInputChange={handleOnAutocompleteInputChange}\n getOptionSelected={(option, value) =>\n option.autocompleteEntry === value.autocompleteEntry\n }\n renderOption={(option) => {\n if (searchString.length > 0) {\n return (\n <Grid container alignItems=\"center\">\n <Grid item xs={1}>\n {this.getOriginBasedIcon(option.origin)}\n </Grid>\n <Grid container item xs={11}>\n <Grid item xs={12}>\n {this.getHighlightedACE(\n searchString,\n decodeCommas(option.autocompleteEntry)\n )}\n </Grid>\n <Grid item xs={12}>\n <FormHelperText>{option.dataset}</FormHelperText>\n </Grid>\n </Grid>\n </Grid>\n );\n }\n }}\n getOptionLabel={(option) => {\n return option?.autocompleteEntry?.length > 0\n ? decodeCommas(option?.autocompleteEntry)\n : option;\n }}\n options={autocompleteList}\n loading={loading}\n renderInput={this.renderAutoCompleteInputField}\n />\n );\n };\n\n renderFailedWFSFetchWarning = (errorMessage) => {\n return (\n <Tooltip title={errorMessage}>\n <WarningIcon color=\"error\">\n <Typography variant=\"srOnly\">{errorMessage}</Typography>\n </WarningIcon>\n </Tooltip>\n );\n };\n\n renderAutoCompleteInputField = (params) => {\n const {\n searchString,\n loading,\n width,\n searchActive,\n map,\n app,\n handleOnClear,\n showSearchResults,\n toggleCollapseSearchResults,\n resultPanelCollapsed,\n handleSearchBarKeyPress,\n searchOptions,\n searchSources,\n updateSearchOptions,\n searchModel,\n handleOnClickOrKeyboardSearch,\n setSearchSources,\n failedWFSFetchMessage,\n } = this.props;\n const disableUnderline = width === \"xs\" ? { disableUnderline: true } : null;\n const showFailedWFSMessage =\n failedWFSFetchMessage.length > 0 && showSearchResults;\n const expandMessage = resultPanelCollapsed\n ? \"Visa sökresultat\"\n : \"Dölj sökresultat\";\n const placeholder = this.getPlaceholder();\n return (\n <TextField\n {...params}\n label={\n <Typography variant=\"srOnly\">Sök i webbplatsens innehåll</Typography>\n }\n variant={width === \"xs\" ? \"standard\" : \"outlined\"}\n placeholder={placeholder}\n onKeyPress={handleSearchBarKeyPress}\n InputLabelProps={{ shrink: true }}\n InputProps={{\n ...params.InputProps,\n ...disableUnderline,\n style: { margin: 0 },\n notched: width === \"xs\" ? null : false,\n endAdornment: (\n <>\n {loading ? <CircularProgress color=\"inherit\" size={20} /> : null}\n {params.InputProps.endAdornment}\n {showFailedWFSMessage &&\n this.renderFailedWFSFetchWarning(failedWFSFetchMessage)}\n {!showSearchResults ? (\n <Tooltip title=\"Utför sökning\">\n <IconButton\n size=\"small\"\n onClick={handleOnClickOrKeyboardSearch}\n >\n <Typography variant=\"srOnly\">Exekvera sökning</Typography>\n <SearchIcon />\n </IconButton>\n </Tooltip>\n ) : (\n <Tooltip title={expandMessage}>\n <IconButton\n onClick={(e) => {\n e.stopPropagation();\n toggleCollapseSearchResults();\n }}\n size=\"small\"\n >\n <Typography variant=\"srOnly\">{expandMessage}</Typography>\n {resultPanelCollapsed ? (\n <ExpandMoreIcon />\n ) : (\n <ExpandLessIcon />\n )}\n </IconButton>\n </Tooltip>\n )}\n {searchString.length > 0 ||\n showSearchResults ||\n searchActive !== \"\" ? (\n <Tooltip title=\"Rensa sökning\">\n <IconButton onClick={handleOnClear} size=\"small\">\n <Typography variant=\"srOnly\">Rensa sökning</Typography>\n <ClearIcon />\n </IconButton>\n </Tooltip>\n ) : (\n <SearchTools\n map={map}\n searchSources={searchSources}\n setSearchSources={setSearchSources}\n app={app}\n searchOptions={searchOptions}\n searchTools={this.props.searchTools}\n searchModel={searchModel}\n updateSearchOptions={updateSearchOptions}\n />\n )}\n </>\n ),\n }}\n />\n );\n };\n\n render() {\n const { classes, showSearchResults, width } = this.props;\n const { panelCollapsed } = this.state;\n\n return (\n <Grid\n className={cslx(classes.searchContainer, {\n [classes.searchCollapsed]: panelCollapsed,\n })}\n >\n <Grid item>\n <Paper elevation={width === \"xs\" ? 0 : 1}>\n {this.renderAutoComplete()}\n </Paper>\n </Grid>\n {showSearchResults && this.renderSearchResultList()}\n </Grid>\n );\n }\n}\n\nexport default withStyles(styles)(withTheme(withWidth()(SearchBar)));\n","import React from \"react\";\nimport Alert from \"@material-ui/lab/Alert\";\nimport SearchResultsList from \"./SearchResultsList\";\nimport Collapse from \"@material-ui/core/Collapse\";\nimport Breadcrumbs from \"@material-ui/core/Breadcrumbs\";\nimport Link from \"@material-ui/core/Link\";\nimport FilterListIcon from \"@material-ui/icons/FilterList\";\nimport SortIcon from \"@material-ui/icons/Sort\";\nimport MoreVertIcon from \"@material-ui/icons/MoreVert\";\nimport CloseIcon from \"@material-ui/icons/Close\";\nimport DeleteIcon from \"@material-ui/icons/Delete\";\nimport ClearIcon from \"@material-ui/icons/Clear\";\nimport {\n Paper,\n Button,\n Grid,\n TextField,\n Typography,\n Tooltip,\n Badge,\n Menu,\n MenuItem,\n Grow,\n IconButton,\n} from \"@material-ui/core\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport SearchResultsDownloadMenu from \"./SearchResultsDownloadMenu\";\n\nconst styles = (theme) => ({\n hidden: {\n display: \"none\",\n },\n searchResultListWrapper: {\n [theme.breakpoints.down(\"xs\")]: {\n maxHeight: \"78vh\",\n },\n [theme.breakpoints.up(\"sm\")]: {\n maxHeight: \"82vh\",\n },\n },\n root: {\n maxHeight: \"80vh\",\n overflow: \"auto\",\n minWidth: 200,\n [theme.breakpoints.up(\"sm\")]: {\n maxWidth: 520,\n },\n [theme.breakpoints.down(\"xs\")]: {\n minWidth: \"100%\",\n maxWidth: \"100%\",\n position: \"absolute\",\n left: 0,\n borderTop: `${theme.spacing(0.2)}px solid ${theme.palette.divider}`,\n },\n },\n filterInputFieldContainer: {\n padding: theme.spacing(1),\n borderBottom: `${theme.spacing(0.1)}px solid ${theme.palette.divider}`,\n },\n headerContainer: {\n paddingRight: theme.spacing(1),\n paddingLeft: theme.spacing(1),\n },\n tallHeaderContainer: {\n minHeight: 42,\n paddingRight: theme.spacing(1),\n paddingLeft: theme.spacing(1),\n borderBottom: `${theme.spacing(0.1)}px solid ${theme.palette.divider}`,\n },\n headerTypography: {\n maxWidth: \"100%\",\n fontSize: 18,\n },\n headerButtons: {\n minWidth: 30,\n },\n breadCrumbLinks: {\n border: \"none\",\n cursor: \"pointer\",\n },\n});\n\nclass SearchResultsContainer extends React.PureComponent {\n state = {\n activeFeature: null,\n activeFeatureCollection: null,\n filteredFeatureCollections: null,\n filteredFeatures: null,\n sumOfResults: this.props.searchResults.featureCollections\n .map((fc) => fc.value.features.length ?? 0)\n .reduce((a, b) => a + b, 0),\n filterInputFieldOpen: false,\n featureCollectionFilter: \"\", // String used to filter featureCollections\n featureFilter: \"\", // String used to filter features\n sortingMenuAnchorEl: null,\n featureCollectionSortingStrategy: \"AtoZ\", // AtoZ representing alphabetical order\n featureSortingStrategy: \"AtoZ\",\n showTools: false,\n selectedFeatures: [],\n };\n\n // Used for setTimeout/clearTimeout, in order to delay filter update when user is typing\n filterInputTimer = null;\n lastFeatureFilter = \"\";\n lastFeatureCollectionFilter = \"\";\n\n // Amount of time before filter changes is committed\n delayBeforeFilterCommit = 300;\n\n searchResultTools = [\n {\n name: \"Filtrera\",\n type: \"filter\",\n render: () => this.renderFilterTool(),\n enabled: this.props.options.enableResultsFiltering ?? true,\n },\n {\n name: \"Sortera\",\n type: \"sort\",\n render: () => this.renderSortTool(),\n enabled: this.props.options.enableResultsSorting ?? true,\n },\n {\n name: \"Rensa\",\n type: \"clear\",\n render: () => this.renderClearTool(),\n enabled: this.props.options.enableResultsSelectionClearing ?? true,\n },\n {\n name: \"Ladda ner\",\n type: \"download\",\n render: () => this.renderDownloadTool(),\n enabled: this.props.options.enableResultsDownloading ?? true,\n },\n ];\n\n sortingStrategies = [\n {\n type: \"AtoZ\",\n name: \"alfabetisk stigande\",\n appliesTo: [\"featureCollections\", \"features\"],\n },\n {\n type: \"ZtoA\",\n name: \"alfabetisk fallande\",\n appliesTo: [\"featureCollections\", \"features\"],\n },\n {\n type: \"numHits\",\n name: \"antal träffar\",\n appliesTo: [\"featureCollections\"],\n },\n ];\n\n componentDidMount = () => {\n const { app } = this.props;\n app.globalObserver.subscribe(\n \"infoClick.searchResultLayerClick\",\n (features) => {\n const featureIds = features.map((feature) => {\n return feature.getId();\n });\n this.showFeatureDetails(featureIds);\n }\n );\n this.getPotentialSingleHit();\n };\n\n componentWillUnmount = () => {\n const { app } = this.props;\n app.globalObserver.unsubscribe(\"infoClick.searchResultLayerClick\");\n };\n\n showFeatureDetails = (featureIds) => {\n const { toggleCollapseSearchResults } = this.props;\n const featureId = featureIds[0]; // Do we want to handle stacked features?\n\n // If searchResultContainer is collapsed, open it.\n if (this.props.panelCollapsed) toggleCollapseSearchResults();\n\n // Get the featureCollection which the clicked feature belongs to\n const featureCollection = this.getFeatureCollectionFromFeatureId(featureId);\n\n // If the collection has onClickName set we won't show the details\n if (featureCollection.source.onClickName) {\n return;\n }\n\n // Get the clicked feature\n const feature = featureCollection.value.features.find(\n (feature) => feature.getId() === featureId\n );\n\n // If the feature has onClickName set we won't show the details\n if (feature.onClickName) {\n return;\n }\n\n this.handleActiveFeatureChange(feature, featureCollection, \"infoClick\");\n };\n\n getFeatureCollectionFromFeatureId = (featureId) => {\n const { featureCollections } = this.props;\n return featureCollections.find((featureCollection) => {\n return (\n featureCollection.value.features.findIndex(\n (feature) => feature.getId() === featureId\n ) > -1\n );\n });\n };\n\n getPotentialSingleHit = () => {\n const { featureCollections } = this.props;\n\n const activeFeatureCollection =\n featureCollections.length === 1 ? featureCollections[0] : undefined;\n const activeFeature = activeFeatureCollection\n ? activeFeatureCollection.value.features.length === 1\n ? activeFeatureCollection.value.features[0]\n : undefined\n : undefined;\n\n // Hack hack.. we shouldn't set active collection and feature if we have a onClickName\n // on the source\n const shouldSetActiveFeatureOrCollection = activeFeatureCollection?.source\n ?.onClickName\n ? false\n : true;\n\n if (shouldSetActiveFeatureOrCollection) {\n this.setState({\n activeFeatureCollection: activeFeatureCollection,\n activeFeature: activeFeature,\n });\n }\n };\n\n handleFilterTextFieldInputChange = (e) => {\n const filterInput = e.target.value;\n this.updateViewFilters(filterInput);\n\n clearTimeout(this.filterInputTimer);\n this.filterInputTimer = setTimeout(() => {\n this.handleFilterUpdate();\n }, this.delayBeforeFilterCommit);\n };\n\n addFeatureToSelected = (feature) => {\n const selectedFeatures = [...this.state.selectedFeatures];\n selectedFeatures.push(feature);\n this.setState({ selectedFeatures: selectedFeatures });\n this.updateMapView(selectedFeatures);\n };\n\n removeFeatureFromSelected = (feature) => {\n const { activeFeatureCollection } = this.state;\n const selectedFeatures = [...this.state.selectedFeatures];\n\n const featureIndex = this.getSelectedFeatureIndex(feature.getId());\n selectedFeatures.splice(featureIndex, 1);\n\n if (activeFeatureCollection?.origin === \"USERSELECT\") {\n this.setState({\n selectedFeatures: selectedFeatures,\n activeFeatureCollection:\n selectedFeatures.length === 0\n ? null\n : this.getSelectedCollection(selectedFeatures),\n });\n } else {\n this.setState({ selectedFeatures: selectedFeatures });\n }\n this.updateMapView(selectedFeatures);\n };\n\n updateMapView = (selectedFeatures) => {\n const { localObserver } = this.props;\n localObserver.publish(\"map.setSelectedStyle\", selectedFeatures);\n localObserver.publish(\"map.zoomToFeatures\", selectedFeatures);\n };\n\n getSelectedFeatureIndex = (featureId) => {\n return this.state.selectedFeatures.findIndex((featureInfo) => {\n return featureInfo.feature.getId() === featureId;\n });\n };\n\n appendSelectedFeaturesCollection = (featureCollections) => {\n const { selectedFeatures } = this.state;\n if (this.state.selectedFeatures.length === 0) {\n return featureCollections;\n }\n const updatedCollections = [...featureCollections];\n updatedCollections.filter((fc) => {\n return fc.origin !== \"USERSELECT\";\n });\n updatedCollections.unshift(this.getSelectedCollection(selectedFeatures));\n return updatedCollections;\n };\n\n getSelectedCollection = (selectedFeatures) => {\n const features = selectedFeatures.reduce(\n (features, featureInfo) => [...features, featureInfo.feature],\n []\n );\n return {\n origin: \"USERSELECT\",\n source: { id: \"userSelected\", caption: \"Markerade objekt\" },\n value: {\n type: \"featureCollection\",\n features: features,\n },\n };\n };\n\n updateViewFilters = (filterInput) => {\n // If we don't have a collection active, we know\n // that the filter is intended for the collections\n if (!this.state.activeFeatureCollection) {\n this.setState({\n featureCollectionFilter: filterInput,\n });\n } else {\n // If we DO have a collection active, we know that\n // the filter is intended for the features in the active\n // collection\n this.setState({\n featureFilter: filterInput,\n });\n }\n };\n\n clearViewFilters = () => {\n if (!this.state.activeFeatureCollection) {\n this.setState(\n {\n featureCollectionFilter: \"\",\n },\n () => {\n this.handleFilterUpdate();\n }\n );\n } else {\n this.setState(\n {\n featureFilter: \"\",\n },\n () => {\n this.handleFilterUpdate();\n }\n );\n }\n };\n\n renderFilterInputField = () => {\n const { classes } = this.props;\n const { activeFeatureCollection, featureFilter, featureCollectionFilter } =\n this.state;\n const showClearFilterButton =\n featureFilter.length > 0 || featureCollectionFilter.length > 0;\n return (\n <Grid item className={classes.filterInputFieldContainer} xs={12}>\n <Typography variant=\"srOnly\">\n Textfält för att filtrera resultatet\n </Typography>\n <TextField\n autoFocus\n onChange={this.handleFilterTextFieldInputChange}\n value={\n activeFeatureCollection ? featureFilter : featureCollectionFilter\n }\n fullWidth\n size=\"small\"\n variant=\"outlined\"\n label=\"Filtrera sökresultaten\"\n InputProps={{\n endAdornment: showClearFilterButton && (\n <Tooltip title=\"Rensa filtret\">\n <IconButton onClick={this.clearViewFilters} size=\"small\">\n <Typography variant=\"srOnly\">Rensa filtret</Typography>\n <ClearIcon />\n </IconButton>\n </Tooltip>\n ),\n }}\n ></TextField>\n </Grid>\n );\n };\n\n getFilteredFeatureCollections = () => {\n const { featureCollectionFilter, filteredFeatureCollections } = this.state;\n const { featureCollections } = this.props;\n // Do we have a filter value?\n if (this.lastFeatureCollectionFilter !== featureCollectionFilter) {\n // Filter all collections\n return featureCollections.filter((featureCollection) => {\n // Returning collections where the filter is included in caption\n return featureCollection?.source?.caption\n .toLowerCase()\n .includes(featureCollectionFilter.toLowerCase());\n });\n } else {\n // No filter update? Return all collections or last filtered.\n if (filteredFeatureCollections?.length > 0) {\n return filteredFeatureCollections;\n }\n return featureCollections;\n }\n };\n\n // Helper function that checks if the filter is active in the\n // current view.\n isFilterActive = () => {\n const { activeFeatureCollection, featureFilter, featureCollectionFilter } =\n this.state;\n // If we have an active featureCollection (meaning that we are\n // viewing _features_, and the featureFilter-value is set, the\n // filter is active.\n return activeFeatureCollection && featureFilter.length > 0\n ? true\n : // If we do not have an active featureCollection (meaning that\n // we are viewing _featureCollections_, and the featureCollection-\n // filter is set, the filter is active.\n !activeFeatureCollection && featureCollectionFilter.length > 0\n ? true\n : // Otherwise, the filter is not active.\n false;\n };\n\n getSortingStrategiesApplyingToView = (view) => {\n return this.sortingStrategies.filter((strategy) =>\n strategy.appliesTo.includes(view)\n );\n };\n\n handleSortingMenuItemClick = (type) => {\n const { activeFeatureCollection } = this.state;\n\n if (activeFeatureCollection) {\n this.setState({\n featureSortingStrategy: type,\n sortingMenuAnchorEl: null,\n });\n } else {\n this.setState({\n featureCollectionSortingStrategy: type,\n sortingMenuAnchorEl: null,\n });\n }\n };\n\n clearAllSelectedFeaturesInView = () => {\n const { localObserver } = this.props;\n const { activeFeatureCollection } = this.state;\n const sourceId = activeFeatureCollection?.source?.id;\n const onSelectedFeaturesView = sourceId === \"userSelected\";\n\n const selectedFeatures =\n !sourceId || onSelectedFeaturesView\n ? []\n : [...this.state.selectedFeatures].filter((featureInfo) => {\n return featureInfo.feature?.source.id !== sourceId;\n });\n this.setState({\n selectedFeatures: selectedFeatures,\n activeFeatureCollection: onSelectedFeaturesView\n ? null\n : activeFeatureCollection,\n });\n localObserver.publish(\"map.setSelectedStyle\", selectedFeatures);\n };\n\n renderSortingMenu = () => {\n const {\n featureCollectionSortingStrategy,\n featureSortingStrategy,\n sortingMenuAnchorEl,\n activeFeatureCollection,\n } = this.state;\n\n const currentSortingStrategies = this.getSortingStrategiesApplyingToView(\n activeFeatureCollection ? \"features\" : \"featureCollections\"\n );\n return (\n <Menu\n anchorEl={sortingMenuAnchorEl}\n open={Boolean(sortingMenuAnchorEl)}\n onClose={() => this.setState({ sortingMenuAnchorEl: null })}\n >\n {currentSortingStrategies.map((strategy, index) => {\n return (\n <MenuItem\n selected={\n strategy.type ===\n (activeFeatureCollection\n ? featureSortingStrategy\n : featureCollectionSortingStrategy)\n }\n onClick={() => this.handleSortingMenuItemClick(strategy.type)}\n key={index}\n value={strategy.type}\n >\n {`${strategy.name[0].toUpperCase()}${strategy.name.slice(1)}`}\n </MenuItem>\n );\n })}\n </Menu>\n );\n };\n\n renderFilterTool = () => {\n const { classes } = this.props;\n const filterActive = this.isFilterActive();\n const filterHelpText = filterActive\n ? \"Filtret är aktivt\"\n : \"Filtrera resultatet\";\n return (\n <Tooltip title={filterHelpText}>\n <Button\n className={classes.headerButtons}\n onClick={() =>\n this.setState({\n filterInputFieldOpen: !this.state.filterInputFieldOpen,\n })\n }\n >\n <Badge\n color=\"primary\"\n badgeContent=\" \"\n variant=\"dot\"\n invisible={!filterActive}\n >\n <FilterListIcon />\n </Badge>\n </Button>\n </Tooltip>\n );\n };\n\n renderSortTool = () => {\n const { classes } = this.props;\n const {\n activeFeatureCollection,\n featureCollectionSortingStrategy,\n featureSortingStrategy,\n } = this.state;\n\n const sortHelpText = `Sortera resultatet, sorterar nu enligt ${\n // Get current sorting strategy from the array of strategies\n this.sortingStrategies.find(\n // by finding...\n (strategy) =>\n // the strategy with the \"type\"-value...\n strategy.type ===\n // corresponding to either the current feature or featureCollection\n // sorting strategy (depending on if we have an active collection or not)\n (activeFeatureCollection\n ? featureSortingStrategy\n : featureCollectionSortingStrategy)\n ).name // And it is the name value of the strategy we want to show\n }`;\n\n return (\n <Tooltip title={sortHelpText}>\n <Button\n className={classes.headerButtons}\n onClick={(e) =>\n this.setState({ sortingMenuAnchorEl: e.currentTarget })\n }\n >\n <SortIcon />\n </Button>\n </Tooltip>\n );\n };\n\n renderClearTool = () => {\n const { classes } = this.props;\n return (\n <Tooltip title=\"Rensa alla selekterade objekt\">\n <Button\n className={classes.headerButtons}\n onClick={this.clearAllSelectedFeaturesInView}\n >\n <DeleteIcon />\n </Button>\n </Tooltip>\n );\n };\n\n renderDownloadTool = () => {\n const collectionsToDownload = this.getCollectionsToDownload();\n return (\n <SearchResultsDownloadMenu\n featureCollections={collectionsToDownload}\n localObserver={this.props.localObserver}\n />\n );\n };\n\n getCollectionsToDownload = () => {\n const {\n activeFeatureCollection,\n filteredFeatureCollections,\n featureFilter,\n } = this.state;\n const { featureCollections } = this.props;\n\n if (activeFeatureCollection) {\n if (activeFeatureCollection.source.id === \"userSelected\") {\n return [activeFeatureCollection];\n }\n if (featureFilter === \"\") {\n return [activeFeatureCollection];\n }\n const filteredFeatures = this.getFilteredFeatures([\n activeFeatureCollection,\n ]);\n const collectionToDownload = {\n ...activeFeatureCollection,\n value: { features: filteredFeatures },\n };\n return [collectionToDownload];\n }\n if (filteredFeatureCollections) {\n return filteredFeatureCollections;\n }\n\n return featureCollections;\n };\n\n allToolsDisabled = () => {\n return this.searchResultTools.filter((tool) => tool.enabled).length === 0;\n };\n\n renderSearchResultListTools = () => {\n const { classes } = this.props;\n if (this.allToolsDisabled()) {\n return null;\n } else {\n return (\n <Grid item container align=\"center\" justify=\"flex-end\">\n <Grow in={this.state.showTools} timeout={800}>\n <Grid\n item\n className={!this.state.showTools ? classes.hidden : null}\n >\n {this.searchResultTools.map((tool, index) => {\n return (\n tool.enabled && (\n <React.Fragment key={index}>{tool.render()}</React.Fragment>\n )\n );\n })}\n </Grid>\n </Grow>\n <Grid item>\n <Tooltip\n title={`${this.state.showTools ? \"Dölj\" : \"Visa\"} verktyg`}\n >\n <Button\n className={classes.headerButtons}\n onClick={() =>\n this.setState({\n showTools: !this.state.showTools,\n filterInputFieldOpen: false,\n })\n }\n >\n {this.state.showTools ? <CloseIcon /> : <MoreVertIcon />}\n </Button>\n </Tooltip>\n </Grid>\n </Grid>\n );\n }\n };\n\n setActiveFeature = (feature) => {\n const { activeFeatureCollection } = this.state;\n this.handleActiveFeatureChange(feature, activeFeatureCollection);\n };\n\n handleActiveFeatureChange = (nextFeature, nextCollection, initiator) => {\n const { localObserver } = this.props;\n const { activeFeature } = this.state;\n const selectedFeatures = [...this.state.selectedFeatures];\n const shouldZoomToFeature = initiator !== \"infoClick\";\n\n if (activeFeature) {\n const featureIndex = selectedFeatures.findIndex((featureInfo) => {\n return (\n featureInfo.feature.getId() === activeFeature.getId() &&\n featureInfo.initiator !== \"userSelect\"\n );\n });\n featureIndex !== -1 && selectedFeatures.splice(featureIndex, 1);\n localObserver.publish(\"map.setSelectedStyle\", selectedFeatures);\n }\n\n if (nextFeature) {\n const nextFeatureSelected = this.featureIsSelected(nextFeature);\n !nextFeatureSelected &&\n selectedFeatures.push(\n this.getNextFeatureInfo(nextFeature, nextCollection, initiator)\n );\n }\n this.setState(\n {\n selectedFeatures: selectedFeatures,\n activeFeatureCollection: nextCollection,\n activeFeature: nextFeature,\n filterInputFieldOpen: false,\n featureFilter: !nextCollection ? \"\" : this.state.featureFilter,\n },\n () => {\n !nextCollection && this.handleFilterUpdate();\n }\n );\n if (nextFeature) {\n if (shouldZoomToFeature) {\n localObserver.publish(\"map.zoomToFeature\", nextFeature);\n }\n localObserver.publish(\"map.setHighLightedStyle\", nextFeature);\n } else {\n localObserver.publish(\"map.setSelectedStyle\", selectedFeatures);\n }\n };\n\n featureIsSelected = (feature) => {\n const { selectedFeatures } = this.state;\n return selectedFeatures.some((featureInfo) => {\n return featureInfo.feature.getId() === feature.getId();\n });\n };\n\n getNextFeatureInfo = (nextFeature, nextCollection, initiator) => {\n if (!nextFeature.source) {\n nextFeature.source = nextCollection.source;\n }\n\n return {\n feature: nextFeature,\n sourceId: nextFeature.source ?? nextCollection.source.id,\n initiator: initiator,\n };\n };\n\n setActiveFeatureCollection = (featureCollection) => {\n this.setState(\n {\n activeFeatureCollection: featureCollection,\n filterInputFieldOpen: false,\n featureFilter: \"\",\n },\n () => {\n this.handleFilterUpdate();\n this.#showCorrespondingWMSLayers(featureCollection);\n }\n );\n };\n\n #showCorrespondingWMSLayers = (featureCollection) => {\n // Respect the setting from admin\n if (this.props.options.showCorrespondingWMSLayers !== true) return;\n\n const layer = this.#getLayerById(featureCollection.source.pid);\n\n if (layer.layerType === \"group\") {\n // Group layers will publish an event to LayerSwitcher that will take\n // care of the somewhat complicated toggling.\n\n // N.B. We don't want to hide any sublayers, only ensure that new ones are shown.\n // So the first step is to find out which sublayers are already visible.\n const alreadyVisibleSubLayers = layer\n .getSource()\n .getParams()\n [\"LAYERS\"].split(\",\")\n .filter((e) => e.length !== 0);\n\n // Next, prepare an array of the already visible layers, plus the new one.\n // Make sure NOT TO CHANGE THE ORDER of sublayers. Hence no push or spread,\n // only a filter on the admin-specified order that we have in the 'subLayers'\n // property.\n const subLayersToShow = layer.subLayers.filter((l) => {\n return (\n alreadyVisibleSubLayers.includes(l) ||\n l === featureCollection.source.id\n );\n });\n\n // Finally, let's publish the event so that LayerSwitcher can take care of the rest\n this.props.app.globalObserver.publish(\"layerswitcher.showLayer\", {\n layer,\n subLayersToShow,\n });\n } else if (!layer.getVisible()) {\n // \"Normal\" layers are easier, we can just toggle the visibility directly.\n // The already existing OL listener will update checkbox state on corresponding layer.\n layer.setVisible(true);\n }\n };\n\n #getLayerById = (layerId) => {\n return this.props.map\n .getLayers()\n .getArray()\n .find((layer) => {\n return layerId === layer.values_.name;\n });\n };\n\n handleFeatureCollectionClick = (featureCollection) => {\n const { app } = this.props;\n const onClickName = featureCollection?.source?.onClickName;\n if (onClickName) {\n app.globalObserver.publish(\n `search.featureCollectionClicked.${onClickName}`,\n featureCollection\n );\n } else {\n this.setActiveFeatureCollection(featureCollection);\n }\n };\n\n sortFeatureCollections = (featureCollections) => {\n const { featureCollectionSortingStrategy } = this.state;\n\n const featureCollectionsAtoZSorted = featureCollections.sort((a, b) =>\n a.source.caption.localeCompare(b.source.caption)\n );\n\n switch (featureCollectionSortingStrategy) {\n case \"numHits\":\n return featureCollections.sort((a, b) =>\n a.value.totalFeatures > b.value.totalFeatures ? -1 : 1\n );\n case \"ZtoA\":\n return featureCollectionsAtoZSorted.reverse();\n default:\n // AtoZ\n return featureCollectionsAtoZSorted;\n }\n };\n\n keyPressIsEnter = (event) => {\n return event.which === 13 || event.keyCode === 13;\n };\n\n getFilteredFeatures = (featureCollections) => {\n const { activeFeatureCollection, featureFilter } = this.state;\n return featureCollections\n .map((fc) => {\n if (activeFeatureCollection) {\n if (fc.source.id === activeFeatureCollection.source.id) {\n return fc.value.features.filter((f) => {\n return f.featureTitle\n .toLowerCase()\n .includes(featureFilter.toLowerCase());\n });\n }\n }\n return fc.value.features;\n })\n .flat();\n };\n\n handleFilterUpdate = () => {\n const { featureCollectionFilter, featureFilter } = this.state;\n const { localObserver, featureCollections } = this.props;\n\n if (\n this.lastFeatureFilter === featureFilter &&\n this.lastFeatureCollectionFilter === featureCollectionFilter\n ) {\n return;\n }\n\n const filteredFeatureCollections =\n this.getFilteredFeatureCollections(featureCollections);\n const filteredFeatures = this.getFilteredFeatures(\n filteredFeatureCollections\n );\n const currentFeatureIds = filteredFeatures.map((feature) => {\n return feature.getId();\n });\n\n this.setState({\n filteredFeatureCollections: filteredFeatureCollections,\n filteredFeatures: filteredFeatures,\n });\n\n this.lastFeatureFilter = featureFilter;\n this.lastFeatureCollectionFilter = featureCollectionFilter;\n\n localObserver.publish(\"map.updateFeaturesAfterFilterChange\", {\n features: filteredFeatures,\n featureIds: currentFeatureIds,\n });\n };\n\n renderBreadCrumbs = (featureCollectionTitle, featureTitle) => {\n const { classes } = this.props;\n const { activeFeatureCollection, activeFeature } = this.state;\n const shouldRenderFeatureCollectionDetails =\n activeFeatureCollection && !activeFeatureCollection.source.onClickName;\n const shouldRenderFeatureDetails =\n activeFeature && !activeFeature.onClickName;\n if (shouldRenderFeatureCollectionDetails) {\n return (\n <Breadcrumbs aria-label=\"breadcrumb\" separator=\"/\">\n <Tooltip title=\"Tillbaka till alla sökresultat\">\n <Link\n className={classes.breadCrumbLinks}\n tabIndex={0}\n color=\"textPrimary\"\n variant=\"caption\"\n onClick={(e) => {\n e.stopPropagation();\n this.handleActiveFeatureChange();\n }}\n onKeyDown={(event) => {\n if (this.keyPressIsEnter(event)) {\n this.handleActiveFeatureChange();\n }\n }}\n onChange={this.handleActiveFeatureChange}\n >\n Sökresultat\n </Link>\n </Tooltip>\n <Tooltip title={featureCollectionTitle}>\n <Link\n className={classes.breadCrumbLinks}\n tabIndex={0}\n color=\"textPrimary\"\n variant=\"caption\"\n onClick={(e) => {\n e.stopPropagation();\n this.setActiveFeature(undefined);\n }}\n onKeyDown={(event) => {\n if (this.keyPressIsEnter(event)) {\n this.setActiveFeature(undefined);\n }\n }}\n >\n {featureCollectionTitle}\n </Link>\n </Tooltip>\n {shouldRenderFeatureDetails && (\n <Tooltip title={featureTitle}>\n <Link\n tabIndex={0}\n className={classes.breadCrumbLinks}\n color=\"textPrimary\"\n variant=\"caption\"\n >\n {featureTitle}\n </Link>\n </Tooltip>\n )}\n </Breadcrumbs>\n );\n } else {\n return null;\n }\n };\n\n renderHeaderInfoBar = (featureCollectionTitle) => {\n const { activeFeatureCollection } = this.state;\n const { classes } = this.props;\n return (\n <Grid\n container\n item\n justify=\"space-between\"\n alignItems=\"center\"\n wrap=\"nowrap\"\n xs={12}\n >\n <Grid\n container\n item\n wrap=\"nowrap\"\n alignItems=\"center\"\n xs={this.state.showTools ? 5 : 11}\n >\n <Tooltip\n title={\n activeFeatureCollection ? featureCollectionTitle : \"Sökresultat\"\n }\n >\n <Typography\n variant=\"button\"\n component=\"div\"\n noWrap\n className={classes.headerTypography}\n >\n {`${\n activeFeatureCollection ? featureCollectionTitle : \"Sökresultat\"\n }`}\n </Typography>\n </Tooltip>\n </Grid>\n <Grid\n container\n item\n justify=\"flex-end\"\n xs={this.state.showTools ? 7 : 1}\n >\n {this.renderSearchResultListTools()}\n </Grid>\n </Grid>\n );\n };\n\n renderSearchResultsHeader = () => {\n const { classes } = this.props;\n const { activeFeatureCollection, activeFeature } = this.state;\n\n const featureCollectionTitle = activeFeatureCollection\n ? activeFeatureCollection.source.caption\n : \"\";\n const featureTitle = activeFeature ? activeFeature.featureTitle : \"\";\n const shouldRenderHeaderInfoBar =\n !activeFeature || activeFeature?.onClickName;\n\n return (\n <Grid\n className={\n shouldRenderHeaderInfoBar\n ? classes.tallHeaderContainer\n : classes.headerContainer\n }\n container\n item\n xs={12}\n >\n <Grid item xs={12}>\n {this.renderBreadCrumbs(featureCollectionTitle, featureTitle)}\n </Grid>\n {shouldRenderHeaderInfoBar &&\n this.renderHeaderInfoBar(featureCollectionTitle, featureTitle)}\n </Grid>\n );\n };\n\n render() {\n const {\n classes,\n app,\n getOriginBasedIcon,\n localObserver,\n panelCollapsed,\n options,\n } = this.props;\n const {\n sumOfResults,\n activeFeatureCollection,\n activeFeature,\n filterInputFieldOpen,\n featureFilter,\n featureCollectionSortingStrategy,\n featureSortingStrategy,\n } = this.state;\n\n const featureCollections =\n // Do we have an active (selected) featureCollection?\n activeFeatureCollection\n ? // Return a array containing only that collection\n [activeFeatureCollection]\n : // Otherwise we return all collections passing the filter\n this.getFilteredFeatureCollections(this.props.featureCollections);\n\n const sortedFeatureCollections =\n this.sortFeatureCollections(featureCollections);\n\n const shouldRenderSelectedCollection =\n options.enableSelectedFeaturesCollection ?? true;\n\n const collectionsToRender = activeFeatureCollection\n ? [activeFeatureCollection]\n : shouldRenderSelectedCollection\n ? this.appendSelectedFeaturesCollection(sortedFeatureCollections)\n : sortedFeatureCollections;\n\n return (\n <Collapse in={!panelCollapsed}>\n {sumOfResults === 0 ? (\n <Paper className={classes.root}>\n <Alert severity=\"warning\">Sökningen gav inget resultat.</Alert>\n </Paper>\n ) : (\n <Paper className={classes.root}>\n <Grid container className={classes.searchResultListWrapper}>\n {this.renderSearchResultsHeader()}\n {filterInputFieldOpen && this.renderFilterInputField()}\n {this.renderSortingMenu()}\n <Grid item xs={12}>\n <SearchResultsList\n localObserver={localObserver}\n getOriginBasedIcon={getOriginBasedIcon}\n featureCollections={collectionsToRender}\n app={app}\n handleFeatureCollectionClick={\n this.handleFeatureCollectionClick\n }\n setActiveFeature={this.setActiveFeature}\n activeFeatureCollection={activeFeatureCollection}\n activeFeature={activeFeature}\n featureFilter={featureFilter}\n featureCollectionSortingStrategy={\n featureCollectionSortingStrategy\n }\n featureSortingStrategy={featureSortingStrategy}\n enableFeaturePreview={options.enableFeaturePreview ?? true}\n enableFeatureToggler={options.enableFeatureToggler ?? true}\n addFeatureToSelected={this.addFeatureToSelected}\n removeFeatureFromSelected={this.removeFeatureFromSelected}\n selectedFeatures={this.state.selectedFeatures}\n shouldRenderSelectedCollection={\n shouldRenderSelectedCollection\n }\n options={options}\n />\n </Grid>\n </Grid>\n </Paper>\n )}\n </Collapse>\n );\n }\n}\n\nexport default withStyles(styles)(SearchResultsContainer);\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { withWidth, List, ListItem } from \"@material-ui/core\";\nimport SearchResultsDataset from \"./SearchResultsDataset\";\nimport SearchResultsDatasetSummary from \"./SearchResultsDatasetSummary\";\n\nconst styles = () => ({\n searchResultList: {\n padding: 0,\n width: \"100%\",\n transition: \"none\",\n },\n searchResultListItem: {\n width: \"100%\",\n display: \"flex\",\n padding: 0,\n transition: \"none\",\n },\n});\n\nclass SearchResultsList extends React.PureComponent {\n componentDidMount = () => {\n const { activeFeature } = this.props;\n //If the search results in exactly one hit (meaning that activeFeature is set on first render),\n // we activate it right a way.\n if (activeFeature) {\n this.handleSingleSearchResult();\n }\n };\n\n handleSingleSearchResult = () => {\n const {\n app,\n activeFeature,\n activeFeatureCollection,\n localObserver,\n addFeatureToSelected,\n } = this.props;\n\n if (activeFeature.onClickName) {\n app.globalObserver.publish(\n `search.featureClicked.${activeFeature.onClickName}`,\n activeFeature\n );\n } else {\n const source = activeFeatureCollection?.source;\n\n activeFeature.source = source;\n addFeatureToSelected({\n feature: activeFeature,\n sourceId: source?.id,\n initiator: \"showDetails\",\n });\n if (this.props.width === \"xs\" || this.props.width === \"sm\") {\n localObserver.publish(\"minimizeSearchResultList\");\n }\n localObserver.publish(\"map.addAndHighlightFeatureInSearchResultLayer\", {\n feature: activeFeature,\n });\n }\n };\n\n handleOnFeatureClick = (feature) => {\n const { app, setActiveFeature } = this.props;\n if (feature.onClickName) {\n app.globalObserver.publish(\n `search.featureClicked.${feature.onClickName}`,\n feature\n );\n } else {\n setActiveFeature(feature);\n }\n };\n\n handleOnFeatureKeyPress = (event, feature) => {\n if (event.which === 13 || event.keyCode === 13) {\n this.handleOnFeatureClick(feature);\n }\n };\n\n renderSearchResultDatasetSummary = (featureCollection) => {\n const { getOriginBasedIcon } = this.props;\n return (\n <SearchResultsDatasetSummary\n featureCollection={featureCollection}\n getOriginBasedIcon={getOriginBasedIcon}\n maxResultsPerDataset={this.props.options.maxResultsPerDataset ?? 100}\n showResultsLimitReachedWarning={\n this.props.options.showResultsLimitReachedWarning ?? true\n }\n />\n );\n };\n\n renderSearchResultDataset = (featureCollection) => {\n const {\n getOriginBasedIcon,\n app,\n activeFeatureCollection,\n activeFeature,\n setActiveFeature,\n handleFeatureCollectionClick,\n featureFilter,\n featureSortingStrategy,\n enableFeaturePreview,\n localObserver,\n enableFeatureToggler,\n selectedFeatures,\n addFeatureToSelected,\n removeFeatureFromSelected,\n shouldRenderSelectedCollection,\n } = this.props;\n return (\n <SearchResultsDataset\n app={app}\n featureCollection={featureCollection}\n getOriginBasedIcon={getOriginBasedIcon}\n selectedFeatures={selectedFeatures}\n activeFeatureCollection={activeFeatureCollection}\n activeFeature={activeFeature}\n handleFeatureCollectionClick={handleFeatureCollectionClick}\n setActiveFeature={setActiveFeature}\n handleOnFeatureClick={this.handleOnFeatureClick}\n handleOnFeatureKeyPress={this.handleOnFeatureKeyPress}\n featureFilter={featureFilter}\n featureSortingStrategy={featureSortingStrategy}\n enableFeaturePreview={enableFeaturePreview}\n localObserver={localObserver}\n enableFeatureToggler={enableFeatureToggler}\n addFeatureToSelected={addFeatureToSelected}\n removeFeatureFromSelected={removeFeatureFromSelected}\n shouldRenderSelectedCollection={shouldRenderSelectedCollection}\n />\n );\n };\n\n renderSearchResultList = () => {\n const { featureCollections, classes, handleFeatureCollectionClick } =\n this.props;\n return (\n <List className={classes.searchResultList}>\n {featureCollections.map((featureCollection) => (\n <ListItem\n disableTouchRipple\n key={featureCollection.source.id}\n className={classes.searchResultListItem}\n id={`search-result-dataset-${featureCollection.source.id}`}\n aria-controls={`search-result-dataset-details-${featureCollection.source.id}`}\n onClick={() => handleFeatureCollectionClick(featureCollection)}\n button\n divider\n >\n {this.renderSearchResultDatasetSummary(featureCollection)}\n </ListItem>\n ))}\n </List>\n );\n };\n\n render() {\n const { activeFeatureCollection } = this.props;\n\n return activeFeatureCollection\n ? this.renderSearchResultDataset(activeFeatureCollection)\n : this.renderSearchResultList();\n }\n}\n\nexport default withStyles(styles)(withWidth()(SearchResultsList));\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { isMobile } from \"../../../utils/IsMobile\";\nimport { List, ListItem } from \"@material-ui/core\";\nimport SearchResultsDatasetFeature from \"./SearchResultsDatasetFeature\";\nimport SearchResultsDatasetFeatureDetails from \"./SearchResultsDatasetFeatureDetails\";\nimport SearchResultsPreview from \"./SearchResultsPreview\";\n\nconst styles = () => ({\n featureList: {\n padding: 0,\n width: \"100%\",\n transition: \"none\",\n },\n featureListItem: {\n width: \"100%\",\n display: \"flex\",\n padding: 0,\n transition: \"none\",\n },\n});\n\nclass SearchResultsDataset extends React.Component {\n //Some sources does not return numberMatched and numberReturned, falling back on features.length\n state = {\n previewFeature: null, // Feature to show in preview\n previewAnchorEl: null, // The element which the preview popper will anchor to\n };\n\n delayBeforeShowingPreview = 800; //Delay before showing preview popper in ms\n previewTimer = null; // Timer to keep track of when delay has passed\n\n shouldComponentUpdate = (prevProps) => {\n const { featureFilter, featureCollection } = this.props;\n const prevFeatureFilter = prevProps.featureFilter;\n const numFeatures = featureCollection.value.features.length;\n const prevNumFeatures = prevProps.featureCollection.value.features.length;\n if (\n featureFilter !== prevFeatureFilter ||\n numFeatures !== prevNumFeatures\n ) {\n clearTimeout(this.previewTimer);\n this.setState({ previewAnchorEl: undefined, previewFeature: undefined });\n return false;\n }\n return true;\n };\n\n componentWillUnmount = () => {\n clearTimeout(this.previewTimer);\n };\n\n setPreviewFeature = (e, feature) => {\n const target = e.currentTarget;\n clearTimeout(this.previewTimer);\n this.previewTimer = setTimeout(() => {\n this.setState({\n previewAnchorEl: target,\n previewFeature: feature,\n });\n }, this.delayBeforeShowingPreview);\n };\n\n resetPreview = () => {\n clearTimeout(this.previewTimer);\n if (this.state.previewFeature)\n this.setState({\n previewAnchorEl: undefined,\n previewFeature: undefined,\n });\n };\n\n getFilteredFeatures = () => {\n const { featureFilter } = this.props;\n const featureCollection = { ...this.props.featureCollection };\n // If user has a value in the filter input...\n if (featureFilter.length > 0) {\n // Filter all features in the collection\n const filteredFeatures = featureCollection.value.features.filter(\n (feature) => {\n // Returning the features having a title including\n // the filter string\n return feature.featureTitle\n .toLowerCase()\n .includes(featureFilter.toLowerCase());\n }\n );\n return filteredFeatures ?? [];\n }\n // Filter length is zero? Return all features\n return featureCollection.value.features ?? [];\n };\n\n getSortedFeatures = (features) => {\n const { featureSortingStrategy } = this.props;\n\n const featuresAtoZSorted = features.sort((a, b) =>\n a.featureTitle.localeCompare(b.featureTitle, undefined, {\n numeric: true, // Ensure that 1 < 2 < 10\n })\n );\n\n switch (featureSortingStrategy) {\n case \"ZtoA\":\n return featuresAtoZSorted.reverse();\n default:\n // AtoZ\n return featuresAtoZSorted;\n }\n };\n\n renderFeatureDetails = (features) => {\n const {\n featureCollection,\n app,\n activeFeatureCollection,\n activeFeature,\n localObserver,\n setActiveFeature,\n enableFeatureToggler,\n } = this.props;\n return (\n <SearchResultsDatasetFeatureDetails\n feature={activeFeature}\n features={features}\n setActiveFeature={setActiveFeature}\n featureCollection={featureCollection}\n app={app}\n source={activeFeatureCollection.source}\n localObserver={localObserver}\n enableFeatureToggler={enableFeatureToggler}\n />\n );\n };\n\n renderFeatureList = (features) => {\n const {\n featureCollection,\n classes,\n app,\n selectedFeatures,\n activeFeature,\n handleOnFeatureClick,\n handleOnFeatureKeyPress,\n getOriginBasedIcon,\n addFeatureToSelected,\n removeFeatureFromSelected,\n shouldRenderSelectedCollection,\n } = this.props;\n\n const sortedFeatures = this.getSortedFeatures(features);\n return (\n <>\n <List\n className={classes.featureList}\n id={`search-result-dataset-details-${featureCollection.source.id}`}\n >\n {sortedFeatures.map((f) => {\n return (\n <ListItem\n disableTouchRipple\n className={classes.featureListItem}\n key={f.getId()}\n divider\n button\n onClick={() => {\n this.resetPreview();\n handleOnFeatureClick(f);\n }}\n onKeyDown={(event) => handleOnFeatureKeyPress(event, f)}\n onMouseEnter={\n !isMobile ? (e) => this.setPreviewFeature(e, f) : null\n }\n onMouseLeave={!isMobile ? this.resetPreview : null}\n >\n <SearchResultsDatasetFeature\n feature={f}\n app={app}\n source={featureCollection.source}\n origin={featureCollection.origin}\n visibleInMap={\n selectedFeatures.findIndex(\n (item) => item.feature.getId() === f.getId()\n ) > -1\n }\n addFeatureToSelected={addFeatureToSelected}\n removeFeatureFromSelected={removeFeatureFromSelected}\n activeFeature={activeFeature}\n getOriginBasedIcon={getOriginBasedIcon}\n shouldRenderSelectedCollection={\n shouldRenderSelectedCollection\n }\n />\n </ListItem>\n );\n })}\n </List>\n {this.renderSearchResultPreview()}\n </>\n );\n };\n\n renderDatasetDetails = () => {\n const { activeFeature } = this.props;\n\n // If the user has selected a feature, we should show its details\n // if the feature does not have a onClickName. If it does, the details\n // will be taken care of somewhere else.\n const shouldRenderFeatureDetails =\n activeFeature && !activeFeature.onClickName;\n\n const features = this.getFilteredFeatures();\n\n return shouldRenderFeatureDetails\n ? this.renderFeatureDetails(features)\n : this.renderFeatureList(features);\n };\n\n renderSearchResultPreview = () => {\n const { previewFeature, previewAnchorEl } = this.state;\n const { activeFeatureCollection, enableFeaturePreview } = this.props;\n const shouldShowPreview =\n enableFeaturePreview && !isMobile && !previewFeature?.onClickName\n ? true\n : false;\n\n if (shouldShowPreview) {\n return (\n <SearchResultsPreview\n previewFeature={previewFeature}\n activeFeatureCollection={activeFeatureCollection}\n app={this.props.app}\n anchorEl={previewAnchorEl}\n />\n );\n } else {\n return null;\n }\n };\n\n render() {\n return this.renderDatasetDetails();\n }\n}\n\nexport default withStyles(styles)(SearchResultsDataset);\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { Checkbox, Typography, Tooltip, Grid } from \"@material-ui/core\";\nimport StarIcon from \"@material-ui/icons/Star\";\nimport StarBorderIcon from \"@material-ui/icons/StarBorder\";\n\nconst styles = (theme) => ({\n root: {\n minHeight: 42,\n width: \"100%\",\n },\n originIconWrapper: {\n paddingLeft: theme.spacing(1),\n },\n typography: {\n maxWidth: \"100%\",\n },\n});\n\nclass SearchResultsDatasetFeature extends React.PureComponent {\n renderShowInMapCheckbox = () => {\n const { visibleInMap } = this.props;\n const helpText = !visibleInMap ? \"Lägg till i urval\" : \"Ta bort från urval\";\n\n return (\n <Grid item align=\"center\">\n <Tooltip title={helpText}>\n <Checkbox\n color=\"default\"\n checked={visibleInMap}\n onClick={(e) => e.stopPropagation()}\n onChange={this.handleCheckboxToggle}\n icon={<StarBorderIcon />}\n checkedIcon={<StarIcon />}\n />\n </Tooltip>\n </Grid>\n );\n };\n\n handleCheckboxToggle = () => {\n const {\n feature,\n source,\n visibleInMap,\n addFeatureToSelected,\n removeFeatureFromSelected,\n } = this.props;\n if (visibleInMap) {\n removeFeatureFromSelected(feature);\n } else {\n feature.source = source;\n addFeatureToSelected({\n feature: feature,\n sourceId: source?.id,\n initiator: \"userSelect\",\n });\n }\n };\n\n renderOriginBasedIcon = () => {\n const { getOriginBasedIcon, origin, classes } = this.props;\n return (\n <Grid className={classes.originIconWrapper}>\n {getOriginBasedIcon(origin)}\n </Grid>\n );\n };\n\n render() {\n const { feature, classes, shouldRenderSelectedCollection } = this.props;\n const shouldRenderCheckbox =\n feature.getGeometry() && shouldRenderSelectedCollection;\n if (feature.featureTitle.length > 0) {\n return (\n <Grid container alignItems=\"center\" className={classes.root}>\n {shouldRenderCheckbox\n ? this.renderShowInMapCheckbox()\n : this.renderOriginBasedIcon()}\n <Grid item xs={9}>\n <Typography noWrap align=\"left\" className={classes.typography}>\n {feature.featureTitle}\n </Typography>\n </Grid>\n <Grid item xs={1}></Grid>\n </Grid>\n );\n } else {\n return null;\n }\n }\n}\nexport default withStyles(styles)(SearchResultsDatasetFeature);\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { Grid, Popover, Typography, fade } from \"@material-ui/core\";\nimport SearchResultsDatasetFeatureDetails from \"./SearchResultsDatasetFeatureDetails\";\n\nconst styles = (theme) => ({\n datasetContainer: {\n boxShadow: \"none\",\n overflow: \"hidden\",\n },\n divider: {\n backgroundColor: theme.palette.divider,\n width: \"100%\",\n },\n datasetDetailsContainer: {\n padding: 0,\n },\n hover: {\n cursor: \"pointer\",\n \"&:hover\": {\n backgroundColor: theme.palette.action.hover,\n },\n },\n preview: {\n pointerEvents: \"none\",\n },\n previewPaper: {\n width: 400,\n maxHeight: 200,\n overflow: \"hidden\",\n background: fade(theme.palette.background.paper, 0.8),\n },\n previewHeaderContainer: {\n paddingTop: theme.spacing(0.8),\n },\n previewContentContainer: {\n borderTop: `${theme.spacing(0.2)}px solid ${theme.palette.divider}`,\n },\n});\n\nclass SearchResultsPreview extends React.PureComponent {\n renderFeaturePreview = () => {\n const { classes, activeFeatureCollection, previewFeature, anchorEl, app } =\n this.props;\n\n return (\n <Popover\n id=\"mouse-over-popover\"\n open={anchorEl ? true : false}\n anchorEl={anchorEl}\n classes={{\n root: classes.preview,\n paper: classes.previewPaper,\n }}\n anchorOrigin={{\n vertical: \"center\",\n horizontal: \"left\",\n }}\n transformOrigin={{\n vertical: \"top\",\n horizontal: \"right\",\n }}\n disableRestoreFocus\n >\n <Grid container>\n <Grid\n item\n align=\"center\"\n className={classes.previewHeaderContainer}\n xs={12}\n >\n <Typography variant=\"button\">Förhandsvisning</Typography>\n </Grid>\n <Grid item className={classes.previewContentContainer} xs={12}>\n <SearchResultsDatasetFeatureDetails\n feature={previewFeature}\n app={app}\n source={activeFeatureCollection.source}\n />\n </Grid>\n </Grid>\n </Popover>\n );\n };\n\n render() {\n const { previewFeature } = this.props;\n return previewFeature ? this.renderFeaturePreview() : null;\n }\n}\n\nexport default withStyles(styles)(SearchResultsPreview);\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { Typography, Chip, Tooltip, Grid } from \"@material-ui/core\";\n\nconst styles = (theme) => ({\n summaryContainer: {\n minHeight: 42,\n paddingRight: theme.spacing(1),\n paddingLeft: theme.spacing(1),\n },\n typography: {\n maxWidth: \"100%\",\n },\n warningChip: {\n color: theme.palette.warning.contrastText,\n backgroundColor:\n theme.palette.type === \"dark\"\n ? theme.palette.warning.dark\n : theme.palette.warning.light,\n },\n});\n\nclass SearchResultsDatasetSummary extends React.PureComponent {\n //Some sources does not return numberMatched and numberReturned, falling back on features.length\n state = {\n numberOfResultsToDisplay:\n this.props.featureCollection.value.features.length,\n };\n\n shouldDisplayWarning = () => {\n const { numberOfResultsToDisplay } = this.state;\n const {\n maxResultsPerDataset,\n featureCollection,\n showResultsLimitReachedWarning,\n } = this.props;\n const { numberMatched, numberReturned } = featureCollection.value;\n\n if (!showResultsLimitReachedWarning) {\n return false;\n }\n\n if (numberReturned < numberMatched) {\n return true;\n }\n\n return maxResultsPerDataset <= numberOfResultsToDisplay;\n };\n\n renderDatasetSummary = () => {\n const { numberOfResultsToDisplay } = this.state;\n const { featureCollection, getOriginBasedIcon, classes } = this.props;\n\n const displayWarning = this.shouldDisplayWarning();\n const toolTipTitle = displayWarning\n ? `Maximalt antal sökträffar har uppnåtts. Förfina sökningen för att säkerställa att viktig information inte missas.`\n : `Visar ${numberOfResultsToDisplay} resultat`;\n\n return (\n <>\n <Grid\n alignItems=\"center\"\n container\n className={classes.summaryContainer}\n >\n <Grid item xs={1}>\n {getOriginBasedIcon(featureCollection.origin)}\n </Grid>\n <Grid item xs={9}>\n <Typography\n noWrap\n variant=\"button\"\n component=\"div\" // The noWrap does not work on variant=\"button\" without changing component\n className={classes.typography}\n >\n {featureCollection.source.caption}\n </Typography>\n </Grid>\n <Grid container item justify=\"flex-end\" xs={2}>\n <Tooltip title={toolTipTitle}>\n <Chip\n size=\"small\"\n color=\"default\"\n className={displayWarning ? classes.warningChip : null}\n label={`${numberOfResultsToDisplay}${\n displayWarning ? \"+\" : \"\"\n }`}\n />\n </Tooltip>\n </Grid>\n </Grid>\n </>\n );\n };\n\n render() {\n const { numberOfResultsToDisplay } = this.state;\n return parseInt(numberOfResultsToDisplay) > 0\n ? this.renderDatasetSummary()\n : null;\n }\n}\n\nexport default withStyles(styles)(SearchResultsDatasetSummary);\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { Button, Tooltip, Menu, MenuItem, Grid } from \"@material-ui/core\";\nimport GetAppIcon from \"@material-ui/icons/GetApp\";\nimport DescriptionIcon from \"@material-ui/icons/Description\";\nimport PublicIcon from \"@material-ui/icons/Public\";\n\nconst styles = (theme) => ({\n menuTogglerButton: {\n minWidth: 30,\n },\n menuItemIcon: {\n paddingRight: theme.spacing(1),\n },\n});\n\nclass SearchResultsDownloadMenu extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n anchorEl: null,\n };\n\n this.downloadOptions = [\n {\n name: \"Ladda ner till Excel\",\n icon: <DescriptionIcon />,\n type: \"Excel\",\n enabled: true,\n onClick: this.handleXLSXDownloadClick,\n },\n {\n name: \"Ladda ner till KML\",\n icon: <PublicIcon />,\n type: \"kml\",\n enabled: true,\n onClick: this.handleKMLDownloadClick,\n },\n ];\n }\n\n handleXLSXDownloadClick = () => {\n const { localObserver, featureCollections, featureId } = this.props;\n localObserver.publish(\"downloadMenu.exportXLSXClick\", {\n featureCollections: featureCollections,\n featureId: featureId,\n });\n this.setState({ anchorEl: null });\n };\n\n handleKMLDownloadClick = () => {\n const { localObserver, featureCollections } = this.props;\n localObserver.publish(\"downloadMenu.exportKMLClick\", featureCollections);\n this.setState({ anchorEl: null });\n };\n\n renderMenuTogglerButton = () => {\n const { classes } = this.props;\n return (\n <Tooltip title=\"Ladda ner objekten\">\n <Button\n className={classes.menuTogglerButton}\n onClick={(e) =>\n this.setState({\n anchorEl: e.currentTarget,\n })\n }\n >\n <GetAppIcon />\n </Button>\n </Tooltip>\n );\n };\n\n renderDownloadMenu = () => {\n const { classes } = this.props;\n const { anchorEl } = this.state;\n const enabledDownloadOptions = this.downloadOptions.filter((option) => {\n return option.enabled;\n });\n return (\n <Menu\n anchorEl={anchorEl}\n open={Boolean(anchorEl)}\n onClose={() => this.setState({ anchorEl: null })}\n >\n {enabledDownloadOptions.map((downloadOption, index) => {\n return (\n <MenuItem key={index} onClick={downloadOption.onClick}>\n <Grid container>\n <Grid item className={classes.menuItemIcon}>\n {downloadOption.icon}\n </Grid>\n <Grid item>{downloadOption.name}</Grid>\n </Grid>\n </MenuItem>\n );\n })}\n </Menu>\n );\n };\n\n render() {\n const { classes } = this.props;\n return (\n <>\n <Tooltip title=\"Ladda ner objekten\">\n <Button\n className={classes.menuTogglerButton}\n onClick={(e) =>\n this.setState({\n anchorEl: e.currentTarget,\n })\n }\n >\n <GetAppIcon />\n </Button>\n </Tooltip>\n {this.renderDownloadMenu()}\n </>\n );\n }\n}\n\nexport default withStyles(styles)(SearchResultsDownloadMenu);\n","import React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport IconButton from \"@material-ui/core/IconButton\";\nimport MoreVertIcon from \"@material-ui/icons/MoreVert\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport {\n ListItemIcon,\n Menu,\n MenuItem,\n Paper,\n Tooltip,\n Typography,\n} from \"@material-ui/core\";\n\nimport Dialog from \"../Dialog/Dialog\";\nimport SearchSettings from \"./SearchSettings\";\n\nconst styles = (theme) => ({});\n\nclass SearchTools extends React.PureComponent {\n state = {\n anchorEl: undefined,\n settingsDialog: false,\n };\n\n constructor(props) {\n super(props);\n this.map = props.map;\n }\n\n handleMenuItemClick = (event, index, option) => {\n const type = option.type;\n if (type === \"SETTINGS\") {\n this.setState({ settingsDialog: true });\n } else {\n this.props.app.globalObserver.publish(option[\"onClickEventName\"], option);\n }\n this.setState({ anchorEl: undefined });\n };\n\n getEnabledTools = () => {\n const { searchTools } = this.props;\n return searchTools.filter((tool) => tool.enabled ?? true);\n };\n\n renderSettingsDialog = () => {\n const { settingsDialog } = this.state;\n const {\n searchOptions,\n searchSources,\n updateSearchOptions,\n searchModel,\n setSearchSources,\n } = this.props;\n if (settingsDialog) {\n return createPortal(\n <Dialog\n options={{\n text: (\n <SearchSettings\n searchOptions={searchOptions}\n searchSources={searchSources}\n updateSearchOptions={updateSearchOptions}\n setSearchSources={setSearchSources}\n searchModel={searchModel}\n />\n ),\n headerText: \"Sökinställningar\",\n buttonText: \"OK\",\n useLegacyNonMarkdownRenderer: true,\n }}\n open={settingsDialog}\n onClose={() => {\n this.setState({\n settingsDialog: false,\n });\n }}\n ></Dialog>,\n document.getElementById(\"windows-container\")\n );\n } else {\n return null;\n }\n };\n\n render() {\n const { anchorEl } = this.state;\n const enabledTools = this.getEnabledTools();\n return (\n <>\n {this.renderSettingsDialog()}\n <Tooltip title=\"Fler sökverktyg och inställningar\">\n <IconButton\n aria-haspopup=\"true\"\n aria-controls=\"lock-menu\"\n name=\"searchOptions\"\n size=\"small\"\n onClick={(e) =>\n this.setState({\n anchorEl: e.currentTarget,\n })\n }\n >\n <Typography variant=\"srOnly\">\n Öppna dialog med fler inställningar\n </Typography>\n <MoreVertIcon />\n </IconButton>\n </Tooltip>\n <Paper>\n <Menu\n id=\"lock-menu\"\n autoFocus={false}\n anchorEl={anchorEl}\n getContentAnchorEl={null}\n anchorOrigin={{ vertical: \"bottom\", horizontal: \"right\" }}\n transformOrigin={{ vertical: \"top\", horizontal: \"center\" }}\n keepMounted\n open={Boolean(anchorEl)}\n onClose={() =>\n this.setState({\n anchorEl: undefined,\n })\n }\n >\n {enabledTools.map((option, index) => (\n <Tooltip key={index} title={option.toolTipTitle ?? \"\"}>\n <MenuItem\n onClick={(event) =>\n this.handleMenuItemClick(event, index, option)\n }\n >\n {option.icon ? (\n <ListItemIcon>{option.icon}</ListItemIcon>\n ) : null}\n <Typography variant=\"srOnly\" noWrap>\n {option.name}\n </Typography>\n <Typography variant=\"inherit\" noWrap>\n {option.name}\n </Typography>\n </MenuItem>\n </Tooltip>\n ))}\n </Menu>\n </Paper>\n </>\n );\n }\n}\n\nexport default withStyles(styles)(SearchTools);\n","import React from \"react\";\n\nimport { withStyles } from \"@material-ui/core/styles\";\nimport {\n Tooltip,\n Grid,\n Switch,\n FormGroup,\n FormLabel,\n FormControl,\n FormControlLabel,\n Select,\n Chip,\n MenuItem,\n Input,\n} from \"@material-ui/core\";\n\nconst styles = (theme) => ({\n chips: {\n display: \"flex\",\n flexWrap: \"wrap\",\n },\n chip: {\n margin: 2,\n },\n});\n\nclass SearchSettings extends React.PureComponent {\n state = {\n showSearchSourcesFilter: this.props.searchSources.length > 0 ? true : false,\n };\n\n localUpdateSearchOptions = (name, value) => {\n const { searchOptions } = this.props;\n // Send the new values up to the Search component's state\n this.props.updateSearchOptions({ ...searchOptions, [name]: value });\n };\n\n render() {\n const { classes, searchOptions, searchSources, searchModel } = this.props;\n return (\n <Grid container spacing={2} direction=\"column\">\n <Grid item xs>\n <FormControl component=\"fieldset\">\n <FormLabel component=\"legend\">Generella sökinställningar</FormLabel>\n <FormGroup>\n <Tooltip title=\"Slå på för att välja vilka datakällor som sökningen kommer göras i. Om reglaget är i off-läget kommer sökningen att ske i alla tillgänliga sökkällor.\">\n <FormControlLabel\n label=\"Begränsa sökkällor\"\n control={\n <Switch\n checked={this.state.showSearchSourcesFilter}\n onChange={(e) => {\n // Pull out the new value\n const showSearchSourcesFilter = e.target.checked;\n\n // Set state to reflect in Switch's UI\n this.setState({\n showSearchSourcesFilter,\n });\n\n // Now, if user has turned off this setting, ensure\n // that we also clean all search sources\n if (showSearchSourcesFilter === false)\n this.props.setSearchSources([]);\n }}\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n {this.state.showSearchSourcesFilter && (\n <Grid container spacing={2}>\n <Grid item xs>\n <Select\n fullWidth\n labelId=\"demo-mutiple-chip-label\"\n multiple\n value={searchSources}\n onChange={(event) =>\n this.props.setSearchSources(event.target.value)\n }\n input={<Input id=\"select-multiple-chip\" />}\n renderValue={(selected) => (\n <div className={classes.chips}>\n {selected.map((option) => (\n <Chip\n key={option.id}\n label={option.caption}\n className={classes.chip}\n />\n ))}\n </div>\n )}\n >\n {searchModel.getSources().map((source) => (\n <MenuItem\n key={source.id}\n value={source}\n // style={getStyles(name, personName, theme)}\n >\n {source.caption}\n </MenuItem>\n ))}\n </Select>\n </Grid>\n </Grid>\n )}\n </FormGroup>\n <FormGroup>\n <Tooltip title=\"Om aktivt kommer sökningen att ske i lager som är inställda för sökning av systemadministratören och som är synliga.\">\n <FormControlLabel\n label=\"Sök endast i synliga lager\"\n control={\n <Switch\n checked={searchOptions.searchInVisibleLayers}\n onChange={() => {\n this.localUpdateSearchOptions(\n \"searchInVisibleLayers\",\n !searchOptions.searchInVisibleLayers\n );\n }}\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n </FormGroup>\n </FormControl>\n </Grid>\n\n <Grid item xs>\n <FormControl component=\"fieldset\">\n <FormLabel component=\"legend\">\n Inställningar för textsökning\n </FormLabel>\n <FormGroup>\n <Tooltip title=\"Om aktivt kommer en sökning på 'väg' även ge träffar på exempelvis 'storväg'.\">\n <FormControlLabel\n label=\"Wildcard före\"\n control={\n <Switch\n checked={searchOptions.wildcardAtStart}\n onChange={() =>\n this.localUpdateSearchOptions(\n \"wildcardAtStart\",\n !searchOptions.wildcardAtStart\n )\n }\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n <Tooltip title=\"Om aktivt kommer en sökning på 'väg' även ge träffar på exempelvis 'vägen'.\">\n <FormControlLabel\n label=\"Wildcard efter\"\n control={\n <Switch\n checked={searchOptions.wildcardAtEnd}\n onChange={() =>\n this.localUpdateSearchOptions(\n \"wildcardAtEnd\",\n !searchOptions.wildcardAtEnd\n )\n }\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n <Tooltip title=\"Om aktivt kommer en sökning på 'a' inte ge träffar på 'A'. Inaktivera för att söka oberoende av gemener/versaler.\">\n <FormControlLabel\n label=\"Skiftlägeskänslighet\"\n control={\n <Switch\n checked={searchOptions.matchCase}\n onChange={() =>\n this.localUpdateSearchOptions(\n \"matchCase\",\n !searchOptions.matchCase\n )\n }\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n </FormGroup>\n </FormControl>\n </Grid>\n\n <Grid item xs>\n <FormControl component=\"fieldset\">\n <FormLabel component=\"legend\">Spatiala sökinställningar</FormLabel>\n <FormGroup>\n <Tooltip title=\"Om aktivt kommer hela objektet (exempelvis en fastigheten) behöva rymmas inom sökområdet för att komma med i resultatet. Om inaktivt räcker det att endast en liten del av objektet ryms inom, eller nuddar vid, sökområdet.\">\n <FormControlLabel\n label=\"Kräv att hela objektet ryms inom sökområde\"\n control={\n <Switch\n checked={searchOptions.activeSpatialFilter === \"within\"}\n onChange={() =>\n this.localUpdateSearchOptions(\n \"activeSpatialFilter\",\n searchOptions.activeSpatialFilter === \"intersects\"\n ? \"within\"\n : \"intersects\"\n )\n }\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n </FormGroup>\n </FormControl>\n </Grid>\n\n <Grid item xs>\n <FormControl component=\"fieldset\">\n <FormLabel component=\"legend\">Visning av resultat</FormLabel>\n <FormGroup>\n <Tooltip title=\"Om aktivt kommer en etikett att visas i kartan intill det markerade sökresultatet\">\n <FormControlLabel\n label=\"Visa textetikett i kartan\"\n control={\n <Switch\n checked={searchOptions.enableLabelOnHighlight}\n onChange={() =>\n this.localUpdateSearchOptions(\n \"enableLabelOnHighlight\",\n !searchOptions.enableLabelOnHighlight\n )\n }\n color=\"primary\"\n />\n }\n />\n </Tooltip>\n </FormGroup>\n </FormControl>\n </Grid>\n </Grid>\n );\n }\n}\n\nexport default withStyles(styles)(SearchSettings);\n","import Draw from \"ol/interaction/Draw\";\nimport { Stroke, Style, Circle, Fill } from \"ol/style\";\nimport { Vector as VectorLayer } from \"ol/layer\";\nimport VectorSource from \"ol/source/Vector\";\nimport { extend, createEmpty, isEmpty } from \"ol/extent\";\nimport Feature from \"ol/Feature\";\nimport FeatureStyle from \"./utils/FeatureStyle\";\nimport { fromExtent } from \"ol/geom/Polygon\";\nimport TileLayer from \"ol/layer/Tile\";\nimport ImageLayer from \"ol/layer/Image\";\nimport { handleClick } from \"../../models/Click\";\nimport { deepMerge } from \"utils/DeepMerge\";\nimport { isValidLayerId } from \"../../utils/Validator\";\n\nclass MapViewModel {\n constructor(settings) {\n this.map = settings.map;\n this.app = settings.app;\n this.options = settings.options;\n this.drawStyleSettings = this.getDrawStyleSettings();\n this.featureStyle = new FeatureStyle(settings.options);\n this.localObserver = settings.localObserver;\n this.initMapLayers();\n this.bindSubscriptions();\n }\n\n ctrlKeyPressed = false;\n\n // An object holding the last highlightInformation.\n // We use this to restore highlight after filter changes.\n lastFeaturesInfo = [];\n\n refreshFeatureStyle = (options) => {\n this.featureStyle = new FeatureStyle(deepMerge(this.options, options));\n // Make sure to set the new style on the results layer. This way\n // we'll get correct labels (if user wants to show them).\n this.resultsLayer.setStyle(this.featureStyle.getDefaultSearchResultStyle);\n };\n\n getDrawStyleSettings = () => {\n const strokeColor = this.options.drawStrokeColor ?? \"rgba(74,74,74,0.5)\";\n const fillColor = this.options.drawFillColor ?? \"rgba(255,255,255,0.07)\";\n\n return { strokeColor: strokeColor, fillColor: fillColor };\n };\n\n getNewVectorSource = () => {\n return new VectorSource({ wrapX: false });\n };\n\n getNewVectorLayer = (source, style) => {\n return new VectorLayer({\n source: source,\n style: style,\n });\n };\n\n getVisibleLayers = () => {\n return this.map\n .getLayers()\n .getArray()\n .filter((layer) => {\n return (\n (layer instanceof TileLayer || layer instanceof ImageLayer) &&\n layer.layersInfo !== undefined &&\n // We consider a layer to be visible only if…\n layer.getVisible() && // …it's visible…\n layer.getSource().getParams()[\"LAYERS\"] &&\n layer.getProperties().name &&\n isValidLayerId(layer.getProperties().name) // …has a specified name property…\n );\n })\n .map((layer) => layer.getSource().getParams()[\"LAYERS\"])\n .join(\",\")\n .split(\",\");\n };\n\n getVisibleSearchLayers = () => {\n const searchSources = this.options.sources;\n const visibleLayers = this.getVisibleLayers();\n const visibleSearchLayers = searchSources.filter((s) => {\n return visibleLayers.find((l_id) => l_id === s.id);\n });\n return visibleSearchLayers;\n };\n\n initMapLayers = () => {\n this.resultSource = this.getNewVectorSource();\n this.resultsLayer = this.getNewVectorLayer(\n this.resultSource,\n this.options.showResultFeaturesInMap ?? true\n ? this.featureStyle.getDefaultSearchResultStyle\n : null\n );\n // FIXME: Remove \"type\", use only \"name\" throughout\n // the application. Should be done as part of #883.\n this.resultsLayer.set(\"type\", \"searchResultLayer\");\n this.resultsLayer.set(\"name\", \"pluginSearchResults\");\n this.drawSource = this.getNewVectorSource();\n this.drawLayer = this.getNewVectorLayer(\n this.drawSource,\n this.getDrawStyle()\n );\n this.drawLayer.set(\"name\", \"pluginSearchDraw\");\n this.map.addLayer(this.drawLayer);\n this.map.addLayer(this.resultsLayer);\n };\n\n bindSubscriptions = () => {\n // Local subscriptions\n this.localObserver.subscribe(\"clearMapView\", this.clearMap);\n this.localObserver.subscribe(\"map.zoomToFeatures\", this.zoomToFeatures);\n this.localObserver.subscribe(\n \"map.addFeaturesToResultsLayer\",\n this.addFeaturesToResultsLayer\n );\n this.localObserver.subscribe(\"map.setSelectedStyle\", this.setSelectedStyle);\n this.localObserver.subscribe(\n \"map.addAndHighlightFeatureInSearchResultLayer\",\n this.addAndHighlightFeatureInSearchResultLayer\n );\n this.localObserver.subscribe(\n \"map.updateFeaturesAfterFilterChange\",\n this.updateFeaturesAfterFilterChange\n );\n this.localObserver.subscribe(\n \"map.setHighLightedStyle\",\n this.setHighLightedStyle\n );\n this.localObserver.subscribe(\"map.zoomToFeature\", this.zoomToFeature);\n // Global subscriptions\n this.app.globalObserver.subscribe(\n \"search.spatialSearchActivated\",\n (options) => {\n if (options.type === \"Extent\") {\n this.searchInCurrentExtent();\n } else if (options.type === \"Select\") {\n this.enableSelectFeaturesSearch();\n } else {\n this.toggleDraw(true, options.type);\n }\n\n // At this stage, the Search input field could be in focus. On\n // mobile devices the on-screen keyboard will show up. We don't\n // need it here (as these search options are purely click/touch-based)\n // so we ensure that it's hidden by blurring the focus.\n document.activeElement.blur();\n }\n );\n };\n\n updateFeaturesAfterFilterChange = (featureInfo) => {\n const { features, featureIds } = featureInfo;\n this.resultSource.forEachFeature((feature) => {\n if (featureIds.indexOf(feature.getId()) === -1) {\n this.resultSource.removeFeature(feature);\n }\n });\n features.forEach((feature) => {\n if (!this.resultSource.getFeatureById(feature.getId())) {\n this.resultSource.addFeature(feature);\n }\n });\n this.setSelectedStyle(this.lastFeaturesInfo);\n this.zoomToFeatures(this.lastFeaturesInfo);\n };\n\n fitMapToSearchResult = () => {\n const currentExtent = this.resultSource.getExtent();\n if (currentExtent.map(Number.isFinite).includes(false) === false) {\n this.fitMapToExtent(currentExtent);\n }\n };\n\n fitMapToExtent = (extent) => {\n this.map.getView().fit(extent, {\n size: this.map.getSize(),\n padding: [20, 20, 20, 20],\n maxZoom: 7,\n });\n };\n\n addFeaturesToResultsLayer = (features) => {\n this.resultSource.clear();\n this.resultSource.addFeatures(features);\n\n if (this.options.showResultFeaturesInMap) {\n this.fitMapToSearchResult();\n }\n };\n\n resetStyleForFeaturesInResultSource = () => {\n this.resultSource.getFeatures().map((f) => f.setStyle(null));\n };\n\n drawSourceHasFeatures = () => {\n return this.drawSource.getFeatures().length > 0;\n };\n\n getDrawStyle = () => {\n return new Style({\n stroke: new Stroke({\n color: this.drawStyleSettings.strokeColor,\n width: 4,\n }),\n fill: new Fill({\n color: this.drawStyleSettings.fillColor,\n }),\n image: new Circle({\n radius: 6,\n stroke: new Stroke({\n color: this.drawStyleSettings.strokeColor,\n width: 2,\n }),\n }),\n });\n };\n\n setHighLightedStyle = (feature) => {\n if (!feature) {\n return;\n }\n const mapFeature = this.getFeatureFromResultSourceById(feature.getId());\n return mapFeature?.setStyle(\n this.featureStyle.getFeatureStyle(mapFeature, \"highlight\")\n );\n };\n\n zoomToFeature = (feature) => {\n if (!feature) {\n return;\n }\n const extent = createEmpty();\n const mapFeature = this.getFeatureFromResultSourceById(feature.getId());\n extend(extent, mapFeature?.getGeometry().getExtent());\n const extentToZoomTo = isEmpty(extent)\n ? this.resultSource.getExtent()\n : extent;\n this.fitMapToExtent(extentToZoomTo);\n };\n\n setSelectedStyle = (featuresInfo) => {\n this.lastFeaturesInfo = featuresInfo;\n this.resetStyleForFeaturesInResultSource();\n featuresInfo.map((featureInfo) => {\n const feature = this.getFeatureFromResultSourceById(\n featureInfo.feature.getId()\n );\n return feature?.setStyle(\n this.featureStyle.getFeatureStyle(feature, \"selection\")\n );\n });\n };\n\n addAndHighlightFeatureInSearchResultLayer = (featureInfo) => {\n const feature = featureInfo.feature;\n feature.setStyle(this.featureStyle.getFeatureStyle(feature, \"highlight\"));\n this.resultSource.addFeature(feature);\n this.fitMapToSearchResult();\n };\n\n getFeatureFromResultSourceById = (fid) => {\n return this.resultSource.getFeatureById(fid);\n };\n\n zoomToFeatures = (featuresInfo) => {\n let extent = createEmpty();\n\n //BoundingExtent-function gave wrong coordinates for some\n featuresInfo.forEach((featureInfo) => {\n const feature = this.getFeatureFromResultSourceById(\n featureInfo.feature.getId()\n );\n if (feature) {\n extend(\n extent,\n this.getFeatureFromResultSourceById(featureInfo.feature.getId())\n .getGeometry()\n .getExtent()\n );\n }\n });\n const extentToZoomTo = isEmpty(extent)\n ? this.resultSource.getExtent()\n : extent;\n\n this.fitMapToExtent(extentToZoomTo);\n };\n\n clearMap = () => {\n if (this.drawSource) {\n this.drawSource.clear();\n }\n if (this.resultSource) {\n this.resultSource.clear();\n }\n this.removeDrawInteraction();\n this.removeSelectListeners();\n this.lastFeaturesInfo = [];\n };\n\n removeDrawInteraction = () => {\n if (this.draw) {\n this.map.removeInteraction(this.draw);\n }\n };\n\n toggleDraw = (active, type, freehand = false) => {\n this.localObserver.publish(\"on-draw-start\", type);\n if (active) {\n this.draw = new Draw({\n source: this.drawSource,\n type: type,\n freehand: type === \"Circle\" ? true : freehand,\n stopClick: true,\n style: this.getDrawStyle(),\n });\n\n this.map.clickLock.add(\"search\");\n this.map.addInteraction(this.draw);\n this.drawSource.clear();\n this.drawSource.on(\"addfeature\", this.handleDrawFeatureAdded);\n } else {\n this.map.removeInteraction(this.draw);\n this.map.clickLock.delete(\"search\");\n\n this.drawSource.clear();\n }\n };\n\n handleDrawFeatureAdded = (e) => {\n // OpenLayers seems to have a problem stopping the clicks if\n // the draw interaction is removed too early. This fix is not pretty,\n // but it gets the job done. It seems to be enough to remove the draw\n // interaction after one cpu-cycle.\n // If this is not added, the user will get a zoom-event when closing\n // a polygon drawing.\n setTimeout(() => {\n this.map.removeInteraction(this.draw);\n this.map.clickLock.delete(\"search\");\n }, 1);\n this.localObserver.publish(\"on-draw-end\", e.feature);\n };\n\n searchInCurrentExtent = () => {\n try {\n const currentExtent = this.map\n .getView()\n .calculateExtent(this.map.getSize());\n\n if (!this.extentIsFinite(currentExtent)) {\n throw new Error(\"Current extent could not be calculated correctly.\");\n }\n const feature = new Feature(fromExtent(currentExtent));\n this.drawSource.addFeature(feature);\n this.localObserver.publish(\"search-within-extent\", [feature]);\n } catch (error) {\n this.handleSearchInCurrentExtentError(error);\n }\n };\n\n extentIsFinite = (extent) => {\n return extent.map(Number.isFinite).includes(false) === false;\n };\n\n handleSearchInCurrentExtentError = (error) => {\n this.localObserver.publish(\"extent-search-failed\");\n console.warn(\"Extent-search-failed: \", error);\n };\n\n enableSelectFeaturesSearch = () => {\n this.drawSource.un(\"addfeature\", this.handleDrawFeatureAdded);\n this.ctrlKeyPressed = false;\n this.localObserver.publish(\"on-select-search-start\");\n this.addSelectListeners();\n };\n\n addSelectListeners = () => {\n this.map.clickLock.add(\"search\");\n this.map.on(\"singleclick\", this.handleSelectFeatureClick);\n document.addEventListener(\"keydown\", this.handleKeyDown);\n document.addEventListener(\"keyup\", this.handleKeyUp);\n };\n\n removeSelectListeners = () => {\n this.map.clickLock.delete(\"search\");\n this.map.un(\"singleclick\", this.handleSelectFeatureClick);\n document.removeEventListener(\"keydown\", this.handleKeyDown);\n document.removeEventListener(\"keyup\", this.handleKeyUp);\n };\n\n handleSelectFeatureClick = (event) => {\n handleClick(event, event.map, (response) => {\n const features = response.features;\n if (features.length === 0) {\n return;\n }\n this.drawSource.addFeatures(response.features);\n if (!this.ctrlKeyPressed) {\n const allFeatures = this.drawSource.getFeatures();\n this.localObserver.publish(\"on-search-selection-done\", allFeatures);\n this.removeSelectListeners();\n }\n });\n };\n\n handleKeyDown = (event) => {\n const { keyCode } = event;\n if (keyCode === 17 && !this.ctrlKeyPressed) {\n this.ctrlKeyPressed = true;\n }\n };\n\n handleKeyUp = (event) => {\n const { keyCode } = event;\n if (keyCode === 17) {\n this.ctrlKeyPressed = false;\n if (this.drawSourceHasFeatures()) {\n const features = this.drawSource.getFeatures();\n this.localObserver.publish(\"on-search-selection-done\", features);\n this.removeSelectListeners();\n }\n }\n };\n}\n\nexport default MapViewModel;\n","import FeatureStyle from \"./FeatureStyle\";\nimport { createXML } from \"../../../utils/KMLWriter\";\nimport { saveAs } from \"file-saver\";\n\nimport { Circle as CircleStyle, Icon } from \"ol/style.js\";\nimport { fromCircle } from \"ol/geom/Polygon.js\";\nimport { Circle } from \"ol/geom.js\";\n\nexport default class KmlExport {\n #featureStyle;\n\n constructor(settings) {\n this.#featureStyle = new FeatureStyle(settings.options);\n this.localObserver = settings.localObserver;\n this.map = settings.map;\n this.bindSubscriptions();\n }\n\n bindSubscriptions = () => {\n this.localObserver.subscribe(\"downloadMenu.exportKMLClick\", this.export);\n };\n\n // Exposed method that:\n // - Expects an object as follows:\n // - {featureCollections: [collections], feature: feature}\n // - If feature is undefined, it exports all features in all collections\n // - Otherwise, it exports the supplied feature. (The collection is needed\n // to create the labels.\n export = (featureCollections) => {\n const exportFeatures = this.#getStyledFeatures(featureCollections);\n this.#exportFeatures(exportFeatures);\n };\n\n #getStyledFeatures = (featureCollections) => {\n return featureCollections\n .map((featureCollection) => {\n return featureCollection.value.features.map((feature) => {\n // Loop all Feature Collections, and loop each Feature\n // within in order to extract a new, correctly styled\n // OL Feature that will be used by the KML writer.\n return this.#getStyledFeature(feature);\n });\n })\n .flat();\n };\n\n #getStyledFeature = (feature) => {\n // Don't modify existing features\n const gjFeature = feature.clone();\n\n // .clone() doesn't take care of our custom properties,\n // so we must add them manually.\n gjFeature.featureTitle = feature.featureTitle;\n gjFeature.shortFeatureTitle = feature.shortFeatureTitle;\n\n // Reset the current style before applying new one\n gjFeature.setStyle();\n gjFeature.setStyle(\n this.#featureStyle.getFeatureStyle(gjFeature, \"selection\")\n );\n return gjFeature;\n };\n\n #exportFeatures = (features) => {\n try {\n new Blob();\n } catch {\n console.info(\"KML export not supported on current platform.\");\n return;\n }\n\n const transformed = [];\n\n features.forEach((feature) => {\n let circleRadius = false;\n if (feature.getGeometry() instanceof Circle) {\n const geom = fromCircle(feature.getGeometry(), 96);\n feature.setGeometry(geom);\n circleRadius = feature.getGeometry().getRadius();\n }\n feature\n .getGeometry()\n .transform(this.map.getView().getProjection(), \"EPSG:4326\");\n\n if (feature.getStyle()[1]) {\n feature.setProperties({\n style: JSON.stringify(\n this.#extractStyle(\n feature.getStyle()[1] || feature.getStyle()[0],\n circleRadius\n )\n ),\n geometryType:\n feature.getGeometryName() === \"geometry\"\n ? feature.getProperties().geometryType\n : feature.getGeometryName(),\n });\n }\n\n transformed.push(feature);\n });\n\n if (features.length > 0) {\n const postData = createXML(transformed, \"Sökexport\");\n saveAs(\n new Blob([postData], {\n type: \"application/vnd.google-earth.kml+xml;charset=utf-8\",\n }),\n `Sökexport - ${new Date().toLocaleString()}.kml`\n );\n }\n };\n\n #extractStyle = (style, circleRadius) => {\n const styleObj = {};\n\n styleObj.text = style?.getText()?.getText() ?? \"\";\n styleObj.image =\n styleObj.getImage() instanceof Icon ? style.getImage().getSrc() : \"\";\n styleObj.pointRadius =\n style.getImage() instanceof CircleStyle\n ? style.getImage().getRadius()\n : \"\";\n if (circleRadius) {\n styleObj.radius = circleRadius;\n }\n styleObj.pointColor =\n style.getImage() instanceof CircleStyle\n ? style.getImage().getFill().getColor()\n : \"\";\n styleObj.fillColor = style.getFill().getColor();\n styleObj.strokeColor = style.getStroke().getColor();\n styleObj.strokeWidth = style.getStroke().getWidth();\n styleObj.strokeDash = style.getStroke().getLineDash();\n return styleObj;\n };\n}\n","import XLSX from \"xlsx\";\n\nexport default class XLSXExport {\n constructor(settings) {\n this.localObserver = settings.localObserver;\n this.bindSubscriptions();\n }\n\n bindSubscriptions = () => {\n this.localObserver.subscribe(\"downloadMenu.exportXLSXClick\", this.export);\n };\n\n export = (exportItems) => {\n try {\n const { featureCollections } = exportItems;\n const workBook = XLSX.utils.book_new();\n const fileName = this.#getFileName(featureCollections);\n\n if (\n featureCollections?.length === 1 &&\n featureCollections[0].origin === \"USERSELECT\"\n ) {\n return this.#createUserSelectedExport(featureCollections[0], fileName);\n }\n\n featureCollections.forEach((fc) => {\n const sheet = this.#createXLSXSheet(fc);\n if (sheet) {\n const sheetName = this.#getSheetName(fc);\n XLSX.utils.book_append_sheet(workBook, sheet, sheetName);\n }\n });\n\n return XLSX.writeFile(workBook, fileName);\n } catch (error) {\n console.warn(\"Failed to export xlsx...\", error);\n }\n };\n\n #getFileName = (featureCollections) => {\n return featureCollections?.length === 1\n ? `${this.#getSheetName(\n featureCollections[0]\n )}-${new Date().toLocaleString()}.xlsx`\n : `Sökexport-${new Date().toLocaleString()}.xlsx`;\n };\n\n #createUserSelectedExport = (featureCollection, fileName) => {\n try {\n const workBook = XLSX.utils.book_new();\n const groupedFeatures = this.#getGroupedFeatures(featureCollection);\n\n Object.keys(groupedFeatures).forEach((key) => {\n const sheetName = key.slice(0, 30);\n const exportArray = this.#getUserSelectedExportArray(\n groupedFeatures[key]\n );\n const sheet = XLSX.utils.aoa_to_sheet(exportArray);\n XLSX.utils.book_append_sheet(workBook, sheet, sheetName);\n });\n\n return XLSX.writeFile(workBook, fileName);\n } catch (error) {\n console.warn(\"Failed to export user selected xlsx...\", error);\n }\n };\n\n #getGroupedFeatures = (featureCollection) => {\n return featureCollection.value.features.reduce((result, f) => {\n (result[f.source.caption] ?? (result[f.source.caption] = [])).push(f);\n return result;\n }, {});\n };\n\n #getUserSelectedExportArray = (features) => {\n const exportArray = [];\n // Keys from first feature. We assume that all features in the collections has the same keys.\n const keys = Object.keys(features[0].getProperties());\n exportArray.push(keys);\n features.forEach((feature) => {\n exportArray.push(Object.values(feature.getProperties()));\n });\n return exportArray;\n };\n\n #createXLSXSheet = (featureCollection) => {\n if (featureCollection?.value?.features?.length > 0) {\n // Destruct the features for readability\n const { features } = featureCollection.value;\n // Initialize a set which will keep track of _all_ the keys that exist on the\n // features. (Except for the key corresponding to the geometry).\n const keys = new Set();\n // Initialize an array that will contain the keys and all values. (This array\n // will be the result from this function). Example:\n // [key1, key2, key3, val_0_0, val_0_1, val_0_2, val_1_0, val_1_1, val_1_2]\n const exportArray = [];\n // We have to make sure that we get all the keys. To ensure this, we must loop\n // over all the features, and make sure that each key is in the set. If it is not\n // we should add it! (As long as it's not the geometry-key).\n features.forEach((feature) => {\n // Get the geometry name (since we don't want to add the geometry\n // property key). (We don't want the geometry in the export).\n const geometryName = feature.getGeometryName();\n // Then we'll get all the value keys (all keys except for the geometry-key).\n const featureValueKeys = feature\n .getKeys()\n .filter((key) => key !== geometryName);\n // Then we'll loop over the keys and add them to the set of keys if it is missing.\n featureValueKeys.forEach((key) => {\n keys.add(key);\n });\n });\n\n // We want the keys at the beginning (top) of the export, so lets\n // push them to the exportArray first.\n exportArray.push([...keys]);\n\n // When we got the keys, we can extract the corresponding values\n // from each feature.\n features.forEach((feature) => {\n // First we have to get all the properties\n const featureProperties = feature.getProperties();\n // Then we initiate a values array\n const values = [];\n // Then we push the value for each key to the value\n // array. Remember that some values might be nullish,\n // but they are still important, otherwise the fields in the\n // xlsx export might get a messed up order.\n for (const key of keys) {\n // If the value is missing, we replace it with an empty string.\n const value = featureProperties[key] ?? \"\";\n // Then push we push it to the array.\n values.push(value);\n }\n // Then we push the array of values to the export array!\n exportArray.push(values);\n });\n\n return XLSX.utils.aoa_to_sheet(exportArray);\n } else {\n return null;\n }\n };\n\n #getSheetName = (featureCollection) => {\n const sheetName = featureCollection?.source?.caption ?? \"Namn saknas\";\n // XLSX does not support names longer than 30 chars.\n return sheetName.slice(0, 30);\n };\n}\n","import React from \"react\";\nimport { easeOut } from \"ol/easing\";\nimport { Button, Paper } from \"@material-ui/core\";\nimport AddIcon from \"@material-ui/icons/Add\";\nimport RemoveIcon from \"@material-ui/icons/Remove\";\nimport { makeStyles } from \"@material-ui/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n display: \"flex\",\n flexDirection: \"column\",\n },\n button: {\n minWidth: \"unset\",\n },\n}));\n\nconst ZoomControl = React.memo((props) => {\n const classes = useStyles();\n\n function zoomByDelta(delta) {\n if (!props.map) return;\n const view = props.map.getView();\n\n if (!view) return;\n const currentZoom = view.getZoom();\n\n if (currentZoom !== undefined) {\n const newZoom = currentZoom + delta;\n\n // TODO: Duration could be an option from map config, allowing admin to disable zoom animation\n const duration = 200;\n if (duration > 0) {\n if (view.getAnimating()) {\n view.cancelAnimations();\n }\n view.animate({\n zoom: newZoom,\n duration: duration,\n easing: easeOut,\n });\n } else {\n view.setZoom(newZoom);\n }\n }\n }\n\n return (\n props.map !== undefined && (\n <Paper className={classes.paper}>\n <Button\n aria-label=\"Zooma in\"\n className={classes.button}\n onClick={() => {\n zoomByDelta(1);\n }}\n >\n <AddIcon />\n </Button>\n <Button\n aria-label=\"Zooma ut\"\n className={classes.button}\n onClick={() => {\n zoomByDelta(-1);\n }}\n >\n <RemoveIcon />\n </Button>\n </Paper>\n )\n );\n});\n\nexport default ZoomControl;\n","import React from \"react\";\nimport { Avatar, Button, Paper, Tooltip } from \"@material-ui/core\";\n\nimport { makeStyles } from \"@material-ui/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n avatar: {\n width: 25,\n height: 25,\n fontSize: \"0.8rem\",\n backgroundColor: theme.palette.text.primary,\n },\n}));\n\n/**\n * @summary Transform a full name to initials, e.g. \"John Smith\" to \"JS\"\n *\n * @param {string} displayName\n * @returns {string} The initials from supplied string\n */\nconst getInitialsFromDisplayName = (displayName) => {\n return displayName\n .split(\" \")\n .map((name) => name[0])\n .join(\"\")\n .toUpperCase();\n};\n\n/**\n * @summary Compose a tooltip string by joining some user detail values\n *\n * @param {object} userDetails\n * @returns {string} Tooltip string value\n */\nconst getTooltipString = (userDetails) => {\n // Let's combine the details to an array\n const userDetailsArrays = [userDetails.displayName, userDetails.description];\n // Then we'll get rid of empty values, and create a string by joining the non-empty\n // values.\n return userDetailsArrays.filter((v) => v !== undefined).join(\", \");\n};\n\n/**\n * @summary A button that contains user's initials inside an Avatar component\n *\n * @param {object} props\n * @returns {object} React\n */\nconst User = React.memo(({ userDetails }) => {\n const classes = useStyles();\n\n return (\n (userDetails && (\n <Tooltip title={getTooltipString(userDetails)}>\n <Paper className={classes.paper}>\n <Button\n aria-label={userDetails.displayName}\n className={classes.button}\n >\n <Avatar alt={userDetails.displayName} className={classes.avatar}>\n {getInitialsFromDisplayName(userDetails.displayName)}\n </Avatar>\n </Button>\n </Paper>\n </Tooltip>\n )) ||\n null\n );\n});\n\nexport default User;\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { easeOut } from \"ol/easing\";\nimport { Button, Paper, Tooltip } from \"@material-ui/core\";\nimport NavigationIcon from \"@material-ui/icons/Navigation\";\nimport { makeStyles } from \"@material-ui/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n}));\n\nconst RotateControl = React.memo((props) => {\n const classes = useStyles();\n const view = useRef();\n const [rotation, setRotation] = useState(view.current?.getRotation() || 0);\n\n useEffect(() => {\n // No reason to go on if there's no map yet\n if (!props.map) return;\n\n // Put the View object into our ref\n view.current = props.map.getView();\n\n // Subscribe to View's rotation change event. When this happens,\n // we want to read the new rotation and put in state.\n view.current.on(\"change:rotation\", subscribeToRotation);\n return () => {\n // Callback in useEffect is the place where we can cleanup\n // previous code. In this case, we unsubscribe the from the\n // event (so we don't get multiple listeners should this get\n // called more times).\n view.current.un(\"change:rotation\", subscribeToRotation);\n };\n }, [props]);\n\n // Use when (un)subscribing View's change rotation event\n function subscribeToRotation() {\n setRotation(view.current.getRotation());\n }\n\n // onClick handler that resets the map (north at top)\n function rotateNorth() {\n // TODO: This could be an option in admin\n const duration = 400;\n\n if (!view.current) return;\n\n if (rotation !== undefined) {\n // If 'duration' will be an option, we must see if user wants to animate or not\n if (duration > 0) {\n view.current.animate({\n rotation: 0,\n duration: duration,\n easing: easeOut,\n });\n } else {\n view.current.setRotation(0);\n }\n }\n }\n\n return (\n (props.map && rotation !== 0 && (\n <Tooltip title=\"Återställ rotation\">\n <Paper className={classes.paper}>\n <Button\n aria-label=\"Återställ rotation\"\n className={classes.button}\n onClick={rotateNorth}\n >\n <NavigationIcon style={{ transform: `rotate(${rotation}rad)` }} />\n </Button>\n </Paper>\n </Tooltip>\n )) ||\n null\n );\n});\n\nexport default RotateControl;\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { ScaleLine } from \"ol/control\";\nimport { Paper, Tooltip } from \"@material-ui/core\";\n\nconst styles = (theme) => {\n return {\n scaleLine: {\n \"& .ol-scale-line\": {\n position: \"static\",\n right: \"inherit\",\n bottom: \"inherit\",\n padding: \"3px\",\n background: theme.palette.background.paper,\n boxShadow: theme.shadows[4],\n borderRadius: theme.shape.borderRadius,\n },\n \"& .ol-scale-line-inner\": {\n cursor: \"default\",\n borderColor: theme.palette.text.primary,\n color: theme.palette.text.primary,\n fontSize: \"0.7em\",\n lineHeight: \"1.5em\",\n },\n },\n scaleBadge: {\n padding: \"0 4px\",\n color: theme.palette.text.primary,\n fontSize: \"0.7em\",\n lineHeight: \"25px\",\n borderRadius: theme.shape.borderRadius,\n cursor: \"default\",\n },\n };\n};\n\nclass ScaleLineControl extends React.PureComponent {\n state = {\n scale: 0,\n };\n\n constructor(props) {\n super(props);\n this.ref = React.createRef();\n }\n\n componentDidUpdate() {\n // Important condition, to ensure that we don't add new ScaleLine and Binds each time value changes\n if (this.props.map && this.ref.current.children.length === 0) {\n // Set initial value of scale\n this.setState({\n scale: this.formatScale(this.getScale()),\n });\n\n // Add ScaleLine\n const scaleLineControl = new ScaleLine({\n target: this.ref.current,\n });\n this.props.map.addControl(scaleLineControl);\n\n // Add custom scale bar with numbers (e.g. 1:1000)\n // Bind change event to update current scale\n this.props.map.getView().on(\"change:resolution\", () => {\n this.setState({\n scale: this.formatScale(this.getScale()),\n });\n });\n }\n }\n\n /**\n * Get current map sclae\n * @instance\n * @return {number} map scale\n */\n getScale() {\n const dpi = 25.4 / 0.28,\n mpu = this.props.map.getView().getProjection().getMetersPerUnit(),\n inchesPerMeter = 39.37,\n res = this.props.map.getView().getResolution();\n\n return res * mpu * inchesPerMeter * dpi;\n }\n\n /**\n * Format scale\n * @instance\n * @param {number} scale\n * @return {string} formatted\n */\n formatScale(scale) {\n return Math.round(scale)\n .toString()\n .replace(/\\B(?=(\\d{3})+(?!\\d))/g, \" \");\n }\n\n renderScaleBadge() {\n const { classes } = this.props;\n return (\n <Tooltip title=\"Nuvarande skala\">\n <Paper elevation={4} className={classes.scaleBadge}>\n 1:{this.state.scale}\n </Paper>\n </Tooltip>\n );\n }\n\n render() {\n const { classes } = this.props;\n return (\n <>\n <div ref={this.ref} className={classes.scaleLine} />\n {this.renderScaleBadge()}\n </>\n );\n }\n}\n\nexport default withStyles(styles)(ScaleLineControl);\n","import React from \"react\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport { Attribution } from \"ol/control\";\n\nconst styles = (theme) => {\n return {\n attributions: {\n \"& .ol-control\": {\n position: \"static\",\n maxWidth: \"none\",\n },\n \"& .ol-attribution\": {\n background: theme.palette.background.paper,\n boxShadow: theme.shadows[4],\n borderRadius: theme.shape.borderRadius,\n height: \"25px\",\n overflow: \"auto\",\n whiteSpace: \"nowrap\",\n [theme.breakpoints.down(\"xs\")]: {\n maxWidth: \"100px\",\n },\n },\n \"& .ol-attribution ul\": {\n color: \"unset\",\n textShadow: \"unset\",\n },\n \"& button\": {\n cursor: \"pointer\",\n boxShadow: \"none\",\n outline: \"none\",\n },\n },\n };\n};\n\nclass AttributionControl extends React.PureComponent {\n constructor(props) {\n super(props);\n this.ref = React.createRef();\n }\n\n componentDidUpdate() {\n // Go on only if map exists AND we haven't done this yet.\n // Without the children.length part, we'd do this all the\n // time as we're inside componentDidUpdate.\n if (this.props.map && this.ref.current.children.length === 0) {\n const attributionControl = new Attribution({\n target: this.ref.current,\n tipLabel: \"Visa/dölj copyrightinformation för kartdata\",\n label: \"©\",\n });\n this.props.map.addControl(attributionControl);\n }\n }\n\n render() {\n const { classes } = this.props;\n return <div ref={this.ref} className={classes.attributions} />;\n }\n}\n\nexport default withStyles(styles)(AttributionControl);\n","import React from \"react\";\nimport { Button, Paper, Tooltip } from \"@material-ui/core\";\nimport VisibilityOffIcon from \"@material-ui/icons/VisibilityOff\";\n\nimport { makeStyles } from \"@material-ui/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n}));\n\n/**\n * @summary Hides all visible layers\n *\n * @param {object} props\n * @returns {object} React\n */\nconst MapCleaner = React.memo((props) => {\n const classes = useStyles();\n\n return (\n props.appModel.config.mapConfig.map.mapcleaner && (\n <Tooltip title=\"Dölj alla aktiva lager\">\n <Paper className={classes.paper}>\n <Button\n aria-label=\"Rensa kartan\"\n className={classes.button}\n onClick={(e) => {\n props.appModel.clear();\n }}\n >\n <VisibilityOffIcon />\n </Button>\n </Paper>\n </Tooltip>\n )\n );\n});\n\nexport default MapCleaner;\n","import React from \"react\";\nimport { Button, Paper, Tooltip } from \"@material-ui/core\";\nimport HomeIcon from \"@material-ui/icons/Home\";\n\nimport { withStyles } from \"@material-ui/core/styles\";\n\nconst styles = (theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n});\n\n/**\n * @summary Resets map to initial zoom level, centrum coordinate and active layers.\n *\n * @param {object} props\n * @returns {object} React\n */\nclass MapResetter extends React.PureComponent {\n // TODO: Also reset layers to default visibility!\n handleClick = (e) => {\n const { map } = this.props;\n if (map !== undefined) {\n const view = map.getView();\n const { zoom, center } = this.props.mapConfig.map;\n view.animate({ zoom, center });\n }\n };\n\n render() {\n const { classes } = this.props;\n\n return (\n <Tooltip title=\"Återställ kartan till startläget\">\n <Paper className={classes.paper}>\n <Button\n aria-label=\"Återställ kartan till startläget\"\n className={classes.button}\n onClick={this.handleClick}\n >\n <HomeIcon />\n </Button>\n </Paper>\n </Tooltip>\n );\n }\n}\n\nexport default withStyles(styles)(MapResetter);\n","import React from \"react\";\nimport { Button, Menu, MenuItem, Paper, Tooltip } from \"@material-ui/core\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport SwitchCameraIcon from \"@material-ui/icons/SwitchCamera\";\nimport { hfetch } from \"utils/FetchWrapper\";\n\nconst styles = (theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n});\n\nclass MapSwitcher extends React.PureComponent {\n // Will hold map configs\n maps = [];\n\n state = {\n anchorEl: null,\n selectedIndex: null,\n };\n\n constructor(props) {\n super(props);\n this.appModel = this.props.appModel;\n this.map = this.props.appModel.getMap();\n }\n\n handleLoading(maps) {\n let { activeMap } = this.appModel.config;\n // Save fetched map configs to global variable\n this.maps = maps;\n\n // Set selectedIndex to currently selected map\n let selectedIndex = this.maps.findIndex((map) => {\n return map.mapConfigurationName === activeMap;\n });\n this.setState({ selectedIndex });\n }\n\n componentDidMount() {\n let { proxy, mapserviceBase } = this.appModel.config.appConfig;\n\n // If user specific maps is provided by the new API, the key will\n // already exist in config and there's no need to fetch again.\n // However, if it's undefined, it looks like we're using the old API\n // and MapSwitcher must do the fetch by itself.\n if (this.appModel.config.userSpecificMaps !== undefined) {\n this.handleLoading(this.appModel.config.userSpecificMaps);\n } else {\n hfetch(`${proxy}${mapserviceBase}/config/userspecificmaps`)\n .then((resp) => resp.json())\n .then((maps) => this.handleLoading(maps))\n .catch((err) => {\n throw new Error(err);\n });\n }\n }\n\n renderMenuItems = () => {\n let menuItems = [];\n this.maps.forEach((item, index) => {\n menuItems.push(\n <MenuItem\n key={index}\n // disabled={index === this.state.selectedIndex}\n selected={index === this.state.selectedIndex}\n onClick={(event) => this.handleMenuItemClick(event, index)}\n >\n {item.mapConfigurationTitle}\n </MenuItem>\n );\n });\n return menuItems;\n };\n\n // Show dropdown menu, anchored to the element clicked\n handleClick = (event) => {\n this.setState({ anchorEl: event.currentTarget });\n };\n\n handleMenuItemClick = (event, index) => {\n const selectedMap = this.maps[index].mapConfigurationName;\n const x = this.map.getView().getCenter()[0];\n const y = this.map.getView().getCenter()[1];\n const z = this.map.getView().getZoom();\n // TODO: A better solution then redirecting is needed. It requires more\n // work in the App component, so that changing the value of this.appModel.config.activeMap\n // would dynamically reload configuration as needed.\n // But for now, simple redirection will do.\n window.location.assign(\n `${window.location.origin}${window.location.pathname}?m=${selectedMap}&x=${x}&y=${y}&z=${z}`\n );\n\n // Not used as we change window.location. But in a better solution, we wouldn't reload the app,\n // and then code below would be needed to hide the dropdown menu.\n // this.setState({ anchorEl: null, selectedIndex: index });\n };\n\n handleClose = () => {\n this.setState({ anchorEl: null });\n };\n\n render() {\n const { anchorEl } = this.state;\n const { classes } = this.props;\n const open = Boolean(anchorEl);\n\n const title =\n this.props.appModel.config.mapConfig.map.title || \"Karta utan titel\";\n\n return (\n // Render only if config says so\n this.props.appModel.config.mapConfig.map.mapselector && (\n <>\n <Tooltip title={`Nuvarande karta: ${title}`}>\n <Paper className={classes.paper}>\n <Button\n aria-label=\"Byt karta\"\n aria-owns={open ? \"render-props-menu\" : undefined}\n aria-haspopup=\"true\"\n className={classes.button}\n onClick={this.handleClick}\n >\n <SwitchCameraIcon />\n </Button>\n </Paper>\n </Tooltip>\n <Menu\n id=\"render-props-menu\"\n anchorEl={anchorEl}\n open={open}\n onClose={this.handleClose}\n >\n {this.renderMenuItems()}\n </Menu>\n </>\n )\n );\n }\n}\n\nexport default withStyles(styles)(MapSwitcher);\n","import React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport propTypes from \"prop-types\";\n\nimport { Button, Paper, Tooltip } from \"@material-ui/core\";\nimport InfoIcon from \"@material-ui/icons/Info\";\n\nimport Dialog from \"../components/Dialog/Dialog\";\n\nimport { functionalOk as functionalCookieOk } from \"models/Cookie\";\n\nconst styles = (theme) => {\n return {\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n };\n};\n\nclass Information extends React.PureComponent {\n static propTypes = {\n classes: propTypes.object.isRequired,\n options: propTypes.object.isRequired,\n };\n\n constructor(props) {\n super(props);\n this.type = \"Information\"; // Special case - plugins that don't use BaseWindowPlugin must specify .type here\n this.options = props.options;\n this.title = this.options.title || \"Om kartan\";\n this.state = {\n dialogOpen: false,\n };\n }\n\n componentDidMount() {\n let dialogOpen = this.options.visibleAtStart;\n\n if (this.options.visibleAtStart === true) {\n if (\n this.options.showInfoOnce === true &&\n parseInt(\n window.localStorage.getItem(\"pluginInformationMessageShown\")\n ) === 1\n ) {\n dialogOpen = false;\n } else {\n if (this.options.showInfoOnce === true && functionalCookieOk()) {\n window.localStorage.setItem(\"pluginInformationMessageShown\", 1);\n }\n dialogOpen = true;\n }\n } else {\n dialogOpen = false;\n }\n\n this.setState({\n dialogOpen,\n });\n }\n\n onClose = () => {\n this.setState({\n dialogOpen: false,\n });\n };\n\n handleOnClick = () => {\n this.setState({\n dialogOpen: true,\n });\n };\n\n renderDialog() {\n const { headerText, text, buttonText } = this.props.options;\n\n return createPortal(\n <Dialog\n options={{\n headerText,\n text,\n buttonText,\n useLegacyNonMarkdownRenderer: true, // Preserve backward compatibility with how Dialog used to work prior ReactMarkdown\n }}\n open={this.state.dialogOpen}\n onClose={this.onClose}\n />,\n document.getElementById(\"windows-container\")\n );\n }\n\n render() {\n const { classes } = this.props;\n return (\n <>\n {this.renderDialog()}\n <Tooltip title={this.title}>\n <Paper className={classes.paper}>\n <Button\n aria-label={this.title}\n className={classes.button}\n onClick={this.handleOnClick}\n >\n <InfoIcon />\n </Button>\n </Paper>\n </Tooltip>\n </>\n );\n }\n}\n\nexport default withStyles(styles)(Information);\n","import React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport propTypes from \"prop-types\";\nimport { withSnackbar } from \"notistack\";\n\nimport { Button, Paper, Tooltip, Menu, MenuItem } from \"@material-ui/core\";\nimport FolderSpecial from \"@material-ui/icons/FolderSpecial\";\n\nimport Dialog from \"../components/Dialog/Dialog\";\n\nconst styles = (theme) => {\n return {\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n };\n};\n\nclass Preset extends React.PureComponent {\n static propTypes = {\n classes: propTypes.object.isRequired,\n appModel: propTypes.object.isRequired,\n };\n\n state = {\n anchorEl: null,\n dialogOpen: false,\n };\n\n constructor(props) {\n super(props);\n this.type = \"Preset\"; // Special case - plugins that don't use BaseWindowPlugin must specify .type here\n this.config = props.appModel.config.mapConfig.tools.find(\n (t) => t.type === \"preset\"\n );\n\n this.appModel = props.appModel;\n this.globalObserver = props.appModel.globalObserver;\n\n // If config wasn't found, it means that Preset is not configured. Quit.\n if (this.config === undefined) return;\n\n // Else, if we're still here, go on.\n this.options = this.config.options;\n this.map = props.appModel.getMap();\n this.title = this.options.title || \"Snabbval\";\n\n this.location = null;\n this.zoom = null;\n this.layers = null;\n }\n\n // Show dropdown menu, anchored to the element clicked\n handleClick = (event) => {\n this.setState({ anchorEl: event.currentTarget });\n };\n\n handleClose = () => {\n this.setState({ anchorEl: null });\n };\n\n // A map-link must contain an x-, y-, and z-position to be valid. This function\n // checks wether that is true or not.\n isValidMapLink = (mapLink) => {\n return (\n (mapLink.includes(\"x=\") && mapLink.includes(\"y=\")) ||\n mapLink.includes(\"l=\")\n );\n };\n\n // Extracts map-information from the provided link and returns the\n // information as an object.\n getMapInfoFromMapLink = (mapLink) => {\n const queryParams = new URLSearchParams(mapLink);\n const x = queryParams.get(\"x\");\n const y = queryParams.get(\"y\");\n const z = queryParams.get(\"z\");\n const l = queryParams.get(\"l\");\n\n const location = x && y ? [x, y] : null;\n const zoom = location ? z : null; // no need to zoom if we don't have a position.\n return { location, zoom, layers: l };\n };\n\n handleItemClick = (event, item) => {\n const url = item.presetUrl.toLowerCase();\n // Let's make sure that the provided url is a valid map-link\n if (this.isValidMapLink(url)) {\n this.handleClose(); // Ensure that popup menu is closed\n const { location, zoom, layers } = this.getMapInfoFromMapLink(url);\n this.location = location;\n this.zoom = location ? zoom || this.map.getView().getZoom() : null;\n\n this.layers = layers;\n\n // If the link contains layers we open the dialog where the user can choose to\n // proceed.\n if (layers) {\n this.openDialog();\n } // If the link does not contain layers, we can simply fly to the new location\n // without toggling layers and so on.\n else {\n this.flyTo(this.map.getView(), this.location, this.zoom);\n }\n } // If the provided url is not a valid map-link, warn the user.\n else {\n this.props.enqueueSnackbar(\n \"Länken till platsen är tyvärr felaktig. Kontakta administratören av karttjänsten för att åtgärda felet.\",\n {\n variant: \"warning\",\n }\n );\n console.error(\n \"Fel i verktyget Snabbval. Länken til : \\n\" +\n item.name +\n \"\\n\" +\n item.presetUrl +\n \"\\när tyvärr felaktig. Någon av följande parametrar saknas: &x=, &y=, &z= eller innehåller fel.\"\n );\n }\n };\n\n renderMenuItems = () => {\n const menuItems = [];\n this.options.presetList.forEach((item, index) => {\n menuItems.push(\n <MenuItem\n key={index}\n onClick={(event) => this.handleItemClick(event, item)}\n >\n {item.name}\n </MenuItem>\n );\n });\n return menuItems;\n };\n\n flyTo(view, location, zoom) {\n if (!location) {\n return;\n }\n const duration = 1500;\n view.animate({\n center: location,\n zoom: zoom,\n duration: duration,\n });\n }\n\n openDialog = () => {\n this.setState({\n dialogOpen: true,\n });\n };\n\n closeDialog = () => {\n const visibleLayers = this.layers.split(\",\");\n this.setState({\n dialogOpen: false,\n });\n this.toggleMapLayers(visibleLayers);\n this.flyTo(this.map.getView(), this.location, this.zoom);\n };\n\n abortDialog = () => {\n this.setState({\n dialogOpen: false,\n });\n };\n\n layerShouldBeVisible = (layer, visibleLayers) => {\n return visibleLayers.some(\n (layerId) => layerId === layer.getProperties()[\"name\"]\n );\n };\n\n toggleMapLayers = (visibleLayers) => {\n const layerSwitcherLayers = this.map\n .getLayers()\n .getArray()\n .filter((layer) => layer.get(\"layerInfo\"));\n\n for (const l of layerSwitcherLayers) {\n if (this.layerShouldBeVisible(l, visibleLayers)) {\n this.globalObserver.publish(\"layerswitcher.showLayer\", l);\n l.setVisible(true);\n } else {\n this.globalObserver.publish(\"layerswitcher.hideLayer\", l);\n l.setVisible(false);\n }\n }\n };\n\n renderDialog() {\n if (this.state.dialogOpen) {\n return createPortal(\n <Dialog\n options={{\n text: \"Alla tända lager i kartan kommer nu att släckas. Snabbvalets fördefinierade lager tänds istället.\",\n headerText: \"Visa snabbval\",\n buttonText: \"OK\",\n abortText: \"Avbryt\",\n useLegacyNonMarkdownRenderer: true,\n }}\n open={this.state.dialogOpen}\n onClose={this.closeDialog}\n onAbort={this.abortDialog}\n />,\n document.getElementById(\"windows-container\")\n );\n } else {\n return null;\n }\n }\n\n render() {\n // If config for Control isn't found, or if the config doesn't contain any presets, quit.\n if (\n this.config === undefined ||\n (this.config.hasOwnProperty(\"options\") &&\n this.config.options.presetList.length < 1)\n ) {\n return null;\n } else {\n const { anchorEl } = this.state;\n const { classes } = this.props;\n const open = Boolean(anchorEl);\n return (\n <>\n <Tooltip title={this.title}>\n <Paper className={classes.paper}>\n <Button\n aria-label={this.title}\n className={classes.button}\n onClick={this.handleClick}\n >\n <FolderSpecial />\n </Button>\n </Paper>\n </Tooltip>\n <Menu\n id=\"render-props-menu\"\n anchorEl={anchorEl}\n open={open}\n onClose={this.handleClose}\n >\n {this.renderMenuItems()}\n </Menu>\n {this.renderDialog()}\n </>\n );\n }\n }\n}\n\nexport default withStyles(styles)(withSnackbar(Preset));\n","import React, { useEffect, useState } from \"react\";\n\nimport { makeStyles } from \"@material-ui/core/styles\";\n\nimport ToggleButton from \"@material-ui/lab/ToggleButton\";\nimport ToggleButtonGroup from \"@material-ui/lab/ToggleButtonGroup\";\n\nimport CloseIcon from \"@material-ui/icons/Close\";\nimport { Paper, Hidden } from \"@material-ui/core\";\n\nimport { functionalOk as functionalCookieOk } from \"models/Cookie\";\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n marginRight: theme.spacing(1),\n [theme.breakpoints.down(\"xs\")]: {\n boxShadow: \"none\",\n },\n },\n button: {\n border: 0,\n color:\n theme.palette.type === \"dark\"\n ? theme.palette.common.white\n : theme.palette.action.active,\n },\n icon: {\n [theme.breakpoints.up(\"md\")]: {\n marginRight: theme.spacing(1),\n },\n },\n grouped: {\n [theme.breakpoints.down(\"xs\")]: {\n border: \"none\",\n },\n },\n}));\n\nfunction DrawerToggleButtons({\n drawerButtons,\n globalObserver,\n initialActiveButton,\n}) {\n const classes = useStyles();\n\n //Set initial active button state based on the initially active drawer, received from App.js\n //This will either be a drawer button name such as \"plugins\" or null, depending on whether there\n //is an active drawer when the map starts (set either from the cookie or config).\n const [activeButton, setActiveButton] = useState(initialActiveButton);\n\n // Sort by the (optional) @order property prior rendering\n // Sort using minus (-) causes the correct behavior, as this will\n // first implicitly convert the value to number.\n // If we'd compare using less than (<), that would sort our values\n // as UTF-16 strings, so we could get something like: 1, 1000, 2,\n // instead of 1, 2, 1000 which is desired in this case.\n drawerButtons = drawerButtons.sort((a, b) => a?.order - b?.order);\n\n // Subscribe only once, important that it's done inside useEffect!\n useEffect(() => {\n globalObserver.subscribe(\"core.unsetActiveButton\", () => {\n setActiveButton(null);\n });\n }, [globalObserver]);\n\n const handleClickOnToggleButton = (e, v) => {\n setActiveButton(v);\n\n if (v === null) {\n window.localStorage.removeItem(\"activeDrawerContent\");\n } else {\n if (functionalCookieOk()) {\n window.localStorage.setItem(\"activeDrawerContent\", v);\n }\n }\n\n // Let the outside world know that a button has been pressed.\n // App will handle changing context. v=null is valid too.\n globalObserver.publish(\"core.drawerContentChanged\", v);\n };\n\n const renderToggleButton = ({ ButtonIcon, value, caption }) => {\n // Currently active toggle button should have a \"Close\" icon\n const icon =\n value === activeButton ? (\n <CloseIcon className={classes.icon} />\n ) : (\n <ButtonIcon className={classes.icon} />\n );\n\n // Caption should be hidden on small screens\n return (\n <ToggleButton\n id={value}\n key={value}\n value={value}\n className={classes.button}\n >\n {icon}\n <Hidden smDown>{caption}</Hidden>\n </ToggleButton>\n );\n };\n\n return (\n drawerButtons.length > 0 && (\n <Paper className={classes.root}>\n <ToggleButtonGroup\n value={activeButton}\n exclusive\n onChange={handleClickOnToggleButton}\n aria-label=\"Drawer content\"\n classes={{ grouped: classes.grouped }}\n >\n {drawerButtons.map((b) => renderToggleButton(b))}\n </ToggleButtonGroup>\n </Paper>\n )\n );\n}\n\nfunction arePropsEqual(prevProps, nextProps) {\n // Only re-render if drawerButtons have changed since last render\n return prevProps.drawerButtons.length === nextProps.drawerButtons.length;\n}\n\nexport default React.memo(DrawerToggleButtons, arePropsEqual);\n","import React from \"react\";\nimport { Button, Paper, Tooltip } from \"@material-ui/core\";\nimport Brightness4Icon from \"@material-ui/icons/Brightness4\";\n\nimport { makeStyles } from \"@material-ui/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n paper: {\n marginBottom: theme.spacing(1),\n },\n button: {\n minWidth: \"unset\",\n },\n}));\n\n/**\n * @summary Hides all visible layers\n *\n * @param {object} props\n * @returns {object} React\n */\nconst ThemeToggler = React.memo((props) => {\n const classes = useStyles();\n\n return (\n (props.showThemeToggler && (\n <Tooltip title=\"Växla mellan mörkt och ljust färgtema\">\n <Paper className={classes.paper}>\n <Button\n aria-label=\"Växla färgtema\"\n className={classes.button}\n onClick={(e) => {\n props.toggleMUITheme();\n }}\n >\n <Brightness4Icon />\n </Button>\n </Paper>\n </Tooltip>\n )) ||\n null\n );\n});\n\nexport default ThemeToggler;\n","const reportWebVitals = (onPerfEntry) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import(\"web-vitals\").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","// IE 11 starts here.\n// If you don't need IE 11, comment out those lines line.\n// Also, change 'browserslist' in package.json to exclude ie11.\nimport \"react-app-polyfill/ie11\";\nimport \"react-app-polyfill/stable\";\nimport \"abortcontroller-polyfill/dist/polyfill-patch-fetch\";\nimport \"allsettled-polyfill\";\n// IE 11 ends here.\n\n// iOS 12 and other older touch devices need this polyfill to\n// support OpenLayers map interactions through Pointer Events API.\n// See: https://github.com/hajkmap/Hajk/issues/606\nimport \"elm-pep\";\n\n// Since we don't want to download roboto from the Google CDN,\n// we use fontSource and import all subsets that MUI relies on here.\nimport \"@fontsource/roboto/300.css\";\nimport \"@fontsource/roboto/400.css\";\nimport \"@fontsource/roboto/500.css\";\nimport \"@fontsource/roboto/700.css\";\n\n// We want to support open-sans locally as well (If someone sets open-sans\n// in the customTheme.json, we still want to avoid requests to outside CDN)\nimport \"@fontsource/open-sans\";\n\n// The documentHandler imports icons in a dynamic way. To avoid requests against\n// an outside CDN, we make sure to install the required font for the icons as well.\nimport \"@fontsource/material-icons\";\n\nimport \"ol/ol.css\";\nimport \"./custom-ol.css\";\n\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport buildConfig from \"./buildConfig.json\";\nimport ErrorIcon from \"@material-ui/icons/Error\";\nimport HajkThemeProvider from \"./components/HajkThemeProvider\";\nimport reportWebVitals from \"./reportWebVitals\";\nimport { initHFetch, hfetch, initFetchWrapper } from \"utils/FetchWrapper\";\nimport LocalStorageHelper from \"utils/LocalStorageHelper\";\n\ninitHFetch();\n\nlet networkErrorMessage =\n \"Nätverksfel. Prova att ladda om applikationen genom att trycka på F5 på ditt tangentbord.\";\nlet parseErrorMessage =\n \"Fel när applikationen skulle läsas in. Detta beror troligtvis på ett konfigurationsfel. Försök igen senare.\";\n\nconst renderError = (message, err) => {\n console.error(err);\n ReactDOM.render(\n <div className=\"start-error\">\n <div>\n <ErrorIcon />\n </div>\n <div>{message}</div>\n </div>,\n document.getElementById(\"root\")\n );\n};\n\n/**\n * Entry point to Hajk.\n * We start with a fetching appConfig.json, that is expected\n * to be located in the same directory as index.js.\n *\n * appConfig.json includes URL to the backend application (called MapService),\n * as well as the default preferred map configuration's file name.\n */\nhfetch(\"appConfig.json\", { cacheBuster: true })\n .then((appConfigResponse) => {\n appConfigResponse.json().then((appConfig) => {\n // Update hfetch with loaded config.\n initFetchWrapper(appConfig);\n // See if we have site-specific error messages\n if (appConfig.networkErrorMessage)\n networkErrorMessage = appConfig.networkErrorMessage;\n if (appConfig.parseErrorMessage)\n parseErrorMessage = appConfig.parseErrorMessage;\n\n // Grab URL params using the new URL API, save for later\n const urlParams = new URL(window.location).searchParams;\n\n // If m param is supplied, try loading a map with that name\n // or else, fall back to default from appConfig.json\n let activeMap = urlParams.has(\"m\")\n ? urlParams.get(\"m\")\n : appConfig.defaultMap;\n\n // Check if mapserviceBase is set in appConfig. If it is not, we will\n // fall back on the simple map and layer configurations found in /public.\n const useMapService =\n appConfig.mapserviceBase && appConfig.mapserviceBase.trim().length > 0;\n\n const useNewApi = appConfig.experimentalNewApi === true;\n\n // Declare fetchMapConfig() that we'll use later on.\n //\n // The name of map config to fetch comes from appConfig.json's \"defaultMap\"\n // parameter, but it can be overridden by the \"m\" URL param.\n //\n // This can lead to a number of problems when users specify non-existing\n // map configs or if a map config's name has been changed.\n //\n // To avoid this, we first try to fetch the user-specified file,\n // but if that fails, we fall back to the hard-coded \"defaultMap\".\n const fetchMapConfig = async () => {\n // If the optional, experimental, consolidated loading process is active,\n // change the API from v1 to v2:\n const mapserviceBase =\n useNewApi === true\n ? appConfig.mapserviceBase.replace(\"v1\", \"v2\")\n : appConfig.mapserviceBase;\n\n // This saves us some keystrokes later on…\n const configUrl = `${appConfig.proxy}${mapserviceBase}/config`;\n try {\n // Try to fetch user-specified config. Return it if OK.\n return await hfetch(`${configUrl}/${activeMap}`);\n } catch {\n // If the previous attempt fails reset \"activeMap\" to hard-coded value…\n activeMap = appConfig.defaultMap;\n // …and fetch again.\n return await hfetch(`${configUrl}/${activeMap}`);\n }\n };\n\n if (useNewApi === true) {\n Promise.all([\n fetchMapConfig(),\n hfetch(\"customTheme.json\", { cacheBuster: true }),\n ])\n .then(([mapConfigResponse, customThemeResponse]) => {\n Promise.all([mapConfigResponse.json(), customThemeResponse.json()])\n .then(([mapConfig, customTheme]) => {\n const config = {\n activeMap: useMapService ? activeMap : \"simpleMapConfig\", // If we are not utilizing mapService, we know that the active map must be \"simpleMapConfig\".\n appConfig: appConfig,\n layersConfig: mapConfig.layersConfig,\n mapConfig: mapConfig.mapConfig,\n userDetails: mapConfig.userDetails,\n userSpecificMaps: mapConfig.userSpecificMaps,\n urlParams,\n };\n\n // At this stage, we know for sure what activeMap is, so we can initiate the LocalStorageHelper\n LocalStorageHelper.setKeyName(config.activeMap);\n\n // Invoke React's renderer. Render Theme. Theme will render App.\n ReactDOM.render(\n <HajkThemeProvider\n activeTools={buildConfig.activeTools}\n config={config}\n customTheme={customTheme}\n />,\n document.getElementById(\"root\")\n );\n })\n .catch((err) => renderError(parseErrorMessage, err));\n })\n .catch((err) => renderError(networkErrorMessage, err));\n } else {\n // Next, we do 3 necessary requests to get the map, layers, and customTheme configurations.\n Promise.all([\n // Get the layers configuration from mapService (if mapService is not active, we fall back on the local\n // \"simpleLayerConfig\" configuration file\n useMapService\n ? hfetch(\n `${appConfig.proxy}${appConfig.mapserviceBase}/config/layers`\n )\n : hfetch(\"simpleLayersConfig.json\", { cacheBuster: true }),\n // Get the specific, requested map configuration (if mapService is not active, we fall back on the local\n // \"simpleMapConfig\" configuration file).\n useMapService\n ? fetchMapConfig()\n : hfetch(\"simpleMapConfig.json\", { cacheBuster: true }),\n // Additionally, we fetch a custom theme that allows site admins to override\n // the default MUI theme without re-compiling the application.\n hfetch(\"customTheme.json\", { cacheBuster: true }),\n ])\n .then(\n ([\n layersConfigResponse,\n mapConfigResponse,\n customThemeResponse,\n ]) => {\n Promise.all([\n layersConfigResponse.json(),\n mapConfigResponse.json(),\n customThemeResponse.json(),\n ])\n .then(([layersConfig, mapConfig, customTheme]) => {\n // The fetched files are decoded to Objects and placed in\n // another object, @name config.\n const config = {\n activeMap: useMapService ? activeMap : \"simpleMapConfig\", // If we are not utilizing mapService, we know that the active map must be \"simpleMapConfig\".\n appConfig: appConfig,\n layersConfig: layersConfig,\n mapConfig: mapConfig,\n urlParams,\n };\n\n // At this stage, we know for sure what activeMap is, so we can initiate the LocalStorageHelper\n LocalStorageHelper.setKeyName(config.activeMap);\n\n // Make sure that the current user is allowed to display the current map\n const layerSwitcherConfig = config.mapConfig.tools.find(\n (tool) => tool.type === \"layerswitcher\"\n );\n if (layerSwitcherConfig === undefined) {\n throw new Error(\n \"noLayerSwitcher: \" +\n (config.appConfig.noLayerSwitcherMessage === undefined\n ? \"This map has no layerSwitcher indicating that you are not allowed to use this map!\"\n : config.appConfig.noLayerSwitcherMessage)\n );\n }\n\n // Invoke React's renderer. Render Theme. Theme will render App.\n ReactDOM.render(\n <HajkThemeProvider\n activeTools={buildConfig.activeTools}\n config={config}\n customTheme={customTheme}\n />,\n document.getElementById(\"root\")\n );\n })\n .catch((err) => {\n console.error(\"Parse error: \", err.message);\n let errMsg = parseErrorMessage;\n if (err.message.startsWith(\"noLayerSwitcher:\")) {\n errMsg = err.message.substr(err.message.indexOf(\":\") + 2);\n }\n renderError(errMsg, err);\n });\n }\n )\n .catch((err) => {\n renderError(networkErrorMessage, err);\n });\n }\n });\n })\n .catch((err) => {\n renderError(networkErrorMessage, err);\n });\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n","// We need som default options before we\n// get the real default options from appConfig\nlet config = {\n hfetch: {\n defaultOptions: { credentials: \"same-origin\" },\n },\n};\n\n// From appConfig it looks approx like this.\n// \"hfetch\": {\n// \"defaultOptions\": {\n// \"credentials\": \"same-origin\"\n// },\n// \"useOptionOverrides\": true,\n// \"optionOverrides\": {\n// \"*www.cachebuster.com*\": {\n// \"cacheBuster\": true\n// },\n// \"*wms-utv.varberg.se*\": {\n// \"credentials\": \"include\"\n// },\n// \"*www.requires-credentials.com*\": {\n// \"credentials\": \"include\"\n// }\n// }\n// }\n\nconst cacheBusterParamName = \"cacheBuster\";\n\nclass FetchWrapper {\n // Had to disable.... eslint does not like my regex for som reason.\n // eslint-disable-next-line no-useless-escape\n urlRegex = /([.*+?^=!:${}()|\\[\\]\\/\\\\])/g;\n\n constructor(options = {}, config = {}) {\n this.isJqueryAjax = options.isJqueryAjax === true;\n this.config = config;\n this.url = \"\";\n this.options = {};\n\n // Hash is used for cacheBuster function.\n this.hash = process?.env?.REACT_APP_GIT_HASH || null;\n this.useCacheBuster =\n process?.env?.REACT_APP_USE_CACHE_BUSTER === \"true\" || false;\n }\n\n matchesUrlPart(url, ruleWithWildCard) {\n // Works with *, example:\n // monk* matches monkey\n // *nk* matches monkey\n // *key matches monkey\n\n const escapeRegex = (url) => url.replace(this.urlRegex, \"\\\\$1\");\n return new RegExp(\n \"^\" + ruleWithWildCard.split(\"*\").map(escapeRegex).join(\".*\") + \"$\"\n ).test(url);\n }\n\n applyOptionOverrides() {\n if (!this.partKeys) {\n this.partKeys = Object.keys(this.config.hfetch.optionOverrides || {});\n this.partKeys.sort((a, b) => b.length - a.length);\n }\n\n const key = this.partKeys.find((key) => {\n return this.matchesUrlPart(this.url, key);\n });\n\n if (key) {\n // We've found a match!\n let overrides = this.config.hfetch.optionOverrides[key] || {};\n this.options = Object.assign(this.options, overrides);\n }\n }\n\n translateToJqueryAjaxOptions() {\n // translate credentials to work with $.ajax(), old admin UI.\n // Will be used in admin later.\n if (this.options.credentials && this.options.credentials === \"include\") {\n this.options.xhrFields = { withCredentials: true };\n delete this.options.credentials; // clean up.\n }\n }\n\n overrideOptions() {\n this.options = Object.assign(\n { ...this.config.hfetch.defaultOptions },\n this.options\n );\n\n if (this.config.hfetch.useOptionOverrides) {\n this.applyOptionOverrides();\n }\n\n if (this.isJqueryAjax) {\n // handle $.ajax() specific things.\n // Will be used in admin later.\n this.translateToJqueryAjaxOptions();\n }\n\n if (this.useCacheBuster === true) {\n // cacheBuster will force browser to reload the file.\n // In this case it's using git commit hash.\n // So every new Hajk version that's build will force reload.\n\n if (\n this.options.cacheBuster === true ||\n (this.mapserviceBaseUri &&\n this.url.indexOf(this.mapserviceBaseUri) === 0)\n ) {\n let cacheBuster = `${\n this.url.indexOf(\"?\") === -1 ? \"?\" : \"&\"\n }${cacheBusterParamName}=${this.hash}`;\n this.url = `${this.url}${cacheBuster}`;\n }\n }\n }\n\n updateConfig(config) {\n this.config = config;\n this.mapserviceBase = this.config.mapserviceBase || \"\";\n this.proxy = this.config.proxy || \"\";\n this.mapserviceBaseUri = `${this.proxy}${this.mapserviceBase}`;\n }\n\n reset() {\n this.options = {};\n this.url = \"\";\n }\n}\n\nlet fetchWrapper = null;\nlet originalFetch = null;\n\nfunction initFetchWrapper(appConfig) {\n config = Object.assign(config, appConfig);\n if (fetchWrapper) {\n fetchWrapper.updateConfig(config);\n }\n if (jqueryAjaxWrapper) {\n jqueryAjaxWrapper.updateConfig(config);\n }\n}\n\nfunction initHFetch() {\n if (fetchWrapper) {\n throw new Error(\"You should only initiate wrapFetch once\");\n }\n fetchWrapper = new FetchWrapper({}, config);\n originalFetch = fetch;\n\n return hfetch;\n}\n\nfunction overrideLayerSourceParams(source) {\n let fw = fetchWrapper;\n fw.reset();\n fw.url = source.url;\n fw.options = { ...source };\n if (fw.config.hfetch.useOptionOverrides) {\n fw.applyOptionOverrides();\n }\n if (fw.options?.credentials === \"include\") {\n if (source.crossOrigin) {\n // handle crossOrigin in tile images etc\n source.crossOrigin = \"use-credentials\";\n }\n }\n}\n\nfunction hfetch(...args) {\n let fw = fetchWrapper;\n fw.reset();\n\n fw.options = args[1] || {};\n\n // Handle all types that the original fetch accepts. The next 2 comment are from fetch documentation.\n // \"A string or any other object with a stringifier — including a URL object — that provides the URL of the resource you want to fetch.\"\n // \"A Request object.\"\n\n if (typeof args[0] === \"string\") {\n fw.url = args[0];\n } else if (args[0] instanceof URL) {\n fw.url = args[0].href;\n } else if (args[0] instanceof Request) {\n // The Request object is deconstructed then reconstructed by original fetch. Not perfect...\n fw.url = args[0].url;\n fw.options = args[0];\n } else {\n fw.url = args[0].toString();\n }\n\n fw.overrideOptions();\n //console.log(\"hfetch\", fw.url, fw.options);\n return originalFetch(fw.url, fw.options);\n}\n\nlet jqueryAjaxWrapper = null;\nlet originalJqueryAjax = null;\n\nfunction wrapJqueryAjax(jqueryObject) {\n if (jqueryAjaxWrapper) {\n throw new Error(\"You should only initiate wrapJqueryAjax once\");\n }\n jqueryAjaxWrapper = new FetchWrapper({ isJqueryAjax: true }, config);\n originalJqueryAjax = jqueryObject.ajax;\n jqueryObject.ajax = xJqueryAjax;\n}\n\nfunction xJqueryAjax(...args) {\n let jw = jqueryAjaxWrapper;\n jw.reset();\n jw.url = args[0];\n\n if (args.length === 1) {\n // Assume $.ajax(object with url)\n jw.options = Object.assign({}, args[0]);\n jw.overrideOptions();\n return originalJqueryAjax(jw.options);\n } else if (args.length === 2) {\n // Assume $.ajax(url, options)\n jw.options = args[1];\n jw.overrideOptions();\n return originalJqueryAjax(jw.url, jw.options);\n }\n}\n\nexport {\n initFetchWrapper,\n initHFetch,\n hfetch,\n wrapJqueryAjax,\n overrideLayerSourceParams,\n};\n","/**\n * TODO:\n * This is obsolete and will be removed once we refactor methods that\n * make use of getIsMobile() and isMobile().\n */\nexport const isMobile = getIsMobile();\n\nexport function getIsMobile() {\n return window.innerWidth < 600;\n}\n","var map = {\n\t\"./components/Alert.js\": [\n\t\t428\n\t],\n\t\"./components/Announcement/Announcement.js\": [\n\t\t490\n\t],\n\t\"./components/App.js\": [\n\t\t476\n\t],\n\t\"./components/Card.js\": [\n\t\t1173,\n\t\t119\n\t],\n\t\"./components/CookieNotice.js\": [\n\t\t488\n\t],\n\t\"./components/Diagram.js\": [\n\t\t1352,\n\t\t2,\n\t\t36,\n\t\t175\n\t],\n\t\"./components/Dialog/Dialog.js\": [\n\t\t220\n\t],\n\t\"./components/Drawer/DrawerToggleButtons.js\": [\n\t\t516\n\t],\n\t\"./components/FeatureInfo/FeatureInfoContainer.js\": [\n\t\t487\n\t],\n\t\"./components/FeatureInfo/FeaturePropsFilters.js\": [\n\t\t420\n\t],\n\t\"./components/FeatureInfo/FeaturePropsParsing.js\": [\n\t\t318\n\t],\n\t\"./components/HajkThemeProvider.js\": [\n\t\t378\n\t],\n\t\"./components/Introduction.js\": [\n\t\t489\n\t],\n\t\"./components/PanelHeader.js\": [\n\t\t453\n\t],\n\t\"./components/PluginControlButton.js\": [\n\t\t1174,\n\t\t176\n\t],\n\t\"./components/PluginWindows.js\": [\n\t\t491\n\t],\n\t\"./components/PopPanel.js\": [\n\t\t1353,\n\t\t177\n\t],\n\t\"./components/Search/MapViewModel.js\": [\n\t\t502\n\t],\n\t\"./components/Search/Search.js\": [\n\t\t473\n\t],\n\t\"./components/Search/SearchBar.js\": [\n\t\t492\n\t],\n\t\"./components/Search/SearchSettings.js\": [\n\t\t501\n\t],\n\t\"./components/Search/SearchTools.js\": [\n\t\t500\n\t],\n\t\"./components/Search/searchResults/SearchResultsContainer.js\": [\n\t\t493\n\t],\n\t\"./components/Search/searchResults/SearchResultsDataset.js\": [\n\t\t495\n\t],\n\t\"./components/Search/searchResults/SearchResultsDatasetFeature.js\": [\n\t\t496\n\t],\n\t\"./components/Search/searchResults/SearchResultsDatasetFeatureDetails.js\": [\n\t\t319\n\t],\n\t\"./components/Search/searchResults/SearchResultsDatasetSummary.js\": [\n\t\t498\n\t],\n\t\"./components/Search/searchResults/SearchResultsDownloadMenu.js\": [\n\t\t499\n\t],\n\t\"./components/Search/searchResults/SearchResultsList.js\": [\n\t\t494\n\t],\n\t\"./components/Search/searchResults/SearchResultsPreview.js\": [\n\t\t497\n\t],\n\t\"./components/Search/utils/FeatureStyle.js\": [\n\t\t272\n\t],\n\t\"./components/Search/utils/KmlExport.js\": [\n\t\t503\n\t],\n\t\"./components/Search/utils/XLSXExport.js\": [\n\t\t504\n\t],\n\t\"./components/SrShortcuts/SrShortcuts.js\": [\n\t\t477\n\t],\n\t\"./components/Table.js\": [\n\t\t1354,\n\t\t178\n\t],\n\t\"./components/Window.js\": [\n\t\t416\n\t],\n\t\"./controls/Attribution.js\": [\n\t\t510\n\t],\n\t\"./controls/Information.js\": [\n\t\t514\n\t],\n\t\"./controls/MapCleaner.js\": [\n\t\t511\n\t],\n\t\"./controls/MapResetter.js\": [\n\t\t512\n\t],\n\t\"./controls/MapSwitcher.js\": [\n\t\t513\n\t],\n\t\"./controls/PresetLinks.js\": [\n\t\t515\n\t],\n\t\"./controls/Rotate.js\": [\n\t\t507\n\t],\n\t\"./controls/ScaleLine.js\": [\n\t\t508\n\t],\n\t\"./controls/ThemeToggler.js\": [\n\t\t517\n\t],\n\t\"./controls/User.js\": [\n\t\t506\n\t],\n\t\"./controls/Zoom.js\": [\n\t\t505\n\t],\n\t\"./hooks/useCookieStatus.js\": [\n\t\t1225,\n\t\t179\n\t],\n\t\"./index.js\": [\n\t\t564\n\t],\n\t\"./models/AppModel.js\": [\n\t\t478\n\t],\n\t\"./models/Click.js\": [\n\t\t304\n\t],\n\t\"./models/Cookie.js\": [\n\t\t100\n\t],\n\t\"./models/Drag.js\": [\n\t\t1355,\n\t\t180\n\t],\n\t\"./models/DrawModel.js\": [\n\t\t1275,\n\t\t12,\n\t\t174,\n\t\t181\n\t],\n\t\"./models/Error.js\": [\n\t\t1356,\n\t\t182\n\t],\n\t\"./models/KmlModel.js\": [\n\t\t1276,\n\t\t7,\n\t\t146\n\t],\n\t\"./models/Plugin.js\": [\n\t\t480\n\t],\n\t\"./models/SearchModel.js\": [\n\t\t479\n\t],\n\t\"./models/SnapHelper.js\": [\n\t\t486\n\t],\n\t\"./models/layers/LayerInfo.js\": [\n\t\t234\n\t],\n\t\"./models/layers/VectorLayer.js\": [\n\t\t485\n\t],\n\t\"./models/layers/WMSLayer.js\": [\n\t\t483\n\t],\n\t\"./models/layers/WMTSLayer.js\": [\n\t\t484\n\t],\n\t\"./plugins/Anchor/Anchor.js\": [\n\t\t1357,\n\t\t49\n\t],\n\t\"./plugins/Anchor/AnchorModel.js\": [\n\t\t1278,\n\t\t183\n\t],\n\t\"./plugins/Anchor/AnchorView.js\": [\n\t\t1277,\n\t\t95\n\t],\n\t\"./plugins/BaseWindowPlugin.js\": [\n\t\t1175,\n\t\t85\n\t],\n\t\"./plugins/Bookmarks/Bookmarks.js\": [\n\t\t1358,\n\t\t50\n\t],\n\t\"./plugins/Bookmarks/BookmarksModel.js\": [\n\t\t1279,\n\t\t184\n\t],\n\t\"./plugins/Bookmarks/BookmarksView.js\": [\n\t\t1280,\n\t\t120\n\t],\n\t\"./plugins/Buffer/Buffer.js\": [\n\t\t1359,\n\t\t5,\n\t\t62,\n\t\t92\n\t],\n\t\"./plugins/Buffer/BufferModel.js\": [\n\t\t1282,\n\t\t5,\n\t\t185\n\t],\n\t\"./plugins/Buffer/BufferView.js\": [\n\t\t1281,\n\t\t86\n\t],\n\t\"./plugins/Collector/Collector.js\": [\n\t\t1360,\n\t\t1,\n\t\t51,\n\t\t26,\n\t\t106\n\t],\n\t\"./plugins/Collector/CollectorModel.js\": [\n\t\t1284,\n\t\t147\n\t],\n\t\"./plugins/Collector/CollectorView.js\": [\n\t\t1345,\n\t\t1,\n\t\t26,\n\t\t83\n\t],\n\t\"./plugins/Collector/components/CollectorForm.js\": [\n\t\t1283,\n\t\t1,\n\t\t59\n\t],\n\t\"./plugins/Collector/components/Page.js\": [\n\t\t1229,\n\t\t1,\n\t\t64\n\t],\n\t\"./plugins/Collector/components/Toolbar.js\": [\n\t\t1208,\n\t\t1,\n\t\t121\n\t],\n\t\"./plugins/Coordinates/Coordinates.js\": [\n\t\t1361,\n\t\t16,\n\t\t53\n\t],\n\t\"./plugins/Coordinates/CoordinatesModel.js\": [\n\t\t1286,\n\t\t186\n\t],\n\t\"./plugins/Coordinates/CoordinatesTransformRow.js\": [\n\t\t1231,\n\t\t16,\n\t\t187\n\t],\n\t\"./plugins/Coordinates/CoordinatesView.js\": [\n\t\t1285,\n\t\t16,\n\t\t148\n\t],\n\t\"./plugins/DialogWindowPlugin.js\": [\n\t\t1287,\n\t\t78\n\t],\n\t\"./plugins/DocumentHandler/DocumentHandler.js\": [\n\t\t1362,\n\t\t8,\n\t\t22,\n\t\t13,\n\t\t20,\n\t\t52\n\t],\n\t\"./plugins/DocumentHandler/DocumentHandlerModel.js\": [\n\t\t1291,\n\t\t65\n\t],\n\t\"./plugins/DocumentHandler/MapViewModel.js\": [\n\t\t1293,\n\t\t188\n\t],\n\t\"./plugins/DocumentHandler/documentSearch/DocumentSearchModel.js\": [\n\t\t1236,\n\t\t122\n\t],\n\t\"./plugins/DocumentHandler/documentSearch/MatchSearch.js\": [\n\t\t1212,\n\t\t189\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/Contents.js\": [\n\t\t1233,\n\t\t136\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/DocumentViewer.js\": [\n\t\t1288,\n\t\t8,\n\t\t87\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/DocumentWindowBase.js\": [\n\t\t1346,\n\t\t8,\n\t\t22,\n\t\t13,\n\t\t20\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/ImagePopupModal.js\": [\n\t\t1209,\n\t\t190\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/Progress.js\": [\n\t\t1290,\n\t\t191\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/ScrollToTop.js\": [\n\t\t1234,\n\t\t149\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/TableOfContents.js\": [\n\t\t1232,\n\t\t150\n\t],\n\t\"./plugins/DocumentHandler/documentWindow/TextArea.js\": [\n\t\t1211,\n\t\t192\n\t],\n\t\"./plugins/DocumentHandler/panelMenu/PanelList.js\": [\n\t\t1205,\n\t\t27\n\t],\n\t\"./plugins/DocumentHandler/panelMenu/PanelMenuContainerView.js\": [\n\t\t1292,\n\t\t8,\n\t\t88\n\t],\n\t\"./plugins/DocumentHandler/panelMenu/PanelMenuListItem.js\": [\n\t\t1228,\n\t\t27\n\t],\n\t\"./plugins/DocumentHandler/panelMenu/panelMenuUtils.js\": [\n\t\t1237,\n\t\t193\n\t],\n\t\"./plugins/DocumentHandler/printMenu/PrintList.js\": [\n\t\t1204,\n\t\t28\n\t],\n\t\"./plugins/DocumentHandler/printMenu/PrintListItem.js\": [\n\t\t1210,\n\t\t28\n\t],\n\t\"./plugins/DocumentHandler/printMenu/PrintSubList.js\": [\n\t\t1363,\n\t\t124\n\t],\n\t\"./plugins/DocumentHandler/printMenu/PrintWindow.js\": [\n\t\t1347,\n\t\t13,\n\t\t135\n\t],\n\t\"./plugins/DocumentHandler/printMenu/TableOfContents.js\": [\n\t\t1289,\n\t\t151\n\t],\n\t\"./plugins/DocumentHandler/utils/ContentComponentFactory.js\": [\n\t\t1227,\n\t\t123\n\t],\n\t\"./plugins/DocumentHandler/utils/helpers.js\": [\n\t\t1184,\n\t\t194\n\t],\n\t\"./plugins/DocumentHandler/utils/htmlToMaterialUiParser.js\": [\n\t\t1235,\n\t\t153\n\t],\n\t\"./plugins/DocumentHandler/utils/stateConverter.js\": [\n\t\t1226,\n\t\t152\n\t],\n\t\"./plugins/Draw/Draw.js\": [\n\t\t1364,\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t7,\n\t\t46\n\t],\n\t\"./plugins/Draw/DrawModel.js\": [\n\t\t1295,\n\t\t7,\n\t\t12,\n\t\t154\n\t],\n\t\"./plugins/Draw/DrawView.js\": [\n\t\t1294,\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t96\n\t],\n\t\"./plugins/Draw/components/Symbology.js\": [\n\t\t1238,\n\t\t2,\n\t\t3,\n\t\t195\n\t],\n\t\"./plugins/Dummy/Dummy.js\": [\n\t\t1365,\n\t\t57\n\t],\n\t\"./plugins/Dummy/DummyModel.js\": [\n\t\t1296,\n\t\t196\n\t],\n\t\"./plugins/Dummy/DummyView.js\": [\n\t\t1297,\n\t\t155\n\t],\n\t\"./plugins/Edit/Edit.js\": [\n\t\t1366,\n\t\t1,\n\t\t12,\n\t\t23,\n\t\t118,\n\t\t75\n\t],\n\t\"./plugins/Edit/EditModel.js\": [\n\t\t1299,\n\t\t12,\n\t\t156\n\t],\n\t\"./plugins/Edit/EditView.js\": [\n\t\t1298,\n\t\t1,\n\t\t23,\n\t\t137\n\t],\n\t\"./plugins/Edit/components/AttributeEditor.js\": [\n\t\t1240,\n\t\t197\n\t],\n\t\"./plugins/Edit/components/Toolbar.js\": [\n\t\t1239,\n\t\t1,\n\t\t97\n\t],\n\t\"./plugins/Export/Export.js\": [\n\t\t1367,\n\t\t69,\n\t\t93\n\t],\n\t\"./plugins/Export/ExportModel.js\": [\n\t\t1301,\n\t\t138\n\t],\n\t\"./plugins/Export/components/ExportPdfSettings.js\": [\n\t\t1300,\n\t\t125\n\t],\n\t\"./plugins/Fir/Fir.js\": [\n\t\t1368,\n\t\t0,\n\t\t4,\n\t\t5,\n\t\t7,\n\t\t38\n\t],\n\t\"./plugins/Fir/FirExportEdpView.js\": [\n\t\t1213,\n\t\t98\n\t],\n\t\"./plugins/Fir/FirExportPropertyListView.js\": [\n\t\t1214,\n\t\t99\n\t],\n\t\"./plugins/Fir/FirExportResidentListView.js\": [\n\t\t1189,\n\t\t89\n\t],\n\t\"./plugins/Fir/FirExportView.js\": [\n\t\t1242,\n\t\t66\n\t],\n\t\"./plugins/Fir/FirIcons.js\": [\n\t\t1178,\n\t\t198\n\t],\n\t\"./plugins/Fir/FirImport.js\": [\n\t\t1245,\n\t\t7,\n\t\t199\n\t],\n\t\"./plugins/Fir/FirLayerController.js\": [\n\t\t1304,\n\t\t5,\n\t\t139\n\t],\n\t\"./plugins/Fir/FirModel.js\": [\n\t\t1302,\n\t\t200\n\t],\n\t\"./plugins/Fir/FirSearchNeighborView.js\": [\n\t\t1243,\n\t\t0,\n\t\t5,\n\t\t67\n\t],\n\t\"./plugins/Fir/FirSearchResultItemView.js\": [\n\t\t1215,\n\t\t201\n\t],\n\t\"./plugins/Fir/FirSearchResultsView.js\": [\n\t\t1244,\n\t\t11,\n\t\t126\n\t],\n\t\"./plugins/Fir/FirSearchView.js\": [\n\t\t1241,\n\t\t15,\n\t\t108\n\t],\n\t\"./plugins/Fir/FirStyles.js\": [\n\t\t1196,\n\t\t202\n\t],\n\t\"./plugins/Fir/FirToolbarView.js\": [\n\t\t1194,\n\t\t107\n\t],\n\t\"./plugins/Fir/FirView.js\": [\n\t\t1303,\n\t\t0,\n\t\t4,\n\t\t5,\n\t\t11,\n\t\t45\n\t],\n\t\"./plugins/Fir/FirWfsService.js\": [\n\t\t1270,\n\t\t203\n\t],\n\t\"./plugins/Fme/Fme.js\": [\n\t\t1369,\n\t\t1,\n\t\t58\n\t],\n\t\"./plugins/Fme/FmeModel.js\": [\n\t\t1305,\n\t\t210\n\t],\n\t\"./plugins/Fme/FmeView.js\": [\n\t\t1306,\n\t\t1,\n\t\t211\n\t],\n\t\"./plugins/FmeServer/FmeServer.js\": [\n\t\t1370,\n\t\t0,\n\t\t25,\n\t\t105,\n\t\t24,\n\t\t94\n\t],\n\t\"./plugins/FmeServer/FmeServerView.js\": [\n\t\t1348,\n\t\t0,\n\t\t25,\n\t\t24\n\t],\n\t\"./plugins/FmeServer/components/DrawToolbox.js\": [\n\t\t1307,\n\t\t157\n\t],\n\t\"./plugins/FmeServer/components/InformationWrapper.js\": [\n\t\t1200,\n\t\t204\n\t],\n\t\"./plugins/FmeServer/components/ListBoxSelector.js\": [\n\t\t1246,\n\t\t205\n\t],\n\t\"./plugins/FmeServer/components/OrderPanel.js\": [\n\t\t1308,\n\t\t127\n\t],\n\t\"./plugins/FmeServer/components/ProductParameters.js\": [\n\t\t1309,\n\t\t0,\n\t\t109\n\t],\n\t\"./plugins/FmeServer/constants/index.js\": [\n\t\t1197,\n\t\t206\n\t],\n\t\"./plugins/FmeServer/hooks/useInterval.js\": [\n\t\t1311,\n\t\t207\n\t],\n\t\"./plugins/FmeServer/hooks/useProductParameters.js\": [\n\t\t1310,\n\t\t208\n\t],\n\t\"./plugins/FmeServer/models/FmeServerModel.js\": [\n\t\t1312,\n\t\t209\n\t],\n\t\"./plugins/FmeServer/models/MapViewModel.js\": [\n\t\t1313,\n\t\t158\n\t],\n\t\"./plugins/GeosuiteExport/GeosuiteExport.js\": [\n\t\t1371,\n\t\t29,\n\t\t19,\n\t\t30,\n\t\t31,\n\t\t76\n\t],\n\t\"./plugins/GeosuiteExport/GeosuiteExportModel.js\": [\n\t\t1349,\n\t\t29,\n\t\t31\n\t],\n\t\"./plugins/GeosuiteExport/GeosuiteExportView.js\": [\n\t\t1350,\n\t\t19,\n\t\t30\n\t],\n\t\"./plugins/GeosuiteExport/components/LinkItem.js\": [\n\t\t1372,\n\t\t212\n\t],\n\t\"./plugins/GeosuiteExport/components/ProductList.js\": [\n\t\t1314,\n\t\t141\n\t],\n\t\"./plugins/InfoDialog/InfoDialog.js\": [\n\t\t1373,\n\t\t63\n\t],\n\t\"./plugins/Informative/Informative.js\": [\n\t\t1374,\n\t\t47\n\t],\n\t\"./plugins/Informative/InformativeModel.js\": [\n\t\t1316,\n\t\t213\n\t],\n\t\"./plugins/Informative/InformativeView.js\": [\n\t\t1315,\n\t\t70\n\t],\n\t\"./plugins/Informative/components/BreadCrumbs.js\": [\n\t\t1247,\n\t\t214\n\t],\n\t\"./plugins/Kir/Kir.js\": [\n\t\t1375,\n\t\t0,\n\t\t4,\n\t\t5,\n\t\t7,\n\t\t40\n\t],\n\t\"./plugins/Kir/KirExportView.js\": [\n\t\t1249,\n\t\t79\n\t],\n\t\"./plugins/Kir/KirLayerController.js\": [\n\t\t1317,\n\t\t5,\n\t\t140\n\t],\n\t\"./plugins/Kir/KirModel.js\": [\n\t\t1318,\n\t\t215\n\t],\n\t\"./plugins/Kir/KirSearchResultItemView.js\": [\n\t\t1216,\n\t\t216\n\t],\n\t\"./plugins/Kir/KirSearchResultsView.js\": [\n\t\t1250,\n\t\t11,\n\t\t159\n\t],\n\t\"./plugins/Kir/KirSearchView.js\": [\n\t\t1248,\n\t\t0,\n\t\t15,\n\t\t110\n\t],\n\t\"./plugins/Kir/KirView.js\": [\n\t\t1319,\n\t\t0,\n\t\t4,\n\t\t11,\n\t\t15,\n\t\t100\n\t],\n\t\"./plugins/Kir/KirWfsService.js\": [\n\t\t1320,\n\t\t217\n\t],\n\t\"./plugins/LayerSwitcher/LayerSwitcher.js\": [\n\t\t1376,\n\t\t0,\n\t\t1,\n\t\t4,\n\t\t14,\n\t\t39\n\t],\n\t\"./plugins/LayerSwitcher/LayerSwitcherModel.js\": [\n\t\t1322,\n\t\t218\n\t],\n\t\"./plugins/LayerSwitcher/LayerSwitcherView.js\": [\n\t\t1321,\n\t\t0,\n\t\t1,\n\t\t4,\n\t\t14,\n\t\t43\n\t],\n\t\"./plugins/LayerSwitcher/components/BackgroundSwitcher.js\": [\n\t\t1267,\n\t\t0,\n\t\t9,\n\t\t111\n\t],\n\t\"./plugins/LayerSwitcher/components/BreadCrumb.js\": [\n\t\t1217,\n\t\t128\n\t],\n\t\"./plugins/LayerSwitcher/components/BreadCrumbs.js\": [\n\t\t1252,\n\t\t1,\n\t\t14,\n\t\t160\n\t],\n\t\"./plugins/LayerSwitcher/components/CQLFilter.js\": [\n\t\t1202,\n\t\t142\n\t],\n\t\"./plugins/LayerSwitcher/components/DownloadLink.js\": [\n\t\t1191,\n\t\t161\n\t],\n\t\"./plugins/LayerSwitcher/components/LayerGroup.js\": [\n\t\t1251,\n\t\t0,\n\t\t9,\n\t\t71\n\t],\n\t\"./plugins/LayerSwitcher/components/LayerGroupItem.js\": [\n\t\t1206,\n\t\t0,\n\t\t9,\n\t\t173\n\t],\n\t\"./plugins/LayerSwitcher/components/LayerItem.js\": [\n\t\t1195,\n\t\t0,\n\t\t9,\n\t\t129\n\t],\n\t\"./plugins/LayerSwitcher/components/LayerSettings.js\": [\n\t\t1190,\n\t\t0,\n\t\t112\n\t],\n\t\"./plugins/LayerSwitcher/components/VectorFilter.js\": [\n\t\t1201,\n\t\t219\n\t],\n\t\"./plugins/Location/CustomControlButtonView.js\": [\n\t\t1323,\n\t\t130\n\t],\n\t\"./plugins/Location/Location.js\": [\n\t\t1377,\n\t\t74,\n\t\t84\n\t],\n\t\"./plugins/Location/LocationModel.js\": [\n\t\t1324,\n\t\t162\n\t],\n\t\"./plugins/Location/LocationView.js\": [\n\t\t1325,\n\t\t163\n\t],\n\t\"./plugins/Measure/Measure.js\": [\n\t\t1378,\n\t\t117,\n\t\t77\n\t],\n\t\"./plugins/Measure/MeasureModel.js\": [\n\t\t1327,\n\t\t164\n\t],\n\t\"./plugins/Measure/MeasureView.js\": [\n\t\t1326,\n\t\t220\n\t],\n\t\"./plugins/Print/AdvancedOptions.js\": [\n\t\t1253,\n\t\t2,\n\t\t3,\n\t\t143\n\t],\n\t\"./plugins/Print/GeneralOptions.js\": [\n\t\t1254,\n\t\t221\n\t],\n\t\"./plugins/Print/Print.js\": [\n\t\t1379,\n\t\t2,\n\t\t3,\n\t\t4,\n\t\t18,\n\t\t41\n\t],\n\t\"./plugins/Print/PrintDialog.js\": [\n\t\t1255,\n\t\t165\n\t],\n\t\"./plugins/Print/PrintModel.js\": [\n\t\t1328,\n\t\t18,\n\t\t90\n\t],\n\t\"./plugins/Print/PrintView.js\": [\n\t\t1329,\n\t\t2,\n\t\t3,\n\t\t4,\n\t\t80\n\t],\n\t\"./plugins/Routing/Routing.js\": [\n\t\t1380,\n\t\t21,\n\t\t54\n\t],\n\t\"./plugins/Routing/RoutingModel.js\": [\n\t\t1342,\n\t\t166\n\t],\n\t\"./plugins/Routing/RoutingView.js\": [\n\t\t1330,\n\t\t21,\n\t\t222\n\t],\n\t\"./plugins/Sketch/Sketch.js\": [\n\t\t1381,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t7,\n\t\t37\n\t],\n\t\"./plugins/Sketch/components/ActivityMenu.js\": [\n\t\t1256,\n\t\t101\n\t],\n\t\"./plugins/Sketch/components/DrawTypeSelector.js\": [\n\t\t1218,\n\t\t102\n\t],\n\t\"./plugins/Sketch/components/FeatureTextSetter.js\": [\n\t\t1220,\n\t\t223\n\t],\n\t\"./plugins/Sketch/components/Information.js\": [\n\t\t1180,\n\t\t224\n\t],\n\t\"./plugins/Sketch/components/UploadDialog.js\": [\n\t\t1221,\n\t\t168\n\t],\n\t\"./plugins/Sketch/components/featureStyle/FeatureStyleAccordion.js\": [\n\t\t1219,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t60\n\t],\n\t\"./plugins/Sketch/components/featureStyle/FeatureStyleEditor.js\": [\n\t\t1222,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t10,\n\t\t225\n\t],\n\t\"./plugins/Sketch/components/featureStyle/FeatureStyleSelector.js\": [\n\t\t1198,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t56\n\t],\n\t\"./plugins/Sketch/components/featureStyle/StrokeTypeSelector.js\": [\n\t\t1192,\n\t\t103\n\t],\n\t\"./plugins/Sketch/constants/index.js\": [\n\t\t1176,\n\t\t113\n\t],\n\t\"./plugins/Sketch/models/SketchModel.js\": [\n\t\t1332,\n\t\t104\n\t],\n\t\"./plugins/Sketch/views/AddView.js\": [\n\t\t1257,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t10,\n\t\t131\n\t],\n\t\"./plugins/Sketch/views/DeleteView.js\": [\n\t\t1260,\n\t\t132\n\t],\n\t\"./plugins/Sketch/views/EditView.js\": [\n\t\t1262,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t10,\n\t\t144\n\t],\n\t\"./plugins/Sketch/views/MoveView.js\": [\n\t\t1261,\n\t\t167\n\t],\n\t\"./plugins/Sketch/views/SaveView.js\": [\n\t\t1258,\n\t\t81\n\t],\n\t\"./plugins/Sketch/views/SettingsView.js\": [\n\t\t1263,\n\t\t91\n\t],\n\t\"./plugins/Sketch/views/SketchView.js\": [\n\t\t1331,\n\t\t0,\n\t\t2,\n\t\t3,\n\t\t10,\n\t\t42\n\t],\n\t\"./plugins/Sketch/views/UploadView.js\": [\n\t\t1259,\n\t\t68\n\t],\n\t\"./plugins/StreetView/StreetView.js\": [\n\t\t1382,\n\t\t55\n\t],\n\t\"./plugins/StreetView/StreetViewModel.js\": [\n\t\t1334,\n\t\t169\n\t],\n\t\"./plugins/StreetView/StreetViewView.js\": [\n\t\t1333,\n\t\t226\n\t],\n\t\"./plugins/Suggest/Suggest.js\": [\n\t\t1383,\n\t\t133\n\t],\n\t\"./plugins/TimeSlider/TimeSlider.js\": [\n\t\t1384,\n\t\t0,\n\t\t48\n\t],\n\t\"./plugins/TimeSlider/TimeSliderView.js\": [\n\t\t1335,\n\t\t0,\n\t\t82\n\t],\n\t\"./plugins/TimeSlider/components/TimeSliderSettings.js\": [\n\t\t1264,\n\t\t145\n\t],\n\t\"./plugins/vtsearch/MapViewModel.js\": [\n\t\t1336,\n\t\t227\n\t],\n\t\"./plugins/vtsearch/SearchModel.js\": [\n\t\t1337,\n\t\t228\n\t],\n\t\"./plugins/vtsearch/SearchResultList/AdvancedAttributeTable.js\": [\n\t\t1223,\n\t\t6,\n\t\t134\n\t],\n\t\"./plugins/vtsearch/SearchResultList/AttributeTable.js\": [\n\t\t1193,\n\t\t6,\n\t\t170\n\t],\n\t\"./plugins/vtsearch/SearchResultList/PanelToolbox.js\": [\n\t\t1265,\n\t\t171\n\t],\n\t\"./plugins/vtsearch/SearchResultList/SearchResultListContainer.js\": [\n\t\t1338,\n\t\t4,\n\t\t6,\n\t\t72\n\t],\n\t\"./plugins/vtsearch/SearchResultList/SummaryTable.js\": [\n\t\t1203,\n\t\t6,\n\t\t172\n\t],\n\t\"./plugins/vtsearch/SearchResultList/TabPanel.js\": [\n\t\t1266,\n\t\t6,\n\t\t114\n\t],\n\t\"./plugins/vtsearch/SearchResultList/VirtualizedTable.js\": [\n\t\t1185,\n\t\t6,\n\t\t229\n\t],\n\t\"./plugins/vtsearch/SearchViews/Journeys.js\": [\n\t\t1339,\n\t\t17,\n\t\t115\n\t],\n\t\"./plugins/vtsearch/SearchViews/Lines.js\": [\n\t\t1340,\n\t\t116\n\t],\n\t\"./plugins/vtsearch/SearchViews/Stops.js\": [\n\t\t1341,\n\t\t73\n\t],\n\t\"./plugins/vtsearch/vtsearch.js\": [\n\t\t1385,\n\t\t4,\n\t\t6,\n\t\t17,\n\t\t61,\n\t\t44\n\t],\n\t\"./reportWebVitals.js\": [\n\t\t518\n\t],\n\t\"./utils/ArraySort.js\": [\n\t\t1386,\n\t\t230\n\t],\n\t\"./utils/ConfigMapper.js\": [\n\t\t481\n\t],\n\t\"./utils/CoordinateSystemLoader.js\": [\n\t\t482\n\t],\n\t\"./utils/DeepMerge.js\": [\n\t\t258\n\t],\n\t\"./utils/Delay.js\": [\n\t\t422\n\t],\n\t\"./utils/FetchWrapper.js\": [\n\t\t65\n\t],\n\t\"./utils/IsMobile.js\": [\n\t\t95\n\t],\n\t\"./utils/KMLWriter.js\": [\n\t\t429\n\t],\n\t\"./utils/LocalStorageHelper.js\": [\n\t\t230\n\t],\n\t\"./utils/StringCommaCoder.js\": [\n\t\t149\n\t],\n\t\"./utils/Validator.js\": [\n\t\t421\n\t],\n\t\"./utils/customComponentsForReactMarkdown.js\": [\n\t\t271\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {\n\t\treturn __webpack_require__(id);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = 981;\nmodule.exports = webpackAsyncContext;"],"sourceRoot":""}