@tavus/cvi-ui 0.0.1-beta.2 → 0.0.1-beta.3
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 +44 -33
- package/dev-components/components/README.md +62 -1
- package/dev-components/components/audio-wave/audio-wave.module.css +33 -0
- package/dev-components/components/audio-wave/index.tsx +55 -0
- package/dev-components/components/controls/controls.module.css +75 -73
- package/dev-components/components/controls/index.tsx +2 -2
- package/dev-components/components/conversation-01/conversation.module.css +222 -0
- package/dev-components/components/conversation-01/index.tsx +180 -0
- package/dev-components/components/{hair-check → hair-check-01}/hair-check.module.css +2 -1
- package/dev-components/components/{hair-check → hair-check-01}/index.tsx +1 -1
- package/dist/index.js +412 -104
- package/dist/types/templates/components.d.ts +32 -2
- package/dist/types/templates/jsx/index.d.ts +11 -1
- package/dist/types/templates/tsx/index.d.ts +11 -1
- package/dist/types/utils/version-utils.d.ts +3 -0
- package/package.json +6 -4
- package/src/templates/components.ts +18 -0
- package/src/templates/index.ts +2 -0
- package/src/templates/jsx/components/audio-wave.json +5 -0
- package/src/templates/jsx/components/controls.json +10 -0
- package/src/templates/jsx/components/conversation-01.json +11 -0
- package/src/templates/jsx/components/cvi-provider.json +5 -0
- package/src/templates/jsx/components/hair-check-01.json +10 -0
- package/src/templates/jsx/hooks/cvi-events-hooks.json +5 -0
- package/src/templates/jsx/hooks/use-cvi-call.json +5 -0
- package/src/templates/jsx/hooks/use-local-camera.json +5 -0
- package/src/templates/jsx/hooks/use-local-microphone.json +5 -0
- package/src/templates/jsx/hooks/use-local-screenshare.json +5 -0
- package/src/templates/jsx/hooks/use-remote-participant-ids.json +5 -0
- package/src/templates/jsx/hooks/use-replica-ids.json +5 -0
- package/src/templates/jsx/hooks/use-request-permissions.json +5 -0
- package/src/templates/jsx/hooks/use-start-haircheck.json +5 -0
- package/src/templates/jsx/index.ts +14 -0
- package/src/templates/tsx/components/audio-wave.json +5 -0
- package/src/templates/tsx/components/controls.json +10 -0
- package/src/templates/tsx/components/conversation-01.json +11 -0
- package/src/templates/tsx/components/cvi-provider.json +5 -0
- package/src/templates/tsx/components/hair-check-01.json +10 -0
- package/src/templates/tsx/hooks/cvi-events-hooks.json +5 -0
- package/src/templates/tsx/hooks/use-cvi-call.json +5 -0
- package/src/templates/tsx/hooks/use-local-camera.json +5 -0
- package/src/templates/tsx/hooks/use-local-microphone.json +5 -0
- package/src/templates/tsx/hooks/use-local-screenshare.json +5 -0
- package/src/templates/tsx/hooks/use-remote-participant-ids.json +5 -0
- package/src/templates/tsx/hooks/use-replica-ids.json +5 -0
- package/src/templates/tsx/hooks/use-request-permissions.json +8 -0
- package/src/templates/tsx/hooks/use-start-haircheck.json +5 -0
- package/src/templates/tsx/index.ts +14 -0
- package/src/utils/resolve-components-tree.ts +59 -2
- package/src/utils/update-files.ts +38 -10
- package/src/utils/version-utils.ts +26 -0
- /package/dev-components/hooks/{use-cvi-call.ts → use-cvi-call.tsx} +0 -0
- /package/dev-components/hooks/{use-local-camera.ts → use-local-camera.tsx} +0 -0
- /package/dev-components/hooks/{use-local-microphone.ts → use-local-microphone.tsx} +0 -0
- /package/dev-components/hooks/{use-local-screenshare.ts → use-local-screenshare.tsx} +0 -0
- /package/dev-components/hooks/{use-remote-participant-ids.ts → use-remote-participant-ids.tsx} +0 -0
- /package/dev-components/hooks/{use-replica-ids.ts → use-replica-ids.tsx} +0 -0
- /package/dev-components/hooks/{use-request-permissions.ts → use-request-permissions.tsx} +0 -0
- /package/dev-components/hooks/{use-start-haircheck.ts → use-start-haircheck.tsx} +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { default as "audio-wave" } from './components/audio-wave.json';
|
|
2
|
+
export { default as "controls" } from './components/controls.json';
|
|
3
|
+
export { default as "conversation-01" } from './components/conversation-01.json';
|
|
4
|
+
export { default as "cvi-provider" } from './components/cvi-provider.json';
|
|
5
|
+
export { default as "hair-check-01" } from './components/hair-check-01.json';
|
|
6
|
+
export { default as "cvi-events-hooks" } from './hooks/cvi-events-hooks.json';
|
|
7
|
+
export { default as "use-cvi-call" } from './hooks/use-cvi-call.json';
|
|
8
|
+
export { default as "use-local-camera" } from './hooks/use-local-camera.json';
|
|
9
|
+
export { default as "use-local-microphone" } from './hooks/use-local-microphone.json';
|
|
10
|
+
export { default as "use-local-screenshare" } from './hooks/use-local-screenshare.json';
|
|
11
|
+
export { default as "use-remote-participant-ids" } from './hooks/use-remote-participant-ids.json';
|
|
12
|
+
export { default as "use-replica-ids" } from './hooks/use-replica-ids.json';
|
|
13
|
+
export { default as "use-request-permissions" } from './hooks/use-request-permissions.json';
|
|
14
|
+
export { default as "use-start-haircheck" } from './hooks/use-start-haircheck.json';
|
|
@@ -1,7 +1,57 @@
|
|
|
1
1
|
import * as templates from '../templates';
|
|
2
|
+
import { removeVersionSuffix, getDefaultVersion } from './version-utils';
|
|
2
3
|
|
|
3
4
|
type ComponentKey = keyof typeof templates.tsx;
|
|
4
5
|
|
|
6
|
+
// Helper function to find component template by name (with or without version)
|
|
7
|
+
function findComponentTemplate(name: string) {
|
|
8
|
+
// First try exact match
|
|
9
|
+
let component = templates.tsx[name as ComponentKey];
|
|
10
|
+
|
|
11
|
+
if (!component) {
|
|
12
|
+
// If no exact match, try without version suffix
|
|
13
|
+
const nameWithoutVersion = removeVersionSuffix(name);
|
|
14
|
+
const defaultVersion = getDefaultVersion(nameWithoutVersion);
|
|
15
|
+
component = templates.tsx[defaultVersion as ComponentKey];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return component;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Helper function to deduplicate components by selecting the latest version
|
|
22
|
+
function deduplicateComponents(components: string[]): string[] {
|
|
23
|
+
const componentGroups = new Map<string, string[]>();
|
|
24
|
+
|
|
25
|
+
// Group components by their base name (without version)
|
|
26
|
+
components.forEach(componentName => {
|
|
27
|
+
const baseName = removeVersionSuffix(componentName);
|
|
28
|
+
if (!componentGroups.has(baseName)) {
|
|
29
|
+
componentGroups.set(baseName, []);
|
|
30
|
+
}
|
|
31
|
+
componentGroups.get(baseName)!.push(componentName);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// For each group, select the component with the highest version number
|
|
35
|
+
const deduplicatedComponents: string[] = [];
|
|
36
|
+
|
|
37
|
+
componentGroups.forEach((componentVersions) => {
|
|
38
|
+
if (componentVersions.length === 1) {
|
|
39
|
+
// Only one version, use it as is
|
|
40
|
+
deduplicatedComponents.push(componentVersions[0]);
|
|
41
|
+
} else {
|
|
42
|
+
// Multiple versions, select the one with the highest version number
|
|
43
|
+
const latestVersion = componentVersions.reduce((latest, current) => {
|
|
44
|
+
const latestVersionNum = parseInt(latest.match(/-(\d+)$/)?.[1] || '0');
|
|
45
|
+
const currentVersionNum = parseInt(current.match(/-(\d+)$/)?.[1] || '0');
|
|
46
|
+
return currentVersionNum > latestVersionNum ? current : latest;
|
|
47
|
+
});
|
|
48
|
+
deduplicatedComponents.push(latestVersion);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return deduplicatedComponents;
|
|
53
|
+
}
|
|
54
|
+
|
|
5
55
|
export function resolveComponentsTree(components: string[]) {
|
|
6
56
|
// npm libraries which should be added to the project
|
|
7
57
|
const dependencies = new Set<string>();
|
|
@@ -10,7 +60,7 @@ export function resolveComponentsTree(components: string[]) {
|
|
|
10
60
|
|
|
11
61
|
// Process each component and its dependencies recursively
|
|
12
62
|
function processComponent(componentName: string) {
|
|
13
|
-
const component =
|
|
63
|
+
const component = findComponentTemplate(componentName);
|
|
14
64
|
if (!component) return;
|
|
15
65
|
|
|
16
66
|
// Add component's dependencies
|
|
@@ -23,8 +73,15 @@ export function resolveComponentsTree(components: string[]) {
|
|
|
23
73
|
});
|
|
24
74
|
}
|
|
25
75
|
|
|
76
|
+
// Deduplicate components before processing
|
|
77
|
+
const uniqueComponents = deduplicateComponents(components);
|
|
78
|
+
|
|
79
|
+
// Update componentsDependencies with deduplicated list
|
|
80
|
+
componentsDependencies.clear();
|
|
81
|
+
uniqueComponents.forEach(component => componentsDependencies.add(component));
|
|
82
|
+
|
|
26
83
|
// Process all requested components
|
|
27
|
-
|
|
84
|
+
uniqueComponents.forEach((componentName) => {
|
|
28
85
|
processComponent(componentName);
|
|
29
86
|
});
|
|
30
87
|
|
|
@@ -8,9 +8,30 @@ import { spinner } from '@/src/components/spinner';
|
|
|
8
8
|
import prompts from 'prompts';
|
|
9
9
|
import * as templates from '../templates';
|
|
10
10
|
import { components as COMPONENTS } from '../templates/components';
|
|
11
|
+
import { removeVersionSuffix, getDefaultVersion } from './version-utils';
|
|
11
12
|
|
|
12
13
|
type ComponentKey = keyof typeof templates.tsx;
|
|
13
14
|
|
|
15
|
+
// Helper function to find component by name (with or without version)
|
|
16
|
+
function findComponentByName(name: string) {
|
|
17
|
+
// First try exact match
|
|
18
|
+
let component = COMPONENTS.find((comp) => comp.name === name);
|
|
19
|
+
|
|
20
|
+
if (!component) {
|
|
21
|
+
// If no exact match, try without version suffix
|
|
22
|
+
const nameWithoutVersion = removeVersionSuffix(name);
|
|
23
|
+
component = COMPONENTS.find((comp) => removeVersionSuffix(comp.name) === nameWithoutVersion);
|
|
24
|
+
|
|
25
|
+
if (component) {
|
|
26
|
+
// If found by versionless name, use the default version
|
|
27
|
+
const defaultVersion = getDefaultVersion(nameWithoutVersion);
|
|
28
|
+
component = COMPONENTS.find((comp) => comp.name === defaultVersion) || component;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return component;
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
export async function updateFiles(
|
|
15
36
|
files: string[],
|
|
16
37
|
config: Config,
|
|
@@ -50,31 +71,38 @@ export async function updateFiles(
|
|
|
50
71
|
const filesSkipped = [];
|
|
51
72
|
|
|
52
73
|
for (const filename of files) {
|
|
53
|
-
const
|
|
54
|
-
if (!
|
|
74
|
+
const component = findComponentByName(filename);
|
|
75
|
+
if (!component) {
|
|
55
76
|
logger.warn(`Component ${filename} not found`);
|
|
56
77
|
continue;
|
|
57
78
|
}
|
|
58
79
|
|
|
80
|
+
// Use the actual component name from the found component
|
|
81
|
+
const actualComponentName = component.name;
|
|
82
|
+
const componentBasePath = component.path;
|
|
83
|
+
|
|
84
|
+
// For file creation, use versionless name
|
|
85
|
+
const fileDisplayName = removeVersionSuffix(actualComponentName);
|
|
86
|
+
|
|
59
87
|
let targetPath: string;
|
|
60
88
|
let targetDir: string;
|
|
61
89
|
|
|
62
90
|
// Handle different component types based on path structure
|
|
63
91
|
if (componentBasePath.startsWith('components/')) {
|
|
64
|
-
// For components: create folder with filename and index file inside
|
|
65
|
-
targetDir = path.join(config.resolvedPaths.cwd, componentsPath,
|
|
92
|
+
// For components: create folder with versionless filename and index file inside
|
|
93
|
+
targetDir = path.join(config.resolvedPaths.cwd, componentsPath, 'components', fileDisplayName);
|
|
66
94
|
targetPath = path.join(targetDir, `index.${config.tsx ? 'tsx' : 'jsx'}`);
|
|
67
95
|
} else if (componentBasePath.startsWith('hooks/')) {
|
|
68
96
|
// For hooks: create direct filename.tsx file
|
|
69
97
|
targetDir = path.join(config.resolvedPaths.cwd, componentsPath, 'hooks');
|
|
70
|
-
targetPath = path.join(targetDir, `${
|
|
98
|
+
targetPath = path.join(targetDir, `${fileDisplayName}.${config.tsx ? 'tsx' : 'jsx'}`);
|
|
71
99
|
} else {
|
|
72
100
|
// Fallback to original logic for other cases
|
|
73
101
|
targetPath = path.join(
|
|
74
102
|
config.resolvedPaths.cwd,
|
|
75
103
|
componentsPath,
|
|
76
104
|
componentBasePath,
|
|
77
|
-
`${
|
|
105
|
+
`${fileDisplayName}.${config.tsx ? 'tsx' : 'jsx'}`
|
|
78
106
|
);
|
|
79
107
|
targetDir = path.dirname(targetPath);
|
|
80
108
|
}
|
|
@@ -90,7 +118,7 @@ export async function updateFiles(
|
|
|
90
118
|
type: 'confirm',
|
|
91
119
|
name: 'overwrite',
|
|
92
120
|
message: `The file ${highlighter.info(
|
|
93
|
-
|
|
121
|
+
fileDisplayName
|
|
94
122
|
)} already exists. Would you like to overwrite?`,
|
|
95
123
|
initial: false,
|
|
96
124
|
});
|
|
@@ -118,7 +146,7 @@ export async function updateFiles(
|
|
|
118
146
|
styles?: string;
|
|
119
147
|
dependencies?: string[];
|
|
120
148
|
componentsDependencies?: string[];
|
|
121
|
-
} = templates[config.tsx ? 'tsx' : 'jsx'][
|
|
149
|
+
} = templates[config.tsx ? 'tsx' : 'jsx'][actualComponentName as ComponentKey];
|
|
122
150
|
// Write the content from templates
|
|
123
151
|
if (template) {
|
|
124
152
|
let content = template.content;
|
|
@@ -134,13 +162,13 @@ export async function updateFiles(
|
|
|
134
162
|
await fs.writeFile(targetPath, content);
|
|
135
163
|
if (template.styles && template.styles.length > 0) {
|
|
136
164
|
// For components, create CSS file in the same directory as the index file
|
|
137
|
-
const cssPath = path.join(targetDir, `${
|
|
165
|
+
const cssPath = path.join(targetDir, `${fileDisplayName}.module.css`);
|
|
138
166
|
await fs.writeFile(cssPath, template.styles);
|
|
139
167
|
}
|
|
140
168
|
} else {
|
|
141
169
|
// For other components, we'll need to handle them differently
|
|
142
170
|
// This part needs to be implemented based on how other components are structured
|
|
143
|
-
logger.warn(`Component ${
|
|
171
|
+
logger.warn(`Component ${actualComponentName} is not yet implemented`);
|
|
144
172
|
continue;
|
|
145
173
|
}
|
|
146
174
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Helper function to remove version suffix from component name
|
|
2
|
+
export function removeVersionSuffix(name: string): string {
|
|
3
|
+
return name.replace(/-\d+$/, '');
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Helper function to get the default version for a component
|
|
7
|
+
export function getDefaultVersion(name: string): string {
|
|
8
|
+
// Map versionless names to their default versions
|
|
9
|
+
const versionMap: Record<string, string> = {
|
|
10
|
+
'conversation': 'conversation-01',
|
|
11
|
+
'hair-check': 'hair-check-01',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return versionMap[name] || name;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Helper function to map user input to actual component names
|
|
18
|
+
export function mapUserInputToComponentName(userInput: string): string {
|
|
19
|
+
// If user input has a version, use it as is
|
|
20
|
+
if (userInput.match(/-\d+$/)) {
|
|
21
|
+
return userInput;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Otherwise, map to default version
|
|
25
|
+
return getDefaultVersion(userInput);
|
|
26
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dev-components/hooks/{use-remote-participant-ids.ts → use-remote-participant-ids.tsx}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|