@courseecho/ai-widget-react 1.0.22 → 1.0.24

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.
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * ShadowWrapper — renders children inside a Shadow DOM so the widget's CSS
3
3
  * is completely isolated from the host application's styles.
4
+ *
5
+ * Key isolation techniques used:
6
+ * 1. :host { all: initial } — kills every inherited CSS property at the boundary
7
+ * 2. Full element reset inside the shadow — counters any UA-sheet or inherited font changes
8
+ * 3. Google Fonts injected into document <head> (fonts are shared across shadow trees)
9
+ * 4. React portal into a container that lives inside the shadow root
4
10
  */
5
11
  import React from 'react';
6
12
  export declare const ShadowWrapper: React.FC<{
@@ -2,12 +2,59 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  /**
3
3
  * ShadowWrapper — renders children inside a Shadow DOM so the widget's CSS
4
4
  * is completely isolated from the host application's styles.
5
+ *
6
+ * Key isolation techniques used:
7
+ * 1. :host { all: initial } — kills every inherited CSS property at the boundary
8
+ * 2. Full element reset inside the shadow — counters any UA-sheet or inherited font changes
9
+ * 3. Google Fonts injected into document <head> (fonts are shared across shadow trees)
10
+ * 4. React portal into a container that lives inside the shadow root
5
11
  */
6
12
  import { useRef, useEffect, useState } from 'react';
7
13
  import { createPortal } from 'react-dom';
8
- // All widget CSS inlined here so it can be injected into the shadow root.
9
- // The @import is replaced with a <link> element appended to the shadow root.
14
+ // Inject Inter font into the document <head> once (fonts ARE shared across shadow DOM boundaries)
15
+ function ensureFont() {
16
+ if (typeof document === 'undefined')
17
+ return;
18
+ if (document.getElementById('aiwg-inter-font'))
19
+ return;
20
+ const link = document.createElement('link');
21
+ link.id = 'aiwg-inter-font';
22
+ link.rel = 'stylesheet';
23
+ link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap';
24
+ document.head.appendChild(link);
25
+ }
10
26
  const WIDGET_CSS = `
27
+ /* ── Total isolation from host app ───────────────────────────────────────── */
28
+ :host {
29
+ all: initial !important;
30
+ display: block !important;
31
+ }
32
+
33
+ /* Guarantee every element inside the shadow starts from a known baseline */
34
+ *, *::before, *::after {
35
+ box-sizing: border-box !important;
36
+ margin: 0 !important;
37
+ padding: 0 !important;
38
+ border: 0 !important;
39
+ font-size: 100% !important;
40
+ font: inherit !important;
41
+ vertical-align: baseline !important;
42
+ line-height: inherit !important;
43
+ color: inherit !important;
44
+ background: transparent !important;
45
+ text-decoration: none !important;
46
+ list-style: none !important;
47
+ }
48
+
49
+ /* Restore sensible block/inline defaults that the above stripped */
50
+ div, section, article, header, footer, main, nav, aside { display: block !important; }
51
+ span, em, strong, small, code, kbd { display: inline !important; }
52
+ button { display: inline-flex !important; cursor: pointer !important; }
53
+ textarea, input { display: block !important; }
54
+ ul, ol { display: flex !important; flex-direction: column !important; }
55
+ a { cursor: pointer !important; }
56
+
57
+ /* ── Widget component styles ─────────────────────────────────────────────── */
11
58
  .aiwg-root *, .aiwg-root *::before, .aiwg-root *::after { box-sizing: border-box; margin: 0; padding: 0; }
12
59
 
13
60
  .aiwg-root {
@@ -146,15 +193,11 @@ export const ShadowWrapper = ({ children }) => {
146
193
  const hostRef = useRef(null);
147
194
  const [portalTarget, setPortalTarget] = useState(null);
148
195
  useEffect(() => {
196
+ ensureFont(); // inject Inter into <head> — fonts are shared across shadow boundaries
149
197
  const host = hostRef.current;
150
198
  if (!host || host.shadowRoot)
151
199
  return;
152
200
  const shadow = host.attachShadow({ mode: 'open' });
153
- // Load Inter font (Google Fonts can't be @imported inside shadow DOM)
154
- const link = document.createElement('link');
155
- link.rel = 'stylesheet';
156
- link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap';
157
- shadow.appendChild(link);
158
201
  // Inject all widget CSS into the shadow root
159
202
  const style = document.createElement('style');
160
203
  style.textContent = WIDGET_CSS;
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Page Content Scanner and AI Suggestion Generator
3
+ * Automatically extracts page content and generates AI-powered suggestions
4
+ */
5
+ import { AiSuggestion, PageScanConfig, AiSuggestionGeneratorConfig } from './models';
6
+ export interface PageContent {
7
+ url: string;
8
+ title: string;
9
+ description: string;
10
+ headings: string[];
11
+ keywords: string[];
12
+ pageType: string;
13
+ rawText: string;
14
+ }
15
+ /**
16
+ * Scans page content and extracts relevant information
17
+ */
18
+ export declare class PageContentScanner {
19
+ private config;
20
+ private cachedContent;
21
+ constructor(config?: PageScanConfig);
22
+ /**
23
+ * Scan page content
24
+ */
25
+ scanPage(): PageContent;
26
+ /**
27
+ * Get cached content if still valid
28
+ */
29
+ private getCachedContent;
30
+ /**
31
+ * Cache content
32
+ */
33
+ private cacheContent;
34
+ /**
35
+ * Extract page title
36
+ */
37
+ private extractTitle;
38
+ /**
39
+ * Extract meta description
40
+ */
41
+ private extractDescription;
42
+ /**
43
+ * Extract all headings
44
+ */
45
+ private extractHeadings;
46
+ /**
47
+ * Extract keywords from meta tags
48
+ */
49
+ private extractKeywords;
50
+ /**
51
+ * Detect page type (course, product, blog, etc.)
52
+ */
53
+ private detectPageType;
54
+ /**
55
+ * Extract main text content
56
+ */
57
+ private extractMainContent;
58
+ /**
59
+ * Clear cache
60
+ */
61
+ clearCache(): void;
62
+ /**
63
+ * Update config
64
+ */
65
+ updateConfig(config: Partial<PageScanConfig>): void;
66
+ }
67
+ /**
68
+ * Generates AI-powered suggestions based on page content
69
+ */
70
+ export declare class AiSuggestionGenerator {
71
+ private config;
72
+ private pageScanner;
73
+ constructor(config?: AiSuggestionGeneratorConfig, pageScanner?: PageContentScanner);
74
+ /**
75
+ * Generate suggestions based on page content
76
+ */
77
+ generateSuggestions(): Promise<AiSuggestion[]>;
78
+ /**
79
+ * Free tier: Generate suggestions locally based on heuristics
80
+ */
81
+ private generateFreeSuggestions;
82
+ /**
83
+ * Premium tier: Use backend AI for smart suggestions
84
+ */
85
+ private generatePremiumSuggestions;
86
+ /**
87
+ * Course page suggestions
88
+ */
89
+ private generateCourseSuggestions;
90
+ /**
91
+ * Product page suggestions
92
+ */
93
+ private generateProductSuggestions;
94
+ /**
95
+ * Blog page suggestions
96
+ */
97
+ private generateBlogSuggestions;
98
+ /**
99
+ * Support page suggestions
100
+ */
101
+ private generateSupportSuggestions;
102
+ /**
103
+ * Documentation page suggestions
104
+ */
105
+ private generateDocsSuggestions;
106
+ /**
107
+ * Generic page suggestions
108
+ */
109
+ private generateGenericSuggestions;
110
+ /**
111
+ * Update config
112
+ */
113
+ updateConfig(config: Partial<AiSuggestionGeneratorConfig>): void;
114
+ /**
115
+ * Get current tier
116
+ */
117
+ getTier(): string;
118
+ }