element-book 26.12.0 → 26.12.1

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.
Files changed (113) hide show
  1. package/{src/data/book-entry/base-book-entry.ts → dist/data/book-entry/base-book-entry.d.ts} +2 -3
  2. package/dist/data/book-entry/base-book-entry.js +1 -0
  3. package/{src/data/book-entry/book-entry-type.ts → dist/data/book-entry/book-entry-type.d.ts} +5 -9
  4. package/dist/data/book-entry/book-entry-type.js +14 -0
  5. package/dist/data/book-entry/book-entry.d.ts +17 -0
  6. package/dist/data/book-entry/book-entry.js +9 -0
  7. package/dist/data/book-entry/book-page/book-page-controls.d.ts +92 -0
  8. package/dist/data/book-entry/book-page/book-page-controls.js +70 -0
  9. package/dist/data/book-entry/book-page/book-page.d.ts +63 -0
  10. package/dist/data/book-entry/book-page/book-page.js +2 -0
  11. package/dist/data/book-entry/book-page/controls-wrapper.d.ts +32 -0
  12. package/dist/data/book-entry/book-page/controls-wrapper.js +65 -0
  13. package/dist/data/book-entry/book-page/define-book-page.d.ts +58 -0
  14. package/dist/data/book-entry/book-page/define-book-page.js +52 -0
  15. package/dist/data/book-entry/book-root.d.ts +12 -0
  16. package/dist/data/book-entry/book-root.js +1 -0
  17. package/dist/data/book-entry/url-breadcrumbs.d.ts +23 -0
  18. package/{src/data/book-entry/url-breadcrumbs.ts → dist/data/book-entry/url-breadcrumbs.js} +8 -17
  19. package/dist/data/book-entry/verify-book-entry.d.ts +3 -0
  20. package/{src/data/book-entry/verify-book-entry.ts → dist/data/book-entry/verify-book-entry.js} +3 -9
  21. package/{src/data/book-tree/book-tree-node.ts → dist/data/book-tree/book-tree-node.d.ts} +9 -15
  22. package/dist/data/book-tree/book-tree-node.js +6 -0
  23. package/dist/data/book-tree/book-tree.d.ts +13 -0
  24. package/dist/data/book-tree/book-tree.js +136 -0
  25. package/dist/data/book-tree/search-nodes.d.ts +5 -0
  26. package/dist/data/book-tree/search-nodes.js +74 -0
  27. package/dist/data/book-tree/tree-cache.d.ts +4 -0
  28. package/dist/data/book-tree/tree-cache.js +8 -0
  29. package/dist/data/unset.d.ts +1 -0
  30. package/dist/index.js +18 -0
  31. package/dist/routing/book-router.d.ts +4 -0
  32. package/{src/routing/book-router.ts → dist/routing/book-router.js} +12 -16
  33. package/{src/routing/book-routing.ts → dist/routing/book-routing.d.ts} +6 -21
  34. package/dist/routing/book-routing.js +33 -0
  35. package/dist/ui/color-theme/color-theme.d.ts +57 -0
  36. package/dist/ui/color-theme/color-theme.js +94 -0
  37. package/dist/ui/color-theme/create-color-theme.d.ts +32 -0
  38. package/dist/ui/color-theme/create-color-theme.js +93 -0
  39. package/dist/ui/elements/book-breadcrumbs.element.d.ts +6 -0
  40. package/dist/ui/elements/book-breadcrumbs.element.js +50 -0
  41. package/dist/ui/elements/book-nav/book-nav-filter.d.ts +2 -0
  42. package/dist/ui/elements/book-nav/book-nav-filter.js +15 -0
  43. package/dist/ui/elements/book-nav/book-nav.element.d.ts +8 -0
  44. package/{src/ui/elements/book-nav/book-nav.element.ts → dist/ui/elements/book-nav/book-nav.element.js} +44 -65
  45. package/dist/ui/elements/common/book-error.element.d.ts +3 -0
  46. package/{src/ui/elements/common/book-error.element.ts → dist/ui/elements/common/book-error.element.js} +8 -12
  47. package/dist/ui/elements/common/book-route-link.element.d.ts +6 -0
  48. package/dist/ui/elements/common/book-route-link.element.js +40 -0
  49. package/dist/ui/elements/define-book-element.d.ts +2 -0
  50. package/dist/ui/elements/define-book-element.js +2 -0
  51. package/{src/ui/elements/element-book-app/element-book-app-slots.ts → dist/ui/elements/element-book-app/element-book-app-slots.d.ts} +3 -3
  52. package/dist/ui/elements/element-book-app/element-book-app-slots.js +18 -0
  53. package/dist/ui/elements/element-book-app/element-book-app.element.d.ts +35 -0
  54. package/dist/ui/elements/element-book-app/element-book-app.element.js +301 -0
  55. package/dist/ui/elements/element-book-app/element-book-config.d.ts +48 -0
  56. package/dist/ui/elements/element-book-app/element-book-config.js +1 -0
  57. package/dist/ui/elements/element-book-app/get-current-nodes.d.ts +3 -0
  58. package/dist/ui/elements/element-book-app/get-current-nodes.js +18 -0
  59. package/dist/ui/elements/element-book-app/global-values.js +1 -0
  60. package/dist/ui/elements/entry-display/book-breadcrumbs-bar.element.d.ts +7 -0
  61. package/dist/ui/elements/entry-display/book-breadcrumbs-bar.element.js +60 -0
  62. package/dist/ui/elements/entry-display/book-entry-description.element.d.ts +4 -0
  63. package/{src/ui/elements/entry-display/book-entry-description.element.ts → dist/ui/elements/entry-display/book-entry-description.element.js} +7 -10
  64. package/dist/ui/elements/entry-display/book-page/book-page-controls.element.d.ts +17 -0
  65. package/dist/ui/elements/entry-display/book-page/book-page-controls.element.js +172 -0
  66. package/dist/ui/elements/entry-display/book-page/book-page-wrapper.element.d.ts +10 -0
  67. package/dist/ui/elements/entry-display/book-page/book-page-wrapper.element.js +86 -0
  68. package/dist/ui/elements/entry-display/element-example/book-element-example-controls.element.d.ts +7 -0
  69. package/dist/ui/elements/entry-display/element-example/book-element-example-controls.element.js +34 -0
  70. package/dist/ui/elements/entry-display/element-example/book-element-example-viewer.element.d.ts +7 -0
  71. package/dist/ui/elements/entry-display/element-example/book-element-example-viewer.element.js +61 -0
  72. package/dist/ui/elements/entry-display/element-example/book-element-example-wrapper.element.d.ts +9 -0
  73. package/dist/ui/elements/entry-display/element-example/book-element-example-wrapper.element.js +50 -0
  74. package/dist/ui/elements/entry-display/entry-display/book-entry-display.element.d.ts +18 -0
  75. package/{src/ui/elements/entry-display/entry-display/book-entry-display.element.ts → dist/ui/elements/entry-display/entry-display/book-entry-display.element.js} +27 -49
  76. package/dist/ui/elements/entry-display/entry-display/create-node-templates.d.ts +13 -0
  77. package/dist/ui/elements/entry-display/entry-display/create-node-templates.js +113 -0
  78. package/dist/ui/events/change-route.event.d.ts +1 -0
  79. package/dist/ui/events/change-route.event.js +2 -0
  80. package/dist/util/fuzzy-search.d.ts +34 -0
  81. package/{src/util/fuzzy-search.ts → dist/util/fuzzy-search.js} +5 -13
  82. package/{src/util/type.ts → dist/util/type.d.ts} +4 -3
  83. package/dist/util/type.js +1 -0
  84. package/package.json +5 -5
  85. package/src/data/book-entry/book-entry.ts +0 -23
  86. package/src/data/book-entry/book-page/book-page-controls.ts +0 -159
  87. package/src/data/book-entry/book-page/book-page.ts +0 -110
  88. package/src/data/book-entry/book-page/controls-wrapper.ts +0 -119
  89. package/src/data/book-entry/book-page/define-book-page.ts +0 -171
  90. package/src/data/book-entry/book-root.ts +0 -16
  91. package/src/data/book-tree/book-tree.ts +0 -225
  92. package/src/data/book-tree/search-nodes.ts +0 -104
  93. package/src/data/book-tree/tree-cache.ts +0 -13
  94. package/src/ui/color-theme/color-theme.ts +0 -152
  95. package/src/ui/color-theme/create-color-theme.ts +0 -139
  96. package/src/ui/elements/book-breadcrumbs.element.ts +0 -60
  97. package/src/ui/elements/book-nav/book-nav-filter.ts +0 -30
  98. package/src/ui/elements/common/book-route-link.element.ts +0 -48
  99. package/src/ui/elements/define-book-element.ts +0 -5
  100. package/src/ui/elements/element-book-app/element-book-app.element.ts +0 -380
  101. package/src/ui/elements/element-book-app/element-book-config.ts +0 -52
  102. package/src/ui/elements/element-book-app/get-current-nodes.ts +0 -35
  103. package/src/ui/elements/entry-display/book-breadcrumbs-bar.element.ts +0 -78
  104. package/src/ui/elements/entry-display/book-page/book-page-controls.element.ts +0 -219
  105. package/src/ui/elements/entry-display/book-page/book-page-wrapper.element.ts +0 -105
  106. package/src/ui/elements/entry-display/element-example/book-element-example-controls.element.ts +0 -42
  107. package/src/ui/elements/entry-display/element-example/book-element-example-viewer.element.ts +0 -79
  108. package/src/ui/elements/entry-display/element-example/book-element-example-wrapper.element.ts +0 -61
  109. package/src/ui/elements/entry-display/entry-display/create-node-templates.ts +0 -183
  110. package/src/ui/events/change-route.event.ts +0 -6
  111. /package/{src/data/unset.ts → dist/data/unset.js} +0 -0
  112. /package/{src/index.ts → dist/index.d.ts} +0 -0
  113. /package/{src/ui/elements/element-book-app/global-values.ts → dist/ui/elements/element-book-app/global-values.d.ts} +0 -0
@@ -1,225 +0,0 @@
1
- import {check} from '@augment-vir/assert';
2
- import {BookEntryType} from '../book-entry/book-entry-type.js';
3
- import {type BookEntry, isBookEntry} from '../book-entry/book-entry.js';
4
- import {listUrlBreadcrumbs, titleToUrlBreadcrumb} from '../book-entry/url-breadcrumbs.js';
5
- import {bookEntryVerifiers} from '../book-entry/verify-book-entry.js';
6
- import {type BookTree, type BookTreeNode, isBookTreeNodeMarker} from './book-tree-node.js';
7
- import {addTreeToCache, getTreeFromCache} from './tree-cache.js';
8
-
9
- export function doesNodeHaveEntryType<const EntryType extends BookEntryType>(
10
- node: unknown,
11
- entryType: EntryType,
12
- ): node is BookTreeNode<EntryType> {
13
- return (
14
- check.hasKey(node, 'entry') &&
15
- check.isObject(node.entry) &&
16
- node.entry.entryType === entryType
17
- );
18
- }
19
-
20
- export function isBookTreeNode<const SpecificType extends BookEntryType>(
21
- input: unknown,
22
- entryType: SpecificType,
23
- ): input is BookTreeNode<SpecificType> {
24
- return isAnyBookTreeNode(input) && input.entry.entryType === entryType;
25
- }
26
-
27
- export function isAnyBookTreeNode(input: unknown): input is BookTreeNode<BookEntryType> {
28
- return !!(
29
- check.hasKeys(input, [
30
- isBookTreeNodeMarker,
31
- 'entry',
32
- ]) && input[isBookTreeNodeMarker]
33
- );
34
- }
35
-
36
- export function createEmptyBookTreeRoot(): BookTreeNode<BookEntryType.Root> {
37
- const rootNode: Readonly<BookTreeNode<BookEntryType.Root>> = {
38
- [isBookTreeNodeMarker]: true,
39
- entry: {
40
- entryType: BookEntryType.Root,
41
- title: '',
42
- parent: undefined,
43
- errors: [],
44
- descriptionParagraphs: [],
45
- },
46
- urlBreadcrumb: '',
47
- fullUrlBreadcrumbs: [],
48
- children: {} as Record<string, BookTreeNode>,
49
- manuallyAdded: true,
50
- };
51
-
52
- return rootNode;
53
- }
54
-
55
- export function createBookTreeFromEntries({
56
- entries,
57
- debug,
58
- }: {
59
- entries: ReadonlyArray<BookEntry>;
60
- debug: boolean;
61
- }): BookTree {
62
- const cachedTree = getTreeFromCache(entries);
63
- if (cachedTree) {
64
- return cachedTree;
65
- }
66
-
67
- const tree = createEmptyBookTreeRoot();
68
-
69
- entries.forEach((newEntry) => addEntryToTree({tree, newEntry, debug, manuallyAdded: true}));
70
-
71
- const flattenedNodes = flattenTree(tree);
72
-
73
- const bookTree: BookTree = {
74
- tree,
75
- flattenedNodes,
76
- };
77
-
78
- addTreeToCache(entries, bookTree);
79
-
80
- if (debug) {
81
- console.info('element-book tree:', tree);
82
- }
83
-
84
- return bookTree;
85
- }
86
-
87
- function getOrAddImmediateParent(
88
- tree: BookTreeNode<BookEntryType.Root>,
89
- entry: BookEntry,
90
- debug: boolean,
91
- ): BookTreeNode {
92
- if (!entry.parent) {
93
- return tree;
94
- }
95
-
96
- const immediateParent = traverseToImmediateParent(entry, tree);
97
-
98
- if (immediateParent) {
99
- return immediateParent;
100
- }
101
-
102
- if (debug) {
103
- console.info(`parent of ${entry.title} not found in tree; adding it now.`);
104
- }
105
-
106
- addEntryToTree({tree, newEntry: entry.parent, debug, manuallyAdded: false});
107
- const immediateParentAfterAdding = traverseToImmediateParent(entry, tree);
108
-
109
- if (!immediateParentAfterAdding) {
110
- throw new Error(
111
- `Failed to find node despite having just added it: ${listUrlBreadcrumbs(entry, false).join(' > ')}`,
112
- );
113
- }
114
-
115
- return immediateParentAfterAdding;
116
- }
117
-
118
- function addEntryToTree({
119
- tree,
120
- newEntry,
121
- debug,
122
- manuallyAdded,
123
- }: {
124
- tree: BookTreeNode<BookEntryType.Root>;
125
- newEntry: BookEntry;
126
- debug: boolean;
127
- manuallyAdded: boolean;
128
- }) {
129
- const errors = bookEntryVerifiers[newEntry.entryType](newEntry);
130
-
131
- newEntry.errors.push(...errors);
132
-
133
- const immediateParent = getOrAddImmediateParent(tree, newEntry, debug);
134
-
135
- const newEntryUrlBreadcrumb = titleToUrlBreadcrumb(newEntry.title);
136
-
137
- const existingChild = immediateParent.children[newEntryUrlBreadcrumb];
138
-
139
- if (existingChild) {
140
- // ignores multiple entries that have been added by following parent chains
141
- if (manuallyAdded) {
142
- if (existingChild.manuallyAdded) {
143
- existingChild.entry.errors.push(
144
- new Error(
145
- `Cannot create duplicate '${newEntryUrlBreadcrumb}'${
146
- immediateParent.urlBreadcrumb
147
- ? ` in parent '${immediateParent.urlBreadcrumb}'.`
148
- : ''
149
- }`,
150
- ),
151
- );
152
-
153
- return;
154
- }
155
-
156
- existingChild.manuallyAdded = true;
157
- }
158
-
159
- return;
160
- }
161
-
162
- const newNode: BookTreeNode = {
163
- [isBookTreeNodeMarker]: true,
164
- children: {},
165
- urlBreadcrumb: newEntryUrlBreadcrumb,
166
- fullUrlBreadcrumbs: [
167
- ...immediateParent.fullUrlBreadcrumbs,
168
- newEntryUrlBreadcrumb,
169
- ],
170
- entry: newEntry,
171
- manuallyAdded,
172
- };
173
-
174
- immediateParent.children[newEntryUrlBreadcrumb] = newNode;
175
-
176
- if (
177
- isBookEntry(newEntry, BookEntryType.Page) &&
178
- Object.values(newEntry.elementExamples).length
179
- ) {
180
- Object.values(newEntry.elementExamples).forEach((elementExample) =>
181
- addEntryToTree({tree, newEntry: elementExample, debug, manuallyAdded}),
182
- );
183
- }
184
- }
185
-
186
- export function traverseToImmediateParent(
187
- entryOrNode: Readonly<BookEntry> | BookTreeNode,
188
- currentTree: Readonly<BookTreeNode>,
189
- ): BookTreeNode | undefined {
190
- const breadcrumbs: string[] = isAnyBookTreeNode(entryOrNode)
191
- ? entryOrNode.fullUrlBreadcrumbs.slice(0, -1)
192
- : listUrlBreadcrumbs(entryOrNode, false);
193
-
194
- if (!breadcrumbs.length) {
195
- return undefined;
196
- }
197
-
198
- const immediateParentNode: BookTreeNode | undefined = breadcrumbs.reduce(
199
- (currentAncestor, nextBreadcrumb) => {
200
- if (!currentAncestor) {
201
- return undefined;
202
- }
203
-
204
- return currentAncestor.children[nextBreadcrumb];
205
- },
206
- currentTree as typeof currentTree | undefined,
207
- );
208
-
209
- return immediateParentNode;
210
- }
211
-
212
- export function flattenTree(node: Readonly<BookTreeNode>): BookTreeNode[] {
213
- const hasErrors: boolean = !!node.entry.errors.length;
214
-
215
- const childNodes = hasErrors
216
- ? []
217
- : Object.values(node.children).map((child) => flattenTree(child));
218
-
219
- const entries: BookTreeNode[] = [
220
- node,
221
- ...childNodes,
222
- ].flat();
223
-
224
- return entries;
225
- }
@@ -1,104 +0,0 @@
1
- import {check} from '@augment-vir/assert';
2
- import {randomString} from '@augment-vir/common';
3
- import {convertTemplateToString} from 'element-vir';
4
- import {fuzzySearch} from '../../util/fuzzy-search.js';
5
- import {type BookTreeNode} from './book-tree-node.js';
6
-
7
- const searchJoin = randomString(32);
8
-
9
- function createBreadcrumbsSearchKey(breadcrumbs: ReadonlyArray<string>): string {
10
- return breadcrumbs.join(searchJoin);
11
- }
12
-
13
- type SearchInclusions = Record<string, boolean>;
14
-
15
- function getFullTreeKeysToInclude(breadcrumbs: ReadonlyArray<string>): string[] {
16
- if (!breadcrumbs.length) {
17
- return [];
18
- }
19
-
20
- const currentKey = createBreadcrumbsSearchKey(breadcrumbs);
21
-
22
- const ancestorKeys = getFullTreeKeysToInclude(breadcrumbs.slice(0, -1));
23
-
24
- return [
25
- currentKey,
26
- ...ancestorKeys,
27
- ];
28
- }
29
-
30
- const errorQueries = [
31
- 'error',
32
- 'errors',
33
- ];
34
- function isSearchingForErrors(searchQuery: string): boolean {
35
- return errorQueries.includes(searchQuery);
36
- }
37
-
38
- export function searchFlattenedNodes({
39
- flattenedNodes,
40
- searchQuery,
41
- }: {
42
- flattenedNodes: ReadonlyArray<BookTreeNode>;
43
- searchQuery: string;
44
- }): ReadonlyArray<BookTreeNode> {
45
- const includeInSearchResults: SearchInclusions = {};
46
-
47
- function addChildren(treeNode: BookTreeNode) {
48
- const childrenKeys = Object.values(treeNode.children).map((child) => {
49
- addChildren(child);
50
- return createBreadcrumbsSearchKey(child.fullUrlBreadcrumbs);
51
- });
52
-
53
- childrenKeys.forEach((keyToInclude) => (includeInSearchResults[keyToInclude] = true));
54
- }
55
-
56
- flattenedNodes.forEach((treeNode) => {
57
- const matchesErrors = treeNode.entry.errors.length && isSearchingForErrors(searchQuery);
58
- const currentNodeSearchKey = createBreadcrumbsSearchKey(treeNode.fullUrlBreadcrumbs);
59
- const shouldInclude =
60
- fuzzySearch({
61
- searchIn: [
62
- treeNode.entry.title,
63
- ...treeNode.entry.descriptionParagraphs.map((paragraph) => {
64
- if (check.isString(paragraph)) {
65
- return paragraph;
66
- } else {
67
- return convertTemplateToString(paragraph);
68
- }
69
- }),
70
- ]
71
- .join(' ')
72
- .toLowerCase(),
73
- searchQuery: searchQuery.toLowerCase(),
74
- }) ||
75
- matchesErrors ||
76
- includeInSearchResults[currentNodeSearchKey];
77
-
78
- if (shouldInclude) {
79
- const keysToInclude = getFullTreeKeysToInclude(treeNode.fullUrlBreadcrumbs);
80
-
81
- addChildren(treeNode);
82
-
83
- keysToInclude.forEach((keyToInclude) => (includeInSearchResults[keyToInclude] = true));
84
- } else {
85
- includeInSearchResults[currentNodeSearchKey] = false;
86
- }
87
- });
88
-
89
- return flattenedNodes.filter((treeNode): boolean => {
90
- const inSearchResultsKey = createBreadcrumbsSearchKey(treeNode.fullUrlBreadcrumbs);
91
-
92
- const shouldInclude = includeInSearchResults[inSearchResultsKey];
93
-
94
- if (!check.isBoolean(shouldInclude)) {
95
- throw new TypeError(
96
- `Failed to find '${treeNode.fullUrlBreadcrumbs.join(
97
- ' > ',
98
- )}' in includeInSearchResults.`,
99
- );
100
- }
101
-
102
- return shouldInclude;
103
- });
104
- }
@@ -1,13 +0,0 @@
1
- import {getOrSetFromMap} from '@augment-vir/common';
2
- import {type BookEntry} from '../book-entry/book-entry.js';
3
- import {type BookTree} from './book-tree-node.js';
4
-
5
- const treeCache = new Map<ReadonlyArray<BookEntry>, BookTree>();
6
-
7
- export function getTreeFromCache(entries: ReadonlyArray<BookEntry>): BookTree | undefined {
8
- return treeCache.get(entries);
9
- }
10
-
11
- export function addTreeToCache(entries: ReadonlyArray<BookEntry>, tree: BookTree): void {
12
- getOrSetFromMap(treeCache, entries, () => tree);
13
- }
@@ -1,152 +0,0 @@
1
- import {check} from '@augment-vir/assert';
2
- import {type CSSResult} from 'element-vir';
3
- import {type SingleCssVarDefinition, defineCssVars, setCssVarValue} from 'lit-css-vars';
4
- import {type NestedType} from '../../util/type.js';
5
-
6
- /**
7
- * A single background and foreground color pairing.
8
- *
9
- * @category Internal
10
- */
11
- export type ColorPair = {background: CSSResult; foreground: CSSResult};
12
-
13
- /**
14
- * Color pairs for everything used by the element-book app.
15
- *
16
- * @category Internal
17
- */
18
- export type ColorTheme = {
19
- nav: {
20
- hover: ColorPair;
21
- active: ColorPair;
22
- selected: ColorPair;
23
- };
24
- accent: {
25
- icon: CSSResult;
26
- };
27
- page: ColorPair & {
28
- backgroundFaint1: CSSResult;
29
- backgroundFaint2: CSSResult;
30
- foregroundFaint1: CSSResult;
31
- foregroundFaint2: CSSResult;
32
- };
33
- };
34
-
35
- type CssResultToCssVar<StartingPoint> = {
36
- [PropName in keyof StartingPoint]: StartingPoint[PropName] extends CSSResult
37
- ? SingleCssVarDefinition
38
- : CssResultToCssVar<StartingPoint[PropName]>;
39
- };
40
-
41
- type ColorThemeCssVars = CssResultToCssVar<ColorTheme>;
42
-
43
- /**
44
- * All color theme CSS vars for the element-book app.
45
- *
46
- * @category Internal
47
- */
48
- export const colorThemeCssVars = defineCssVars({
49
- 'element-book-nav-hover-background-color': 'magenta',
50
- 'element-book-nav-hover-foreground-color': 'magenta',
51
- 'element-book-nav-active-background-color': 'magenta',
52
- 'element-book-nav-active-foreground-color': 'magenta',
53
- 'element-book-nav-selected-background-color': 'magenta',
54
- 'element-book-nav-selected-foreground-color': 'magenta',
55
- 'element-book-accent-icon-color': 'magenta',
56
- 'element-book-page-background-color': 'magenta',
57
- 'element-book-page-background-faint-level-1-color': 'magenta',
58
- 'element-book-page-background-faint-level-2-color': 'magenta',
59
- 'element-book-page-foreground-color': 'magenta',
60
- 'element-book-page-foreground-faint-level-1-color': 'magenta',
61
- 'element-book-page-foreground-faint-level-2-color': 'magenta',
62
- });
63
-
64
- const colorThemeCssVarMapping: ColorThemeCssVars = {
65
- nav: {
66
- hover: {
67
- background: colorThemeCssVars['element-book-nav-hover-background-color'],
68
- foreground: colorThemeCssVars['element-book-nav-hover-foreground-color'],
69
- },
70
- active: {
71
- background: colorThemeCssVars['element-book-nav-active-background-color'],
72
- foreground: colorThemeCssVars['element-book-nav-active-foreground-color'],
73
- },
74
- selected: {
75
- background: colorThemeCssVars['element-book-nav-selected-background-color'],
76
- foreground: colorThemeCssVars['element-book-nav-selected-foreground-color'],
77
- },
78
- },
79
- accent: {
80
- icon: colorThemeCssVars['element-book-accent-icon-color'],
81
- },
82
- page: {
83
- background: colorThemeCssVars['element-book-page-background-color'],
84
- backgroundFaint1: colorThemeCssVars['element-book-page-background-faint-level-1-color'],
85
- backgroundFaint2: colorThemeCssVars['element-book-page-background-faint-level-2-color'],
86
- foreground: colorThemeCssVars['element-book-page-foreground-color'],
87
- foregroundFaint1: colorThemeCssVars['element-book-page-foreground-faint-level-1-color'],
88
- foregroundFaint2: colorThemeCssVars['element-book-page-foreground-faint-level-2-color'],
89
- },
90
- };
91
-
92
- /**
93
- * Sets a new color theme's CSS vars on the given HTML element for the element-book app.
94
- *
95
- * @category Internal
96
- */
97
- export function setThemeCssVars(element: HTMLElement, theme: ColorTheme) {
98
- recursiveSetThemeCssVars(element, theme, colorThemeCssVarMapping);
99
- }
100
-
101
- function isCssResult(input: unknown): input is CSSResult {
102
- return check.hasKey(input, '_$cssResult$');
103
- }
104
-
105
- function isCssVarDefinition(input: unknown): input is SingleCssVarDefinition {
106
- return (
107
- check.hasKeys(input, [
108
- 'name',
109
- 'value',
110
- 'default',
111
- ]) &&
112
- check.isString(input.default) &&
113
- isCssResult(input.name) &&
114
- isCssResult(input.value)
115
- );
116
- }
117
-
118
- function recursiveSetThemeCssVars(
119
- element: HTMLElement,
120
- nestedCssResult: NestedType<CSSResult>,
121
- nestedCssVars: NestedType<SingleCssVarDefinition>,
122
- ) {
123
- Object.entries(nestedCssResult).forEach(
124
- ([
125
- key,
126
- value,
127
- ]) => {
128
- const nestedCssVar = nestedCssVars[key];
129
-
130
- if (!nestedCssVar) {
131
- throw new Error(`no nestedCssVar at key '${key}'`);
132
- }
133
-
134
- if (isCssResult(value)) {
135
- if (!isCssVarDefinition(nestedCssVar)) {
136
- throw new Error(`got a CSS result at '${key}' but no CSS var`);
137
- }
138
-
139
- setCssVarValue({
140
- forCssVar: nestedCssVar,
141
- onElement: element,
142
- toValue: String(value),
143
- });
144
- } else {
145
- if (isCssVarDefinition(nestedCssVar)) {
146
- throw new Error(`got no CSS result at '${key}' but did find a CSS var`);
147
- }
148
- recursiveSetThemeCssVars(element, value, nestedCssVar);
149
- }
150
- },
151
- );
152
- }
@@ -1,139 +0,0 @@
1
- import {type PartialWithUndefined, mapObjectValues} from '@augment-vir/common';
2
- import Color from 'colorjs.io';
3
- import {type CSSResult, unsafeCSS} from 'element-vir';
4
- import {type RequireExactlyOne} from 'type-fest';
5
- import {type NestedType} from '../../util/type.js';
6
- import {type ColorTheme} from './color-theme.js';
7
-
8
- // as cast because colorjs.io's types for itself are wrong
9
- type FixedColor = Color & {
10
- set: (input: Record<string, number>) => Color;
11
- };
12
-
13
- type NestedColors = NestedType<Color>;
14
-
15
- type NestedColorsToCssResult<Colors extends Readonly<NestedColors>> = {
16
- [PropName in keyof Colors]: Colors[PropName] extends Color
17
- ? CSSResult
18
- : NestedColorsToCssResult<Exclude<Colors[PropName], Color>>;
19
- };
20
-
21
- function colorsObjectToCssResult<const Colors extends NestedColors>(
22
- colors: Colors,
23
- ): NestedColorsToCssResult<Colors> {
24
- return mapObjectValues(colors, (key, value) => {
25
- if (value instanceof Color) {
26
- return unsafeCSS(value.toString({format: 'hex'}));
27
- } else {
28
- return colorsObjectToCssResult(value);
29
- }
30
- }) as NestedColorsToCssResult<Colors>;
31
- }
32
-
33
- /**
34
- * The default theme color.
35
- *
36
- * @category Internal
37
- */
38
- export const defaultThemeStartColor = 'dodgerblue';
39
-
40
- type BackForeGroundColor = 'black' | 'white';
41
-
42
- function calculateTextColorString(color: Color): BackForeGroundColor {
43
- const onWhite = Math.abs(color.contrast('white', 'APCA'));
44
- const onBlack = Math.abs(color.contrast('black', 'APCA'));
45
- const textColorString = onWhite > onBlack ? 'white' : 'black';
46
- return textColorString;
47
- }
48
-
49
- function createColorPair({
50
- background,
51
- foreground,
52
- }: RequireExactlyOne<{background: Color; foreground: Color}>) {
53
- return {
54
- background: background ?? new Color(calculateTextColorString(foreground)),
55
- foreground: foreground ?? new Color(calculateTextColorString(background)),
56
- };
57
- }
58
-
59
- /**
60
- * Theme style options for the element-book app.
61
- *
62
- * @category Internal
63
- */
64
- export enum ThemeStyle {
65
- Dark = 'dark',
66
- Light = 'light',
67
- }
68
-
69
- /**
70
- * Theme configuration options for the element-book app.
71
- *
72
- * @category Internal
73
- */
74
- export type ThemeConfig = PartialWithUndefined<{
75
- themeColor: string;
76
- themeStyle: ThemeStyle;
77
- }>;
78
-
79
- function flipBackForeground(input: BackForeGroundColor): BackForeGroundColor {
80
- return input === 'black' ? 'white' : 'black';
81
- }
82
-
83
- const faintForegroundColors = {
84
- black: {
85
- foregroundFaint1: new Color('#ccc'),
86
- foregroundFaint2: new Color('#eee'),
87
- },
88
- white: {
89
- foregroundFaint1: new Color('#ccc'),
90
- foregroundFaint2: new Color('#eee'),
91
- },
92
- } as const;
93
-
94
- const faintBackgroundColors = {
95
- black: {
96
- backgroundFaint1: new Color('#666'),
97
- backgroundFaint2: new Color('#444'),
98
- },
99
- white: {
100
- backgroundFaint1: new Color('#ccc'),
101
- backgroundFaint2: new Color('#fafafa'),
102
- },
103
- } as const;
104
-
105
- /**
106
- * Creates a theme from the given theme configuration.
107
- *
108
- * @category Internal
109
- */
110
- export function createTheme({
111
- themeColor: inputThemeColor = defaultThemeStartColor,
112
- themeStyle = ThemeStyle.Light,
113
- }: ThemeConfig = {}): ColorTheme {
114
- const themeColor = new Color(inputThemeColor) as FixedColor;
115
- const backgroundColor = new Color(themeStyle === ThemeStyle.Dark ? 'black' : 'white');
116
- const foregroundColorString = calculateTextColorString(backgroundColor);
117
- const foregroundColor = new Color(foregroundColorString);
118
-
119
- const colors = {
120
- nav: {
121
- hover: createColorPair({background: themeColor.clone().set({'hsl.l': 93})}),
122
- active: createColorPair({background: themeColor.clone().set({'hsl.l': 90})}),
123
- selected: createColorPair({background: themeColor.clone().set({'hsl.l': 85})}),
124
- },
125
- accent: {
126
- icon: themeColor.clone().set({'hsl.l': 40}),
127
- },
128
- page: {
129
- background: backgroundColor,
130
- ...faintBackgroundColors[flipBackForeground(foregroundColorString)],
131
- foreground: foregroundColor,
132
- ...faintForegroundColors[foregroundColorString],
133
- },
134
- } as const;
135
-
136
- const convertedToCssResults = colorsObjectToCssResult(colors);
137
-
138
- return convertedToCssResults;
139
- }
@@ -1,60 +0,0 @@
1
- import {css, html} from 'element-vir';
2
- import {type BookRouter} from '../../routing/book-router.js';
3
- import {type BookFullRoute, BookMainRoute} from '../../routing/book-routing.js';
4
- import {BookRouteLink} from './common/book-route-link.element.js';
5
- import {defineBookElement} from './define-book-element.js';
6
-
7
- export const BookBreadcrumbs = defineBookElement<{
8
- currentRoute: Readonly<BookFullRoute>;
9
- router: Readonly<BookRouter> | undefined;
10
- }>()({
11
- tagName: 'book-breadcrumbs',
12
- styles: css`
13
- :host {
14
- display: flex;
15
- color: #999;
16
- }
17
-
18
- .spacer {
19
- padding: 0 4px;
20
- }
21
- `,
22
- render: ({inputs}) => {
23
- const bookPaths = inputs.currentRoute.paths.slice(1);
24
-
25
- if (!bookPaths.length) {
26
- return html`
27
- &nbsp;
28
- `;
29
- }
30
-
31
- return bookPaths.map((currentPath, pathIndex, pathsArray) => {
32
- const isLastPath = pathIndex >= pathsArray.length - 1;
33
-
34
- const fullPathSoFar = pathsArray.slice(0, pathIndex + 1);
35
-
36
- const spacer = isLastPath
37
- ? ''
38
- : html`
39
- <span class="spacer">&gt;</span>
40
- `;
41
-
42
- return html`
43
- <${BookRouteLink.assign({
44
- route: {
45
- hash: undefined,
46
- search: undefined,
47
- paths: [
48
- BookMainRoute.Book,
49
- ...fullPathSoFar,
50
- ],
51
- },
52
- router: inputs.router,
53
- })}>
54
- ${currentPath}
55
- </${BookRouteLink}>
56
- ${spacer}
57
- `;
58
- });
59
- },
60
- });