UNPKG

@finos/legend-lego

Version:
378 lines 34.2 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * Copyright (c) 2025-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { AnchorLinkIcon, BasePopover, ChevronDownIcon, ChevronRightIcon, ClockIcon, CogIcon, ControlledDropdownMenu, FilterIcon, InfoCircleIcon, MenuContent, MenuContentItem, MoreVerticalIcon, PlayIcon, SearchIcon, TimesIcon, Tooltip, clsx, TreeView, PackageIcon, CheckSquareIcon, MinusSquareIcon, EmptySquareIcon, CaretRightIcon, CaretLeftIcon, } from '@finos/legend-art'; import { CORE_PURE_PATH, ELEMENT_PATH_DELIMITER, getMultiplicityDescription, MILESTONING_STEREOTYPE, PROPERTY_ACCESSOR, } from '@finos/legend-graph'; import { AssociationDocumentationEntry, BasicDocumentationEntry, ClassDocumentationEntry, EnumerationDocumentationEntry, ModelDocumentationEntry, PropertyDocumentationEntry, } from './ModelDocumentationAnalysis.js'; import { debounce, isNonNullable, prettyCONSTName } from '@finos/legend-shared'; import { DataGrid, } from '../data-grid/DataGrid.js'; import { useApplicationStore, useCommands, } from '@finos/legend-application'; import { observer } from 'mobx-react-lite'; import { checkFilterTreeNode, ModelsDocumentationFilterTreeElementNodeData, ModelsDocumentationFilterTreeNodeCheckType, ModelsDocumentationFilterTreePackageNodeData, ModelsDocumentationFilterTreeRootNodeData, ModelsDocumentationFilterTreeTypeNodeData, uncheckAllFilterTree, uncheckFilterTreeNode, } from './ModelDocumentationState.js'; import { FuzzySearchAdvancedConfigMenu } from '../application/FuzzySearchAdvancedConfigMenu.js'; import { useEffect, useMemo, useRef } from 'react'; export const getMilestoningLabel = (val) => { switch (val) { case MILESTONING_STEREOTYPE.BITEMPORAL: return 'Bi-temporal'; case MILESTONING_STEREOTYPE.BUSINESS_TEMPORAL: return 'Business Temporal'; case MILESTONING_STEREOTYPE.PROCESSING_TEMPORAL: return 'Processing Temporal'; default: return undefined; } }; const ElementInfoTooltip = (props) => { const { entry, children } = props; return (_jsx(Tooltip, { arrow: false, placement: "bottom-end", disableInteractive: true, classes: { tooltip: 'models-documentation__tooltip', tooltipPlacementRight: 'models-documentation__tooltip--right', }, slotProps: { transition: { // disable transition // NOTE: somehow, this is the only workaround we have, if for example // we set `appear = true`, the tooltip will jump out of position timeout: 0, }, }, title: _jsxs("div", { className: "models-documentation__tooltip__content", children: [_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Name" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.name })] }), _jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Path" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.path })] }), entry instanceof ClassDocumentationEntry && entry.milestoning !== undefined && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Milestoning" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: getMilestoningLabel(entry.milestoning) })] }))] }), children: children })); }; const PropertyInfoTooltip = (props) => { const { entry, elementEntry, children } = props; return (_jsx(Tooltip, { arrow: false, placement: "bottom-end", disableInteractive: true, classes: { tooltip: 'models-documentation__tooltip', tooltipPlacementRight: 'models-documentation__tooltip--right', }, slotProps: { transition: { // disable transition // NOTE: somehow, this is the only workaround we have, if for example // we set `appear = true`, the tooltip will jump out of position timeout: 0, }, }, title: _jsxs("div", { className: "models-documentation__tooltip__content", children: [_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Name" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.name })] }), _jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Owner" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: elementEntry.path })] }), entry.type && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Type" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.type })] })), entry.multiplicity && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Multiplicity" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: getMultiplicityDescription(entry.multiplicity) })] })), entry.milestoning && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Milestoning" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: getMilestoningLabel(entry.milestoning) })] }))] }), children: children })); }; export const ElementContentCellRenderer = observer((params) => { const { data, modelsDocumentationState } = params; const applicationStore = useApplicationStore(); const showHumanizedForm = modelsDocumentationState.showHumanizedForm; if (!data) { return null; } const copyPath = () => { applicationStore.clipboardService .copyTextToClipboard(data.elementEntry.path) .catch(applicationStore.alertUnhandledError); }; const label = showHumanizedForm ? prettyCONSTName(data.elementEntry.name) : data.elementEntry.name; if (data.elementEntry instanceof ClassDocumentationEntry) { return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Class: ${data.elementEntry.path}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--class", children: "C" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label }), data.elementEntry.milestoning && (_jsx("div", { className: "models-documentation__grid__cell__label__milestoning-badge", title: `Milestoning: ${getMilestoningLabel(data.elementEntry.milestoning)}`, children: _jsx(ClockIcon, {}) }))] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(ElementInfoTooltip, { entry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' }, elevation: 7, }, content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }), _jsx(MenuContentItem, { disabled: true, children: "Preview Data" })] }), children: _jsx(MoreVerticalIcon, {}) })] })] })); } else if (data.elementEntry instanceof EnumerationDocumentationEntry) { return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Enumeration: ${data.elementEntry.path}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--enumeration", children: "E" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label })] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(ElementInfoTooltip, { entry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' }, elevation: 7, }, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }) }), children: _jsx(MoreVerticalIcon, {}) })] })] })); } else if (data.elementEntry instanceof AssociationDocumentationEntry) { return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Association: ${data.elementEntry.path}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--association", children: "A" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label })] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(ElementInfoTooltip, { entry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' }, elevation: 7, }, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }) }), children: _jsx(MoreVerticalIcon, {}) })] })] })); } return null; }); export const SubElementDocContentCellRenderer = observer((params) => { const { data, modelsDocumentationState } = params; const applicationStore = useApplicationStore(); const showHumanizedForm = modelsDocumentationState.showHumanizedForm; if (!data) { return null; } let label = showHumanizedForm ? prettyCONSTName(data.text) : data.text; const isDerivedProperty = label.endsWith('()'); label = isDerivedProperty ? label.slice(0, -2) : label; if (data.entry instanceof ModelDocumentationEntry) { return null; } else if (data.entry instanceof PropertyDocumentationEntry) { return (_jsxs("div", { className: "models-documentation__grid__cell", title: `${isDerivedProperty ? 'Derived property' : 'Property'}: ${data.elementEntry.path}${PROPERTY_ACCESSOR}${data.entry.name}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--property", children: "P" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label }), isDerivedProperty && (_jsx("div", { className: "models-documentation__grid__cell__label__derived-property-badge", children: "()" })), data.entry.milestoning && (_jsx("div", { className: "models-documentation__grid__cell__label__milestoning-badge", title: `Milestoning: ${getMilestoningLabel(data.entry.milestoning)}`, children: _jsx(ClockIcon, {}) }))] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(PropertyInfoTooltip, { entry: data.entry, elementEntry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' }, elevation: 7, }, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { disabled: true, children: "Preview Data" }) }), children: _jsx(MoreVerticalIcon, {}) })] })] })); } else if (data.entry instanceof BasicDocumentationEntry) { const copyValue = () => { applicationStore.clipboardService .copyTextToClipboard(data.elementEntry.path + PROPERTY_ACCESSOR + data.entry.name) .catch(applicationStore.alertUnhandledError); }; return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Enum: ${data.elementEntry.path}${PROPERTY_ACCESSOR}${data.entry.name}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--enum", children: "e" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label })] }), _jsx("div", { className: "models-documentation__grid__cell__actions", children: _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' }, elevation: 7, }, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: copyValue, children: "Copy Value" }) }), children: _jsx(MoreVerticalIcon, {}) }) })] })); } return null; }); export const ElementDocumentationCellRenderer = (params) => { const data = params.data; if (!data) { return null; } return data.documentation.trim() ? (data.documentation) : (_jsx("div", { className: "models-documentation__grid__empty-cell", children: "No documentation provided" })); }; export const ModelsDocumentationGridPanel = observer((props) => { const { modelsDocumentationState, applicationStore } = props; const documentationState = modelsDocumentationState; const darkMode = !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled; return (_jsx("div", { className: clsx('models-documentation__viewer__grid', { 'models-documentation__grid': documentationState.showFilterPanel, 'ag-theme-balham': !darkMode, 'ag-theme-balham-dark': darkMode, }), children: _jsx(DataGrid, { rowData: documentationState.filteredSearchResults, overlayNoRowsTemplate: `<div class="models-documentation__grid--empty">No documentation found</div>`, // highlight element row getRowClass: (params) => params.data?.entry instanceof ModelDocumentationEntry ? 'models-documentation__grid__element-row' : undefined, alwaysShowVerticalScroll: true, gridOptions: { suppressScrollOnNewData: true, getRowId: (rowData) => rowData.data.uuid, }, suppressFieldDotNotation: true, columnDefs: [ { minWidth: 50, sortable: true, resizable: true, cellRendererParams: { modelsDocumentationState, applicationStore, }, cellRenderer: ElementContentCellRenderer, headerName: 'Model', flex: 1, }, { minWidth: 50, sortable: false, resizable: true, cellRendererParams: { modelsDocumentationState, applicationStore, }, cellRenderer: SubElementDocContentCellRenderer, headerName: '', flex: 1, }, { minWidth: 50, sortable: false, resizable: false, headerClass: 'models-documentation__grid__last-column-header', cellRenderer: ElementDocumentationCellRenderer, headerName: 'Documentation', flex: 1, wrapText: true, autoHeight: true, }, ] }) })); }); export const getFilterTreeNodeIcon = (node) => { if (node instanceof ModelsDocumentationFilterTreeElementNodeData) { if (node.typePath === CORE_PURE_PATH.CLASS) { return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--class", children: "C" })); } else if (node.typePath === CORE_PURE_PATH.ENUMERATION) { return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--enumeration", children: "E" })); } else if (node.typePath === CORE_PURE_PATH.ASSOCIATION) { return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--association", children: "A" })); } } else if (node instanceof ModelsDocumentationFilterTreePackageNodeData) { return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--package", children: _jsx(PackageIcon, {}) })); } else if (node instanceof ModelsDocumentationFilterTreeTypeNodeData) { switch (node.typePath) { case CORE_PURE_PATH.CLASS: return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--class", children: "C" })); case CORE_PURE_PATH.ENUMERATION: return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--enumeration", children: "E" })); case CORE_PURE_PATH.ASSOCIATION: return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--association", children: "A" })); default: return undefined; } } return undefined; }; const getFilterNodeCount = (node, documentationState) => { if (node instanceof ModelsDocumentationFilterTreeElementNodeData) { return documentationState.searchResults.filter((result) => node.elementPath === result.elementEntry.path).length; } else if (node instanceof ModelsDocumentationFilterTreePackageNodeData) { return documentationState.searchResults.filter((result) => node.packagePath === result.elementEntry.path || result.elementEntry.path.startsWith(`${node.packagePath}${ELEMENT_PATH_DELIMITER}`)).length; } else if (node instanceof ModelsDocumentationFilterTreeTypeNodeData) { return node.typePath === CORE_PURE_PATH.CLASS ? documentationState.searchResults.filter((entry) => entry.elementEntry instanceof ClassDocumentationEntry).length : node.typePath === CORE_PURE_PATH.ENUMERATION ? documentationState.searchResults.filter((entry) => entry.elementEntry instanceof EnumerationDocumentationEntry).length : node.typePath === CORE_PURE_PATH.ASSOCIATION ? documentationState.searchResults.filter((entry) => entry.elementEntry instanceof AssociationDocumentationEntry).length : undefined; } else if (node instanceof ModelsDocumentationFilterTreeRootNodeData) { return documentationState.searchResults.length; } return undefined; }; const ModelsDocumentationFilterTreeNodeContainer = observer((props) => { const { node, level, innerProps } = props; const { documentationState, refreshTreeData, uncheckTree, updateFilter } = innerProps; const isExpandable = Boolean(node.childrenIds.length); const expandIcon = isExpandable ? (node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}))) : (_jsx("div", {})); const checkerIcon = node.checkType === ModelsDocumentationFilterTreeNodeCheckType.CHECKED ? (_jsx(CheckSquareIcon, {})) : node.checkType === ModelsDocumentationFilterTreeNodeCheckType.PARTIALLY_CHECKED ? (_jsx(MinusSquareIcon, {})) : (_jsx(EmptySquareIcon, {})); const nodeCount = getFilterNodeCount(node, documentationState); const toggleChecker = (event) => { event.stopPropagation(); if (node.checkType === ModelsDocumentationFilterTreeNodeCheckType.CHECKED) { uncheckFilterTreeNode(node); } else { checkFilterTreeNode(node); } refreshTreeData(); updateFilter(); }; const toggleExpandNode = (event) => { event.stopPropagation(); if (isExpandable) { node.setIsOpen(!node.isOpen); refreshTreeData(); } }; const onNodeClick = () => { uncheckTree(); checkFilterTreeNode(node); if (isExpandable && !node.isOpen) { node.setIsOpen(true); } refreshTreeData(); updateFilter(); }; return (_jsxs("div", { className: "tree-view__node__container models-documentation__filter__tree__node__container", style: { paddingLeft: `${(level - 1) * 1.4}rem`, display: 'flex', }, onClick: onNodeClick, children: [_jsx("div", { className: "models-documentation__filter__tree__node__expand-icon", onClick: toggleExpandNode, children: expandIcon }), _jsx("div", { className: "models-documentation__filter__tree__node__checker", onClick: toggleChecker, children: checkerIcon }), getFilterTreeNodeIcon(node), _jsx("div", { className: "tree-view__node__label models-documentation__filter__tree__node__label", children: node.label }), nodeCount !== undefined && (_jsx("div", { className: "tree-view__node__label models-documentation__filter__tree__node__count", children: nodeCount }))] })); }); const ModelsDocumentationFilterPanel = observer((props) => { const { modelsDocumentationState } = props; const documentationState = modelsDocumentationState; const resetAll = () => documentationState.resetAllFilters(); const resetTypeFilter = () => documentationState.resetTypeFilter(); const resetPackageFilter = () => documentationState.resetPackageFilter(); return (_jsxs("div", { className: "models-documentation__filter__panel", children: [_jsx("div", { className: "models-documentation__filter__group", children: _jsxs("div", { className: "models-documentation__filter__group__header", children: [_jsx("div", { className: "models-documentation__filter__group__header__label", children: "Filter" }), _jsx("div", { className: "models-documentation__filter__group__header__actions", children: _jsx("button", { className: "models-documentation__filter__group__header__reset", tabIndex: -1, disabled: !documentationState.isFilterCustomized, onClick: resetAll, children: "Reset All" }) })] }) }), _jsxs("div", { className: "models-documentation__filter__group models-documentation__filter__group--by-type", children: [_jsxs("div", { className: "models-documentation__filter__group__header", children: [_jsx("div", { className: "models-documentation__filter__group__header__label", children: "Filter by Type" }), _jsx("div", { className: "models-documentation__filter__group__header__actions", children: _jsx("button", { className: "models-documentation__filter__group__header__reset", tabIndex: -1, disabled: !documentationState.isTypeFilterCustomized, onClick: resetTypeFilter, children: "Reset" }) })] }), _jsx("div", { className: "models-documentation__filter__group__content", children: _jsx(TreeView, { components: { TreeNodeContainer: ModelsDocumentationFilterTreeNodeContainer, }, treeData: documentationState.typeFilterTreeData, getChildNodes: (node) => node.childrenIds .map((id) => documentationState.typeFilterTreeData.nodes.get(id)) .filter(isNonNullable) .sort((a, b) => a.label.localeCompare(b.label)), innerProps: { documentationState, refreshTreeData: () => documentationState.resetTypeFilterTreeData(), uncheckTree: () => uncheckAllFilterTree(documentationState.typeFilterTreeData), updateFilter: () => documentationState.updateTypeFilter(), } }) })] }), _jsxs("div", { className: "models-documentation__filter__group models-documentation__filter__group--by-package", children: [_jsxs("div", { className: "models-documentation__filter__group__header", children: [_jsx("div", { className: "models-documentation__filter__group__header__label", children: "Filter by Package" }), _jsx("div", { className: "models-documentation__filter__group__header__actions", children: _jsx("button", { className: "models-documentation__filter__group__header__reset", tabIndex: -1, disabled: !documentationState.isPackageFilterCustomized, onClick: resetPackageFilter, children: "Reset" }) })] }), _jsx("div", { className: "models-documentation__filter__group__content", children: _jsx(TreeView, { components: { TreeNodeContainer: ModelsDocumentationFilterTreeNodeContainer, }, treeData: documentationState.packageFilterTreeData, getChildNodes: (node) => node.childrenIds .map((id) => documentationState.packageFilterTreeData.nodes.get(id)) .filter(isNonNullable) .sort((a, b) => a.label.localeCompare(b.label)), innerProps: { documentationState, refreshTreeData: () => documentationState.resetPackageFilterTreeData(), uncheckTree: () => uncheckAllFilterTree(documentationState.packageFilterTreeData), updateFilter: () => documentationState.updatePackageFilter(), } }) })] })] })); }); const ModelsDocumentationSearchBar = observer((props) => { const { modelsDocumentationState } = props; const searchInputRef = useRef(null); const searchConfigTriggerRef = useRef(null); const documentationState = modelsDocumentationState; const searchText = documentationState.searchText; const debouncedSearch = useMemo(() => debounce(() => documentationState.search(), 100), [documentationState]); const onSearchTextChange = (event) => { documentationState.setSearchText(event.target.value); debouncedSearch.cancel(); debouncedSearch(); }; // actions const clearSearchText = () => { documentationState.resetSearch(); documentationState.focusSearchInput(); }; const toggleSearchConfigMenu = () => documentationState.setShowSearchConfigurationMenu(!documentationState.showSearchConfigurationMenu); const onKeyDown = (event) => { if (event.code === 'Escape') { documentationState.selectSearchInput(); } }; // search config menu const closeSearchConfigMenu = () => documentationState.setShowSearchConfigurationMenu(false); const onSearchConfigMenuOpen = () => documentationState.focusSearchInput(); useEffect(() => { if (searchInputRef.current) { documentationState.setSearchInput(searchInputRef.current); } return () => documentationState.setSearchInput(undefined); }, [documentationState]); return (_jsxs("div", { className: "models-documentation__search", children: [_jsx("input", { ref: searchInputRef, onKeyDown: onKeyDown, className: "models-documentation__search__input input", spellCheck: false, onChange: onSearchTextChange, value: searchText, placeholder: "Search (Ctrl + Shift + F)" }), _jsx("button", { ref: searchConfigTriggerRef, className: clsx('models-documentation__search__input__config__trigger', { 'models-documentation__search__input__config__trigger--toggled': documentationState.showSearchConfigurationMenu, 'models-documentation__search__input__config__trigger--active': documentationState.searchConfigurationState .isAdvancedSearchActive, }), tabIndex: -1, onClick: toggleSearchConfigMenu, title: `${documentationState.searchConfigurationState.isAdvancedSearchActive ? 'Advanced search is currently active\n' : ''}Click to toggle search config menu`, children: _jsx(CogIcon, {}) }), _jsx(BasePopover, { open: Boolean(documentationState.showSearchConfigurationMenu), slotProps: { transition: { onEnter: onSearchConfigMenuOpen, }, }, anchorEl: searchConfigTriggerRef.current, onClose: closeSearchConfigMenu, anchorOrigin: { vertical: 'bottom', horizontal: 'center', }, transformOrigin: { vertical: 'top', horizontal: 'center', }, children: _jsx(FuzzySearchAdvancedConfigMenu, { configState: documentationState.searchConfigurationState }) }), !searchText ? (_jsx("div", { className: "models-documentation__search__input__search__icon", children: _jsx(SearchIcon, {}) })) : (_jsx("button", { className: "models-documentation__search__input__clear-btn", tabIndex: -1, onClick: clearSearchText, title: "Clear", children: _jsx(TimesIcon, {}) }))] })); }); const ProductWikiPlaceholder = (props) => (_jsx("div", { className: "models-documentation__viewer__wiki__placeholder", children: props.message })); export const ModelsDocumentation = observer((props) => { const { modelsDocumentationState, applicationStore, title, queryModel } = props; const sectionRef = useRef(null); const elementDocs = modelsDocumentationState.elementDocs; useCommands(modelsDocumentationState); const toggleFilterPanel = () => modelsDocumentationState.setShowFilterPanel(!modelsDocumentationState.showFilterPanel); return (_jsxs("div", { ref: sectionRef, className: "models-documentation__viewer__wiki__section", children: [_jsxs("div", { className: "models-documentation__viewer__wiki__section__header", children: [_jsxs("div", { className: "models-documentation__viewer__wiki__section__header__label", children: [title ?? 'Models Documentation', _jsx("button", { className: "models-documentation__viewer__wiki__section__header__anchor", tabIndex: -1, children: _jsx(AnchorLinkIcon, {}) })] }), queryModel && (_jsxs("button", { className: "models-documentation__viewer__wiki__section__header__query-btn", tabIndex: -1, onClick: queryModel, title: "Query", children: [_jsx(PlayIcon, {}), "Query"] }))] }), _jsxs("div", { className: "models-documentation__viewer__wiki__section__content", children: [elementDocs.length > 0 && (_jsxs("div", { className: "models-documentation", children: [_jsxs("div", { className: "models-documentation__header", children: [_jsxs("button", { className: "models-documentation__filter__toggler", title: "Toggle Filter Panel", tabIndex: -1, onClick: toggleFilterPanel, children: [_jsx("div", { className: "models-documentation__filter__toggler__arrow", children: modelsDocumentationState.showFilterPanel ? (_jsx(CaretLeftIcon, {})) : (_jsx(CaretRightIcon, {})) }), _jsx("div", { className: "models-documentation__filter__toggler__icon", children: _jsx(FilterIcon, {}) })] }), _jsx(ModelsDocumentationSearchBar, { modelsDocumentationState: modelsDocumentationState })] }), _jsxs("div", { className: "models-documentation__content", children: [modelsDocumentationState.showFilterPanel && (_jsx(ModelsDocumentationFilterPanel, { modelsDocumentationState: modelsDocumentationState })), _jsx(ModelsDocumentationGridPanel, { modelsDocumentationState: modelsDocumentationState, applicationStore: applicationStore })] })] })), elementDocs.length === 0 && (_jsx(ProductWikiPlaceholder, { message: "(not specified)" }))] })] })); }); //# sourceMappingURL=ModelDocumentationViewer.js.map