/// /** * Social Module - Pattern for social media profiles * * A composable pattern that can be used standalone or embedded in containers * like Record. Stores social platform, handle, and profile URL. */ import { computed, type Default, NAME, recipe, UI } from "commontools"; import type { ModuleMetadata } from "./container-protocol.ts"; // ===== Self-Describing Metadata ===== export const MODULE_METADATA: ModuleMetadata = { type: "social", label: "Social", icon: "\u{1F517}", // link emoji schema: { platform: { type: "string", enum: [ "twitter", "linkedin", "github", "instagram", "facebook", "youtube", "tiktok", "mastodon", "bluesky", ], description: "Social platform", }, handle: { type: "string", description: "Username/handle" }, profileUrl: { type: "string", format: "uri", description: "Profile URL" }, }, fieldMapping: ["platform", "handle", "profileUrl"], }; // ===== Types ===== /** Supported social platforms */ type SocialPlatform = | "twitter" | "linkedin" | "github" | "instagram" | "facebook" | "youtube" | "tiktok" | "mastodon" | "bluesky"; export interface SocialModuleInput { /** Social platform (normalize: Insta→instagram, X→twitter) */ platform: Default; /** Username/handle without @ prefix */ handle: Default; /** Profile URL */ profileUrl: Default; } // ===== Constants ===== const PLATFORM_OPTIONS = [ { value: "", label: "Select platform" }, { value: "twitter", label: "𝕏 Twitter/X" }, { value: "linkedin", label: "🔗 LinkedIn" }, { value: "github", label: "🐙 GitHub" }, { value: "instagram", label: "📷 Instagram" }, { value: "facebook", label: "📘 Facebook" }, { value: "youtube", label: "▶️ YouTube" }, { value: "tiktok", label: "🎵 TikTok" }, { value: "mastodon", label: "🐘 Mastodon" }, { value: "bluesky", label: "🦋 Bluesky" }, ]; // ===== The Pattern ===== export const SocialModule = recipe( "SocialModule", ({ platform, handle, profileUrl }) => { const displayText = computed(() => { const opt = PLATFORM_OPTIONS.find((o) => o.value === platform); return handle ? `${opt?.label || platform}: @${handle}` : "Not set"; }); return { [NAME]: computed(() => `${MODULE_METADATA.icon} Social: ${displayText}`), [UI]: ( ), platform, handle, profileUrl, }; }, ); export default SocialModule;