浏览代码

Create global product

Loris Leiva 2 年之前
父节点
当前提交
bc6dae0ed9

+ 3 - 3
src/components/MobileNavigation.jsx

@@ -86,10 +86,10 @@ export function MobileNavigation({ page }) {
               <LogoWithName product={page.product} />
             </Link>
           </div>
-          {page.product?.sections && (
+          {page.product.sections && (
             <Sections
-              className="flex flex-col gap-2 mt-12 -ml-2"
-              sections={page.product?.sections}
+              className="-ml-2 mt-12 flex flex-col gap-2"
+              sections={page.product.sections}
               activeSectionId={page.activeSection?.id}
             />
           )}

+ 6 - 2
src/components/products/Grid.jsx

@@ -1,9 +1,13 @@
 import clsx from 'clsx'
 import { LogoWithName } from './Logo'
-import { products } from './index'
+import { products as allProducts } from './index'
 import Link from 'next/link'
 
-export function Grid({ onClick, className, ...props }) {
+export function Grid({ onClick, withoutFallback, className, ...props }) {
+  const products = withoutFallback
+    ? allProducts.filter((product) => !product.isFallbackProduct)
+    : allProducts
+
   return (
     <ul className={clsx(['grid gap-3', className])} {...props}>
       {products.map((product) => (

+ 3 - 24
src/components/products/Logo.jsx

@@ -1,18 +1,13 @@
-import clsx from 'clsx'
-
 export function LogoWithName({ product, ...props }) {
-  const name = product?.name ?? 'Metaplex'
-  const headline = product?.headline ?? 'Developer Hub'
-
   return (
     <div className="flex items-center" {...props}>
       <Logo product={product} className="h-8 w-8 shrink-0" />
       <div className="ml-4 flex flex-1 flex-col justify-center text-left">
         <div className="text-sm font-medium leading-none text-slate-800 dark:text-white">
-          {name}
+          {product.name}
         </div>
-        <div className="text-sm leading-none mt-1 text-slate-500 dark:text-slate-400">
-          {headline}
+        <div className="mt-1 text-sm leading-none text-slate-500 dark:text-slate-400">
+          {product.headline}
         </div>
       </div>
     </div>
@@ -20,22 +15,6 @@ export function LogoWithName({ product, ...props }) {
 }
 
 export function Logo({ product, className, ...props }) {
-  if (!product)
-    return (
-      <svg
-        width="112"
-        height="112"
-        viewBox="0 0 112 112"
-        xmlns="http://www.w3.org/2000/svg"
-        className={clsx('fill-slate-900 dark:fill-slate-100', className)}
-        {...props}
-      >
-        <path d="M111.712 89.3819C112.649 90.9852 111.492 92.9998 109.634 92.9998H88.7318C87.8777 92.9998 87.0879 92.5474 86.656 91.8105L46.0955 22.6205C45.1557 21.0173 46.3123 19 48.1712 19H69.1906C70.0457 19 70.8366 19.4537 71.2679 20.1916L111.712 89.3819Z" />
-        <path d="M55.5027 70.5526C55.9845 71.3624 55.9481 72.3784 55.4101 73.1519L43.7707 89.8792C42.7676 91.3206 40.6051 91.2377 39.7162 89.7231L0.333968 22.6189C-0.606477 21.0165 0.550995 19 2.41125 19H23.4572C24.3066 19 25.0932 19.4469 25.5271 20.176L55.5027 70.5526Z" />
-        <path d="M18.9993 88.7289C19.9512 90.334 18.7947 92.3647 16.9287 92.3647H2.49828C1.16868 92.3647 0.0908203 91.2868 0.0908203 89.9575V65.6304C0.0908203 63.1823 3.31983 62.2966 4.56882 64.4021L18.9993 88.7289Z" />
-      </svg>
-    )
-
   const LogoComponent = product.logo
   return <LogoComponent className={className} {...props} />
 }

+ 27 - 0
src/components/products/global/Hero.jsx

@@ -0,0 +1,27 @@
+import { Hero as BaseHero } from '@/components/Hero'
+import { HeroCode } from '@/components/HeroCode'
+
+const codeProps = {
+  tabs: [
+    { name: 'metadata.rs', isActive: true },
+    { name: 'offchain-metadata.json', isActive: false },
+  ],
+  language: 'rust',
+  code: `pub struct Metadata {
+    pub key: Key,
+    pub update_authority: Pubkey,
+    pub mint: Pubkey,
+    pub data: Data,
+    pub primary_sale_happened: bool,
+    pub is_mutable: bool,
+    // ...
+  }`,
+}
+
+export function Hero({ page }) {
+  return (
+    <BaseHero page={page}>
+      <HeroCode {...codeProps}></HeroCode>
+    </BaseHero>
+  )
+}

+ 18 - 0
src/components/products/global/Logo.jsx

@@ -0,0 +1,18 @@
+import clsx from 'clsx'
+
+export function Logo({ className, ...props }) {
+  return (
+    <svg
+      width="112"
+      height="112"
+      viewBox="0 0 112 112"
+      xmlns="http://www.w3.org/2000/svg"
+      className={clsx('fill-slate-900 dark:fill-slate-100', className)}
+      {...props}
+    >
+      <path d="M111.712 89.3819C112.649 90.9852 111.492 92.9998 109.634 92.9998H88.7318C87.8777 92.9998 87.0879 92.5474 86.656 91.8105L46.0955 22.6205C45.1557 21.0173 46.3123 19 48.1712 19H69.1906C70.0457 19 70.8366 19.4537 71.2679 20.1916L111.712 89.3819Z" />
+      <path d="M55.5027 70.5526C55.9845 71.3624 55.9481 72.3784 55.4101 73.1519L43.7707 89.8792C42.7676 91.3206 40.6051 91.2377 39.7162 89.7231L0.333968 22.6189C-0.606477 21.0165 0.550995 19 2.41125 19H23.4572C24.3066 19 25.0932 19.4469 25.5271 20.176L55.5027 70.5526Z" />
+      <path d="M18.9993 88.7289C19.9512 90.334 18.7947 92.3647 16.9287 92.3647H2.49828C1.16868 92.3647 0.0908203 91.2868 0.0908203 89.9575V65.6304C0.0908203 63.1823 3.31983 62.2966 4.56882 64.4021L18.9993 88.7289Z" />
+    </svg>
+  )
+}

+ 29 - 0
src/components/products/global/index.js

@@ -0,0 +1,29 @@
+import { documentationSection } from '@/shared/sections'
+import { Hero } from './Hero'
+import { Logo } from './Logo'
+
+export const global = {
+  name: 'Metaplex',
+  headline: 'Developer Hub',
+  description: 'TODO',
+  path: '',
+  isFallbackProduct: true,
+  logo: Logo,
+  github: 'https://github.com',
+  className: 'accent-sky',
+  heroes: [{ path: '/', component: Hero }],
+  sections: [
+    {
+      ...documentationSection(''),
+      navigation: [
+        {
+          title: 'Introduction',
+          links: [
+            { title: 'Getting started', href: '/' },
+            { title: 'Installation', href: '/installation' },
+          ],
+        },
+      ],
+    },
+  ],
+}

+ 2 - 0
src/components/products/index.js

@@ -1,12 +1,14 @@
 import { bubblegum } from './bubblegum'
 import { candyMachine } from './candyMachine'
 import { fusion } from './fusion'
+import { global } from './global'
 import { hydra } from './hydra'
 import { tokenAuthRules } from './tokenAuthRules'
 import { tokenMetadata } from './tokenMetadata'
 import { toolbox } from './toolbox'
 
 export const products = [
+  global,
   tokenMetadata,
   tokenAuthRules,
   bubblegum,

+ 36 - 15
src/shared/usePage.js

@@ -6,7 +6,7 @@ import { products } from '@/components/products'
 export function usePage(pageProps) {
   const { pathname } = useRouter()
   const title = pageProps.markdoc?.frontmatter.title ?? 'Metaplex Documentation'
-  const product = getProductFromPathname(pathname)
+  const product = getActiveProduct(pathname, pageProps)
   const activeSection = getActiveSection(pathname, product, pageProps)
   const activeHero = getActiveHero(pathname, product, pageProps)
 
@@ -17,25 +17,41 @@ export function usePage(pageProps) {
     product,
     activeHero,
     activeSection,
-    isIndexPage:  product?.path ? pathname === `/${product.path}` : false,
+    isIndexPage: product?.path ? pathname === `/${product.path}` : false,
     tableOfContents: pageProps.markdoc?.content
       ? parseTableOfContents(pageProps.markdoc.content)
       : [],
   }
 }
 
-function getProductFromPathname(pathname) {
-  const path = pathname.replace(/^\/|\/$/, '').split('/')?.[0]
-  return products.find((product) => product.path === path)
+function getActiveProduct(pathname, pageProps) {
+  const pathnameFirstSegment = pathname.replace(/^\/|\/$/, '').split('/')?.[0]
+  const foundProduct = products.find((product) => {
+    const defaultIsPageFromProduct = () => {
+      if (product.isFallbackProduct) return false
+      return product.path === pathnameFirstSegment
+    }
+    return product.isPageFromProduct
+      ? product.isPageFromProduct({ pathname, product, pageProps })
+      : defaultIsPageFromProduct()
+  })
+  if (foundProduct) return foundProduct
+
+  const fallbackProduct = products.find((product) => product.isFallbackProduct)
+  if (fallbackProduct) return fallbackProduct
+
+  throw new Error('No product found')
 }
 
 function getActiveHero(pathname, product, pageProps) {
   if (!product?.heroes) return undefined
-  return product.heroes.find((hero) => {
-    return hero.doesPageHaveHero
-      ? hero.doesPageHaveHero({ pathname, hero, product, pageProps })
-      : pathname === hero.path
-  })?.component ?? undefined
+  return (
+    product.heroes.find((hero) => {
+      return hero.doesPageHaveHero
+        ? hero.doesPageHaveHero({ pathname, hero, product, pageProps })
+        : pathname === hero.path
+    })?.component ?? undefined
+  )
 }
 
 function getActiveSection(pathname, product, pageProps) {
@@ -45,16 +61,21 @@ function getActiveSection(pathname, product, pageProps) {
   const foundSection = product.sections.find((section) => {
     const defaultIsPageFromSection = () => {
       if (section.isFallbackSection) return false
-      return pathname.startsWith(`${section.href}/`) || pathname === section.href
+      return (
+        pathname.startsWith(`${section.href}/`) || pathname === section.href
+      )
     }
     return section.isPageFromSection
       ? section.isPageFromSection({ pathname, section, product, pageProps })
       : defaultIsPageFromSection()
   })
-  const fallbackSection = product.sections.find((section) => section.isFallbackSection)
-  const activeSection = foundSection || fallbackSection
-    ? { ...(foundSection ?? fallbackSection) }
-    : undefined
+  const fallbackSection = product.sections.find(
+    (section) => section.isFallbackSection
+  )
+  const activeSection =
+    foundSection || fallbackSection
+      ? { ...(foundSection ?? fallbackSection) }
+      : undefined
 
   // Add navigation helpers.
   if (activeSection && activeSection.navigation) {