@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/MIGRATION.md +502 -0
- package/README.md +340 -0
- package/dist/loader.d.ts +78 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +96 -0
- package/dist/loader.js.map +7 -0
- package/dist/react/TTSInitializer.d.ts +64 -0
- package/dist/react/TTSInitializer.d.ts.map +1 -0
- package/dist/react/TTSInitializer.js +132 -0
- package/dist/react/TTSInitializer.js.map +1 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +17 -0
- package/dist/react/index.js.map +1 -0
- package/dist/widget.css +839 -0
- package/dist/widget.d.ts +176 -0
- package/dist/widget.d.ts.map +1 -0
- package/dist/widget.js +96 -0
- package/dist/widget.js.map +7 -0
- package/package.json +84 -0
- package/src/react/TTSInitializer.tsx +163 -0
- package/src/react/index.ts +11 -0
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
|
+
|