wakeflow-widgets
v0.0.5
Published
widget-monorepo/ │ ├── packages/ │ ├── core/ │ │ └── loader.js # Universal loader │ │ │ ├── widget-voice/ │ │ ├── src/ │ │ │ ├── index.js │ │ │ └── VoiceWidget.js │ │ └── vite.config.js │ │ │ ├── widget-chat/ │ │
Downloads
14
Readme
widget-monorepo/ │ ├── packages/ │ ├── core/ │ │ └── loader.js # Universal loader │ │ │ ├── widget-voice/ │ │ ├── src/ │ │ │ ├── index.js │ │ │ └── VoiceWidget.js │ │ └── vite.config.js │ │ │ ├── widget-chat/ │ │ ├── src/ │ │ │ ├── index.js │ │ │ └── ChatWidget.js │ │ └── vite.config.js │ │ │ └── widget-analytics/ │ ├── src/ │ │ ├── index.js │ │ └── AnalyticsWidget.js │ └── vite.config.js │ ├── package.json └── vite.workspace.config.js
{ "test": { "include": ["packages//test/**/.{test,spec}.{js,ts}"], "coverage": { "provider": "v8", "reporter": ["text", "json", "html"] } } }
2. Root Package JSON:
<antArtifact identifier="root-package-json" type="application/vnd.ant.code" language="json" title="Root Package Configuration">
{
"name": "wakeflow-widgets",
"private": true,
"type": "module",
"scripts": {
"build": "npm run build:voice && npm run build:chat && npm run build:analytics",
"build:voice": "cd packages/widget-voice && vite build",
"build:chat": "cd packages/widget-chat && vite build",
"build:analytics": "cd packages/widget-analytics && vite build",
"test": "vitest",
"test:coverage": "vitest run --coverage"
},
"devDependencies": {
"@vitejs/plugin-react-swc": "^3.3.2",
"vitest": "^0.34.6"
}
}- Individual Package Vite Configuration:
export default defineConfig({ plugins: [react()], test: { globals: true, environment: 'jsdom', setupFiles: ['./test/setup.js'], coverage: { provider: 'v8', reporter: ['text', 'json', 'html'] } }, build: { lib: { entry: './src/index.js', name: 'VoiceWidget', formats: ['umd'] }, rollupOptions: { external: ['react', 'react-dom'], output: { globals: { react: 'React', 'react-dom': 'ReactDOM' } } } } })
4. Universal Loader Script:
<antArtifact identifier="universal-loader" type="application/vnd.ant.code" language="javascript" title="Universal Widget Loader">
// packages/core/loader.js
(function() {
// Prevent multiple initializations
if (window.WidgetLoader) return;
window.WidgetLoader = true;
// Widget configuration storage
window.WidgetConfigs = {};
// Universal widget loader
window.loadWidget = function(widgetName, config = {}) {
// Create unique container for each widget
const containerId = `widget-${widgetName}-container`;
const existingContainer = document.getElementById(containerId);
if (existingContainer) {
existingContainer.innerHTML = '';
}
const widgetContainer = existingContainer || (() => {
const newContainer = document.createElement('div');
newContainer.id = containerId;
document.body.appendChild(newContainer);
return newContainer;
})();
// Store configuration
window.WidgetConfigs[widgetName] = {
...config,
containerId
};
// Dynamic script loader
function loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.async = true;
script.crossOrigin = 'anonymous';
script.onload = () => resolve(script);
script.onerror = (error) => reject(error);
document.head.appendChild(script);
});
}
// Widget initialization process
const initializeWidget = async () => {
try {
// Ensure React dependencies
if (typeof React === 'undefined' || typeof ReactDOM === 'undefined') {
await Promise.all([
loadScript('https://unpkg.com/react@18/umd/react.production.min.js'),
loadScript('https://unpkg.com/react-dom@18/umd/react-dom.production.min.js')
]);
}
// Dynamically load specific widget
await loadScript(`/wakeflow/${widgetName}.umd.js`);
// Initialize widget
if (window[`${widgetName}Widget`] && window[`${widgetName}Widget`].initWidget) {
window[`${widgetName}Widget`].initWidget(window.WidgetConfigs[widgetName]);
} else {
console.error(`Widget initialization failed for: ${widgetName}`);
}
} catch (error) {
console.error(`Complete widget load process failed for ${widgetName}:`, error);
}
};
// Start initialization
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeWidget);
} else {
initializeWidget();
}
};
})();- Example Widget Entry Point:
export function initWidget(config) { const container = document.getElementById(config.containerId)
if (container) { ReactDOM.createRoot(container).render( <React.StrictMode> <VoiceWidget {...config} /> </React.StrictMode> ) } }
// Ensure global availability for UMD if (typeof window !== 'undefined') { window.voiceWidget = { initWidget }; }
6. Example Package JSON for a Widget:
<antArtifact identifier="widget-package-json" type="application/vnd.ant.code" language="json" title="Widget Package Configuration">
{
"name": "@wakeflow/widget-voice",
"version": "1.0.0",
"type": "module",
"main": "dist/voice.umd.js",
"scripts": {
"build": "vite build",
"test": "vitest",
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@vitejs/plugin-react-swc": "^3.3.2",
"vite": "^4.4.9",
"vitest": "^0.34.6"
}
}Key Improvements with Vitest Workspaces
- Unified testing configuration
- Easy package management
- Consistent build and test processes
- Workspace-wide test coverage
- Modular project structure
Usage Remains the Same
<script src="/wakeflow/loader.js"></script>
<script>
loadWidget('voice', {
orgName: 'wakeflow.io',
mode: 'bubble'
});
</script>Setup Instructions
- Install dependencies:
npm install- Build all widgets:
npm run build- Run tests:
npm test