diff --git a/doc/ui-examples/version-selector/css/menubar.css b/doc/ui-examples/version-selector/css/menubar.css
new file mode 100644
index 0000000..dfc9f65
--- /dev/null
+++ b/doc/ui-examples/version-selector/css/menubar.css
@@ -0,0 +1,94 @@
+.component-selector {
+ position: relative;
+ top: 0.45rem;
+}
+.component-selector i.fa {
+ font-size: 100%;
+ vertical-align: middle;
+}
+.component-selector a { color: var(--menubar-text-color); }
+.component-selector ul {
+ font-size: 0;
+ list-style-type: none;
+ padding: 0;
+}
+.component-selector ul li {
+ display: inline-block;
+ font-size: .86rem;
+ color: var(--menubar-text-color);
+ padding: 14px;
+ position: relative;
+ z-index: 999;
+}
+.component-selector ul li .nav-item-toggle {
+ background: transparent url(../img/chevron.svg) no-repeat center / 50%;
+ border: none;
+ outline: none;
+ line-height: inherit;
+ padding: 0;
+ position: absolute;
+ margin-top: 0;
+ margin-left: calc(var(--nav-line-height) * 1em - 1.5em);
+ transform: rotate(0deg);
+}
+.component-selector ul li span {
+ background-color: var(--menubar-version-label-color);
+ border-radius: 3px;
+ display: inline-block;
+ font-size: 0.6rem;
+ padding: 2px 5px;
+ text-align: center;
+ vertical-align: bottom;
+}
+.component-selector ul li span a { color: white }
+.component-selector ul li span:hover {
+ background-color: var(--menubar-version-label-hover-color);
+}
+.component-selector ul li span:hover a {
+ text-decoration: none;
+ color: var(--menubar-text-color);
+}
+.component-selector ul li ul {
+ display: none;
+ top: 28px;
+}
+.component-selector ul li:hover {
+ cursor: pointer;
+ /* background-color: var(--menubar-background-color); */
+}
+.component-selector ul li:hover ul {
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
+ display: block;
+ left: 0;
+ margin-top: 15px;
+ max-height: 72vh;
+ overflow-y: auto;
+ position: absolute;
+ scrollbar-color: auto;
+ overscroll-behavior-y: none;
+ width: 320px;
+}
+.component-selector ul li:hover ul li {
+ display: block;
+ background-color: var(--menubar-background-color);
+}
+.component-selector ul li:hover ul li:hover {
+ background-color: var(--menubar-hover-color);
+}
+.component-selector ul li:hover ul li span {
+ background-color: var(--menubar-version-label-color);
+ border-radius: 3px;
+ display: inline-block;
+ font-size: 0.6rem;
+ padding: 2px 5px;
+ text-align: center;
+ vertical-align: bottom;
+}
+.component-selector ul li:hover ul li span a { color: white }
+.component-selector ul li:hover ul li span:hover {
+ background-color: var(--menubar-version-label-hover-color);
+}
+.component-selector ul li:hover ul li span:hover a {
+ text-decoration: none;
+ color: var(--menubar-text-color);
+}
diff --git a/doc/ui-examples/version-selector/partials/header-content.hbs b/doc/ui-examples/version-selector/partials/header-content.hbs
new file mode 100644
index 0000000..d51e370
--- /dev/null
+++ b/doc/ui-examples/version-selector/partials/header-content.hbs
@@ -0,0 +1,23 @@
+
diff --git a/doc/ui-examples/version-selector/partials/main-menu-docref.hbs b/doc/ui-examples/version-selector/partials/main-menu-docref.hbs
new file mode 100644
index 0000000..926733f
--- /dev/null
+++ b/doc/ui-examples/version-selector/partials/main-menu-docref.hbs
@@ -0,0 +1,18 @@
+
+{{#if (and resolved (not external))}}
+{{#with (lookup site.components component)}}
+ {{{./title}}}
+ {{#each ./versions}}
+ {{#if (ne ./displayVersion 'default')}}
+
+ {{./displayVersion}}
+
+ {{/if}}
+ {{/each}}
+{{/with}}
+{{else}}
+ {{doc_title}}{{#if external}} {{/if}}
+{{/if}}
+
diff --git a/doc/ui-examples/version-selector/partials/main-menu-group-end.hbs b/doc/ui-examples/version-selector/partials/main-menu-group-end.hbs
new file mode 100644
index 0000000..a25f9ee
--- /dev/null
+++ b/doc/ui-examples/version-selector/partials/main-menu-group-end.hbs
@@ -0,0 +1 @@
+
diff --git a/doc/ui-examples/version-selector/partials/main-menu-group-start.hbs b/doc/ui-examples/version-selector/partials/main-menu-group-start.hbs
new file mode 100644
index 0000000..e311f76
--- /dev/null
+++ b/doc/ui-examples/version-selector/partials/main-menu-group-start.hbs
@@ -0,0 +1,2 @@
+{{group_title}}
+
diff --git a/doc/ui-examples/version-selector/partials/main-menu.hbs b/doc/ui-examples/version-selector/partials/main-menu.hbs
new file mode 100644
index 0000000..5a6eb2e
--- /dev/null
+++ b/doc/ui-examples/version-selector/partials/main-menu.hbs
@@ -0,0 +1 @@
+
diff --git a/extensions/v1/builder.js b/extensions/v1/builder.js
index 1bc7e27..b1c623f 100644
--- a/extensions/v1/builder.js
+++ b/extensions/v1/builder.js
@@ -44,11 +44,11 @@ class MenuBuilder {
resolveMenuDefinition(modules) {
if (this.componentName && this.configFile) {
- let configModule = modules.find(module => module.name === this.componentName);
+ const configModule = modules.find(module => module.name === this.componentName);
if (configModule === undefined) {
throw new Error(`specified menu component ${this.componentName} not found`);
}
- let menuConfigFile = configModule.files.find(file => file.src.path === this.configFile);
+ const menuConfigFile = configModule.files.find(file => file.src.path === this.configFile);
if (menuConfigFile === undefined) {
throw new Error(`specified menu file ${this.configFile} not found in component ${this.componentName}`);
}
@@ -61,10 +61,15 @@ class MenuBuilder {
build(contentCatalog) {
// resolved menu template
- let mainMenuContent = new MenuContent(this.hbs.groupStart, this.hbs.groupEnd, this.hbs.docRef);
+ const mainMenuContent = new MenuContent(this.hbs.groupStart, this.hbs.groupEnd, this.hbs.docRef);
this.menu.forEach(entry => {
if (entry.title) {
mainMenuContent.add(this.inspectGroupEntry(undefined, entry, contentCatalog));
+ } else if (entry.module) {
+ const component = contentCatalog.getComponent(entry.module);
+ mainMenuContent.add(component
+ ? Document.resolved(component.latest.title, component.latest.url, component.name)
+ : Document.unresolved(entry.module));
} else {
throw new Error(`root element must have a title and optional entries ${this.toString(entry)}`);
}
@@ -73,7 +78,7 @@ class MenuBuilder {
}
toString(entry) {
- var s = `${entry.toString()} {`;
+ let s = `${entry.toString()} {`;
Object.getOwnPropertyNames(entry).forEach(key => {
s += `${key}=${entry[key]}, `
});
@@ -81,13 +86,13 @@ class MenuBuilder {
}
inspectGroupEntry(parentNode, entry, contentCatalog) {
- let groupNode = new Group(entry.title);
+ const groupNode = new Group(entry.title);
parentNode?.add(groupNode);
entry.entries?.forEach((subEntry) => {
if (subEntry.module) {
- let component = contentCatalog.getComponent(subEntry.module);
+ const component = contentCatalog.getComponent(subEntry.module);
groupNode.add(component
- ? Document.resolved(component.latest.title, component.latest.url)
+ ? Document.resolved(component.latest.title, component.latest.url, component.name)
: Document.unresolved(entry.module));
} else if (subEntry.link) {
groupNode.add(Document.external(subEntry.title, subEntry.link));
diff --git a/extensions/v1/index.js b/extensions/v1/index.js
index 7235e71..e40bca5 100644
--- a/extensions/v1/index.js
+++ b/extensions/v1/index.js
@@ -30,8 +30,8 @@ class DynaMenuExtension {
}
navigationBuilt({playbook, siteAsciiDocConfig, siteCatalog, uiCatalog, contentCatalog, navigationCatalog}) {
- let htmlPartialContent = this.builder.build(contentCatalog);
- let menuFile = this.registerMainMenuContent(htmlPartialContent);
+ const htmlPartialContent = this.builder.build(contentCatalog);
+ const menuFile = this.registerMainMenuContent(htmlPartialContent);
this.logger.debug(`derived menu template:
============
${htmlPartialContent}
diff --git a/extensions/v1/menuStructure.js b/extensions/v1/menuStructure.js
index 6bc3717..c15bb4c 100644
--- a/extensions/v1/menuStructure.js
+++ b/extensions/v1/menuStructure.js
@@ -32,24 +32,26 @@ class Document extends Entry {
ref;
resolved;
external;
+ component;
static external(title, ref) {
- return new Document(title, ref, true, true);
+ return new Document(title, ref, true, true, null);
}
- static resolved(title, ref) {
- return new Document(title, ref, true, false);
+ static resolved(title, ref, component) {
+ return new Document(title, ref, true, false, component);
}
static unresolved(name) {
- return new Document(name, "#", false, false);
+ return new Document(name, "#", false, false, null);
}
- constructor(title, ref, resolved = true, external = false) {
+ constructor(title, ref, resolved = true, external = false, component = null) {
super(title);
this.ref = ref;
this.resolved = resolved;
this.external = external;
+ this.component = component;
}
toString() {
@@ -76,7 +78,12 @@ class MenuContent {
toPartialHandlebar() {
return this.groups
- .map(entry => this.mapGroup(entry, 0))
+ .map(
+ function(entry) {
+ if (entry instanceof Group) return this.mapGroup(entry, 0);
+ if (entry instanceof Document) return this.link(entry);
+ }, this
+ )
.join("\n");
}
@@ -89,7 +96,7 @@ class MenuContent {
}
link(entry) {
- return `{{> ${this.hbsDocRef} resolved=${entry.resolved} doc_title="${entry.title}" ref="${entry.ref}" external=${entry.external} }}`;
+ return `{{> ${this.hbsDocRef} resolved=${entry.resolved} doc_title="${entry.title}" ref="${entry.ref}" external=${entry.external} component="${entry.component}" }}`;
}
indent(level) {