@skhema/web-component 0.0.9 → 0.0.11
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.
- package/dist/components/SkhemaElement.d.ts.map +1 -1
- package/dist/index.cjs +16 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +16 -17
- package/dist/index.es.js.map +1 -1
- package/dist/utils/analytics.d.ts +0 -1
- package/dist/utils/analytics.d.ts.map +1 -1
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/seo.d.ts.map +1 -1
- package/dist/web-component.min.js +1 -1
- package/dist/web-component.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SkhemaElement.d.ts","sourceRoot":"","sources":["../../src/components/SkhemaElement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAkB,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"SkhemaElement.d.ts","sourceRoot":"","sources":["../../src/components/SkhemaElement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAkB,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AA+T9G,qBAAa,aAAc,SAAQ,WAAW;IAC5C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,kBAAkB,CAAS;;IAOnC,MAAM,KAAK,kBAAkB,IAAI,CAAC,MAAM,uBAAuB,CAAC,EAAE,CAEjE;IAED,iBAAiB;IAYjB,wBAAwB,CAAC,KAAK,EAAE,MAAM,uBAAuB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAM/G,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,aAAa;IAiErB,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,iBAAiB;YAoBX,SAAS;YAsBT,eAAe;IAgBtB,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC,OAAO,IAAI,IAAI;CAGvB;AAGD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,mBAAoB,SAAQ,qBAAqB;KAAG;IAE9D,UAAU,GAAG,CAAC;QACZ,UAAU,iBAAiB;YACzB,gBAAgB,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG;gBACnD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;aACpB,CAAC;SACH;KACF;CACF"}
|
package/dist/index.cjs
CHANGED
|
@@ -35,16 +35,6 @@ function getElementTypeAcronym(elementType) {
|
|
|
35
35
|
const type = Object.values(types.ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
36
36
|
return (type == null ? void 0 : type.acronym) || elementType.substring(0, 2).toUpperCase();
|
|
37
37
|
}
|
|
38
|
-
function generateContentHash$1(content) {
|
|
39
|
-
let hash = 0;
|
|
40
|
-
const cleanContent = content.trim().substring(0, 200);
|
|
41
|
-
for (let i = 0; i < cleanContent.length; i++) {
|
|
42
|
-
const char = cleanContent.charCodeAt(i);
|
|
43
|
-
hash = (hash << 5) - hash + char;
|
|
44
|
-
hash = hash & hash;
|
|
45
|
-
}
|
|
46
|
-
return Math.abs(hash).toString(36).substring(0, 12);
|
|
47
|
-
}
|
|
48
38
|
async function trackEmbedLoad(analytics) {
|
|
49
39
|
try {
|
|
50
40
|
const data = new URLSearchParams({
|
|
@@ -80,9 +70,12 @@ async function trackClick(contentData) {
|
|
|
80
70
|
timestamp: contentData.timestamp
|
|
81
71
|
};
|
|
82
72
|
if (navigator.sendBeacon) {
|
|
73
|
+
const blob = new Blob([JSON.stringify(data)], {
|
|
74
|
+
type: "application/json"
|
|
75
|
+
});
|
|
83
76
|
navigator.sendBeacon(
|
|
84
77
|
"https://api.skhema.com/api:XGdoUqHx/component/click",
|
|
85
|
-
|
|
78
|
+
blob
|
|
86
79
|
);
|
|
87
80
|
} else {
|
|
88
81
|
fetch("https://api.skhema.com/api:XGdoUqHx/component/click", {
|
|
@@ -101,6 +94,16 @@ function shouldTrackAnalytics(element) {
|
|
|
101
94
|
const trackAnalytics = element.getAttribute("track-analytics");
|
|
102
95
|
return trackAnalytics !== "false";
|
|
103
96
|
}
|
|
97
|
+
function generateContentHash(content) {
|
|
98
|
+
let hash = 0;
|
|
99
|
+
const cleanContent = content.trim().substring(0, 200);
|
|
100
|
+
for (let i = 0; i < cleanContent.length; i++) {
|
|
101
|
+
const char = cleanContent.charCodeAt(i);
|
|
102
|
+
hash = (hash << 5) - hash + char;
|
|
103
|
+
hash = hash & hash;
|
|
104
|
+
}
|
|
105
|
+
return Math.abs(hash).toString(36).substring(0, 12);
|
|
106
|
+
}
|
|
104
107
|
function generateStructuredData(content, elementType, contributorId, sourceUrl) {
|
|
105
108
|
return {
|
|
106
109
|
"@context": "https://schema.org",
|
|
@@ -124,7 +127,7 @@ function generateStructuredData(content, elementType, contributorId, sourceUrl)
|
|
|
124
127
|
};
|
|
125
128
|
}
|
|
126
129
|
function generateRedirectUrl(content, elementType, contributorId, options = {}) {
|
|
127
|
-
const baseUrl = options.baseUrl || "https://
|
|
130
|
+
const baseUrl = options.baseUrl || "https://app.skhema.com/save";
|
|
128
131
|
const contentHash = generateContentHash(content);
|
|
129
132
|
const sourceUrl = encodeURIComponent(window.location.href);
|
|
130
133
|
const timestamp = Date.now();
|
|
@@ -138,9 +141,6 @@ function generateRedirectUrl(content, elementType, contributorId, options = {})
|
|
|
138
141
|
});
|
|
139
142
|
return `${baseUrl}?contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}&${params.toString()}`;
|
|
140
143
|
}
|
|
141
|
-
function generateContentHash(content) {
|
|
142
|
-
return btoa(content.substring(0, 50)).replace(/[^a-zA-Z0-9]/g, "").substring(0, 12);
|
|
143
|
-
}
|
|
144
144
|
function createMetaTags(content, elementType, contributorId) {
|
|
145
145
|
const label = getElementTypeLabel(elementType);
|
|
146
146
|
return `
|
|
@@ -512,7 +512,7 @@ class SkhemaElement extends HTMLElement {
|
|
|
512
512
|
contributor_id: validation.contributorId,
|
|
513
513
|
element_type: validation.elementType,
|
|
514
514
|
content,
|
|
515
|
-
content_hash: generateContentHash
|
|
515
|
+
content_hash: generateContentHash(content),
|
|
516
516
|
source_url: this.getAttribute("source-url") || window.location.href,
|
|
517
517
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
518
518
|
page_title: document.title
|
|
@@ -663,7 +663,6 @@ if (typeof window !== "undefined" && !customElements.get("skhema-element")) {
|
|
|
663
663
|
}
|
|
664
664
|
exports.SkhemaElement = SkhemaElement;
|
|
665
665
|
exports.default = SkhemaElement;
|
|
666
|
-
exports.generateContentHash = generateContentHash$1;
|
|
667
666
|
exports.generateRedirectUrl = generateRedirectUrl;
|
|
668
667
|
exports.generateStructuredData = generateStructuredData;
|
|
669
668
|
exports.getElementTypeAcronym = getElementTypeAcronym;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/utils/validation.ts","../src/utils/analytics.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["import { ELEMENT_TYPES } from '@skhema/types';\nimport type { ElementValue } from '@skhema/types';\n\nexport function isValidElementType(elementType: string): 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).map(t => t.value).join(', ');\n errors.push(`Invalid element-type \"${elementType}\". Valid types: ${validTypes}`);\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 || '') ? elementType as ElementValue : 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}","import type { EmbedAnalytics, ContentData } from '../components/types.js';\n\nexport 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\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n const data = new URLSearchParams({\n contributor_id: analytics.contributorId,\n element_type: analytics.elementType,\n content_hash: analytics.contentHash,\n page_url: analytics.pageUrl,\n page_title: analytics.pageTitle || '',\n timestamp: analytics.timestamp.toString(),\n user_agent: analytics.userAgent || ''\n });\n\n // Use beacon for reliability\n if (navigator.sendBeacon) {\n navigator.sendBeacon('https://api.skhema.com/api:XGdoUqHx/component/embed', data);\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n keepalive: true\n }).catch(() => {\n // Fail silently - analytics shouldn't break the component\n });\n }\n } catch (error) {\n // Fail silently\n console.debug('Analytics tracking failed:', error);\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n const data = {\n contributor_id: contentData.contributor_id,\n element_type: contentData.element_type,\n content_hash: contentData.content_hash,\n source_url: contentData.source_url,\n timestamp: contentData.timestamp\n };\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n 'https://api.skhema.com/api:XGdoUqHx/component/click',\n JSON.stringify(data)\n );\n } else {\n fetch('https://api.skhema.com/api:XGdoUqHx/component/click', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n keepalive: true\n }).catch(() => {\n // Fail silently\n });\n }\n } catch (error) {\n console.debug('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}","import type { ElementValue } from '@skhema/types';\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://api.skhema.com/api:XGdoUqHx/component/redirect'; // @TODO: change to actual redirect URL\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 \n return `${baseUrl}?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\nfunction generateContentHash(content: string): string {\n // Simple hash for URL generation\n return btoa(content.substring(0, 50))\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 12);\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 createAriaAttributes(elementType: ElementValue): Record<string, string> {\n const label = getElementTypeLabel(elementType);\n \n return {\n 'role': 'article',\n 'aria-label': `${label} - Strategic insight`,\n 'aria-describedby': 'skhema-description'\n };\n}","import type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './types.js';\nimport { validateAttributes, getElementTypeLabel } from '../utils/validation.js';\nimport { generateContentHash, trackEmbedLoad, trackClick, shouldTrackAnalytics } from '../utils/analytics.js';\nimport { generateStructuredData, generateRedirectUrl, createMetaTags, createAriaAttributes } from '../utils/seo.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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'closed' });\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return ['element-type', 'contributor-id', 'content', 'source-url', 'theme', 'track-analytics'];\n }\n\n connectedCallback() {\n if (this.componentConnected) return;\n this.componentConnected = true;\n \n try {\n this.render();\n this.trackLoad();\n } catch (error) {\n this.renderError('Failed to initialize component', error);\n }\n }\n\n attributeChangedCallback(_name: keyof SkhemaElementAttributes, oldValue: string | null, newValue: string | null) {\n if (oldValue !== newValue && this.componentConnected) {\n this.render();\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', ['Add content between the opening and closing tags, or use the content attribute']);\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(content, element_type, contributor_id);\n const theme = this.getAttribute('theme') || 'auto';\n\n // Generate contributor display name and initials\n const displayName = this.formatContributorName(contributor_id);\n const initials = this.getInitials(displayName);\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 this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-card\" data-theme=\"${theme}\">\n <div class=\"skhema-header\">\n <div class=\"skhema-contributor\">\n <div class=\"skhema-avatar\" title=\"${displayName}\">\n ${initials}\n </div>\n <div class=\"skhema-contributor-info\">\n <div class=\"skhema-contributor-name\">${displayName}</div>\n <div class=\"skhema-contributor-role\">Strategy Insight</div>\n </div>\n </div>\n <div class=\"skhema-element-badge\" title=\"${label}\">\n ${label}\n </div>\n </div>\n \n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${content}</div>\n </div>\n \n <div class=\"skhema-footer\">\n <div class=\"skhema-attribution\">\n Powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n <a href=\"${redirectUrl}\" \n class=\"skhema-save-btn\" \n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this insight to Skhema\">\n Save to Skhema\n </a>\n </div>\n </div>\n `;\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector('.skhema-save-btn') as HTMLAnchorElement;\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event);\n });\n }\n }\n\n private formatContributorName(contributorId: string): string {\n // Convert contributor_id to display name\n return contributorId\n .split(/[_-]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n private getInitials(name: string): string {\n return name\n .split(' ')\n .map(word => word.charAt(0))\n .join('')\n .toUpperCase()\n .substring(0, 2);\n }\n\n private renderError(title: string, errors: string | string[] | any) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)];\n \n this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-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(new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true\n }));\n }\n\n private addStructuredData() {\n if (!this.contentData) return;\n\n const { content, element_type, contributor_id, source_url } = this.contentData;\n \n // Add structured data to the document head\n const structuredData = generateStructuredData(content, element_type, contributor_id, source_url);\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 (!shouldTrackAnalytics(this as HTMLElement) || !this.contentData) return;\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\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(new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true\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(new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true\n }));\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData;\n }\n\n public refresh(): void {\n this.render();\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n \n namespace JSX {\n interface IntrinsicElements {\n 'skhema-element': Partial<SkhemaElementAttributes> & {\n [key: string]: any;\n };\n }\n }\n}","import { SkhemaElement } from './components/SkhemaElement.js';\n\n// Export the component class\nexport { SkhemaElement };\n\n// Export types for TypeScript users\nexport type {\n SkhemaElementAttributes,\n EmbedAnalytics,\n ContentData,\n SkhemaElementEventMap\n} from './components/types.js';\n\n// Export utilities\nexport {\n isValidElementType,\n validateAttributes,\n getElementTypeLabel,\n getElementTypeAcronym\n} from './utils/validation.js';\n\nexport {\n generateContentHash,\n shouldTrackAnalytics\n} from './utils/analytics.js';\n\nexport {\n generateStructuredData,\n generateRedirectUrl\n} from './utils/seo.js';\n\n// Manual registration function for consuming applications\nexport function registerSkhemaElement() {\n if (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n }\n}\n\n// Auto-register in browser environments (can be tree-shaken if not needed)\nif (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n}\n\n// Default export for convenience\nexport default SkhemaElement;"],"names":["ELEMENT_TYPES","generateContentHash"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/utils/validation.ts","../src/utils/analytics.ts","../src/utils/hash.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["import { ELEMENT_TYPES } from '@skhema/types';\nimport type { ElementValue } from '@skhema/types';\n\nexport function isValidElementType(elementType: string): 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).map(t => t.value).join(', ');\n errors.push(`Invalid element-type \"${elementType}\". Valid types: ${validTypes}`);\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 || '') ? elementType as ElementValue : 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}","import type { EmbedAnalytics, ContentData } from '../components/types.js';\n\n\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n const data = new URLSearchParams({\n contributor_id: analytics.contributorId,\n element_type: analytics.elementType,\n content_hash: analytics.contentHash,\n page_url: analytics.pageUrl,\n page_title: analytics.pageTitle || '',\n timestamp: analytics.timestamp.toString(),\n user_agent: analytics.userAgent || ''\n });\n\n // Use beacon for reliability\n if (navigator.sendBeacon) {\n navigator.sendBeacon('https://api.skhema.com/api:XGdoUqHx/component/embed', data);\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n keepalive: true\n }).catch(() => {\n // Fail silently - analytics shouldn't break the component\n });\n }\n } catch (error) {\n // Fail silently\n console.debug('Analytics tracking failed:', error);\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n const data = {\n contributor_id: contentData.contributor_id,\n element_type: contentData.element_type,\n content_hash: contentData.content_hash,\n source_url: contentData.source_url,\n timestamp: contentData.timestamp\n };\n\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(data)], {\n type: 'application/json'\n });\n navigator.sendBeacon(\n 'https://api.skhema.com/api:XGdoUqHx/component/click',\n blob\n );\n } else {\n fetch('https://api.skhema.com/api:XGdoUqHx/component/click', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n keepalive: true\n }).catch(() => {\n // Fail silently\n });\n }\n } catch (error) {\n console.debug('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}","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}","import type { ElementValue } from '@skhema/types';\nimport { getElementTypeLabel } from './validation.js';\nimport { generateContentHash } from './hash.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 \n return `${baseUrl}?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\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 createAriaAttributes(elementType: ElementValue): Record<string, string> {\n const label = getElementTypeLabel(elementType);\n \n return {\n 'role': 'article',\n 'aria-label': `${label} - Strategic insight`,\n 'aria-describedby': 'skhema-description'\n };\n}","import type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './types.js';\nimport { validateAttributes, getElementTypeLabel } from '../utils/validation.js';\nimport { trackEmbedLoad, trackClick, shouldTrackAnalytics } from '../utils/analytics.js';\nimport { generateContentHash } from '../utils/hash.js';\nimport { generateStructuredData, generateRedirectUrl, createMetaTags, createAriaAttributes } from '../utils/seo.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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'closed' });\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return ['element-type', 'contributor-id', 'content', 'source-url', 'theme', 'track-analytics'];\n }\n\n connectedCallback() {\n if (this.componentConnected) return;\n this.componentConnected = true;\n \n try {\n this.render();\n this.trackLoad();\n } catch (error) {\n this.renderError('Failed to initialize component', error);\n }\n }\n\n attributeChangedCallback(_name: keyof SkhemaElementAttributes, oldValue: string | null, newValue: string | null) {\n if (oldValue !== newValue && this.componentConnected) {\n this.render();\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', ['Add content between the opening and closing tags, or use the content attribute']);\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(content, element_type, contributor_id);\n const theme = this.getAttribute('theme') || 'auto';\n\n // Generate contributor display name and initials\n const displayName = this.formatContributorName(contributor_id);\n const initials = this.getInitials(displayName);\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 this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-card\" data-theme=\"${theme}\">\n <div class=\"skhema-header\">\n <div class=\"skhema-contributor\">\n <div class=\"skhema-avatar\" title=\"${displayName}\">\n ${initials}\n </div>\n <div class=\"skhema-contributor-info\">\n <div class=\"skhema-contributor-name\">${displayName}</div>\n <div class=\"skhema-contributor-role\">Strategy Insight</div>\n </div>\n </div>\n <div class=\"skhema-element-badge\" title=\"${label}\">\n ${label}\n </div>\n </div>\n \n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${content}</div>\n </div>\n \n <div class=\"skhema-footer\">\n <div class=\"skhema-attribution\">\n Powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n <a href=\"${redirectUrl}\" \n class=\"skhema-save-btn\" \n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this insight to Skhema\">\n Save to Skhema\n </a>\n </div>\n </div>\n `;\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector('.skhema-save-btn') as HTMLAnchorElement;\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event);\n });\n }\n }\n\n private formatContributorName(contributorId: string): string {\n // Convert contributor_id to display name\n return contributorId\n .split(/[_-]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n private getInitials(name: string): string {\n return name\n .split(' ')\n .map(word => word.charAt(0))\n .join('')\n .toUpperCase()\n .substring(0, 2);\n }\n\n private renderError(title: string, errors: string | string[] | any) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)];\n \n this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-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(new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true\n }));\n }\n\n private addStructuredData() {\n if (!this.contentData) return;\n\n const { content, element_type, contributor_id, source_url } = this.contentData;\n \n // Add structured data to the document head\n const structuredData = generateStructuredData(content, element_type, contributor_id, source_url);\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 (!shouldTrackAnalytics(this as HTMLElement) || !this.contentData) return;\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\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(new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true\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(new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true\n }));\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData;\n }\n\n public refresh(): void {\n this.render();\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n \n namespace JSX {\n interface IntrinsicElements {\n 'skhema-element': Partial<SkhemaElementAttributes> & {\n [key: string]: any;\n };\n }\n }\n}","import { SkhemaElement } from './components/SkhemaElement.js';\n\n// Export the component class\nexport { SkhemaElement };\n\n// Export types for TypeScript users\nexport type {\n SkhemaElementAttributes,\n EmbedAnalytics,\n ContentData,\n SkhemaElementEventMap\n} from './components/types.js';\n\n// Export utilities\nexport {\n isValidElementType,\n validateAttributes,\n getElementTypeLabel,\n getElementTypeAcronym\n} from './utils/validation.js';\n\nexport {\n // Removed generateContentHash\n shouldTrackAnalytics\n} from './utils/analytics.js';\n\nexport {\n generateStructuredData,\n generateRedirectUrl\n} from './utils/seo.js';\n\n// Manual registration function for consuming applications\nexport function registerSkhemaElement() {\n if (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n }\n}\n\n// Auto-register in browser environments (can be tree-shaken if not needed)\nif (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n}\n\n// Default export for convenience\nexport default SkhemaElement;"],"names":["ELEMENT_TYPES"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { SkhemaElement } from './components/SkhemaElement.js';
|
|
|
3
3
|
export { SkhemaElement };
|
|
4
4
|
export type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './components/types.js';
|
|
5
5
|
export { isValidElementType, validateAttributes, getElementTypeLabel, getElementTypeAcronym } from './utils/validation.js';
|
|
6
|
-
export {
|
|
6
|
+
export { shouldTrackAnalytics } from './utils/analytics.js';
|
|
7
7
|
export { generateStructuredData, generateRedirectUrl } from './utils/seo.js';
|
|
8
8
|
export declare function registerSkhemaElement(): void;
|
|
9
9
|
export default SkhemaElement;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,CAAC;AAGzB,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,WAAW,EACX,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,CAAC;AAGzB,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,WAAW,EACX,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEL,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAGxB,wBAAgB,qBAAqB,SAIpC;AAQD,eAAe,aAAa,CAAC"}
|
package/dist/index.es.js
CHANGED
|
@@ -33,16 +33,6 @@ function getElementTypeAcronym(elementType) {
|
|
|
33
33
|
const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
34
34
|
return (type == null ? void 0 : type.acronym) || elementType.substring(0, 2).toUpperCase();
|
|
35
35
|
}
|
|
36
|
-
function generateContentHash$1(content) {
|
|
37
|
-
let hash = 0;
|
|
38
|
-
const cleanContent = content.trim().substring(0, 200);
|
|
39
|
-
for (let i = 0; i < cleanContent.length; i++) {
|
|
40
|
-
const char = cleanContent.charCodeAt(i);
|
|
41
|
-
hash = (hash << 5) - hash + char;
|
|
42
|
-
hash = hash & hash;
|
|
43
|
-
}
|
|
44
|
-
return Math.abs(hash).toString(36).substring(0, 12);
|
|
45
|
-
}
|
|
46
36
|
async function trackEmbedLoad(analytics) {
|
|
47
37
|
try {
|
|
48
38
|
const data = new URLSearchParams({
|
|
@@ -78,9 +68,12 @@ async function trackClick(contentData) {
|
|
|
78
68
|
timestamp: contentData.timestamp
|
|
79
69
|
};
|
|
80
70
|
if (navigator.sendBeacon) {
|
|
71
|
+
const blob = new Blob([JSON.stringify(data)], {
|
|
72
|
+
type: "application/json"
|
|
73
|
+
});
|
|
81
74
|
navigator.sendBeacon(
|
|
82
75
|
"https://api.skhema.com/api:XGdoUqHx/component/click",
|
|
83
|
-
|
|
76
|
+
blob
|
|
84
77
|
);
|
|
85
78
|
} else {
|
|
86
79
|
fetch("https://api.skhema.com/api:XGdoUqHx/component/click", {
|
|
@@ -99,6 +92,16 @@ function shouldTrackAnalytics(element) {
|
|
|
99
92
|
const trackAnalytics = element.getAttribute("track-analytics");
|
|
100
93
|
return trackAnalytics !== "false";
|
|
101
94
|
}
|
|
95
|
+
function generateContentHash(content) {
|
|
96
|
+
let hash = 0;
|
|
97
|
+
const cleanContent = content.trim().substring(0, 200);
|
|
98
|
+
for (let i = 0; i < cleanContent.length; i++) {
|
|
99
|
+
const char = cleanContent.charCodeAt(i);
|
|
100
|
+
hash = (hash << 5) - hash + char;
|
|
101
|
+
hash = hash & hash;
|
|
102
|
+
}
|
|
103
|
+
return Math.abs(hash).toString(36).substring(0, 12);
|
|
104
|
+
}
|
|
102
105
|
function generateStructuredData(content, elementType, contributorId, sourceUrl) {
|
|
103
106
|
return {
|
|
104
107
|
"@context": "https://schema.org",
|
|
@@ -122,7 +125,7 @@ function generateStructuredData(content, elementType, contributorId, sourceUrl)
|
|
|
122
125
|
};
|
|
123
126
|
}
|
|
124
127
|
function generateRedirectUrl(content, elementType, contributorId, options = {}) {
|
|
125
|
-
const baseUrl = options.baseUrl || "https://
|
|
128
|
+
const baseUrl = options.baseUrl || "https://app.skhema.com/save";
|
|
126
129
|
const contentHash = generateContentHash(content);
|
|
127
130
|
const sourceUrl = encodeURIComponent(window.location.href);
|
|
128
131
|
const timestamp = Date.now();
|
|
@@ -136,9 +139,6 @@ function generateRedirectUrl(content, elementType, contributorId, options = {})
|
|
|
136
139
|
});
|
|
137
140
|
return `${baseUrl}?contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}&${params.toString()}`;
|
|
138
141
|
}
|
|
139
|
-
function generateContentHash(content) {
|
|
140
|
-
return btoa(content.substring(0, 50)).replace(/[^a-zA-Z0-9]/g, "").substring(0, 12);
|
|
141
|
-
}
|
|
142
142
|
function createMetaTags(content, elementType, contributorId) {
|
|
143
143
|
const label = getElementTypeLabel(elementType);
|
|
144
144
|
return `
|
|
@@ -510,7 +510,7 @@ class SkhemaElement extends HTMLElement {
|
|
|
510
510
|
contributor_id: validation.contributorId,
|
|
511
511
|
element_type: validation.elementType,
|
|
512
512
|
content,
|
|
513
|
-
content_hash: generateContentHash
|
|
513
|
+
content_hash: generateContentHash(content),
|
|
514
514
|
source_url: this.getAttribute("source-url") || window.location.href,
|
|
515
515
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
516
516
|
page_title: document.title
|
|
@@ -662,7 +662,6 @@ if (typeof window !== "undefined" && !customElements.get("skhema-element")) {
|
|
|
662
662
|
export {
|
|
663
663
|
SkhemaElement,
|
|
664
664
|
SkhemaElement as default,
|
|
665
|
-
generateContentHash$1 as generateContentHash,
|
|
666
665
|
generateRedirectUrl,
|
|
667
666
|
generateStructuredData,
|
|
668
667
|
getElementTypeAcronym,
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/utils/validation.ts","../src/utils/analytics.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["import { ELEMENT_TYPES } from '@skhema/types';\nimport type { ElementValue } from '@skhema/types';\n\nexport function isValidElementType(elementType: string): 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).map(t => t.value).join(', ');\n errors.push(`Invalid element-type \"${elementType}\". Valid types: ${validTypes}`);\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 || '') ? elementType as ElementValue : 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}","import type { EmbedAnalytics, ContentData } from '../components/types.js';\n\nexport 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\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n const data = new URLSearchParams({\n contributor_id: analytics.contributorId,\n element_type: analytics.elementType,\n content_hash: analytics.contentHash,\n page_url: analytics.pageUrl,\n page_title: analytics.pageTitle || '',\n timestamp: analytics.timestamp.toString(),\n user_agent: analytics.userAgent || ''\n });\n\n // Use beacon for reliability\n if (navigator.sendBeacon) {\n navigator.sendBeacon('https://api.skhema.com/api:XGdoUqHx/component/embed', data);\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n keepalive: true\n }).catch(() => {\n // Fail silently - analytics shouldn't break the component\n });\n }\n } catch (error) {\n // Fail silently\n console.debug('Analytics tracking failed:', error);\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n const data = {\n contributor_id: contentData.contributor_id,\n element_type: contentData.element_type,\n content_hash: contentData.content_hash,\n source_url: contentData.source_url,\n timestamp: contentData.timestamp\n };\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n 'https://api.skhema.com/api:XGdoUqHx/component/click',\n JSON.stringify(data)\n );\n } else {\n fetch('https://api.skhema.com/api:XGdoUqHx/component/click', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n keepalive: true\n }).catch(() => {\n // Fail silently\n });\n }\n } catch (error) {\n console.debug('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}","import type { ElementValue } from '@skhema/types';\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://api.skhema.com/api:XGdoUqHx/component/redirect'; // @TODO: change to actual redirect URL\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 \n return `${baseUrl}?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\nfunction generateContentHash(content: string): string {\n // Simple hash for URL generation\n return btoa(content.substring(0, 50))\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 12);\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 createAriaAttributes(elementType: ElementValue): Record<string, string> {\n const label = getElementTypeLabel(elementType);\n \n return {\n 'role': 'article',\n 'aria-label': `${label} - Strategic insight`,\n 'aria-describedby': 'skhema-description'\n };\n}","import type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './types.js';\nimport { validateAttributes, getElementTypeLabel } from '../utils/validation.js';\nimport { generateContentHash, trackEmbedLoad, trackClick, shouldTrackAnalytics } from '../utils/analytics.js';\nimport { generateStructuredData, generateRedirectUrl, createMetaTags, createAriaAttributes } from '../utils/seo.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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'closed' });\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return ['element-type', 'contributor-id', 'content', 'source-url', 'theme', 'track-analytics'];\n }\n\n connectedCallback() {\n if (this.componentConnected) return;\n this.componentConnected = true;\n \n try {\n this.render();\n this.trackLoad();\n } catch (error) {\n this.renderError('Failed to initialize component', error);\n }\n }\n\n attributeChangedCallback(_name: keyof SkhemaElementAttributes, oldValue: string | null, newValue: string | null) {\n if (oldValue !== newValue && this.componentConnected) {\n this.render();\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', ['Add content between the opening and closing tags, or use the content attribute']);\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(content, element_type, contributor_id);\n const theme = this.getAttribute('theme') || 'auto';\n\n // Generate contributor display name and initials\n const displayName = this.formatContributorName(contributor_id);\n const initials = this.getInitials(displayName);\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 this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-card\" data-theme=\"${theme}\">\n <div class=\"skhema-header\">\n <div class=\"skhema-contributor\">\n <div class=\"skhema-avatar\" title=\"${displayName}\">\n ${initials}\n </div>\n <div class=\"skhema-contributor-info\">\n <div class=\"skhema-contributor-name\">${displayName}</div>\n <div class=\"skhema-contributor-role\">Strategy Insight</div>\n </div>\n </div>\n <div class=\"skhema-element-badge\" title=\"${label}\">\n ${label}\n </div>\n </div>\n \n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${content}</div>\n </div>\n \n <div class=\"skhema-footer\">\n <div class=\"skhema-attribution\">\n Powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n <a href=\"${redirectUrl}\" \n class=\"skhema-save-btn\" \n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this insight to Skhema\">\n Save to Skhema\n </a>\n </div>\n </div>\n `;\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector('.skhema-save-btn') as HTMLAnchorElement;\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event);\n });\n }\n }\n\n private formatContributorName(contributorId: string): string {\n // Convert contributor_id to display name\n return contributorId\n .split(/[_-]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n private getInitials(name: string): string {\n return name\n .split(' ')\n .map(word => word.charAt(0))\n .join('')\n .toUpperCase()\n .substring(0, 2);\n }\n\n private renderError(title: string, errors: string | string[] | any) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)];\n \n this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-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(new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true\n }));\n }\n\n private addStructuredData() {\n if (!this.contentData) return;\n\n const { content, element_type, contributor_id, source_url } = this.contentData;\n \n // Add structured data to the document head\n const structuredData = generateStructuredData(content, element_type, contributor_id, source_url);\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 (!shouldTrackAnalytics(this as HTMLElement) || !this.contentData) return;\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\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(new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true\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(new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true\n }));\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData;\n }\n\n public refresh(): void {\n this.render();\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n \n namespace JSX {\n interface IntrinsicElements {\n 'skhema-element': Partial<SkhemaElementAttributes> & {\n [key: string]: any;\n };\n }\n }\n}","import { SkhemaElement } from './components/SkhemaElement.js';\n\n// Export the component class\nexport { SkhemaElement };\n\n// Export types for TypeScript users\nexport type {\n SkhemaElementAttributes,\n EmbedAnalytics,\n ContentData,\n SkhemaElementEventMap\n} from './components/types.js';\n\n// Export utilities\nexport {\n isValidElementType,\n validateAttributes,\n getElementTypeLabel,\n getElementTypeAcronym\n} from './utils/validation.js';\n\nexport {\n generateContentHash,\n shouldTrackAnalytics\n} from './utils/analytics.js';\n\nexport {\n generateStructuredData,\n generateRedirectUrl\n} from './utils/seo.js';\n\n// Manual registration function for consuming applications\nexport function registerSkhemaElement() {\n if (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n }\n}\n\n// Auto-register in browser environments (can be tree-shaken if not needed)\nif (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n}\n\n// Default export for convenience\nexport default SkhemaElement;"],"names":["generateContentHash"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/utils/validation.ts","../src/utils/analytics.ts","../src/utils/hash.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["import { ELEMENT_TYPES } from '@skhema/types';\nimport type { ElementValue } from '@skhema/types';\n\nexport function isValidElementType(elementType: string): 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).map(t => t.value).join(', ');\n errors.push(`Invalid element-type \"${elementType}\". Valid types: ${validTypes}`);\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 || '') ? elementType as ElementValue : 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}","import type { EmbedAnalytics, ContentData } from '../components/types.js';\n\n\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n const data = new URLSearchParams({\n contributor_id: analytics.contributorId,\n element_type: analytics.elementType,\n content_hash: analytics.contentHash,\n page_url: analytics.pageUrl,\n page_title: analytics.pageTitle || '',\n timestamp: analytics.timestamp.toString(),\n user_agent: analytics.userAgent || ''\n });\n\n // Use beacon for reliability\n if (navigator.sendBeacon) {\n navigator.sendBeacon('https://api.skhema.com/api:XGdoUqHx/component/embed', data);\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n keepalive: true\n }).catch(() => {\n // Fail silently - analytics shouldn't break the component\n });\n }\n } catch (error) {\n // Fail silently\n console.debug('Analytics tracking failed:', error);\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n const data = {\n contributor_id: contentData.contributor_id,\n element_type: contentData.element_type,\n content_hash: contentData.content_hash,\n source_url: contentData.source_url,\n timestamp: contentData.timestamp\n };\n\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(data)], {\n type: 'application/json'\n });\n navigator.sendBeacon(\n 'https://api.skhema.com/api:XGdoUqHx/component/click',\n blob\n );\n } else {\n fetch('https://api.skhema.com/api:XGdoUqHx/component/click', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n keepalive: true\n }).catch(() => {\n // Fail silently\n });\n }\n } catch (error) {\n console.debug('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}","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}","import type { ElementValue } from '@skhema/types';\nimport { getElementTypeLabel } from './validation.js';\nimport { generateContentHash } from './hash.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 \n return `${baseUrl}?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\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 createAriaAttributes(elementType: ElementValue): Record<string, string> {\n const label = getElementTypeLabel(elementType);\n \n return {\n 'role': 'article',\n 'aria-label': `${label} - Strategic insight`,\n 'aria-describedby': 'skhema-description'\n };\n}","import type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './types.js';\nimport { validateAttributes, getElementTypeLabel } from '../utils/validation.js';\nimport { trackEmbedLoad, trackClick, shouldTrackAnalytics } from '../utils/analytics.js';\nimport { generateContentHash } from '../utils/hash.js';\nimport { generateStructuredData, generateRedirectUrl, createMetaTags, createAriaAttributes } from '../utils/seo.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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'closed' });\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return ['element-type', 'contributor-id', 'content', 'source-url', 'theme', 'track-analytics'];\n }\n\n connectedCallback() {\n if (this.componentConnected) return;\n this.componentConnected = true;\n \n try {\n this.render();\n this.trackLoad();\n } catch (error) {\n this.renderError('Failed to initialize component', error);\n }\n }\n\n attributeChangedCallback(_name: keyof SkhemaElementAttributes, oldValue: string | null, newValue: string | null) {\n if (oldValue !== newValue && this.componentConnected) {\n this.render();\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', ['Add content between the opening and closing tags, or use the content attribute']);\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(content, element_type, contributor_id);\n const theme = this.getAttribute('theme') || 'auto';\n\n // Generate contributor display name and initials\n const displayName = this.formatContributorName(contributor_id);\n const initials = this.getInitials(displayName);\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 this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-card\" data-theme=\"${theme}\">\n <div class=\"skhema-header\">\n <div class=\"skhema-contributor\">\n <div class=\"skhema-avatar\" title=\"${displayName}\">\n ${initials}\n </div>\n <div class=\"skhema-contributor-info\">\n <div class=\"skhema-contributor-name\">${displayName}</div>\n <div class=\"skhema-contributor-role\">Strategy Insight</div>\n </div>\n </div>\n <div class=\"skhema-element-badge\" title=\"${label}\">\n ${label}\n </div>\n </div>\n \n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${content}</div>\n </div>\n \n <div class=\"skhema-footer\">\n <div class=\"skhema-attribution\">\n Powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n <a href=\"${redirectUrl}\" \n class=\"skhema-save-btn\" \n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this insight to Skhema\">\n Save to Skhema\n </a>\n </div>\n </div>\n `;\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector('.skhema-save-btn') as HTMLAnchorElement;\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event);\n });\n }\n }\n\n private formatContributorName(contributorId: string): string {\n // Convert contributor_id to display name\n return contributorId\n .split(/[_-]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n private getInitials(name: string): string {\n return name\n .split(' ')\n .map(word => word.charAt(0))\n .join('')\n .toUpperCase()\n .substring(0, 2);\n }\n\n private renderError(title: string, errors: string | string[] | any) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)];\n \n this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-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(new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true\n }));\n }\n\n private addStructuredData() {\n if (!this.contentData) return;\n\n const { content, element_type, contributor_id, source_url } = this.contentData;\n \n // Add structured data to the document head\n const structuredData = generateStructuredData(content, element_type, contributor_id, source_url);\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 (!shouldTrackAnalytics(this as HTMLElement) || !this.contentData) return;\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\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(new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true\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(new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true\n }));\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData;\n }\n\n public refresh(): void {\n this.render();\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n \n namespace JSX {\n interface IntrinsicElements {\n 'skhema-element': Partial<SkhemaElementAttributes> & {\n [key: string]: any;\n };\n }\n }\n}","import { SkhemaElement } from './components/SkhemaElement.js';\n\n// Export the component class\nexport { SkhemaElement };\n\n// Export types for TypeScript users\nexport type {\n SkhemaElementAttributes,\n EmbedAnalytics,\n ContentData,\n SkhemaElementEventMap\n} from './components/types.js';\n\n// Export utilities\nexport {\n isValidElementType,\n validateAttributes,\n getElementTypeLabel,\n getElementTypeAcronym\n} from './utils/validation.js';\n\nexport {\n // Removed generateContentHash\n shouldTrackAnalytics\n} from './utils/analytics.js';\n\nexport {\n generateStructuredData,\n generateRedirectUrl\n} from './utils/seo.js';\n\n// Manual registration function for consuming applications\nexport function registerSkhemaElement() {\n if (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n }\n}\n\n// Auto-register in browser environments (can be tree-shaken if not needed)\nif (typeof window !== 'undefined' && !customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n}\n\n// Default export for convenience\nexport default SkhemaElement;"],"names":[],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { EmbedAnalytics, ContentData } from '../components/types.js';
|
|
2
2
|
|
|
3
|
-
export declare function generateContentHash(content: string): string;
|
|
4
3
|
export declare function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void>;
|
|
5
4
|
export declare function trackClick(contentData: ContentData): Promise<void>;
|
|
6
5
|
export declare function shouldTrackAnalytics(element: HTMLElement): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1E,wBAAsB,cAAc,CAAC,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B7E;AAED,wBAAsB,UAAU,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BxE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAGlE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAY3D"}
|
package/dist/utils/seo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/utils/seo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/utils/seo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIlD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,YAAY,EACzB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAChB,MAAM,CAqBR;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,YAAY,EACzB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,GACL,MAAM,CAkBR;AAGD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,YAAY,EACzB,aAAa,EAAE,MAAM,GACpB,MAAM,CAYR;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQtF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).SkhemaWebComponent={})}(this,function(n){"use strict";const e={KEY_CHALLENGE:{value:"key_challenge",label:"Key Challenge",acronym:"KC"},SUPPORTING_FACT:{value:"supporting_fact",label:"Supporting Fact",acronym:"SF"},ASSOCIATED_IMPACT:{value:"associated_impact",label:"Associated Impact",acronym:"AI"},GUIDING_POLICY:{value:"guiding_policy",label:"Guiding Policy",acronym:"GP"},COMPETITOR_MOVE:{value:"competitor_move",label:"Competitor Move",acronym:"CM"},SCOPE:{value:"scope",label:"Scope",acronym:"SC"},CONSTRAINT:{value:"constraint",label:"Constraint",acronym:"CN"},SOLUTION_ALTERNATIVE:{value:"solution_alternative",label:"Solution Alternative",acronym:"SA"},ASSUMPTION_HYPOTHESIS:{value:"assumption_hypothesis",label:"Assumption Hypothesis",acronym:"AH"},EXPERIMENT:{value:"experiment",label:"Experiment",acronym:"EX"},ACTION:{value:"action",label:"Action",acronym:"AC"},INVESTMENT:{value:"investment",label:"Investment",acronym:"IN"},ESTIMATE:{value:"estimate",label:"Estimate",acronym:"ES"},BASELINE:{value:"baseline",label:"Baseline",acronym:"BL"},OUTCOME:{value:"outcome",label:"Outcome",acronym:"OC"},PERFORMANCE_VARIABLE:{value:"performance_variable",label:"Performance Variable",acronym:"PV"},CAPABILITY:{value:"capability",label:"Capability",acronym:"CP"},SYSTEM:{value:"system",label:"System",acronym:"SY"},PRINCIPLE:{value:"principle",label:"Principle",acronym:"PR"}};function t(n){return Object.values(e).map(n=>n.value).includes(n)}function a(n){const t=Object.values(e).find(e=>e.value===n);return(null==t?void 0:t.label)||n}function r(n){let e=0;const t=n.trim().substring(0,200);for(let a=0;a<t.length;a++){e=(e<<5)-e+t.charCodeAt(a),e&=e}return Math.abs(e).toString(36).substring(0,12)}function o(n){return"false"!==n.getAttribute("track-analytics")}function i(n,e,t,a={}){const r=a.baseUrl||"https://api.skhema.com/api:XGdoUqHx/component/redirect",o=function(n){return btoa(n.substring(0,50)).replace(/[^a-zA-Z0-9]/g,"").substring(0,12)}(n),i=encodeURIComponent(window.location.href),s=Date.now();return`${r}?contributor_id=${t}&element_type=${e}&content_hash=${o}&${new URLSearchParams({source:i,t:s.toString(),utm_source:a.utmSource||"web_component",utm_medium:a.utmMedium||"embedded",utm_campaign:a.utmCampaign||e,utm_content:t}).toString()}`}const s="\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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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";class c extends HTMLElement{constructor(){super(),this.contentData=null,this.componentConnected=!1,this.shadow=this.attachShadow({mode:"closed"})}static get observedAttributes(){return["element-type","contributor-id","content","source-url","theme","track-analytics"]}connectedCallback(){if(!this.componentConnected){this.componentConnected=!0;try{this.render(),this.trackLoad()}catch(n){this.renderError("Failed to initialize component",n)}}}attributeChangedCallback(n,e,t){e!==t&&this.componentConnected&&this.render()}render(){const n=function(n){const a=[],r=n.getAttribute("element-type"),o=n.getAttribute("contributor-id");if(r){if(!t(r)){const n=Object.values(e).map(n=>n.value).join(", ");a.push(`Invalid element-type "${r}". Valid types: ${n}`)}}else a.push("Missing required attribute: element-type");return o?0===o.trim().length&&a.push("contributor-id cannot be empty"):a.push("Missing required attribute: contributor-id"),{isValid:0===a.length,errors:a,elementType:t(r||"")?r:void 0,contributorId:o||void 0}}(this);if(!n.isValid)return void this.renderError("Invalid component attributes",n.errors);const a=this.getContent();a.trim()?(this.contentData={contributor_id:n.contributorId,element_type:n.elementType,content:a,content_hash:r(a),source_url:this.getAttribute("source-url")||window.location.href,timestamp:(new Date).toISOString(),page_title:document.title},this.renderContent(),this.addStructuredData()):this.renderError("Component requires content",["Add content between the opening and closing tags, or use the content attribute"])}getContent(){return this.getAttribute("content")||this.textContent||""}renderContent(){if(!this.contentData)return;const{element_type:n,contributor_id:e,content:t}=this.contentData,r=a(n),o=i(t,n,e),c=this.getAttribute("theme")||"auto",l=this.formatContributorName(e),m=this.getInitials(l),h={role:"article","aria-label":`${a(n)} - Strategic insight`,"aria-describedby":"skhema-description"};Object.entries(h).forEach(([n,e])=>{this.setAttribute(n,e)}),this.shadow.innerHTML=`\n <style>${s}</style>\n \n <div class="skhema-insight-card" data-theme="${c}">\n <div class="skhema-header">\n <div class="skhema-contributor">\n <div class="skhema-avatar" title="${l}">\n ${m}\n </div>\n <div class="skhema-contributor-info">\n <div class="skhema-contributor-name">${l}</div>\n <div class="skhema-contributor-role">Strategy Insight</div>\n </div>\n </div>\n <div class="skhema-element-badge" title="${r}">\n ${r}\n </div>\n </div>\n \n <div class="skhema-content">\n <div class="skhema-content-text">${t}</div>\n </div>\n \n <div class="skhema-footer">\n <div class="skhema-attribution">\n Powered by <a href="https://skhema.com" target="_blank" rel="noopener noreferrer">Skhema</a>\n </div>\n <a href="${o}" \n class="skhema-save-btn" \n target="_blank"\n rel="noopener noreferrer"\n title="Save this insight to Skhema">\n Save to Skhema\n </a>\n </div>\n </div>\n `;const d=this.shadow.querySelector(".skhema-save-btn");d&&d.addEventListener("click",n=>{this.handleSaveClick(n)})}formatContributorName(n){return n.split(/[_-]/).map(n=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join(" ")}getInitials(n){return n.split(" ").map(n=>n.charAt(0)).join("").toUpperCase().substring(0,2)}renderError(n,e){const t=Array.isArray(e)?e:[String(e)];this.shadow.innerHTML=`\n <style>${s}</style>\n \n <div class="skhema-insight-card">\n <div class="skhema-error">\n <div class="skhema-error-title">Skhema Component Error: ${n}</div>\n <ul class="skhema-error-list">\n ${t.map(n=>`<li>${n}</li>`).join("")}\n </ul>\n </div>\n </div>\n `,this.dispatchEvent(new CustomEvent("skhema:error",{detail:{error:n,details:e},bubbles:!0}))}addStructuredData(){if(!this.contentData)return;const{content:n,element_type:e,contributor_id:t,source_url:r}=this.contentData,o=function(n,e,t,r){return{"@context":"https://schema.org","@type":"AnalysisContent",text:n,analysisType:e,category:a(e),contributor:t,url:i(n,e,t),provider:{"@type":"Organization",name:"Skhema",url:"https://skhema.com"},isPartOf:{"@type":"WebPage",url:r},dateCreated:(new Date).toISOString(),platform:"Skhema"}}(n,e,t,r),s=document.createElement("script");s.type="application/ld+json",s.textContent=JSON.stringify(o),s.className="skhema-structured-data",document.head.appendChild(s);const c=document.createElement("div");c.innerHTML=function(n,e,t){return`\n <div itemscope itemtype="https://schema.org/AnalysisContent" style="display:none;">\n <meta itemprop="analysisType" content="${e}">\n <meta itemprop="text" content="${n}">\n <meta itemprop="contributor" content="${t}">\n <meta itemprop="category" content="${a(e)}">\n <meta itemprop="platform" content="Skhema">\n </div>\n `}(n,e,t),c.className="skhema-structured-data",document.body.appendChild(c)}async trackLoad(){if(!o(this)||!this.contentData)return;const n={contributorId:this.contentData.contributor_id,elementType:this.contentData.element_type,contentHash:this.contentData.content_hash,pageUrl:window.location.href,pageTitle:document.title,timestamp:Date.now(),userAgent:navigator.userAgent};await async function(n){try{const e=new URLSearchParams({contributor_id:n.contributorId,element_type:n.elementType,content_hash:n.contentHash,page_url:n.pageUrl,page_title:n.pageTitle||"",timestamp:n.timestamp.toString(),user_agent:n.userAgent||""});navigator.sendBeacon?navigator.sendBeacon("https://api.skhema.com/api:XGdoUqHx/component/embed",e):fetch("https://api.skhema.com/api:XGdoUqHx/component/embed",{method:"POST",body:e,keepalive:!0}).catch(()=>{})}catch(e){console.debug("Analytics tracking failed:",e)}}(n),this.dispatchEvent(new CustomEvent("skhema:load",{detail:n,bubbles:!0}))}async handleSaveClick(n){this.contentData&&(o(this)&&await async function(n){try{const e={contributor_id:n.contributor_id,element_type:n.element_type,content_hash:n.content_hash,source_url:n.source_url,timestamp:n.timestamp};navigator.sendBeacon?navigator.sendBeacon("https://api.skhema.com/api:XGdoUqHx/component/click",JSON.stringify(e)):fetch("https://api.skhema.com/api:XGdoUqHx/component/click",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0}).catch(()=>{})}catch(e){console.debug("Click tracking failed:",e)}}(this.contentData),this.dispatchEvent(new CustomEvent("skhema:click",{detail:this.contentData,bubbles:!0})))}getContentData(){return this.contentData}refresh(){this.render()}}customElements.get("skhema-element")||customElements.define("skhema-element",c),"undefined"!=typeof window&&(window.SkhemaElement=c),n.SkhemaElement=c,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).SkhemaWebComponent={})}(this,function(n){"use strict";const e={KEY_CHALLENGE:{value:"key_challenge",label:"Key Challenge",acronym:"KC"},SUPPORTING_FACT:{value:"supporting_fact",label:"Supporting Fact",acronym:"SF"},ASSOCIATED_IMPACT:{value:"associated_impact",label:"Associated Impact",acronym:"AI"},GUIDING_POLICY:{value:"guiding_policy",label:"Guiding Policy",acronym:"GP"},COMPETITOR_MOVE:{value:"competitor_move",label:"Competitor Move",acronym:"CM"},SCOPE:{value:"scope",label:"Scope",acronym:"SC"},CONSTRAINT:{value:"constraint",label:"Constraint",acronym:"CN"},SOLUTION_ALTERNATIVE:{value:"solution_alternative",label:"Solution Alternative",acronym:"SA"},ASSUMPTION_HYPOTHESIS:{value:"assumption_hypothesis",label:"Assumption Hypothesis",acronym:"AH"},EXPERIMENT:{value:"experiment",label:"Experiment",acronym:"EX"},ACTION:{value:"action",label:"Action",acronym:"AC"},INVESTMENT:{value:"investment",label:"Investment",acronym:"IN"},ESTIMATE:{value:"estimate",label:"Estimate",acronym:"ES"},BASELINE:{value:"baseline",label:"Baseline",acronym:"BL"},OUTCOME:{value:"outcome",label:"Outcome",acronym:"OC"},PERFORMANCE_VARIABLE:{value:"performance_variable",label:"Performance Variable",acronym:"PV"},CAPABILITY:{value:"capability",label:"Capability",acronym:"CP"},SYSTEM:{value:"system",label:"System",acronym:"SY"},PRINCIPLE:{value:"principle",label:"Principle",acronym:"PR"}};function t(n){return Object.values(e).map(n=>n.value).includes(n)}function a(n){const t=Object.values(e).find(e=>e.value===n);return(null==t?void 0:t.label)||n}function r(n){return"false"!==n.getAttribute("track-analytics")}function o(n){let e=0;const t=n.trim().substring(0,200);for(let a=0;a<t.length;a++){e=(e<<5)-e+t.charCodeAt(a),e&=e}return Math.abs(e).toString(36).substring(0,12)}function i(n,e,t,a={}){const r=a.baseUrl||"https://app.skhema.com/save",i=o(n),s=encodeURIComponent(window.location.href),c=Date.now();return`${r}?contributor_id=${t}&element_type=${e}&content_hash=${i}&${new URLSearchParams({source:s,t:c.toString(),utm_source:a.utmSource||"web_component",utm_medium:a.utmMedium||"embedded",utm_campaign:a.utmCampaign||e,utm_content:t}).toString()}`}const s="\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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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";class c extends HTMLElement{constructor(){super(),this.contentData=null,this.componentConnected=!1,this.shadow=this.attachShadow({mode:"closed"})}static get observedAttributes(){return["element-type","contributor-id","content","source-url","theme","track-analytics"]}connectedCallback(){if(!this.componentConnected){this.componentConnected=!0;try{this.render(),this.trackLoad()}catch(n){this.renderError("Failed to initialize component",n)}}}attributeChangedCallback(n,e,t){e!==t&&this.componentConnected&&this.render()}render(){const n=function(n){const a=[],r=n.getAttribute("element-type"),o=n.getAttribute("contributor-id");if(r){if(!t(r)){const n=Object.values(e).map(n=>n.value).join(", ");a.push(`Invalid element-type "${r}". Valid types: ${n}`)}}else a.push("Missing required attribute: element-type");return o?0===o.trim().length&&a.push("contributor-id cannot be empty"):a.push("Missing required attribute: contributor-id"),{isValid:0===a.length,errors:a,elementType:t(r||"")?r:void 0,contributorId:o||void 0}}(this);if(!n.isValid)return void this.renderError("Invalid component attributes",n.errors);const a=this.getContent();a.trim()?(this.contentData={contributor_id:n.contributorId,element_type:n.elementType,content:a,content_hash:o(a),source_url:this.getAttribute("source-url")||window.location.href,timestamp:(new Date).toISOString(),page_title:document.title},this.renderContent(),this.addStructuredData()):this.renderError("Component requires content",["Add content between the opening and closing tags, or use the content attribute"])}getContent(){return this.getAttribute("content")||this.textContent||""}renderContent(){if(!this.contentData)return;const{element_type:n,contributor_id:e,content:t}=this.contentData,r=a(n),o=i(t,n,e),c=this.getAttribute("theme")||"auto",l=this.formatContributorName(e),m=this.getInitials(l),h={role:"article","aria-label":`${a(n)} - Strategic insight`,"aria-describedby":"skhema-description"};Object.entries(h).forEach(([n,e])=>{this.setAttribute(n,e)}),this.shadow.innerHTML=`\n <style>${s}</style>\n \n <div class="skhema-insight-card" data-theme="${c}">\n <div class="skhema-header">\n <div class="skhema-contributor">\n <div class="skhema-avatar" title="${l}">\n ${m}\n </div>\n <div class="skhema-contributor-info">\n <div class="skhema-contributor-name">${l}</div>\n <div class="skhema-contributor-role">Strategy Insight</div>\n </div>\n </div>\n <div class="skhema-element-badge" title="${r}">\n ${r}\n </div>\n </div>\n \n <div class="skhema-content">\n <div class="skhema-content-text">${t}</div>\n </div>\n \n <div class="skhema-footer">\n <div class="skhema-attribution">\n Powered by <a href="https://skhema.com" target="_blank" rel="noopener noreferrer">Skhema</a>\n </div>\n <a href="${o}" \n class="skhema-save-btn" \n target="_blank"\n rel="noopener noreferrer"\n title="Save this insight to Skhema">\n Save to Skhema\n </a>\n </div>\n </div>\n `;const d=this.shadow.querySelector(".skhema-save-btn");d&&d.addEventListener("click",n=>{this.handleSaveClick(n)})}formatContributorName(n){return n.split(/[_-]/).map(n=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join(" ")}getInitials(n){return n.split(" ").map(n=>n.charAt(0)).join("").toUpperCase().substring(0,2)}renderError(n,e){const t=Array.isArray(e)?e:[String(e)];this.shadow.innerHTML=`\n <style>${s}</style>\n \n <div class="skhema-insight-card">\n <div class="skhema-error">\n <div class="skhema-error-title">Skhema Component Error: ${n}</div>\n <ul class="skhema-error-list">\n ${t.map(n=>`<li>${n}</li>`).join("")}\n </ul>\n </div>\n </div>\n `,this.dispatchEvent(new CustomEvent("skhema:error",{detail:{error:n,details:e},bubbles:!0}))}addStructuredData(){if(!this.contentData)return;const{content:n,element_type:e,contributor_id:t,source_url:r}=this.contentData,o=function(n,e,t,r){return{"@context":"https://schema.org","@type":"AnalysisContent",text:n,analysisType:e,category:a(e),contributor:t,url:i(n,e,t),provider:{"@type":"Organization",name:"Skhema",url:"https://skhema.com"},isPartOf:{"@type":"WebPage",url:r},dateCreated:(new Date).toISOString(),platform:"Skhema"}}(n,e,t,r),s=document.createElement("script");s.type="application/ld+json",s.textContent=JSON.stringify(o),s.className="skhema-structured-data",document.head.appendChild(s);const c=document.createElement("div");c.innerHTML=function(n,e,t){return`\n <div itemscope itemtype="https://schema.org/AnalysisContent" style="display:none;">\n <meta itemprop="analysisType" content="${e}">\n <meta itemprop="text" content="${n}">\n <meta itemprop="contributor" content="${t}">\n <meta itemprop="category" content="${a(e)}">\n <meta itemprop="platform" content="Skhema">\n </div>\n `}(n,e,t),c.className="skhema-structured-data",document.body.appendChild(c)}async trackLoad(){if(!r(this)||!this.contentData)return;const n={contributorId:this.contentData.contributor_id,elementType:this.contentData.element_type,contentHash:this.contentData.content_hash,pageUrl:window.location.href,pageTitle:document.title,timestamp:Date.now(),userAgent:navigator.userAgent};await async function(n){try{const e=new URLSearchParams({contributor_id:n.contributorId,element_type:n.elementType,content_hash:n.contentHash,page_url:n.pageUrl,page_title:n.pageTitle||"",timestamp:n.timestamp.toString(),user_agent:n.userAgent||""});navigator.sendBeacon?navigator.sendBeacon("https://api.skhema.com/api:XGdoUqHx/component/embed",e):fetch("https://api.skhema.com/api:XGdoUqHx/component/embed",{method:"POST",body:e,keepalive:!0}).catch(()=>{})}catch(e){console.debug("Analytics tracking failed:",e)}}(n),this.dispatchEvent(new CustomEvent("skhema:load",{detail:n,bubbles:!0}))}async handleSaveClick(n){this.contentData&&(r(this)&&await async function(n){try{const e={contributor_id:n.contributor_id,element_type:n.element_type,content_hash:n.content_hash,source_url:n.source_url,timestamp:n.timestamp};if(navigator.sendBeacon){const n=new Blob([JSON.stringify(e)],{type:"application/json"});navigator.sendBeacon("https://api.skhema.com/api:XGdoUqHx/component/click",n)}else fetch("https://api.skhema.com/api:XGdoUqHx/component/click",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0}).catch(()=>{})}catch(e){console.debug("Click tracking failed:",e)}}(this.contentData),this.dispatchEvent(new CustomEvent("skhema:click",{detail:this.contentData,bubbles:!0})))}getContentData(){return this.contentData}refresh(){this.render()}}customElements.get("skhema-element")||customElements.define("skhema-element",c),"undefined"!=typeof window&&(window.SkhemaElement=c),n.SkhemaElement=c,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
|
|
2
2
|
//# sourceMappingURL=web-component.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-component.min.js","sources":["../../skhema-types-library/dist/schema/elements.js","../src/utils/validation.ts","../src/utils/analytics.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/cdn.ts"],"sourcesContent":["export const ELEMENT_TYPES = {\n KEY_CHALLENGE: {\n value: \"key_challenge\",\n label: \"Key Challenge\",\n acronym: \"KC\"\n },\n SUPPORTING_FACT: {\n value: \"supporting_fact\",\n label: \"Supporting Fact\",\n acronym: \"SF\"\n },\n ASSOCIATED_IMPACT: {\n value: \"associated_impact\",\n label: \"Associated Impact\",\n acronym: \"AI\"\n },\n GUIDING_POLICY: {\n value: \"guiding_policy\",\n label: \"Guiding Policy\",\n acronym: \"GP\"\n },\n COMPETITOR_MOVE: {\n value: \"competitor_move\",\n label: \"Competitor Move\",\n acronym: \"CM\"\n },\n SCOPE: {\n value: \"scope\",\n label: \"Scope\",\n acronym: \"SC\"\n },\n CONSTRAINT: {\n value: \"constraint\",\n label: \"Constraint\",\n acronym: \"CN\"\n },\n SOLUTION_ALTERNATIVE: {\n value: \"solution_alternative\",\n label: \"Solution Alternative\",\n acronym: \"SA\"\n },\n ASSUMPTION_HYPOTHESIS: {\n value: \"assumption_hypothesis\",\n label: \"Assumption Hypothesis\",\n acronym: \"AH\"\n },\n EXPERIMENT: {\n value: \"experiment\",\n label: \"Experiment\",\n acronym: \"EX\"\n },\n ACTION: {\n value: \"action\",\n label: \"Action\",\n acronym: \"AC\"\n },\n INVESTMENT: {\n value: \"investment\",\n label: \"Investment\",\n acronym: \"IN\"\n },\n ESTIMATE: {\n value: \"estimate\",\n label: \"Estimate\",\n acronym: \"ES\"\n },\n BASELINE: {\n value: \"baseline\",\n label: \"Baseline\",\n acronym: \"BL\"\n },\n OUTCOME: {\n value: \"outcome\",\n label: \"Outcome\",\n acronym: \"OC\"\n },\n PERFORMANCE_VARIABLE: {\n value: \"performance_variable\",\n label: \"Performance Variable\",\n acronym: \"PV\"\n },\n CAPABILITY: {\n value: \"capability\",\n label: \"Capability\",\n acronym: \"CP\"\n },\n SYSTEM: {\n value: \"system\",\n label: \"System\",\n acronym: \"SY\"\n },\n PRINCIPLE: {\n value: \"principle\",\n label: \"Principle\",\n acronym: \"PR\"\n }\n};\n","import { ELEMENT_TYPES } from '@skhema/types';\nimport type { ElementValue } from '@skhema/types';\n\nexport function isValidElementType(elementType: string): 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).map(t => t.value).join(', ');\n errors.push(`Invalid element-type \"${elementType}\". Valid types: ${validTypes}`);\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 || '') ? elementType as ElementValue : 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}","import type { EmbedAnalytics, ContentData } from '../components/types.js';\n\nexport 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\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n const data = new URLSearchParams({\n contributor_id: analytics.contributorId,\n element_type: analytics.elementType,\n content_hash: analytics.contentHash,\n page_url: analytics.pageUrl,\n page_title: analytics.pageTitle || '',\n timestamp: analytics.timestamp.toString(),\n user_agent: analytics.userAgent || ''\n });\n\n // Use beacon for reliability\n if (navigator.sendBeacon) {\n navigator.sendBeacon('https://api.skhema.com/api:XGdoUqHx/component/embed', data);\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n keepalive: true\n }).catch(() => {\n // Fail silently - analytics shouldn't break the component\n });\n }\n } catch (error) {\n // Fail silently\n console.debug('Analytics tracking failed:', error);\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n const data = {\n contributor_id: contentData.contributor_id,\n element_type: contentData.element_type,\n content_hash: contentData.content_hash,\n source_url: contentData.source_url,\n timestamp: contentData.timestamp\n };\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n 'https://api.skhema.com/api:XGdoUqHx/component/click',\n JSON.stringify(data)\n );\n } else {\n fetch('https://api.skhema.com/api:XGdoUqHx/component/click', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n keepalive: true\n }).catch(() => {\n // Fail silently\n });\n }\n } catch (error) {\n console.debug('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}","import type { ElementValue } from '@skhema/types';\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://api.skhema.com/api:XGdoUqHx/component/redirect'; // @TODO: change to actual redirect URL\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 \n return `${baseUrl}?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\nfunction generateContentHash(content: string): string {\n // Simple hash for URL generation\n return btoa(content.substring(0, 50))\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 12);\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 createAriaAttributes(elementType: ElementValue): Record<string, string> {\n const label = getElementTypeLabel(elementType);\n \n return {\n 'role': 'article',\n 'aria-label': `${label} - Strategic insight`,\n 'aria-describedby': 'skhema-description'\n };\n}","import type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './types.js';\nimport { validateAttributes, getElementTypeLabel } from '../utils/validation.js';\nimport { generateContentHash, trackEmbedLoad, trackClick, shouldTrackAnalytics } from '../utils/analytics.js';\nimport { generateStructuredData, generateRedirectUrl, createMetaTags, createAriaAttributes } from '../utils/seo.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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'closed' });\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return ['element-type', 'contributor-id', 'content', 'source-url', 'theme', 'track-analytics'];\n }\n\n connectedCallback() {\n if (this.componentConnected) return;\n this.componentConnected = true;\n \n try {\n this.render();\n this.trackLoad();\n } catch (error) {\n this.renderError('Failed to initialize component', error);\n }\n }\n\n attributeChangedCallback(_name: keyof SkhemaElementAttributes, oldValue: string | null, newValue: string | null) {\n if (oldValue !== newValue && this.componentConnected) {\n this.render();\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', ['Add content between the opening and closing tags, or use the content attribute']);\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(content, element_type, contributor_id);\n const theme = this.getAttribute('theme') || 'auto';\n\n // Generate contributor display name and initials\n const displayName = this.formatContributorName(contributor_id);\n const initials = this.getInitials(displayName);\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 this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-card\" data-theme=\"${theme}\">\n <div class=\"skhema-header\">\n <div class=\"skhema-contributor\">\n <div class=\"skhema-avatar\" title=\"${displayName}\">\n ${initials}\n </div>\n <div class=\"skhema-contributor-info\">\n <div class=\"skhema-contributor-name\">${displayName}</div>\n <div class=\"skhema-contributor-role\">Strategy Insight</div>\n </div>\n </div>\n <div class=\"skhema-element-badge\" title=\"${label}\">\n ${label}\n </div>\n </div>\n \n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${content}</div>\n </div>\n \n <div class=\"skhema-footer\">\n <div class=\"skhema-attribution\">\n Powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n <a href=\"${redirectUrl}\" \n class=\"skhema-save-btn\" \n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this insight to Skhema\">\n Save to Skhema\n </a>\n </div>\n </div>\n `;\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector('.skhema-save-btn') as HTMLAnchorElement;\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event);\n });\n }\n }\n\n private formatContributorName(contributorId: string): string {\n // Convert contributor_id to display name\n return contributorId\n .split(/[_-]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n private getInitials(name: string): string {\n return name\n .split(' ')\n .map(word => word.charAt(0))\n .join('')\n .toUpperCase()\n .substring(0, 2);\n }\n\n private renderError(title: string, errors: string | string[] | any) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)];\n \n this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-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(new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true\n }));\n }\n\n private addStructuredData() {\n if (!this.contentData) return;\n\n const { content, element_type, contributor_id, source_url } = this.contentData;\n \n // Add structured data to the document head\n const structuredData = generateStructuredData(content, element_type, contributor_id, source_url);\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 (!shouldTrackAnalytics(this as HTMLElement) || !this.contentData) return;\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\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(new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true\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(new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true\n }));\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData;\n }\n\n public refresh(): void {\n this.render();\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n \n namespace JSX {\n interface IntrinsicElements {\n 'skhema-element': Partial<SkhemaElementAttributes> & {\n [key: string]: any;\n };\n }\n }\n}","// CDN bundle entry point - automatically registers the component\nimport { SkhemaElement } from './components/SkhemaElement.js';\n\n// Register the custom element for CDN usage\nif (!customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n}\n\n// Expose on global for UMD builds\nif (typeof window !== 'undefined') {\n (window as any).SkhemaElement = SkhemaElement;\n}\n\nexport { SkhemaElement };"],"names":["ELEMENT_TYPES","KEY_CHALLENGE","value","label","acronym","SUPPORTING_FACT","ASSOCIATED_IMPACT","GUIDING_POLICY","COMPETITOR_MOVE","SCOPE","CONSTRAINT","SOLUTION_ALTERNATIVE","ASSUMPTION_HYPOTHESIS","EXPERIMENT","ACTION","INVESTMENT","ESTIMATE","BASELINE","OUTCOME","PERFORMANCE_VARIABLE","CAPABILITY","SYSTEM","PRINCIPLE","isValidElementType","elementType","Object","values","map","type","includes","getElementTypeLabel","find","t","generateContentHash","content","hash","cleanContent","trim","substring","i","length","charCodeAt","Math","abs","toString","shouldTrackAnalytics","element","getAttribute","generateRedirectUrl","contributorId","options","baseUrl","contentHash","btoa","replace","sourceUrl","encodeURIComponent","window","location","href","timestamp","Date","now","URLSearchParams","source","utm_source","utmSource","utm_medium","utmMedium","utm_campaign","utmCampaign","utm_content","styles","SkhemaElement","HTMLElement","constructor","super","this","contentData","componentConnected","shadow","attachShadow","mode","observedAttributes","connectedCallback","render","trackLoad","error","renderError","attributeChangedCallback","_name","oldValue","newValue","validation","errors","validTypes","join","push","isValid","validateAttributes","getContent","contributor_id","element_type","content_hash","source_url","toISOString","page_title","document","title","renderContent","addStructuredData","textContent","redirectUrl","theme","displayName","formatContributorName","initials","getInitials","ariaAttrs","role","entries","forEach","key","setAttribute","innerHTML","saveBtn","querySelector","addEventListener","event","handleSaveClick","split","word","charAt","toUpperCase","slice","toLowerCase","name","errorList","Array","isArray","String","dispatchEvent","CustomEvent","detail","details","bubbles","structuredData","text","analysisType","category","contributor","url","provider","isPartOf","dateCreated","platform","generateStructuredData","script","createElement","JSON","stringify","className","head","appendChild","metaDiv","createMetaTags","body","analytics","pageUrl","pageTitle","userAgent","navigator","async","data","page_url","user_agent","sendBeacon","fetch","method","keepalive","catch","console","debug","trackEmbedLoad","_event","headers","trackClick","getContentData","refresh","customElements","get","define"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"web-component.min.js","sources":["../../skhema-types-library/dist/schema/elements.js","../src/utils/validation.ts","../src/utils/analytics.ts","../src/utils/hash.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/cdn.ts"],"sourcesContent":["export const ELEMENT_TYPES = {\n KEY_CHALLENGE: {\n value: \"key_challenge\",\n label: \"Key Challenge\",\n acronym: \"KC\"\n },\n SUPPORTING_FACT: {\n value: \"supporting_fact\",\n label: \"Supporting Fact\",\n acronym: \"SF\"\n },\n ASSOCIATED_IMPACT: {\n value: \"associated_impact\",\n label: \"Associated Impact\",\n acronym: \"AI\"\n },\n GUIDING_POLICY: {\n value: \"guiding_policy\",\n label: \"Guiding Policy\",\n acronym: \"GP\"\n },\n COMPETITOR_MOVE: {\n value: \"competitor_move\",\n label: \"Competitor Move\",\n acronym: \"CM\"\n },\n SCOPE: {\n value: \"scope\",\n label: \"Scope\",\n acronym: \"SC\"\n },\n CONSTRAINT: {\n value: \"constraint\",\n label: \"Constraint\",\n acronym: \"CN\"\n },\n SOLUTION_ALTERNATIVE: {\n value: \"solution_alternative\",\n label: \"Solution Alternative\",\n acronym: \"SA\"\n },\n ASSUMPTION_HYPOTHESIS: {\n value: \"assumption_hypothesis\",\n label: \"Assumption Hypothesis\",\n acronym: \"AH\"\n },\n EXPERIMENT: {\n value: \"experiment\",\n label: \"Experiment\",\n acronym: \"EX\"\n },\n ACTION: {\n value: \"action\",\n label: \"Action\",\n acronym: \"AC\"\n },\n INVESTMENT: {\n value: \"investment\",\n label: \"Investment\",\n acronym: \"IN\"\n },\n ESTIMATE: {\n value: \"estimate\",\n label: \"Estimate\",\n acronym: \"ES\"\n },\n BASELINE: {\n value: \"baseline\",\n label: \"Baseline\",\n acronym: \"BL\"\n },\n OUTCOME: {\n value: \"outcome\",\n label: \"Outcome\",\n acronym: \"OC\"\n },\n PERFORMANCE_VARIABLE: {\n value: \"performance_variable\",\n label: \"Performance Variable\",\n acronym: \"PV\"\n },\n CAPABILITY: {\n value: \"capability\",\n label: \"Capability\",\n acronym: \"CP\"\n },\n SYSTEM: {\n value: \"system\",\n label: \"System\",\n acronym: \"SY\"\n },\n PRINCIPLE: {\n value: \"principle\",\n label: \"Principle\",\n acronym: \"PR\"\n }\n};\n","import { ELEMENT_TYPES } from '@skhema/types';\nimport type { ElementValue } from '@skhema/types';\n\nexport function isValidElementType(elementType: string): 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).map(t => t.value).join(', ');\n errors.push(`Invalid element-type \"${elementType}\". Valid types: ${validTypes}`);\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 || '') ? elementType as ElementValue : 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}","import type { EmbedAnalytics, ContentData } from '../components/types.js';\n\n\nexport async function trackEmbedLoad(analytics: EmbedAnalytics): Promise<void> {\n try {\n const data = new URLSearchParams({\n contributor_id: analytics.contributorId,\n element_type: analytics.elementType,\n content_hash: analytics.contentHash,\n page_url: analytics.pageUrl,\n page_title: analytics.pageTitle || '',\n timestamp: analytics.timestamp.toString(),\n user_agent: analytics.userAgent || ''\n });\n\n // Use beacon for reliability\n if (navigator.sendBeacon) {\n navigator.sendBeacon('https://api.skhema.com/api:XGdoUqHx/component/embed', data);\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n keepalive: true\n }).catch(() => {\n // Fail silently - analytics shouldn't break the component\n });\n }\n } catch (error) {\n // Fail silently\n console.debug('Analytics tracking failed:', error);\n }\n}\n\nexport async function trackClick(contentData: ContentData): Promise<void> {\n try {\n const data = {\n contributor_id: contentData.contributor_id,\n element_type: contentData.element_type,\n content_hash: contentData.content_hash,\n source_url: contentData.source_url,\n timestamp: contentData.timestamp\n };\n\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(data)], {\n type: 'application/json'\n });\n navigator.sendBeacon(\n 'https://api.skhema.com/api:XGdoUqHx/component/click',\n blob\n );\n } else {\n fetch('https://api.skhema.com/api:XGdoUqHx/component/click', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n keepalive: true\n }).catch(() => {\n // Fail silently\n });\n }\n } catch (error) {\n console.debug('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}","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}","import type { ElementValue } from '@skhema/types';\nimport { getElementTypeLabel } from './validation.js';\nimport { generateContentHash } from './hash.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 \n return `${baseUrl}?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\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 createAriaAttributes(elementType: ElementValue): Record<string, string> {\n const label = getElementTypeLabel(elementType);\n \n return {\n 'role': 'article',\n 'aria-label': `${label} - Strategic insight`,\n 'aria-describedby': 'skhema-description'\n };\n}","import type { SkhemaElementAttributes, EmbedAnalytics, ContentData, SkhemaElementEventMap } from './types.js';\nimport { validateAttributes, getElementTypeLabel } from '../utils/validation.js';\nimport { trackEmbedLoad, trackClick, shouldTrackAnalytics } from '../utils/analytics.js';\nimport { generateContentHash } from '../utils/hash.js';\nimport { generateStructuredData, generateRedirectUrl, createMetaTags, createAriaAttributes } from '../utils/seo.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 --skhema-gradient: linear-gradient(135deg, hsl(344 57% 54%) 0%, hsl(345 100% 75%) 100%);\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.375rem;\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:host([theme=\"dark\"]) {\n /* Dark mode colors */\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 - inspired by your design */\n.skhema-insight-card {\n position: relative;\n background: var(--skhema-card);\n border: 1px solid var(--skhema-border);\n border-radius: calc(var(--skhema-radius) * 2);\n padding: 16px;\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}\n\n.skhema-insight-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 contributor info */\n.skhema-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n gap: 12px;\n}\n\n.skhema-contributor {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n}\n\n.skhema-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--skhema-gradient);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 14px;\n color: white;\n flex-shrink: 0;\n}\n\n.skhema-contributor-info {\n min-width: 0;\n flex: 1;\n}\n\n.skhema-contributor-name {\n font-weight: 500;\n font-size: 14px;\n color: var(--skhema-text);\n margin: 0;\n line-height: 1.2;\n}\n\n.skhema-contributor-role {\n font-size: 12px;\n color: var(--skhema-text-muted);\n margin: 0;\n line-height: 1.2;\n}\n\n/* Element type badge */\n.skhema-element-badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n border-radius: var(--skhema-radius);\n font-size: 11px;\n font-weight: 500;\n color: var(--skhema-text-muted);\n text-transform: capitalize;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Content section */\n.skhema-content {\n margin: 12px 0 16px 0;\n padding: 0;\n}\n\n.skhema-content-text {\n font-size: 15px;\n line-height: 1.6;\n color: var(--skhema-text);\n margin: 0;\n font-style: italic;\n position: relative;\n}\n\n.skhema-content-text::before {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-right: 4px;\n}\n\n.skhema-content-text::after {\n content: '\"';\n color: var(--skhema-primary);\n font-size: 20px;\n font-weight: 600;\n margin-left: 4px;\n}\n\n/* Footer section */\n.skhema-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--skhema-border);\n}\n\n.skhema-attribution {\n font-size: 11px;\n color: var(--skhema-text-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.skhema-attribution a {\n color: var(--skhema-primary);\n text-decoration: none;\n font-weight: 500;\n}\n\n.skhema-attribution a:hover {\n text-decoration: underline;\n}\n\n/* Save button with gradient and arrow */\n.skhema-save-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: var(--skhema-gradient);\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: var(--skhema-radius);\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--skhema-shadow);\n white-space: nowrap;\n}\n\n.skhema-save-btn:hover {\n transform: translateY(-1px);\n box-shadow: var(--skhema-shadow-md);\n}\n\n.skhema-save-btn:active {\n transform: translateY(0);\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: '→';\n transition: transform 0.2s ease;\n}\n\n.skhema-save-btn:hover::after {\n transform: translateX(2px);\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: var(--skhema-radius);\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/* Loading state */\n.skhema-loading {\n background: var(--skhema-accent);\n border: 1px solid var(--skhema-border);\n padding: 12px;\n border-radius: var(--skhema-radius);\n color: var(--skhema-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n.skhema-loading::after {\n content: '...';\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0%, 33% { content: '...'; }\n 66% { content: '..'; }\n 100% { content: '.'; }\n}\n\n/* Responsive design */\n@media (max-width: 640px) {\n .skhema-insight-card {\n margin: 4px 0;\n padding: 12px;\n }\n \n .skhema-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n \n .skhema-footer {\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-insight-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\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'closed' });\n }\n\n static get observedAttributes(): (keyof SkhemaElementAttributes)[] {\n return ['element-type', 'contributor-id', 'content', 'source-url', 'theme', 'track-analytics'];\n }\n\n connectedCallback() {\n if (this.componentConnected) return;\n this.componentConnected = true;\n \n try {\n this.render();\n this.trackLoad();\n } catch (error) {\n this.renderError('Failed to initialize component', error);\n }\n }\n\n attributeChangedCallback(_name: keyof SkhemaElementAttributes, oldValue: string | null, newValue: string | null) {\n if (oldValue !== newValue && this.componentConnected) {\n this.render();\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', ['Add content between the opening and closing tags, or use the content attribute']);\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(content, element_type, contributor_id);\n const theme = this.getAttribute('theme') || 'auto';\n\n // Generate contributor display name and initials\n const displayName = this.formatContributorName(contributor_id);\n const initials = this.getInitials(displayName);\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 this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-card\" data-theme=\"${theme}\">\n <div class=\"skhema-header\">\n <div class=\"skhema-contributor\">\n <div class=\"skhema-avatar\" title=\"${displayName}\">\n ${initials}\n </div>\n <div class=\"skhema-contributor-info\">\n <div class=\"skhema-contributor-name\">${displayName}</div>\n <div class=\"skhema-contributor-role\">Strategy Insight</div>\n </div>\n </div>\n <div class=\"skhema-element-badge\" title=\"${label}\">\n ${label}\n </div>\n </div>\n \n <div class=\"skhema-content\">\n <div class=\"skhema-content-text\">${content}</div>\n </div>\n \n <div class=\"skhema-footer\">\n <div class=\"skhema-attribution\">\n Powered by <a href=\"https://skhema.com\" target=\"_blank\" rel=\"noopener noreferrer\">Skhema</a>\n </div>\n <a href=\"${redirectUrl}\" \n class=\"skhema-save-btn\" \n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"Save this insight to Skhema\">\n Save to Skhema\n </a>\n </div>\n </div>\n `;\n\n // Add click event listener\n const saveBtn = this.shadow.querySelector('.skhema-save-btn') as HTMLAnchorElement;\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event);\n });\n }\n }\n\n private formatContributorName(contributorId: string): string {\n // Convert contributor_id to display name\n return contributorId\n .split(/[_-]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n private getInitials(name: string): string {\n return name\n .split(' ')\n .map(word => word.charAt(0))\n .join('')\n .toUpperCase()\n .substring(0, 2);\n }\n\n private renderError(title: string, errors: string | string[] | any) {\n const errorList = Array.isArray(errors) ? errors : [String(errors)];\n \n this.shadow.innerHTML = `\n <style>${styles}</style>\n \n <div class=\"skhema-insight-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(new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true\n }));\n }\n\n private addStructuredData() {\n if (!this.contentData) return;\n\n const { content, element_type, contributor_id, source_url } = this.contentData;\n \n // Add structured data to the document head\n const structuredData = generateStructuredData(content, element_type, contributor_id, source_url);\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 (!shouldTrackAnalytics(this as HTMLElement) || !this.contentData) return;\n\n const analytics: EmbedAnalytics = {\n contributorId: this.contentData.contributor_id,\n elementType: this.contentData.element_type,\n contentHash: this.contentData.content_hash,\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(new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true\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(new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true\n }));\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData;\n }\n\n public refresh(): void {\n this.render();\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n \n namespace JSX {\n interface IntrinsicElements {\n 'skhema-element': Partial<SkhemaElementAttributes> & {\n [key: string]: any;\n };\n }\n }\n}","// CDN bundle entry point - automatically registers the component\nimport { SkhemaElement } from './components/SkhemaElement.js';\n\n// Register the custom element for CDN usage\nif (!customElements.get('skhema-element')) {\n customElements.define('skhema-element', SkhemaElement as CustomElementConstructor);\n}\n\n// Expose on global for UMD builds\nif (typeof window !== 'undefined') {\n (window as any).SkhemaElement = SkhemaElement;\n}\n\nexport { SkhemaElement };"],"names":["ELEMENT_TYPES","KEY_CHALLENGE","value","label","acronym","SUPPORTING_FACT","ASSOCIATED_IMPACT","GUIDING_POLICY","COMPETITOR_MOVE","SCOPE","CONSTRAINT","SOLUTION_ALTERNATIVE","ASSUMPTION_HYPOTHESIS","EXPERIMENT","ACTION","INVESTMENT","ESTIMATE","BASELINE","OUTCOME","PERFORMANCE_VARIABLE","CAPABILITY","SYSTEM","PRINCIPLE","isValidElementType","elementType","Object","values","map","type","includes","getElementTypeLabel","find","t","shouldTrackAnalytics","element","getAttribute","generateContentHash","content","hash","cleanContent","trim","substring","i","length","charCodeAt","Math","abs","toString","generateRedirectUrl","contributorId","options","baseUrl","contentHash","sourceUrl","encodeURIComponent","window","location","href","timestamp","Date","now","URLSearchParams","source","utm_source","utmSource","utm_medium","utmMedium","utm_campaign","utmCampaign","utm_content","styles","SkhemaElement","HTMLElement","constructor","super","this","contentData","componentConnected","shadow","attachShadow","mode","observedAttributes","connectedCallback","render","trackLoad","error","renderError","attributeChangedCallback","_name","oldValue","newValue","validation","errors","validTypes","join","push","isValid","validateAttributes","getContent","contributor_id","element_type","content_hash","source_url","toISOString","page_title","document","title","renderContent","addStructuredData","textContent","redirectUrl","theme","displayName","formatContributorName","initials","getInitials","ariaAttrs","role","entries","forEach","key","setAttribute","innerHTML","saveBtn","querySelector","addEventListener","event","handleSaveClick","split","word","charAt","toUpperCase","slice","toLowerCase","name","errorList","Array","isArray","String","dispatchEvent","CustomEvent","detail","details","bubbles","structuredData","text","analysisType","category","contributor","url","provider","isPartOf","dateCreated","platform","generateStructuredData","script","createElement","JSON","stringify","className","head","appendChild","metaDiv","createMetaTags","body","analytics","pageUrl","pageTitle","userAgent","navigator","async","data","page_url","user_agent","sendBeacon","fetch","method","keepalive","catch","console","debug","trackEmbedLoad","_event","blob","Blob","headers","trackClick","getContentData","refresh","customElements","get","define"],"mappings":"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"}
|