@supernal/tts-widget 1.0.0

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/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@supernal/tts-widget",
3
+ "version": "1.0.0",
4
+ "description": "Embeddable TTS widget for blogs and websites",
5
+ "main": "./dist/widget.js",
6
+ "module": "./dist/widget.js",
7
+ "types": "./dist/widget.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/widget.d.ts",
11
+ "import": "./dist/widget.js",
12
+ "default": "./dist/widget.js"
13
+ },
14
+ "./loader": {
15
+ "types": "./dist/loader.d.ts",
16
+ "import": "./dist/loader.js",
17
+ "default": "./dist/loader.js"
18
+ },
19
+ "./widget.js": {
20
+ "types": "./dist/widget.d.ts",
21
+ "import": "./dist/widget.js",
22
+ "default": "./dist/widget.js"
23
+ },
24
+ "./react": {
25
+ "types": "./dist/react/index.d.ts",
26
+ "import": "./dist/react/index.js",
27
+ "default": "./dist/react/index.js"
28
+ },
29
+ "./widget.css": "./dist/widget.css",
30
+ "./dist/widget.css": "./dist/widget.css"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "src/react",
35
+ "README.md",
36
+ "MIGRATION.md",
37
+ "dist/supernal-tts-logo.svg"
38
+ ],
39
+ "scripts": {
40
+ "build": "npm run build:ts && npm run build:loader && npm run build:bundle && npm run build:css",
41
+ "build:ts": "tsc",
42
+ "build:loader": "esbuild src/loader.ts --bundle --minify --sourcemap --outfile=dist/loader.js --format=esm --external:none --define:__PACKAGE_VERSION__='\"1.3.1\"'",
43
+ "build:bundle": "esbuild src/widget.ts --bundle --minify --sourcemap --outfile=dist/widget.js --format=esm --external:none",
44
+ "build:css": "cp src/widget.css dist/widget.css",
45
+ "dev": "tsc --watch",
46
+ "clean": "rm -rf dist",
47
+ "prepublishOnly": "npm run clean && npm run build"
48
+ },
49
+ "keywords": [
50
+ "tts",
51
+ "text-to-speech",
52
+ "widget",
53
+ "audio",
54
+ "speech",
55
+ "supernal",
56
+ "accessibility",
57
+ "voice"
58
+ ],
59
+ "author": "Supernal Intelligence",
60
+ "license": "MIT",
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "https://github.com/supernalintelligence/supernal-nova.git",
64
+ "directory": "families/supernal-tts/packages/@supernal-tts/widget"
65
+ },
66
+ "homepage": "https://www.tts.supernal.ai",
67
+ "bugs": {
68
+ "url": "https://github.com/supernalintelligence/supernal-tts/issues"
69
+ },
70
+ "peerDependencies": {
71
+ "react": ">=16.8.0"
72
+ },
73
+ "peerDependenciesMeta": {
74
+ "react": {
75
+ "optional": true
76
+ }
77
+ },
78
+ "devDependencies": {
79
+ "@types/minimatch": "^5.1.2",
80
+ "@types/react": "^18.0.0",
81
+ "esbuild": "^0.20.0",
82
+ "typescript": "^5.0.0"
83
+ }
84
+ }
@@ -0,0 +1,163 @@
1
+ /**
2
+ * TTSInitializer - React component for initializing Supernal TTS widget
3
+ *
4
+ * Usage:
5
+ * import { TTSInitializer } from '@supernal/tts-widget/react';
6
+ * import '@supernal/tts-widget/widget.css';
7
+ *
8
+ * // In your root layout or _app.tsx
9
+ * <TTSInitializer
10
+ * apiUrl="https://www.tts.supernal.ai"
11
+ * apiKey={process.env.NEXT_PUBLIC_TTS_API_KEY}
12
+ * mode="auto" // Try CDN, fallback to bundled (default)
13
+ * version="major" // Load latest v1.x.x (default)
14
+ * />
15
+ */
16
+
17
+ import * as React from 'react';
18
+ import { useEffect, useState } from 'react';
19
+
20
+ export interface TTSInitializerProps {
21
+ apiUrl?: string;
22
+ apiKey?: string;
23
+ provider?: string;
24
+ voice?: string;
25
+ speed?: number; // Default speed for all widgets (1.0 = normal)
26
+ devMode?: boolean;
27
+ clientSideSpeed?: boolean;
28
+ showBranding?: boolean;
29
+
30
+ // New smart loader options
31
+ /**
32
+ * Loading mode:
33
+ * - 'auto': Try CDN, fallback to bundled (default, recommended)
34
+ * - 'cdn': Force CDN load, error if unavailable
35
+ * - 'bundled': Always use bundled version (CSP-safe)
36
+ */
37
+ mode?: 'auto' | 'cdn' | 'bundled';
38
+
39
+ /**
40
+ * Version strategy:
41
+ * - 'major': Load latest v1.x.x (default, recommended)
42
+ * - 'latest': Load absolute latest (risky)
43
+ * - '1.3.0': Pin to specific version
44
+ */
45
+ version?: 'major' | 'latest' | string;
46
+
47
+ /**
48
+ * CDN fetch timeout in milliseconds (default: 3000)
49
+ */
50
+ timeout?: number;
51
+
52
+ /**
53
+ * Callback when CDN load fails and fallback is used
54
+ */
55
+ onCdnFail?: (error: Error) => void;
56
+
57
+ /**
58
+ * Callback when CDN load succeeds
59
+ */
60
+ onCdnSuccess?: () => void;
61
+ }
62
+
63
+ export default function TTSInitializer({
64
+ apiUrl = 'https://www.tts.supernal.ai',
65
+ apiKey,
66
+ provider = 'openai',
67
+ voice = 'alloy',
68
+ speed = 1.0,
69
+ devMode,
70
+ clientSideSpeed = true,
71
+ showBranding = true,
72
+ mode = 'auto',
73
+ version = 'major',
74
+ timeout = 3000,
75
+ onCdnFail,
76
+ onCdnSuccess,
77
+ }: TTSInitializerProps) {
78
+ const [error, setError] = useState<string | null>(null);
79
+
80
+ useEffect(() => {
81
+ // Only run on client side
82
+ if (typeof window === 'undefined') return;
83
+
84
+ let isMounted = true;
85
+
86
+ // Note: Users should import CSS separately:
87
+ // import '@supernal/tts-widget/widget.css';
88
+
89
+ // Load widget using smart loader
90
+ const loadWidget = async () => {
91
+ try {
92
+ const loaderModule = await import('../loader');
93
+ const { WidgetLoader } = loaderModule;
94
+
95
+ const widget = await WidgetLoader.load({
96
+ mode,
97
+ version,
98
+ timeout,
99
+ onCdnFail: (err) => {
100
+ console.warn('[TTS Widget] CDN load failed, using bundled version:', err.message);
101
+ onCdnFail?.(err);
102
+ },
103
+ onCdnSuccess: () => {
104
+ console.log('[TTS Widget] Successfully loaded from CDN');
105
+ onCdnSuccess?.();
106
+ },
107
+ });
108
+
109
+ // Only initialize if component is still mounted
110
+ if (!isMounted) return;
111
+
112
+ // Initialize widget if not already initialized
113
+ if (!(window as any).SupernalTTSInstance) {
114
+ widget.init({
115
+ apiUrl,
116
+ apiKey,
117
+ provider,
118
+ voice,
119
+ speed,
120
+ devMode,
121
+ clientSideSpeed,
122
+ showBranding,
123
+ });
124
+ }
125
+ } catch (err) {
126
+ if (!isMounted) return;
127
+
128
+ const errorMessage = err instanceof Error ? err.message : String(err);
129
+ console.error('[TTS Widget] Failed to load:', errorMessage);
130
+ setError(errorMessage);
131
+ }
132
+ };
133
+
134
+ loadWidget();
135
+
136
+ // Cleanup function
137
+ return () => {
138
+ isMounted = false;
139
+ // Don't remove CSS or instance - they should persist across component unmounts
140
+ };
141
+ }, [apiUrl, apiKey, provider, voice, speed, devMode, clientSideSpeed, showBranding, mode, version, timeout]);
142
+
143
+ // Optionally render error state
144
+ if (error && devMode) {
145
+ return React.createElement('div', {
146
+ style: {
147
+ padding: '12px',
148
+ background: '#fee',
149
+ border: '1px solid #fcc',
150
+ borderRadius: '4px',
151
+ color: '#c33',
152
+ fontFamily: 'monospace',
153
+ fontSize: '12px',
154
+ }
155
+ }, [
156
+ React.createElement('strong', { key: 'title' }, 'TTS Widget Error: '),
157
+ error
158
+ ]);
159
+ }
160
+
161
+ return null; // This component doesn't render anything in production
162
+ }
163
+
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Supernal TTS Widget - React Components
3
+ *
4
+ * Provides React-specific components for easy integration
5
+ */
6
+
7
+ export { default as TTSInitializer, type TTSInitializerProps } from './TTSInitializer';
8
+
9
+ // Also provide default export for convenience
10
+ export { default } from './TTSInitializer';
11
+