diff --git a/package.json b/package.json index e575e48520..3acdff7d24 100644 --- a/package.json +++ b/package.json @@ -339,6 +339,7 @@ "react-router-dom": "^5.2.0", "react-select": "^3.1.0", "react-select-event": "^5.1.0", + "react-simple-tree-menu": "^1.1.18", "react-window": "^1.8.5", "sass-loader": "^8.0.2", "sharp": "^0.26.1", diff --git a/src/renderer/components/layout/page-layout.tsx b/src/renderer/components/layout/page-layout.tsx index 19d32434c0..345f881449 100644 --- a/src/renderer/components/layout/page-layout.tsx +++ b/src/renderer/components/layout/page-layout.tsx @@ -6,6 +6,7 @@ import { autobind, cssNames, IClassName } from "../../utils"; import { Icon } from "../icon"; import { navigation } from "../../navigation"; import { ScrollSpy } from "../scroll-spy/scroll-spy"; +import { RecursiveTreeView } from "../tree-view"; export interface PageLayoutProps extends React.DOMAttributes { className?: IClassName; @@ -80,11 +81,7 @@ export class PageLayout extends React.Component {
{ showNavigation && (
-
    -
  • Section 1
  • -
  • Section 2
  • -
  • {navigation.toString()}
  • -
+
)}
diff --git a/src/renderer/components/scroll-spy/scroll-spy.tsx b/src/renderer/components/scroll-spy/scroll-spy.tsx index c5d3dc610f..9fb4684840 100644 --- a/src/renderer/components/scroll-spy/scroll-spy.tsx +++ b/src/renderer/components/scroll-spy/scroll-spy.tsx @@ -1,11 +1,12 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; +import { NavigationTree } from "../tree-view"; interface Props extends React.DOMAttributes { - render: (data: any) => any + render: (data: NavigationTree[]) => any } export function ScrollSpy(props: Props) { - let navigationData: any = {}; + const [tree, setTree] = useState([]); const updateNavigation = () => { const firstSection = document.querySelector("section"); @@ -14,31 +15,28 @@ export function ScrollSpy(props: Props) { throw new Error("No
tag founded! Content should be placed inside
elements to activate navigation."); } - navigationData = { - id: "root", - name: "Parent", - children: getNavigation(firstSection.parentElement) - }; - - console.log(navigationData); + setTree([ + ...tree, + ...getNavigation(firstSection.parentElement) + ]); }; const getNavigation = (element: Element) => { const sections = element.querySelectorAll(":scope > section"); // Searching only direct children of an element. Impossible without :scope - const children: any = []; + const children: NavigationTree[] = []; sections.forEach(section => { - const id = section.getAttribute("id"); - const name = section.querySelector(":first-child").textContent; + const key = section.getAttribute("id"); + const label = section.querySelector(":first-child").textContent; - if (!name || !id) { + if (!label || !key) { return; } children.push({ - id, - name, - children: getNavigation(section) + key, + label, + nodes: getNavigation(section) }); }); @@ -53,7 +51,7 @@ export function ScrollSpy(props: Props) { return (
- {props.render(navigationData)} + {props.render(tree)}
); } diff --git a/src/renderer/components/tree-view/index.ts b/src/renderer/components/tree-view/index.ts new file mode 100644 index 0000000000..4514f03621 --- /dev/null +++ b/src/renderer/components/tree-view/index.ts @@ -0,0 +1 @@ +export * from "./tree-view"; diff --git a/src/renderer/components/tree-view/tree-view.tsx b/src/renderer/components/tree-view/tree-view.tsx new file mode 100644 index 0000000000..2e35d0df9a --- /dev/null +++ b/src/renderer/components/tree-view/tree-view.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import TreeMenu from "react-simple-tree-menu"; +import { Icon } from "../icon"; + +export interface NavigationTree { + key: string; + label: string; + nodes?: NavigationTree[]; +} + +interface Props { + data: NavigationTree[] +} + +export function RecursiveTreeView({ data }: Props) { + return ( + + ); +} diff --git a/yarn.lock b/yarn.lock index 2cc97b2383..e8f814ec67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3515,6 +3515,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -5586,6 +5591,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-memoize@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e" + integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== + fast-safe-stringify@^2.0.4: version "2.0.7" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" @@ -7152,6 +7162,11 @@ is-electron@^2.2.0: resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.0.tgz#8943084f09e8b731b3a7a0298a7b5d56f6b7eef0" integrity sha512-SpMppC2XR3YdxSzczXReBjqs2zGscWQpBIKqwXYBFic0ERaxNVgwLCHwOLZeESfdJQjX0RDvrJ1lBXX2ij+G1Q== +is-empty@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-empty/-/is-empty-1.2.0.tgz#de9bb5b278738a05a0b09a57e1fb4d4a341a9f6b" + integrity sha1-3pu1snhzigWgsJpX4ftNSjQan2s= + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -11272,6 +11287,16 @@ react-select@^3.1.0: react-input-autosize "^2.2.2" react-transition-group "^4.3.0" +react-simple-tree-menu@^1.1.18: + version "1.1.18" + resolved "https://registry.yarnpkg.com/react-simple-tree-menu/-/react-simple-tree-menu-1.1.18.tgz#4c35f6c2348da8deac5cd10ab5dd07a5213f74f2" + integrity sha512-sW33U4TF6J3CuhDXs40r8KXCZsyd9JKLVHRwCx0hxaWaXFD0p7LeeK1gJB+GLNErSGs1F1847E/kkTIyKi9E0w== + dependencies: + classnames "^2.2.6" + fast-memoize "^2.5.1" + is-empty "^1.2.0" + tiny-debounce "^0.1.1" + react-transition-group@^4.3.0, react-transition-group@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" @@ -13208,6 +13233,11 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tiny-debounce@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/tiny-debounce/-/tiny-debounce-0.1.1.tgz#e7759447ca1d48830d3b302ce94666a0ca537b1d" + integrity sha1-53WUR8odSIMNOzAs6UZmoMpTex0= + tiny-invariant@^1.0.2, tiny-invariant@^1.0.6: version "1.1.0" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"