UNPKG

@zohodesk/docs-builder

Version:

docs-builder is used to build your own docs

209 lines (183 loc) 8.64 kB
import React, { useState, useMemo, useEffect } from "react"; import { Link, useLocation, useHistory } from "react-router-dom"; import style from "./Sidebar.module.css"; import image from "../../assets/icons/desk.png"; import docsObjectConvertor from "./docsObjectConvertor"; export default function Sidebar(_ref) { let { components } = _ref; const [searchQuery, setSearchQuery] = useState(""); const [openFolders, setOpenFolders] = useState({}); const [openGroups, setOpenGroups] = useState({}); const location = useLocation(); const history = useHistory(); // Filter components based on search query const filteredComponents = useMemo(() => { if (!searchQuery.trim()) return components; return searchFilter(searchQuery); }, [components, searchQuery]); // Convert filtered components to docs object structure const organizedDocs = useMemo(() => docsObjectConvertor(filteredComponents), [filteredComponents]); // Handle component route navigation const navigateToComponent = componentName => { if (componentName) { history.push(`/all/${componentName}`); } }; // Clear search input const clearSearch = () => { setSearchQuery(""); }; // Toggle folder open/closed state const toggleFolder = folderName => { setOpenFolders(prevState => { const newOpenFolders = { ...prevState }; newOpenFolders[folderName] = !prevState[folderName]; // Close other folders when opening a new one Object.keys(prevState).forEach(prevFolder => { if (prevFolder !== folderName && newOpenFolders[folderName]) { newOpenFolders[prevFolder] = false; } }); return newOpenFolders; }); }; // Toggle group open/closed state within a folder const toggleGroup = (folderName, groupName) => { const groupKey = `${folderName}_${groupName}`; setOpenGroups(prevState => { const newOpenGroups = { ...prevState }; newOpenGroups[groupKey] = !prevState[groupKey]; // Close other groups in the same folder when opening a new one Object.keys(prevState).forEach(prevGroup => { if (prevGroup.startsWith(`${folderName}_`) && prevGroup !== groupKey && newOpenGroups[groupKey]) { newOpenGroups[prevGroup] = false; } }); return newOpenGroups; }); }; // Filter components by search query function searchFilter(searchQuery) { const filteredData = Object.entries(components).filter(_ref2 => { let [compId, component] = _ref2; const lowercaseName = component.name ? component.name.toLowerCase() : ""; const lowercaseQuery = searchQuery.toLowerCase(); return lowercaseName.includes(lowercaseQuery); }); return Object.fromEntries(filteredData); } // Extract the base component name from path (ignore tab routing) const getComponentNameFromPath = path => { // First, split by "/" const pathParts = path.split("/"); // Get the component name (expected to be the last part or the one before a tab name) let componentName = pathParts[pathParts.length - 1]; // Check if this is a tab route and get the actual component name if (["proptypes", "code", "playground"].includes(componentName)) { componentName = pathParts[pathParts.length - 2]; } return componentName; }; // Auto-expand folders and groups based on current URL path useEffect(() => { const pathParts = location.pathname.split("/"); const isAllRoute = pathParts.length <= 2 || pathParts[1] === "all" && pathParts.length === 2; // If navigating to /all route, close all folders if (isAllRoute) { setOpenFolders({}); setOpenGroups({}); return; } const componentName = getComponentNameFromPath(location.pathname); // Only proceed if this is a component path if (!componentName || componentName === "all") return; // Reset open state const newOpenFolders = {}; const newOpenGroups = {}; // Find and open the folder and group containing the current component for (const [folderName, groups] of Object.entries(organizedDocs)) { for (const [groupName, components] of Object.entries(groups)) { if (components.hasOwnProperty(componentName)) { newOpenFolders[folderName] = true; newOpenGroups[`${folderName}_${groupName}`] = true; break; } } } setOpenFolders(newOpenFolders); setOpenGroups(newOpenGroups); }, [location.pathname, organizedDocs]); return /*#__PURE__*/React.createElement("div", { className: style.sidebar }, /*#__PURE__*/React.createElement("div", { className: style.sidebarContent }, /*#__PURE__*/React.createElement(Link, { to: "/all", className: style.logoContainer }, /*#__PURE__*/React.createElement("img", { className: style.logo, src: image, alt: "Logo" }), /*#__PURE__*/React.createElement("div", { className: style.docsVersion }, "Docs v2.0.0"), /*#__PURE__*/React.createElement("i", { className: `fa-solid fa-house ${style.homeIcon}` })), /*#__PURE__*/React.createElement("div", { className: style.navigationContainer }, /*#__PURE__*/React.createElement("div", { className: style.searchContainer }, /*#__PURE__*/React.createElement("i", { className: `fa-solid fa-magnifying-glass ${style.searchIcon}` }), /*#__PURE__*/React.createElement("input", { type: "text", placeholder: "Search components...", className: style.searchInput, value: searchQuery, onChange: e => setSearchQuery(e.target.value) }), searchQuery && /*#__PURE__*/React.createElement("button", { className: style.clearButton, onClick: clearSearch }, /*#__PURE__*/React.createElement("i", { className: "fa-solid fa-times" }))), /*#__PURE__*/React.createElement("div", { className: style.componentList }, Object.entries(organizedDocs).map(_ref3 => { let [folderName, groups] = _ref3; return /*#__PURE__*/React.createElement("div", { key: folderName, className: `${style.folder} ${openFolders[folderName] ? style.folderOpen : ""}` }, /*#__PURE__*/React.createElement("div", { className: style.folderHeader, onClick: () => toggleFolder(folderName) }, /*#__PURE__*/React.createElement("i", { className: `fa-regular fa-folder ${style.folderIcon}` }), /*#__PURE__*/React.createElement("span", { className: style.folderName }, folderName), /*#__PURE__*/React.createElement("span", { className: style.itemCount }, Object.keys(groups).length), /*#__PURE__*/React.createElement("i", { className: `fa-solid fa-chevron-right ${style.chevron} ${openFolders[folderName] ? style.chevronOpen : ""}` })), (searchQuery || openFolders[folderName]) && /*#__PURE__*/React.createElement("div", { className: style.groupsContainer }, Object.entries(groups).map(_ref4 => { let [groupName, components] = _ref4; return /*#__PURE__*/React.createElement("div", { key: groupName, className: `${style.group} ${openGroups[`${folderName}_${groupName}`] ? style.groupOpen : ""}` }, /*#__PURE__*/React.createElement("div", { className: style.groupHeader, onClick: () => toggleGroup(folderName, groupName) }, /*#__PURE__*/React.createElement("i", { className: `fa-regular fa-file ${style.groupIcon}` }), /*#__PURE__*/React.createElement("span", { className: style.groupName }, groupName), /*#__PURE__*/React.createElement("span", { className: style.itemCount }, Object.keys(components).length), /*#__PURE__*/React.createElement("i", { className: `fa-solid fa-chevron-right ${style.chevron} ${openGroups[`${folderName}_${groupName}`] ? style.chevronOpen : ""}` })), (searchQuery || openGroups[`${folderName}_${groupName}`]) && /*#__PURE__*/React.createElement("div", { className: style.componentsContainer }, Object.keys(components).map(compId => { const componentName = compId.split("__")[1] || compId; const currentCompInPath = getComponentNameFromPath(location.pathname); const isActive = compId === currentCompInPath; return /*#__PURE__*/React.createElement("div", { key: compId, className: `${style.component} ${isActive ? style.componentActive : ""}`, onClick: () => navigateToComponent(compId) }, /*#__PURE__*/React.createElement("i", { className: `fa-brands fa-react ${style.componentIcon}` }), /*#__PURE__*/React.createElement("span", { className: style.componentName }, componentName)); }))); }))); }))))); }