1.0.2 • Published 9 days ago

@pezak/hui-sanity v1.0.2

Weekly downloads
-
License
MIT
Repository
-
Last release
9 days ago

hui-sanity

npm version npm downloads License Nuxt

Harry's UI (hui) sanity package. Configures @nuxtjs/sanity under the hood. Provides composables, etc.

Depends on hui-i18n for localization of fields, so you need to install and configure @pezak/hui-i18n in order to use the sanity module.

 Release Notes

Installation

Install the module to your Nuxt application with one command:

npx nuxi module add @pezak/hui-sanity

Sanity Config

In your /config folder create a sanity.config.ts to configure the hui module and @nuxtjs/sanity used behind-the-scenes.

Update id to point to your project and apiVersion to today's date.

export default {
  projectId: "8m33196t",
  apiVersion: "2024-04-01",
  dataset: "production",
};

The package automatically loads this file and does the rest. If you need more custom config you can use the module key huiSanity.

Usage

You can import multiple types from @pezak/hui-sanity/types such as SanityDocument, SanityImage, SanityPage.

Most frequently used queries are provided from @pezak/hui-sanity/query like imageWithAsset

PageContent and sections

In order to use sanity provided sections for page content, create a component /components/PageContent.vue.

Each section component that can be added as page content in Sanity, needs to be added in the components object explicitly. The key matches the sanity doc type.

<script setup lang="ts">
defineProps<{ content: any[] }>();

const components = {
  hero: resolveComponent("Hero"),
};
</script>

<template>
  <component
    :is="components[c._type as keyof typeof components]"
    v-for="c in content"
    :key="c._id"
    v-bind="c"
  ></component>
</template>

Then in your main page [...slug].vue:

<script setup lang="ts">
import type { SanityPage } from "@pezak/hui-sanity/types";
import { pageQuery } from "./page.query";

const { t } = useMessages();

// Handle Page Fetching
const route = useRoute();

const getPageData = async (
  slug: string[],
): Promise<{
  data: globalThis.Ref<SanityPage | null>;
  pending: globalThis.Ref<boolean>;
  type: "page";
}> => {
  // Page is a generic page
  const query = groq`
    *[_type == "page" && slug.current == "${slug ? slug?.join("/") : "/"}"]{
      ${pageQuery}
    }[0]
  `;
  const { data, pending } = await useSanityQueryWithPreview<SanityPage>(query);

  return { data, pending, type: "page" };
};

const page = await getPageData(route.params.slug as string[]);

// Handle Page Seo Meta
useSeo(page.data.value?.seo);

// This is needed for sanity previewing.
useHead({
  link: [{ rel: "canonical", href: getCanonicalUrl(page.data.value) }],
});
</script>

<template>
  <div :key="route.fullPath">
    <!-- 404 Not Found -->
    <NotFound
      :code="404"
      :message="t('pageNotFound')"
      v-if="!page.data?.value"
    />

    <!-- Page -->
    <PageContent
      :content="page.data.value.content"
      v-else-if="page.type === 'page'"
    />
  </div>
</template>

Composables

const { data, pending } = await useSanityQueryWithPreview<SanityPage>(query);

In app.vue

const headerQuery = groq`
  *[_id == "header"]{ ..., links[]{
    ..., page->
  }}[0]
`;
const footerQuery = groq`
  *[_id == "footer"]{ ..., topLinks[]{
      ..., page->
  }}[0]
`;

const { data } = useSanityQuery<{
  header: HeaderProps;
  footer: FooterProps;
}>(
  `{ 
    "header": ${headerQuery},
    "footer": ${footerQuery},
  }`,
);

Contribution

1.0.2

9 days ago

1.0.1

1 month ago

1.0.0

2 months ago

0.7.2-dev.1

2 months ago

0.7.2-dev.0

2 months ago

0.7.1

2 months ago

0.7.0

2 months ago

0.6.1

2 months ago

0.6.0

2 months ago

0.5.0

2 months ago

0.4.0

2 months ago

0.2.0

2 months ago

0.1.0

2 months ago

0.0.4

2 months ago