@veluai/velu 0.2.39 → 0.2.40

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.
@@ -9,7 +9,7 @@
9
9
  "properties": {
10
10
  "theme": {
11
11
  "type": "string",
12
- "enum": ["velu", "vepa", "thulir", "aalam"],
12
+ "enum": ["velu", "vepa", "thulir", "aalam", "nila"],
13
13
  "description": "Visual preset. Vepa follows Mintlify Sequoia, Thulir follows Mintlify Mint, and Aalam follows Mintlify Maple; light/dark preference is independent. Defaults to velu."
14
14
  },
15
15
  "$schema": {
@@ -272,6 +272,7 @@
272
272
  "additionalProperties": false,
273
273
  "description": "A navigation container. Higher-precedence keys nest the lower ones (products contain versions contain languages contain tabs contain groups/pages).",
274
274
  "properties": {
275
+ "preservePagePaths": { "type": "boolean", "description": "Keep page URLs unchanged across product, version and language axes. Enabled by Mintlify migration." },
275
276
  "products": { "type": "array", "items": { "$ref": "#/$defs/product" } },
276
277
  "versions": { "type": "array", "items": { "$ref": "#/$defs/version" } },
277
278
  "languages": { "type": "array", "items": { "$ref": "#/$defs/language" } },
package/src/navigation.js CHANGED
@@ -90,6 +90,7 @@ const lastSeg = (url) => {
90
90
  */
91
91
  export function normalizeNavigation(raw) {
92
92
  const root = { kind: 'root', children: normalizeChildren(raw ?? {}) };
93
+ if (raw?.preservePagePaths === true) root.preservePagePaths = true;
93
94
  applyDefaults(root.children);
94
95
  return root;
95
96
  }
@@ -250,12 +251,13 @@ export function walkPages(tree) {
250
251
  node.kind === 'root' ? ancestors : [...ancestors, node];
251
252
  for (const c of node.children ?? []) visit(c, next, nextAncestors);
252
253
  };
253
- visit(tree, { product: null, version: null, language: null }, []);
254
+ visit(tree, { product: null, version: null, language: null, ...(tree.preservePagePaths ? { preservePagePaths: true } : {}) }, []);
254
255
  return out;
255
256
  }
256
257
 
257
258
  /** Compose a page URL from a page path + an axis context. */
258
259
  function urlInCtx(pagePath, ctx) {
260
+ if (ctx.preservePagePaths) return urlForPath(pagePath);
259
261
  const prefix = [ctx.product, ctx.version, ctx.language].filter(Boolean);
260
262
  const leaf = urlForPath(pagePath).split('/').filter(Boolean);
261
263
  return '/' + [...prefix, ...leaf].join('/');
@@ -929,7 +929,7 @@ function DocsPage() {
929
929
  // against it like any other heading.
930
930
  const pageId = React.useMemo(() => {
931
931
  if (!frontmatter.title) return null;
932
- if (site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme)) return 'page-title';
932
+ if (site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme)) return 'page-title';
933
933
  return new GithubSlugger().slug(frontmatter.title);
934
934
  }, [frontmatter.title, site.theme]);
935
935
 
@@ -969,7 +969,7 @@ function DocsPage() {
969
969
  const root = drawerRef.current?.parentElement;
970
970
  if (!root) return;
971
971
  const observer = new ResizeObserver(([entry]) => {
972
- const narrow = entry.contentRect.width <= (['thulir', 'aalam'].includes(site.theme) ? 1023 : 640);
972
+ const narrow = entry.contentRect.width <= (['thulir', 'aalam', 'nila'].includes(site.theme) ? 1023 : 640);
973
973
  setDrawerViewport(narrow);
974
974
  if (!narrow) setDrawerOpen(false);
975
975
  });
@@ -988,7 +988,7 @@ function DocsPage() {
988
988
  drawer.querySelector('.velu-docs-layout__drawer-close')?.focus();
989
989
  const onKey = e => {
990
990
  if (e.key === 'Escape') {
991
- if (drawer.querySelector('.velu-docs-layout__drawer-docselect[data-open="true"]')) return;
991
+ if (drawer.querySelector('.velu-docs-layout__drawer-docselect[data-open="true"], .velu-nav-select[data-open="true"]')) return;
992
992
  setDrawerOpen(false); return;
993
993
  }
994
994
  if (e.key !== 'Tab') return;
@@ -1350,8 +1350,8 @@ function DocsPage() {
1350
1350
  logo: site.logo,
1351
1351
  }}
1352
1352
  brandTrailing={
1353
- versionSwitcher && (
1354
- <span className="velu-hide-on-mobile">{versionSwitcher}</span>
1353
+ (versionSwitcher || (site.theme === 'nila' && productSwitcher)) && (
1354
+ <span className="velu-hide-on-mobile">{versionSwitcher}{site.theme === 'nila' && productSwitcher}</span>
1355
1355
  )
1356
1356
  }
1357
1357
  center={
@@ -1382,7 +1382,7 @@ function DocsPage() {
1382
1382
  </Cluster>
1383
1383
  }
1384
1384
  actions={navActions}
1385
- trailing={<ThemeToggle variant={site.theme === 'aalam' ? 'inline' : site.theme === 'vepa' || site.theme === 'thulir' ? 'menu' : undefined} />}
1385
+ trailing={<ThemeToggle variant={site.theme === 'aalam' ? 'inline' : site.theme === 'vepa' || ['thulir', 'nila'].includes(site.theme) ? 'menu' : undefined} />}
1386
1386
  tabsTrailing={
1387
1387
  chrome.mode === 'custom' || chrome.mode === 'assistant'
1388
1388
  ? undefined
@@ -1394,7 +1394,7 @@ function DocsPage() {
1394
1394
  breadcrumb={
1395
1395
  chrome.mode === 'custom' || chrome.mode === 'assistant'
1396
1396
  ? []
1397
- : ['thulir', 'aalam'].includes(site.theme) ? (nav?.breadcrumb ?? []).slice(-2) : (nav?.breadcrumb ?? [])
1397
+ : ['thulir', 'aalam', 'nila'].includes(site.theme) ? (nav?.breadcrumb ?? []).slice(-2) : (nav?.breadcrumb ?? [])
1398
1398
  }
1399
1399
  activeTab={nav?.activeTab}
1400
1400
  tabs={
@@ -1448,7 +1448,7 @@ function DocsPage() {
1448
1448
  </>
1449
1449
  )}
1450
1450
  </RouterLink>
1451
- <ThemeToggle variant={site.theme === 'vepa' || site.theme === 'thulir' ? 'menu' : undefined} />
1451
+ <ThemeToggle variant={site.theme === 'vepa' || ['thulir', 'nila'].includes(site.theme) ? 'menu' : undefined} />
1452
1452
  <button
1453
1453
  type="button"
1454
1454
  className="velu-docs-layout__drawer-close"
@@ -1592,7 +1592,7 @@ function DocsPage() {
1592
1592
  left column, including anchors, in one overflow. */}
1593
1593
  <div className="velu-docs-nav-region">
1594
1594
  <div
1595
- id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? 'navigation-items' : 'sidebar-content'}
1595
+ id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? 'navigation-items' : 'sidebar-content'}
1596
1596
  ref={leftAsideRef}
1597
1597
  className={`velu-docs-nav-scroll${site.theme === 'aalam' ? '' : ' velu-hide-scrollbar'}`}
1598
1598
  style={{
@@ -1690,12 +1690,12 @@ function DocsPage() {
1690
1690
  />
1691
1691
  ) : isChangelog && changelogTags.length && site.theme !== 'vepa' ? (
1692
1692
  <ChangelogFilters tags={changelogTags} />
1693
- ) : site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? (
1693
+ ) : site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? (
1694
1694
  <>
1695
1695
  {isChangelog && changelogTags.length > 0 ? (
1696
1696
  <ChangelogFilters tags={changelogTags} />
1697
1697
  ) : null}
1698
- <VepaToc items={pageToc} activeId={['thulir', 'aalam'].includes(site.theme) && activeId === pageId ? pageToc[0]?.id : activeId} onSelect={scrollTo} />
1698
+ <VepaToc items={pageToc} activeId={['thulir', 'aalam', 'nila'].includes(site.theme) && activeId === pageId ? pageToc[0]?.id : activeId} onSelect={scrollTo} />
1699
1699
  </>
1700
1700
  ) : (
1701
1701
  <Toc id="table-of-contents-content" items={toc} activeId={activeId} onSelect={scrollTo} />
@@ -1740,7 +1740,7 @@ function DocsPage() {
1740
1740
  on tab/mobile we keep the normal TOC bar (no filters). Hidden
1741
1741
  entirely when the page mode has no table of contents. */}
1742
1742
  {chrome.toc && (
1743
- <TocBar items={toc} activeId={activeId} onSelect={scrollTo} label={['thulir', 'aalam'].includes(site.theme) ? 'On this page' : undefined} />
1743
+ <TocBar items={toc} activeId={activeId} onSelect={scrollTo} label={['thulir', 'aalam', 'nila'].includes(site.theme) ? 'On this page' : undefined} />
1744
1744
  )}
1745
1745
  <main
1746
1746
  id="content-area"
@@ -1780,7 +1780,7 @@ function DocsPage() {
1780
1780
  </span>
1781
1781
  </button>
1782
1782
  )}
1783
- <div id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? undefined : 'content'} data-contextual-actions={site.contextual?.options?.length ? 'true' : 'false'} className="velu-docs-layout__article" data-pagefind-body={chrome.assistant ? undefined : ""}>
1783
+ <div id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? undefined : 'content'} data-contextual-actions={site.contextual?.options?.length ? 'true' : 'false'} className="velu-docs-layout__article" data-pagefind-body={chrome.assistant ? undefined : ""}>
1784
1784
  {/* Per-page agent/IDE action bar: the section eyebrow + a
1785
1785
  "Copy Page" split-button whose dropdown is driven by the
1786
1786
  Mintlify-compatible `contextual` config. Renders nothing
@@ -1810,7 +1810,7 @@ function DocsPage() {
1810
1810
  Custom / frame / assistant are a blank canvas — no auto hero. */}
1811
1811
  {chrome.hero && (frontmatter.title || frontmatter.description) && (
1812
1812
  <div className="velu-hero">
1813
- {frontmatter.title && <h1 id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? 'page-title' : pageId}>{frontmatter.title}</h1>}
1813
+ {frontmatter.title && <h1 id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? 'page-title' : pageId}>{frontmatter.title}</h1>}
1814
1814
  {frontmatter.description && (
1815
1815
  <p
1816
1816
  style={{
@@ -1831,7 +1831,7 @@ function DocsPage() {
1831
1831
  level. Falls back to a not-found / missing-file notice
1832
1832
  when the route has no page (or its file is absent). */}
1833
1833
  <MDXProvider components={defaultMdxComponents}>
1834
- <mdx-content key={site.theme === 'vepa' ? pathname : undefined} id={(site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme)) && !entry?.api ? 'content' : undefined} class="velu-prose">
1834
+ <mdx-content key={site.theme === 'vepa' ? pathname : undefined} id={(site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme)) && !entry?.api ? 'content' : undefined} class="velu-prose">
1835
1835
  {PageComponent ? (
1836
1836
  <ErrorBoundary key={pathname} file={entry?.relPath}>
1837
1837
  {entry?.mdxApi ? <ApiReferencePage {...entry.mdxApi} preset={site.theme}><PageComponent /></ApiReferencePage> : <PageComponent />}
@@ -1847,7 +1847,7 @@ function DocsPage() {
1847
1847
  </MDXProvider>
1848
1848
  {/* Page-foot feedback widget — ref'd so the sticky AskBar
1849
1849
  above can hide as the user scrolls near it. */}
1850
- {chrome.articleChrome && !['thulir', 'aalam'].includes(site.theme) && (
1850
+ {chrome.articleChrome && !['thulir', 'aalam', 'nila'].includes(site.theme) && (
1851
1851
  <div ref={setFeedbackEl} style={{ marginTop: 'var(--s3)' }}>
1852
1852
  {/* key resets the widget's vote state on page change. "Yes"
1853
1853
  submits immediately; "No" submits once its form is sent.
@@ -1868,7 +1868,7 @@ function DocsPage() {
1868
1868
  {chrome.articleChrome && !frontmatter.hidePagination && (nav?.prev || nav?.next) && (
1869
1869
  <PageNav
1870
1870
  id="pagination"
1871
- style={['thulir', 'aalam'].includes(site.theme) ? undefined : { marginTop: 'var(--s2)' }}
1871
+ style={['thulir', 'aalam', 'nila'].includes(site.theme) ? undefined : { marginTop: 'var(--s2)' }}
1872
1872
  variant={site.theme === 'aalam' ? 'aalam' : 'default'}
1873
1873
  prev={nav?.prev}
1874
1874
  next={nav?.next}
@@ -1909,7 +1909,7 @@ function DocsPage() {
1909
1909
  full footer section); with link columns they live in the full
1910
1910
  footer below instead. */}
1911
1911
  {chrome.articleChrome && (footerHasLinks ? (
1912
- site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? null : <PoweredBy />
1912
+ site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? null : <PoweredBy />
1913
1913
  ) : (
1914
1914
  <div className="velu-content-foot">
1915
1915
  <SocialLinks socials={footerSocials} />
@@ -1928,7 +1928,7 @@ function DocsPage() {
1928
1928
  overlap via footerOverlap below. */}
1929
1929
  {footerHasLinks && chrome.footer && (
1930
1930
  <advanced-footer
1931
- id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? undefined : 'footer'}
1931
+ id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? undefined : 'footer'}
1932
1932
  ref={setFooterEl}
1933
1933
  data-velu-footer
1934
1934
  style={{ position: 'relative', zIndex: 20 }}
@@ -2004,3 +2004,4 @@ export default function App() {
2004
2004
  </Routes>
2005
2005
  );
2006
2006
  }
2007
+