@veluai/velu 0.2.39 → 0.2.41

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,19 +1382,23 @@ 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
1389
1389
  : languageSwitcher || undefined
1390
1390
  }
1391
- onMenuClick={chrome.sidebar ? () => setDrawerOpen((v) => !v) : undefined}
1391
+ onMenuClick={
1392
+ chrome.sidebar || chrome.mode === 'center'
1393
+ ? () => setDrawerOpen((v) => !v)
1394
+ : undefined
1395
+ }
1392
1396
  menuOpen={drawerOpen}
1393
1397
  menuId={site.theme === 'vepa' ? 'sidebar-content' : 'sidebar'}
1394
1398
  breadcrumb={
1395
1399
  chrome.mode === 'custom' || chrome.mode === 'assistant'
1396
1400
  ? []
1397
- : ['thulir', 'aalam'].includes(site.theme) ? (nav?.breadcrumb ?? []).slice(-2) : (nav?.breadcrumb ?? [])
1401
+ : ['thulir', 'aalam', 'nila'].includes(site.theme) ? (nav?.breadcrumb ?? []).slice(-2) : (nav?.breadcrumb ?? [])
1398
1402
  }
1399
1403
  activeTab={nav?.activeTab}
1400
1404
  tabs={
@@ -1448,7 +1452,7 @@ function DocsPage() {
1448
1452
  </>
1449
1453
  )}
1450
1454
  </RouterLink>
1451
- <ThemeToggle variant={site.theme === 'vepa' || site.theme === 'thulir' ? 'menu' : undefined} />
1455
+ <ThemeToggle variant={site.theme === 'vepa' || ['thulir', 'nila'].includes(site.theme) ? 'menu' : undefined} />
1452
1456
  <button
1453
1457
  type="button"
1454
1458
  className="velu-docs-layout__drawer-close"
@@ -1592,7 +1596,7 @@ function DocsPage() {
1592
1596
  left column, including anchors, in one overflow. */}
1593
1597
  <div className="velu-docs-nav-region">
1594
1598
  <div
1595
- id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? 'navigation-items' : 'sidebar-content'}
1599
+ id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? 'navigation-items' : 'sidebar-content'}
1596
1600
  ref={leftAsideRef}
1597
1601
  className={`velu-docs-nav-scroll${site.theme === 'aalam' ? '' : ' velu-hide-scrollbar'}`}
1598
1602
  style={{
@@ -1690,12 +1694,12 @@ function DocsPage() {
1690
1694
  />
1691
1695
  ) : isChangelog && changelogTags.length && site.theme !== 'vepa' ? (
1692
1696
  <ChangelogFilters tags={changelogTags} />
1693
- ) : site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? (
1697
+ ) : site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? (
1694
1698
  <>
1695
1699
  {isChangelog && changelogTags.length > 0 ? (
1696
1700
  <ChangelogFilters tags={changelogTags} />
1697
1701
  ) : null}
1698
- <VepaToc items={pageToc} activeId={['thulir', 'aalam'].includes(site.theme) && activeId === pageId ? pageToc[0]?.id : activeId} onSelect={scrollTo} />
1702
+ <VepaToc items={pageToc} activeId={['thulir', 'aalam', 'nila'].includes(site.theme) && activeId === pageId ? pageToc[0]?.id : activeId} onSelect={scrollTo} />
1699
1703
  </>
1700
1704
  ) : (
1701
1705
  <Toc id="table-of-contents-content" items={toc} activeId={activeId} onSelect={scrollTo} />
@@ -1740,7 +1744,7 @@ function DocsPage() {
1740
1744
  on tab/mobile we keep the normal TOC bar (no filters). Hidden
1741
1745
  entirely when the page mode has no table of contents. */}
1742
1746
  {chrome.toc && (
1743
- <TocBar items={toc} activeId={activeId} onSelect={scrollTo} label={['thulir', 'aalam'].includes(site.theme) ? 'On this page' : undefined} />
1747
+ <TocBar items={toc} activeId={activeId} onSelect={scrollTo} label={['thulir', 'aalam', 'nila'].includes(site.theme) ? 'On this page' : undefined} />
1744
1748
  )}
1745
1749
  <main
1746
1750
  id="content-area"
@@ -1780,7 +1784,7 @@ function DocsPage() {
1780
1784
  </span>
1781
1785
  </button>
1782
1786
  )}
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 : ""}>
1787
+ <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
1788
  {/* Per-page agent/IDE action bar: the section eyebrow + a
1785
1789
  "Copy Page" split-button whose dropdown is driven by the
1786
1790
  Mintlify-compatible `contextual` config. Renders nothing
@@ -1810,7 +1814,7 @@ function DocsPage() {
1810
1814
  Custom / frame / assistant are a blank canvas — no auto hero. */}
1811
1815
  {chrome.hero && (frontmatter.title || frontmatter.description) && (
1812
1816
  <div className="velu-hero">
1813
- {frontmatter.title && <h1 id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? 'page-title' : pageId}>{frontmatter.title}</h1>}
1817
+ {frontmatter.title && <h1 id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? 'page-title' : pageId}>{frontmatter.title}</h1>}
1814
1818
  {frontmatter.description && (
1815
1819
  <p
1816
1820
  style={{
@@ -1831,7 +1835,7 @@ function DocsPage() {
1831
1835
  level. Falls back to a not-found / missing-file notice
1832
1836
  when the route has no page (or its file is absent). */}
1833
1837
  <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">
1838
+ <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
1839
  {PageComponent ? (
1836
1840
  <ErrorBoundary key={pathname} file={entry?.relPath}>
1837
1841
  {entry?.mdxApi ? <ApiReferencePage {...entry.mdxApi} preset={site.theme}><PageComponent /></ApiReferencePage> : <PageComponent />}
@@ -1847,7 +1851,7 @@ function DocsPage() {
1847
1851
  </MDXProvider>
1848
1852
  {/* Page-foot feedback widget — ref'd so the sticky AskBar
1849
1853
  above can hide as the user scrolls near it. */}
1850
- {chrome.articleChrome && !['thulir', 'aalam'].includes(site.theme) && (
1854
+ {chrome.articleChrome && !['thulir', 'aalam', 'nila'].includes(site.theme) && (
1851
1855
  <div ref={setFeedbackEl} style={{ marginTop: 'var(--s3)' }}>
1852
1856
  {/* key resets the widget's vote state on page change. "Yes"
1853
1857
  submits immediately; "No" submits once its form is sent.
@@ -1868,7 +1872,7 @@ function DocsPage() {
1868
1872
  {chrome.articleChrome && !frontmatter.hidePagination && (nav?.prev || nav?.next) && (
1869
1873
  <PageNav
1870
1874
  id="pagination"
1871
- style={['thulir', 'aalam'].includes(site.theme) ? undefined : { marginTop: 'var(--s2)' }}
1875
+ style={['thulir', 'aalam', 'nila'].includes(site.theme) ? undefined : { marginTop: 'var(--s2)' }}
1872
1876
  variant={site.theme === 'aalam' ? 'aalam' : 'default'}
1873
1877
  prev={nav?.prev}
1874
1878
  next={nav?.next}
@@ -1909,7 +1913,7 @@ function DocsPage() {
1909
1913
  full footer section); with link columns they live in the full
1910
1914
  footer below instead. */}
1911
1915
  {chrome.articleChrome && (footerHasLinks ? (
1912
- site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? null : <PoweredBy />
1916
+ site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? null : <PoweredBy />
1913
1917
  ) : (
1914
1918
  <div className="velu-content-foot">
1915
1919
  <SocialLinks socials={footerSocials} />
@@ -1928,7 +1932,7 @@ function DocsPage() {
1928
1932
  overlap via footerOverlap below. */}
1929
1933
  {footerHasLinks && chrome.footer && (
1930
1934
  <advanced-footer
1931
- id={site.theme === 'vepa' || ['thulir', 'aalam'].includes(site.theme) ? undefined : 'footer'}
1935
+ id={site.theme === 'vepa' || ['thulir', 'aalam', 'nila'].includes(site.theme) ? undefined : 'footer'}
1932
1936
  ref={setFooterEl}
1933
1937
  data-velu-footer
1934
1938
  style={{ position: 'relative', zIndex: 20 }}
@@ -2004,3 +2008,4 @@ export default function App() {
2004
2008
  </Routes>
2005
2009
  );
2006
2010
  }
2011
+