Skip to content

Commit ed4e28f

Browse files
first commit
0 parents  commit ed4e28f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+20727
-0
lines changed

.gitignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

.prettierrc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"semi": false,
3+
"singleQuote": true,
4+
"jsxSingleQuote": true
5+
}

.storybook/main.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const { mergeConfig } = require('vite')
2+
const path = require('path')
3+
4+
module.exports = {
5+
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
6+
addons: [
7+
'@storybook/addon-links',
8+
'@storybook/addon-essentials',
9+
'@storybook/addon-interactions',
10+
'@storybook/theming',
11+
],
12+
framework: '@storybook/react',
13+
core: {
14+
builder: '@storybook/builder-vite',
15+
},
16+
features: {
17+
storyStoreV7: true,
18+
},
19+
/* async viteFinal(config) {
20+
const { config: userConfig } = await loadConfigFromFile(
21+
path.resolve(__dirname, '../vite.config.ts')
22+
)
23+
24+
return mergeConfig(config, {
25+
...userConfig,
26+
})
27+
}, */
28+
async viteFinal(config) {
29+
return mergeConfig(config, {
30+
css: {
31+
preprocessorOptions: {
32+
scss: {
33+
additionalData: `@import "../src/styles/_index.scss";`,
34+
},
35+
},
36+
},
37+
resolve: {
38+
alias: {
39+
'@': path.resolve(__dirname, './src'),
40+
},
41+
},
42+
})
43+
},
44+
}

.storybook/manager.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { addons } from '@storybook/addons'
2+
import { themes } from '@storybook/theming'
3+
4+
addons.setConfig({
5+
theme: themes.dark,
6+
})

.storybook/preview-head.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
window.global = window;
3+
</script>

.storybook/preview.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { themes } from '@storybook/theming'
2+
import '../src/index.scss'
3+
4+
export const parameters = {
5+
actions: { argTypesRegex: '^on[A-Z].*' },
6+
controls: {
7+
matchers: {
8+
color: /(background|color)$/i,
9+
date: /Date$/,
10+
},
11+
docs: {
12+
theme: themes.dark,
13+
},
14+
},
15+
}

README.md

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Talk to Me
2+
3+
Talk to Me is an application that allows the user to talk/text to a customizable avatar. It was developed with Speech recognition API, TypeScript, React and SCSS modules.
4+
5+
The interaction can occur in two ways:
6+
1. By clicking in the avatar and talk;
7+
2. By switching to text mode and text the input;
8+
9+
Note: SpeechRecognition API is only available in some browsers. Check [here](https://caniuse.com/speech-recognition) browser compatibility.
10+
11+
## Get Start
12+
13+
You can customize the conversation, by defining your own object of input/output and passing it as a `conversation` as a prop. This `conversation` object must follow the structure below, and you can check `conversation.example.ts` file as an example.
14+
15+
```js
16+
const conversation = [
17+
{
18+
inputs: string[]
19+
inputKeywords: string[] // keywords mandatory in the input, to reproduce the corresponding output
20+
output: string
21+
},
22+
{ ... },
23+
]
24+
```
25+
26+
The avatar shown in this project is an example created at [SVG Avatars](https://svgavatars.com/). You can create your own avatar, converted into a React component and add the SCSS classes needed for the SVG animations in the corresponding SVG elements, as shown in the template avatar.
27+
28+
`TalkToMe`component can be used as described in the example below:
29+
30+
```jsx
31+
const Component = () => {
32+
return (
33+
<h1>
34+
<h1>Click and talk to me</h1>
35+
<TalkToMe
36+
conversation={conversation}
37+
onStopTalking={smile}
38+
avatarProps={avatarProps}
39+
onTyping={smile}
40+
onUnmatchedOutput={onUnmatchedOutput}
41+
/>
42+
</>
43+
)
44+
}
45+
```
46+
47+
You can further customize your component by passing the props listed below:
48+
| Prop name | Type | Description | Default |
49+
|----------|:-------------|------:|-------:|
50+
| conversation | Dialogue[] | Array of dialogues to be used in the conversation with the avatar | - |
51+
| avatarProps | AvatarProps | Props to be passed to the SVG avatar | - |
52+
| avatar* | () => JSX.Element | React Component with the custom SVG | - |
53+
| defaultOutput* | string | Sentence that is spoken/written when no matching output is found for the inserted input. | _I didn't understand!_ |
54+
| lang* | string | Code of the language used for input/output speech | en |
55+
| preferredVoiceName* | string | Name of a specific SpeechRecognition API voice to be configured for the avatar | the default value in the chosen browser |
56+
| voiceGender* | string | Gender of the voice to be configured for the avatar. Can take the values "male" or "female". | - |
57+
| additionalClass* | string | css class name to apply to the TalkToMe component. | - |
58+
| avatarAdditionalClass* | string | css class name to apply to the Avatar. | - |
59+
| textChatPlaceholder* | string | Placeholder to display in the text input component. | _Type your question here_ |
60+
| activateSpeech* | boolean | Enables/Disable speech functionality | true |
61+
| activateTextChat* | boolean | Enables/Disable text chat functionality | true |
62+
| onUnmatchedOutput* | () => Promise<void> | void | Function to be executed when no matching input was found for the provided output | - |
63+
| onTyping* | () => void | Function to be executed while the output text is being typed | - |
64+
| onStopTalking* | () => void | Function to be executed when the output speech is finished | - |
65+
| onNoSpeechRecognitionSupport* | () => void | Function to be executed when the browser does not support SpeechRecognition API | - |
66+
67+
\*optional
68+
69+
```js
70+
interface AvatarProps {
71+
breathing?: boolean
72+
talking?: boolean
73+
smiling?: boolean
74+
pouting?: boolean
75+
blinking?: boolean
76+
rollingEyes?: boolean
77+
lookingUp?: boolean
78+
leftEyeWink?: boolean
79+
rightEyeWink?: boolean
80+
liftLeftEyebrow?: boolean
81+
liftRightEyebrow?: boolean
82+
width?: number
83+
height?: number
84+
additionalClass?: string
85+
}
86+
87+
export interface Dialogue {
88+
inputs: string[]
89+
inputKeywords: string[]
90+
}
91+
```
92+
93+
## Available Scripts
94+
95+
### `yarn install`
96+
97+
Installs all the dependencies required to run and develop this application.
98+
99+
### `yarn dev`
100+
101+
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
102+
103+
### `yarn build`
104+
105+
Build a production-ready application.
106+
107+
### `yarn preview`
108+
109+
Runs the production build locally
110+
111+
### `yarn storybook`
112+
113+
Runs storybook design system
114+
Open [http://localhost:6006](http://localhost:6006) to view it in the browser.
115+
116+
### `yarn test:unit`
117+
118+
Launches the test runner in the interactive watch mode.\
119+
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
120+
121+
### `yarn test:unit-coverage`
122+
123+
Launches the test runner in the interactive watch mode and shows tets coverage report.

__mocks__/file-mock.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const fileMock = 'test-file-stub';
2+
export default fileMock;

index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Vite + React + TS</title>
7+
</head>
8+
<body>
9+
<div id="root"></div>
10+
<script type="module" src="/src/main.tsx"></script>
11+
</body>
12+
</html>

package.json

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"name": "@marianapatcosta/talk-to-me",
3+
"author": "Mariana Costa",
4+
"private": true,
5+
"description": "Talk to Me is an application that allows the user to talk/text to a customizable avatar",
6+
"version": "0.0.0",
7+
"license": "MIT",
8+
"repository": {
9+
"type": "git",
10+
"url": "git+https://github.com/marianapatcosta/talk-to-me.git"
11+
},
12+
"homepage": "https://github.com/marianapatcosta/talk-to-me#readme",
13+
"bugs": {
14+
"url": "https://github.com/marianapatcosta/talk-to-me/issues"
15+
},
16+
"files": [
17+
"dist",
18+
"README.md"
19+
],
20+
"main": "dist/talk-to-me.umd.js",
21+
"unpkg": "dist/talk-to-me.iife.js",
22+
"jsdelivr": "dist/talk-to-me.iife.js",
23+
"module": "./dist/talk-to-me.es.js",
24+
"exports": {
25+
".": {
26+
"import": "./dist/talk-to-me.es.js",
27+
"require": "./dist/talk-to-me.umd.js"
28+
}
29+
},
30+
"types": "./dist/types/index.d.ts",
31+
"scripts": {
32+
"dev": "vite",
33+
"build": "vite build && tsc",
34+
"preview": "vite preview",
35+
"test:unit": "jest --env=jsdom",
36+
"test:unit-coverage": "jest --watchAll --env=jsdom --coverage",
37+
"storybook": "start-storybook -p 6006"
38+
},
39+
"dependencies": {
40+
"react": "^18.2.0",
41+
"react-dom": "^18.2.0"
42+
},
43+
"devDependencies": {
44+
"@babel/core": "^7.20.2",
45+
"@babel/preset-env": "^7.20.2",
46+
"@babel/preset-react": "^7.18.6",
47+
"@babel/preset-typescript": "^7.18.6",
48+
"@storybook/addon-actions": "^6.5.13",
49+
"@storybook/addon-essentials": "^6.5.13",
50+
"@storybook/addon-interactions": "^6.5.13",
51+
"@storybook/addon-links": "^6.5.13",
52+
"@storybook/addons": "^6.5.13",
53+
"@storybook/builder-vite": "^0.2.5",
54+
"@storybook/jest": "^0.0.10",
55+
"@storybook/react": "^6.5.13",
56+
"@storybook/testing-library": "^0.0.13",
57+
"@storybook/testing-react": "^1.3.0",
58+
"@storybook/theming": "^6.5.13",
59+
"@testing-library/jest-dom": "^5.16.5",
60+
"@testing-library/react": "^13.4.0",
61+
"@testing-library/user-event": "^14.4.3",
62+
"@types/babel__core": "^7.1.20",
63+
"@types/babel__generator": "^7.6.4",
64+
"@types/jest": "^29.2.2",
65+
"@types/node": "^18.11.9",
66+
"@types/react": "^18.0.24",
67+
"@types/react-dom": "^18.0.8",
68+
"@types/webspeechapi": "^0.0.29",
69+
"@vitejs/plugin-react": "^2.2.0",
70+
"babel-loader": "^8.3.0",
71+
"eslint": "^8.27.0",
72+
"eslint-config-react-app": "^7.0.1",
73+
"identity-obj-proxy": "^3.0.0",
74+
"jest": "^29.3.1",
75+
"jest-environment-jsdom": "^29.3.1",
76+
"jsdom": "^20.0.2",
77+
"sass": "^1.56.1",
78+
"ts-jest": "^29.0.3",
79+
"ts-node": "^10.9.1",
80+
"typescript": "^4.6.4",
81+
"vite": "^3.2.3"
82+
},
83+
"eslintConfig": {
84+
"extends": [
85+
"react-app",
86+
"react-app/jest"
87+
]
88+
},
89+
"jest": {
90+
"preset": "ts-jest",
91+
"collectCoverage": true,
92+
"collectCoverageFrom": [
93+
"src/**/*.ts",
94+
"src/**/*.tsx",
95+
"!src/**/*.stories.tsx",
96+
"!src/main.tsx",
97+
"!src/types.ts",
98+
"!src/assets/**/.tsx",
99+
"!src/assets/**/.ts"
100+
],
101+
"coverageReporters": [
102+
"text"
103+
],
104+
"moduleNameMapper": {
105+
"^@/(.+)": "<rootDir>/src/$1",
106+
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
107+
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/file-mock.ts"
108+
},
109+
"transform": {
110+
"^.+\\.ts?$": "ts-jest"
111+
},
112+
"roots": [
113+
"<rootDir>/src"
114+
],
115+
"testMatch": [
116+
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
117+
],
118+
"setupFilesAfterEnv": [
119+
"<rootDir>/test-env-setup.ts"
120+
]
121+
}
122+
}

0 commit comments

Comments
 (0)