element-book 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/element-book-entry/element-book-entry.d.ts +3 -0
- package/dist/data/element-book-entry/element-book-entry.js +4 -1
- package/dist/data/element-book-entry/entry-tree/entry-tree.js +1 -1
- package/dist/data/element-book-entry/entry-tree/walk-entry-tree.d.ts +0 -1
- package/dist/data/element-book-entry/entry-tree/walk-entry-tree.js +0 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/ui/elements/element-book-app.element.js +70 -59
- package/dist/ui/elements/entry-display/element-book-entry-display.element.d.ts +2 -1
- package/dist/ui/elements/entry-display/element-book-entry-display.element.js +48 -22
- package/package.json +1 -1
|
@@ -7,3 +7,6 @@ export type ElementBookRoot = {
|
|
|
7
7
|
parent: undefined;
|
|
8
8
|
};
|
|
9
9
|
export type ElementBookEntry = ElementBookChapter | ElementBookPage | ElementBookRoot;
|
|
10
|
+
export declare function isElementBookEntry<SpecificType extends ElementBookEntryTypeEnum>(entry: unknown, type: SpecificType): entry is Extract<ElementBookEntry, {
|
|
11
|
+
type: SpecificType;
|
|
12
|
+
}>;
|
|
@@ -16,7 +16,7 @@ export function createEmptyEntryTreeRoot() {
|
|
|
16
16
|
return rootNode;
|
|
17
17
|
}
|
|
18
18
|
export function titleToBreadcrumb(title) {
|
|
19
|
-
return collapseWhiteSpace(title).replaceAll(/\s/g, '-');
|
|
19
|
+
return collapseWhiteSpace(title).toLowerCase().replaceAll(/\s/g, '-');
|
|
20
20
|
}
|
|
21
21
|
export function entriesToTree(entries) {
|
|
22
22
|
const tree = createEmptyEntryTreeRoot();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MaybePromise } from '@augment-vir/common';
|
|
2
2
|
import { EntryTreeNode } from './entry-tree';
|
|
3
|
-
export declare function findFirstPageBreadcrumbs(entryTree: Readonly<EntryTreeNode>): string[];
|
|
4
3
|
/**
|
|
5
4
|
* Walk the whole given tree, calling callback on each node. If callback returns the boolean false
|
|
6
5
|
* exactly, then all walking will abort. If callback returns a promise, this function will return a
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
import { ElementBookEntryTypeEnum } from '../element-book-entry-type';
|
|
2
|
-
import { doesNodeHaveEntryType, listBreadcrumbs } from './entry-tree';
|
|
3
|
-
export function findFirstPageBreadcrumbs(entryTree) {
|
|
4
|
-
let pageEntry;
|
|
5
|
-
walkEntryTree(entryTree, (node) => {
|
|
6
|
-
if (doesNodeHaveEntryType(node, ElementBookEntryTypeEnum.Page)) {
|
|
7
|
-
pageEntry = node;
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
return;
|
|
11
|
-
});
|
|
12
|
-
if (!pageEntry) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
return listBreadcrumbs(pageEntry.entry).concat(pageEntry.breadcrumb);
|
|
16
|
-
}
|
|
17
1
|
/**
|
|
18
2
|
* Walk the whole given tree, calling callback on each node. If callback returns the boolean false
|
|
19
3
|
* exactly, then all walking will abort. If callback returns a promise, this function will return a
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './data/element-book-entry/element-book-chapter/element-book-chapter';
|
|
2
|
+
export * from './data/element-book-entry/element-book-entry';
|
|
2
3
|
export * from './data/element-book-entry/element-book-page/element-book-page';
|
|
3
4
|
export * from './data/element-book-entry/element-book-page/element-book-page-example';
|
|
4
5
|
export * from './ui/elements/element-book-app.element';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './data/element-book-entry/element-book-chapter/element-book-chapter';
|
|
2
|
+
export * from './data/element-book-entry/element-book-entry';
|
|
2
3
|
export * from './data/element-book-entry/element-book-page/element-book-page';
|
|
3
4
|
export * from './data/element-book-entry/element-book-page/element-book-page-example';
|
|
4
5
|
export * from './ui/elements/element-book-app.element';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { extractErrorMessage } from '@augment-vir/common';
|
|
1
2
|
import { assign, css, defineElement, html, listen } from 'element-vir';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
3
|
+
import { isElementBookEntry, } from '../../data/element-book-entry/element-book-entry';
|
|
4
|
+
import { ElementBookEntryTypeEnum } from '../../data/element-book-entry/element-book-entry-type';
|
|
5
|
+
import { entriesToTree, findEntryByBreadcrumbs, listBreadcrumbs, } from '../../data/element-book-entry/entry-tree/entry-tree';
|
|
4
6
|
import { createElementBookRouter } from '../../routing/create-element-book-router';
|
|
5
7
|
import { emptyElementBookFullRoute, } from '../../routing/element-book-routing';
|
|
6
8
|
import { setThemeCssVars } from '../color-theme/color-theme';
|
|
@@ -65,71 +67,80 @@ export const ElementBookApp = defineElement()({
|
|
|
65
67
|
setThemeCssVars(host, state.colors.theme);
|
|
66
68
|
},
|
|
67
69
|
renderCallback: ({ state, inputs, host, updateState }) => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
colors: {
|
|
72
|
-
original: inputs.themeColor,
|
|
73
|
-
theme: newTheme,
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
setThemeCssVars(host, newTheme);
|
|
77
|
-
}
|
|
78
|
-
function updateRoutes(newRoute) {
|
|
79
|
-
if (state.router) {
|
|
80
|
-
state.router.setRoutes(newRoute);
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
70
|
+
try {
|
|
71
|
+
if (inputs.themeColor !== state.colors?.original) {
|
|
72
|
+
const newTheme = createTheme(inputs.themeColor);
|
|
83
73
|
updateState({
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
colors: {
|
|
75
|
+
original: inputs.themeColor,
|
|
76
|
+
theme: newTheme,
|
|
87
77
|
},
|
|
88
78
|
});
|
|
79
|
+
setThemeCssVars(host, newTheme);
|
|
89
80
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
function updateRoutes(newRoute) {
|
|
82
|
+
if (state.router) {
|
|
83
|
+
state.router.setRoutes(newRoute);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
updateState({
|
|
87
|
+
currentRoute: {
|
|
88
|
+
...state.currentRoute,
|
|
89
|
+
...newRoute,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
101
93
|
}
|
|
94
|
+
const entriesTree = entriesToTree(inputs.entries);
|
|
95
|
+
const initialNode = findEntryByBreadcrumbs(state.currentRoute.paths, entriesTree);
|
|
96
|
+
if (!initialNode ||
|
|
97
|
+
isElementBookEntry(initialNode.entry, ElementBookEntryTypeEnum.Root)) {
|
|
98
|
+
const firstChild = Object.values(entriesTree.children)[0];
|
|
99
|
+
if (!firstChild) {
|
|
100
|
+
throw new Error(`No entries exist.`);
|
|
101
|
+
}
|
|
102
|
+
const firstEntryBreadcrumbs = listBreadcrumbs(firstChild.entry, true);
|
|
103
|
+
const defaultPath = inputs.defaultPath ??
|
|
104
|
+
(firstEntryBreadcrumbs.length ? firstEntryBreadcrumbs : undefined);
|
|
105
|
+
if (defaultPath && defaultPath.length) {
|
|
106
|
+
const newRoute = {
|
|
107
|
+
paths: defaultPath,
|
|
108
|
+
};
|
|
109
|
+
updateRoutes(newRoute);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const currentNode = findEntryByBreadcrumbs(state.currentRoute.paths, entriesTree);
|
|
113
|
+
if (!currentNode) {
|
|
114
|
+
throw new Error(`Tried to self-correct for invalid path ${state.currentRoute.paths.join('/')}
|
|
115
|
+
but failed to do so.`);
|
|
116
|
+
}
|
|
117
|
+
return html `
|
|
118
|
+
<div
|
|
119
|
+
class="root"
|
|
120
|
+
${listen(ChangeRouteEvent, (event) => {
|
|
121
|
+
updateRoutes(event.detail);
|
|
122
|
+
})}
|
|
123
|
+
>
|
|
124
|
+
<${ElementBookNav}
|
|
125
|
+
${assign(ElementBookNav, {
|
|
126
|
+
tree: entriesTree,
|
|
127
|
+
router: state.router,
|
|
128
|
+
selectedPath: state.currentRoute.paths,
|
|
129
|
+
})}
|
|
130
|
+
></${ElementBookNav}>
|
|
131
|
+
<${ElementBookEntryDisplay}
|
|
132
|
+
${assign(ElementBookEntryDisplay, {
|
|
133
|
+
currentRoute: state.currentRoute,
|
|
134
|
+
currentNode,
|
|
135
|
+
})}
|
|
136
|
+
></${ElementBookEntryDisplay}>
|
|
137
|
+
</div>
|
|
138
|
+
`;
|
|
102
139
|
}
|
|
103
|
-
|
|
104
|
-
if (!currentNode) {
|
|
140
|
+
catch (error) {
|
|
105
141
|
return html `
|
|
106
|
-
<p class="error">
|
|
107
|
-
Tried to self-correct for invalid path ${state.currentRoute.paths.join('/')} but
|
|
108
|
-
failed to do so.
|
|
109
|
-
</p>
|
|
142
|
+
<p class="error">${extractErrorMessage(error)}</p>
|
|
110
143
|
`;
|
|
111
144
|
}
|
|
112
|
-
return html `
|
|
113
|
-
<div
|
|
114
|
-
class="root"
|
|
115
|
-
${listen(ChangeRouteEvent, (event) => {
|
|
116
|
-
updateRoutes(event.detail);
|
|
117
|
-
})}
|
|
118
|
-
>
|
|
119
|
-
<${ElementBookNav}
|
|
120
|
-
${assign(ElementBookNav, {
|
|
121
|
-
tree: entriesTree,
|
|
122
|
-
router: state.router,
|
|
123
|
-
selectedPath: state.currentRoute.paths,
|
|
124
|
-
})}
|
|
125
|
-
></${ElementBookNav}>
|
|
126
|
-
<${ElementBookEntryDisplay}
|
|
127
|
-
${assign(ElementBookEntryDisplay, {
|
|
128
|
-
currentRoute: state.currentRoute,
|
|
129
|
-
currentNode,
|
|
130
|
-
})}
|
|
131
|
-
></${ElementBookEntryDisplay}>
|
|
132
|
-
</div>
|
|
133
|
-
`;
|
|
134
145
|
},
|
|
135
146
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { HTMLTemplateResult } from 'element-vir';
|
|
1
2
|
import { EntryTreeNode } from '../../../data/element-book-entry/entry-tree/entry-tree';
|
|
2
3
|
import { ElementBookFullRoute } from '../../../routing/element-book-routing';
|
|
3
4
|
export declare const ElementBookEntryDisplay: import("element-vir").DeclarativeElementDefinition<"element-book-entry-display", {
|
|
4
5
|
currentRoute: Readonly<ElementBookFullRoute>;
|
|
5
6
|
currentNode: Readonly<EntryTreeNode>;
|
|
6
|
-
}, {}, {}, string, string,
|
|
7
|
+
}, {}, {}, string, string, HTMLTemplateResult, undefined>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { VirIcon } from '@electrovir/icon-element';
|
|
2
2
|
import { assign, css, html, renderIf } from 'element-vir';
|
|
3
|
+
import { isElementBookEntry } from '../../../data/element-book-entry/element-book-entry';
|
|
3
4
|
import { ElementBookEntryTypeEnum } from '../../../data/element-book-entry/element-book-entry-type';
|
|
4
5
|
import { listBreadcrumbs, } from '../../../data/element-book-entry/entry-tree/entry-tree';
|
|
5
6
|
import { colorThemeCssVars } from '../../color-theme/color-theme';
|
|
@@ -44,27 +45,9 @@ export const ElementBookEntryDisplay = defineElementBookElement()({
|
|
|
44
45
|
}
|
|
45
46
|
`,
|
|
46
47
|
renderCallback: ({ inputs }) => {
|
|
47
|
-
const
|
|
48
|
+
const nestedPages = extractNestedPages(inputs.currentNode);
|
|
48
49
|
const entryBreadcrumbs = listBreadcrumbs(inputs.currentNode.entry, true);
|
|
49
|
-
const
|
|
50
|
-
const exampleTemplates = descendantPages.map((descendantPage) => {
|
|
51
|
-
return html `
|
|
52
|
-
<div class="page-examples">
|
|
53
|
-
${renderIf(showPageTitles, html `
|
|
54
|
-
<h2>
|
|
55
|
-
<${VirIcon} ${assign(VirIcon, { icon: Element24Icon })}></${VirIcon}>
|
|
56
|
-
${descendantPage.title}
|
|
57
|
-
</h2>
|
|
58
|
-
`)}
|
|
59
|
-
<${ElementBookPageExamples}
|
|
60
|
-
${assign(ElementBookPageExamples, {
|
|
61
|
-
page: descendantPage,
|
|
62
|
-
parentBreadcrumbs: entryBreadcrumbs,
|
|
63
|
-
})}
|
|
64
|
-
></${ElementBookPageExamples}>
|
|
65
|
-
</div>
|
|
66
|
-
`;
|
|
67
|
-
});
|
|
50
|
+
const exampleTemplates = createNestedPagesTemplates(nestedPages, entryBreadcrumbs, true);
|
|
68
51
|
return html `
|
|
69
52
|
<div class="title-bar">
|
|
70
53
|
<${ElementBookBreadcrumbs}
|
|
@@ -75,9 +58,52 @@ export const ElementBookEntryDisplay = defineElementBookElement()({
|
|
|
75
58
|
`;
|
|
76
59
|
},
|
|
77
60
|
});
|
|
78
|
-
function
|
|
61
|
+
function createNestedPagesTemplates(nestedPages, parentBreadcrumbs, isTopLevel) {
|
|
62
|
+
const showTitles = !isTopLevel &&
|
|
63
|
+
(nestedPages.length !== 1 || nestedPages[0]?.type !== ElementBookEntryTypeEnum.Page);
|
|
64
|
+
return nestedPages
|
|
65
|
+
.map((nesting) => {
|
|
66
|
+
if (isElementBookEntry(nesting, ElementBookEntryTypeEnum.Page)) {
|
|
67
|
+
return html `
|
|
68
|
+
<div class="page-examples">
|
|
69
|
+
${renderIf(showTitles, html `
|
|
70
|
+
<h2>
|
|
71
|
+
<${VirIcon}
|
|
72
|
+
${assign(VirIcon, { icon: Element24Icon })}
|
|
73
|
+
></${VirIcon}>
|
|
74
|
+
${nesting.title}
|
|
75
|
+
</h2>
|
|
76
|
+
`)}
|
|
77
|
+
<${ElementBookPageExamples}
|
|
78
|
+
${assign(ElementBookPageExamples, {
|
|
79
|
+
page: nesting,
|
|
80
|
+
parentBreadcrumbs: parentBreadcrumbs,
|
|
81
|
+
})}
|
|
82
|
+
></${ElementBookPageExamples}>
|
|
83
|
+
</div>
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
return Object.entries(nesting).map(([title, nextNesting,]) => {
|
|
88
|
+
return html `
|
|
89
|
+
${renderIf(showTitles, html `
|
|
90
|
+
<h1>${title}</h1>
|
|
91
|
+
`)}
|
|
92
|
+
${createNestedPagesTemplates(nextNesting, parentBreadcrumbs, false)}
|
|
93
|
+
`;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
.flat();
|
|
98
|
+
}
|
|
99
|
+
function extractNestedPages(node) {
|
|
79
100
|
if (node.entry.type === ElementBookEntryTypeEnum.Page) {
|
|
80
101
|
return [node.entry];
|
|
81
102
|
}
|
|
82
|
-
|
|
103
|
+
const nestedPages = [
|
|
104
|
+
{
|
|
105
|
+
[node.entry.title]: Object.values(node.children).map(extractNestedPages).flat(),
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
return nestedPages;
|
|
83
109
|
}
|