@skhema/embed 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +55 -0
  2. package/dist/components/SkhemaComponent.d.ts +0 -1
  3. package/dist/components/SkhemaComponent.d.ts.map +1 -1
  4. package/dist/components/SkhemaElement.d.ts.map +1 -1
  5. package/dist/embed.min.js +1 -1
  6. package/dist/embed.min.js.map +1 -1
  7. package/dist/index-DBeyneZT.cjs +215 -0
  8. package/dist/index-DBeyneZT.cjs.map +1 -0
  9. package/dist/index-jwx5CXLB.js +216 -0
  10. package/dist/index-jwx5CXLB.js.map +1 -0
  11. package/dist/index.cjs +113 -668
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.es.js +83 -637
  14. package/dist/index.es.js.map +1 -1
  15. package/dist/render/index.d.ts +55 -0
  16. package/dist/render/index.d.ts.map +1 -0
  17. package/dist/render.cjs +7 -0
  18. package/dist/render.cjs.map +1 -0
  19. package/dist/render.d.ts +2 -0
  20. package/dist/render.es.js +7 -0
  21. package/dist/render.es.js.map +1 -0
  22. package/dist/styles/design-tokens.d.ts +32 -4
  23. package/dist/styles/design-tokens.d.ts.map +1 -1
  24. package/dist/tokens.cjs +16 -0
  25. package/dist/tokens.cjs.map +1 -0
  26. package/dist/tokens.d.ts +17 -0
  27. package/dist/tokens.d.ts.map +1 -0
  28. package/dist/tokens.es.js +16 -0
  29. package/dist/tokens.es.js.map +1 -0
  30. package/dist/utils/color.d.ts +25 -0
  31. package/dist/utils/color.d.ts.map +1 -0
  32. package/dist/utils/sanitization.d.ts +7 -1
  33. package/dist/utils/sanitization.d.ts.map +1 -1
  34. package/dist/validation-DCw9rQeH.cjs +176 -0
  35. package/dist/validation-DCw9rQeH.cjs.map +1 -0
  36. package/dist/validation-Dt4L_df8.js +177 -0
  37. package/dist/validation-Dt4L_df8.js.map +1 -0
  38. package/package.json +20 -7
  39. package/dist/utils/author-attribution.d.ts +0 -16
  40. package/dist/utils/author-attribution.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/styles/design-tokens.ts","../src/utils/author-attribution.ts","../src/utils/analytics.ts","../src/utils/component-validation.ts","../src/utils/hash.ts","../src/utils/sanitization.ts","../src/utils/validation.ts","../src/utils/seo.ts","../src/components/SkhemaComponent.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["/**\n * Hardcoded color tokens for component-type badge colors.\n * Embeds can't rely on host page CSS vars, so we use inline values.\n * Source: skhema-web/src/app/globals.css oklch tokens converted to HSL-ish for browser compat.\n */\n\nexport const COMPONENT_COLORS = {\n diagnosis: {\n bg: 'oklch(0.65 0.06 25 / 0.15)',\n text: 'oklch(0.65 0.06 25)',\n border: 'oklch(0.65 0.06 25 / 0.3)',\n },\n method: {\n bg: 'oklch(0.6 0.06 250 / 0.15)',\n text: 'oklch(0.6 0.06 250)',\n border: 'oklch(0.6 0.06 250 / 0.3)',\n },\n initiatives: {\n bg: 'oklch(0.6 0.06 155 / 0.15)',\n text: 'oklch(0.6 0.06 155)',\n border: 'oklch(0.6 0.06 155 / 0.3)',\n },\n measures: {\n bg: 'oklch(0.6 0.06 300 / 0.15)',\n text: 'oklch(0.6 0.06 300)',\n border: 'oklch(0.6 0.06 300 / 0.3)',\n },\n support: {\n bg: 'oklch(0.65 0.06 65 / 0.15)',\n text: 'oklch(0.65 0.06 65)',\n border: 'oklch(0.65 0.06 65 / 0.3)',\n },\n} as const\n\nexport type ComponentColorKey = keyof typeof COMPONENT_COLORS\n\n/**\n * Shared base card CSS variables for light and dark modes.\n */\nexport const CARD_VARS = {\n light: {\n '--skhema-bg': 'hsl(0 0% 100%)',\n '--skhema-card': 'hsl(0 0% 100%)',\n '--skhema-border': 'hsl(214.3 31.8% 91.4%)',\n '--skhema-text': 'hsl(222.2 84% 4.9%)',\n '--skhema-text-muted': 'hsl(215.4 16.3% 46.9%)',\n '--skhema-accent': 'hsl(210 40% 96%)',\n '--skhema-surface-subtle': 'hsl(210 40% 97%)',\n },\n dark: {\n '--skhema-bg': 'hsl(222.2 84% 4.9%)',\n '--skhema-card': 'hsl(222.2 84% 4.9%)',\n '--skhema-border': 'hsl(217.2 32.6% 17.5%)',\n '--skhema-text': 'hsl(210 40% 98%)',\n '--skhema-text-muted': 'hsl(215 20.2% 65.1%)',\n '--skhema-accent': 'hsl(217.2 32.6% 17.5%)',\n '--skhema-surface-subtle': 'hsl(217.2 32.6% 12%)',\n },\n} as const\n\n/**\n * Shared card structure styles (used by both SkhemaElement and SkhemaComponent).\n */\nexport const SHARED_CARD_STYLES = `\n/* Monospace acronym badge */\n.skhema-acronym-badge {\n display: inline-flex;\n align-items: center;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 10px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 2px;\n letter-spacing: 0.02em;\n flex-shrink: 0;\n}\n\n/* Footer attribution tagline */\n.skhema-footer-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n line-height: 1.4;\n}\n\n.skhema-footer-attribution a {\n color: var(--skhema-text-muted);\n text-decoration: underline;\n text-decoration-color: var(--skhema-border);\n text-underline-offset: 2px;\n}\n\n.skhema-footer-attribution a:hover {\n color: var(--skhema-text);\n}\n\n/* Contributor line in footer */\n.skhema-contributor-line {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--skhema-text-muted);\n}\n\n.skhema-contributor-line svg {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n}\n\n.skhema-author-link {\n color: inherit;\n text-decoration: none;\n}\n\n.skhema-author-link:hover {\n color: var(--skhema-text);\n text-decoration: underline;\n}\n\n/* Save button — primary brand color */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-primary);\n color: white;\n border: none;\n padding: 6px 14px;\n border-radius: calc(var(--skhema-radius) + 2px);\n font-size: 12px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: background 0.15s ease;\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n background: var(--skhema-primary-hover);\n}\n\n.skhema-save-btn:active {\n background: var(--skhema-primary-pressed);\n}\n\n.skhema-save-btn:focus {\n outline: 2px solid var(--skhema-primary);\n outline-offset: 2px;\n}\n\n.skhema-save-btn::after {\n content: '\\\\2192';\n font-size: 13px;\n}\n`\n\n/**\n * User SVG icon (inline, no external deps).\n */\nexport const USER_ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/></svg>`\n","/**\n * Resolve author display from element attributes.\n * Prefer author-name; contributor-name is deprecated.\n */\nexport interface AuthorAttribution {\n authorName: string\n authorSlug?: string\n}\n\nexport function readAuthorAttribution(\n element: HTMLElement\n): AuthorAttribution | null {\n const authorName =\n element.getAttribute('author-name') ||\n element.getAttribute('contributor-name')\n if (!authorName?.trim()) {\n return null\n }\n const authorSlug = element.getAttribute('author-slug')?.trim()\n return {\n authorName: authorName.trim(),\n authorSlug: authorSlug || undefined,\n }\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\n/**\n * Footer HTML: \"By {authorName}\", linked when authorSlug is set.\n */\nexport function formatAuthorAttributionHtml(\n authorName: string,\n authorSlug?: string\n): string {\n const label = `By ${escapeHtml(authorName)}`\n if (authorSlug) {\n return `<a href=\"https://skhema.com/contributors/${encodeURIComponent(authorSlug)}\" class=\"skhema-author-link\" target=\"_blank\" rel=\"noopener noreferrer\">${label}</a>`\n }\n return `<span class=\"skhema-author-text\">${label}</span>`\n}\n\nexport function formatContributorIdFallback(contributorId: string): string {\n return contributorId\n .split(/[_-]/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n}\n\nexport function resolveAuthorFooterHtml(\n element: HTMLElement,\n contributorId: string\n): string {\n const attribution = readAuthorAttribution(element)\n if (attribution) {\n return formatAuthorAttributionHtml(\n attribution.authorName,\n attribution.authorSlug\n )\n }\n return `<span class=\"skhema-author-text\">By ${escapeHtml(formatContributorIdFallback(contributorId))}</span>`\n}\n","import type {\n ComponentContentData,\n ComponentEmbedAnalytics,\n ContentData,\n EmbedAnalytics,\n} from '../components/types.js'\n\n/**\n * Analytics endpoint — Supabase edge function via Cloudflare proxy.\n * Falls back to direct Supabase URL if proxy is not configured.\n */\nconst ANALYTICS_ENDPOINT =\n 'https://analytics.skhema.com/functions/v1/embed-manage'\n\n// Cookie-based tracking management\ninterface TrackedEmbed {\n contentHash: string\n timestamp: number\n}\n\nconst TRACKING_COOKIE_NAME = '_sk'\nconst TRACKING_EXPIRY_HOURS = 24\nconst MAX_TRACKED_ITEMS = 50 // Prevent cookie from growing too large\n\nfunction getTrackedEmbeds(): TrackedEmbed[] {\n try {\n const cookie = document.cookie\n .split('; ')\n .find((row) => row.startsWith(`${TRACKING_COOKIE_NAME}=`))\n\n if (!cookie) return []\n\n const data = JSON.parse(decodeURIComponent(cookie.split('=')[1]))\n const now = Date.now()\n const cutoff = now - TRACKING_EXPIRY_HOURS * 60 * 60 * 1000\n\n // Filter out expired entries\n return data.filter((item: TrackedEmbed) => item.timestamp > cutoff)\n } catch {\n return []\n }\n}\n\nfunction setTrackedEmbeds(tracked: TrackedEmbed[]): void {\n try {\n // Keep only the most recent entries to prevent cookie bloat\n const limited = tracked.slice(-MAX_TRACKED_ITEMS)\n const expires = new Date(\n Date.now() + TRACKING_EXPIRY_HOURS * 60 * 60 * 1000\n )\n\n document.cookie = `${TRACKING_COOKIE_NAME}=${encodeURIComponent(\n JSON.stringify(limited)\n )}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`\n } catch {\n // Fail silently if cookie storage fails\n }\n}\n\nfunction hasBeenTracked(contentHash: string): boolean {\n const tracked = getTrackedEmbeds()\n return tracked.some((item) => item.contentHash === contentHash)\n}\n\nfunction markAsTracked(contentHash: string): void {\n const tracked = getTrackedEmbeds()\n tracked.push({\n contentHash,\n timestamp: Date.now(),\n })\n setTrackedEmbeds(tracked)\n}\n\n// Batching system for analytics\ninterface BatchedAnalytics {\n embeds: EmbedAnalytics[]\n clicks: ContentData[]\n componentEmbeds: ComponentEmbedAnalytics[]\n componentClicks: ComponentContentData[]\n}\n\nclass AnalyticsBatcher {\n private batch: BatchedAnalytics = {\n embeds: [],\n clicks: [],\n componentEmbeds: [],\n componentClicks: [],\n }\n private batchTimeout: number | null = null\n private readonly BATCH_DELAY = 2000 // 2 seconds\n private readonly MAX_BATCH_SIZE = 10\n\n addEmbedLoad(analytics: EmbedAnalytics): void {\n this.batch.embeds.push(analytics)\n this.scheduleBatchSend()\n }\n\n addClick(contentData: ContentData): void {\n this.batch.clicks.push(contentData)\n this.scheduleBatchSend()\n }\n\n addComponentEmbedLoad(analytics: ComponentEmbedAnalytics): void {\n this.batch.componentEmbeds.push(analytics)\n this.scheduleBatchSend()\n }\n\n addComponentClick(contentData: ComponentContentData): void {\n this.batch.componentClicks.push(contentData)\n this.scheduleBatchSend()\n }\n\n private scheduleBatchSend(): void {\n // Clear existing timeout\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout)\n }\n\n // Send immediately if any batch is full\n const totalItems =\n this.batch.embeds.length +\n this.batch.clicks.length +\n this.batch.componentEmbeds.length +\n this.batch.componentClicks.length\n\n if (totalItems >= this.MAX_BATCH_SIZE) {\n this.sendBatch()\n return\n }\n\n // Otherwise, wait for more events or timeout\n this.batchTimeout = window.setTimeout(() => {\n this.sendBatch()\n }, this.BATCH_DELAY)\n }\n\n private async sendBatch(): Promise<void> {\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout)\n this.batchTimeout = null\n }\n\n const currentBatch = { ...this.batch }\n this.batch = {\n embeds: [],\n clicks: [],\n componentEmbeds: [],\n componentClicks: [],\n }\n\n const hasItems =\n currentBatch.embeds.length > 0 ||\n currentBatch.clicks.length > 0 ||\n currentBatch.componentEmbeds.length > 0 ||\n currentBatch.componentClicks.length > 0\n\n if (!hasItems) return\n\n // Send embeds if any\n if (currentBatch.embeds.length > 0) {\n await this.sendEmbeds(currentBatch.embeds)\n }\n\n // Send clicks if any\n if (currentBatch.clicks.length > 0) {\n await this.sendClicks(currentBatch.clicks)\n }\n\n // Send component embeds if any\n if (currentBatch.componentEmbeds.length > 0) {\n await this.sendComponentEmbeds(currentBatch.componentEmbeds)\n }\n\n // Send component clicks if any\n if (currentBatch.componentClicks.length > 0) {\n await this.sendComponentClicks(currentBatch.componentClicks)\n }\n }\n\n private async sendEmbeds(embeds: EmbedAnalytics[]): Promise<void> {\n if (embeds.length === 0) return\n\n try {\n const payload = {\n action: 'embed',\n events: embeds.map((embed) => ({\n contributor_id: embed.contributorId,\n element_type: embed.elementType,\n content_hash: embed.contentHash,\n content: embed.content,\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n })),\n }\n\n await sendWithRetry(ANALYTICS_ENDPOINT, payload, 'json')\n } catch (error) {\n console.debug('Embed tracking failed:', error)\n }\n }\n\n private async sendClicks(clicks: ContentData[]): Promise<void> {\n // Send clicks individually since they typically navigate away from page\n for (const click of clicks) {\n try {\n const data = {\n action: 'click',\n contributor_id: click.contributor_id,\n content_hash: click.content_hash,\n source_url: click.source_url,\n element_type: click.element_type,\n }\n\n fetch(ANALYTICS_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n credentials: 'omit',\n keepalive: true,\n }).catch(() => {\n // Fail silently\n })\n } catch (error) {\n console.debug('Click tracking failed:', error)\n }\n }\n }\n\n private async sendComponentEmbeds(\n embeds: ComponentEmbedAnalytics[]\n ): Promise<void> {\n if (embeds.length === 0) return\n\n // Edge function expects flat fields at top level, not wrapped in events[]\n for (const embed of embeds) {\n try {\n const payload = {\n action: 'component_embed',\n contributor_id: embed.contributorId,\n component_type: embed.componentType,\n component_hash: embed.componentHash,\n title: embed.title,\n elements: embed.elements.map((el) => ({\n element_type: el.elementType,\n content: el.content,\n content_hash: el.contentHash,\n })),\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n }\n\n await sendWithRetry(ANALYTICS_ENDPOINT, payload, 'json')\n } catch (error) {\n console.debug('Component embed tracking failed:', error)\n }\n }\n }\n\n private async sendComponentClicks(\n clicks: ComponentContentData[]\n ): Promise<void> {\n for (const click of clicks) {\n try {\n const data = {\n action: 'component_click',\n contributor_id: click.contributor_id,\n component_type: click.component_type,\n component_hash: click.component_hash,\n title: click.title,\n source_url: click.source_url,\n }\n\n fetch(ANALYTICS_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n credentials: 'omit',\n keepalive: true,\n }).catch(() => {\n // Fail silently\n })\n } catch (error) {\n console.debug('Component click tracking failed:', error)\n }\n }\n }\n\n // Ensure batch is sent when page unloads.\n // Uses sendBeacon for reliability — async fetch won't complete during unload.\n flush(): void {\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout)\n this.batchTimeout = null\n }\n\n const currentBatch = { ...this.batch }\n this.batch = {\n embeds: [],\n clicks: [],\n componentEmbeds: [],\n componentClicks: [],\n }\n\n // Send embeds via beacon\n if (currentBatch.embeds.length > 0) {\n const payload = {\n action: 'embed',\n events: currentBatch.embeds.map((embed) => ({\n contributor_id: embed.contributorId,\n element_type: embed.elementType,\n content_hash: embed.contentHash,\n content: embed.content,\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n })),\n }\n this.sendViaBeacon(payload)\n }\n\n // Send clicks via beacon\n for (const click of currentBatch.clicks) {\n this.sendViaBeacon({\n action: 'click',\n contributor_id: click.contributor_id,\n content_hash: click.content_hash,\n source_url: click.source_url,\n element_type: click.element_type,\n })\n }\n\n // Send component embeds via beacon (flat fields, not wrapped in events[])\n for (const embed of currentBatch.componentEmbeds) {\n this.sendViaBeacon({\n action: 'component_embed',\n contributor_id: embed.contributorId,\n component_type: embed.componentType,\n component_hash: embed.componentHash,\n title: embed.title,\n elements: embed.elements.map((el) => ({\n element_type: el.elementType,\n content: el.content,\n content_hash: el.contentHash,\n })),\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n })\n }\n\n // Send component clicks via beacon\n for (const click of currentBatch.componentClicks) {\n this.sendViaBeacon({\n action: 'component_click',\n contributor_id: click.contributor_id,\n component_type: click.component_type,\n component_hash: click.component_hash,\n title: click.title,\n source_url: click.source_url,\n })\n }\n }\n\n private sendViaBeacon(payload: Record<string, unknown>): void {\n try {\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(\n ANALYTICS_ENDPOINT,\n new Blob([JSON.stringify(payload)], { type: 'application/json' })\n )\n } else {\n // Fallback to fetch with keepalive\n fetch(ANALYTICS_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n credentials: 'omit',\n keepalive: true,\n }).catch(() => {})\n }\n } catch {\n // Fail silently during unload\n }\n }\n}\n\n// Global batcher instance\nconst analyticsBatcher = new AnalyticsBatcher()\n\n// Flush on page unload\nif (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', () => {\n analyticsBatcher.flush()\n })\n\n // Also flush on visibility change (mobile browsers)\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n analyticsBatcher.flush()\n }\n })\n}\n\n// Retry logic with exponential backoff\nasync function sendWithRetry(\n url: string,\n data: URLSearchParams | Record<string, unknown>,\n contentType: 'json' | 'urlencoded' = 'json',\n maxRetries = 3\n): Promise<void> {\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const options: RequestInit = {\n method: 'POST',\n credentials: 'omit',\n keepalive: true,\n }\n\n if (contentType === 'json') {\n options.headers = { 'Content-Type': 'application/json' }\n options.body = JSON.stringify(data)\n } else {\n options.body = data as URLSearchParams\n }\n\n const response = await fetch(url, options)\n\n if (response.ok) return\n\n if (response.status >= 400 && response.status < 500) {\n // Client error, don't retry\n break\n }\n } catch (error) {\n if (attempt === maxRetries - 1) {\n console.debug('Analytics failed after retries:', error)\n return\n }\n }\n\n // Exponential backoff: 1s, 2s, 4s\n await new Promise((resolve) =>\n setTimeout(resolve, Math.pow(2, attempt) * 1000)\n )\n }\n}\n\n// Main tracking functions\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n // Check if this embed has already been tracked\n if (hasBeenTracked(analytics.contentHash)) {\n console.debug('Embed already tracked, skipping:', analytics.contentHash)\n return\n }\n\n // Mark as tracked before sending to prevent race conditions\n markAsTracked(analytics.contentHash)\n\n // Add to batch instead of sending immediately\n analyticsBatcher.addEmbedLoad(analytics)\n } catch (error) {\n console.debug('Analytics tracking failed:', error)\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n // Add to batch instead of sending immediately\n analyticsBatcher.addClick(contentData)\n } catch (error) {\n console.debug('Click tracking failed:', error)\n }\n}\n\nexport async function trackComponentEmbedLoad(\n analytics: ComponentEmbedAnalytics\n): Promise<void> {\n try {\n // Check if this component has already been tracked\n if (hasBeenTracked(analytics.componentHash)) {\n console.debug(\n 'Component embed already tracked, skipping:',\n analytics.componentHash\n )\n return\n }\n\n // Mark as tracked before sending to prevent race conditions\n markAsTracked(analytics.componentHash)\n\n // Add to batch instead of sending immediately\n analyticsBatcher.addComponentEmbedLoad(analytics)\n } catch (error) {\n console.debug('Component analytics tracking failed:', error)\n }\n}\n\nexport async function trackComponentClick(\n contentData: ComponentContentData\n): Promise<void> {\n try {\n analyticsBatcher.addComponentClick(contentData)\n } catch (error) {\n console.debug('Component click tracking failed:', error)\n }\n}\n\nexport function shouldTrackAnalytics(element: HTMLElement): boolean {\n const trackAnalytics = element.getAttribute('track-analytics')\n return trackAnalytics !== 'false'\n}\n","import type { ComponentValue, ElementValue } from '@skhema/types'\nimport { COMPONENT_TYPES, SKHEMA_MAPPING } from '@skhema/types'\n\n/**\n * Validate that a string is a valid component type.\n */\nexport function isValidComponentType(\n componentType: string\n): componentType is ComponentValue {\n const validTypes = Object.values(COMPONENT_TYPES).map((t) => t.value)\n return validTypes.includes(componentType as ComponentValue)\n}\n\n/**\n * Validate that an element type belongs to the given component type.\n */\nexport function validateElementBelongsToComponent(\n elementType: string,\n componentType: string\n): boolean {\n if (!isValidComponentType(componentType)) return false\n\n const validElements =\n SKHEMA_MAPPING.elementFlow[\n componentType as keyof typeof SKHEMA_MAPPING.elementFlow\n ]\n if (!validElements) return false\n\n return validElements.some((e) => e.value === elementType)\n}\n\n/**\n * Get the human-readable label for a component type.\n */\nexport function getComponentTypeLabel(componentType: string): string {\n const type = Object.values(COMPONENT_TYPES).find(\n (t) => t.value === componentType\n )\n return type?.label || componentType\n}\n\n/**\n * Get the acronym for a component type (e.g., 'BD' for diagnosis).\n */\nexport function getComponentTypeAcronym(componentType: string): string {\n const type = Object.values(COMPONENT_TYPES).find(\n (t) => t.value === componentType\n )\n return type?.acronym || componentType.substring(0, 2).toUpperCase()\n}\n\n/**\n * Resolve which component type an element belongs to.\n * Returns the component value, or 'diagnosis' as fallback.\n */\nexport function resolveComponentType(elementType: string): ComponentValue {\n for (const [componentValue, elements] of Object.entries(\n SKHEMA_MAPPING.elementFlow\n )) {\n if (elements.some((e) => e.value === elementType)) {\n return componentValue as ComponentValue\n }\n }\n return 'diagnosis'\n}\n\n/**\n * Get all valid element types for a given component, ordered per the mapping.\n */\nexport function getElementTypesForComponent(\n componentType: string\n): ElementValue[] {\n if (!isValidComponentType(componentType)) return []\n const elements =\n SKHEMA_MAPPING.elementFlow[\n componentType as keyof typeof SKHEMA_MAPPING.elementFlow\n ]\n return elements?.map((e) => e.value) || []\n}\n","export function generateContentHash(content: string): string {\n // Simple hash function for content identification\n let hash = 0\n const cleanContent = content.trim().substring(0, 200)\n\n for (let i = 0; i < cleanContent.length; i++) {\n const char = cleanContent.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n\n return Math.abs(hash).toString(36).substring(0, 12)\n}\n\n/**\n * Generate a hash for a component by concatenating sorted element content.\n * Used for component-level deduplication and analytics.\n */\nexport function generateComponentHash(\n elements: Array<{ elementType: string; content: string }>\n): string {\n const sorted = [...elements].sort((a, b) => {\n const typeCompare = a.elementType.localeCompare(b.elementType)\n if (typeCompare !== 0) return typeCompare\n return a.content.localeCompare(b.content)\n })\n\n const combined = sorted.map((e) => `${e.elementType}:${e.content}`).join('|')\n return generateContentHash(combined)\n}\n","/**\n * Content sanitization utilities for Skhema web component\n */\n\n/**\n * Sanitizes content to prevent XSS attacks and removes URLs\n * @param content The raw content to sanitize\n * @returns Sanitized HTML-safe content with URLs removed\n */\nexport function sanitizeContent(content: string): string {\n // HTML entity encoding for basic XSS protection\n const htmlEncode = (str: string): string => {\n const div = document.createElement('div')\n div.textContent = str\n return div.innerHTML\n }\n\n // Strip URLs first\n let sanitized = stripUrls(content)\n\n // Encode all HTML entities to prevent script injection\n sanitized = htmlEncode(sanitized)\n\n // Preserve line breaks for readability\n sanitized = sanitized.replace(/\\n/g, '<br>')\n\n // Apply text wrapping rules for long text\n sanitized = applyTextWrapping(sanitized)\n\n return sanitized\n}\n\n/**\n * Strips all URLs from the content\n * @param text The text containing potential URLs\n * @returns Text with all URLs removed\n */\nfunction stripUrls(text: string): string {\n // Comprehensive URL patterns to remove\n const patterns = [\n // Standard URLs with protocols\n /https?:\\/\\/[^\\s<>\"{}|\\\\^`[\\]]+/gi,\n // FTP URLs\n /ftp:\\/\\/[^\\s<>\"{}|\\\\^`[\\]]+/gi,\n // URLs without protocol but with www\n /www\\.[^\\s<>\"{}|\\\\^`[\\]]+/gi,\n // Email-like patterns\n /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/gi,\n // Common domain patterns (anything.com, anything.org, etc.)\n /(?:^|\\s)([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}(?:\\/[^\\s]*)?/gi,\n ]\n\n let stripped = text\n patterns.forEach((pattern) => {\n stripped = stripped.replace(pattern, '')\n })\n\n // Clean up any multiple spaces left after URL removal\n stripped = stripped.replace(/\\s+/g, ' ').trim()\n\n return stripped\n}\n\n/**\n * Applies intelligent text wrapping to prevent layout breaking\n * @param text The text to apply wrapping rules to\n * @returns Text with appropriate wrapping hints\n */\nfunction applyTextWrapping(text: string): string {\n // Split text into words\n const words = text.split(/(\\s+)/)\n\n return words\n .map((word) => {\n // Skip if it's whitespace or already contains HTML\n if (/^\\s+$/.test(word) || word.includes('<')) {\n return word\n }\n\n // For very long words (>30 chars), add word-break opportunities\n if (word.length > 30) {\n // Insert zero-width spaces every 10 characters for breaking\n return word.replace(/(.{10})/g, '$1\\u200B')\n }\n\n return word\n })\n .join('')\n}\n\n/**\n * Validates if content contains potentially malicious patterns or URLs\n * @param content The content to validate\n * @returns Object with validation status and detected issues\n */\nexport function validateContentSecurity(content: string): {\n isSecure: boolean\n issues: string[]\n} {\n const issues: string[] = []\n\n // Check for script tags\n if (/<script[\\s>]/i.test(content)) {\n issues.push('Script tags detected')\n }\n\n // Check for event handlers\n if (/on\\w+\\s*=/i.test(content)) {\n issues.push('Event handlers detected')\n }\n\n // Check for javascript: protocol\n if (/javascript:/i.test(content)) {\n issues.push('JavaScript protocol detected')\n }\n\n // Check for data: URLs that could contain scripts\n if (/data:[^,]*script/i.test(content)) {\n issues.push('Data URL with script detected')\n }\n\n // Check for iframe tags\n if (/<iframe[\\s>]/i.test(content)) {\n issues.push('Iframe tags detected')\n }\n\n // Check for URLs (since we want to disallow them)\n if (/https?:\\/\\//i.test(content) || /www\\./i.test(content)) {\n issues.push('URLs detected in content')\n }\n\n return {\n isSecure: issues.length === 0,\n issues,\n }\n}\n\n/**\n * Strips all HTML tags from content\n * @param content The content to strip\n * @returns Plain text content\n */\nexport function stripHtml(content: string): string {\n const div = document.createElement('div')\n div.innerHTML = content\n return div.textContent || div.innerText || ''\n}\n\n/**\n * Checks if content contains any URLs\n * @param content The content to check\n * @returns True if URLs are found\n */\nexport function containsUrls(content: string): boolean {\n const urlPatterns = [\n /https?:\\/\\//i,\n /ftp:\\/\\//i,\n /www\\./i,\n /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/i,\n /(?:^|\\s)([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}(?:\\/[^\\s]*)?/i,\n ]\n\n return urlPatterns.some((pattern) => pattern.test(content))\n}\n","import type { ElementValue } from '@skhema/types'\nimport { ELEMENT_TYPES } from '@skhema/types'\n\nexport function isValidElementType(\n elementType: string\n): elementType is ElementValue {\n const validTypes = Object.values(ELEMENT_TYPES).map((type) => type.value)\n return validTypes.includes(elementType as ElementValue)\n}\n\nexport function validateAttributes(element: HTMLElement): {\n isValid: boolean\n errors: string[]\n elementType?: ElementValue\n contributorId?: string\n} {\n const errors: string[] = []\n\n const elementType = element.getAttribute('element-type')\n const contributorId = element.getAttribute('contributor-id')\n\n if (!elementType) {\n errors.push('Missing required attribute: element-type')\n } else if (!isValidElementType(elementType)) {\n const validTypes = Object.values(ELEMENT_TYPES)\n .map((t) => t.value)\n .join(', ')\n errors.push(\n `Invalid element-type \"${elementType}\". Valid types: ${validTypes}`\n )\n }\n\n if (!contributorId) {\n errors.push('Missing required attribute: contributor-id')\n } else if (contributorId.trim().length === 0) {\n errors.push('contributor-id cannot be empty')\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n elementType: isValidElementType(elementType || '')\n ? (elementType as ElementValue)\n : undefined,\n contributorId: contributorId || undefined,\n }\n}\n\nexport function getElementTypeLabel(elementType: ElementValue): string {\n const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType)\n return type?.label || elementType\n}\n\nexport function getElementTypeAcronym(elementType: ElementValue): string {\n const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType)\n return type?.acronym || elementType.substring(0, 2).toUpperCase()\n}\n","import type { ComponentValue, ElementValue } from '@skhema/types'\nimport { getComponentTypeLabel } from './component-validation.js'\nimport { generateContentHash } from './hash.js'\nimport { getElementTypeLabel } from './validation.js'\n\nexport function generateStructuredData(\n content: string,\n elementType: ElementValue,\n contributorId: string,\n sourceUrl: string\n): object {\n return {\n '@context': 'https://schema.org',\n '@type': 'AnalysisContent',\n text: content,\n analysisType: elementType,\n category: getElementTypeLabel(elementType),\n contributor: contributorId,\n url: generateRedirectUrl(content, elementType, contributorId),\n provider: {\n '@type': 'Organization',\n name: 'Skhema',\n url: 'https://skhema.com',\n },\n isPartOf: {\n '@type': 'WebPage',\n url: sourceUrl,\n },\n dateCreated: new Date().toISOString(),\n platform: 'Skhema',\n }\n}\n\nexport function generateRedirectUrl(\n content: string,\n elementType: ElementValue,\n contributorId: string,\n options: {\n baseUrl?: string\n utmSource?: string\n utmMedium?: string\n utmCampaign?: string\n } = {}\n): string {\n const baseUrl = options.baseUrl || 'https://app.skhema.com/save' // This page will handle the authentication and content saving\n const contentHash = generateContentHash(content)\n const sourceUrl = encodeURIComponent(window.location.href)\n const timestamp = Date.now()\n\n const params = new URLSearchParams({\n source: sourceUrl,\n t: timestamp.toString(),\n utm_source: options.utmSource || 'web_component',\n utm_medium: options.utmMedium || 'embedded',\n utm_campaign: options.utmCampaign || elementType,\n utm_content: contributorId,\n })\n\n return `${baseUrl}?type=contributor&contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}&${params.toString()}`\n // return `${baseUrl}/contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}?${params.toString()}`;\n}\n\nexport function createMetaTags(\n content: string,\n elementType: ElementValue,\n contributorId: string\n): string {\n const label = getElementTypeLabel(elementType)\n\n return `\n <div itemscope itemtype=\"https://schema.org/AnalysisContent\" style=\"display:none;\">\n <meta itemprop=\"analysisType\" content=\"${elementType}\">\n <meta itemprop=\"text\" content=\"${content}\">\n <meta itemprop=\"contributor\" content=\"${contributorId}\">\n <meta itemprop=\"category\" content=\"${label}\">\n <meta itemprop=\"platform\" content=\"Skhema\">\n </div>\n `\n}\n\nexport function generateComponentStructuredData(\n title: string,\n componentType: ComponentValue,\n contributorId: string,\n elements: Array<{ elementType: string; content: string }>,\n sourceUrl: string\n): object {\n const componentLabel = getComponentTypeLabel(componentType)\n\n return {\n '@context': 'https://schema.org',\n '@type': 'CreativeWork',\n name: title,\n description: `${componentLabel} strategy component`,\n category: componentLabel,\n contributor: contributorId,\n url: generateComponentRedirectUrl(\n generateContentHash(elements.map((e) => e.content).join('|')),\n componentType,\n contributorId\n ),\n hasPart: elements.map((el) => ({\n '@type': 'AnalysisContent',\n text: el.content,\n analysisType: el.elementType,\n category: getElementTypeLabel(el.elementType as ElementValue),\n })),\n provider: {\n '@type': 'Organization',\n name: 'Skhema',\n url: 'https://skhema.com',\n },\n isPartOf: {\n '@type': 'WebPage',\n url: sourceUrl,\n },\n dateCreated: new Date().toISOString(),\n platform: 'Skhema',\n }\n}\n\nexport function generateComponentRedirectUrl(\n componentHash: string,\n componentType: ComponentValue,\n contributorId: string,\n options: {\n baseUrl?: string\n utmSource?: string\n utmMedium?: string\n utmCampaign?: string\n } = {}\n): string {\n const baseUrl = options.baseUrl || 'https://app.skhema.com/save'\n const sourceUrl = encodeURIComponent(window.location.href)\n const timestamp = Date.now()\n\n const params = new URLSearchParams({\n source: sourceUrl,\n t: timestamp.toString(),\n utm_source: options.utmSource || 'web_component',\n utm_medium: options.utmMedium || 'embedded',\n utm_campaign: options.utmCampaign || componentType,\n utm_content: contributorId,\n })\n\n return `${baseUrl}?type=component&component_type=${componentType}&component_hash=${componentHash}&contributor_id=${contributorId}&${params.toString()}`\n}\n\nexport function createAriaAttributes(\n elementType: ElementValue\n): Record<string, string> {\n const label = getElementTypeLabel(elementType)\n\n return {\n role: 'article',\n 'aria-label': `${label} - Strategic element`,\n 'aria-describedby': 'skhema-description',\n }\n}\n","import type { ComponentValue, ElementValue } from '@skhema/types'\nimport {\n COMPONENT_COLORS,\n SHARED_CARD_STYLES,\n USER_ICON_SVG,\n} from '../styles/design-tokens.js'\nimport { resolveAuthorFooterHtml } from '../utils/author-attribution.js'\nimport {\n shouldTrackAnalytics,\n trackComponentClick,\n trackComponentEmbedLoad,\n} from '../utils/analytics.js'\nimport {\n getComponentTypeAcronym,\n getComponentTypeLabel,\n getElementTypesForComponent,\n isValidComponentType,\n validateElementBelongsToComponent,\n} from '../utils/component-validation.js'\nimport { generateComponentHash } from '../utils/hash.js'\nimport { sanitizeContent } from '../utils/sanitization.js'\nimport {\n generateComponentRedirectUrl,\n generateComponentStructuredData,\n} from '../utils/seo.js'\nimport { getElementTypeLabel } from '../utils/validation.js'\nimport type { SkhemaElement } from './SkhemaElement.js'\nimport type {\n ComponentContentData,\n ComponentEmbedAnalytics,\n NestedElementData,\n SkhemaComponentAttributes,\n SkhemaComponentEventMap,\n} from './types.js'\n\nconst styles = `\n:host {\n --skhema-primary: hsl(344 57% 54%);\n --skhema-primary-hover: hsl(344 50% 47%);\n --skhema-secondary: hsl(345 100% 75%);\n\n /* Light mode colors */\n --skhema-bg: hsl(0 0% 100%);\n --skhema-card: hsl(0 0% 100%);\n --skhema-border: hsl(214.3 31.8% 91.4%);\n --skhema-text: hsl(222.2 84% 4.9%);\n --skhema-text-muted: hsl(215.4 16.3% 46.9%);\n --skhema-accent: hsl(210 40% 96%);\n --skhema-surface-subtle: hsl(210 40% 97%);\n\n /* Shadows */\n --skhema-shadow: 0 1px 3px 0 hsl(0 0 0 / 0.1), 0 1px 2px -1px hsl(0 0 0 / 0.1);\n --skhema-shadow-md: 0 4px 6px -1px hsl(0 0 0 / 0.1), 0 2px 4px -2px hsl(0 0 0 / 0.1);\n --skhema-shadow-lg: 0 10px 15px -3px hsl(0 0 0 / 0.1), 0 4px 6px -4px hsl(0 0 0 / 0.1);\n --skhema-radius: 0.1rem;\n\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Inter', sans-serif;\n line-height: 1.5;\n color: var(--skhema-text);\n}\n\n/* Dark mode */\n.skhema-component-card[data-theme=\"dark\"],\n.skhema-skeleton[data-theme=\"dark\"] {\n --skhema-bg: hsl(222.2 84% 4.9%);\n --skhema-card: hsl(222.2 84% 4.9%);\n --skhema-border: hsl(217.2 32.6% 17.5%);\n --skhema-text: hsl(210 40% 98%);\n --skhema-text-muted: hsl(215 20.2% 65.1%);\n --skhema-accent: hsl(217.2 32.6% 17.5%);\n --skhema-surface-subtle: hsl(217.2 32.6% 12%);\n}\n\n/* Main card */\n.skhema-component-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n padding: 0;\n box-shadow: var(--skhema-shadow);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 600px;\n margin: 8px 0;\n overflow: hidden;\n}\n\n.skhema-component-card:hover {\n box-shadow: var(--skhema-shadow-lg);\n transform: translateY(-1px);\n}\n\n/* Colored top border */\n.skhema-top-border {\n height: 2px;\n width: 100%;\n}\n\n/* Header */\n.skhema-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--skhema-border);\n}\n\n.skhema-type-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n}\n\n.skhema-title-separator {\n color: var(--skhema-text-muted);\n font-size: 13px;\n}\n\n.skhema-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--skhema-text);\n}\n\n/* Elements section */\n.skhema-elements {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* Element group */\n.skhema-element-group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.skhema-element-label {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 10px;\n font-weight: 600;\n color: var(--skhema-text-muted);\n}\n\n.skhema-element-content {\n font-size: 14px;\n line-height: 1.6;\n color: var(--skhema-text);\n padding-left: 8px;\n border-left: 2px solid var(--skhema-border);\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n/* Footer */\n.skhema-footer {\n padding: 12px 16px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-footer-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n${SHARED_CARD_STYLES}\n\n/* Error state */\n.skhema-error {\n background: hsl(0 93% 94%);\n border: 1px solid hsl(0 84% 60%);\n color: hsl(0 74% 42%);\n padding: 12px;\n border-radius: calc(var(--skhema-radius) + 2px);\n font-size: 13px;\n}\n\n.skhema-error-title {\n font-weight: 600;\n margin-bottom: 8px;\n}\n\n.skhema-error-list {\n margin: 0;\n padding-left: 16px;\n}\n\n/* Skeleton loading state */\n.skhema-skeleton {\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n padding: 16px;\n box-shadow: var(--skhema-shadow);\n max-width: 600px;\n margin: 8px 0;\n animation: skeletonPulse 1.5s ease-in-out infinite;\n}\n\n.skhema-skeleton-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.skhema-skeleton-badge {\n width: 32px;\n height: 20px;\n border-radius: 2px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skhema-skeleton-text {\n flex: 1;\n}\n\n.skhema-skeleton-line {\n height: 12px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: calc(var(--skhema-radius) + 2px);\n margin: 6px 0;\n}\n\n.skhema-skeleton-line.short { width: 40%; }\n.skhema-skeleton-line.medium { width: 70%; }\n\n.skhema-skeleton-content {\n margin: 16px 0;\n}\n\n@keyframes skeletonPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.8; }\n}\n\n@keyframes shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n}\n\n/* Responsive */\n@media (max-width: 640px) {\n .skhema-component-card {\n margin: 4px 0;\n }\n\n .skhema-header {\n padding: 10px 12px;\n flex-wrap: wrap;\n }\n\n .skhema-elements {\n padding: 12px;\n }\n\n .skhema-footer {\n padding: 10px 12px;\n }\n\n .skhema-footer-row {\n flex-direction: column;\n align-items: stretch;\n gap: 8px;\n }\n\n .skhema-save-btn {\n justify-content: center;\n }\n}\n\n/* Accessibility */\n@media (prefers-reduced-motion: reduce) {\n .skhema-component-card,\n .skhema-save-btn {\n transition: none;\n }\n}\n\n.skhema-structured-data {\n display: none !important;\n}\n`\n\nexport class SkhemaComponent extends HTMLElement {\n private shadow: ShadowRoot\n private contentData: ComponentContentData | null = null\n private componentConnected = false\n private hasTrackedLoad = false\n private pendingRender: number | null = null\n private themeObserver: MutationObserver | null = null\n private mediaQueryListener: MediaQueryList | null = null\n\n constructor() {\n super()\n this.shadow = this.attachShadow({ mode: 'closed' })\n this.renderSkeleton()\n }\n\n static get observedAttributes(): (keyof SkhemaComponentAttributes)[] {\n return [\n 'component-type',\n 'contributor-id',\n 'author-name',\n 'author-slug',\n 'contributor-name',\n 'title',\n 'theme',\n 'track-analytics',\n 'source-url',\n ]\n }\n\n connectedCallback() {\n if (this.componentConnected) return\n this.componentConnected = true\n\n try {\n this.addPreconnectHints()\n\n // Listen for child element ready events (fired by children that upgrade after us)\n this.addEventListener('skhema:element-ready', () => {\n this.scheduleRender()\n })\n\n // Children may have already upgraded and dispatched skhema:element-ready\n // before our listener was set up (registration order: skhema-element first).\n // Wait for any pending custom element upgrades, then render.\n if (typeof customElements.whenDefined === 'function') {\n customElements.whenDefined('skhema-element').then(() => {\n this.scheduleRender()\n })\n } else {\n this.scheduleRender()\n }\n\n this.setupThemeListeners()\n } catch (error) {\n this.renderError('Failed to initialize component', error)\n }\n }\n\n disconnectedCallback() {\n this.cleanupThemeListeners()\n if (this.pendingRender !== null) {\n cancelAnimationFrame(this.pendingRender)\n this.pendingRender = null\n }\n }\n\n attributeChangedCallback(\n _name: keyof SkhemaComponentAttributes,\n oldValue: string | null,\n newValue: string | null\n ) {\n if (oldValue !== newValue && this.componentConnected) {\n this.scheduleRender()\n }\n }\n\n private scheduleRender() {\n if (this.pendingRender !== null) {\n cancelAnimationFrame(this.pendingRender)\n }\n this.pendingRender = requestAnimationFrame(() => {\n this.pendingRender = null\n this.render()\n })\n }\n\n private render() {\n const validation = this.validateComponentAttributes()\n\n if (!validation.isValid) {\n this.renderError('Invalid component attributes', validation.errors)\n return\n }\n\n const componentType = validation.componentType!\n const contributorId = validation.contributorId!\n const title = this.getAttribute('title') || ''\n\n // Gather child element data\n const childElements = this.gatherChildElements(componentType)\n\n if (childElements.length === 0) {\n this.renderError('Component requires child elements', [\n 'Add <skhema-element> children inside this component',\n ])\n return\n }\n\n const componentHash = generateComponentHash(\n childElements.map((el) => ({\n elementType: el.elementType,\n content: el.content,\n }))\n )\n\n this.contentData = {\n contributor_id: contributorId,\n component_type: componentType,\n component_hash: componentHash,\n title,\n elements: childElements.map((el) => ({\n element_type: el.elementType,\n content: el.content,\n content_hash: el.contentHash,\n })),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n this.renderContent(childElements)\n this.addStructuredData()\n this.trackLoad()\n }\n\n private validateComponentAttributes(): {\n isValid: boolean\n errors: string[]\n componentType?: ComponentValue\n contributorId?: string\n } {\n const errors: string[] = []\n const componentType = this.getAttribute('component-type')\n const contributorId = this.getAttribute('contributor-id')\n\n if (!componentType) {\n errors.push('Missing required attribute: component-type')\n } else if (!isValidComponentType(componentType)) {\n errors.push(`Invalid component-type \"${componentType}\"`)\n }\n\n if (!contributorId) {\n errors.push('Missing required attribute: contributor-id')\n } else if (contributorId.trim().length === 0) {\n errors.push('contributor-id cannot be empty')\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n componentType: isValidComponentType(componentType || '')\n ? (componentType as ComponentValue)\n : undefined,\n contributorId: contributorId || undefined,\n }\n }\n\n private gatherChildElements(\n componentType: ComponentValue\n ): NestedElementData[] {\n const children = Array.from(\n this.querySelectorAll('skhema-element')\n ) as SkhemaElement[]\n\n const elements: NestedElementData[] = []\n\n for (const child of children) {\n const data = child.getElementData?.()\n if (!data) continue\n\n // Validate element belongs to this component type\n if (!validateElementBelongsToComponent(data.elementType, componentType)) {\n console.warn(\n `skhema-component: element type \"${data.elementType}\" does not belong to component type \"${componentType}\"`\n )\n // Warn but don't block — still include the element\n }\n\n elements.push(data)\n }\n\n // Sort by elementFlow order for the component type\n const orderedTypes = getElementTypesForComponent(componentType)\n\n elements.sort((a, b) => {\n const aIdx = orderedTypes.indexOf(a.elementType as ElementValue)\n const bIdx = orderedTypes.indexOf(b.elementType as ElementValue)\n // Unknown types go to the end\n const aOrder = aIdx === -1 ? orderedTypes.length : aIdx\n const bOrder = bIdx === -1 ? orderedTypes.length : bIdx\n return aOrder - bOrder\n })\n\n return elements\n }\n\n private renderContent(elements: NestedElementData[]) {\n if (!this.contentData) return\n\n const { component_type, contributor_id, title } = this.contentData\n const componentLabel = getComponentTypeLabel(component_type)\n const acronym = getComponentTypeAcronym(component_type)\n const colors =\n COMPONENT_COLORS[component_type as keyof typeof COMPONENT_COLORS]\n const authorFooterHtml = resolveAuthorFooterHtml(this, contributor_id)\n\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n const redirectUrl = generateComponentRedirectUrl(\n this.contentData.component_hash,\n component_type,\n contributor_id\n )\n\n const badgeStyle = colors\n ? `background: ${colors.bg}; color: ${colors.text}; border: 1px solid ${colors.border};`\n : ''\n\n const topBorderColor = colors ? colors.text : 'var(--skhema-primary)'\n\n // Group elements by type\n const groupedElements = this.groupElementsByType(elements)\n\n // Build element sections HTML\n const elementSectionsHtml = groupedElements\n .map(\n (group) => `\n <div class=\"skhema-element-group\">\n <div class=\"skhema-element-label\">${getElementTypeLabel(group.elementType as ElementValue)}</div>\n ${group.items\n .map(\n (item) =>\n `<div class=\"skhema-element-content\">${sanitizeContent(item.content)}</div>`\n )\n .join('')}\n </div>\n `\n )\n .join('')\n\n // Set ARIA attributes\n this.setAttribute('role', 'article')\n this.setAttribute(\n 'aria-label',\n `${componentLabel} component${title ? ` — ${title}` : ''}`\n )\n\n const titleHtml = title\n ? `<span class=\"skhema-title-separator\">&mdash;</span><span class=\"skhema-title\">${title}</span>`\n : ''\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-component-card\" data-theme=\"${actualTheme}\">\n <div class=\"skhema-top-border\" style=\"background: ${topBorderColor};\"></div>\n\n <div class=\"skhema-header\">\n <span class=\"skhema-acronym-badge\" style=\"${badgeStyle}\" title=\"${componentLabel}\">\n ${acronym}\n </span>\n <span class=\"skhema-type-label\">${componentLabel}</span>\n ${titleHtml}\n </div>\n\n <div class=\"skhema-elements\">\n ${elementSectionsHtml}\n </div>\n\n <div class=\"skhema-footer\">\n <div class=\"skhema-footer-row\">\n <span class=\"skhema-contributor-line\">\n ${USER_ICON_SVG}\n ${authorFooterHtml}\n </span>\n <a href=\"${redirectUrl}\"\n class=\"skhema-save-btn\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this component to Skhema\">\n Save to Skhema\n </a>\n </div>\n <div class=\"skhema-footer-attribution\">\n Strategy powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n </div>\n </div>\n\n <slot style=\"display:none;\"></slot>\n `\n\n // Add click listener\n const saveBtn = this.shadow.querySelector(\n '.skhema-save-btn'\n ) as HTMLAnchorElement\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event)\n })\n }\n }\n\n private groupElementsByType(\n elements: NestedElementData[]\n ): Array<{ elementType: string; items: NestedElementData[] }> {\n const groups = new Map<string, NestedElementData[]>()\n\n for (const el of elements) {\n const existing = groups.get(el.elementType)\n if (existing) {\n existing.push(el)\n } else {\n groups.set(el.elementType, [el])\n }\n }\n\n // Return in insertion order (already sorted by elementFlow)\n return Array.from(groups.entries()).map(([elementType, items]) => ({\n elementType,\n items,\n }))\n }\n\n private getActualTheme(themeAttribute: string): 'light' | 'dark' {\n if (themeAttribute === 'light' || themeAttribute === 'dark') {\n return themeAttribute\n }\n\n const htmlElement = document.documentElement\n const bodyElement = document.body\n\n const htmlTheme =\n htmlElement.getAttribute('data-theme') ||\n htmlElement.getAttribute('theme') ||\n htmlElement.className.match(/theme-(\\w+)/)?.[1]\n\n const bodyTheme =\n bodyElement.getAttribute('data-theme') ||\n bodyElement.getAttribute('theme') ||\n bodyElement.className.match(/theme-(\\w+)/)?.[1]\n\n const hasDarkClass =\n htmlElement.classList.contains('dark') ||\n bodyElement.classList.contains('dark') ||\n htmlElement.classList.contains('dark-mode') ||\n bodyElement.classList.contains('dark-mode')\n\n if (hasDarkClass || htmlTheme === 'dark' || bodyTheme === 'dark') {\n return 'dark'\n }\n\n const computedStyles = window.getComputedStyle(htmlElement)\n const colorScheme = computedStyles.getPropertyValue('color-scheme')\n if (colorScheme && colorScheme.includes('dark')) {\n return 'dark'\n }\n\n if (\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ) {\n return 'dark'\n }\n\n return 'light'\n }\n\n private addPreconnectHints() {\n if (\n document.querySelector(\n 'link[rel=\"preconnect\"][href*=\"analytics.skhema.com\"]'\n )\n ) {\n return\n }\n\n try {\n const preconnectApi = document.createElement('link')\n preconnectApi.rel = 'preconnect'\n preconnectApi.href = 'https://analytics.skhema.com'\n document.head.appendChild(preconnectApi)\n\n const dnsPrefetch = document.createElement('link')\n dnsPrefetch.rel = 'dns-prefetch'\n dnsPrefetch.href = 'https://skhema.com'\n document.head.appendChild(dnsPrefetch)\n } catch (error) {\n console.debug('Failed to add preconnect hints:', error)\n }\n }\n\n private renderSkeleton() {\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-skeleton\" data-theme=\"${actualTheme}\">\n <div class=\"skhema-skeleton-header\">\n <div class=\"skhema-skeleton-badge\"></div>\n <div class=\"skhema-skeleton-text\">\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n <div class=\"skhema-skeleton-content\">\n <div class=\"skhema-skeleton-line short\"></div>\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line short\"></div>\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n\n <slot style=\"display:none;\"></slot>\n `\n }\n\n private renderError(title: string, errors: string | string[] | unknown) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)]\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-component-card\">\n <div class=\"skhema-error\">\n <div class=\"skhema-error-title\">Skhema Component Error: ${title}</div>\n <ul class=\"skhema-error-list\">\n ${errorList.map((error) => `<li>${error}</li>`).join('')}\n </ul>\n </div>\n </div>\n\n <slot style=\"display:none;\"></slot>\n `\n\n this.dispatchEvent(\n new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true,\n })\n )\n }\n\n private addStructuredData() {\n if (!this.contentData) return\n\n const { component_type, contributor_id, title, elements, source_url } =\n this.contentData\n\n const structuredData = generateComponentStructuredData(\n title,\n component_type,\n contributor_id,\n elements.map((el) => ({\n elementType: el.element_type,\n content: el.content,\n })),\n source_url\n )\n\n const script = document.createElement('script')\n script.type = 'application/ld+json'\n script.textContent = JSON.stringify(structuredData)\n script.className = 'skhema-structured-data'\n document.head.appendChild(script)\n }\n\n private async trackLoad() {\n if (\n !shouldTrackAnalytics(this as HTMLElement) ||\n !this.contentData ||\n this.hasTrackedLoad\n ) {\n return\n }\n\n this.hasTrackedLoad = true\n\n const analytics: ComponentEmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n componentType: this.contentData.component_type,\n componentHash: this.contentData.component_hash,\n title: this.contentData.title,\n elements: this.contentData.elements.map((el) => ({\n elementType: el.element_type,\n content: el.content,\n contentHash: el.content_hash,\n })),\n pageUrl: window.location.href,\n pageTitle: document.title,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n }\n\n await trackComponentEmbedLoad(analytics)\n\n this.dispatchEvent(\n new CustomEvent('skhema:component-load', {\n detail: analytics,\n bubbles: true,\n })\n )\n }\n\n private async handleSaveClick(_event: Event) {\n if (!this.contentData) return\n\n if (shouldTrackAnalytics(this as HTMLElement)) {\n await trackComponentClick(this.contentData)\n }\n\n this.dispatchEvent(\n new CustomEvent('skhema:component-click', {\n detail: this.contentData,\n bubbles: true,\n })\n )\n }\n\n // Public API\n public getContentData(): ComponentContentData | null {\n return this.contentData\n }\n\n public refresh(): void {\n this.render()\n }\n\n private setupThemeListeners(): void {\n const themeAttribute = this.getAttribute('theme')\n if (themeAttribute === 'auto' || !themeAttribute) {\n if (window.matchMedia) {\n this.mediaQueryListener = window.matchMedia(\n '(prefers-color-scheme: dark)'\n )\n const handleThemeChange = () => this.updateTheme()\n this.mediaQueryListener.addEventListener('change', handleThemeChange)\n }\n\n this.themeObserver = new MutationObserver(() => this.updateTheme())\n\n this.themeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n\n this.themeObserver.observe(document.body, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n }\n }\n\n private cleanupThemeListeners(): void {\n if (this.themeObserver) {\n this.themeObserver.disconnect()\n this.themeObserver = null\n }\n if (this.mediaQueryListener) {\n this.mediaQueryListener = null\n }\n }\n\n private updateTheme(): void {\n const themeAttribute = this.getAttribute('theme') || 'auto'\n if (themeAttribute === 'auto') {\n const card = this.shadow.querySelector('.skhema-component-card')\n if (card) {\n const newTheme = this.getActualTheme('auto')\n card.setAttribute('data-theme', newTheme)\n }\n }\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface HTMLElementEventMap extends SkhemaComponentEventMap {}\n\n interface SkhemaComponentJSX extends Partial<SkhemaComponentAttributes> {\n [key: string]: unknown\n }\n\n interface JSXIntrinsicElements {\n 'skhema-component': SkhemaComponentJSX\n }\n}\n","import {\n COMPONENT_COLORS,\n SHARED_CARD_STYLES,\n USER_ICON_SVG,\n} from '../styles/design-tokens.js'\nimport { resolveAuthorFooterHtml } from '../utils/author-attribution.js'\nimport {\n shouldTrackAnalytics,\n trackClick,\n trackEmbedLoad,\n} from '../utils/analytics.js'\nimport {\n getComponentTypeAcronym,\n resolveComponentType,\n} from '../utils/component-validation.js'\nimport { generateContentHash } from '../utils/hash.js'\nimport {\n sanitizeContent,\n validateContentSecurity,\n} from '../utils/sanitization.js'\nimport {\n createAriaAttributes,\n createMetaTags,\n generateRedirectUrl,\n generateStructuredData,\n} from '../utils/seo.js'\nimport { getElementTypeLabel, validateAttributes } from '../utils/validation.js'\nimport type {\n ContentData,\n EmbedAnalytics,\n NestedElementData,\n SkhemaElementAttributes,\n SkhemaElementEventMap,\n} from './types.js'\n\n// Inline styles matching Skhema UI library design system\nconst styles = `\n:host {\n /* Skhema Brand Colors - matching UI library */\n --skhema-primary: hsl(344 57% 54%); /* #cd476a */\n --skhema-primary-hover: hsl(344 50% 47%); /* #b53d5e */\n --skhema-primary-pressed: hsl(343 50% 41%); /* #9d3552 */\n --skhema-secondary: hsl(345 100% 75%); /* #ff82a2 */\n\n /* Light mode colors */\n --skhema-bg: hsl(0 0% 100%);\n --skhema-card: hsl(0 0% 100%);\n --skhema-border: hsl(214.3 31.8% 91.4%);\n --skhema-text: hsl(222.2 84% 4.9%);\n --skhema-text-muted: hsl(215.4 16.3% 46.9%);\n --skhema-accent: hsl(210 40% 96%);\n\n /* Shadows matching UI library */\n --skhema-shadow: 0 1px 3px 0 hsl(0 0 0 / 0.1), 0 1px 2px -1px hsl(0 0 0 / 0.1);\n --skhema-shadow-md: 0 4px 6px -1px hsl(0 0 0 / 0.1), 0 2px 4px -2px hsl(0 0 0 / 0.1);\n --skhema-shadow-lg: 0 10px 15px -3px hsl(0 0 0 / 0.1), 0 4px 6px -4px hsl(0 0 0 / 0.1);\n --skhema-radius: 0.1rem;\n\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Inter', sans-serif;\n line-height: 1.5;\n color: var(--skhema-text);\n}\n\n/* Dark mode styles - applied via data-theme attribute */\n.skhema-element-card[data-theme=\"dark\"],\n.skhema-skeleton[data-theme=\"dark\"] {\n --skhema-bg: hsl(222.2 84% 4.9%);\n --skhema-card: hsl(222.2 84% 4.9%);\n --skhema-border: hsl(217.2 32.6% 17.5%);\n --skhema-text: hsl(210 40% 98%);\n --skhema-text-muted: hsl(215 20.2% 65.1%);\n --skhema-accent: hsl(217.2 32.6% 17.5%);\n}\n\n/* Main component card */\n.skhema-element-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n padding: 0;\n box-shadow: var(--skhema-shadow);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 600px;\n margin: 8px 0;\n overflow: hidden;\n}\n\n.skhema-element-card:hover {\n box-shadow: var(--skhema-shadow-lg);\n border-color: var(--skhema-primary);\n transform: translateY(-1px);\n}\n\n/* Header section with acronym badge + element type label */\n.skhema-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--skhema-border);\n}\n\n/* Content section */\n.skhema-content {\n padding: 16px;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n word-wrap: break-word;\n overflow-wrap: break-word;\n hyphens: auto;\n max-width: 100%;\n}\n\n/* Footer section */\n.skhema-footer {\n padding: 12px 16px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-footer-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n${SHARED_CARD_STYLES}\n\n/* Element type label next to badge */\n.skhema-type-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--skhema-text);\n}\n\n/* Error state */\n.skhema-error {\n background: hsl(0 93% 94%);\n border: 1px solid hsl(0 84% 60%);\n color: hsl(0 74% 42%);\n padding: 12px;\n border-radius: calc(var(--skhema-radius) + 2px);\n font-size: 13px;\n}\n\n.skhema-error-title {\n font-weight: 600;\n margin-bottom: 8px;\n}\n\n.skhema-error-list {\n margin: 0;\n padding-left: 16px;\n}\n\n/* Skeleton loading state */\n.skhema-skeleton {\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n padding: 16px;\n box-shadow: var(--skhema-shadow);\n max-width: 600px;\n margin: 8px 0;\n animation: skeletonPulse 1.5s ease-in-out infinite;\n}\n\n.skhema-skeleton-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.skhema-skeleton-badge {\n width: 32px;\n height: 20px;\n border-radius: 2px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skhema-skeleton-text {\n flex: 1;\n}\n\n.skhema-skeleton-line {\n height: 12px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: calc(var(--skhema-radius) + 2px);\n margin: 6px 0;\n}\n\n.skhema-skeleton-line.short {\n width: 40%;\n}\n\n.skhema-skeleton-line.medium {\n width: 70%;\n}\n\n.skhema-skeleton-content {\n margin: 16px 0;\n}\n\n@keyframes skeletonPulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.8;\n }\n}\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-element-card {\n margin: 4px 0;\n }\n\n .skhema-header {\n padding: 10px 12px;\n }\n\n .skhema-content {\n padding: 12px;\n }\n\n .skhema-footer {\n padding: 10px 12px;\n }\n\n .skhema-footer-row {\n flex-direction: column;\n align-items: stretch;\n gap: 8px;\n }\n\n .skhema-save-btn {\n justify-content: center;\n }\n}\n\n/* Accessibility */\n@media (prefers-reduced-motion: reduce) {\n .skhema-element-card,\n .skhema-save-btn {\n transition: none;\n }\n\n .skhema-save-btn::after {\n transition: none;\n }\n\n .skhema-save-btn:hover::after {\n transform: none;\n }\n}\n\n.skhema-structured-data {\n display: none !important;\n}\n`\n\nexport class SkhemaElement extends HTMLElement {\n private shadow: ShadowRoot\n private contentData: ContentData | null = null\n private componentConnected = false\n private hasTrackedLoad = false\n private nestedMode = false\n private themeObserver: MutationObserver | null = null\n private mediaQueryListener: MediaQueryList | null = null\n\n constructor() {\n super()\n this.shadow = this.attachShadow({ mode: 'closed' })\n // Show skeleton immediately while component initializes\n this.renderSkeleton()\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return [\n 'element-type',\n 'contributor-id',\n 'author-name',\n 'author-slug',\n 'contributor-name',\n 'content',\n 'source-url',\n 'theme',\n 'track-analytics',\n ]\n }\n\n connectedCallback() {\n if (this.componentConnected) return\n this.componentConnected = true\n\n // Check if nested inside a <skhema-component>\n if (this.closest('skhema-component')) {\n this.nestedMode = true\n\n // Validate and parse content\n const validation = validateAttributes(this as HTMLElement)\n if (!validation.isValid) {\n console.warn(\n 'skhema-element: invalid attributes in nested mode',\n validation.errors\n )\n return\n }\n\n const content = this.getContent()\n if (!content.trim()) {\n console.warn('skhema-element: empty content in nested mode')\n return\n }\n\n this.contentData = {\n contributor_id: validation.contributorId!,\n element_type: validation.elementType!,\n content: content,\n content_hash: generateContentHash(content),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n // Clear shadow DOM — parent component handles rendering\n this.shadow.innerHTML = ''\n\n // Dispatch ready event so parent component can discover us\n this.dispatchEvent(\n new CustomEvent('skhema:element-ready', {\n bubbles: true,\n composed: true,\n detail: this.getElementData(),\n })\n )\n return\n }\n\n try {\n // Add preconnect hints for faster analytics loading\n this.addPreconnectHints()\n\n // Use requestAnimationFrame for smoother render\n requestAnimationFrame(() => {\n this.render()\n this.trackLoad()\n this.setupThemeListeners()\n })\n } catch (error) {\n this.renderError('Failed to initialize component', error)\n }\n }\n\n disconnectedCallback() {\n this.cleanupThemeListeners()\n }\n\n attributeChangedCallback(\n _name: keyof SkhemaElementAttributes,\n oldValue: string | null,\n newValue: string | null\n ) {\n if (oldValue !== newValue && this.componentConnected && !this.nestedMode) {\n this.render()\n }\n }\n\n /**\n * Returns element data for parent <skhema-component> consumption.\n */\n public getElementData(): NestedElementData | null {\n if (!this.contentData) return null\n return {\n elementType: this.contentData.element_type,\n content: this.contentData.content,\n contentHash: this.contentData.content_hash,\n }\n }\n\n private render() {\n const validation = validateAttributes(this as HTMLElement)\n\n if (!validation.isValid) {\n this.renderError('Invalid component attributes', validation.errors)\n return\n }\n\n const content = this.getContent()\n if (!content.trim()) {\n this.renderError('Component requires content', [\n 'Add content between the opening and closing tags, or use the content attribute',\n ])\n return\n }\n\n // Validate content security\n const securityValidation = validateContentSecurity(content)\n if (!securityValidation.isSecure) {\n this.renderError(\n 'Content security validation failed',\n securityValidation.issues\n )\n return\n }\n\n this.contentData = {\n contributor_id: validation.contributorId!,\n element_type: validation.elementType!,\n content: content,\n content_hash: generateContentHash(content),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n this.renderContent()\n this.addStructuredData()\n }\n\n private getContent(): string {\n return this.getAttribute('content') || this.textContent || ''\n }\n\n private renderContent() {\n if (!this.contentData) return\n\n const { element_type, contributor_id, content } = this.contentData\n const label = getElementTypeLabel(element_type)\n const redirectUrl = generateRedirectUrl(\n content,\n element_type,\n contributor_id\n )\n\n // Determine the actual theme to use\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n const authorFooterHtml = resolveAuthorFooterHtml(this, contributor_id)\n\n // Resolve component type for badge color\n const componentType = resolveComponentType(element_type)\n const acronym = getComponentTypeAcronym(componentType)\n const colors =\n COMPONENT_COLORS[componentType as keyof typeof COMPONENT_COLORS]\n\n // Set ARIA attributes on host element\n const ariaAttrs = createAriaAttributes(element_type)\n Object.entries(ariaAttrs).forEach(([key, value]) => {\n this.setAttribute(key, value)\n })\n\n const badgeStyle = colors\n ? `background: ${colors.bg}; color: ${colors.text}; border: 1px solid ${colors.border};`\n : ''\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-element-card\" data-theme=\"${actualTheme}\">\n <div class=\"skhema-header\">\n <span class=\"skhema-acronym-badge\" style=\"${badgeStyle}\" title=\"${label}\">\n ${acronym}\n </span>\n <span class=\"skhema-type-label\">${label}</span>\n </div>\n\n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${sanitizeContent(content)}</div>\n </div>\n\n <div class=\"skhema-footer\">\n <div class=\"skhema-footer-row\">\n <span class=\"skhema-contributor-line\">\n ${USER_ICON_SVG}\n ${authorFooterHtml}\n </span>\n <a href=\"${redirectUrl}\"\n class=\"skhema-save-btn\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this element to Skhema\">\n Save to Skhema\n </a>\n </div>\n <div class=\"skhema-footer-attribution\">\n Strategy powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n </div>\n </div>\n `\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector(\n '.skhema-save-btn'\n ) as HTMLAnchorElement\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event)\n })\n }\n }\n\n private getActualTheme(themeAttribute: string): 'light' | 'dark' {\n if (themeAttribute === 'light' || themeAttribute === 'dark') {\n return themeAttribute\n }\n\n // Auto mode - detect from system/page\n // First check if the page has set a data-theme or theme attribute\n const htmlElement = document.documentElement\n const bodyElement = document.body\n\n // Check common theme attributes on html or body\n const htmlTheme =\n htmlElement.getAttribute('data-theme') ||\n htmlElement.getAttribute('theme') ||\n htmlElement.className.match(/theme-(\\w+)/)?.[1]\n\n const bodyTheme =\n bodyElement.getAttribute('data-theme') ||\n bodyElement.getAttribute('theme') ||\n bodyElement.className.match(/theme-(\\w+)/)?.[1]\n\n // Check for dark mode classes\n const hasDarkClass =\n htmlElement.classList.contains('dark') ||\n bodyElement.classList.contains('dark') ||\n htmlElement.classList.contains('dark-mode') ||\n bodyElement.classList.contains('dark-mode')\n\n if (hasDarkClass || htmlTheme === 'dark' || bodyTheme === 'dark') {\n return 'dark'\n }\n\n // Check CSS custom properties that might indicate theme\n const computedStyles = window.getComputedStyle(htmlElement)\n const colorScheme = computedStyles.getPropertyValue('color-scheme')\n if (colorScheme && colorScheme.includes('dark')) {\n return 'dark'\n }\n\n // Check system preference\n if (\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ) {\n return 'dark'\n }\n\n // Default to light\n return 'light'\n }\n\n private addPreconnectHints() {\n // Only add preconnect hints once per page\n if (\n document.querySelector(\n 'link[rel=\"preconnect\"][href*=\"analytics.skhema.com\"]'\n )\n ) {\n return\n }\n\n try {\n // Preconnect to analytics API\n const preconnectApi = document.createElement('link')\n preconnectApi.rel = 'preconnect'\n preconnectApi.href = 'https://analytics.skhema.com'\n document.head.appendChild(preconnectApi)\n\n // DNS prefetch for main domain\n const dnsPrefetch = document.createElement('link')\n dnsPrefetch.rel = 'dns-prefetch'\n dnsPrefetch.href = 'https://skhema.com'\n document.head.appendChild(dnsPrefetch)\n } catch (error) {\n console.debug('Failed to add preconnect hints:', error)\n }\n }\n\n private renderSkeleton() {\n // Determine theme for skeleton\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-skeleton\" data-theme=\"${actualTheme}\">\n <div class=\"skhema-skeleton-header\">\n <div class=\"skhema-skeleton-badge\"></div>\n <div class=\"skhema-skeleton-text\">\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n <div class=\"skhema-skeleton-content\">\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n `\n }\n\n private renderError(title: string, errors: string | string[] | unknown) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)]\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-element-card\">\n <div class=\"skhema-error\">\n <div class=\"skhema-error-title\">Skhema Component Error: ${title}</div>\n <ul class=\"skhema-error-list\">\n ${errorList.map((error) => `<li>${error}</li>`).join('')}\n </ul>\n </div>\n </div>\n `\n\n // Dispatch error event\n this.dispatchEvent(\n new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true,\n })\n )\n }\n\n private addStructuredData() {\n if (!this.contentData) return\n\n const { content, element_type, contributor_id, source_url } =\n this.contentData\n\n // Add structured data to the document head\n const structuredData = generateStructuredData(\n content,\n element_type,\n contributor_id,\n source_url\n )\n const script = document.createElement('script')\n script.type = 'application/ld+json'\n script.textContent = JSON.stringify(structuredData)\n script.className = 'skhema-structured-data'\n document.head.appendChild(script)\n\n // Add meta tags for SEO\n const metaDiv = document.createElement('div')\n metaDiv.innerHTML = createMetaTags(content, element_type, contributor_id)\n metaDiv.className = 'skhema-structured-data'\n document.body.appendChild(metaDiv)\n }\n\n private async trackLoad() {\n if (\n !shouldTrackAnalytics(this as HTMLElement) ||\n !this.contentData ||\n this.hasTrackedLoad\n ) {\n return\n }\n\n this.hasTrackedLoad = true\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\n content: this.contentData.content,\n pageUrl: window.location.href,\n pageTitle: document.title,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n }\n\n await trackEmbedLoad(analytics)\n\n // Dispatch load event\n this.dispatchEvent(\n new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true,\n })\n )\n }\n\n private async handleSaveClick(_event: Event) {\n if (!this.contentData) return\n\n // Track click analytics\n if (shouldTrackAnalytics(this as HTMLElement)) {\n await trackClick(this.contentData)\n }\n\n // Dispatch click event\n this.dispatchEvent(\n new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true,\n })\n )\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData\n }\n\n public refresh(): void {\n if (!this.nestedMode) {\n this.render()\n }\n }\n\n private setupThemeListeners(): void {\n // Only set up listeners if theme is 'auto' or not specified\n const themeAttribute = this.getAttribute('theme')\n if (themeAttribute === 'auto' || !themeAttribute) {\n // Listen for system theme changes\n if (window.matchMedia) {\n this.mediaQueryListener = window.matchMedia(\n '(prefers-color-scheme: dark)'\n )\n const handleThemeChange = () => this.updateTheme()\n this.mediaQueryListener.addEventListener('change', handleThemeChange)\n }\n\n // Listen for theme changes on html/body elements\n this.themeObserver = new MutationObserver(() => this.updateTheme())\n\n // Observe both html and body for attribute changes\n this.themeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n\n this.themeObserver.observe(document.body, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n }\n }\n\n private cleanupThemeListeners(): void {\n if (this.themeObserver) {\n this.themeObserver.disconnect()\n this.themeObserver = null\n }\n\n if (this.mediaQueryListener) {\n // Note: We can't remove the specific listener without storing the reference\n // but setting to null will allow garbage collection\n this.mediaQueryListener = null\n }\n }\n\n private updateTheme(): void {\n // Only update if component is using auto theme\n const themeAttribute = this.getAttribute('theme') || 'auto'\n if (themeAttribute === 'auto') {\n // Re-render with new detected theme\n const card = this.shadow.querySelector('.skhema-element-card')\n if (card) {\n const newTheme = this.getActualTheme('auto')\n card.setAttribute('data-theme', newTheme)\n }\n }\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n\n interface SkhemaElementJSX extends Partial<SkhemaElementAttributes> {\n [key: string]: unknown\n }\n\n // Module augmentation for JSX without using namespace\n interface JSXIntrinsicElements {\n 'skhema-element': SkhemaElementJSX\n }\n}\n","import { SkhemaComponent } from './components/SkhemaComponent.js'\nimport { SkhemaElement } from './components/SkhemaElement.js'\n\n// Export component classes\nexport { SkhemaComponent, SkhemaElement }\n\n// Export types for TypeScript users\nexport type {\n ComponentContentData,\n ComponentEmbedAnalytics,\n ContentData,\n EmbedAnalytics,\n NestedElementData,\n SkhemaComponentAttributes,\n SkhemaComponentEventMap,\n SkhemaElementAttributes,\n SkhemaElementEventMap,\n} from './components/types.js'\n\n// Export element utilities\nexport {\n getElementTypeAcronym,\n getElementTypeLabel,\n isValidElementType,\n validateAttributes,\n} from './utils/validation.js'\n\n// Export component utilities\nexport {\n getComponentTypeAcronym,\n getComponentTypeLabel,\n isValidComponentType,\n resolveComponentType,\n validateElementBelongsToComponent,\n} from './utils/component-validation.js'\n\n// Export hash utilities\nexport { generateComponentHash } from './utils/hash.js'\n\n// Export analytics utilities\nexport {\n shouldTrackAnalytics,\n trackComponentClick,\n trackComponentEmbedLoad,\n} from './utils/analytics.js'\n\n// Export SEO utilities\nexport {\n generateComponentRedirectUrl,\n generateComponentStructuredData,\n generateRedirectUrl,\n generateStructuredData,\n} from './utils/seo.js'\n\n// Manual registration functions\nexport function registerSkhemaElement() {\n if (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define(\n 'skhema-element',\n SkhemaElement as CustomElementConstructor\n )\n }\n}\n\nexport function registerSkhemaComponent() {\n if (\n typeof window !== 'undefined' &&\n !customElements.get('skhema-component')\n ) {\n customElements.define(\n 'skhema-component',\n SkhemaComponent as CustomElementConstructor\n )\n }\n}\n\n// Auto-register in browser environments (can be tree-shaken if not needed)\nif (typeof window !== 'undefined') {\n if (!customElements.get('skhema-element')) {\n customElements.define(\n 'skhema-element',\n SkhemaElement as CustomElementConstructor\n )\n }\n if (!customElements.get('skhema-component')) {\n customElements.define(\n 'skhema-component',\n SkhemaComponent as CustomElementConstructor\n )\n }\n}\n\n// Default export for convenience\nexport default SkhemaElement\n"],"names":["COMPONENT_TYPES","SKHEMA_MAPPING","ELEMENT_TYPES","styles"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/analytics.ts","../src/utils/hash.ts","../src/utils/seo.ts","../src/components/SkhemaComponent.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["import type {\n ComponentContentData,\n ComponentEmbedAnalytics,\n ContentData,\n EmbedAnalytics,\n} from '../components/types.js'\n\n/**\n * Analytics endpoint — Supabase edge function via Cloudflare proxy.\n * Falls back to direct Supabase URL if proxy is not configured.\n */\nconst ANALYTICS_ENDPOINT =\n 'https://analytics.skhema.com/functions/v1/embed-manage'\n\n// Cookie-based tracking management\ninterface TrackedEmbed {\n contentHash: string\n timestamp: number\n}\n\nconst TRACKING_COOKIE_NAME = '_sk'\nconst TRACKING_EXPIRY_HOURS = 24\nconst MAX_TRACKED_ITEMS = 50 // Prevent cookie from growing too large\n\nfunction getTrackedEmbeds(): TrackedEmbed[] {\n try {\n const cookie = document.cookie\n .split('; ')\n .find((row) => row.startsWith(`${TRACKING_COOKIE_NAME}=`))\n\n if (!cookie) return []\n\n const data = JSON.parse(decodeURIComponent(cookie.split('=')[1]))\n const now = Date.now()\n const cutoff = now - TRACKING_EXPIRY_HOURS * 60 * 60 * 1000\n\n // Filter out expired entries\n return data.filter((item: TrackedEmbed) => item.timestamp > cutoff)\n } catch {\n return []\n }\n}\n\nfunction setTrackedEmbeds(tracked: TrackedEmbed[]): void {\n try {\n // Keep only the most recent entries to prevent cookie bloat\n const limited = tracked.slice(-MAX_TRACKED_ITEMS)\n const expires = new Date(\n Date.now() + TRACKING_EXPIRY_HOURS * 60 * 60 * 1000\n )\n\n document.cookie = `${TRACKING_COOKIE_NAME}=${encodeURIComponent(\n JSON.stringify(limited)\n )}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`\n } catch {\n // Fail silently if cookie storage fails\n }\n}\n\nfunction hasBeenTracked(contentHash: string): boolean {\n const tracked = getTrackedEmbeds()\n return tracked.some((item) => item.contentHash === contentHash)\n}\n\nfunction markAsTracked(contentHash: string): void {\n const tracked = getTrackedEmbeds()\n tracked.push({\n contentHash,\n timestamp: Date.now(),\n })\n setTrackedEmbeds(tracked)\n}\n\n// Batching system for analytics\ninterface BatchedAnalytics {\n embeds: EmbedAnalytics[]\n clicks: ContentData[]\n componentEmbeds: ComponentEmbedAnalytics[]\n componentClicks: ComponentContentData[]\n}\n\nclass AnalyticsBatcher {\n private batch: BatchedAnalytics = {\n embeds: [],\n clicks: [],\n componentEmbeds: [],\n componentClicks: [],\n }\n private batchTimeout: number | null = null\n private readonly BATCH_DELAY = 2000 // 2 seconds\n private readonly MAX_BATCH_SIZE = 10\n\n addEmbedLoad(analytics: EmbedAnalytics): void {\n this.batch.embeds.push(analytics)\n this.scheduleBatchSend()\n }\n\n addClick(contentData: ContentData): void {\n this.batch.clicks.push(contentData)\n this.scheduleBatchSend()\n }\n\n addComponentEmbedLoad(analytics: ComponentEmbedAnalytics): void {\n this.batch.componentEmbeds.push(analytics)\n this.scheduleBatchSend()\n }\n\n addComponentClick(contentData: ComponentContentData): void {\n this.batch.componentClicks.push(contentData)\n this.scheduleBatchSend()\n }\n\n private scheduleBatchSend(): void {\n // Clear existing timeout\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout)\n }\n\n // Send immediately if any batch is full\n const totalItems =\n this.batch.embeds.length +\n this.batch.clicks.length +\n this.batch.componentEmbeds.length +\n this.batch.componentClicks.length\n\n if (totalItems >= this.MAX_BATCH_SIZE) {\n this.sendBatch()\n return\n }\n\n // Otherwise, wait for more events or timeout\n this.batchTimeout = window.setTimeout(() => {\n this.sendBatch()\n }, this.BATCH_DELAY)\n }\n\n private async sendBatch(): Promise<void> {\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout)\n this.batchTimeout = null\n }\n\n const currentBatch = { ...this.batch }\n this.batch = {\n embeds: [],\n clicks: [],\n componentEmbeds: [],\n componentClicks: [],\n }\n\n const hasItems =\n currentBatch.embeds.length > 0 ||\n currentBatch.clicks.length > 0 ||\n currentBatch.componentEmbeds.length > 0 ||\n currentBatch.componentClicks.length > 0\n\n if (!hasItems) return\n\n // Send embeds if any\n if (currentBatch.embeds.length > 0) {\n await this.sendEmbeds(currentBatch.embeds)\n }\n\n // Send clicks if any\n if (currentBatch.clicks.length > 0) {\n await this.sendClicks(currentBatch.clicks)\n }\n\n // Send component embeds if any\n if (currentBatch.componentEmbeds.length > 0) {\n await this.sendComponentEmbeds(currentBatch.componentEmbeds)\n }\n\n // Send component clicks if any\n if (currentBatch.componentClicks.length > 0) {\n await this.sendComponentClicks(currentBatch.componentClicks)\n }\n }\n\n private async sendEmbeds(embeds: EmbedAnalytics[]): Promise<void> {\n if (embeds.length === 0) return\n\n try {\n const payload = {\n action: 'embed',\n events: embeds.map((embed) => ({\n contributor_id: embed.contributorId,\n element_type: embed.elementType,\n content_hash: embed.contentHash,\n content: embed.content,\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n })),\n }\n\n await sendWithRetry(ANALYTICS_ENDPOINT, payload, 'json')\n } catch (error) {\n console.debug('Embed tracking failed:', error)\n }\n }\n\n private async sendClicks(clicks: ContentData[]): Promise<void> {\n // Send clicks individually since they typically navigate away from page\n for (const click of clicks) {\n try {\n const data = {\n action: 'click',\n contributor_id: click.contributor_id,\n content_hash: click.content_hash,\n source_url: click.source_url,\n element_type: click.element_type,\n }\n\n fetch(ANALYTICS_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n credentials: 'omit',\n keepalive: true,\n }).catch(() => {\n // Fail silently\n })\n } catch (error) {\n console.debug('Click tracking failed:', error)\n }\n }\n }\n\n private async sendComponentEmbeds(\n embeds: ComponentEmbedAnalytics[]\n ): Promise<void> {\n if (embeds.length === 0) return\n\n // Edge function expects flat fields at top level, not wrapped in events[]\n for (const embed of embeds) {\n try {\n const payload = {\n action: 'component_embed',\n contributor_id: embed.contributorId,\n component_type: embed.componentType,\n component_hash: embed.componentHash,\n title: embed.title,\n elements: embed.elements.map((el) => ({\n element_type: el.elementType,\n content: el.content,\n content_hash: el.contentHash,\n })),\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n }\n\n await sendWithRetry(ANALYTICS_ENDPOINT, payload, 'json')\n } catch (error) {\n console.debug('Component embed tracking failed:', error)\n }\n }\n }\n\n private async sendComponentClicks(\n clicks: ComponentContentData[]\n ): Promise<void> {\n for (const click of clicks) {\n try {\n const data = {\n action: 'component_click',\n contributor_id: click.contributor_id,\n component_type: click.component_type,\n component_hash: click.component_hash,\n title: click.title,\n source_url: click.source_url,\n }\n\n fetch(ANALYTICS_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n credentials: 'omit',\n keepalive: true,\n }).catch(() => {\n // Fail silently\n })\n } catch (error) {\n console.debug('Component click tracking failed:', error)\n }\n }\n }\n\n // Ensure batch is sent when page unloads.\n // Uses sendBeacon for reliability — async fetch won't complete during unload.\n flush(): void {\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout)\n this.batchTimeout = null\n }\n\n const currentBatch = { ...this.batch }\n this.batch = {\n embeds: [],\n clicks: [],\n componentEmbeds: [],\n componentClicks: [],\n }\n\n // Send embeds via beacon\n if (currentBatch.embeds.length > 0) {\n const payload = {\n action: 'embed',\n events: currentBatch.embeds.map((embed) => ({\n contributor_id: embed.contributorId,\n element_type: embed.elementType,\n content_hash: embed.contentHash,\n content: embed.content,\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n })),\n }\n this.sendViaBeacon(payload)\n }\n\n // Send clicks via beacon\n for (const click of currentBatch.clicks) {\n this.sendViaBeacon({\n action: 'click',\n contributor_id: click.contributor_id,\n content_hash: click.content_hash,\n source_url: click.source_url,\n element_type: click.element_type,\n })\n }\n\n // Send component embeds via beacon (flat fields, not wrapped in events[])\n for (const embed of currentBatch.componentEmbeds) {\n this.sendViaBeacon({\n action: 'component_embed',\n contributor_id: embed.contributorId,\n component_type: embed.componentType,\n component_hash: embed.componentHash,\n title: embed.title,\n elements: embed.elements.map((el) => ({\n element_type: el.elementType,\n content: el.content,\n content_hash: el.contentHash,\n })),\n page_url: embed.pageUrl,\n page_title: embed.pageTitle || '',\n user_agent: embed.userAgent || '',\n })\n }\n\n // Send component clicks via beacon\n for (const click of currentBatch.componentClicks) {\n this.sendViaBeacon({\n action: 'component_click',\n contributor_id: click.contributor_id,\n component_type: click.component_type,\n component_hash: click.component_hash,\n title: click.title,\n source_url: click.source_url,\n })\n }\n }\n\n private sendViaBeacon(payload: Record<string, unknown>): void {\n try {\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(\n ANALYTICS_ENDPOINT,\n new Blob([JSON.stringify(payload)], { type: 'application/json' })\n )\n } else {\n // Fallback to fetch with keepalive\n fetch(ANALYTICS_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n credentials: 'omit',\n keepalive: true,\n }).catch(() => {})\n }\n } catch {\n // Fail silently during unload\n }\n }\n}\n\n// Global batcher instance\nconst analyticsBatcher = new AnalyticsBatcher()\n\n// Flush on page unload\nif (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', () => {\n analyticsBatcher.flush()\n })\n\n // Also flush on visibility change (mobile browsers)\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n analyticsBatcher.flush()\n }\n })\n}\n\n// Retry logic with exponential backoff\nasync function sendWithRetry(\n url: string,\n data: URLSearchParams | Record<string, unknown>,\n contentType: 'json' | 'urlencoded' = 'json',\n maxRetries = 3\n): Promise<void> {\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const options: RequestInit = {\n method: 'POST',\n credentials: 'omit',\n keepalive: true,\n }\n\n if (contentType === 'json') {\n options.headers = { 'Content-Type': 'application/json' }\n options.body = JSON.stringify(data)\n } else {\n options.body = data as URLSearchParams\n }\n\n const response = await fetch(url, options)\n\n if (response.ok) return\n\n if (response.status >= 400 && response.status < 500) {\n // Client error, don't retry\n break\n }\n } catch (error) {\n if (attempt === maxRetries - 1) {\n console.debug('Analytics failed after retries:', error)\n return\n }\n }\n\n // Exponential backoff: 1s, 2s, 4s\n await new Promise((resolve) =>\n setTimeout(resolve, Math.pow(2, attempt) * 1000)\n )\n }\n}\n\n// Main tracking functions\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n // Check if this embed has already been tracked\n if (hasBeenTracked(analytics.contentHash)) {\n console.debug('Embed already tracked, skipping:', analytics.contentHash)\n return\n }\n\n // Mark as tracked before sending to prevent race conditions\n markAsTracked(analytics.contentHash)\n\n // Add to batch instead of sending immediately\n analyticsBatcher.addEmbedLoad(analytics)\n } catch (error) {\n console.debug('Analytics tracking failed:', error)\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n // Add to batch instead of sending immediately\n analyticsBatcher.addClick(contentData)\n } catch (error) {\n console.debug('Click tracking failed:', error)\n }\n}\n\nexport async function trackComponentEmbedLoad(\n analytics: ComponentEmbedAnalytics\n): Promise<void> {\n try {\n // Check if this component has already been tracked\n if (hasBeenTracked(analytics.componentHash)) {\n console.debug(\n 'Component embed already tracked, skipping:',\n analytics.componentHash\n )\n return\n }\n\n // Mark as tracked before sending to prevent race conditions\n markAsTracked(analytics.componentHash)\n\n // Add to batch instead of sending immediately\n analyticsBatcher.addComponentEmbedLoad(analytics)\n } catch (error) {\n console.debug('Component analytics tracking failed:', error)\n }\n}\n\nexport async function trackComponentClick(\n contentData: ComponentContentData\n): Promise<void> {\n try {\n analyticsBatcher.addComponentClick(contentData)\n } catch (error) {\n console.debug('Component click tracking failed:', error)\n }\n}\n\nexport function shouldTrackAnalytics(element: HTMLElement): boolean {\n const trackAnalytics = element.getAttribute('track-analytics')\n return trackAnalytics !== 'false'\n}\n","export function generateContentHash(content: string): string {\n // Simple hash function for content identification\n let hash = 0\n const cleanContent = content.trim().substring(0, 200)\n\n for (let i = 0; i < cleanContent.length; i++) {\n const char = cleanContent.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n\n return Math.abs(hash).toString(36).substring(0, 12)\n}\n\n/**\n * Generate a hash for a component by concatenating sorted element content.\n * Used for component-level deduplication and analytics.\n */\nexport function generateComponentHash(\n elements: Array<{ elementType: string; content: string }>\n): string {\n const sorted = [...elements].sort((a, b) => {\n const typeCompare = a.elementType.localeCompare(b.elementType)\n if (typeCompare !== 0) return typeCompare\n return a.content.localeCompare(b.content)\n })\n\n const combined = sorted.map((e) => `${e.elementType}:${e.content}`).join('|')\n return generateContentHash(combined)\n}\n","import type { ComponentValue, ElementValue } from '@skhema/types'\nimport { getComponentTypeLabel } from './component-validation.js'\nimport { generateContentHash } from './hash.js'\nimport { getElementTypeLabel } from './validation.js'\n\nexport function generateStructuredData(\n content: string,\n elementType: ElementValue,\n contributorId: string,\n sourceUrl: string\n): object {\n return {\n '@context': 'https://schema.org',\n '@type': 'AnalysisContent',\n text: content,\n analysisType: elementType,\n category: getElementTypeLabel(elementType),\n contributor: contributorId,\n url: generateRedirectUrl(content, elementType, contributorId),\n provider: {\n '@type': 'Organization',\n name: 'Skhema',\n url: 'https://skhema.com',\n },\n isPartOf: {\n '@type': 'WebPage',\n url: sourceUrl,\n },\n dateCreated: new Date().toISOString(),\n platform: 'Skhema',\n }\n}\n\nexport function generateRedirectUrl(\n content: string,\n elementType: ElementValue,\n contributorId: string,\n options: {\n baseUrl?: string\n utmSource?: string\n utmMedium?: string\n utmCampaign?: string\n } = {}\n): string {\n const baseUrl = options.baseUrl || 'https://app.skhema.com/save' // This page will handle the authentication and content saving\n const contentHash = generateContentHash(content)\n const sourceUrl = encodeURIComponent(window.location.href)\n const timestamp = Date.now()\n\n const params = new URLSearchParams({\n source: sourceUrl,\n t: timestamp.toString(),\n utm_source: options.utmSource || 'web_component',\n utm_medium: options.utmMedium || 'embedded',\n utm_campaign: options.utmCampaign || elementType,\n utm_content: contributorId,\n })\n\n return `${baseUrl}?type=contributor&contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}&${params.toString()}`\n // return `${baseUrl}/contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}?${params.toString()}`;\n}\n\nexport function createMetaTags(\n content: string,\n elementType: ElementValue,\n contributorId: string\n): string {\n const label = getElementTypeLabel(elementType)\n\n return `\n <div itemscope itemtype=\"https://schema.org/AnalysisContent\" style=\"display:none;\">\n <meta itemprop=\"analysisType\" content=\"${elementType}\">\n <meta itemprop=\"text\" content=\"${content}\">\n <meta itemprop=\"contributor\" content=\"${contributorId}\">\n <meta itemprop=\"category\" content=\"${label}\">\n <meta itemprop=\"platform\" content=\"Skhema\">\n </div>\n `\n}\n\nexport function generateComponentStructuredData(\n title: string,\n componentType: ComponentValue,\n contributorId: string,\n elements: Array<{ elementType: string; content: string }>,\n sourceUrl: string\n): object {\n const componentLabel = getComponentTypeLabel(componentType)\n\n return {\n '@context': 'https://schema.org',\n '@type': 'CreativeWork',\n name: title,\n description: `${componentLabel} strategy component`,\n category: componentLabel,\n contributor: contributorId,\n url: generateComponentRedirectUrl(\n generateContentHash(elements.map((e) => e.content).join('|')),\n componentType,\n contributorId\n ),\n hasPart: elements.map((el) => ({\n '@type': 'AnalysisContent',\n text: el.content,\n analysisType: el.elementType,\n category: getElementTypeLabel(el.elementType as ElementValue),\n })),\n provider: {\n '@type': 'Organization',\n name: 'Skhema',\n url: 'https://skhema.com',\n },\n isPartOf: {\n '@type': 'WebPage',\n url: sourceUrl,\n },\n dateCreated: new Date().toISOString(),\n platform: 'Skhema',\n }\n}\n\nexport function generateComponentRedirectUrl(\n componentHash: string,\n componentType: ComponentValue,\n contributorId: string,\n options: {\n baseUrl?: string\n utmSource?: string\n utmMedium?: string\n utmCampaign?: string\n } = {}\n): string {\n const baseUrl = options.baseUrl || 'https://app.skhema.com/save'\n const sourceUrl = encodeURIComponent(window.location.href)\n const timestamp = Date.now()\n\n const params = new URLSearchParams({\n source: sourceUrl,\n t: timestamp.toString(),\n utm_source: options.utmSource || 'web_component',\n utm_medium: options.utmMedium || 'embedded',\n utm_campaign: options.utmCampaign || componentType,\n utm_content: contributorId,\n })\n\n return `${baseUrl}?type=component&component_type=${componentType}&component_hash=${componentHash}&contributor_id=${contributorId}&${params.toString()}`\n}\n\nexport function createAriaAttributes(\n elementType: ElementValue\n): Record<string, string> {\n const label = getElementTypeLabel(elementType)\n\n return {\n role: 'article',\n 'aria-label': `${label} - Strategic element`,\n 'aria-describedby': 'skhema-description',\n }\n}\n","import type { ComponentValue, ElementValue } from '@skhema/types'\nimport { renderComponentCardHtml } from '../render/index.js'\nimport {\n CARD_SHADOW_LG,\n PRIMARY_HOVER_HEX,\n PRIMARY_PRESSED_HEX,\n} from '../styles/design-tokens.js'\nimport {\n shouldTrackAnalytics,\n trackComponentClick,\n trackComponentEmbedLoad,\n} from '../utils/analytics.js'\nimport {\n getComponentTypeLabel,\n getElementTypesForComponent,\n isValidComponentType,\n validateElementBelongsToComponent,\n} from '../utils/component-validation.js'\nimport { generateComponentHash } from '../utils/hash.js'\nimport {\n generateComponentRedirectUrl,\n generateComponentStructuredData,\n} from '../utils/seo.js'\nimport type { SkhemaElement } from './SkhemaElement.js'\nimport type {\n ComponentContentData,\n ComponentEmbedAnalytics,\n NestedElementData,\n SkhemaComponentAttributes,\n SkhemaComponentEventMap,\n} from './types.js'\n\n// Browser-only styles. The card STRUCTURE + base colours come from the shared,\n// email-safe `@skhema/embed/render` output (inline hex). This block carries the\n// progressive enhancements (hover/transition over `.skhema-card`) plus the\n// shadow-DOM-only skeleton + error states (unchanged CSS-var styling).\nconst styles = `\n:host {\n --skhema-primary: hsl(344 57% 54%);\n --skhema-primary-hover: hsl(344 50% 47%);\n --skhema-secondary: hsl(345 100% 75%);\n\n /* Light mode colors */\n --skhema-bg: hsl(0 0% 100%);\n --skhema-card: hsl(0 0% 100%);\n --skhema-border: hsl(214.3 31.8% 91.4%);\n --skhema-text: hsl(222.2 84% 4.9%);\n --skhema-text-muted: hsl(215.4 16.3% 46.9%);\n --skhema-accent: hsl(210 40% 96%);\n --skhema-surface-subtle: hsl(210 40% 97%);\n\n /* Shadows */\n --skhema-shadow: 0 1px 3px 0 hsl(0 0 0 / 0.1), 0 1px 2px -1px hsl(0 0 0 / 0.1);\n --skhema-shadow-md: 0 4px 6px -1px hsl(0 0 0 / 0.1), 0 2px 4px -2px hsl(0 0 0 / 0.1);\n --skhema-shadow-lg: 0 10px 15px -3px hsl(0 0 0 / 0.1), 0 4px 6px -4px hsl(0 0 0 / 0.1);\n --skhema-radius: 0.1rem;\n\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Inter', sans-serif;\n line-height: 1.5;\n color: var(--skhema-text);\n}\n\n/* Dark mode (skeleton/error only) */\n.skhema-component-card[data-theme=\"dark\"],\n.skhema-skeleton[data-theme=\"dark\"] {\n --skhema-bg: hsl(222.2 84% 4.9%);\n --skhema-card: hsl(222.2 84% 4.9%);\n --skhema-border: hsl(217.2 32.6% 17.5%);\n --skhema-text: hsl(210 40% 98%);\n --skhema-text-muted: hsl(215 20.2% 65.1%);\n --skhema-accent: hsl(217.2 32.6% 17.5%);\n --skhema-surface-subtle: hsl(217.2 32.6% 12%);\n}\n\n/* Progressive enhancement over the inline-styled, rendered card. Inline styles\n win on specificity, so the changed properties use !important to layer on. */\n.skhema-card {\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1), transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.skhema-card:hover {\n box-shadow: ${CARD_SHADOW_LG} !important;\n transform: translateY(-1px);\n}\n\n.skhema-save-btn {\n transition: background 0.15s ease;\n}\n\n.skhema-save-btn:hover {\n background: ${PRIMARY_HOVER_HEX} !important;\n}\n\n.skhema-save-btn:active {\n background: ${PRIMARY_PRESSED_HEX} !important;\n}\n\n/* Error card wrapper (browser-only state) */\n.skhema-component-card {\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n box-shadow: var(--skhema-shadow);\n max-width: 600px;\n margin: 8px 0;\n overflow: hidden;\n}\n\n/* Error state */\n.skhema-error {\n background: hsl(0 93% 94%);\n border: 1px solid hsl(0 84% 60%);\n color: hsl(0 74% 42%);\n padding: 12px;\n border-radius: calc(var(--skhema-radius) + 2px);\n font-size: 13px;\n}\n\n.skhema-error-title {\n font-weight: 600;\n margin-bottom: 8px;\n}\n\n.skhema-error-list {\n margin: 0;\n padding-left: 16px;\n}\n\n/* Skeleton loading state */\n.skhema-skeleton {\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n padding: 16px;\n box-shadow: var(--skhema-shadow);\n max-width: 600px;\n margin: 8px 0;\n animation: skeletonPulse 1.5s ease-in-out infinite;\n}\n\n.skhema-skeleton-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.skhema-skeleton-badge {\n width: 32px;\n height: 20px;\n border-radius: 2px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skhema-skeleton-text {\n flex: 1;\n}\n\n.skhema-skeleton-line {\n height: 12px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: calc(var(--skhema-radius) + 2px);\n margin: 6px 0;\n}\n\n.skhema-skeleton-line.short { width: 40%; }\n.skhema-skeleton-line.medium { width: 70%; }\n\n.skhema-skeleton-content {\n margin: 16px 0;\n}\n\n@keyframes skeletonPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.8; }\n}\n\n@keyframes shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n}\n\n/* Accessibility */\n@media (prefers-reduced-motion: reduce) {\n .skhema-card,\n .skhema-save-btn {\n transition: none;\n }\n}\n\n.skhema-structured-data {\n display: none !important;\n}\n`\n\nexport class SkhemaComponent extends HTMLElement {\n private shadow: ShadowRoot\n private contentData: ComponentContentData | null = null\n private componentConnected = false\n private hasTrackedLoad = false\n private pendingRender: number | null = null\n private themeObserver: MutationObserver | null = null\n private mediaQueryListener: MediaQueryList | null = null\n\n constructor() {\n super()\n this.shadow = this.attachShadow({ mode: 'closed' })\n this.renderSkeleton()\n }\n\n static get observedAttributes(): (keyof SkhemaComponentAttributes)[] {\n return [\n 'component-type',\n 'contributor-id',\n 'author-name',\n 'author-slug',\n 'contributor-name',\n 'title',\n 'theme',\n 'track-analytics',\n 'source-url',\n ]\n }\n\n connectedCallback() {\n if (this.componentConnected) return\n this.componentConnected = true\n\n try {\n this.addPreconnectHints()\n\n // Listen for child element ready events (fired by children that upgrade after us)\n this.addEventListener('skhema:element-ready', () => {\n this.scheduleRender()\n })\n\n // Children may have already upgraded and dispatched skhema:element-ready\n // before our listener was set up (registration order: skhema-element first).\n // Wait for any pending custom element upgrades, then render.\n if (typeof customElements.whenDefined === 'function') {\n customElements.whenDefined('skhema-element').then(() => {\n this.scheduleRender()\n })\n } else {\n this.scheduleRender()\n }\n\n this.setupThemeListeners()\n } catch (error) {\n this.renderError('Failed to initialize component', error)\n }\n }\n\n disconnectedCallback() {\n this.cleanupThemeListeners()\n if (this.pendingRender !== null) {\n cancelAnimationFrame(this.pendingRender)\n this.pendingRender = null\n }\n }\n\n attributeChangedCallback(\n _name: keyof SkhemaComponentAttributes,\n oldValue: string | null,\n newValue: string | null\n ) {\n if (oldValue !== newValue && this.componentConnected) {\n this.scheduleRender()\n }\n }\n\n private scheduleRender() {\n if (this.pendingRender !== null) {\n cancelAnimationFrame(this.pendingRender)\n }\n this.pendingRender = requestAnimationFrame(() => {\n this.pendingRender = null\n this.render()\n })\n }\n\n private render() {\n const validation = this.validateComponentAttributes()\n\n if (!validation.isValid) {\n this.renderError('Invalid component attributes', validation.errors)\n return\n }\n\n const componentType = validation.componentType!\n const contributorId = validation.contributorId!\n const title = this.getAttribute('title') || ''\n\n // Gather child element data\n const childElements = this.gatherChildElements(componentType)\n\n if (childElements.length === 0) {\n this.renderError('Component requires child elements', [\n 'Add <skhema-element> children inside this component',\n ])\n return\n }\n\n const componentHash = generateComponentHash(\n childElements.map((el) => ({\n elementType: el.elementType,\n content: el.content,\n }))\n )\n\n this.contentData = {\n contributor_id: contributorId,\n component_type: componentType,\n component_hash: componentHash,\n title,\n elements: childElements.map((el) => ({\n element_type: el.elementType,\n content: el.content,\n content_hash: el.contentHash,\n })),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n this.renderContent(childElements)\n this.addStructuredData()\n this.trackLoad()\n }\n\n private validateComponentAttributes(): {\n isValid: boolean\n errors: string[]\n componentType?: ComponentValue\n contributorId?: string\n } {\n const errors: string[] = []\n const componentType = this.getAttribute('component-type')\n const contributorId = this.getAttribute('contributor-id')\n\n if (!componentType) {\n errors.push('Missing required attribute: component-type')\n } else if (!isValidComponentType(componentType)) {\n errors.push(`Invalid component-type \"${componentType}\"`)\n }\n\n if (!contributorId) {\n errors.push('Missing required attribute: contributor-id')\n } else if (contributorId.trim().length === 0) {\n errors.push('contributor-id cannot be empty')\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n componentType: isValidComponentType(componentType || '')\n ? (componentType as ComponentValue)\n : undefined,\n contributorId: contributorId || undefined,\n }\n }\n\n private gatherChildElements(\n componentType: ComponentValue\n ): NestedElementData[] {\n const children = Array.from(\n this.querySelectorAll('skhema-element')\n ) as SkhemaElement[]\n\n const elements: NestedElementData[] = []\n\n for (const child of children) {\n const data = child.getElementData?.()\n if (!data) continue\n\n // Validate element belongs to this component type\n if (!validateElementBelongsToComponent(data.elementType, componentType)) {\n console.warn(\n `skhema-component: element type \"${data.elementType}\" does not belong to component type \"${componentType}\"`\n )\n // Warn but don't block — still include the element\n }\n\n elements.push(data)\n }\n\n // Sort by elementFlow order for the component type\n const orderedTypes = getElementTypesForComponent(componentType)\n\n elements.sort((a, b) => {\n const aIdx = orderedTypes.indexOf(a.elementType as ElementValue)\n const bIdx = orderedTypes.indexOf(b.elementType as ElementValue)\n // Unknown types go to the end\n const aOrder = aIdx === -1 ? orderedTypes.length : aIdx\n const bOrder = bIdx === -1 ? orderedTypes.length : bIdx\n return aOrder - bOrder\n })\n\n return elements\n }\n\n private renderContent(elements: NestedElementData[]) {\n if (!this.contentData) return\n\n const { component_type, contributor_id, title } = this.contentData\n const componentLabel = getComponentTypeLabel(component_type)\n\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n const redirectUrl = generateComponentRedirectUrl(\n this.contentData.component_hash,\n component_type,\n contributor_id\n )\n\n // Set ARIA attributes\n this.setAttribute('role', 'article')\n this.setAttribute(\n 'aria-label',\n `${componentLabel} component${title ? ` — ${title}` : ''}`\n )\n\n // Card structure + base styling come from the shared, email-safe renderer\n // (single source of truth). The renderer groups elements by type; the\n // browser-only `<style>` layers hover / transitions on top.\n const cardHtml = renderComponentCardHtml({\n componentType: component_type,\n title,\n elements: elements.map((el) => ({\n elementType: el.elementType,\n content: el.content,\n })),\n saveUrl: redirectUrl,\n authorName:\n this.getAttribute('author-name') ||\n this.getAttribute('contributor-name'),\n authorSlug: this.getAttribute('author-slug'),\n contributorId: contributor_id,\n theme: actualTheme,\n })\n\n this.shadow.innerHTML = `<style>${styles}</style>${cardHtml}<slot style=\"display:none;\"></slot>`\n\n // Add click listener\n const saveBtn = this.shadow.querySelector(\n '.skhema-save-btn'\n ) as HTMLAnchorElement\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event)\n })\n }\n }\n\n private getActualTheme(themeAttribute: string): 'light' | 'dark' {\n if (themeAttribute === 'light' || themeAttribute === 'dark') {\n return themeAttribute\n }\n\n const htmlElement = document.documentElement\n const bodyElement = document.body\n\n const htmlTheme =\n htmlElement.getAttribute('data-theme') ||\n htmlElement.getAttribute('theme') ||\n htmlElement.className.match(/theme-(\\w+)/)?.[1]\n\n const bodyTheme =\n bodyElement.getAttribute('data-theme') ||\n bodyElement.getAttribute('theme') ||\n bodyElement.className.match(/theme-(\\w+)/)?.[1]\n\n const hasDarkClass =\n htmlElement.classList.contains('dark') ||\n bodyElement.classList.contains('dark') ||\n htmlElement.classList.contains('dark-mode') ||\n bodyElement.classList.contains('dark-mode')\n\n if (hasDarkClass || htmlTheme === 'dark' || bodyTheme === 'dark') {\n return 'dark'\n }\n\n const computedStyles = window.getComputedStyle(htmlElement)\n const colorScheme = computedStyles.getPropertyValue('color-scheme')\n if (colorScheme && colorScheme.includes('dark')) {\n return 'dark'\n }\n\n if (\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ) {\n return 'dark'\n }\n\n return 'light'\n }\n\n private addPreconnectHints() {\n if (\n document.querySelector(\n 'link[rel=\"preconnect\"][href*=\"analytics.skhema.com\"]'\n )\n ) {\n return\n }\n\n try {\n const preconnectApi = document.createElement('link')\n preconnectApi.rel = 'preconnect'\n preconnectApi.href = 'https://analytics.skhema.com'\n document.head.appendChild(preconnectApi)\n\n const dnsPrefetch = document.createElement('link')\n dnsPrefetch.rel = 'dns-prefetch'\n dnsPrefetch.href = 'https://skhema.com'\n document.head.appendChild(dnsPrefetch)\n } catch (error) {\n console.debug('Failed to add preconnect hints:', error)\n }\n }\n\n private renderSkeleton() {\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-skeleton\" data-theme=\"${actualTheme}\">\n <div class=\"skhema-skeleton-header\">\n <div class=\"skhema-skeleton-badge\"></div>\n <div class=\"skhema-skeleton-text\">\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n <div class=\"skhema-skeleton-content\">\n <div class=\"skhema-skeleton-line short\"></div>\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line short\"></div>\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n\n <slot style=\"display:none;\"></slot>\n `\n }\n\n private renderError(title: string, errors: string | string[] | unknown) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)]\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-component-card\">\n <div class=\"skhema-error\">\n <div class=\"skhema-error-title\">Skhema Component Error: ${title}</div>\n <ul class=\"skhema-error-list\">\n ${errorList.map((error) => `<li>${error}</li>`).join('')}\n </ul>\n </div>\n </div>\n\n <slot style=\"display:none;\"></slot>\n `\n\n this.dispatchEvent(\n new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true,\n })\n )\n }\n\n private addStructuredData() {\n if (!this.contentData) return\n\n const { component_type, contributor_id, title, elements, source_url } =\n this.contentData\n\n const structuredData = generateComponentStructuredData(\n title,\n component_type,\n contributor_id,\n elements.map((el) => ({\n elementType: el.element_type,\n content: el.content,\n })),\n source_url\n )\n\n const script = document.createElement('script')\n script.type = 'application/ld+json'\n script.textContent = JSON.stringify(structuredData)\n script.className = 'skhema-structured-data'\n document.head.appendChild(script)\n }\n\n private async trackLoad() {\n if (\n !shouldTrackAnalytics(this as HTMLElement) ||\n !this.contentData ||\n this.hasTrackedLoad\n ) {\n return\n }\n\n this.hasTrackedLoad = true\n\n const analytics: ComponentEmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n componentType: this.contentData.component_type,\n componentHash: this.contentData.component_hash,\n title: this.contentData.title,\n elements: this.contentData.elements.map((el) => ({\n elementType: el.element_type,\n content: el.content,\n contentHash: el.content_hash,\n })),\n pageUrl: window.location.href,\n pageTitle: document.title,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n }\n\n await trackComponentEmbedLoad(analytics)\n\n this.dispatchEvent(\n new CustomEvent('skhema:component-load', {\n detail: analytics,\n bubbles: true,\n })\n )\n }\n\n private async handleSaveClick(_event: Event) {\n if (!this.contentData) return\n\n if (shouldTrackAnalytics(this as HTMLElement)) {\n await trackComponentClick(this.contentData)\n }\n\n this.dispatchEvent(\n new CustomEvent('skhema:component-click', {\n detail: this.contentData,\n bubbles: true,\n })\n )\n }\n\n // Public API\n public getContentData(): ComponentContentData | null {\n return this.contentData\n }\n\n public refresh(): void {\n this.render()\n }\n\n private setupThemeListeners(): void {\n const themeAttribute = this.getAttribute('theme')\n if (themeAttribute === 'auto' || !themeAttribute) {\n if (window.matchMedia) {\n this.mediaQueryListener = window.matchMedia(\n '(prefers-color-scheme: dark)'\n )\n const handleThemeChange = () => this.updateTheme()\n this.mediaQueryListener.addEventListener('change', handleThemeChange)\n }\n\n this.themeObserver = new MutationObserver(() => this.updateTheme())\n\n this.themeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n\n this.themeObserver.observe(document.body, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n }\n }\n\n private cleanupThemeListeners(): void {\n if (this.themeObserver) {\n this.themeObserver.disconnect()\n this.themeObserver = null\n }\n if (this.mediaQueryListener) {\n this.mediaQueryListener = null\n }\n }\n\n private updateTheme(): void {\n // Theme is baked into the rendered card's inline hex, so re-render rather\n // than flip an attribute.\n const themeAttribute = this.getAttribute('theme') || 'auto'\n if (themeAttribute === 'auto' && this.contentData) {\n this.scheduleRender()\n }\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface HTMLElementEventMap extends SkhemaComponentEventMap {}\n\n interface SkhemaComponentJSX extends Partial<SkhemaComponentAttributes> {\n [key: string]: unknown\n }\n\n interface JSXIntrinsicElements {\n 'skhema-component': SkhemaComponentJSX\n }\n}\n","import { renderElementCardHtml } from '../render/index.js'\nimport {\n CARD_SHADOW_LG,\n PRIMARY_HEX,\n PRIMARY_HOVER_HEX,\n PRIMARY_PRESSED_HEX,\n} from '../styles/design-tokens.js'\nimport {\n shouldTrackAnalytics,\n trackClick,\n trackEmbedLoad,\n} from '../utils/analytics.js'\nimport { generateContentHash } from '../utils/hash.js'\nimport { validateContentSecurity } from '../utils/sanitization.js'\nimport {\n createAriaAttributes,\n createMetaTags,\n generateRedirectUrl,\n generateStructuredData,\n} from '../utils/seo.js'\nimport { validateAttributes } from '../utils/validation.js'\nimport type {\n ContentData,\n EmbedAnalytics,\n NestedElementData,\n SkhemaElementAttributes,\n SkhemaElementEventMap,\n} from './types.js'\n\n// Browser-only styles. The card STRUCTURE + base colours now come from the\n// shared, email-safe `@skhema/embed/render` output (inline hex), so this block\n// only carries: (1) the progressive enhancements email/CLI can't have — hover\n// + transitions over the rendered `.skhema-card` — and (2) the shadow-DOM-only\n// skeleton + error states (which keep the original CSS-var styling verbatim).\nconst styles = `\n:host {\n /* Skhema Brand Colors - matching UI library */\n --skhema-primary: hsl(344 57% 54%); /* #cd476a */\n --skhema-primary-hover: hsl(344 50% 47%); /* #b53d5e */\n --skhema-primary-pressed: hsl(343 50% 41%); /* #9d3552 */\n --skhema-secondary: hsl(345 100% 75%); /* #ff82a2 */\n\n /* Light mode colors */\n --skhema-bg: hsl(0 0% 100%);\n --skhema-card: hsl(0 0% 100%);\n --skhema-border: hsl(214.3 31.8% 91.4%);\n --skhema-text: hsl(222.2 84% 4.9%);\n --skhema-text-muted: hsl(215.4 16.3% 46.9%);\n --skhema-accent: hsl(210 40% 96%);\n\n /* Shadows matching UI library */\n --skhema-shadow: 0 1px 3px 0 hsl(0 0 0 / 0.1), 0 1px 2px -1px hsl(0 0 0 / 0.1);\n --skhema-shadow-md: 0 4px 6px -1px hsl(0 0 0 / 0.1), 0 2px 4px -2px hsl(0 0 0 / 0.1);\n --skhema-shadow-lg: 0 10px 15px -3px hsl(0 0 0 / 0.1), 0 4px 6px -4px hsl(0 0 0 / 0.1);\n --skhema-radius: 0.1rem;\n\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Inter', sans-serif;\n line-height: 1.5;\n color: var(--skhema-text);\n}\n\n/* Dark mode styles - applied via data-theme attribute (skeleton/error only) */\n.skhema-element-card[data-theme=\"dark\"],\n.skhema-skeleton[data-theme=\"dark\"] {\n --skhema-bg: hsl(222.2 84% 4.9%);\n --skhema-card: hsl(222.2 84% 4.9%);\n --skhema-border: hsl(217.2 32.6% 17.5%);\n --skhema-text: hsl(210 40% 98%);\n --skhema-text-muted: hsl(215 20.2% 65.1%);\n --skhema-accent: hsl(217.2 32.6% 17.5%);\n}\n\n/* Progressive enhancement over the inline-styled, rendered card. Inline styles\n win on specificity, so the changed properties use !important to layer on. */\n.skhema-card {\n transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1), transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.skhema-card:hover {\n box-shadow: ${CARD_SHADOW_LG} !important;\n transform: translateY(-1px);\n}\n\n.skhema-card[data-skhema-kind=\"element\"]:hover {\n border-color: ${PRIMARY_HEX} !important;\n}\n\n.skhema-save-btn {\n transition: background 0.15s ease;\n}\n\n.skhema-save-btn:hover {\n background: ${PRIMARY_HOVER_HEX} !important;\n}\n\n.skhema-save-btn:active {\n background: ${PRIMARY_PRESSED_HEX} !important;\n}\n\n/* Error card wrapper (browser-only state) */\n.skhema-element-card {\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n box-shadow: var(--skhema-shadow);\n max-width: 600px;\n margin: 8px 0;\n overflow: hidden;\n}\n\n/* Error state */\n.skhema-error {\n background: hsl(0 93% 94%);\n border: 1px solid hsl(0 84% 60%);\n color: hsl(0 74% 42%);\n padding: 12px;\n border-radius: calc(var(--skhema-radius) + 2px);\n font-size: 13px;\n}\n\n.skhema-error-title {\n font-weight: 600;\n margin-bottom: 8px;\n}\n\n.skhema-error-list {\n margin: 0;\n padding-left: 16px;\n}\n\n/* Skeleton loading state */\n.skhema-skeleton {\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) + 2px);\n padding: 16px;\n box-shadow: var(--skhema-shadow);\n max-width: 600px;\n margin: 8px 0;\n animation: skeletonPulse 1.5s ease-in-out infinite;\n}\n\n.skhema-skeleton-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.skhema-skeleton-badge {\n width: 32px;\n height: 20px;\n border-radius: 2px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skhema-skeleton-text {\n flex: 1;\n}\n\n.skhema-skeleton-line {\n height: 12px;\n background: linear-gradient(90deg,\n var(--skhema-border) 25%,\n var(--skhema-accent) 50%,\n var(--skhema-border) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: calc(var(--skhema-radius) + 2px);\n margin: 6px 0;\n}\n\n.skhema-skeleton-line.short {\n width: 40%;\n}\n\n.skhema-skeleton-line.medium {\n width: 70%;\n}\n\n.skhema-skeleton-content {\n margin: 16px 0;\n}\n\n@keyframes skeletonPulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.8;\n }\n}\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n/* Accessibility */\n@media (prefers-reduced-motion: reduce) {\n .skhema-card,\n .skhema-save-btn {\n transition: none;\n }\n}\n\n.skhema-structured-data {\n display: none !important;\n}\n`\n\nexport class SkhemaElement extends HTMLElement {\n private shadow: ShadowRoot\n private contentData: ContentData | null = null\n private componentConnected = false\n private hasTrackedLoad = false\n private nestedMode = false\n private themeObserver: MutationObserver | null = null\n private mediaQueryListener: MediaQueryList | null = null\n\n constructor() {\n super()\n this.shadow = this.attachShadow({ mode: 'closed' })\n // Show skeleton immediately while component initializes\n this.renderSkeleton()\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return [\n 'element-type',\n 'contributor-id',\n 'author-name',\n 'author-slug',\n 'contributor-name',\n 'content',\n 'source-url',\n 'theme',\n 'track-analytics',\n ]\n }\n\n connectedCallback() {\n if (this.componentConnected) return\n this.componentConnected = true\n\n // Check if nested inside a <skhema-component>\n if (this.closest('skhema-component')) {\n this.nestedMode = true\n\n // Validate and parse content\n const validation = validateAttributes(this as HTMLElement)\n if (!validation.isValid) {\n console.warn(\n 'skhema-element: invalid attributes in nested mode',\n validation.errors\n )\n return\n }\n\n const content = this.getContent()\n if (!content.trim()) {\n console.warn('skhema-element: empty content in nested mode')\n return\n }\n\n this.contentData = {\n contributor_id: validation.contributorId!,\n element_type: validation.elementType!,\n content: content,\n content_hash: generateContentHash(content),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n // Clear shadow DOM — parent component handles rendering\n this.shadow.innerHTML = ''\n\n // Dispatch ready event so parent component can discover us\n this.dispatchEvent(\n new CustomEvent('skhema:element-ready', {\n bubbles: true,\n composed: true,\n detail: this.getElementData(),\n })\n )\n return\n }\n\n try {\n // Add preconnect hints for faster analytics loading\n this.addPreconnectHints()\n\n // Use requestAnimationFrame for smoother render\n requestAnimationFrame(() => {\n this.render()\n this.trackLoad()\n this.setupThemeListeners()\n })\n } catch (error) {\n this.renderError('Failed to initialize component', error)\n }\n }\n\n disconnectedCallback() {\n this.cleanupThemeListeners()\n }\n\n attributeChangedCallback(\n _name: keyof SkhemaElementAttributes,\n oldValue: string | null,\n newValue: string | null\n ) {\n if (oldValue !== newValue && this.componentConnected && !this.nestedMode) {\n this.render()\n }\n }\n\n /**\n * Returns element data for parent <skhema-component> consumption.\n */\n public getElementData(): NestedElementData | null {\n if (!this.contentData) return null\n return {\n elementType: this.contentData.element_type,\n content: this.contentData.content,\n contentHash: this.contentData.content_hash,\n }\n }\n\n private render() {\n const validation = validateAttributes(this as HTMLElement)\n\n if (!validation.isValid) {\n this.renderError('Invalid component attributes', validation.errors)\n return\n }\n\n const content = this.getContent()\n if (!content.trim()) {\n this.renderError('Component requires content', [\n 'Add content between the opening and closing tags, or use the content attribute',\n ])\n return\n }\n\n // Validate content security\n const securityValidation = validateContentSecurity(content)\n if (!securityValidation.isSecure) {\n this.renderError(\n 'Content security validation failed',\n securityValidation.issues\n )\n return\n }\n\n this.contentData = {\n contributor_id: validation.contributorId!,\n element_type: validation.elementType!,\n content: content,\n content_hash: generateContentHash(content),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n this.renderContent()\n this.addStructuredData()\n }\n\n private getContent(): string {\n return this.getAttribute('content') || this.textContent || ''\n }\n\n private renderContent() {\n if (!this.contentData) return\n\n const { element_type, contributor_id, content } = this.contentData\n const redirectUrl = generateRedirectUrl(\n content,\n element_type,\n contributor_id\n )\n\n // Determine the actual theme to use\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n // Set ARIA attributes on host element\n const ariaAttrs = createAriaAttributes(element_type)\n Object.entries(ariaAttrs).forEach(([key, value]) => {\n this.setAttribute(key, value)\n })\n\n // Card structure + base styling come from the shared, email-safe renderer\n // (single source of truth). The browser-only `<style>` layers hover /\n // transitions on top.\n const cardHtml = renderElementCardHtml({\n elementType: element_type,\n content,\n saveUrl: redirectUrl,\n authorName:\n this.getAttribute('author-name') ||\n this.getAttribute('contributor-name'),\n authorSlug: this.getAttribute('author-slug'),\n contributorId: contributor_id,\n theme: actualTheme,\n })\n\n this.shadow.innerHTML = `<style>${styles}</style>${cardHtml}`\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector(\n '.skhema-save-btn'\n ) as HTMLAnchorElement\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event)\n })\n }\n }\n\n private getActualTheme(themeAttribute: string): 'light' | 'dark' {\n if (themeAttribute === 'light' || themeAttribute === 'dark') {\n return themeAttribute\n }\n\n // Auto mode - detect from system/page\n // First check if the page has set a data-theme or theme attribute\n const htmlElement = document.documentElement\n const bodyElement = document.body\n\n // Check common theme attributes on html or body\n const htmlTheme =\n htmlElement.getAttribute('data-theme') ||\n htmlElement.getAttribute('theme') ||\n htmlElement.className.match(/theme-(\\w+)/)?.[1]\n\n const bodyTheme =\n bodyElement.getAttribute('data-theme') ||\n bodyElement.getAttribute('theme') ||\n bodyElement.className.match(/theme-(\\w+)/)?.[1]\n\n // Check for dark mode classes\n const hasDarkClass =\n htmlElement.classList.contains('dark') ||\n bodyElement.classList.contains('dark') ||\n htmlElement.classList.contains('dark-mode') ||\n bodyElement.classList.contains('dark-mode')\n\n if (hasDarkClass || htmlTheme === 'dark' || bodyTheme === 'dark') {\n return 'dark'\n }\n\n // Check CSS custom properties that might indicate theme\n const computedStyles = window.getComputedStyle(htmlElement)\n const colorScheme = computedStyles.getPropertyValue('color-scheme')\n if (colorScheme && colorScheme.includes('dark')) {\n return 'dark'\n }\n\n // Check system preference\n if (\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ) {\n return 'dark'\n }\n\n // Default to light\n return 'light'\n }\n\n private addPreconnectHints() {\n // Only add preconnect hints once per page\n if (\n document.querySelector(\n 'link[rel=\"preconnect\"][href*=\"analytics.skhema.com\"]'\n )\n ) {\n return\n }\n\n try {\n // Preconnect to analytics API\n const preconnectApi = document.createElement('link')\n preconnectApi.rel = 'preconnect'\n preconnectApi.href = 'https://analytics.skhema.com'\n document.head.appendChild(preconnectApi)\n\n // DNS prefetch for main domain\n const dnsPrefetch = document.createElement('link')\n dnsPrefetch.rel = 'dns-prefetch'\n dnsPrefetch.href = 'https://skhema.com'\n document.head.appendChild(dnsPrefetch)\n } catch (error) {\n console.debug('Failed to add preconnect hints:', error)\n }\n }\n\n private renderSkeleton() {\n // Determine theme for skeleton\n const themeAttribute = this.getAttribute('theme') || 'auto'\n const actualTheme = this.getActualTheme(themeAttribute)\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-skeleton\" data-theme=\"${actualTheme}\">\n <div class=\"skhema-skeleton-header\">\n <div class=\"skhema-skeleton-badge\"></div>\n <div class=\"skhema-skeleton-text\">\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n <div class=\"skhema-skeleton-content\">\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line\"></div>\n <div class=\"skhema-skeleton-line medium\"></div>\n </div>\n </div>\n `\n }\n\n private renderError(title: string, errors: string | string[] | unknown) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)]\n\n this.shadow.innerHTML = `\n <style>${styles}</style>\n\n <div class=\"skhema-element-card\">\n <div class=\"skhema-error\">\n <div class=\"skhema-error-title\">Skhema Component Error: ${title}</div>\n <ul class=\"skhema-error-list\">\n ${errorList.map((error) => `<li>${error}</li>`).join('')}\n </ul>\n </div>\n </div>\n `\n\n // Dispatch error event\n this.dispatchEvent(\n new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true,\n })\n )\n }\n\n private addStructuredData() {\n if (!this.contentData) return\n\n const { content, element_type, contributor_id, source_url } =\n this.contentData\n\n // Add structured data to the document head\n const structuredData = generateStructuredData(\n content,\n element_type,\n contributor_id,\n source_url\n )\n const script = document.createElement('script')\n script.type = 'application/ld+json'\n script.textContent = JSON.stringify(structuredData)\n script.className = 'skhema-structured-data'\n document.head.appendChild(script)\n\n // Add meta tags for SEO\n const metaDiv = document.createElement('div')\n metaDiv.innerHTML = createMetaTags(content, element_type, contributor_id)\n metaDiv.className = 'skhema-structured-data'\n document.body.appendChild(metaDiv)\n }\n\n private async trackLoad() {\n if (\n !shouldTrackAnalytics(this as HTMLElement) ||\n !this.contentData ||\n this.hasTrackedLoad\n ) {\n return\n }\n\n this.hasTrackedLoad = true\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\n content: this.contentData.content,\n pageUrl: window.location.href,\n pageTitle: document.title,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n }\n\n await trackEmbedLoad(analytics)\n\n // Dispatch load event\n this.dispatchEvent(\n new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true,\n })\n )\n }\n\n private async handleSaveClick(_event: Event) {\n if (!this.contentData) return\n\n // Track click analytics\n if (shouldTrackAnalytics(this as HTMLElement)) {\n await trackClick(this.contentData)\n }\n\n // Dispatch click event\n this.dispatchEvent(\n new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true,\n })\n )\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData\n }\n\n public refresh(): void {\n if (!this.nestedMode) {\n this.render()\n }\n }\n\n private setupThemeListeners(): void {\n // Only set up listeners if theme is 'auto' or not specified\n const themeAttribute = this.getAttribute('theme')\n if (themeAttribute === 'auto' || !themeAttribute) {\n // Listen for system theme changes\n if (window.matchMedia) {\n this.mediaQueryListener = window.matchMedia(\n '(prefers-color-scheme: dark)'\n )\n const handleThemeChange = () => this.updateTheme()\n this.mediaQueryListener.addEventListener('change', handleThemeChange)\n }\n\n // Listen for theme changes on html/body elements\n this.themeObserver = new MutationObserver(() => this.updateTheme())\n\n // Observe both html and body for attribute changes\n this.themeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n\n this.themeObserver.observe(document.body, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme'],\n })\n }\n }\n\n private cleanupThemeListeners(): void {\n if (this.themeObserver) {\n this.themeObserver.disconnect()\n this.themeObserver = null\n }\n\n if (this.mediaQueryListener) {\n // Note: We can't remove the specific listener without storing the reference\n // but setting to null will allow garbage collection\n this.mediaQueryListener = null\n }\n }\n\n private updateTheme(): void {\n // Only update if component is using auto theme. Theme is now baked into the\n // rendered card's inline hex, so re-render rather than flip an attribute.\n const themeAttribute = this.getAttribute('theme') || 'auto'\n if (themeAttribute === 'auto' && this.contentData && !this.nestedMode) {\n this.renderContent()\n }\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n\n interface SkhemaElementJSX extends Partial<SkhemaElementAttributes> {\n [key: string]: unknown\n }\n\n // Module augmentation for JSX without using namespace\n interface JSXIntrinsicElements {\n 'skhema-element': SkhemaElementJSX\n }\n}\n","import { SkhemaComponent } from './components/SkhemaComponent.js'\nimport { SkhemaElement } from './components/SkhemaElement.js'\n\n// Export component classes\nexport { SkhemaComponent, SkhemaElement }\n\n// Export types for TypeScript users\nexport type {\n ComponentContentData,\n ComponentEmbedAnalytics,\n ContentData,\n EmbedAnalytics,\n NestedElementData,\n SkhemaComponentAttributes,\n SkhemaComponentEventMap,\n SkhemaElementAttributes,\n SkhemaElementEventMap,\n} from './components/types.js'\n\n// Export element utilities\nexport {\n getElementTypeAcronym,\n getElementTypeLabel,\n isValidElementType,\n validateAttributes,\n} from './utils/validation.js'\n\n// Export component utilities\nexport {\n getComponentTypeAcronym,\n getComponentTypeLabel,\n isValidComponentType,\n resolveComponentType,\n validateElementBelongsToComponent,\n} from './utils/component-validation.js'\n\n// Export hash utilities\nexport { generateComponentHash } from './utils/hash.js'\n\n// Export analytics utilities\nexport {\n shouldTrackAnalytics,\n trackComponentClick,\n trackComponentEmbedLoad,\n} from './utils/analytics.js'\n\n// Export SEO utilities\nexport {\n generateComponentRedirectUrl,\n generateComponentStructuredData,\n generateRedirectUrl,\n generateStructuredData,\n} from './utils/seo.js'\n\n// Manual registration functions\nexport function registerSkhemaElement() {\n if (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define(\n 'skhema-element',\n SkhemaElement as CustomElementConstructor\n )\n }\n}\n\nexport function registerSkhemaComponent() {\n if (\n typeof window !== 'undefined' &&\n !customElements.get('skhema-component')\n ) {\n customElements.define(\n 'skhema-component',\n SkhemaComponent as CustomElementConstructor\n )\n }\n}\n\n// Auto-register in browser environments (can be tree-shaken if not needed)\nif (typeof window !== 'undefined') {\n if (!customElements.get('skhema-element')) {\n customElements.define(\n 'skhema-element',\n SkhemaElement as CustomElementConstructor\n )\n }\n if (!customElements.get('skhema-component')) {\n customElements.define(\n 'skhema-component',\n SkhemaComponent as CustomElementConstructor\n )\n }\n}\n\n// Default export for convenience\nexport default SkhemaElement\n"],"names":["getElementTypeLabel","getComponentTypeLabel","styles","CARD_SHADOW_LG","PRIMARY_HOVER_HEX","PRIMARY_PRESSED_HEX","validation","isValidComponentType","validateElementBelongsToComponent","getElementTypesForComponent","renderComponentCardHtml","PRIMARY_HEX","validateAttributes","validateContentSecurity","renderElementCardHtml"],"mappings":"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"}