@publier/shell 4.0.1 → 4.1.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.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { h as docsShell, i as DocsShellOptions } from "./integration-BNKc2flb.mjs";
1
+ import { g as docsShell, i as DocsShellOptions } from "./integration-B_QSCkLI.mjs";
2
2
  import "astro/zod";
3
3
  //#region src/build/headers.d.ts
4
4
  /**
@@ -182,7 +182,23 @@ interface NavCta {
182
182
  label: string;
183
183
  href: string;
184
184
  }
185
+ interface NavProduct {
186
+ label: string;
187
+ /** Local product URL prefix used to resolve the current selection. */
188
+ path: string;
189
+ /** Landing destination. Defaults to path. */
190
+ href?: string;
191
+ /** Omit for a product without versioned documentation. */
192
+ versions?: {
193
+ label: string;
194
+ path: string;
195
+ badge?: string;
196
+ default?: boolean;
197
+ }[];
198
+ }
185
199
  interface NavVariant {
200
+ /** Optional product selector and independent version lists. */
201
+ products?: NavProduct[];
186
202
  brand: string;
187
203
  logo: {
188
204
  light?: string;
@@ -204,4 +220,4 @@ interface NavConfig {
204
220
  }
205
221
  declare function docsShell(options?: DocsShellOptions): AstroIntegration;
206
222
  //#endregion
207
- export { publierCascadeHoistPlugin as _, DocsSidebarMetaOverride as a, NavCta as c, NavPathRule as d, NavVariant as f, hoistMediaOutOfUtilitiesLayer as g, docsShell as h, DocsShellOptions as i, NavItem as l, SiteConfig as m, DocVersionConfig as n, LlmsConfig as o, SidebarAnchorConfig as p, DocsConfig as r, NavConfig as s, AnnouncementConfig as t, NavLink as u };
223
+ export { hoistMediaOutOfUtilitiesLayer as _, DocsSidebarMetaOverride as a, NavCta as c, NavPathRule as d, NavProduct as f, docsShell as g, SiteConfig as h, DocsShellOptions as i, NavItem as l, SidebarAnchorConfig as m, DocVersionConfig as n, LlmsConfig as o, NavVariant as p, DocsConfig as r, NavConfig as s, AnnouncementConfig as t, NavLink as u, publierCascadeHoistPlugin as v };
@@ -1,2 +1,2 @@
1
- import { _ as publierCascadeHoistPlugin, a as DocsSidebarMetaOverride, c as NavCta, d as NavPathRule, f as NavVariant, g as hoistMediaOutOfUtilitiesLayer, h as docsShell, i as DocsShellOptions, l as NavItem, m as SiteConfig, n as DocVersionConfig, o as LlmsConfig, p as SidebarAnchorConfig, r as DocsConfig, s as NavConfig, t as AnnouncementConfig, u as NavLink } from "./integration-BNKc2flb.mjs";
2
- export { AnnouncementConfig, DocVersionConfig, DocsConfig, DocsShellOptions, DocsSidebarMetaOverride, LlmsConfig, NavConfig, NavCta, NavItem, NavLink, NavPathRule, NavVariant, SidebarAnchorConfig, SiteConfig, docsShell, hoistMediaOutOfUtilitiesLayer, publierCascadeHoistPlugin };
1
+ import { _ as hoistMediaOutOfUtilitiesLayer, a as DocsSidebarMetaOverride, c as NavCta, d as NavPathRule, f as NavProduct, g as docsShell, h as SiteConfig, i as DocsShellOptions, l as NavItem, m as SidebarAnchorConfig, n as DocVersionConfig, o as LlmsConfig, p as NavVariant, r as DocsConfig, s as NavConfig, t as AnnouncementConfig, u as NavLink, v as publierCascadeHoistPlugin } from "./integration-B_QSCkLI.mjs";
2
+ export { AnnouncementConfig, DocVersionConfig, DocsConfig, DocsShellOptions, DocsSidebarMetaOverride, LlmsConfig, NavConfig, NavCta, NavItem, NavLink, NavPathRule, NavProduct, NavVariant, SidebarAnchorConfig, SiteConfig, docsShell, hoistMediaOutOfUtilitiesLayer, publierCascadeHoistPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@publier/shell",
3
- "version": "4.0.1",
3
+ "version": "4.1.1",
4
4
  "license": "UNLICENSED",
5
5
  "description": "Qwik + Astro docs layout for Publier sites.",
6
6
  "type": "module",
@@ -115,7 +115,7 @@
115
115
  "@github/details-menu-element": "^1.0.13",
116
116
  "@github/relative-time-element": "^5.3.1",
117
117
  "@github/tab-container-element": "^4.9.0",
118
- "@publier/native": "4.0.0",
118
+ "@publier/native": "5.0.1",
119
119
  "@tailwindcss/typography": "^0.5.20",
120
120
  "astro-pagefind": "^2.0.1",
121
121
  "daisyui": "^5.7.22",
@@ -4,8 +4,8 @@ import { navConfig, type NavVariant } from 'virtual:publier-nav-config';
4
4
  import type { TopNavMobileProps } from './types.ts';
5
5
 
6
6
  const EMPTY: NavVariant = { brand: '', logo: null, tabs: [], links: [], cta: null };
7
- const { variant = 'default', currentPath = '' } = Astro.props as TopNavMobileProps;
8
- const v = navConfig.variants[variant] ?? navConfig.variants.default ?? EMPTY;
7
+ const { variant = 'default', currentPath = '', variantConfig } = Astro.props as TopNavMobileProps;
8
+ const v = variantConfig ?? navConfig.variants[variant] ?? navConfig.variants.default ?? EMPTY;
9
9
  const html = shellRenderTopNavMobile(JSON.stringify({ currentPath, v }));
10
10
  ---
11
11
  <Fragment set:html={html} />
@@ -4,8 +4,8 @@ import { navConfig, type NavVariant } from 'virtual:publier-nav-config';
4
4
  import type { TopNavProps } from './types.ts';
5
5
 
6
6
  const EMPTY: NavVariant = { brand: '', logo: null, tabs: [], links: [], cta: null };
7
- const { variant = 'default', currentPath = '' } = Astro.props as TopNavProps;
8
- const v = navConfig.variants[variant] ?? navConfig.variants.default ?? EMPTY;
7
+ const { variant = 'default', currentPath = '', variantConfig } = Astro.props as TopNavProps;
8
+ const v = variantConfig ?? navConfig.variants[variant] ?? navConfig.variants.default ?? EMPTY;
9
9
  const [searchSlotHtml, themeSlotHtml, mobileSlotHtml] = await Promise.all([
10
10
  Astro.slots.has('search') ? Astro.slots.render('search') : Promise.resolve(null),
11
11
  Astro.slots.has('theme') ? Astro.slots.render('theme') : Promise.resolve(null),
@@ -475,12 +475,15 @@ export interface TileGridProps {
475
475
  export interface TopNavProps {
476
476
  /** Variant name from `publier.config.yaml` nav block. Default: `"default"`. */
477
477
  variant?: string;
478
+ /** Resolved navigation for a layout that derives its own docs sections. */
479
+ variantConfig?: import('virtual:publier-nav-config').NavVariant;
478
480
  /** Current page path for active highlighting. Pass `Astro.url.pathname`. */
479
481
  currentPath?: string;
480
482
  }
481
483
 
482
484
  export interface TopNavMobileProps {
483
485
  variant?: string;
486
+ variantConfig?: import('virtual:publier-nav-config').NavVariant;
484
487
  currentPath?: string;
485
488
  }
486
489
 
@@ -10,11 +10,11 @@ import { announcement } from 'virtual:publier-announcement';
10
10
  import { appearance } from 'virtual:publier-appearance';
11
11
  import { feeds } from 'virtual:publier-feeds';
12
12
  import { fonts } from 'virtual:publier-fonts';
13
- import { navConfig } from 'virtual:publier-nav-config';
13
+ import { navConfig, type NavVariant } from 'virtual:publier-nav-config';
14
14
  import { site } from 'virtual:publier-site';
15
15
 
16
- interface Props { title: string; description?: string; nav?: string | false; class?: string; lang?: string }
17
- const { title, description, nav: navProp, class: className, lang = Astro.currentLocale ?? 'en' } = Astro.props;
16
+ interface Props { title: string; description?: string; nav?: string | false; navConfig?: NavVariant; class?: string; lang?: string }
17
+ const { title, description, nav: navProp, navConfig: resolvedNav, class: className, lang = Astro.currentLocale ?? 'en' } = Astro.props;
18
18
  const currentPath = Astro.url.pathname;
19
19
  let navVariant: string | false;
20
20
  if (navProp !== undefined) {
@@ -54,10 +54,10 @@ const [head, bodyOpen, bodyClose] = JSON.parse(shellRenderBaseLayout(JSON.string
54
54
  <slot name="skip" />
55
55
  <Fragment set:html={bodyOpen} />
56
56
  {navVariant !== false && (
57
- <TopNav variant={navVariant} currentPath={currentPath}>
57
+ <TopNav variant={navVariant} variantConfig={resolvedNav} currentPath={currentPath}>
58
58
  {navConfig.searchEnabled && <SearchButton slot="search" />}
59
59
  <ThemeToggle slot="theme" default={appearance.default} strict={appearance.strict} />
60
- <TopNavMobile slot="mobile" variant={navVariant} currentPath={currentPath} />
60
+ <TopNavMobile slot="mobile" variant={navVariant} variantConfig={resolvedNav} currentPath={currentPath} />
61
61
  </TopNav>
62
62
  )}
63
63
  <slot />
@@ -1,10 +1,12 @@
1
1
  ---
2
2
  import { getCollection, render } from 'astro:content';
3
3
  import BaseLayout from '../layouts/base-layout.astro';
4
- import { type BreadcrumbItem, DocsLayout, LastModified, SectionSwitcher, Sidebar, SkipLink, TableOfContents } from '../components/index.ts';
4
+ import { type BreadcrumbItem, DocsLayout, LastModified, Sidebar, SkipLink, TableOfContents } from '../components/index.ts';
5
5
  import { buildSidebar, entryToPage } from '@publier/shell/search';
6
6
  import { shellPlanDocsSlug, shellRenderDocsSlug } from '@publier/native';
7
7
  import { docsConfig } from 'virtual:publier-docs-config';
8
+ import { navConfig, type NavVariant } from 'virtual:publier-nav-config';
9
+ import { site } from 'virtual:publier-site';
8
10
  import '../styles/expressive-code.css';
9
11
  export async function getStaticPaths() {
10
12
  return (await getCollection('docs')).map((entry) => ({ params: { slug: entry.id.replace(/\.(mdx?|md)$/, '').replace(/\/index$/, '').replace(/^index$/, '') || undefined }, props: { entry } }));
@@ -22,6 +24,13 @@ const sections = [
22
24
  return page ? [{ label: page.url === path ? page.frontmatter.title : section, href: page.url }] : [];
23
25
  }),
24
26
  ];
27
+
28
+ const configuredNav = navConfig.variants.docs;
29
+ const docsNav: NavVariant = { ...(configuredNav ?? { brand: site.name, logo: site.logo, tabs: sections, links: [], cta: null }) };
30
+
31
+ if (!docsNav.products?.length && docsConfig.versions.length > 0) {
32
+ docsNav.products = [{ label: 'Documentation', path: '/', href: '/docs', versions: docsConfig.versions }];
33
+ }
25
34
  const breadcrumbs = plan.breadcrumbs.map((crumb) => {
26
35
  const page = pages.find((page) => page.url === crumb.href);
27
36
  return page && crumb.href !== '/docs' ? { ...crumb, label: page.frontmatter.title } : crumb;
@@ -31,12 +40,11 @@ const sidebarItems = buildSidebar(pages.filter((_, index) => ids.has(all[index].
31
40
  const [bodyHead, bodyTail] = shellRenderDocsSlug(JSON.stringify({ title: entry.data.title, description: entry.data.description ?? null })).split('<!--publier-content-slot-->');
32
41
  const lastUpdated = entry.data.lastUpdated instanceof Date ? entry.data.lastUpdated : null;
33
42
  ---
34
- <BaseLayout title={`${entry.data.title} — Docs`} description={entry.data.description} nav="docs">
43
+ <BaseLayout title={`${entry.data.title} — Docs`} description={entry.data.description} nav="docs" navConfig={docsNav}>
35
44
  <SkipLink slot="skip" targetId="main-content" />
36
45
  <DocsLayout breadcrumbs={breadcrumbs.length > 2 ? breadcrumbs : undefined}>
37
46
  <Fragment slot="sidebar">
38
- <SectionSwitcher sections={sections} currentPath={plan.current_path} />
39
- <Sidebar items={sidebarItems} currentPath={plan.current_path} versions={docsConfig.versions.length > 0 ? docsConfig.versions : undefined} anchors={docsConfig.anchors.length > 0 ? docsConfig.anchors : undefined} scope={plan.scope} />
47
+ <Sidebar items={sidebarItems} currentPath={plan.current_path} anchors={docsConfig.anchors.length > 0 ? docsConfig.anchors : undefined} scope={plan.scope} />
40
48
  </Fragment>
41
49
  <TableOfContents slot="toc" headings={headings} />
42
50
  <Fragment set:html={bodyHead} />
@@ -666,3 +666,55 @@ header.alert[data-publier-banner] [data-publier-banner-dismiss] {
666
666
  .prose :where(h2, h3, h4, h5, h6)[id] {
667
667
  scroll-margin-top: 5rem;
668
668
  }
669
+
670
+ /* Documentation keeps product selection and section navigation in the header.
671
+ * Keep the sidebar and anchor offsets in step with both header rows. */
672
+ body:has([data-publier-docs-tabs]) {
673
+ --publier-header-height: 7.125rem;
674
+ }
675
+ [data-publier-docs-header] .navbar-start {
676
+ flex: 0 0 auto;
677
+ width: auto;
678
+ }
679
+ [data-publier-docs-header] .navbar {
680
+ gap: 0.75rem;
681
+ }
682
+ [data-publier-docs-tabs] {
683
+ border-top: 1px solid var(--color-base-300);
684
+ }
685
+ [data-publier-docs-tabs] > div {
686
+ display: flex;
687
+ align-items: center;
688
+ gap: 0.5rem;
689
+ padding-inline: 2rem;
690
+ min-height: 3rem;
691
+ }
692
+ [data-publier-docs-tabs] a.btn {
693
+ border-radius: 0;
694
+ height: 3rem;
695
+ border-bottom: 2px solid transparent;
696
+ background: transparent;
697
+ white-space: nowrap;
698
+ }
699
+ [data-publier-docs-tabs] a[aria-current="page"] {
700
+ border-bottom-color: var(--color-primary);
701
+ color: var(--color-primary);
702
+ }
703
+ [data-publier-docs-sidebar],
704
+ aside[aria-label="Table of contents"] {
705
+ top: var(--publier-header-height, 4rem);
706
+ max-height: calc(100vh - var(--publier-header-height, 4rem));
707
+ }
708
+ body:has([data-publier-docs-header]) :is(h2, h3, h4)[id] {
709
+ scroll-margin-top: calc(var(--publier-header-height, 4rem) + 1rem);
710
+ }
711
+ @media (width < 64rem) {
712
+ [data-publier-docs-tabs] > div {
713
+ padding-inline: 1rem;
714
+ gap: 0;
715
+ overflow-x: auto;
716
+ }
717
+ [data-publier-docs-tabs] a.btn {
718
+ padding-inline: 0.75rem;
719
+ }
720
+ }
@@ -44,7 +44,19 @@ declare module 'virtual:publier-nav-config' {
44
44
  href: string;
45
45
  }
46
46
 
47
+ export interface NavProduct {
48
+ label: string;
49
+ /** Local product URL prefix used to resolve the current selection. */
50
+ path: string;
51
+ /** Landing destination. Defaults to path. */
52
+ href?: string;
53
+ /** Omit for a product without versioned documentation. */
54
+ versions?: { label: string; path: string; badge?: string; default?: boolean }[];
55
+ }
56
+
47
57
  export interface NavVariant {
58
+ /** Optional product selector and independent version lists. */
59
+ products?: NavProduct[];
48
60
  /** Brand text next to (or replacing) the logo. */
49
61
  brand: string;
50
62
  /** Logo paths. Null when no logo configured. */