@canopy-iiif/app 0.8.3 → 0.8.4
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/lib/build/build.js +2 -0
- package/lib/build/dev.js +38 -22
- package/lib/build/mdx.js +12 -2
- package/lib/build/pages.js +15 -1
- package/lib/components/navigation.js +308 -0
- package/lib/page-context.js +14 -0
- package/package.json +1 -1
- package/ui/dist/index.mjs +4 -5
- package/ui/dist/index.mjs.map +2 -2
- package/ui/dist/server.mjs +126 -37
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/components/_sub-navigation.scss +76 -0
- package/ui/styles/components/index.scss +1 -0
- package/ui/styles/components/search/_results.scss +41 -4
- package/ui/styles/index.css +110 -0
package/lib/build/build.js
CHANGED
|
@@ -20,6 +20,7 @@ const { ensureStyles } = require("./styles");
|
|
|
20
20
|
const { copyAssets } = require("./assets");
|
|
21
21
|
const { logLine } = require("./log");
|
|
22
22
|
const { verifyBuildOutput } = require("./verify");
|
|
23
|
+
const navigation = require("../components/navigation");
|
|
23
24
|
|
|
24
25
|
// hold records between builds if skipping IIIF
|
|
25
26
|
let iiifRecordsCache = [];
|
|
@@ -41,6 +42,7 @@ async function build(options = {}) {
|
|
|
41
42
|
});
|
|
42
43
|
logLine("• Reset MDX cache", "blue", { dim: true });
|
|
43
44
|
mdx?.resetMdxCaches();
|
|
45
|
+
navigation?.resetNavigationCache?.();
|
|
44
46
|
if (!skipIiif) {
|
|
45
47
|
await cleanDir(OUT_DIR);
|
|
46
48
|
logLine(`• Cleaned output directory`, "blue", { dim: true });
|
package/lib/build/dev.js
CHANGED
|
@@ -617,29 +617,45 @@ function startServer() {
|
|
|
617
617
|
}
|
|
618
618
|
if (pathname === "/") pathname = "/index.html";
|
|
619
619
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
// 3) if a directory, use its index.html
|
|
624
|
-
let filePath = null;
|
|
625
|
-
const candidateA = path.join(OUT_DIR, pathname);
|
|
626
|
-
const candidateB = path.join(OUT_DIR, pathname + ".html");
|
|
627
|
-
if (fs.existsSync(candidateA)) {
|
|
628
|
-
filePath = candidateA;
|
|
629
|
-
} else if (fs.existsSync(candidateB)) {
|
|
630
|
-
filePath = candidateB;
|
|
620
|
+
function toSitePath(p) {
|
|
621
|
+
const rel = p.startsWith("/") ? `.${p}` : p;
|
|
622
|
+
return path.resolve(OUT_DIR, rel);
|
|
631
623
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
624
|
+
|
|
625
|
+
const ensureLeadingSlash = (p) => (p.startsWith("/") ? p : `/${p}`);
|
|
626
|
+
const basePath = ensureLeadingSlash(pathname);
|
|
627
|
+
const noTrailing = basePath !== "/" ? basePath.replace(/\/+$/, "") : basePath;
|
|
628
|
+
const attempts = [];
|
|
629
|
+
|
|
630
|
+
const primaryPath = noTrailing === "/" ? "/index.html" : noTrailing;
|
|
631
|
+
attempts.push(toSitePath(primaryPath));
|
|
632
|
+
|
|
633
|
+
if (!/\.html$/i.test(primaryPath)) {
|
|
634
|
+
attempts.push(toSitePath(`${primaryPath}.html`));
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const withoutHtml = primaryPath.replace(/\.html$/i, "");
|
|
638
|
+
attempts.push(toSitePath(`${withoutHtml}/index.html`));
|
|
639
|
+
|
|
640
|
+
let filePath = null;
|
|
641
|
+
for (const candidate of attempts) {
|
|
642
|
+
if (!candidate) continue;
|
|
643
|
+
let stat;
|
|
644
|
+
try {
|
|
645
|
+
stat = fs.statSync(candidate);
|
|
646
|
+
} catch (_) {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (stat.isFile()) {
|
|
650
|
+
filePath = candidate;
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
653
|
+
if (stat.isDirectory()) {
|
|
654
|
+
const idx = path.join(candidate, "index.html");
|
|
655
|
+
if (fs.existsSync(idx)) {
|
|
656
|
+
filePath = idx;
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
643
659
|
}
|
|
644
660
|
}
|
|
645
661
|
if (!filePath) {
|
package/lib/build/mdx.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
withBase,
|
|
13
13
|
} = require("../common");
|
|
14
14
|
const yaml = require("js-yaml");
|
|
15
|
+
const { getPageContext } = require("../page-context");
|
|
15
16
|
|
|
16
17
|
function parseFrontmatter(src) {
|
|
17
18
|
let input = String(src || "");
|
|
@@ -280,10 +281,19 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
280
281
|
const app = await loadAppWrapper();
|
|
281
282
|
const dirLayout = await getNearestDirLayout(filePath);
|
|
282
283
|
const contentNode = React.createElement(MDXContent, extraProps);
|
|
284
|
+
const layoutProps = dirLayout ? { ...extraProps } : null;
|
|
283
285
|
const withLayout = dirLayout
|
|
284
|
-
? React.createElement(dirLayout,
|
|
286
|
+
? React.createElement(dirLayout, layoutProps, contentNode)
|
|
285
287
|
: contentNode;
|
|
286
|
-
const
|
|
288
|
+
const PageContext = getPageContext();
|
|
289
|
+
const contextValue = {
|
|
290
|
+
navigation: extraProps && extraProps.navigation ? extraProps.navigation : null,
|
|
291
|
+
page: extraProps && extraProps.page ? extraProps.page : null,
|
|
292
|
+
};
|
|
293
|
+
const withContext = PageContext
|
|
294
|
+
? React.createElement(PageContext.Provider, { value: contextValue }, withLayout)
|
|
295
|
+
: withLayout;
|
|
296
|
+
const withApp = React.createElement(app.App, null, withContext);
|
|
287
297
|
const compMap = { ...components, a: Anchor };
|
|
288
298
|
const page = MDXProvider
|
|
289
299
|
? React.createElement(MDXProvider, { components: compMap }, withApp)
|
package/lib/build/pages.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { fs, fsp, path, CONTENT_DIR, OUT_DIR, ensureDirSync, htmlShell } = require('../common');
|
|
2
2
|
const { log } = require('./log');
|
|
3
3
|
const mdx = require('./mdx');
|
|
4
|
+
const navigation = require('../components/navigation');
|
|
4
5
|
|
|
5
6
|
// Cache: dir -> frontmatter data for _layout.mdx in that dir
|
|
6
7
|
const LAYOUT_META = new Map();
|
|
@@ -44,7 +45,20 @@ function mapContentPathToOutput(filePath) {
|
|
|
44
45
|
async function renderContentMdxToHtml(filePath, outPath, extraProps = {}) {
|
|
45
46
|
const source = await fsp.readFile(filePath, 'utf8');
|
|
46
47
|
const title = mdx.extractTitle(source);
|
|
47
|
-
const
|
|
48
|
+
const relContentPath = path.relative(CONTENT_DIR, filePath);
|
|
49
|
+
const normalizedRel = navigation.normalizeRelativePath(relContentPath);
|
|
50
|
+
const pageInfo = navigation.getPageInfo(normalizedRel);
|
|
51
|
+
const navData = navigation.buildNavigationForFile(normalizedRel);
|
|
52
|
+
const mergedProps = { ...(extraProps || {}) };
|
|
53
|
+
if (pageInfo) {
|
|
54
|
+
mergedProps.page = mergedProps.page
|
|
55
|
+
? { ...pageInfo, ...mergedProps.page }
|
|
56
|
+
: pageInfo;
|
|
57
|
+
}
|
|
58
|
+
if (navData && !mergedProps.navigation) {
|
|
59
|
+
mergedProps.navigation = navData;
|
|
60
|
+
}
|
|
61
|
+
const { body, head } = await mdx.compileMdxFile(filePath, outPath, null, mergedProps);
|
|
48
62
|
const needsHydrateViewer = body.includes('data-canopy-viewer');
|
|
49
63
|
const needsHydrateSlider = body.includes('data-canopy-slider');
|
|
50
64
|
const needsSearchForm = true; // search form runtime is global
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
const {fs, path, CONTENT_DIR, rootRelativeHref} = require("../common");
|
|
2
|
+
const mdx = require("../build/mdx.js");
|
|
3
|
+
const {getPageContext} = require("../page-context");
|
|
4
|
+
|
|
5
|
+
const EXCLUDED_ROOTS = new Set(["works", "search"]);
|
|
6
|
+
|
|
7
|
+
let NAV_CACHE = null;
|
|
8
|
+
|
|
9
|
+
function normalizeRelativePath(rel) {
|
|
10
|
+
if (!rel) return "";
|
|
11
|
+
let normalized = String(rel).replace(/\\+/g, "/");
|
|
12
|
+
while (normalized.startsWith("./")) normalized = normalized.slice(2);
|
|
13
|
+
while (normalized.startsWith("../")) normalized = normalized.slice(3);
|
|
14
|
+
if (normalized.startsWith("/")) {
|
|
15
|
+
normalized = normalized.replace(/^\/+/, "");
|
|
16
|
+
}
|
|
17
|
+
return normalized;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function humanizeSegment(seg) {
|
|
21
|
+
if (!seg) return "";
|
|
22
|
+
const cleaned = String(seg).replace(/[-_]+/g, " ");
|
|
23
|
+
return cleaned.replace(/(^|\s)([a-z])/g, (match) => match.toUpperCase());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function slugFromRelative(relativePath) {
|
|
27
|
+
const normalized = normalizeRelativePath(relativePath);
|
|
28
|
+
if (!normalized) {
|
|
29
|
+
return {slug: "", segments: [], isIndex: false};
|
|
30
|
+
}
|
|
31
|
+
const parts = normalized.split("/");
|
|
32
|
+
const fileName = parts.pop() || "";
|
|
33
|
+
const baseName = fileName.replace(/\.mdx$/i, "");
|
|
34
|
+
const isIndex = baseName.toLowerCase() === "index";
|
|
35
|
+
const dirSegments = parts.filter(Boolean);
|
|
36
|
+
const segments = isIndex ? dirSegments : dirSegments.concat(baseName);
|
|
37
|
+
const slug = segments.join("/");
|
|
38
|
+
return {slug, segments, isIndex};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function pageSortKey(relativePath) {
|
|
42
|
+
const normalized = normalizeRelativePath(relativePath).toLowerCase();
|
|
43
|
+
if (!normalized) return "";
|
|
44
|
+
return normalized.replace(/(^|\/)index\.mdx$/i, "$1-index.mdx");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function extractTitleSafe(raw) {
|
|
48
|
+
try {
|
|
49
|
+
return mdx.extractTitle(raw);
|
|
50
|
+
} catch (_) {
|
|
51
|
+
return "Untitled";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function collectPagesSync() {
|
|
56
|
+
const pages = [];
|
|
57
|
+
|
|
58
|
+
function walk(dir) {
|
|
59
|
+
let entries = [];
|
|
60
|
+
try {
|
|
61
|
+
entries = fs.readdirSync(dir, {withFileTypes: true});
|
|
62
|
+
} catch (_) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
if (!entry) continue;
|
|
67
|
+
const name = entry.name || "";
|
|
68
|
+
if (!name) continue;
|
|
69
|
+
if (name.startsWith(".")) continue;
|
|
70
|
+
const absPath = path.join(dir, name);
|
|
71
|
+
const relPath = path.relative(CONTENT_DIR, absPath);
|
|
72
|
+
const normalizedRel = normalizeRelativePath(relPath);
|
|
73
|
+
if (!normalizedRel) continue;
|
|
74
|
+
const segments = normalizedRel.split("/");
|
|
75
|
+
const firstRaw = segments[0] || "";
|
|
76
|
+
const firstSegment = firstRaw.replace(/\.mdx$/i, "");
|
|
77
|
+
if (EXCLUDED_ROOTS.has(firstSegment)) continue;
|
|
78
|
+
if (segments.some((segment) => segment.startsWith("_"))) continue;
|
|
79
|
+
if (entry.isDirectory()) {
|
|
80
|
+
walk(absPath);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (!entry.isFile()) continue;
|
|
84
|
+
if (!/\.mdx$/i.test(name)) continue;
|
|
85
|
+
let raw = "";
|
|
86
|
+
try {
|
|
87
|
+
raw = fs.readFileSync(absPath, "utf8");
|
|
88
|
+
} catch (_) {
|
|
89
|
+
raw = "";
|
|
90
|
+
}
|
|
91
|
+
const {
|
|
92
|
+
slug,
|
|
93
|
+
segments: slugSegments,
|
|
94
|
+
isIndex,
|
|
95
|
+
} = slugFromRelative(normalizedRel);
|
|
96
|
+
const titleRaw = extractTitleSafe(raw);
|
|
97
|
+
const fallbackTitle = humanizeSegment(
|
|
98
|
+
slugSegments.slice(-1)[0] || firstSegment || ""
|
|
99
|
+
);
|
|
100
|
+
const title =
|
|
101
|
+
titleRaw && titleRaw !== "Untitled"
|
|
102
|
+
? titleRaw
|
|
103
|
+
: fallbackTitle || titleRaw;
|
|
104
|
+
const htmlRel = normalizedRel.replace(/\.mdx$/i, ".html");
|
|
105
|
+
const href = rootRelativeHref(htmlRel);
|
|
106
|
+
const page = {
|
|
107
|
+
filePath: absPath,
|
|
108
|
+
relativePath: normalizedRel,
|
|
109
|
+
slug,
|
|
110
|
+
segments: slugSegments,
|
|
111
|
+
isIndex,
|
|
112
|
+
href,
|
|
113
|
+
title,
|
|
114
|
+
fallbackTitle,
|
|
115
|
+
sortKey: pageSortKey(normalizedRel),
|
|
116
|
+
topSegment: slugSegments[0] || firstSegment || "",
|
|
117
|
+
};
|
|
118
|
+
pages.push(page);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
walk(CONTENT_DIR);
|
|
123
|
+
pages.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
124
|
+
return pages;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function createNode(slug) {
|
|
128
|
+
const segments = slug ? slug.split("/") : [];
|
|
129
|
+
const name = segments.slice(-1)[0] || "";
|
|
130
|
+
return {
|
|
131
|
+
slug,
|
|
132
|
+
segments,
|
|
133
|
+
name,
|
|
134
|
+
title: humanizeSegment(name),
|
|
135
|
+
href: null,
|
|
136
|
+
hasContent: false,
|
|
137
|
+
relativePath: null,
|
|
138
|
+
sortKey: slug || name,
|
|
139
|
+
sourcePage: null,
|
|
140
|
+
children: [],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function getNavigationCache() {
|
|
145
|
+
if (NAV_CACHE) return NAV_CACHE;
|
|
146
|
+
const pages = collectPagesSync();
|
|
147
|
+
const pagesByRelative = new Map();
|
|
148
|
+
const nodes = new Map();
|
|
149
|
+
|
|
150
|
+
for (const page of pages) {
|
|
151
|
+
const {slug, segments} = page;
|
|
152
|
+
pagesByRelative.set(page.relativePath, page);
|
|
153
|
+
if (!segments.length) continue;
|
|
154
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
155
|
+
const key = segments.slice(0, i + 1).join("/");
|
|
156
|
+
if (key && !nodes.has(key)) {
|
|
157
|
+
nodes.set(key, createNode(key));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const page of pages) {
|
|
163
|
+
if (!page.slug) continue;
|
|
164
|
+
const node = nodes.get(page.slug);
|
|
165
|
+
if (!node) continue;
|
|
166
|
+
if (
|
|
167
|
+
!node.sourcePage ||
|
|
168
|
+
(node.sourcePage && node.sourcePage.isIndex && !page.isIndex)
|
|
169
|
+
) {
|
|
170
|
+
node.sourcePage = page;
|
|
171
|
+
node.title = page.title || node.title;
|
|
172
|
+
node.href = page.href || node.href;
|
|
173
|
+
node.relativePath = page.relativePath;
|
|
174
|
+
node.sortKey = page.sortKey || node.sortKey;
|
|
175
|
+
node.hasContent = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const node of nodes.values()) {
|
|
180
|
+
const {segments} = node;
|
|
181
|
+
if (!segments.length) continue;
|
|
182
|
+
const parentSlug = segments.slice(0, -1).join("/");
|
|
183
|
+
if (!parentSlug) continue;
|
|
184
|
+
const parent = nodes.get(parentSlug);
|
|
185
|
+
if (!parent) continue;
|
|
186
|
+
if (!parent.children.some((child) => child.slug === node.slug)) {
|
|
187
|
+
parent.children.push(node);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const sortChildren = (node) => {
|
|
192
|
+
node.children.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
193
|
+
for (const child of node.children) sortChildren(child);
|
|
194
|
+
};
|
|
195
|
+
for (const node of nodes.values()) {
|
|
196
|
+
sortChildren(node);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const roots = new Map();
|
|
200
|
+
for (const node of nodes.values()) {
|
|
201
|
+
if (node.segments.length === 1) {
|
|
202
|
+
roots.set(node.slug, node);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
NAV_CACHE = {
|
|
207
|
+
pages,
|
|
208
|
+
pagesByRelative,
|
|
209
|
+
nodes,
|
|
210
|
+
roots,
|
|
211
|
+
};
|
|
212
|
+
return NAV_CACHE;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function cloneNode(node, currentSlug) {
|
|
216
|
+
if (!node) return null;
|
|
217
|
+
const slug = node.slug;
|
|
218
|
+
const isActive = currentSlug && slug === currentSlug;
|
|
219
|
+
const isAncestor = !!(
|
|
220
|
+
currentSlug &&
|
|
221
|
+
slug &&
|
|
222
|
+
slug.length < currentSlug.length &&
|
|
223
|
+
currentSlug.startsWith(slug + "/")
|
|
224
|
+
);
|
|
225
|
+
const children = node.children
|
|
226
|
+
.map((child) => cloneNode(child, currentSlug))
|
|
227
|
+
.filter(Boolean);
|
|
228
|
+
if (!node.hasContent && !children.length) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
slug,
|
|
233
|
+
title: node.title,
|
|
234
|
+
href: node.href,
|
|
235
|
+
segments: node.segments.slice(),
|
|
236
|
+
depth: Math.max(0, node.segments.length - 1),
|
|
237
|
+
isActive: !!isActive,
|
|
238
|
+
isAncestor,
|
|
239
|
+
isExpanded: !!(isActive || isAncestor),
|
|
240
|
+
hasContent: node.hasContent,
|
|
241
|
+
relativePath: node.relativePath,
|
|
242
|
+
children,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function getPageInfo(relativePath) {
|
|
247
|
+
const cache = getNavigationCache();
|
|
248
|
+
const normalized = normalizeRelativePath(relativePath);
|
|
249
|
+
const page = cache.pagesByRelative.get(normalized);
|
|
250
|
+
if (page) {
|
|
251
|
+
return {
|
|
252
|
+
title: page.title,
|
|
253
|
+
href: page.href,
|
|
254
|
+
slug: page.slug,
|
|
255
|
+
segments: page.segments.slice(),
|
|
256
|
+
relativePath: page.relativePath,
|
|
257
|
+
rootSegment: page.segments[0] || "",
|
|
258
|
+
isIndex: page.isIndex,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const {slug, segments} = slugFromRelative(normalized);
|
|
262
|
+
const htmlRel = normalized.replace(/\.mdx$/i, ".html");
|
|
263
|
+
return {
|
|
264
|
+
title: humanizeSegment(segments.slice(-1)[0] || slug || ""),
|
|
265
|
+
href: rootRelativeHref(htmlRel),
|
|
266
|
+
slug,
|
|
267
|
+
segments,
|
|
268
|
+
relativePath: normalized,
|
|
269
|
+
rootSegment: segments[0] || "",
|
|
270
|
+
isIndex: false,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function buildNavigationForFile(relativePath) {
|
|
275
|
+
const cache = getNavigationCache();
|
|
276
|
+
const normalized = normalizeRelativePath(relativePath);
|
|
277
|
+
const page = cache.pagesByRelative.get(normalized);
|
|
278
|
+
const fallback = slugFromRelative(normalized);
|
|
279
|
+
const slug = page ? page.slug : fallback.slug;
|
|
280
|
+
const rootSegment = page
|
|
281
|
+
? page.segments[0] || ""
|
|
282
|
+
: fallback.segments[0] || "";
|
|
283
|
+
if (!slug || !rootSegment || EXCLUDED_ROOTS.has(rootSegment)) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const rootNode = cache.roots.get(rootSegment);
|
|
287
|
+
if (!rootNode) return null;
|
|
288
|
+
const cloned = cloneNode(rootNode, slug);
|
|
289
|
+
if (!cloned) return null;
|
|
290
|
+
return {
|
|
291
|
+
rootSegment,
|
|
292
|
+
currentSlug: slug,
|
|
293
|
+
root: cloned,
|
|
294
|
+
title: cloned.title,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function resetNavigationCache() {
|
|
299
|
+
NAV_CACHE = null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
module.exports = {
|
|
303
|
+
normalizeRelativePath,
|
|
304
|
+
getPageInfo,
|
|
305
|
+
buildNavigationForFile,
|
|
306
|
+
resetNavigationCache,
|
|
307
|
+
getPageContext,
|
|
308
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const React = require('react');
|
|
2
|
+
|
|
3
|
+
let PageContext = null;
|
|
4
|
+
|
|
5
|
+
function getPageContext() {
|
|
6
|
+
if (!PageContext) {
|
|
7
|
+
PageContext = React.createContext({ navigation: null, page: null });
|
|
8
|
+
}
|
|
9
|
+
return PageContext;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
getPageContext,
|
|
14
|
+
};
|
package/package.json
CHANGED
package/ui/dist/index.mjs
CHANGED
|
@@ -120,7 +120,7 @@ function GridItem({ children, className = "", style = {}, ...rest }) {
|
|
|
120
120
|
}
|
|
121
121
|
function Grid({
|
|
122
122
|
breakpointCols,
|
|
123
|
-
gap = "
|
|
123
|
+
gap = "1.618rem",
|
|
124
124
|
paddingY = "0",
|
|
125
125
|
className = "",
|
|
126
126
|
style = {},
|
|
@@ -391,12 +391,12 @@ function SearchTabs({
|
|
|
391
391
|
const toLabel = (t) => t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : "";
|
|
392
392
|
const hasFilters = typeof onOpenFilters === "function";
|
|
393
393
|
const filterBadge = activeFilterCount > 0 ? ` (${activeFilterCount})` : "";
|
|
394
|
-
return /* @__PURE__ */ React11.createElement("div", { className: "
|
|
394
|
+
return /* @__PURE__ */ React11.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React11.createElement(
|
|
395
395
|
"div",
|
|
396
396
|
{
|
|
397
397
|
role: "tablist",
|
|
398
398
|
"aria-label": "Search types",
|
|
399
|
-
className: "
|
|
399
|
+
className: "canopy-search-tabs"
|
|
400
400
|
},
|
|
401
401
|
orderedTypes.map((t) => {
|
|
402
402
|
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
@@ -409,8 +409,7 @@ function SearchTabs({
|
|
|
409
409
|
role: "tab",
|
|
410
410
|
"aria-selected": active,
|
|
411
411
|
type: "button",
|
|
412
|
-
onClick: () => onTypeChange && onTypeChange(t)
|
|
413
|
-
className: "px-3 py-2 text-sm rounded-t-md border-b-2 -mb-px transition-colors " + (active ? "border-brand-600 text-brand-700" : "border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300")
|
|
412
|
+
onClick: () => onTypeChange && onTypeChange(t)
|
|
414
413
|
},
|
|
415
414
|
toLabel(t),
|
|
416
415
|
" (",
|