@skhema/web-component 0.0.13 → 0.0.15
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/README.md +10 -10
- package/dist/cdn.d.ts +0 -1
- package/dist/cdn.d.ts.map +1 -1
- package/dist/components/SkhemaElement.d.ts +6 -8
- package/dist/components/SkhemaElement.d.ts.map +1 -1
- package/dist/components/types.d.ts +4 -4
- package/dist/components/types.d.ts.map +1 -1
- package/dist/index.cjs +114 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +114 -66
- package/dist/index.es.js.map +1 -1
- package/dist/utils/analytics.d.ts +1 -2
- package/dist/utils/analytics.d.ts.map +1 -1
- package/dist/utils/seo.d.ts +0 -1
- package/dist/utils/seo.d.ts.map +1 -1
- package/dist/utils/validation.d.ts +0 -1
- package/dist/utils/validation.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 +17 -3
package/README.md
CHANGED
|
@@ -19,23 +19,23 @@ npm install @skhema/web-component
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
```javascript
|
|
22
|
-
import '@skhema/web-component'
|
|
22
|
+
import '@skhema/web-component'
|
|
23
23
|
// Component is automatically registered
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Attributes
|
|
27
27
|
|
|
28
|
-
| Attribute
|
|
29
|
-
|
|
30
|
-
| `element-type`
|
|
31
|
-
| `contributor-id` | ✓
|
|
32
|
-
| `content`
|
|
33
|
-
| `theme`
|
|
28
|
+
| Attribute | Required | Description |
|
|
29
|
+
| ---------------- | -------- | ------------------------------------- |
|
|
30
|
+
| `element-type` | ✓ | Type of strategic element |
|
|
31
|
+
| `contributor-id` | ✓ | Your contributor identifier |
|
|
32
|
+
| `content` | | Alternative to inner text |
|
|
33
|
+
| `theme` | | Visual theme: `light`, `dark`, `auto` |
|
|
34
34
|
|
|
35
35
|
## Element Types
|
|
36
36
|
|
|
37
37
|
- `key_challenge` - Business challenges
|
|
38
|
-
- `supporting_fact` - Evidence and data points
|
|
38
|
+
- `supporting_fact` - Evidence and data points
|
|
39
39
|
- `guiding_policy` - Strategic approaches
|
|
40
40
|
- `solution_alternative` - Potential solutions
|
|
41
41
|
- And more...
|
|
@@ -45,7 +45,7 @@ import '@skhema/web-component';
|
|
|
45
45
|
```html
|
|
46
46
|
<article>
|
|
47
47
|
<p>The automotive industry is undergoing transformation...</p>
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
<skhema-element element-type="key_challenge" contributor-id="analyst">
|
|
50
50
|
Traditional automakers face retooling challenges while competing with Tesla.
|
|
51
51
|
</skhema-element>
|
|
@@ -54,4 +54,4 @@ import '@skhema/web-component';
|
|
|
54
54
|
|
|
55
55
|
## License
|
|
56
56
|
|
|
57
|
-
MIT
|
|
57
|
+
MIT
|
package/dist/cdn.d.ts
CHANGED
package/dist/cdn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,
|
|
1
|
+
{"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAiB7D,OAAO,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ContentData, SkhemaElementAttributes, SkhemaElementEventMap } from './types.js';
|
|
3
2
|
export declare class SkhemaElement extends HTMLElement {
|
|
4
3
|
private shadow;
|
|
5
4
|
private contentData;
|
|
@@ -23,12 +22,11 @@ export declare class SkhemaElement extends HTMLElement {
|
|
|
23
22
|
declare global {
|
|
24
23
|
interface HTMLElementEventMap extends SkhemaElementEventMap {
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
25
|
+
interface SkhemaElementJSX extends Partial<SkhemaElementAttributes> {
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
interface JSXIntrinsicElements {
|
|
29
|
+
'skhema-element': SkhemaElementJSX;
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
//# sourceMappingURL=SkhemaElement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SkhemaElement.d.ts","sourceRoot":"","sources":["../../src/components/SkhemaElement.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SkhemaElement.d.ts","sourceRoot":"","sources":["../../src/components/SkhemaElement.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,WAAW,EAEX,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,YAAY,CAAA;AA2TnB,qBAAa,aAAc,SAAQ,WAAW;IAC5C,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,kBAAkB,CAAQ;;IAOlC,MAAM,KAAK,kBAAkB,IAAI,CAAC,MAAM,uBAAuB,CAAC,EAAE,CASjE;IAED,iBAAiB;IAYjB,wBAAwB,CACtB,KAAK,EAAE,MAAM,uBAAuB,EACpC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOzB,OAAO,CAAC,MAAM;IA8Bd,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,aAAa;IAuErB,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,iBAAiB;YA0BX,SAAS;YAyBT,eAAe;IAkBtB,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC,OAAO,IAAI,IAAI;CAGvB;AAGD,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,mBAAoB,SAAQ,qBAAqB;KAAG;IAE9D,UAAU,gBAAiB,SAAQ,OAAO,CAAC,uBAAuB,CAAC;QACjE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB;IAGD,UAAU,oBAAoB;QAC5B,gBAAgB,EAAE,gBAAgB,CAAA;KACnC;CACF"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ElementValue } from '@skhema/types';
|
|
2
|
-
|
|
3
2
|
export interface SkhemaElementAttributes {
|
|
4
3
|
'element-type': ElementValue;
|
|
5
4
|
'contributor-id': string;
|
|
6
|
-
|
|
5
|
+
content?: string;
|
|
7
6
|
'source-url'?: string;
|
|
8
|
-
|
|
7
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
9
8
|
'track-analytics'?: 'true' | 'false';
|
|
10
9
|
}
|
|
11
10
|
export interface EmbedAnalytics {
|
|
12
11
|
contributorId: string;
|
|
13
12
|
elementType: ElementValue;
|
|
14
13
|
contentHash: string;
|
|
14
|
+
content: string;
|
|
15
15
|
pageUrl: string;
|
|
16
16
|
pageTitle?: string;
|
|
17
17
|
timestamp: number;
|
|
@@ -37,7 +37,7 @@ export interface SkhemaElementEventMap {
|
|
|
37
37
|
'skhema:click': CustomEvent<ContentData>;
|
|
38
38
|
'skhema:error': CustomEvent<{
|
|
39
39
|
error: string;
|
|
40
|
-
details?:
|
|
40
|
+
details?: unknown;
|
|
41
41
|
}>;
|
|
42
42
|
}
|
|
43
43
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/components/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/components/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,YAAY,CAAA;IAC5B,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;IACjC,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,YAAY,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,YAAY,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,WAAW,CAAC,cAAc,CAAC,CAAA;IAC1C,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,CAAA;IACxC,cAAc,EAAE,WAAW,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CAClE"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,39 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
3
|
const types = require("@skhema/types");
|
|
4
|
-
function
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (!elementType) {
|
|
13
|
-
errors.push("Missing required attribute: element-type");
|
|
14
|
-
} else if (!isValidElementType(elementType)) {
|
|
15
|
-
const validTypes = Object.values(types.ELEMENT_TYPES).map((t) => t.value).join(", ");
|
|
16
|
-
errors.push(`Invalid element-type "${elementType}". Valid types: ${validTypes}`);
|
|
17
|
-
}
|
|
18
|
-
if (!contributorId) {
|
|
19
|
-
errors.push("Missing required attribute: contributor-id");
|
|
20
|
-
} else if (contributorId.trim().length === 0) {
|
|
21
|
-
errors.push("contributor-id cannot be empty");
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
isValid: errors.length === 0,
|
|
25
|
-
errors,
|
|
26
|
-
elementType: isValidElementType(elementType || "") ? elementType : void 0,
|
|
27
|
-
contributorId: contributorId || void 0
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function getElementTypeLabel(elementType) {
|
|
31
|
-
const type = Object.values(types.ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
32
|
-
return (type == null ? void 0 : type.label) || elementType;
|
|
33
|
-
}
|
|
34
|
-
function getElementTypeAcronym(elementType) {
|
|
35
|
-
const type = Object.values(types.ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
36
|
-
return (type == null ? void 0 : type.acronym) || elementType.substring(0, 2).toUpperCase();
|
|
4
|
+
function toUrlSafeBase64(str) {
|
|
5
|
+
const base64 = btoa(
|
|
6
|
+
encodeURIComponent(str).replace(
|
|
7
|
+
/%([0-9A-F]{2})/g,
|
|
8
|
+
(_, p1) => String.fromCharCode(parseInt(p1, 16))
|
|
9
|
+
)
|
|
10
|
+
);
|
|
11
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
37
12
|
}
|
|
38
13
|
async function trackEmbedLoad(analytics) {
|
|
39
14
|
try {
|
|
@@ -41,13 +16,17 @@ async function trackEmbedLoad(analytics) {
|
|
|
41
16
|
contributor_id: analytics.contributorId,
|
|
42
17
|
element_type: analytics.elementType,
|
|
43
18
|
content_hash: analytics.contentHash,
|
|
19
|
+
content: toUrlSafeBase64(analytics.content),
|
|
44
20
|
page_url: analytics.pageUrl,
|
|
45
21
|
page_title: analytics.pageTitle || "",
|
|
46
22
|
timestamp: analytics.timestamp.toString(),
|
|
47
23
|
user_agent: analytics.userAgent || ""
|
|
48
24
|
});
|
|
49
25
|
if (navigator.sendBeacon) {
|
|
50
|
-
navigator.sendBeacon(
|
|
26
|
+
navigator.sendBeacon(
|
|
27
|
+
"https://api.skhema.com/api:XGdoUqHx/component/embed",
|
|
28
|
+
data
|
|
29
|
+
);
|
|
51
30
|
} else {
|
|
52
31
|
fetch("https://api.skhema.com/api:XGdoUqHx/component/embed", {
|
|
53
32
|
method: "POST",
|
|
@@ -96,26 +75,62 @@ function generateContentHash(content) {
|
|
|
96
75
|
}
|
|
97
76
|
return Math.abs(hash).toString(36).substring(0, 12);
|
|
98
77
|
}
|
|
78
|
+
function isValidElementType(elementType) {
|
|
79
|
+
const validTypes = Object.values(types.ELEMENT_TYPES).map((type) => type.value);
|
|
80
|
+
return validTypes.includes(elementType);
|
|
81
|
+
}
|
|
82
|
+
function validateAttributes(element) {
|
|
83
|
+
const errors = [];
|
|
84
|
+
const elementType = element.getAttribute("element-type");
|
|
85
|
+
const contributorId = element.getAttribute("contributor-id");
|
|
86
|
+
if (!elementType) {
|
|
87
|
+
errors.push("Missing required attribute: element-type");
|
|
88
|
+
} else if (!isValidElementType(elementType)) {
|
|
89
|
+
const validTypes = Object.values(types.ELEMENT_TYPES).map((t) => t.value).join(", ");
|
|
90
|
+
errors.push(
|
|
91
|
+
`Invalid element-type "${elementType}". Valid types: ${validTypes}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
if (!contributorId) {
|
|
95
|
+
errors.push("Missing required attribute: contributor-id");
|
|
96
|
+
} else if (contributorId.trim().length === 0) {
|
|
97
|
+
errors.push("contributor-id cannot be empty");
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
isValid: errors.length === 0,
|
|
101
|
+
errors,
|
|
102
|
+
elementType: isValidElementType(elementType || "") ? elementType : void 0,
|
|
103
|
+
contributorId: contributorId || void 0
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function getElementTypeLabel(elementType) {
|
|
107
|
+
const type = Object.values(types.ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
108
|
+
return type?.label || elementType;
|
|
109
|
+
}
|
|
110
|
+
function getElementTypeAcronym(elementType) {
|
|
111
|
+
const type = Object.values(types.ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
112
|
+
return type?.acronym || elementType.substring(0, 2).toUpperCase();
|
|
113
|
+
}
|
|
99
114
|
function generateStructuredData(content, elementType, contributorId, sourceUrl) {
|
|
100
115
|
return {
|
|
101
116
|
"@context": "https://schema.org",
|
|
102
117
|
"@type": "AnalysisContent",
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
118
|
+
text: content,
|
|
119
|
+
analysisType: elementType,
|
|
120
|
+
category: getElementTypeLabel(elementType),
|
|
121
|
+
contributor: contributorId,
|
|
122
|
+
url: generateRedirectUrl(content, elementType, contributorId),
|
|
123
|
+
provider: {
|
|
109
124
|
"@type": "Organization",
|
|
110
|
-
|
|
111
|
-
|
|
125
|
+
name: "Skhema",
|
|
126
|
+
url: "https://skhema.com"
|
|
112
127
|
},
|
|
113
|
-
|
|
128
|
+
isPartOf: {
|
|
114
129
|
"@type": "WebPage",
|
|
115
|
-
|
|
130
|
+
url: sourceUrl
|
|
116
131
|
},
|
|
117
|
-
|
|
118
|
-
|
|
132
|
+
dateCreated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
133
|
+
platform: "Skhema"
|
|
119
134
|
};
|
|
120
135
|
}
|
|
121
136
|
function generateRedirectUrl(content, elementType, contributorId, options = {}) {
|
|
@@ -148,7 +163,7 @@ function createMetaTags(content, elementType, contributorId) {
|
|
|
148
163
|
function createAriaAttributes(elementType) {
|
|
149
164
|
const label = getElementTypeLabel(elementType);
|
|
150
165
|
return {
|
|
151
|
-
|
|
166
|
+
role: "article",
|
|
152
167
|
"aria-label": `${label} - Strategic insight`,
|
|
153
168
|
"aria-describedby": "skhema-description"
|
|
154
169
|
};
|
|
@@ -472,7 +487,14 @@ class SkhemaElement extends HTMLElement {
|
|
|
472
487
|
this.shadow = this.attachShadow({ mode: "closed" });
|
|
473
488
|
}
|
|
474
489
|
static get observedAttributes() {
|
|
475
|
-
return [
|
|
490
|
+
return [
|
|
491
|
+
"element-type",
|
|
492
|
+
"contributor-id",
|
|
493
|
+
"content",
|
|
494
|
+
"source-url",
|
|
495
|
+
"theme",
|
|
496
|
+
"track-analytics"
|
|
497
|
+
];
|
|
476
498
|
}
|
|
477
499
|
connectedCallback() {
|
|
478
500
|
if (this.componentConnected) return;
|
|
@@ -497,7 +519,9 @@ class SkhemaElement extends HTMLElement {
|
|
|
497
519
|
}
|
|
498
520
|
const content = this.getContent();
|
|
499
521
|
if (!content.trim()) {
|
|
500
|
-
this.renderError("Component requires content", [
|
|
522
|
+
this.renderError("Component requires content", [
|
|
523
|
+
"Add content between the opening and closing tags, or use the content attribute"
|
|
524
|
+
]);
|
|
501
525
|
return;
|
|
502
526
|
}
|
|
503
527
|
this.contentData = {
|
|
@@ -519,7 +543,11 @@ class SkhemaElement extends HTMLElement {
|
|
|
519
543
|
if (!this.contentData) return;
|
|
520
544
|
const { element_type, contributor_id, content } = this.contentData;
|
|
521
545
|
const label = getElementTypeLabel(element_type);
|
|
522
|
-
const redirectUrl = generateRedirectUrl(
|
|
546
|
+
const redirectUrl = generateRedirectUrl(
|
|
547
|
+
content,
|
|
548
|
+
element_type,
|
|
549
|
+
contributor_id
|
|
550
|
+
);
|
|
523
551
|
const theme = this.getAttribute("theme") || "auto";
|
|
524
552
|
const displayName = this.formatContributorName(contributor_id);
|
|
525
553
|
const initials = this.getInitials(displayName);
|
|
@@ -564,7 +592,9 @@ class SkhemaElement extends HTMLElement {
|
|
|
564
592
|
</div>
|
|
565
593
|
</div>
|
|
566
594
|
`;
|
|
567
|
-
const saveBtn = this.shadow.querySelector(
|
|
595
|
+
const saveBtn = this.shadow.querySelector(
|
|
596
|
+
".skhema-save-btn"
|
|
597
|
+
);
|
|
568
598
|
if (saveBtn) {
|
|
569
599
|
saveBtn.addEventListener("click", (event) => {
|
|
570
600
|
this.handleSaveClick(event);
|
|
@@ -591,15 +621,22 @@ class SkhemaElement extends HTMLElement {
|
|
|
591
621
|
</div>
|
|
592
622
|
</div>
|
|
593
623
|
`;
|
|
594
|
-
this.dispatchEvent(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
624
|
+
this.dispatchEvent(
|
|
625
|
+
new CustomEvent("skhema:error", {
|
|
626
|
+
detail: { error: title, details: errors },
|
|
627
|
+
bubbles: true
|
|
628
|
+
})
|
|
629
|
+
);
|
|
598
630
|
}
|
|
599
631
|
addStructuredData() {
|
|
600
632
|
if (!this.contentData) return;
|
|
601
633
|
const { content, element_type, contributor_id, source_url } = this.contentData;
|
|
602
|
-
const structuredData = generateStructuredData(
|
|
634
|
+
const structuredData = generateStructuredData(
|
|
635
|
+
content,
|
|
636
|
+
element_type,
|
|
637
|
+
contributor_id,
|
|
638
|
+
source_url
|
|
639
|
+
);
|
|
603
640
|
const script = document.createElement("script");
|
|
604
641
|
script.type = "application/ld+json";
|
|
605
642
|
script.textContent = JSON.stringify(structuredData);
|
|
@@ -616,26 +653,31 @@ class SkhemaElement extends HTMLElement {
|
|
|
616
653
|
contributorId: this.contentData.contributor_id,
|
|
617
654
|
elementType: this.contentData.element_type,
|
|
618
655
|
contentHash: this.contentData.content_hash,
|
|
656
|
+
content: this.contentData.content,
|
|
619
657
|
pageUrl: window.location.href,
|
|
620
658
|
pageTitle: document.title,
|
|
621
659
|
timestamp: Date.now(),
|
|
622
660
|
userAgent: navigator.userAgent
|
|
623
661
|
};
|
|
624
662
|
await trackEmbedLoad(analytics);
|
|
625
|
-
this.dispatchEvent(
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
663
|
+
this.dispatchEvent(
|
|
664
|
+
new CustomEvent("skhema:load", {
|
|
665
|
+
detail: analytics,
|
|
666
|
+
bubbles: true
|
|
667
|
+
})
|
|
668
|
+
);
|
|
629
669
|
}
|
|
630
670
|
async handleSaveClick(_event) {
|
|
631
671
|
if (!this.contentData) return;
|
|
632
672
|
if (shouldTrackAnalytics(this)) {
|
|
633
673
|
await trackClick(this.contentData);
|
|
634
674
|
}
|
|
635
|
-
this.dispatchEvent(
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
675
|
+
this.dispatchEvent(
|
|
676
|
+
new CustomEvent("skhema:click", {
|
|
677
|
+
detail: this.contentData,
|
|
678
|
+
bubbles: true
|
|
679
|
+
})
|
|
680
|
+
);
|
|
639
681
|
}
|
|
640
682
|
// Public API methods
|
|
641
683
|
getContentData() {
|
|
@@ -647,11 +689,17 @@ class SkhemaElement extends HTMLElement {
|
|
|
647
689
|
}
|
|
648
690
|
function registerSkhemaElement() {
|
|
649
691
|
if (typeof window !== "undefined" && !customElements.get("skhema-element")) {
|
|
650
|
-
customElements.define(
|
|
692
|
+
customElements.define(
|
|
693
|
+
"skhema-element",
|
|
694
|
+
SkhemaElement
|
|
695
|
+
);
|
|
651
696
|
}
|
|
652
697
|
}
|
|
653
698
|
if (typeof window !== "undefined" && !customElements.get("skhema-element")) {
|
|
654
|
-
customElements.define(
|
|
699
|
+
customElements.define(
|
|
700
|
+
"skhema-element",
|
|
701
|
+
SkhemaElement
|
|
702
|
+
);
|
|
655
703
|
}
|
|
656
704
|
exports.SkhemaElement = SkhemaElement;
|
|
657
705
|
exports.default = SkhemaElement;
|
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/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 credentials: 'omit',\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 // Always use fetch for click tracking to ensure proper CORS handling\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 credentials: 'omit',\n keepalive: true\n }).catch(() => {\n // Fail silently\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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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/utils/analytics.ts","../src/utils/hash.ts","../src/utils/validation.ts","../src/utils/seo.ts","../src/components/SkhemaElement.ts","../src/index.ts"],"sourcesContent":["import type { ContentData, EmbedAnalytics } from '../components/types.js'\n\n/**\n * Encode string to URL-safe base64\n */\nfunction toUrlSafeBase64(str: string): string {\n // Convert string to base64\n const base64 = btoa(\n encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, p1) =>\n String.fromCharCode(parseInt(p1, 16))\n )\n )\n // Make it URL-safe by replacing + with -, / with _, and removing trailing =\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\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 content: toUrlSafeBase64(analytics.content),\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(\n 'https://api.skhema.com/api:XGdoUqHx/component/embed',\n data\n )\n } else {\n // Fallback to fetch\n fetch('https://api.skhema.com/api:XGdoUqHx/component/embed', {\n method: 'POST',\n body: data,\n credentials: 'omit',\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 // Always use fetch for click tracking to ensure proper CORS handling\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 credentials: 'omit',\n keepalive: true,\n }).catch(() => {\n // Fail silently\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}\n","export function generateContentHash(content: string): string {\n // Simple hash function for content identification\n let hash = 0\n const cleanContent = content.trim().substring(0, 200)\n\n for (let i = 0; i < cleanContent.length; i++) {\n const char = cleanContent.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n\n return Math.abs(hash).toString(36).substring(0, 12)\n}\n","import type { ElementValue } from '@skhema/types'\nimport { ELEMENT_TYPES } from '@skhema/types'\n\nexport function isValidElementType(\n elementType: string\n): elementType is ElementValue {\n const validTypes = Object.values(ELEMENT_TYPES).map((type) => type.value)\n return validTypes.includes(elementType as ElementValue)\n}\n\nexport function validateAttributes(element: HTMLElement): {\n isValid: boolean\n errors: string[]\n elementType?: ElementValue\n contributorId?: string\n} {\n const errors: string[] = []\n\n const elementType = element.getAttribute('element-type')\n const contributorId = element.getAttribute('contributor-id')\n\n if (!elementType) {\n errors.push('Missing required attribute: element-type')\n } else if (!isValidElementType(elementType)) {\n const validTypes = Object.values(ELEMENT_TYPES)\n .map((t) => t.value)\n .join(', ')\n errors.push(\n `Invalid element-type \"${elementType}\". Valid types: ${validTypes}`\n )\n }\n\n if (!contributorId) {\n errors.push('Missing required attribute: contributor-id')\n } else if (contributorId.trim().length === 0) {\n errors.push('contributor-id cannot be empty')\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n elementType: isValidElementType(elementType || '')\n ? (elementType as ElementValue)\n : undefined,\n contributorId: contributorId || undefined,\n }\n}\n\nexport function getElementTypeLabel(elementType: ElementValue): string {\n const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType)\n return type?.label || elementType\n}\n\nexport function getElementTypeAcronym(elementType: ElementValue): string {\n const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType)\n return type?.acronym || elementType.substring(0, 2).toUpperCase()\n}\n","import type { ElementValue } from '@skhema/types'\nimport { generateContentHash } from './hash.js'\nimport { getElementTypeLabel } from './validation.js'\n\nexport function generateStructuredData(\n content: string,\n elementType: ElementValue,\n contributorId: string,\n sourceUrl: string\n): object {\n return {\n '@context': 'https://schema.org',\n '@type': 'AnalysisContent',\n text: content,\n analysisType: elementType,\n category: getElementTypeLabel(elementType),\n contributor: contributorId,\n url: generateRedirectUrl(content, elementType, contributorId),\n provider: {\n '@type': 'Organization',\n name: 'Skhema',\n url: 'https://skhema.com',\n },\n isPartOf: {\n '@type': 'WebPage',\n url: sourceUrl,\n },\n dateCreated: new Date().toISOString(),\n platform: 'Skhema',\n }\n}\n\nexport function generateRedirectUrl(\n content: string,\n elementType: ElementValue,\n contributorId: string,\n options: {\n baseUrl?: string\n utmSource?: string\n utmMedium?: string\n utmCampaign?: string\n } = {}\n): string {\n const baseUrl = options.baseUrl || 'https://app.skhema.com/save' // This page will handle the authentication and content saving\n const contentHash = generateContentHash(content)\n const sourceUrl = encodeURIComponent(window.location.href)\n const timestamp = Date.now()\n\n const params = new URLSearchParams({\n source: sourceUrl,\n t: timestamp.toString(),\n utm_source: options.utmSource || 'web_component',\n utm_medium: options.utmMedium || 'embedded',\n utm_campaign: options.utmCampaign || elementType,\n utm_content: contributorId,\n })\n\n return `${baseUrl}?contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}&${params.toString()}`\n // return `${baseUrl}/contributor_id=${contributorId}&element_type=${elementType}&content_hash=${contentHash}?${params.toString()}`;\n}\n\nexport function createMetaTags(\n content: string,\n elementType: ElementValue,\n contributorId: string\n): string {\n const label = getElementTypeLabel(elementType)\n\n return `\n <div itemscope itemtype=\"https://schema.org/AnalysisContent\" style=\"display:none;\">\n <meta itemprop=\"analysisType\" content=\"${elementType}\">\n <meta itemprop=\"text\" content=\"${content}\">\n <meta itemprop=\"contributor\" content=\"${contributorId}\">\n <meta itemprop=\"category\" content=\"${label}\">\n <meta itemprop=\"platform\" content=\"Skhema\">\n </div>\n `\n}\n\nexport function createAriaAttributes(\n elementType: ElementValue\n): 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}\n","import {\n shouldTrackAnalytics,\n trackClick,\n trackEmbedLoad,\n} from '../utils/analytics.js'\nimport { generateContentHash } from '../utils/hash.js'\nimport {\n createAriaAttributes,\n createMetaTags,\n generateRedirectUrl,\n generateStructuredData,\n} from '../utils/seo.js'\nimport { getElementTypeLabel, validateAttributes } from '../utils/validation.js'\nimport type {\n ContentData,\n EmbedAnalytics,\n SkhemaElementAttributes,\n SkhemaElementEventMap,\n} from './types.js'\n\n// Inline styles matching Skhema UI library design system\nconst styles = `\n:host {\n /* Skhema Brand Colors - matching UI library */\n --skhema-primary: hsl(344 57% 54%); /* #cd476a */\n --skhema-primary-hover: hsl(344 50% 47%); /* #b53d5e */\n --skhema-primary-pressed: hsl(343 50% 41%); /* #9d3552 */\n --skhema-secondary: hsl(345 100% 75%); /* #ff82a2 */\n --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 [\n 'element-type',\n 'contributor-id',\n 'content',\n 'source-url',\n 'theme',\n 'track-analytics',\n ]\n }\n\n connectedCallback() {\n if (this.componentConnected) return\n this.componentConnected = true\n\n try {\n this.render()\n this.trackLoad()\n } catch (error) {\n this.renderError('Failed to initialize component', error)\n }\n }\n\n attributeChangedCallback(\n _name: keyof SkhemaElementAttributes,\n oldValue: string | null,\n newValue: string | null\n ) {\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', [\n 'Add content between the opening and closing tags, or use the content attribute',\n ])\n return\n }\n\n this.contentData = {\n contributor_id: validation.contributorId!,\n element_type: validation.elementType!,\n content: content,\n content_hash: generateContentHash(content),\n source_url: this.getAttribute('source-url') || window.location.href,\n timestamp: new Date().toISOString(),\n page_title: document.title,\n }\n\n this.renderContent()\n this.addStructuredData()\n }\n\n private getContent(): string {\n return this.getAttribute('content') || this.textContent || ''\n }\n\n private renderContent() {\n if (!this.contentData) return\n\n const { element_type, contributor_id, content } = this.contentData\n const label = getElementTypeLabel(element_type)\n const redirectUrl = generateRedirectUrl(\n content,\n element_type,\n contributor_id\n )\n 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(\n '.skhema-save-btn'\n ) as HTMLAnchorElement\n if (saveBtn) {\n saveBtn.addEventListener('click', (event) => {\n this.handleSaveClick(event)\n })\n }\n }\n\n private 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[] | unknown) {\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(\n new CustomEvent('skhema:error', {\n detail: { error: title, details: errors },\n bubbles: true,\n })\n )\n }\n\n private addStructuredData() {\n if (!this.contentData) return\n\n const { content, element_type, contributor_id, source_url } =\n this.contentData\n\n // Add structured data to the document head\n const structuredData = generateStructuredData(\n content,\n element_type,\n contributor_id,\n source_url\n )\n const script = document.createElement('script')\n script.type = 'application/ld+json'\n script.textContent = JSON.stringify(structuredData)\n script.className = 'skhema-structured-data'\n document.head.appendChild(script)\n\n // Add meta tags for SEO\n const metaDiv = document.createElement('div')\n metaDiv.innerHTML = createMetaTags(content, element_type, contributor_id)\n metaDiv.className = 'skhema-structured-data'\n document.body.appendChild(metaDiv)\n }\n\n private async trackLoad() {\n if (!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 content: this.contentData.content,\n pageUrl: window.location.href,\n pageTitle: document.title,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n }\n\n await trackEmbedLoad(analytics)\n\n // Dispatch load event\n this.dispatchEvent(\n new CustomEvent('skhema:load', {\n detail: analytics,\n bubbles: true,\n })\n )\n }\n\n private async handleSaveClick(_event: Event) {\n if (!this.contentData) return\n\n // Track click analytics\n if (shouldTrackAnalytics(this as HTMLElement)) {\n await trackClick(this.contentData)\n }\n\n // Dispatch click event\n this.dispatchEvent(\n new CustomEvent('skhema:click', {\n detail: this.contentData,\n bubbles: true,\n })\n )\n }\n\n // Public API methods\n public getContentData(): ContentData | null {\n return this.contentData\n }\n\n public refresh(): void {\n this.render()\n }\n}\n\n// Type augmentation for custom events and JSX elements\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface HTMLElementEventMap extends SkhemaElementEventMap {}\n\n interface SkhemaElementJSX extends Partial<SkhemaElementAttributes> {\n [key: string]: unknown\n }\n\n // Module augmentation for JSX without using namespace\n interface JSXIntrinsicElements {\n 'skhema-element': SkhemaElementJSX\n }\n}\n","import { SkhemaElement } from './components/SkhemaElement.js'\n\n// Export the component class\nexport { SkhemaElement }\n\n// Export types for TypeScript users\nexport type {\n ContentData,\n EmbedAnalytics,\n SkhemaElementAttributes,\n SkhemaElementEventMap,\n} from './components/types.js'\n\n// Export utilities\nexport {\n getElementTypeAcronym,\n getElementTypeLabel,\n isValidElementType,\n validateAttributes,\n} from './utils/validation.js'\n\nexport {\n // Removed generateContentHash\n shouldTrackAnalytics,\n} from './utils/analytics.js'\n\nexport { generateRedirectUrl, generateStructuredData } 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(\n 'skhema-element',\n SkhemaElement as CustomElementConstructor\n )\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(\n 'skhema-element',\n SkhemaElement as CustomElementConstructor\n )\n}\n\n// Default export for convenience\nexport default SkhemaElement\n"],"names":["ELEMENT_TYPES"],"mappings":"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;AAAA,EAAA;AAExB;ACpEA,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { SkhemaElement } from './components/SkhemaElement.js';
|
|
2
|
-
|
|
3
2
|
export { SkhemaElement };
|
|
4
|
-
export type {
|
|
5
|
-
export {
|
|
6
|
-
export { shouldTrackAnalytics } from './utils/analytics.js';
|
|
7
|
-
export {
|
|
3
|
+
export type { ContentData, EmbedAnalytics, SkhemaElementAttributes, SkhemaElementEventMap, } from './components/types.js';
|
|
4
|
+
export { getElementTypeAcronym, getElementTypeLabel, isValidElementType, validateAttributes, } from './utils/validation.js';
|
|
5
|
+
export { shouldTrackAnalytics, } from './utils/analytics.js';
|
|
6
|
+
export { generateRedirectUrl, generateStructuredData } from './utils/seo.js';
|
|
8
7
|
export declare function registerSkhemaElement(): void;
|
|
9
8
|
export default SkhemaElement;
|
|
10
9
|
//# sourceMappingURL=index.d.ts.map
|
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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAG7D,OAAO,EAAE,aAAa,EAAE,CAAA;AAGxB,YAAY,EACV,WAAW,EACX,cAAc,EACd,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAEL,oBAAoB,GACrB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAG5E,wBAAgB,qBAAqB,SAOpC;AAWD,eAAe,aAAa,CAAA"}
|