UNPKG

@vyuh/sanity-schema-marketing

Version:

The Sanity schema package for the Marketing content blocks

227 lines (216 loc) 6.83 kB
import { ContentDescriptor, ContentSchemaBuilder } from '@vyuh/sanity-schema-core'; import { TbUsers as Icon } from 'react-icons/tb'; import { defineField, defineType } from 'sanity'; /** * Team section schema for marketing pages * Based on common patterns from Tailwind UI team sections */ /** * Content descriptor for team content items */ export class TeamDescriptor extends ContentDescriptor { static readonly schemaName = 'marketing.team'; constructor(props: Partial<TeamDescriptor>) { super(TeamDescriptor.schemaName, props); } } /** * Default layout schema for team content items */ export const defaultTeamLayout = defineType({ name: `${TeamDescriptor.schemaName}.layout.default`, title: 'Default', type: 'object', icon: Icon, fields: [ defineField({ name: 'variant', title: 'Variant', type: 'string', description: 'The style variant for the team section', options: { list: [ { title: 'Simple grid', value: 'simple-grid' }, { title: 'With large images', value: 'with-large-images' }, ], }, initialValue: 'simple-grid', validation: (Rule) => Rule.required(), }), ], preview: { select: { variant: 'variant', }, prepare({ variant }) { const variantDisplay = variant ? variant .split('-') .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(' ') : 'Simple Grid'; return { title: `Team Layout: ${variantDisplay}`, subtitle: 'Default', media: Icon, }; }, }, }); export class TeamSchemaBuilder extends ContentSchemaBuilder { private schema = defineType({ name: TeamDescriptor.schemaName, title: 'Team Section', type: 'object', icon: Icon, fields: [ defineField({ name: 'title', title: 'Title', type: 'string', description: 'The main title for the team section', validation: (Rule) => Rule.required(), }), defineField({ name: 'subtitle', title: 'Subtitle', type: 'text', description: 'A supporting text that appears below the title', }), defineField({ name: 'members', title: 'Team Members', type: 'array', of: [ { type: 'object', fields: [ defineField({ name: 'name', title: 'Name', type: 'string', validation: (Rule) => Rule.required(), }), defineField({ name: 'role', title: 'Role', type: 'string', validation: (Rule) => Rule.required(), }), defineField({ name: 'image', title: 'Photo', type: 'image', options: { hotspot: true, }, validation: (Rule) => Rule.required(), }), defineField({ name: 'bio', title: 'Bio', type: 'text', description: 'Short biography of the team member', }), defineField({ name: 'featured', title: 'Featured Member', type: 'boolean', description: 'Whether this member should be highlighted', initialValue: false, }), defineField({ name: 'socialLinks', title: 'Social Links', type: 'array', of: [ { type: 'object', fields: [ defineField({ name: 'platform', title: 'Platform', type: 'string', options: { list: [ { title: 'Twitter', value: 'twitter' }, { title: 'LinkedIn', value: 'linkedin' }, { title: 'GitHub', value: 'github' }, { title: 'Instagram', value: 'instagram' }, { title: 'Facebook', value: 'facebook' }, { title: 'Website', value: 'website' }, ], }, validation: (Rule) => Rule.required(), }), defineField({ name: 'action', title: 'Social Link', type: 'vyuh.action', validation: (Rule) => Rule.required(), }), ], preview: { select: { platform: 'platform', title: 'action.title', url: 'action.url', }, prepare({ platform, title, url }) { return { title: `${platform ? platform.charAt(0).toUpperCase() + platform.slice(1) : 'Social'}: ${title || url || 'Untitled'}`, }; }, }, }, ], }), ], preview: { select: { name: 'name', role: 'role', featured: 'featured', media: 'image', socialCount: 'socialLinks.length', }, prepare({ name, role, featured, media, socialCount = 0 }) { return { title: `Member: ${name || 'Untitled'}`, subtitle: `${role || 'No role'}${featured ? ' • Featured' : ''}${socialCount > 0 ? ` • ${socialCount} social link${socialCount === 1 ? '' : 's'}` : ''}`, media, }; }, }, }, ], validation: (Rule) => Rule.required().min(1), }), defineField({ name: 'action', title: 'Action', type: 'vyuh.action', description: 'Optional call-to-action button', }), ], preview: { select: { title: 'title', members: 'members', }, prepare({ title, members = [] }) { return { title: `Team: ${title || 'Untitled'}`, subtitle: `${members.length} member${members.length === 1 ? '' : 's'}`, media: Icon, }; }, }, }); constructor() { super(TeamDescriptor.schemaName); } build(descriptors: ContentDescriptor[]) { return this.schema; } }