@brillout/docpress 0.9.8 → 0.10.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 (63) hide show
  1. package/Layout.tsx +102 -40
  2. package/{navigation → MenuModal}/Collapsible.css +7 -0
  3. package/MenuModal/NavigationWithColumnLayout.css +11 -0
  4. package/MenuModal/NavigationWithColumnLayout.tsx +253 -0
  5. package/MenuModal/toggleMenuModal.ts +132 -0
  6. package/MenuModal.tsx +68 -79
  7. package/{navigation/Navigation.css → NavItemComponent.css} +1 -23
  8. package/NavItemComponent.tsx +149 -0
  9. package/components/Note.css +0 -1
  10. package/config/resolveHeadingsData.ts +1 -1
  11. package/css/code/diff.css +10 -5
  12. package/css/code.css +1 -1
  13. package/css/colorize-on-hover.css +6 -7
  14. package/css/heading.css +9 -3
  15. package/css/index.css +1 -0
  16. package/dist/NavItemComponent.d.ts +39 -0
  17. package/dist/NavItemComponent.js +109 -0
  18. package/dist/config/resolveHeadingsData.d.ts +1 -1
  19. package/dist/config/resolvePageContext.d.ts +2 -2
  20. package/dist/renderer/determineNavItemsColumnLayout.d.ts +1 -1
  21. package/docsearch/SearchLink.tsx +7 -3
  22. package/icons/books.svg +46 -0
  23. package/icons/gear.svg +35 -0
  24. package/icons/index.ts +5 -0
  25. package/icons/magnifying-glass.svg +31 -0
  26. package/icons/seedling.svg +24 -0
  27. package/index.ts +2 -0
  28. package/initKeyBindings.ts +1 -1
  29. package/package.json +1 -1
  30. package/renderer/determineNavItemsColumnLayout.ts +1 -1
  31. package/renderer/initOnNavigation.ts +1 -1
  32. package/renderer/onRenderClient.tsx +1 -1
  33. package/utils/css.ts +0 -6
  34. package/dist/Layout.d.ts +0 -15
  35. package/dist/Layout.js +0 -321
  36. package/dist/MenuModal.d.ts +0 -13
  37. package/dist/MenuModal.js +0 -124
  38. package/dist/NavSecondaryContent.d.ts +0 -6
  39. package/dist/NavSecondaryContent.js +0 -57
  40. package/dist/autoScrollNav.d.ts +0 -3
  41. package/dist/autoScrollNav.js +0 -35
  42. package/dist/components/EditPageNote.d.ts +0 -7
  43. package/dist/components/EditPageNote.js +0 -11
  44. package/dist/docsearch/SearchLink.d.ts +0 -4
  45. package/dist/docsearch/SearchLink.js +0 -25
  46. package/dist/docsearch/toggleDocsearchModal.d.ts +0 -4
  47. package/dist/docsearch/toggleDocsearchModal.js +0 -26
  48. package/dist/navigation/Collapsible.d.ts +0 -10
  49. package/dist/navigation/Collapsible.js +0 -35
  50. package/dist/navigation/Navigation.d.ts +0 -21
  51. package/dist/navigation/Navigation.js +0 -255
  52. package/dist/utils/PassTrough.d.ts +0 -3
  53. package/dist/utils/PassTrough.js +0 -6
  54. package/dist/utils/Style.d.ts +0 -5
  55. package/dist/utils/Style.js +0 -6
  56. package/dist/utils/css.d.ts +0 -1
  57. package/dist/utils/css.js +0 -27
  58. package/dist/utils/getViewportWidth.d.ts +0 -1
  59. package/dist/utils/getViewportWidth.js +0 -4
  60. package/dist/utils/throttle.d.ts +0 -1
  61. package/dist/utils/throttle.js +0 -14
  62. package/navigation/Navigation.tsx +0 -382
  63. /package/{navigation → MenuModal}/Collapsible.tsx +0 -0
@@ -1,3 +0,0 @@
1
- export { PassThrough };
2
- import React from 'react';
3
- declare function PassThrough({ children }: any): React.JSX.Element;
@@ -1,6 +0,0 @@
1
- export { PassThrough };
2
- import React from 'react';
3
- function PassThrough(_a) {
4
- var children = _a.children;
5
- return React.createElement(React.Fragment, null, children);
6
- }
@@ -1,5 +0,0 @@
1
- export { Style };
2
- import React from 'react';
3
- declare function Style({ children }: {
4
- children: string;
5
- }): React.JSX.Element;
@@ -1,6 +0,0 @@
1
- export { Style };
2
- import React from 'react';
3
- function Style(_a) {
4
- var children = _a.children;
5
- return React.createElement("style", { dangerouslySetInnerHTML: { __html: children } });
6
- }
@@ -1 +0,0 @@
1
- export declare function css(strings: TemplateStringsArray | string[], ...values: (string | number)[]): string;
package/dist/utils/css.js DELETED
@@ -1,27 +0,0 @@
1
- export function css(strings) {
2
- var values = [];
3
- for (var _i = 1; _i < arguments.length; _i++) {
4
- values[_i - 1] = arguments[_i];
5
- }
6
- // The boring part
7
- var result = strings
8
- .map(function (str, i) {
9
- var s = str;
10
- if (i !== strings.length - 1) {
11
- s += values[i];
12
- }
13
- return s;
14
- })
15
- .join('');
16
- // Remove comments
17
- result = result
18
- .split('\n')
19
- .filter(function (line) { return !line.startsWith('// '); })
20
- .join('\n');
21
- // Minifiy
22
- result = result
23
- .replace(/\s+/g, ' ') // Replace all whitespace sequences with a single space
24
- .replace(/\s*([{}:;])\s*/g, '$1') // Remove space around {, }, :, ;
25
- .trim(); // Trim any leading/trailing whitespace
26
- return result;
27
- }
@@ -1 +0,0 @@
1
- export declare function getViewportWidth(): number;
@@ -1,4 +0,0 @@
1
- export function getViewportWidth() {
2
- // `window.innerWidth` inlcudes scrollbar width: https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
3
- return document.documentElement.clientWidth;
4
- }
@@ -1 +0,0 @@
1
- export declare function throttle<T extends (...args: any[]) => void>(func: T, limit: number): T;
@@ -1,14 +0,0 @@
1
- export function throttle(func, limit) {
2
- var inThrottle;
3
- return function () {
4
- var args = [];
5
- for (var _i = 0; _i < arguments.length; _i++) {
6
- args[_i] = arguments[_i];
7
- }
8
- if (!inThrottle) {
9
- func.apply(this, args);
10
- inThrottle = true;
11
- setTimeout(function () { return (inThrottle = false); }, limit);
12
- }
13
- };
14
- }
@@ -1,382 +0,0 @@
1
- // TODO/refactor: rename file and/or component
2
- export { NavigationContent }
3
- // TODO/refactor: do this only on the server side?
4
- export type { NavItem }
5
-
6
- import React, { useEffect, useState } from 'react'
7
- import { assert, assertWarning, jsxToTextContent } from '../utils/server'
8
- import './Navigation.css'
9
- import { parseTitle } from '../parseTitle'
10
- import { usePageContext } from '../renderer/usePageContext'
11
- import '@docsearch/css'
12
- import '../global.d.ts'
13
- import { getViewportWidth } from '../utils/getViewportWidth'
14
- import { navLeftWidthMax, navLeftWidthMin } from '../Layout'
15
- import { throttle } from '../utils/throttle'
16
- import { Collapsible } from './Collapsible'
17
-
18
- type NavItem = {
19
- level: number
20
- url?: string | null
21
- color?: string
22
- title: string
23
- titleInNav: string
24
- menuModalFullWidth?: true
25
- isColumnEntry?: ColumnMap
26
- }
27
- function NavigationContent(props: {
28
- navItems: NavItem[]
29
- showOnlyRelevant?: true
30
- columnLayout?: true
31
- }) {
32
- const pageContext = usePageContext()
33
- const navItemsWithComputed = getNavItemsWithComputed(props.navItems, pageContext.urlPathname)
34
-
35
- let navContent: React.ReactNode
36
- if (!props.columnLayout) {
37
- let navItemsRelevant = navItemsWithComputed
38
- if (props.showOnlyRelevant) navItemsRelevant = navItemsRelevant.filter((navItemGroup) => navItemGroup.isRelevant)
39
- navContent = navItemsRelevant.map((navItem, i) => <NavItemComponent navItem={navItem} key={i} />)
40
- } else {
41
- assert(!props.showOnlyRelevant)
42
- navContent = <NavigationWithColumnLayout navItemsWithComputed={navItemsWithComputed} />
43
- }
44
-
45
- return (
46
- <div className="navigation-content" style={{ marginTop: 10 }}>
47
- {navContent}
48
- </div>
49
- )
50
- }
51
-
52
- function NavigationWithColumnLayout(props: { navItemsWithComputed: NavItemComputed[] }) {
53
- let [viewportWidth, setViewportWidth] = useState<number | undefined>()
54
- const updateviewportwidth = () => setViewportWidth(getViewportWidth())
55
- useEffect(() => {
56
- updateviewportwidth()
57
- window.addEventListener('resize', throttle(updateviewportwidth, 300), { passive: true })
58
- })
59
- const navItemsByColumnLayouts = getNavItemsByColumnLayouts(props.navItemsWithComputed, viewportWidth)
60
- return (
61
- <>
62
- {navItemsByColumnLayouts.map((columnLayout, i) => (
63
- <div key={i}>
64
- {columnLayout.isFullWidthCategory ? (
65
- <div style={{ marginTop: 0 }}>
66
- <ColumnsWrapper numberOfColumns={columnLayout.columns.length}>
67
- <Collapsible
68
- head={(onClick) => <NavItemComponent navItem={columnLayout.navItemLevel1} onClick={onClick} />}
69
- disabled={columnLayout.columns.length > 1}
70
- collapsedInit={!columnLayout.navItemLevel1.isRelevant}
71
- marginBottomOnExpand={10}
72
- >
73
- <ColumnsLayout className="collapsible">
74
- {columnLayout.columns.map((column, j) => (
75
- <Column key={j}>
76
- {column.navItems.map((navItem, k) => (
77
- <NavItemComponent key={k} navItem={navItem} />
78
- ))}
79
- </Column>
80
- ))}
81
- <CategoryBorder navItemLevel1={columnLayout.navItemLevel1} />
82
- </ColumnsLayout>
83
- </Collapsible>
84
- </ColumnsWrapper>
85
- </div>
86
- ) : (
87
- <ColumnsWrapper numberOfColumns={columnLayout.columns.length}>
88
- <ColumnsLayout>
89
- {columnLayout.columns.map((column, j) => (
90
- <Column key={j}>
91
- {column.categories.map((category, k) => (
92
- <div key={k} style={{ marginBottom: 0 }}>
93
- <Collapsible
94
- head={(onClick) => <NavItemComponent navItem={category.navItemLevel1} onClick={onClick} />}
95
- disabled={columnLayout.columns.length > 1}
96
- collapsedInit={!category.navItemLevel1.isRelevant}
97
- marginBottomOnExpand={40}
98
- >
99
- {category.navItems.map((navItem, l) => (
100
- <NavItemComponent key={l} navItem={navItem} />
101
- ))}
102
- <CategoryBorder navItemLevel1={category.navItemLevel1} />
103
- </Collapsible>
104
- </div>
105
- ))}
106
- </Column>
107
- ))}
108
- </ColumnsLayout>
109
- </ColumnsWrapper>
110
- )}
111
- </div>
112
- ))}
113
- </>
114
- )
115
- }
116
- function Column({ children }: { children: React.ReactNode }) {
117
- return (
118
- <div
119
- style={{
120
- flexGrow: 1,
121
- maxWidth: navLeftWidthMax,
122
- display: 'flex',
123
- flexDirection: 'column',
124
- }}
125
- >
126
- {children}
127
- </div>
128
- )
129
- }
130
- function ColumnsWrapper({ children, numberOfColumns }: { children: React.ReactNode; numberOfColumns: number }) {
131
- return (
132
- <div
133
- style={{
134
- width: numberOfColumns * (navLeftWidthMax + 20),
135
- maxWidth: '100%',
136
- margin: 'auto',
137
- }}
138
- >
139
- {children}
140
- </div>
141
- )
142
- }
143
- function ColumnsLayout({ children, className }: { children: React.ReactNode; className?: string }) {
144
- return (
145
- <div
146
- className={className}
147
- style={{
148
- display: 'flex',
149
- justifyContent: 'space-between',
150
- }}
151
- >
152
- {children}
153
- </div>
154
- )
155
- }
156
- function CategoryBorder({ navItemLevel1 }: { navItemLevel1: NavItemComputed }) {
157
- assert(navItemLevel1.level === 1)
158
- return <div className="category-border" style={{ background: navItemLevel1.color! }} />
159
- }
160
-
161
- type PropsNavItem = PropsAnchor & PropsSpan
162
- type PropsAnchor = React.HTMLProps<HTMLAnchorElement>
163
- type PropsSpan = React.HTMLProps<HTMLSpanElement>
164
- function NavItemComponent({
165
- navItem,
166
- onClick,
167
- }: {
168
- navItem: NavItemComputed
169
- onClick?: PropsNavItem['onClick']
170
- }) {
171
- assert([1, 2, 3, 4].includes(navItem.level), navItem)
172
-
173
- const titleJsx = parseTitle(navItem.title)
174
- const titleInNavJsx = parseTitle(navItem.titleInNav)
175
-
176
- if (navItem.level === 1 || navItem.level === 4) {
177
- assert(navItem.url === undefined)
178
- } else {
179
- const sectionTitle = jsxToTextContent(titleJsx)
180
- assertWarning(
181
- navItem.url,
182
- [
183
- `${jsxToTextContent(titleInNavJsx)} is missing a URL hash.`,
184
- `Add a URL hash with: \`## ${sectionTitle}{#some-hash}\`.`,
185
- /* TODO/eventually: not implemented yet.
186
- `Use \`<h2 id="url-hash">${sectionTitle}</h2>\` instead of \`## ${sectionTitle}\`.`,
187
- */
188
- ].join(' '),
189
- )
190
- }
191
-
192
- let children: JSX.Element = titleInNavJsx
193
- if (navItem.level === 1) {
194
- children = (
195
- <>
196
- {children}
197
- <Chevron className="collapsible-icon" height={9} />
198
- </>
199
- )
200
- }
201
-
202
- const props: PropsNavItem = {
203
- href: navItem.url ?? undefined,
204
- children,
205
- onClick,
206
- className: [
207
- 'nav-item',
208
- 'nav-item-level-' + navItem.level,
209
- navItem.url && navItem.isActive && ' is-active',
210
- navItem.isFirstOfItsKind && 'nav-item-first-of-its-kind',
211
- navItem.isLastOfItsKind && 'nav-item-last-of-its-kind',
212
- ]
213
- .filter(Boolean)
214
- .join(' '),
215
- }
216
- if (navItem.level === 1) {
217
- props.style = {
218
- ['--category-color']: navItem.color!,
219
- }
220
- }
221
-
222
- if (navItem.level === 2 || navItem.level === 3) {
223
- return <a {...props} />
224
- } else {
225
- return <span {...props} />
226
- }
227
- }
228
-
229
- type NavItemsByColumnLayout =
230
- | {
231
- columns: {
232
- categories: {
233
- navItemLevel1: NavItemComputed
234
- navItems: NavItemComputed[]
235
- }[]
236
- }[]
237
- isFullWidthCategory: false
238
- }
239
- | {
240
- navItemLevel1: NavItemComputed
241
- columns: { navItems: NavItemComputed[] }[]
242
- isFullWidthCategory: true
243
- }
244
- type NavItemsByColumnLayout2 = { columns: NavItemComputed[][][]; isFullWidthCategory: boolean }
245
- function getNavItemsByColumnLayouts(navItems: NavItemComputed[], viewportWidth: number = 0): NavItemsByColumnLayout[] {
246
- const navItemsByColumnEntries = getNavItemsByColumnEntries(navItems)
247
- const numberOfColumnsMax = Math.floor(viewportWidth / navLeftWidthMin) || 1
248
- const navItemsByColumnLayouts: NavItemsByColumnLayout[] = navItemsByColumnEntries.map(
249
- ({ columnEntries, isFullWidthCategory }) => {
250
- const numberOfColumns = Math.min(numberOfColumnsMax, columnEntries.length)
251
- if (!isFullWidthCategory) {
252
- const columns: {
253
- categories: {
254
- navItemLevel1: NavItemComputed
255
- navItems: NavItemComputed[]
256
- }[]
257
- }[] = []
258
- columnEntries.forEach((columnEntry) => {
259
- const idx = numberOfColumns === 1 ? 0 : columnEntry.columnMap[numberOfColumns]!
260
- assert(idx >= 0)
261
- columns[idx] ??= { categories: [] }
262
- const navItemLevel1 = columnEntry.navItems[0]
263
- const navItems = columnEntry.navItems.slice(1)
264
- columns[idx].categories.push({ navItemLevel1, navItems })
265
- })
266
- const navItemsByColumnLayout: NavItemsByColumnLayout = { columns, isFullWidthCategory }
267
- return navItemsByColumnLayout
268
- } else {
269
- let navItemLevel1: NavItemComputed
270
- const columns: { navItems: NavItemComputed[] }[] = []
271
- columnEntries.forEach((columnEntry, i) => {
272
- const idx = numberOfColumns === 1 ? 0 : columnEntry.columnMap[numberOfColumns]!
273
- assert(idx >= 0)
274
- columns[idx] ??= { navItems: [] }
275
- let { navItems } = columnEntry
276
- if (i === 0) {
277
- navItemLevel1 = navItems[0]
278
- navItems = navItems.slice(1)
279
- }
280
- columns[idx].navItems.push(...navItems)
281
- })
282
- const navItemsByColumnLayout: NavItemsByColumnLayout = {
283
- columns,
284
- navItemLevel1: navItemLevel1!,
285
- isFullWidthCategory,
286
- }
287
- return navItemsByColumnLayout
288
- }
289
- },
290
- )
291
- return navItemsByColumnLayouts
292
- }
293
- type NavItemsByColumnEntries = { columnEntries: ColumnEntry[]; isFullWidthCategory: boolean }[]
294
- type ColumnEntry = { navItems: NavItemComputed[]; columnMap: ColumnMap }
295
- type ColumnMap = Record<number, number>
296
- function getNavItemsByColumnEntries(navItems: NavItemComputed[]): NavItemsByColumnEntries {
297
- const navItemsByColumnEntries: NavItemsByColumnEntries = []
298
- let columnEntries: ColumnEntry[] = []
299
- let columnEntry: ColumnEntry
300
- let isFullWidthCategory: boolean | undefined
301
- navItems.forEach((navItem) => {
302
- if (navItem.level === 1) {
303
- const isFullWidthCategoryPrevious = isFullWidthCategory
304
- isFullWidthCategory = !!navItem.menuModalFullWidth
305
- if (isFullWidthCategoryPrevious !== undefined && isFullWidthCategoryPrevious !== isFullWidthCategory) {
306
- navItemsByColumnEntries.push({ columnEntries, isFullWidthCategory: isFullWidthCategoryPrevious })
307
- columnEntries = []
308
- }
309
- }
310
- assert(isFullWidthCategory !== undefined)
311
- if (navItem.isColumnEntry) {
312
- assert(navItem.level === 1 || navItem.level === 4)
313
- columnEntry = { navItems: [navItem], columnMap: navItem.isColumnEntry }
314
- columnEntries.push(columnEntry)
315
- } else {
316
- assert(navItem.level !== 1)
317
- columnEntry.navItems.push(navItem)
318
- }
319
- })
320
- assert(isFullWidthCategory !== undefined)
321
- navItemsByColumnEntries.push({ columnEntries, isFullWidthCategory })
322
- return navItemsByColumnEntries
323
- }
324
-
325
- type NavItemComputed = ReturnType<typeof getNavItemsWithComputed>[number]
326
- function getNavItemsWithComputed(navItems: NavItem[], currentUrl: string) {
327
- let navItemIdx: number | undefined
328
- const navItemsWithComputed = navItems.map((navItem, i) => {
329
- assert([1, 2, 3, 4].includes(navItem.level), navItem)
330
-
331
- const navItemPrevious = navItems[i - 1]
332
- const navItemNext = navItems[i + 1]
333
-
334
- let isActive = false
335
- if (navItem.url === currentUrl) {
336
- assert(navItem.level === 2, { currentUrl })
337
- assert(navItemIdx === undefined)
338
- navItemIdx = i
339
- isActive = true
340
- }
341
-
342
- const isFirstOfItsKind = navItem.level !== navItemPrevious?.level
343
- const isLastOfItsKind = navItem.level !== navItemNext?.level
344
-
345
- const navItemComputed = {
346
- ...navItem,
347
- isActive,
348
- isRelevant: false,
349
- isFirstOfItsKind,
350
- isLastOfItsKind,
351
- }
352
-
353
- return navItemComputed
354
- })
355
-
356
- // Set `isRelevant`
357
- if (navItemIdx !== undefined) {
358
- for (let i = navItemIdx; i >= 0; i--) {
359
- const navItem = navItemsWithComputed[i]!
360
- navItem.isRelevant = true
361
- if (navItem.level === 1) break
362
- }
363
- for (let i = navItemIdx; i < navItemsWithComputed.length; i++) {
364
- const navItem = navItemsWithComputed[i]!
365
- if (navItem.level === 1) break
366
- navItem.isRelevant = true
367
- }
368
- }
369
-
370
- return navItemsWithComputed
371
- }
372
-
373
- function Chevron(props: React.HTMLProps<SVGSVGElement>) {
374
- return (
375
- <svg viewBox="0 0 512 292.52" xmlns="http://www.w3.org/2000/svg" {...props}>
376
- <path
377
- fill="#aaa"
378
- d="M10.725 82.42L230.125 261.82c6.8 6.8 16.2 10.7 25.9 10.7s19.1-3.9 25.9-10.7l219.4-179.4c14.3-14.3 14.3-37.4 0-51.7s-37.4-14.3-51.7 0l-193.6 153.6-193.6-153.6c-14.3-14.3-37.4-14.3-51.7 0s-14.3 37.5 0 51.7z"
379
- />
380
- </svg>
381
- )
382
- }
File without changes