/// /** * Shared type definitions for the contacts pattern family. * * Extracted to break circular dependencies between contacts.tsx, * person.tsx, and family-member.tsx. */ import { type Default, NAME, UI, type VNode } from "commontools"; // ============================================================================ // PersonLike - Schelling point for person data (structural type) // ============================================================================ /** * Minimal interface for person-like items. * Defined locally in patterns, not in core API - works via duck typing. * Any object with { firstName, lastName } satisfies PersonLike. */ export interface PersonLike { firstName: string; lastName: string; /** Optional link to same entity in another context (e.g., work vs personal) */ sameAs?: PersonLike; } // ============================================================================ // Address & SocialProfile - Structured sub-types // ============================================================================ export interface Address { label: Default; // "Home", "Work", etc. street: Default; city: Default; state: Default; zip: Default; country: Default; } export interface SocialProfile { platform: Default; // "LinkedIn", "Twitter", etc. url: Default; } // ============================================================================ // Birthday - Structured date with optional year // ============================================================================ export interface Birthday { month: Default; // 1-12, 0 = unset day: Default; // 1-31, 0 = unset year: Default; // 4-digit year, 0 = unknown } // ============================================================================ // Person Type - Extends PersonLike with optional contact fields // ============================================================================ export interface Person extends PersonLike { firstName: string; lastName: string; // Name extensions middleName: Default; nickname: Default; // preferred name / what they go by prefix: Default; // Dr., Mr., Prof. suffix: Default; // Jr., III, Ph.D. // Identity metadata pronouns: Default; // freeform: "he/him", "they/them" birthday: Default; photo: Default; // URL or data reference // Contact fields email: Default; phone: Default; notes: Default; tags: Default; addresses: Default; socialProfiles: Default; } // ============================================================================ // FamilyMember Type - Extends PersonLike with family-specific fields // ============================================================================ export interface FamilyMember extends PersonLike { firstName: string; lastName: string; relationship: Default; birthday: Default; // ISO date string (YYYY-MM-DD) dietaryRestrictions: Default; notes: Default; tags: Default; allergies: Default; giftIdeas: Default; } // ============================================================================ // ContactPiece - What the container stores in its contacts array // ============================================================================ /** * A contact piece has [NAME], [UI], and either person or member data. */ export interface ContactPiece { [NAME]: string; [UI]: VNode; person?: Person; member?: FamilyMember; } // ============================================================================ // ContactGroup - Manual grouping of contacts // ============================================================================ export interface ContactGroup { name: string; contactIndices: Default; // indices into contacts[] } // Default export required by ct check infrastructure export default undefined;