@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.
Files changed (59) hide show
  1. package/README.md +44 -33
  2. package/dev-components/components/README.md +62 -1
  3. package/dev-components/components/audio-wave/audio-wave.module.css +33 -0
  4. package/dev-components/components/audio-wave/index.tsx +55 -0
  5. package/dev-components/components/controls/controls.module.css +75 -73
  6. package/dev-components/components/controls/index.tsx +2 -2
  7. package/dev-components/components/conversation-01/conversation.module.css +222 -0
  8. package/dev-components/components/conversation-01/index.tsx +180 -0
  9. package/dev-components/components/{hair-check → hair-check-01}/hair-check.module.css +2 -1
  10. package/dev-components/components/{hair-check → hair-check-01}/index.tsx +1 -1
  11. package/dist/index.js +412 -104
  12. package/dist/types/templates/components.d.ts +32 -2
  13. package/dist/types/templates/jsx/index.d.ts +11 -1
  14. package/dist/types/templates/tsx/index.d.ts +11 -1
  15. package/dist/types/utils/version-utils.d.ts +3 -0
  16. package/package.json +6 -4
  17. package/src/templates/components.ts +18 -0
  18. package/src/templates/index.ts +2 -0
  19. package/src/templates/jsx/components/audio-wave.json +5 -0
  20. package/src/templates/jsx/components/controls.json +10 -0
  21. package/src/templates/jsx/components/conversation-01.json +11 -0
  22. package/src/templates/jsx/components/cvi-provider.json +5 -0
  23. package/src/templates/jsx/components/hair-check-01.json +10 -0
  24. package/src/templates/jsx/hooks/cvi-events-hooks.json +5 -0
  25. package/src/templates/jsx/hooks/use-cvi-call.json +5 -0
  26. package/src/templates/jsx/hooks/use-local-camera.json +5 -0
  27. package/src/templates/jsx/hooks/use-local-microphone.json +5 -0
  28. package/src/templates/jsx/hooks/use-local-screenshare.json +5 -0
  29. package/src/templates/jsx/hooks/use-remote-participant-ids.json +5 -0
  30. package/src/templates/jsx/hooks/use-replica-ids.json +5 -0
  31. package/src/templates/jsx/hooks/use-request-permissions.json +5 -0
  32. package/src/templates/jsx/hooks/use-start-haircheck.json +5 -0
  33. package/src/templates/jsx/index.ts +14 -0
  34. package/src/templates/tsx/components/audio-wave.json +5 -0
  35. package/src/templates/tsx/components/controls.json +10 -0
  36. package/src/templates/tsx/components/conversation-01.json +11 -0
  37. package/src/templates/tsx/components/cvi-provider.json +5 -0
  38. package/src/templates/tsx/components/hair-check-01.json +10 -0
  39. package/src/templates/tsx/hooks/cvi-events-hooks.json +5 -0
  40. package/src/templates/tsx/hooks/use-cvi-call.json +5 -0
  41. package/src/templates/tsx/hooks/use-local-camera.json +5 -0
  42. package/src/templates/tsx/hooks/use-local-microphone.json +5 -0
  43. package/src/templates/tsx/hooks/use-local-screenshare.json +5 -0
  44. package/src/templates/tsx/hooks/use-remote-participant-ids.json +5 -0
  45. package/src/templates/tsx/hooks/use-replica-ids.json +5 -0
  46. package/src/templates/tsx/hooks/use-request-permissions.json +8 -0
  47. package/src/templates/tsx/hooks/use-start-haircheck.json +5 -0
  48. package/src/templates/tsx/index.ts +14 -0
  49. package/src/utils/resolve-components-tree.ts +59 -2
  50. package/src/utils/update-files.ts +38 -10
  51. package/src/utils/version-utils.ts +26 -0
  52. /package/dev-components/hooks/{use-cvi-call.ts → use-cvi-call.tsx} +0 -0
  53. /package/dev-components/hooks/{use-local-camera.ts → use-local-camera.tsx} +0 -0
  54. /package/dev-components/hooks/{use-local-microphone.ts → use-local-microphone.tsx} +0 -0
  55. /package/dev-components/hooks/{use-local-screenshare.ts → use-local-screenshare.tsx} +0 -0
  56. /package/dev-components/hooks/{use-remote-participant-ids.ts → use-remote-participant-ids.tsx} +0 -0
  57. /package/dev-components/hooks/{use-replica-ids.ts → use-replica-ids.tsx} +0 -0
  58. /package/dev-components/hooks/{use-request-permissions.ts → use-request-permissions.tsx} +0 -0
  59. /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 = templates.tsx[componentName as ComponentKey];
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
- components.forEach((componentName) => {
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 componentBasePath = COMPONENTS.find((component) => component.name === filename)?.path;
54
- if (!componentBasePath) {
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, componentBasePath);
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, `${filename}.${config.tsx ? 'tsx' : 'jsx'}`);
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
- `${filename}.${config.tsx ? 'tsx' : 'jsx'}`
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
- filename
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'][filename as ComponentKey];
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, `${filename}.module.css`);
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 ${filename} is not yet implemented`);
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
+ }