diff --git a/CHANGELOG.md b/CHANGELOG.md index 06794c77cc..22346a0dd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Resolves [#3777](https://github.com/microsoft/BotFramework-WebChat/issues/3777). Added a new `adaptiveCardsParserMaxVersion` style options for selecting the maximum supported version when parsing an Adaptive Cards, by [@compulim](https://github.com/compulim) in PR [#3778](https://github.com/microsoft/BotFramework-WebChat/pull/3778) +- Resolves [#2100](https://github.com/microsoft/BotFramework-WebChat/issues/2100). Add types declarations for Style Options in api bundle, by [@corinagum](https://github.com/corinagum), in PR [#3818](https://github.com/microsoft/BotFramework-WebChat/pull/3818) ### Fixed diff --git a/__tests__/.eslintrc b/__tests__/.eslintrc index 01dcb648fd..e879ad0fb7 100644 --- a/__tests__/.eslintrc +++ b/__tests__/.eslintrc @@ -2,5 +2,7 @@ globals: runHTMLTest: readonly ignorePatterns: - "**/*.js" +- "**/*.ts" +- "**/*.tsx" - "!/html/__jest__/*.js" - "!/setup/*.js" diff --git a/__tests__/adaptiveCards.js b/__tests__/adaptiveCards.js index a6f0f1a794..38ffb3c30d 100644 --- a/__tests__/adaptiveCards.js +++ b/__tests__/adaptiveCards.js @@ -7,7 +7,6 @@ import scrollToBottomCompleted from './setup/conditions/scrollToBottomCompleted' import uiConnected from './setup/conditions/uiConnected'; import createAdaptiveCardsHostConfig from '../packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig'; -import defaultStyleOptions from '../packages/component/src/Styles/defaultStyleOptions'; // selenium-webdriver API doc: // https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html @@ -57,7 +56,7 @@ test('action styles', async () => { }); test('breakfast card with custom host config', async () => { - const adaptiveCardHostConfig = createAdaptiveCardsHostConfig({ ...defaultStyleOptions, bubbleTextColor: '#FF0000' }); + const adaptiveCardHostConfig = createAdaptiveCardsHostConfig({ bubbleTextColor: '#FF0000' }); const { driver, pageObjects } = await setupWebDriver({ props: { @@ -179,7 +178,7 @@ test('Inputs card with custom style options and submit action', async () => { props: { styleOptions: { cardPushButtonBackgroundColor: '#ee0606', - cardPushButtonTextColor:'#ee0606' + cardPushButtonTextColor: '#ee0606' } } }); diff --git a/__tests__/types/__typescript__/.gitignore b/__tests__/types/__typescript__/.gitignore new file mode 100644 index 0000000000..c981789ba1 --- /dev/null +++ b/__tests__/types/__typescript__/.gitignore @@ -0,0 +1,4 @@ +dirNumber.js +dirString.js +styleOptionsAccent.js +styleOptionsCardEmph.js \ No newline at end of file diff --git a/__tests__/types/__typescript__/dirNumber.tsx b/__tests__/types/__typescript__/dirNumber.tsx new file mode 100644 index 0000000000..1f867e3ba3 --- /dev/null +++ b/__tests__/types/__typescript__/dirNumber.tsx @@ -0,0 +1,10 @@ +import ReactWebChat, { createStyleSet, StyleOptions } from '../../../packages/bundle/lib/index'; + +function main() { + const styleOptions: StyleOptions = { accent: 'black', cardEmphasisBackgroundColor: 'orange' }; + + createStyleSet(styleOptions); + + // "dir" of type number should fail + return ; +} diff --git a/__tests__/types/__typescript__/dirString.tsx b/__tests__/types/__typescript__/dirString.tsx new file mode 100644 index 0000000000..cd7e894833 --- /dev/null +++ b/__tests__/types/__typescript__/dirString.tsx @@ -0,0 +1,10 @@ +import ReactWebChat, { createStyleSet, StyleOptions } from '../../../packages/bundle/lib/index'; + +function main() { + const styleOptions: StyleOptions = { accent: 'black', cardEmphasisBackgroundColor: 'orange' }; + + createStyleSet(styleOptions); + + // Verify: "dir" of type string should pass + return ; +} diff --git a/__tests__/types/__typescript__/styleOptionsAccent.tsx b/__tests__/types/__typescript__/styleOptionsAccent.tsx new file mode 100644 index 0000000000..5c88b8480f --- /dev/null +++ b/__tests__/types/__typescript__/styleOptionsAccent.tsx @@ -0,0 +1,10 @@ +import ReactWebChat, { createStyleSet, StyleOptions } from '../../../packages/bundle/lib/index-minimal'; + +function main() { + const styleOptions: StyleOptions = { accent: 'black' }; + + createStyleSet(styleOptions); + + // Verify: Setting "accent" must should pass. + return ; +} diff --git a/__tests__/types/__typescript__/styleOptionsCardEmph.tsx b/__tests__/types/__typescript__/styleOptionsCardEmph.tsx new file mode 100644 index 0000000000..2d20c3f1f7 --- /dev/null +++ b/__tests__/types/__typescript__/styleOptionsCardEmph.tsx @@ -0,0 +1,10 @@ +import ReactWebChat, { createStyleSet, StyleOptions } from '../../../packages/bundle/lib/index-minimal'; + +function main() { + const styleOptions: StyleOptions = { cardEmphasisBackgroundColor: 'orange' }; + + createStyleSet(styleOptions); + + // Verify: Setting "cardEmphasisBackgroundColor" using minimal bundle must fail. + return ; +} diff --git a/__tests__/types/typesCheck.js b/__tests__/types/typesCheck.js new file mode 100644 index 0000000000..da708ee51b --- /dev/null +++ b/__tests__/types/typesCheck.js @@ -0,0 +1,54 @@ +const ts = require('typescript'); +const path = require('path'); + +function compile(...filenames) { + const program = ts.createProgram(filenames, { + allowSyntheticDefaultImports: true, + jsx: 'react', + noEmit: true, + skipLibCheck: true, + }); + + const emitResult = program.emit(); + const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + const errors = []; + + allDiagnostics.forEach(diagnostic => { + if (diagnostic.file) { + const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); + const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + errors.push(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); + } else { + errors.push(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')); + } + }); + + return errors; +}; + + +it('should pass dir as string', () => { + const dirStringErrors = compile(path.join(__dirname, './__typescript__/dirString.tsx')); + + expect(dirStringErrors).toHaveProperty('length', 0); +}); + +it('should fail on dir as number', () => { + const dirNumErrors = compile(path.join(__dirname, './__typescript__/dirNumber.tsx')); + + expect(dirNumErrors).toHaveProperty('length', 1); + expect(dirNumErrors[0]).toEqual(expect.stringContaining(`Type 'number' is not assignable to type '"ltr" | "rtl" | "auto"'`)); +}); + +it('should fail on accent', () => { + const accentErrors = compile(path.join(__dirname, './__typescript__/styleOptionsAccent.tsx')); + + expect(accentErrors).toHaveProperty('length', 0); +}); + +it('should pass on cardEmphasisBackgroundColor', () => { + const cardEmphErrors = compile(path.join(__dirname, './__typescript__/styleOptionsCardEmph.tsx')); + + expect(cardEmphErrors).toHaveProperty('length', 1); + expect(cardEmphErrors[0]).toEqual(expect.stringContaining(`Type '{ cardEmphasisBackgroundColor: string; }' is not assignable to type 'StyleOptions'`)); +}); diff --git a/docs/API.md b/docs/API.md index 74dc87058c..f2ab416be4 100644 --- a/docs/API.md +++ b/docs/API.md @@ -20,7 +20,7 @@ There are several properties that you might pass into your Web Chat React Compon | `renderMarkdown` | Change the default Markdown renderer object. | | `sendTypingIndicator` | Display a typing signal from the user to the bot to indicate that the user is not idling. | | `store` | Specify a custom store, e.g. for adding programmatic activity to the bot. | -| `styleOptions` | Object that stores customization values for your styling of Web Chat. For the complete list of (frequently updated) default style options, please see the [defaultStyleOptions.js](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/component/src/Styles/defaultStyleOptions.js) file. | +| `styleOptions` | Object that stores customization values for your styling of Web Chat. For the complete list of (frequently updated) default style options, please see the [defaultStyleOptions.ts](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/api/src/defaultStyleOptions.ts) and [adaptiveCards/defaultStyleOptions.ts](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/bundle/src/adaptiveCards/defaultStyleOptions.ts) file. | | `styleSet` | The non-recommended way of overriding styles. | | `userID` | Specify a userID. There are two ways to specify the `userID`: in props, or in the token when generating the token call (`createDirectLine()`). If both methods are used to specify the userID, the token userID property will be used, and a `console.warn` will appear during runtime. If the `userID` is provided via props but is prefixed with `'dl'`, e.g. `'dl_1234'`, the value will be thrown and a new `ID` generated. If `userID` is not specified, it will default to a random user ID. Multiple users sharing the same user ID is not recommended; their user state will be shared, which creates a security risk when authenticating. | | `username` | Specify a username. | diff --git a/docs/HOOKS.md b/docs/HOOKS.md index 016489b778..3f94cc524e 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -1131,7 +1131,7 @@ useStyleOptions(): [StyleOptions] This hook will return the style options. UI components should honor the styling preferences. -The value is not the same as the props. Web Chat will merge the style options passed in props with default values specified in [`defaultStyleOptions.js`](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/component/src/Styles/defaultStyleOptions.js). +The value is not the same as the props. Web Chat will merge the style options passed in props with default values specified in [`defaultStyleOptions.ts`](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/api/src/defaultStyleOptions.ts) and [`adaptiveCards/defaultStyleOptions.ts`](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/bundle/src/adaptiveCards/defaultStyleOptions.ts) when Adaptive Cards is enabled. To modify the value of `styleOptions` state, change the props you pass to Web Chat. diff --git a/jest.config.js b/jest.config.js index 5eab9506d8..4aeabd93ac 100644 --- a/jest.config.js +++ b/jest.config.js @@ -76,6 +76,7 @@ module.exports = { '/__tests__/html/assets', '/__tests__/html/__dist__', '/__tests__/html/__jest__', + '/__tests__/types/__typescript__', '/__tests__/setup/', '/packages/directlinespeech/__tests__/utilities/', '/packages/playground/', diff --git a/package-lock.json b/package-lock.json index 3da5daf530..6526aff9cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13697,6 +13697,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "dev": true + }, "uglify-js": { "version": "3.11.5", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.5.tgz", diff --git a/package.json b/package.json index cd52430491..e663f82ff8 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "serve": "^11.3.2", "serve-handler": "^6.1.3", "strip-ansi": "^6.0.0", + "typescript": "^4.2.3", "xmlbuilder": "^15.1.1" }, "dependencies": {} diff --git a/packages/api/.eslintrc.yml b/packages/api/.eslintrc.yml index 3d1c9cc36d..1046d75635 100644 --- a/packages/api/.eslintrc.yml +++ b/packages/api/.eslintrc.yml @@ -3,6 +3,9 @@ extends: plugins: - prettier - react-hooks +- '@typescript-eslint/eslint-plugin' +parser: + '@typescript-eslint/parser' rules: # plugins prettier/prettier: error @@ -89,3 +92,11 @@ rules: react/jsx-wrap-multilines: error # Conflict with no-extra-parens react-hooks/rules-of-hooks: error react-hooks/exhaustive-deps: warn + + # TypeScript + + # The correct way to use with typescript-eslint is to disable the core version. + # https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md#how-to-use + no-use-before-define: off + '@typescript-eslint/no-use-before-define': + - error diff --git a/packages/api/babel.config.json b/packages/api/babel.config.json index e43758f909..b84cdf97d7 100644 --- a/packages/api/babel.config.json +++ b/packages/api/babel.config.json @@ -5,6 +5,7 @@ "plugins": ["babel-plugin-istanbul"] } }, + "ignore": ["src/index.tsx"], "overrides": [ { "plugins": [], diff --git a/packages/api/package-lock.json b/packages/api/package-lock.json index 25f4eabe12..8768b66439 100644 --- a/packages/api/package-lock.json +++ b/packages/api/package-lock.json @@ -3594,6 +3594,32 @@ "upath": "^1.1.1" } }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -3627,6 +3653,188 @@ "csstype": "^3.0.2" } }, + "@typescript-eslint/eslint-plugin": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.19.0.tgz", + "integrity": "sha512-CRQNQ0mC2Pa7VLwKFbrGVTArfdVDdefS+gTw0oC98vSI98IX5A8EVH4BzJ2FOB0YlCmm8Im36Elad/Jgtvveaw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.19.0", + "@typescript-eslint/scope-manager": "4.19.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.19.0.tgz", + "integrity": "sha512-9/23F1nnyzbHKuoTqFN1iXwN3bvOm/PRIXSBR3qFAYotK/0LveEOHr5JT1WZSzcD6BESl8kPOG3OoDRKO84bHA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.19.0.tgz", + "integrity": "sha512-/uabZjo2ZZhm66rdAu21HA8nQebl3lAIDcybUoOxoI7VbZBYavLIwtOOmykKCJy+Xq6Vw6ugkiwn8Js7D6wieA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", + "debug": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.19.0.tgz", + "integrity": "sha512-GGy4Ba/hLXwJXygkXqMzduqOMc+Na6LrJTZXJWVhRrSuZeXmu8TAnniQVKgj8uTRKe4igO2ysYzH+Np879G75g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0" + } + }, + "@typescript-eslint/types": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.19.0.tgz", + "integrity": "sha512-A4iAlexVvd4IBsSTNxdvdepW0D4uR/fwxDrKUa+iEY9UWvGREu2ZyB8ylTENM1SH8F7bVC9ac9+si3LWNxcBuA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.19.0.tgz", + "integrity": "sha512-3xqArJ/A62smaQYRv2ZFyTA+XxGGWmlDYrsfZG68zJeNbeqRScnhf81rUVa6QG4UgzHnXw5VnMT5cg75dQGDkA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.19.0.tgz", + "integrity": "sha512-aGPS6kz//j7XLSlgpzU2SeTqHPsmRYxFztj2vPuMMFJXZudpRSehE3WCV+BaxwZFvfAqMoSd86TEuM0PQ59E/A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.19.0", + "eslint-visitor-keys": "^2.0.0" + } + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -4013,6 +4221,12 @@ } } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -4437,6 +4651,15 @@ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "optional": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -5421,6 +5644,15 @@ } } }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -6291,6 +6523,74 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -6302,6 +6602,15 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -6316,6 +6625,12 @@ "flat-cache": "^3.0.4" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "filewatcher": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/filewatcher/-/filewatcher-3.0.1.tgz", @@ -6648,6 +6963,34 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "globby": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -7443,6 +7786,12 @@ "readable-stream": "^2.0.1" } }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -7579,6 +7928,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -8306,6 +8661,12 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -8327,8 +8688,7 @@ "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "optional": true + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pify": { "version": "4.0.1", @@ -8514,6 +8874,12 @@ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -8825,6 +9191,12 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -8842,6 +9214,15 @@ "inherits": "^2.0.1" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -9763,6 +10144,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -10049,7 +10439,11 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } } } }, diff --git a/packages/api/package.json b/packages/api/package.json index df1977960a..921f273a65 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -3,6 +3,7 @@ "version": "0.0.0-0", "description": "React DOM component of botframework-webchat", "main": "lib/index.js", + "typings": "lib/index.d.ts", "publishConfig": { "access": "public" }, @@ -37,6 +38,8 @@ "@babel/preset-typescript": "^7.13.0", "@types/node": "^14.14.35", "@types/react": "^16.9.55", + "@typescript-eslint/eslint-plugin": "^4.19.0", + "@typescript-eslint/parser": "^4.19.0", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "cldr-data": "^36.0.0", diff --git a/packages/api/src/StyleOptions.ts b/packages/api/src/StyleOptions.ts new file mode 100644 index 0000000000..e0f6a6587b --- /dev/null +++ b/packages/api/src/StyleOptions.ts @@ -0,0 +1,494 @@ +type StyleOptions = { + /** + * Basic styling + */ + + /** Web Chat component accent color */ + accent?: string; + + /** + * Transcript background color + */ + backgroundColor?: string; + + /** + * Secondary component color + */ + subtle?: string; + + /** + * Default padding used in most visual components + */ + paddingRegular?: number; + + /** + * Padding used for suggestedAction buttons + */ + paddingWide?: number; + + /** + Transition for Bubble, Carousel, and StackedLayout + */ + transitionDuration?: string; + + /** + * Fonts + * Default font size will be inherited from the host app + */ + + /** + * Font size used for secondary components such as sendStatus + */ + fontSizeSmall?: number | string; + + /** + * Font used for ErrorBox + * comma-space separated string + */ + monospaceFont?: string; + + /** + * Font used in most visual components + * comma-space separated string + */ + primaryFont?: string; + + rootHeight?: number | string; + + rootWidth?: number | string; + + /** + * "z-index" for the root container of Web Chat. This will form a new stacking context so "z-index" used in children won't pollute. + */ + rootZIndex?: number; + + /** + * Avatar styling + */ + + /** + * Border radius used for both bot and user avatar + */ + avatarBorderRadius?: number | string; + + /** + * Height and width of avatar + */ + avatarSize?: number; + + /** + * Background color defaults to accent + */ + botAvatarBackgroundColor?: string; + + /** + * URL string. Can be data URI or blob + * botAvatarInitials must be set to empty string + */ + botAvatarImage?: string; + + /** + * Typically rendered as two letters, e.g. 'WC' + * Empty string is required when setting botAvatarImage + */ + botAvatarInitials?: string; + + /** + * Background color defaults to accent + */ + userAvatarBackgroundColor?: string; + + /** + * URL string. Can be data URI or blob + * userAvatarInitials must be set to empty string + */ + userAvatarImage?: string; + + /** + * Typically rendered as two letters, i.e. 'WC' + * Empty string is required when setting userAvatarImage + */ + userAvatarInitials?: string; + + /** + * Avatar grouping can be set at 3 different levels: + * Show avatar on activities sharing the same sender ('sender') + * Show avatar on activities sharing the same status ('status'; default) + * Show avatar on every activity (true) + */ + showAvatarInGroup?: true | 'sender' | 'status'; + + /** + * Bubble styling + * 'Bubble' refers to the container of the activit(ies) from the bot and user. Below, non-'fromUser' props refer to styling for the bot activities. + */ + + bubbleBackground?: string; + bubbleBorderColor?: string; + bubbleBorderRadius?: number; + bubbleBorderStyle?: string; + bubbleBorderWidth?: number; + bubbleFromUserBackground?: string; + bubbleFromUserBorderColor?: string; + bubbleFromUserBorderRadius?: number; + bubbleFromUserBorderStyle?: string; + bubbleFromUserBorderWidth?: number; + + /** + * Nub offset 'bottom' will render nub at the bottom + * A positive or negative number will shift nub offset up/down + * "top" is equivalent to positive zero. + * "bottom" is equivalent to negative zero. + */ + bubbleFromUserNubOffset?: number | 'bottom' | 'top'; + + /** + * Nub size 0 will render a sharp corner + */ + bubbleFromUserNubSize?: number; + + bubbleFromUserTextColor?: string; + bubbleImageHeight?: number; + bubbleMaxWidth?: number; + bubbleMinHeight?: number; + bubbleMinWidth?: number; + + /** + * Nub offset ''bottom' will render nub at the bottom + * A positive or negative number will shift nub offset up/down + * "top" is equivalent to positive zero. + * "bottom" is equivalent to negative zero. + */ + bubbleNubOffset?: number | 'bottom' | 'top'; + + /** + * Nub size 0 will render a sharp corner + */ + bubbleNubSize?: number; + + bubbleTextColor?: string; + + messageActivityWordBreak?: 'normal' | 'break-all' | 'break-word' | 'keep-all'; + + /** + * Connectivity UI styling + */ + + connectivityIconPadding?: number; + connectivityMarginLeftRight?: number; + connectivityMarginTopBottom?: number; + connectivityTextSize?: number | string; + failedConnectivity?: number | string; + slowConnectivity?: string; + notificationText?: string; + + /** + * Slow connection status will render after x amount of time with no service response + */ + slowConnectionAfter?: number; + + /** + * Emoji styling + * If true, Web Chat's default set of emoji will be enabled. See patchStyleOptions.js for default list. + * A custom object will enable unicode emoji specified by the developer. + * key: emoticon + * value: unicode emoji + */ + emojiSet?: boolean | Record; + + /** + * Live region - Accessibility + * New activities will be rendered in the non-visual live region and removed after a certain amount of time. Modify this property to change fade time. + */ + internalLiveRegionFadeAfter?: number; + + /** + * Markdown styling + * Parse markdown to ensure carriage return is respected + */ + markdownRespectCRLF?: boolean; + + /** + * Assign new image for anchor links to indicate external + */ + + markdownExternalLinkIconImage?: string; + /** + * Scroll behavior styling + */ + + /** + * Prevent scroll to end button from rendering + */ + hideScrollToEndButton?: boolean; + + /** + * Snap to activity to 'snap-point' + * If true, scrolling will pause after 1 activity is received. + * Specifying a number will pause after X number of activities + */ + autoScrollSnapOnActivity?: boolean | number; + + /** + * Specify number of pixels to overscroll or underscroll after pause + */ + autoScrollSnapOnActivityOffset?: number; + + /** + * If true, scrolling will pause after activities have filled the page. + * Specifying a number (0 to 1) will pause after % of page is filled + */ + autoScrollSnapOnPage?: boolean | number; + + /** + * Specify number of pixels to overscroll or underscroll after pause + */ + autoScrollSnapOnPageoffset?: number; + + /** + * Send box styling + */ + + hideSendBox?: boolean; + hideUploadButton?: boolean; + microphoneButtonColorOnDictate?: string; + sendBoxBackground?: string; + + /** + * Button color defaults to subtle + */ + sendBoxButtonColor?: string; + + sendBoxButtonColorOnDisabled?: string; + sendBoxButtonColorOnFocus?: string; + sendBoxButtonColorOnHover?: string; + + /** + * Disabled text color defaults to subtle + */ + sendBoxDisabledTextColor?: string; + + sendBoxHeight?: number | string; + sendBoxMaxHeight?: number | string; + sendBoxTextColor?: string; + sendBoxBorderBottom?: number | string; + sendBoxBorderLeft?: number | string; + sendBoxBorderRight?: number | string; + sendBoxBorderTop?: number | string; + sendBoxPlaceholderColor?: string; + sendBoxTextWrap?: boolean; + sendBoxButtonAlignment?: 'bottom' | 'stretch' | 'top'; + + /** + * Show spoken text + */ + showSpokenText?: boolean; + + /** + * Spinner animation styling + */ + + spinnerAnimationBackgroundImage?: string; + spinnerAnimationHeight?: number | string; + spinnerAnimationWidth?: number | string; + spinnerAnimationPadding?: number | string; + + /** + * Suggested Actions + */ + + suggestedActionBackground?: string; + + /** + * Border color defaults to accent. + */ + suggestedActionBorderColor?: string; + + suggestedActionBorderRadius?: number | string; + suggestedActionBorderStyle?: string; + suggestedActionBorderWidth?: number | string; + + /** + * Disabled background defaults to suggestedActionBackground + */ + suggestedActionDisabledBackground?: string; + + suggestedActionDisabledBorderColor?: string; + suggestedActionDisabledBorderStyle?: string; + suggestedActionDisabledBorderWidth?: number | string; + + /** + * Disabled text color defaults to subtle + */ + suggestedActionDisabledTextColor?: string; + + suggestedActionHeight?: number | string; + suggestedActionImageHeight?: number | string; + suggestedActionLayout?: 'carousel' | 'flow' | 'stacked'; + suggestedActionTextColor?: string; + + /** + * Suggested actions carousel layout + */ + + /** + * Cursor when mouseover on flipper + */ + suggestedActionsCarouselFlipperCursor?: string; + + /** + * Flipper bounding box size + */ + suggestedActionsCarouselFlipperBoxWidth?: number; + + /** + * Flipper button's visible size + */ + suggestedActionsCarouselFlipperSize?: number; + + /** + * Suggested actions flow layout + * Default value is 'auto', + */ + suggestedActionsFlowMaxHeight?: undefined; + + /** + * Suggested actions stacked layout + */ + + /** + * Stacked height container's max height. Default value is 'auto' + */ + suggestedActionsStackedHeight?: number | 'auto'; + + /** + * Stacked overflow default value is 'auto + */ + suggestedActionsStackedOverflow?: 'string'; + + /** + * Button max height default value is 100% if suggestedActionsStackedLayoutButtonTextWrap is true + */ + suggestedActionsStackedLayoutButtonMaxHeight?: number | string; + + /** + * Button Text Wrap, if set to true, will wrap long text in buttons in STACKED mode ONLY + */ + suggestedActionsStackedLayoutButtonTextWrap?: boolean; + + /** + * Timestamp + */ + + groupTimestamp?: boolean; + sendTimeout?: number; + sendTimeoutForAttachments?: number; + + /** + * Timestamp color default value is subtle + */ + timestampColor?: string; + + timestampFormat?: 'absolute' | 'relative'; + + /** + * Transcript styling + */ + + transcriptTerminatorBackgroundColor?: string; + transcriptTerminatorBorderRadius?: number | string; + transcriptTerminatorColor?: string; + transcriptTerminatorFontSize?: number | string; + + transcriptActivityVisualKeyboardIndicatorColor?: string; + transcriptActivityVisualKeyboardIndicatorStyle?: string; + transcriptActivityVisualKeyboardIndicatorWidth?: number | string; + + transcriptVisualKeyboardIndicatorColor?: string; + transcriptVisualKeyboardIndicatorStyle?: string; + transcriptVisualKeyboardIndicatorWidth?: number | string; + + /** + * Transcript overlay button + * e.g. carousel and suggested action flippers, scroll to bottom, etc. + */ + + newMessagesButtonFontSize?: number | string; + transcriptOverlayButtonBackground?: string; + transcriptOverlayButtonBackgroundOnDisabled?: string; + transcriptOverlayButtonBackgroundOnFocus?: string; + transcriptOverlayButtonBackgroundOnHover?: string; + transcriptOverlayButtonColor?: string; + transcriptOverlayButtonColorOnDisabled?: string; + + /** + * Default value is transcriptOverlayButtonColor + */ + transcriptOverlayButtonColorOnFocus?: string; + + /** + * Default value is transcriptOverlayButtonColor + */ + transcriptOverlayButtonColorOnHover?: string; + + /** + * Toast UI + */ + + /** + * New debounce timeout value only affects new notifications. + */ + notificationDebounceTimeout?: number; + + hideToaster?: boolean; + toasterHeight?: number | string; + toasterMaxHeight?: number | string; + toasterSingularMaxHeight?: number | string; + toastFontSize?: number | string; + toastIconWidth?: number | string; + toastSeparatorColor?: string; + toastTextPadding?: number | string; + + toastErrorBackgroundColor?: string; + toastErrorColor?: string; + toastInfoBackgroundColor?: string; + toastInfoColor?: string; + toastSuccessBackgroundColor?: string; + toastSuccessColor?: string; + toastWarnBackgroundColor?: string; + toastWarnColor?: string; + + /** + * Typing animation + */ + + typingAnimationBackgroundImage?: string; + typingAnimationDuration?: number; + typingAnimationHeight?: number | string; + typingAnimationWidth?: number | string; + + /** + * Upload thumbnail + */ + + enableUploadThumbnail?: boolean; + uploadThumbnailContentType?: string; + uploadThumbnailHeight?: number | string; + uploadThumbnailQuality?: number; + uploadThumbnailWidth?: number | string; + + /** + * Video + */ + + videoHeight?: number | string; +}; + +type StrictStyleOptions = Required & { + bubbleFromUserNubOffset: number; + bubbleNubOffset: number; + emojiSet: false | Record; +}; + +export default StyleOptions; +export { StrictStyleOptions }; diff --git a/packages/api/src/defaultStyleOptions.js b/packages/api/src/defaultStyleOptions.ts similarity index 59% rename from packages/api/src/defaultStyleOptions.js rename to packages/api/src/defaultStyleOptions.ts index 3af5f854dd..beec45cac9 100644 --- a/packages/api/src/defaultStyleOptions.js +++ b/packages/api/src/defaultStyleOptions.ts @@ -1,4 +1,5 @@ /* eslint no-magic-numbers: "off" */ +import StyleOptions from './StyleOptions'; function fontFamily(fonts) { return fonts.map(font => `'${font}'`).join(', '); @@ -8,33 +9,34 @@ const DEFAULT_ACCENT = '#0063B1'; const DEFAULT_SUBTLE = '#767676'; // With contrast 4.5:1 to white const PADDING_REGULAR = 10; -const DEFAULT_OPTIONS = { - // Color and paddings +const DEFAULT_OPTIONS: Required = { + // Basic styling accent: DEFAULT_ACCENT, backgroundColor: 'White', - cardEmphasisBackgroundColor: '#F0F0F0', + subtle: DEFAULT_SUBTLE, paddingRegular: PADDING_REGULAR, paddingWide: PADDING_REGULAR * 2, - subtle: DEFAULT_SUBTLE, - - // Word break - messageActivityWordBreak: 'break-word', // 'normal' || 'break-all' || 'break-word' || 'keep-all' - - // Fonts fontSizeSmall: '80%', monospaceFont: fontFamily(['Consolas', 'Courier New', 'monospace']), primaryFont: fontFamily(['Calibri', 'Helvetica Neue', 'Arial', 'sans-serif']), + // Root + rootHeight: '100%', + rootWidth: '100%', + rootZIndex: 0, // "z-index" for the root container of Web Chat. This will form a new stacking context so "z-index" used in children won't pollute. + + transitionDuration: '0s', + // Avatar avatarBorderRadius: '50%', avatarSize: 40, - botAvatarBackgroundColor: undefined, // defaults to accent color - botAvatarImage: undefined, // Or a string of URL. Can be a data URI or blob. - botAvatarInitials: undefined, // Or a string. Empty strings means it has avatar but not initials inside. - userAvatarBackgroundColor: undefined, // defaults to accent color - userAvatarImage: undefined, // Or a string of URL. Can be a data URI or blob. - userAvatarInitials: undefined, // Or a string. Empty strings means it has avatar but not initials inside. - showAvatarInGroup: 'status', // Or 'sender' or true (on every activity). + botAvatarBackgroundColor: undefined, + botAvatarImage: undefined, + botAvatarInitials: undefined, + userAvatarBackgroundColor: undefined, + userAvatarImage: undefined, + userAvatarInitials: undefined, + showAvatarInGroup: 'status', // Bubble // TODO: Should we make a bubbleFromBot* @@ -48,139 +50,126 @@ const DEFAULT_OPTIONS = { bubbleFromUserBorderRadius: 2, bubbleFromUserBorderStyle: 'solid', bubbleFromUserBorderWidth: 1, - bubbleFromUserNubOffset: 0, // Either a positive/negative number, or "bottom" - bubbleFromUserNubSize: undefined, // Or a number. 0 means a sharp corner. + bubbleFromUserNubOffset: 0, + bubbleFromUserNubSize: undefined, bubbleFromUserTextColor: 'Black', bubbleImageHeight: 240, - bubbleMaxWidth: 480, // screen width = 600px + bubbleMaxWidth: 480, // Based off screen width = 600px bubbleMinHeight: 40, - bubbleMinWidth: 250, // min screen width = 300px, Edge requires 372px (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13621468/) - bubbleNubOffset: 0, // Either a positive/negative number, or "bottom" - bubbleNubSize: undefined, // Or a number. 0 means a sharp corner. + bubbleMinWidth: 250, // min screen width = 300px; Microsoft Edge requires 372px (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13621468/) + bubbleNubOffset: 0, + bubbleNubSize: undefined, bubbleTextColor: 'Black', + messageActivityWordBreak: 'break-word', - // Markdown - markdownRespectCRLF: true, + // Connectivity UI + connectivityIconPadding: PADDING_REGULAR * 1.2, + connectivityMarginLeftRight: PADDING_REGULAR * 1.4, + connectivityMarginTopBottom: PADDING_REGULAR * 0.8, + connectivityTextSize: '75%', + failedConnectivity: '#C50F1F', + slowConnectivity: '#EAA300', + notificationText: '#5E5E5E', + slowConnectionAfter: 15000, - // Rich Cards - richCardWrapTitle: false, // Applies to subtitles as well + // Emoji + emojiSet: true, - // Root - rootHeight: '100%', - rootWidth: '100%', - rootZIndex: 0, // "z-index" for the root container of Web Chat. This will form a new stacking context so "z-index" used in children won't pollute. + // Live region - Accessibility + internalLiveRegionFadeAfter: 1000, - // Scroll to end button + // Markdown + markdownExternalLinkIconImage: + 'url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIzIDMgMTggMTgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTcuMjUwMSA0LjUwMDE3SDEwLjc0OTVDMTEuMTYzNyA0LjUwMDE3IDExLjQ5OTUgNC44MzU5NiAxMS40OTk1IDUuMjUwMTdDMTEuNDk5NSA1LjYyOTg2IDExLjIxNzMgNS45NDM2NiAxMC44NTEzIDUuOTkzMzJMMTAuNzQ5NSA2LjAwMDE3SDcuMjQ5NzRDNi4wNzA3OSA1Ljk5OTYxIDUuMTAzNDkgNi45MDY1NiA1LjAwNzg2IDguMDYxMTJMNS4wMDAyOCA4LjIyMDAzTDUuMDAzMTIgMTYuNzUwN0M1LjAwMzQzIDE3Ljk0MTUgNS45Mjg4NSAxOC45MTYxIDcuMDk5NjYgMTguOTk0OUw3LjI1MzcxIDE5LjAwMDFMMTUuNzUxOCAxOC45ODg0QzE2Ljk0MTUgMTguOTg2OCAxNy45MTQ1IDE4LjA2MiAxNy45OTM1IDE2Ljg5MjNMMTcuOTk4NyAxNi43Mzg0VjEzLjIzMjFDMTcuOTk4NyAxMi44MTc5IDE4LjMzNDUgMTIuNDgyMSAxOC43NDg3IDEyLjQ4MjFDMTkuMTI4NCAxMi40ODIxIDE5LjQ0MjIgMTIuNzY0MyAxOS40OTE4IDEzLjEzMDNMMTkuNDk4NyAxMy4yMzIxVjE2LjczODRDMTkuNDk4NyAxOC43NDA3IDE3LjkyOTMgMjAuMzc2OSAxNS45NTI4IDIwLjQ4MjlMMTUuNzUzOCAyMC40ODg0TDcuMjU4MjcgMjAuNTAwMUw3LjA1NDk1IDIwLjQ5NDlDNS4xNDIzOSAyMC4zOTU0IDMuNjA4OTUgMTguODYyNyAzLjUwODM3IDE2Ljk1MDJMMy41MDMxMiAxNi43NTExTDMuNTAwODkgOC4yNTI3TDMuNTA1MjkgOC4wNTAyQzMuNjA1MzkgNi4xMzc0OSA1LjEzODY3IDQuNjA0NDkgNy4wNTA5NiA0LjUwNTI3TDcuMjUwMSA0LjUwMDE3SDEwLjc0OTVINy4yNTAxWk0xMy43NDgxIDMuMDAxNDZMMjAuMzAxOCAzLjAwMTk3TDIwLjQwMTQgMy4wMTU3NUwyMC41MDIyIDMuMDQzOTNMMjAuNTU5IDMuMDY4MDNDMjAuNjEyMiAzLjA5MTIyIDIwLjY2MzQgMy4xMjE2MyAyMC43MTExIDMuMTU4ODVMMjAuNzgwNCAzLjIyMTU2TDIwLjg2NDEgMy4zMjAxNEwyMC45MTgzIDMuNDEwMjVMMjAuOTU3IDMuNTAwNTdMMjAuOTc2MiAzLjU2NDc2TDIwLjk4OTggMy42Mjg2MkwyMC45OTkyIDMuNzIyODJMMjAuOTk5NyAxMC4yNTU0QzIwLjk5OTcgMTAuNjY5NiAyMC42NjM5IDExLjAwNTQgMjAuMjQ5NyAxMS4wMDU0QzE5Ljg3IDExLjAwNTQgMTkuNTU2MiAxMC43MjMyIDE5LjUwNjUgMTAuMzU3MUwxOS40OTk3IDEwLjI1NTRMMTkuNDk4OSA1LjU2MTQ3TDEyLjI3OTcgMTIuNzg0N0MxMi4wMTM0IDEzLjA1MSAxMS41OTY4IDEzLjA3NTMgMTEuMzAzMSAxMi44NTc1TDExLjIxOSAxMi43ODQ5QzEwLjk1MjcgMTIuNTE4NyAxMC45Mjg0IDEyLjEwMjEgMTEuMTQ2MiAxMS44MDg0TDExLjIxODggMTEuNzI0M0wxOC40MzY5IDQuNTAxNDZIMTMuNzQ4MUMxMy4zNjg0IDQuNTAxNDYgMTMuMDU0NiA0LjIxOTMxIDEzLjAwNSAzLjg1MzI0TDEyLjk5ODEgMy43NTE0NkMxMi45OTgxIDMuMzcxNzcgMTMuMjgwMyAzLjA1Nzk3IDEzLjY0NjQgMy4wMDgzMUwxMy43NDgxIDMuMDAxNDZaIiBmaWxsPSIjMjEyMTIxIiAvPjwvc3ZnPg==)', + markdownRespectCRLF: true, + + // Scroll behavior hideScrollToEndButton: false, + autoScrollSnapOnActivity: false, + autoScrollSnapOnActivityOffset: 0, + autoScrollSnapOnPage: false, + autoScrollSnapOnPageoffset: 0, // Send box hideSendBox: false, hideUploadButton: false, microphoneButtonColorOnDictate: '#F33', sendBoxBackground: 'White', - sendBoxButtonColor: undefined, // defaults to subtle + sendBoxButtonColor: undefined, sendBoxButtonColorOnDisabled: '#CCC', sendBoxButtonColorOnFocus: '#333', sendBoxButtonColorOnHover: '#333', - sendBoxDisabledTextColor: undefined, // defaults to subtle + sendBoxDisabledTextColor: undefined, sendBoxHeight: 40, sendBoxMaxHeight: 200, sendBoxTextColor: 'Black', // TODO: We should deprecate this because there isn't an easy way to make the width of the send box narrower than the transcript - sendBoxBorderBottom: '', - sendBoxBorderLeft: '', - sendBoxBorderRight: '', + sendBoxBorderBottom: undefined, + sendBoxBorderLeft: undefined, + sendBoxBorderRight: undefined, sendBoxBorderTop: 'solid 1px #E6E6E6', - sendBoxPlaceholderColor: undefined, // defaults to subtle + sendBoxPlaceholderColor: undefined, sendBoxTextWrap: false, - sendBoxButtonAlignment: 'stretch', // "stretch", "top" or "bottom" + sendBoxButtonAlignment: 'stretch', // Visually show spoken text showSpokenText: false, + spinnerAnimationBackgroundImage: undefined, + spinnerAnimationHeight: 16, + spinnerAnimationWidth: 16, + spinnerAnimationPadding: 12, + // Suggested actions suggestedActionBackground: 'White', - suggestedActionBorder: undefined, // split into 3, null - suggestedActionBorderColor: undefined, // defaults to accent + suggestedActionBorderColor: undefined, suggestedActionBorderRadius: 0, suggestedActionBorderStyle: 'solid', suggestedActionBorderWidth: 2, - suggestedActionDisabledBackground: undefined, // defaults to suggestedActionBackground + suggestedActionDisabledBackground: undefined, suggestedActionDisabledBorderColor: '#E6E6E6', suggestedActionDisabledBorderStyle: 'solid', suggestedActionDisabledBorderWidth: 2, - suggestedActionDisabledTextColor: undefined, // defaults to subtle + suggestedActionDisabledTextColor: undefined, suggestedActionHeight: 40, suggestedActionImageHeight: 20, - suggestedActionLayout: 'carousel', // Either "carousel", "flow", or "stacked" - suggestedActionTextColor: null, + suggestedActionLayout: 'carousel', + suggestedActionTextColor: undefined, // Suggested actions carousel layout - suggestedActionsCarouselFlipperCursor: null, // Cursor when mouse over on flipper - suggestedActionsCarouselFlipperBoxWidth: 40, // Flipper bounding box size - suggestedActionsCarouselFlipperSize: 20, // Flipper visible size + suggestedActionsCarouselFlipperCursor: undefined, + suggestedActionsCarouselFlipperBoxWidth: 40, + suggestedActionsCarouselFlipperSize: 20, // Suggested actions flow layout - suggestedActionsFlowMaxHeight: undefined, // Defaults to "auto". + suggestedActionsFlowMaxHeight: undefined, // Suggested actions stacked layout - suggestedActionsStackedHeight: undefined, // sets the container's max height. defaults to 'auto' - suggestedActionsStackedOverflow: undefined, // defaults to 'auto', - suggestedActionsStackedLayoutButtonMaxHeight: undefined, // defaults to 100% if suggestedActionsStackedLayoutButtonTextWrap is true - suggestedActionsStackedLayoutButtonTextWrap: false, // if set to true, buttons with long text will wrap in STACKED mode ONLY + suggestedActionsStackedHeight: undefined, + suggestedActionsStackedOverflow: undefined, + suggestedActionsStackedLayoutButtonMaxHeight: undefined, + suggestedActionsStackedLayoutButtonTextWrap: false, // Timestamp groupTimestamp: true, sendTimeout: 20000, sendTimeoutForAttachments: 120000, - timestampColor: undefined, // defaults to subtle - timestampFormat: 'relative', // 'absolute' + timestampColor: undefined, + timestampFormat: 'relative', - // Transcript overlay buttons (e.g. carousel and suggested action flippers, scroll to bottom, etc.) + // Transcript overlay buttons newMessagesButtonFontSize: '85%', transcriptOverlayButtonBackground: 'rgba(0, 0, 0, .6)', + transcriptOverlayButtonBackgroundOnDisabled: 'rgba(0, 0, 0, .6)', transcriptOverlayButtonBackgroundOnFocus: 'rgba(0, 0, 0, .8)', transcriptOverlayButtonBackgroundOnHover: 'rgba(0, 0, 0, .8)', transcriptOverlayButtonColor: 'White', - transcriptOverlayButtonColorOnFocus: undefined, // defaults to transcriptOverlayButtonColor - transcriptOverlayButtonColorOnHover: undefined, // defaults to transcriptOverlayButtonColor - - // Video - videoHeight: 270, // based on bubbleMaxWidth: 480 / 16 * 9 = 270 - - // Connectivity UI - connectivityIconPadding: PADDING_REGULAR * 1.2, - connectivityMarginLeftRight: PADDING_REGULAR * 1.4, - connectivityMarginTopBottom: PADDING_REGULAR * 0.8, - connectivityTextSize: '75%', - failedConnectivity: '#C50F1F', - slowConnectivity: '#EAA300', - notificationText: '#5E5E5E', - slowConnectionAfter: 15000, - - typingAnimationBackgroundImage: null, - typingAnimationDuration: 5000, - typingAnimationHeight: 20, - typingAnimationWidth: 64, - - spinnerAnimationBackgroundImage: null, - spinnerAnimationHeight: 16, - spinnerAnimationWidth: 16, - spinnerAnimationPadding: 12, - - // TODO: [P0] #3322 This is only supported on HTML. - enableUploadThumbnail: true, - uploadThumbnailContentType: 'image/jpeg', - uploadThumbnailHeight: 360, - uploadThumbnailQuality: 0.6, - uploadThumbnailWidth: 720, - - // deprecated; will be removed on or after 2021-02-01 - spinnerAnimationPaddingRight: undefined, + transcriptOverlayButtonColorOnDisabled: 'White', + transcriptOverlayButtonColorOnFocus: undefined, + transcriptOverlayButtonColorOnHover: undefined, // Toast UI - // New debounce timeout value only affects new notifications. notificationDebounceTimeout: 400, hideToaster: false, @@ -201,17 +190,36 @@ const DEFAULT_OPTIONS = { toastWarnBackgroundColor: '#FFF4CE', toastWarnColor: '#3B3A39', - // Emoji - emojiSet: true, // true || false || { ':)' : '😊'} + // Transcript + transcriptTerminatorBackgroundColor: '#595959', + transcriptTerminatorBorderRadius: 5, + transcriptTerminatorColor: 'White', + transcriptTerminatorFontSize: 12, - // Auto-scroll behavior - autoScrollSnapOnActivity: false, // true will pause scroll after 1 activity is received. Specifying a number will pause after X number of activities - autoScrollSnapOnActivityOffset: 0, // Specify number of pixels to overscroll or underscroll after pause - autoScrollSnapOnPage: false, // true will pause scroll after activities filled the page. Specifying a number (0 to 1) will pause after % of page is filled - autoScrollSnapOnPageoffset: 0, // Specify number of pixels to overscroll or underscroll after pause + transcriptActivityVisualKeyboardIndicatorColor: DEFAULT_SUBTLE, + transcriptActivityVisualKeyboardIndicatorStyle: 'dashed', + transcriptActivityVisualKeyboardIndicatorWidth: 1, - markdownExternalLinkIconImage: - 'url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIzIDMgMTggMTgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTcuMjUwMSA0LjUwMDE3SDEwLjc0OTVDMTEuMTYzNyA0LjUwMDE3IDExLjQ5OTUgNC44MzU5NiAxMS40OTk1IDUuMjUwMTdDMTEuNDk5NSA1LjYyOTg2IDExLjIxNzMgNS45NDM2NiAxMC44NTEzIDUuOTkzMzJMMTAuNzQ5NSA2LjAwMDE3SDcuMjQ5NzRDNi4wNzA3OSA1Ljk5OTYxIDUuMTAzNDkgNi45MDY1NiA1LjAwNzg2IDguMDYxMTJMNS4wMDAyOCA4LjIyMDAzTDUuMDAzMTIgMTYuNzUwN0M1LjAwMzQzIDE3Ljk0MTUgNS45Mjg4NSAxOC45MTYxIDcuMDk5NjYgMTguOTk0OUw3LjI1MzcxIDE5LjAwMDFMMTUuNzUxOCAxOC45ODg0QzE2Ljk0MTUgMTguOTg2OCAxNy45MTQ1IDE4LjA2MiAxNy45OTM1IDE2Ljg5MjNMMTcuOTk4NyAxNi43Mzg0VjEzLjIzMjFDMTcuOTk4NyAxMi44MTc5IDE4LjMzNDUgMTIuNDgyMSAxOC43NDg3IDEyLjQ4MjFDMTkuMTI4NCAxMi40ODIxIDE5LjQ0MjIgMTIuNzY0MyAxOS40OTE4IDEzLjEzMDNMMTkuNDk4NyAxMy4yMzIxVjE2LjczODRDMTkuNDk4NyAxOC43NDA3IDE3LjkyOTMgMjAuMzc2OSAxNS45NTI4IDIwLjQ4MjlMMTUuNzUzOCAyMC40ODg0TDcuMjU4MjcgMjAuNTAwMUw3LjA1NDk1IDIwLjQ5NDlDNS4xNDIzOSAyMC4zOTU0IDMuNjA4OTUgMTguODYyNyAzLjUwODM3IDE2Ljk1MDJMMy41MDMxMiAxNi43NTExTDMuNTAwODkgOC4yNTI3TDMuNTA1MjkgOC4wNTAyQzMuNjA1MzkgNi4xMzc0OSA1LjEzODY3IDQuNjA0NDkgNy4wNTA5NiA0LjUwNTI3TDcuMjUwMSA0LjUwMDE3SDEwLjc0OTVINy4yNTAxWk0xMy43NDgxIDMuMDAxNDZMMjAuMzAxOCAzLjAwMTk3TDIwLjQwMTQgMy4wMTU3NUwyMC41MDIyIDMuMDQzOTNMMjAuNTU5IDMuMDY4MDNDMjAuNjEyMiAzLjA5MTIyIDIwLjY2MzQgMy4xMjE2MyAyMC43MTExIDMuMTU4ODVMMjAuNzgwNCAzLjIyMTU2TDIwLjg2NDEgMy4zMjAxNEwyMC45MTgzIDMuNDEwMjVMMjAuOTU3IDMuNTAwNTdMMjAuOTc2MiAzLjU2NDc2TDIwLjk4OTggMy42Mjg2MkwyMC45OTkyIDMuNzIyODJMMjAuOTk5NyAxMC4yNTU0QzIwLjk5OTcgMTAuNjY5NiAyMC42NjM5IDExLjAwNTQgMjAuMjQ5NyAxMS4wMDU0QzE5Ljg3IDExLjAwNTQgMTkuNTU2MiAxMC43MjMyIDE5LjUwNjUgMTAuMzU3MUwxOS40OTk3IDEwLjI1NTRMMTkuNDk4OSA1LjU2MTQ3TDEyLjI3OTcgMTIuNzg0N0MxMi4wMTM0IDEzLjA1MSAxMS41OTY4IDEzLjA3NTMgMTEuMzAzMSAxMi44NTc1TDExLjIxOSAxMi43ODQ5QzEwLjk1MjcgMTIuNTE4NyAxMC45Mjg0IDEyLjEwMjEgMTEuMTQ2MiAxMS44MDg0TDExLjIxODggMTEuNzI0M0wxOC40MzY5IDQuNTAxNDZIMTMuNzQ4MUMxMy4zNjg0IDQuNTAxNDYgMTMuMDU0NiA0LjIxOTMxIDEzLjAwNSAzLjg1MzI0TDEyLjk5ODEgMy43NTE0NkMxMi45OTgxIDMuMzcxNzcgMTMuMjgwMyAzLjA1Nzk3IDEzLjY0NjQgMy4wMDgzMUwxMy43NDgxIDMuMDAxNDZaIiBmaWxsPSIjMjEyMTIxIiAvPjwvc3ZnPg==)' + transcriptVisualKeyboardIndicatorColor: 'Black', + transcriptVisualKeyboardIndicatorStyle: 'solid', + transcriptVisualKeyboardIndicatorWidth: 2, + + // Typing animation + typingAnimationBackgroundImage: undefined, + typingAnimationDuration: 5000, + typingAnimationHeight: 20, + typingAnimationWidth: 64, + + // Upload thumbnail + // TODO: [P0] #3322 This is only supported in HTML. + enableUploadThumbnail: true, + uploadThumbnailContentType: 'image/jpeg', + uploadThumbnailHeight: 360, + uploadThumbnailQuality: 0.6, + uploadThumbnailWidth: 720, + + // Video + videoHeight: 270 // based on bubbleMaxWidth: 480 / 16 * 9 = 270 }; export default DEFAULT_OPTIONS; diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.tsx similarity index 91% rename from packages/api/src/hooks/Composer.js rename to packages/api/src/hooks/Composer.tsx index 12e78f382c..10610141a5 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.tsx @@ -1,6 +1,6 @@ import { Provider } from 'react-redux'; import PropTypes from 'prop-types'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { FC, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import updateIn from 'simple-update-in'; import createCustomEvent from '../utils/createCustomEvent'; @@ -8,7 +8,9 @@ import ErrorBoundary from './utils/ErrorBoundary'; import getAllLocalizedStrings from '../localization/getAllLocalizedStrings'; import isObject from '../utils/isObject'; import normalizeLanguage from '../utils/normalizeLanguage'; +// @ts-ignore import PrecompiledGlobalize from '../external/PrecompiledGlobalize'; +import StyleOptions from '../StyleOptions'; import { clearSuggestedActions, @@ -45,14 +47,15 @@ import mapMap from '../utils/mapMap'; import observableToPromise from './utils/observableToPromise'; import Tracker from './internal/Tracker'; import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; -import WebChatAPIContext from './internal/WebChatAPIContext'; +import { default as WebChatAPIContext } from './internal/WebChatAPIContext'; import applyMiddleware, { forLegacyRenderer as applyMiddlewareForLegacyRenderer, forRenderer as applyMiddlewareForRenderer } from './middleware/applyMiddleware'; -import patchStyleOptions from '../patchStyleOptions'; +import normalizeStyleOptions from '../normalizeStyleOptions'; +import patchStyleOptionsFromDeprecatedProps from '../patchStyleOptionsFromDeprecatedProps'; import singleToArray from './utils/singleToArray'; // List of Redux actions factory we are hoisting as Web Chat functions @@ -87,7 +90,7 @@ function createCardActionContext({ cardActionMiddleware, directLine, dispatch }) )({ dispatch }); return { - onCardAction: (cardAction, { target } = {}) => + onCardAction: (cardAction, { target }: { target?: any } = {}) => runMiddleware({ cardAction, getSignInUrl: @@ -148,7 +151,44 @@ function mergeStringsOverrides(localizedStrings, language, overrideLocalizedStri return { ...localizedStrings, ...overrideLocalizedStrings }; } -const Composer = ({ +type ComposerProps = { + activityMiddleware: any; + activityRenderer: any; + activityStatusMiddleware: any; + activityStatusRenderer: any; + attachmentForScreenReaderMiddleware: any; + attachmentMiddleware: any; + attachmentRenderer: any; + avatarMiddleware: any; + avatarRenderer: any; + cardActionMiddleware: any; + children: ReactNode; + dir: string; + directLine: any; + disabled: boolean; + downscaleImageToDataURL: any; + grammars: any; + groupActivitiesMiddleware: any; + groupTimestamp: boolean | number; + internalErrorBoxClass: any; + internalRenderErrorBox: any; + locale: string; + onTelemetry: any; + overrideLocalizedStrings: any; + renderMarkdown: any; + selectVoice: any; + sendTimeout: number; + sendTypingIndicator: any; + styleOptions: StyleOptions; + toastMiddleware: any; + toastRenderer: any; + typingIndicatorMiddleware: any; + typingIndicatorRenderer: any; + userID: string; + username: string; +}; + +const Composer: FC = ({ activityMiddleware, activityRenderer, activityStatusMiddleware, @@ -188,11 +228,10 @@ const Composer = ({ const patchedDir = useMemo(() => (dir === 'ltr' || dir === 'rtl' ? dir : 'auto'), [dir]); const patchedGrammars = useMemo(() => grammars || [], [grammars]); - const patchedStyleOptions = useMemo(() => patchStyleOptions(styleOptions, { groupTimestamp, sendTimeout }), [ - groupTimestamp, - sendTimeout, - styleOptions - ]); + const patchedStyleOptions = useMemo( + () => normalizeStyleOptions(patchStyleOptionsFromDeprecatedProps(styleOptions, { groupTimestamp, sendTimeout })), + [groupTimestamp, sendTimeout, styleOptions] + ); useEffect(() => { dispatch(setLanguage(locale)); @@ -503,7 +542,12 @@ const Composer = ({ }; // We will create a Redux store if it was not passed in -const ComposeWithStore = ({ internalRenderErrorBox, onTelemetry, store, ...props }) => { +const ComposeWithStore: FC = ({ + internalRenderErrorBox, + onTelemetry, + store, + ...props +}) => { const [error, setError] = useState(); const handleError = useCallback( diff --git a/packages/api/src/hooks/internal/Tracker.js b/packages/api/src/hooks/internal/Tracker.ts similarity index 61% rename from packages/api/src/hooks/internal/Tracker.js rename to packages/api/src/hooks/internal/Tracker.ts index 3dffdab20f..5c5363edf7 100644 --- a/packages/api/src/hooks/internal/Tracker.js +++ b/packages/api/src/hooks/internal/Tracker.ts @@ -1,9 +1,9 @@ import useTracker from './useTracker'; -const Tracker = () => { +const Tracker: React.FC<{}> = () => { useTracker(); - return false; + return null; }; export default Tracker; diff --git a/packages/api/src/hooks/internal/WebChatAPIContext.js b/packages/api/src/hooks/internal/WebChatAPIContext.ts similarity index 78% rename from packages/api/src/hooks/internal/WebChatAPIContext.js rename to packages/api/src/hooks/internal/WebChatAPIContext.ts index c25d3d4c41..bb6407ab72 100644 --- a/packages/api/src/hooks/internal/WebChatAPIContext.js +++ b/packages/api/src/hooks/internal/WebChatAPIContext.ts @@ -1,6 +1,6 @@ import { createContext } from 'react'; -const context = createContext({ +const context = createContext({ sendFocusRef: null }); diff --git a/packages/api/src/index.js b/packages/api/src/index.js new file mode 100644 index 0000000000..9d1778fa47 --- /dev/null +++ b/packages/api/src/index.js @@ -0,0 +1,10 @@ +// IMPORTANT: To export anything from this file, add it to index.tsx, which is the .d.ts for this file. + +import * as hooks from './hooks'; +import Composer from './hooks/Composer'; +import concatMiddleware from './hooks/middleware/concatMiddleware'; +import defaultStyleOptions from './defaultStyleOptions'; +import Localize, { localize } from './localization/Localize'; +import normalizeStyleOptions from './normalizeStyleOptions'; + +export { Composer, concatMiddleware, defaultStyleOptions, hooks, Localize, localize, normalizeStyleOptions }; diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts deleted file mode 100644 index 501e2d5659..0000000000 --- a/packages/api/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as hooks from './hooks'; -import Composer from './hooks/Composer'; -import concatMiddleware from './hooks/middleware/concatMiddleware'; -import Localize, { localize } from './localization/Localize'; - -export { Composer, concatMiddleware, hooks, Localize, localize }; diff --git a/packages/api/src/index.tsx b/packages/api/src/index.tsx new file mode 100644 index 0000000000..7d9393c392 --- /dev/null +++ b/packages/api/src/index.tsx @@ -0,0 +1,10 @@ +import StyleOptions, { StrictStyleOptions } from './StyleOptions'; + +declare const defaultStyleOptions: Required; + +// TODO: [P2] ESLint of DLSpeech SDK should ignore this file since its from API. +// eslint-disable-next-line no-unused-vars +declare function normalizeStyleOptions(styleOptions: StyleOptions): StrictStyleOptions; + +export type { StrictStyleOptions, StyleOptions }; +export { defaultStyleOptions, normalizeStyleOptions }; diff --git a/packages/api/src/normalizeStyleOptions.ts b/packages/api/src/normalizeStyleOptions.ts new file mode 100644 index 0000000000..3ef3e81262 --- /dev/null +++ b/packages/api/src/normalizeStyleOptions.ts @@ -0,0 +1,76 @@ +import defaultStyleOptions from './defaultStyleOptions'; +import StyleOptions, { StrictStyleOptions } from './StyleOptions'; + +// TODO: [P4] We should add a notice for people who want to use "styleSet" instead of "styleOptions". +// "styleSet" is actually CSS stylesheet and it is based on the DOM tree. +// DOM tree may change from time to time, thus, maintaining "styleSet" becomes a constant effort. + +// eslint-disable-next-line complexity +export default function normalizeStyleOptions(options: StyleOptions = {}): StrictStyleOptions { + const filledOptions: Required = { ...defaultStyleOptions, ...options }; + + // Keep this list flat (no nested style) and serializable (no functions) + const { bubbleFromUserNubOffset, bubbleNubOffset, emojiSet } = filledOptions; + + let normalizedBubbleFromUserNubOffset: number; + let normalizedBubbleNubOffset: number; + let normalizedEmojiSet: false | Record; + + if (bubbleFromUserNubOffset === 'top') { + normalizedBubbleFromUserNubOffset = 0; + } else if (typeof bubbleFromUserNubOffset !== 'number') { + normalizedBubbleFromUserNubOffset = -0; + } else { + normalizedBubbleFromUserNubOffset = bubbleFromUserNubOffset; + } + + if (bubbleNubOffset === 'top') { + normalizedBubbleNubOffset = 0; + } else if (typeof bubbleNubOffset !== 'number') { + normalizedBubbleNubOffset = -0; + } else { + normalizedBubbleNubOffset = bubbleNubOffset; + } + + if (emojiSet === true) { + normalizedEmojiSet = { + ':)': '😊', + ':-)': '😊', + '(:': '😊', + '(-:': '😊', + ':-|': '😐', + ':|': '😐', + ':-(': '☚ī¸', + ':(': '☚ī¸', + ':-D': '😀', + ':D': '😀', + ':-p': '😛', + ':p': '😛', + ':-P': '😛', + ':P': '😛', + ':-o': '😲', + ':o': '😲', + ':O': '😲', + ':-O': '😲', + ':-0': '😲', + ':0': '😲', + ';-)': '😉', + ';)': '😉', + '<3': '❤ī¸', + ' groupTimestampFromProps); + } + + if (typeof sendTimeoutFromProps !== 'undefined' && typeof styleOptions.sendTimeout === 'undefined') { + console.warn( + 'Web Chat: "sendTimeout" has been moved to "styleOptions". This deprecation migration will be removed on or after January 1 2022.' + ); + + styleOptions = updateIn(styleOptions, ['sendTimeout'], () => sendTimeoutFromProps); + } + + if (styleOptions.slowConnectionAfter < 0) { + console.warn('Web Chat: "slowConnectionAfter" cannot be negative, will set to 0.'); + + styleOptions = updateIn(styleOptions, ['slowConnectionAfter'], () => 0); + } + + return styleOptions; +} diff --git a/packages/api/src/tsconfig.json b/packages/api/src/tsconfig.json index ca32a35acf..35417e5ca6 100644 --- a/packages/api/src/tsconfig.json +++ b/packages/api/src/tsconfig.json @@ -3,11 +3,13 @@ "allowSyntheticDefaultImports": true, "declaration": true, "declarationDir": "../lib", + "declarationMap": true, "emitDeclarationOnly": true, - "isolatedModules": true, "jsx": "react", "preserveWatchOutput": true, "pretty": true, - "skipLibCheck": true - } + "skipLibCheck": true, + "sourceMap": true + }, + "files": ["index.tsx"] } diff --git a/packages/bundle/babel.config.json b/packages/bundle/babel.config.json index 35e0d17fac..96a91c73ef 100644 --- a/packages/bundle/babel.config.json +++ b/packages/bundle/babel.config.json @@ -4,6 +4,7 @@ "plugins": ["babel-plugin-istanbul"] } }, + "ignore": ["src/index.tsx", "src/index-es5.tsx", "src/index-minimal.tsx"], "plugins": [ "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread", diff --git a/packages/bundle/package-lock.json b/packages/bundle/package-lock.json index 2768f0ea97..585e3b5a3e 100644 --- a/packages/bundle/package-lock.json +++ b/packages/bundle/package-lock.json @@ -2981,13 +2981,13 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.18.0.tgz", - "integrity": "sha512-Lzkc/2+7EoH7+NjIWLS2lVuKKqbEmJhtXe3rmfA8cyiKnZm3IfLf51irnBcmow8Q/AptVV0XBZmBJKuUJTe6cQ==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.19.0.tgz", + "integrity": "sha512-CRQNQ0mC2Pa7VLwKFbrGVTArfdVDdefS+gTw0oC98vSI98IX5A8EVH4BzJ2FOB0YlCmm8Im36Elad/Jgtvveaw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.18.0", - "@typescript-eslint/scope-manager": "4.18.0", + "@typescript-eslint/experimental-utils": "4.19.0", + "@typescript-eslint/scope-manager": "4.19.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -2997,28 +2997,28 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz", - "integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.19.0.tgz", + "integrity": "sha512-GGy4Ba/hLXwJXygkXqMzduqOMc+Na6LrJTZXJWVhRrSuZeXmu8TAnniQVKgj8uTRKe4igO2ysYzH+Np879G75g==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/visitor-keys": "4.18.0" + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0" } }, "@typescript-eslint/types": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz", - "integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.19.0.tgz", + "integrity": "sha512-A4iAlexVvd4IBsSTNxdvdepW0D4uR/fwxDrKUa+iEY9UWvGREu2ZyB8ylTENM1SH8F7bVC9ac9+si3LWNxcBuA==", "dev": true }, "@typescript-eslint/visitor-keys": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz", - "integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.19.0.tgz", + "integrity": "sha512-aGPS6kz//j7XLSlgpzU2SeTqHPsmRYxFztj2vPuMMFJXZudpRSehE3WCV+BaxwZFvfAqMoSd86TEuM0PQ59E/A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", + "@typescript-eslint/types": "4.19.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -3032,9 +3032,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -3049,43 +3049,43 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.18.0.tgz", - "integrity": "sha512-92h723Kblt9JcT2RRY3QS2xefFKar4ZQFVs3GityOKWQYgtajxt/tuXIzL7sVCUlM1hgreiV5gkGYyBpdOwO6A==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.19.0.tgz", + "integrity": "sha512-9/23F1nnyzbHKuoTqFN1iXwN3bvOm/PRIXSBR3qFAYotK/0LveEOHr5JT1WZSzcD6BESl8kPOG3OoDRKO84bHA==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.18.0", - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/typescript-estree": "4.18.0", + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz", - "integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.19.0.tgz", + "integrity": "sha512-GGy4Ba/hLXwJXygkXqMzduqOMc+Na6LrJTZXJWVhRrSuZeXmu8TAnniQVKgj8uTRKe4igO2ysYzH+Np879G75g==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/visitor-keys": "4.18.0" + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0" } }, "@typescript-eslint/types": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz", - "integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.19.0.tgz", + "integrity": "sha512-A4iAlexVvd4IBsSTNxdvdepW0D4uR/fwxDrKUa+iEY9UWvGREu2ZyB8ylTENM1SH8F7bVC9ac9+si3LWNxcBuA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.18.0.tgz", - "integrity": "sha512-wt4xvF6vvJI7epz+rEqxmoNQ4ZADArGQO9gDU+cM0U5fdVv7N+IAuVoVAoZSOZxzGHBfvE3XQMLdy+scsqFfeg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.19.0.tgz", + "integrity": "sha512-3xqArJ/A62smaQYRv2ZFyTA+XxGGWmlDYrsfZG68zJeNbeqRScnhf81rUVa6QG4UgzHnXw5VnMT5cg75dQGDkA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/visitor-keys": "4.18.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -3094,12 +3094,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz", - "integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.19.0.tgz", + "integrity": "sha512-aGPS6kz//j7XLSlgpzU2SeTqHPsmRYxFztj2vPuMMFJXZudpRSehE3WCV+BaxwZFvfAqMoSd86TEuM0PQ59E/A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", + "@typescript-eslint/types": "4.19.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -3123,9 +3123,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -3140,41 +3140,41 @@ } }, "@typescript-eslint/parser": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.18.0.tgz", - "integrity": "sha512-W3z5S0ZbecwX3PhJEAnq4mnjK5JJXvXUDBYIYGoweCyWyuvAKfGHvzmpUzgB5L4cRBb+cTu9U/ro66dx7dIimA==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.19.0.tgz", + "integrity": "sha512-/uabZjo2ZZhm66rdAu21HA8nQebl3lAIDcybUoOxoI7VbZBYavLIwtOOmykKCJy+Xq6Vw6ugkiwn8Js7D6wieA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.18.0", - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/typescript-estree": "4.18.0", + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", "debug": "^4.1.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz", - "integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.19.0.tgz", + "integrity": "sha512-GGy4Ba/hLXwJXygkXqMzduqOMc+Na6LrJTZXJWVhRrSuZeXmu8TAnniQVKgj8uTRKe4igO2ysYzH+Np879G75g==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/visitor-keys": "4.18.0" + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0" } }, "@typescript-eslint/types": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz", - "integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.19.0.tgz", + "integrity": "sha512-A4iAlexVvd4IBsSTNxdvdepW0D4uR/fwxDrKUa+iEY9UWvGREu2ZyB8ylTENM1SH8F7bVC9ac9+si3LWNxcBuA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.18.0.tgz", - "integrity": "sha512-wt4xvF6vvJI7epz+rEqxmoNQ4ZADArGQO9gDU+cM0U5fdVv7N+IAuVoVAoZSOZxzGHBfvE3XQMLdy+scsqFfeg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.19.0.tgz", + "integrity": "sha512-3xqArJ/A62smaQYRv2ZFyTA+XxGGWmlDYrsfZG68zJeNbeqRScnhf81rUVa6QG4UgzHnXw5VnMT5cg75dQGDkA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", - "@typescript-eslint/visitor-keys": "4.18.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -3192,9 +3192,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -3209,12 +3209,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz", - "integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.19.0.tgz", + "integrity": "sha512-aGPS6kz//j7XLSlgpzU2SeTqHPsmRYxFztj2vPuMMFJXZudpRSehE3WCV+BaxwZFvfAqMoSd86TEuM0PQ59E/A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.18.0", + "@typescript-eslint/types": "4.19.0", "eslint-visitor-keys": "^2.0.0" } }, diff --git a/packages/bundle/package.json b/packages/bundle/package.json index e93f9154e4..b761a248ab 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -33,6 +33,7 @@ "adaptivecards": "2.5.0", "botframework-directlinejs": "0.14.1", "botframework-directlinespeech-sdk": "0.0.0-0", + "botframework-webchat-api": "0.0.0-0", "botframework-webchat-component": "0.0.0-0", "botframework-webchat-core": "0.0.0-0", "classnames": "2.2.6", @@ -61,8 +62,8 @@ "@babel/preset-typescript": "^7.13.0", "@types/node": "^14.14.35", "@types/react": "^16.9.55", - "@typescript-eslint/eslint-plugin": "^4.18.0", - "@typescript-eslint/parser": "^4.18.0", + "@typescript-eslint/eslint-plugin": "^4.19.0", + "@typescript-eslint/parser": "^4.19.0", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "concurrently": "^6.0.0", diff --git a/packages/bundle/src/FullBundleStyleOptions.ts b/packages/bundle/src/FullBundleStyleOptions.ts new file mode 100644 index 0000000000..3a1fd94499 --- /dev/null +++ b/packages/bundle/src/FullBundleStyleOptions.ts @@ -0,0 +1,9 @@ +import { StrictStyleOptions, StyleOptions } from 'botframework-webchat-api'; + +import AdaptiveCardStyleOptions, { StrictAdaptiveCardsStyleOptions } from './adaptiveCards/AdaptiveCardsStyleOptions'; + +type FullBundleStyleOptions = StyleOptions & AdaptiveCardStyleOptions; +type StrictFullBundleStyleOptions = StrictStyleOptions & StrictAdaptiveCardsStyleOptions; + +export default FullBundleStyleOptions; +export { StrictFullBundleStyleOptions }; diff --git a/packages/bundle/src/adaptiveCards/AdaptiveCardsStyleOptions.ts b/packages/bundle/src/adaptiveCards/AdaptiveCardsStyleOptions.ts new file mode 100644 index 0000000000..50f69cfb0a --- /dev/null +++ b/packages/bundle/src/adaptiveCards/AdaptiveCardsStyleOptions.ts @@ -0,0 +1,31 @@ +type AdaptiveCardsStyleOptions = { + /** + * Adaptive Cards styling + */ + + /** + * Adaptive Cards styling for 'emphasis' container style + */ + cardEmphasisBackgroundColor?: string; + + /** + * Adaptive Cards: background color of Adaptive Cards button with status of 'aria-pressed' + */ + cardPushButtonBackgroundColor?: string; + + /** + * Adaptive Cards: text color of Adaptive Cards button with status of 'aria-pressed' + */ + cardPushButtonTextColor?: string; + + /** + * Cards: Rich Cards + * Enable title (and subtitle) wrapping + */ + richCardWrapTitle?: boolean; +}; + +type StrictAdaptiveCardsStyleOptions = Required; + +export default AdaptiveCardsStyleOptions; +export { StrictAdaptiveCardsStyleOptions }; diff --git a/packages/bundle/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.js b/packages/bundle/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.ts similarity index 94% rename from packages/bundle/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.js rename to packages/bundle/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.ts index d517c0f333..9094f6c0e3 100644 --- a/packages/bundle/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.js +++ b/packages/bundle/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.ts @@ -1,10 +1,12 @@ +import FullBundleStyleOptions from '../../../FullBundleStyleOptions'; + export default function ({ cardPushButtonBackgroundColor, cardPushButtonTextColor, accent, paddingRegular, primaryFont -}) { +}: FullBundleStyleOptions) { return { '&.webchat__adaptive-card-renderer': { '& .ac-input, & .ac-inlineActionButton, & .ac-quickActionButton': { diff --git a/packages/bundle/src/adaptiveCards/Styles/StyleSet/AudioCardAttachment.js b/packages/bundle/src/adaptiveCards/Styles/StyleSet/AudioCardAttachment.js index 1b521c5f49..b4e2b3ebb5 100644 --- a/packages/bundle/src/adaptiveCards/Styles/StyleSet/AudioCardAttachment.js +++ b/packages/bundle/src/adaptiveCards/Styles/StyleSet/AudioCardAttachment.js @@ -2,7 +2,7 @@ // Later, we will rewrite these attachments without Adaptive Cards // We are leaving the CSS here as-is for now -export default function AudioCardAttachment({ paddingRegular }) { +export default function AudioCardAttachment({ paddingRegular = undefined }) { return { // TODO: [P2] We should not set "display" in styleSet, this will allow the user to break the layout for no good reasons. display: 'flex', diff --git a/packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig.js b/packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig.js deleted file mode 100644 index eb938f5b3c..0000000000 --- a/packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig.js +++ /dev/null @@ -1,113 +0,0 @@ -import { defaultStyleOptions } from 'botframework-webchat-component'; -// https://docs.microsoft.com/en-us/adaptive-cards/rendering-cards/host-config - -export default ({ - accent, - bubbleTextColor, - cardEmphasisBackgroundColor, - primaryFont, - subtle -} = defaultStyleOptions) => ({ - containerStyles: { - default: { - foregroundColors: { - default: { - default: bubbleTextColor, - subtle - }, - accent: { - default: accent, - subtle: accent - } - } - }, - emphasis: { - backgroundColor: cardEmphasisBackgroundColor, - foregroundColors: { - default: { - default: bubbleTextColor, - subtle - } - } - }, - accent: { - backgroundColor: '#C7DEF9', - foregroundColors: { - default: { - default: '#333333', - subtle: '#EE333333' - } - } - }, - good: { - backgroundColor: '#CCFFCC', - foregroundColors: { - default: { - default: '#333333', - subtle: '#EE333333' - } - } - }, - attention: { - backgroundColor: '#FFC5B2', - foregroundColors: { - default: { - default: '#333333', - subtle: '#EE333333' - } - } - }, - warning: { - backgroundColor: '#FFE2B2', - foregroundColors: { - default: { - default: '#333333', - subtle: '#EE333333' - } - } - } - }, - supportsInteractivity: true, - fontFamily: primaryFont, - imageSizes: { - small: 40, - medium: 80, - large: 160 - }, - actions: { - actionAlignment: 'stretch', - actionsOrientation: 'vertical', - buttonSpacing: 8, - maxActions: 100, - showCard: { - actionMode: 'inline', - inlineTopMargin: 8 - }, - spacing: 'default' - }, - adaptiveCard: { - allowCustomStyle: false - }, - imageSet: { - imageSize: 'medium', - maxImageHeight: 100 - }, - factSet: { - title: { - color: 'default', - size: 'default', - isSubtle: false, - weight: 'bolder', - wrap: true, - maxWidth: 150 - }, - value: { - color: 'default', - size: 'default', - isSubtle: false, - weight: 'default', - wrap: true - }, - spacing: 8 - } -}); diff --git a/packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig.ts b/packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig.ts new file mode 100644 index 0000000000..42319f4a81 --- /dev/null +++ b/packages/bundle/src/adaptiveCards/Styles/adaptiveCardHostConfig.ts @@ -0,0 +1,118 @@ +import { normalizeStyleOptions } from 'botframework-webchat-api'; + +import FullBundleStyleOptions from '../../FullBundleStyleOptions'; +import normalizeAdaptiveCardsStyleOptions from '../normalizeStyleOptions'; + +// https://docs.microsoft.com/en-us/adaptive-cards/rendering-cards/host-config + +export default function createAdaptiveCardsHostConfig(styleOptions: FullBundleStyleOptions) { + const { accent, bubbleTextColor, cardEmphasisBackgroundColor, primaryFont, subtle } = { + ...normalizeStyleOptions(styleOptions), + ...normalizeAdaptiveCardsStyleOptions(styleOptions) + }; + + return { + containerStyles: { + default: { + foregroundColors: { + default: { + default: bubbleTextColor, + subtle + }, + accent: { + default: accent, + subtle: accent + } + } + }, + emphasis: { + backgroundColor: cardEmphasisBackgroundColor, + foregroundColors: { + default: { + default: bubbleTextColor, + subtle + } + } + }, + accent: { + backgroundColor: '#C7DEF9', + foregroundColors: { + default: { + default: '#333333', + subtle: '#EE333333' + } + } + }, + good: { + backgroundColor: '#CCFFCC', + foregroundColors: { + default: { + default: '#333333', + subtle: '#EE333333' + } + } + }, + attention: { + backgroundColor: '#FFC5B2', + foregroundColors: { + default: { + default: '#333333', + subtle: '#EE333333' + } + } + }, + warning: { + backgroundColor: '#FFE2B2', + foregroundColors: { + default: { + default: '#333333', + subtle: '#EE333333' + } + } + } + }, + supportsInteractivity: true, + fontFamily: primaryFont, + imageSizes: { + small: 40, + medium: 80, + large: 160 + }, + actions: { + actionAlignment: 'stretch', + actionsOrientation: 'vertical', + buttonSpacing: 8, + maxActions: 100, + showCard: { + actionMode: 'inline', + inlineTopMargin: 8 + }, + spacing: 'default' + }, + adaptiveCard: { + allowCustomStyle: false + }, + imageSet: { + imageSize: 'medium', + maxImageHeight: 100 + }, + factSet: { + title: { + color: 'default', + size: 'default', + isSubtle: false, + weight: 'bolder', + wrap: true, + maxWidth: 150 + }, + value: { + color: 'default', + size: 'default', + isSubtle: false, + weight: 'default', + wrap: true + }, + spacing: 8 + } + }; +} diff --git a/packages/bundle/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.js b/packages/bundle/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.ts similarity index 50% rename from packages/bundle/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.js rename to packages/bundle/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.ts index fce615b348..762edf4758 100644 --- a/packages/bundle/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.js +++ b/packages/bundle/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.ts @@ -1,19 +1,24 @@ -import { defaultStyleOptions } from 'botframework-webchat-component'; +import { normalizeStyleOptions, StyleOptions } from 'botframework-webchat-api'; +import AdaptiveCardsStyleOptions from '../AdaptiveCardsStyleOptions'; import createAdaptiveCardRendererStyle from './StyleSet/AdaptiveCardRenderer'; import createAnimationCardAttachmentStyle from './StyleSet/AnimationCardAttachment'; import createAudioCardAttachmentStyle from './StyleSet/AudioCardAttachment'; +import normalizeAdaptiveCardsStyleOptions from '../normalizeStyleOptions'; // TODO: [P4] We should add a notice for people who want to use "styleSet" instead of "styleOptions". // "styleSet" is actually CSS stylesheet and it is based on the DOM tree. // DOM tree may change from time to time, thus, maintaining "styleSet" becomes a constant effort. -export default function createAdaptiveCardsStyleSet(options) { - options = { ...defaultStyleOptions, ...options }; +export default function createAdaptiveCardsStyleSet(options: StyleOptions & AdaptiveCardsStyleOptions): any { + const strictOptions = { + ...normalizeStyleOptions(options), + ...normalizeAdaptiveCardsStyleOptions(options) + }; return { - adaptiveCardRenderer: createAdaptiveCardRendererStyle(options), - animationCardAttachment: createAnimationCardAttachmentStyle(options), - audioCardAttachment: createAudioCardAttachmentStyle(options) + adaptiveCardRenderer: createAdaptiveCardRendererStyle(strictOptions), + animationCardAttachment: createAnimationCardAttachmentStyle(), + audioCardAttachment: createAudioCardAttachmentStyle(strictOptions) }; } diff --git a/packages/bundle/src/adaptiveCards/defaultStyleOptions.ts b/packages/bundle/src/adaptiveCards/defaultStyleOptions.ts new file mode 100644 index 0000000000..3418fe59a6 --- /dev/null +++ b/packages/bundle/src/adaptiveCards/defaultStyleOptions.ts @@ -0,0 +1,10 @@ +import AdaptiveCardsStyleOptions from './AdaptiveCardsStyleOptions'; + +const ADAPTIVE_CARDS_DEFAULT_STYLE_OPTIONS: Required = { + cardEmphasisBackgroundColor: '#F0F0F0', + cardPushButtonBackgroundColor: '#0063B1', + cardPushButtonTextColor: 'white', + richCardWrapTitle: false +}; + +export default ADAPTIVE_CARDS_DEFAULT_STYLE_OPTIONS; diff --git a/packages/bundle/src/adaptiveCards/normalizeStyleOptions.ts b/packages/bundle/src/adaptiveCards/normalizeStyleOptions.ts new file mode 100644 index 0000000000..68c30bef97 --- /dev/null +++ b/packages/bundle/src/adaptiveCards/normalizeStyleOptions.ts @@ -0,0 +1,8 @@ +import AdaptiveCardsStyleOptions, { StrictAdaptiveCardsStyleOptions } from './AdaptiveCardsStyleOptions'; +import defaultStyleOptions from './defaultStyleOptions'; + +export default function normalizeStyleOptions( + styleOptions: AdaptiveCardsStyleOptions +): StrictAdaptiveCardsStyleOptions { + return { ...defaultStyleOptions, ...styleOptions }; +} diff --git a/packages/bundle/src/createFullStyleSet.js b/packages/bundle/src/createFullStyleSet.ts similarity index 81% rename from packages/bundle/src/createFullStyleSet.js rename to packages/bundle/src/createFullStyleSet.ts index 27ccf4e354..ec96928fa7 100644 --- a/packages/bundle/src/createFullStyleSet.js +++ b/packages/bundle/src/createFullStyleSet.ts @@ -1,11 +1,13 @@ import { createStyleSet } from 'botframework-webchat-component'; +import { StyleOptions } from 'botframework-webchat-api'; + import createAdaptiveCardsStyleSet from './adaptiveCards/Styles/createAdaptiveCardsStyleSet'; // TODO: [P4] We should add a notice for people who want to use "styleSet" instead of "styleOptions". // "styleSet" is actually CSS stylesheet and it is based on the DOM tree. // DOM tree may change from time to time, thus, maintaining "styleSet" becomes a constant effort. -export default function createFullStyleSet(options) { +export default function createFullStyleSet(options: StyleOptions) { return { ...createStyleSet(options), ...createAdaptiveCardsStyleSet(options) diff --git a/packages/bundle/src/fullBundleDefaultStyleOptions.ts b/packages/bundle/src/fullBundleDefaultStyleOptions.ts new file mode 100644 index 0000000000..764dd19fe3 --- /dev/null +++ b/packages/bundle/src/fullBundleDefaultStyleOptions.ts @@ -0,0 +1,11 @@ +import { defaultStyleOptions } from 'botframework-webchat-api'; +import adaptiveCardsDefaultStyleOptions from './adaptiveCards/defaultStyleOptions'; + +import FullBundleStyleOptions from './FullBundleStyleOptions'; + +const FULL_BUNDLE_DEFAULT_STYLE_OPTIONS: Required = { + ...defaultStyleOptions, + ...adaptiveCardsDefaultStyleOptions +}; + +export default FULL_BUNDLE_DEFAULT_STYLE_OPTIONS; diff --git a/packages/bundle/src/index-es5.ts b/packages/bundle/src/index-es5.ts index 313d011e08..4fe7301f7c 100644 --- a/packages/bundle/src/index-es5.ts +++ b/packages/bundle/src/index-es5.ts @@ -1,3 +1,5 @@ +// IMPORTANT: To export anything from this file, add it to index-es5.tsx, which is the .d.ts for this file. + /* eslint dot-notation: ["error", { "allowPattern": "^WebChat$" }] */ // window['WebChat'] is required for TypeScript diff --git a/packages/bundle/src/index-es5.tsx b/packages/bundle/src/index-es5.tsx new file mode 100644 index 0000000000..4294c2c2c8 --- /dev/null +++ b/packages/bundle/src/index-es5.tsx @@ -0,0 +1,49 @@ +import { FC } from 'react'; +import { + Components as ComponentsFromComponent, + ComposerProps, + ReactWebChatProps +} from 'botframework-webchat-component'; + +import StyleOptions from './FullBundleStyleOptions'; + +type Replace = Omit & T2; + +/** Creates a set of styles with support of Adaptive Cards */ +declare function createStyleSet(styleOptions: StyleOptions): any; + +declare const Components: Omit & { + Composer: FC< + Replace< + ComposerProps, + { + /** Style options with support of Adaptive Cards */ + styleOptions?: StyleOptions; + } + > + >; +}; + +/** React-based Web Chat with support of Adaptive Cards */ +declare const ReactWebChat: FC< + Replace< + ReactWebChatProps, + { + /** Style options with support of Adaptive Cards */ + styleOptions?: StyleOptions; + } + > +>; + +export default ReactWebChat; +export { Components, createStyleSet }; +export type { StyleOptions }; + +// Doc: +// - We don't want to export the whole index.ts, we just want to export what the user actually needed +// - That's why we only exporting index.tsx (we cannot name it index.d.ts because TSC won't pick it up) +// - Changing between full bundle and minimal should be very smooth +// - That's why we name both StyleOptions the same +// - To use minimal, import 'botframework-webchat/lib/index-minimal'; +// - Declarations need to be emitted to /lib/*.d.ts for code-splitting purpose +// - import 'botframework-webchat/lib/index-minimal' should see IntelliSense support diff --git a/packages/bundle/src/index-minimal.ts b/packages/bundle/src/index-minimal.ts index 1284f045c9..ae74bf8d10 100644 --- a/packages/bundle/src/index-minimal.ts +++ b/packages/bundle/src/index-minimal.ts @@ -1,3 +1,5 @@ +// IMPORTANT: To export anything from this file, add it to index-minimal.tsx, which is the .d.ts for this file. + /* eslint dot-notation: ["error", { "allowPattern": "^WebChat$" }] */ // window['WebChat'] is required for TypeScript diff --git a/packages/bundle/src/index-minimal.tsx b/packages/bundle/src/index-minimal.tsx new file mode 100644 index 0000000000..e9c84c76ee --- /dev/null +++ b/packages/bundle/src/index-minimal.tsx @@ -0,0 +1,9 @@ +import { StyleOptions } from 'botframework-webchat-api'; +import ReactWebChat, { Components } from 'botframework-webchat-component'; + +/** Creates a set of styles */ +declare function createStyleSet(styleOptions: StyleOptions): any; + +export default ReactWebChat; +export { Components, createStyleSet }; +export type { StyleOptions }; diff --git a/packages/bundle/src/index.ts b/packages/bundle/src/index.ts index fc0e483c2f..92beb6d471 100644 --- a/packages/bundle/src/index.ts +++ b/packages/bundle/src/index.ts @@ -1,3 +1,5 @@ +// IMPORTANT: To export anything from this file, add it to index.tsx, which is the .d.ts for this file. + /* eslint dot-notation: ["error", { "allowPattern": "^WebChat$" }] */ // window['WebChat'] is required for TypeScript diff --git a/packages/bundle/src/index.tsx b/packages/bundle/src/index.tsx new file mode 100644 index 0000000000..8eb0019032 --- /dev/null +++ b/packages/bundle/src/index.tsx @@ -0,0 +1,45 @@ +import { FC } from 'react'; +import { ComposerProps, ReactWebChatProps } from 'botframework-webchat-component'; + +import StyleOptions from './FullBundleStyleOptions'; + +type Replace = Omit & T2; + +/** Creates a set of styles with support of Adaptive Cards */ +declare function createStyleSet(styleOptions: StyleOptions): any; + +declare const Components: { + Composer: FC< + Replace< + ComposerProps, + { + /** Style options with support of Adaptive Cards */ + styleOptions?: StyleOptions; + } + > + >; +}; + +/** React-based Web Chat with support of Adaptive Cards */ +declare const ReactWebChat: FC< + Replace< + ReactWebChatProps, + { + /** Style options with support of Adaptive Cards */ + styleOptions?: StyleOptions; + } + > +>; + +export default ReactWebChat; +export { Components, createStyleSet }; +export type { StyleOptions }; + +// Doc: +// - We don't want to export the whole index.ts, we just want to export what the user actually needed +// - That's why we only exporting index.tsx (we cannot name it index.d.ts because TSC won't pick it up) +// - Changing between full bundle and minimal should be very smooth +// - That's why we name both StyleOptions the same +// - To use minimal, import 'botframework-webchat/lib/index-minimal'; +// - Declarations need to be emitted to /lib/*.d.ts for code-splitting purpose +// - import 'botframework-webchat/lib/index-minimal' should see IntelliSense support diff --git a/packages/bundle/src/tsconfig.json b/packages/bundle/src/tsconfig.json index ca32a35acf..67687e45e4 100644 --- a/packages/bundle/src/tsconfig.json +++ b/packages/bundle/src/tsconfig.json @@ -3,11 +3,13 @@ "allowSyntheticDefaultImports": true, "declaration": true, "declarationDir": "../lib", + "declarationMap": true, "emitDeclarationOnly": true, - "isolatedModules": true, "jsx": "react", "preserveWatchOutput": true, "pretty": true, - "skipLibCheck": true - } + "skipLibCheck": true, + "sourceMap": true + }, + "files": ["index.tsx", "index-es5.tsx", "index-minimal.tsx"] } diff --git a/packages/bundle/src/useComposerProps.js b/packages/bundle/src/useComposerProps.js index c1222e68e3..a0afa9ba57 100644 --- a/packages/bundle/src/useComposerProps.js +++ b/packages/bundle/src/useComposerProps.js @@ -1,6 +1,6 @@ +import { concatMiddleware } from 'botframework-webchat-component'; import { useMemo } from 'react'; -import { concatMiddleware, defaultStyleOptions } from 'botframework-webchat-component'; import createAdaptiveCardsAttachmentForScreenReaderMiddleware from './adaptiveCards/createAdaptiveCardsAttachmentForScreenReaderMiddleware'; import createAdaptiveCardsAttachmentMiddleware from './adaptiveCards/createAdaptiveCardsAttachmentMiddleware'; import createAdaptiveCardsStyleSet from './adaptiveCards/Styles/createAdaptiveCardsStyleSet'; @@ -24,11 +24,9 @@ export default function useComposerProps({ [attachmentForScreenReaderMiddleware] ); - const patchedStyleOptions = useMemo(() => ({ ...defaultStyleOptions, ...styleOptions }), [styleOptions]); - // When styleSet is not specified, the styleOptions will be used to create Adaptive Cards styleSet and merged into useStyleSet. - const extraStyleSet = useMemo(() => (styleSet ? undefined : createAdaptiveCardsStyleSet(patchedStyleOptions)), [ - patchedStyleOptions, + const extraStyleSet = useMemo(() => (styleSet ? undefined : createAdaptiveCardsStyleSet(styleOptions)), [ + styleOptions, styleSet ]); diff --git a/packages/component/.eslintrc.yml b/packages/component/.eslintrc.yml index 3d1c9cc36d..1046d75635 100644 --- a/packages/component/.eslintrc.yml +++ b/packages/component/.eslintrc.yml @@ -3,6 +3,9 @@ extends: plugins: - prettier - react-hooks +- '@typescript-eslint/eslint-plugin' +parser: + '@typescript-eslint/parser' rules: # plugins prettier/prettier: error @@ -89,3 +92,11 @@ rules: react/jsx-wrap-multilines: error # Conflict with no-extra-parens react-hooks/rules-of-hooks: error react-hooks/exhaustive-deps: warn + + # TypeScript + + # The correct way to use with typescript-eslint is to disable the core version. + # https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md#how-to-use + no-use-before-define: off + '@typescript-eslint/no-use-before-define': + - error diff --git a/packages/component/babel.config.json b/packages/component/babel.config.json index cfadc9c45f..9ea0a28993 100644 --- a/packages/component/babel.config.json +++ b/packages/component/babel.config.json @@ -5,6 +5,7 @@ "plugins": ["babel-plugin-istanbul"] } }, + "ignore": ["src/index.tsx"], "overrides": [ { "plugins": [], diff --git a/packages/component/package-lock.json b/packages/component/package-lock.json index 98a96a9487..9e640d7a2a 100644 --- a/packages/component/package-lock.json +++ b/packages/component/package-lock.json @@ -3553,6 +3553,32 @@ "upath": "^1.1.1" } }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -3608,6 +3634,141 @@ "vfile-message": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.19.0.tgz", + "integrity": "sha512-CRQNQ0mC2Pa7VLwKFbrGVTArfdVDdefS+gTw0oC98vSI98IX5A8EVH4BzJ2FOB0YlCmm8Im36Elad/Jgtvveaw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.19.0", + "@typescript-eslint/scope-manager": "4.19.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.19.0.tgz", + "integrity": "sha512-9/23F1nnyzbHKuoTqFN1iXwN3bvOm/PRIXSBR3qFAYotK/0LveEOHr5JT1WZSzcD6BESl8kPOG3OoDRKO84bHA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.19.0.tgz", + "integrity": "sha512-/uabZjo2ZZhm66rdAu21HA8nQebl3lAIDcybUoOxoI7VbZBYavLIwtOOmykKCJy+Xq6Vw6ugkiwn8Js7D6wieA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", + "debug": "^4.1.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.19.0.tgz", + "integrity": "sha512-GGy4Ba/hLXwJXygkXqMzduqOMc+Na6LrJTZXJWVhRrSuZeXmu8TAnniQVKgj8uTRKe4igO2ysYzH+Np879G75g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0" + } + }, + "@typescript-eslint/types": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.19.0.tgz", + "integrity": "sha512-A4iAlexVvd4IBsSTNxdvdepW0D4uR/fwxDrKUa+iEY9UWvGREu2ZyB8ylTENM1SH8F7bVC9ac9+si3LWNxcBuA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.19.0.tgz", + "integrity": "sha512-3xqArJ/A62smaQYRv2ZFyTA+XxGGWmlDYrsfZG68zJeNbeqRScnhf81rUVa6QG4UgzHnXw5VnMT5cg75dQGDkA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.19.0.tgz", + "integrity": "sha512-aGPS6kz//j7XLSlgpzU2SeTqHPsmRYxFztj2vPuMMFJXZudpRSehE3WCV+BaxwZFvfAqMoSd86TEuM0PQ59E/A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.19.0", + "eslint-visitor-keys": "^2.0.0" + } + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -3913,6 +4074,12 @@ } } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -4207,6 +4374,15 @@ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "optional": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -5180,6 +5356,15 @@ } } }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -6037,6 +6222,74 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -6048,6 +6301,15 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "fbjs": { "version": "0.8.17", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", @@ -6083,6 +6345,12 @@ "flat-cache": "^3.0.4" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "filewatcher": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/filewatcher/-/filewatcher-3.0.1.tgz", @@ -6371,6 +6639,34 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "globby": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -7271,6 +7567,12 @@ "readable-stream": "^2.0.1" } }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -7392,6 +7694,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -7899,6 +8207,12 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -7914,8 +8228,7 @@ "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "optional": true + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pify": { "version": "4.0.1", @@ -8090,6 +8403,12 @@ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -8511,6 +8830,12 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -8528,6 +8853,15 @@ "inherits": "^2.0.1" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -9457,6 +9791,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -9828,7 +10171,11 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } } } }, diff --git a/packages/component/package.json b/packages/component/package.json index 4b75a25e13..c41e02da20 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -3,6 +3,7 @@ "version": "0.0.0-0", "description": "React component of botframework-webchat", "main": "lib/index.js", + "typings": "lib/index.d.ts", "publishConfig": { "access": "public" }, @@ -34,6 +35,8 @@ "@babel/preset-typescript": "^7.13.0", "@types/node": "^14.14.35", "@types/react": "^16.9.55", + "@typescript-eslint/eslint-plugin": "^4.19.0", + "@typescript-eslint/parser": "^4.19.0", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "concurrently": "^6.0.0", diff --git a/packages/component/src/BasicTranscript.js b/packages/component/src/BasicTranscript.js index d1a55b079f..a3231ab9b7 100644 --- a/packages/component/src/BasicTranscript.js +++ b/packages/component/src/BasicTranscript.js @@ -265,7 +265,7 @@ const InternalTranscript = ({ activityElementsRef, className }) => { let showCallout; - // Depends on different "showAvatarInGroup" setting, we will show the avatar in different positions. + // Depending on the "showAvatarInGroup" setting, the avatar will render in different positions. if (showAvatarInGroup === 'sender') { if (topSideNub) { showCallout = firstInSenderGroup && firstInSenderAndStatusGroup; @@ -766,6 +766,8 @@ const InternalTranscript = ({ activityElementsRef, className }) => { ))} + {/* TODO: [P2] Fix ESLint error `no-use-before-define` */} + {/* eslint-disable-next-line @typescript-eslint/no-use-before-define */} .bubble-box': { - maxWidth: bubbleMaxWidth, - minWidth: bubbleMinWidth - }, - - '& > .filler': { - minWidth: paddingRegular - } - }; -} diff --git a/packages/component/src/Styles/StyleSet/SingleAttachmentActivity.ts b/packages/component/src/Styles/StyleSet/SingleAttachmentActivity.ts new file mode 100644 index 0000000000..1e28a7bfac --- /dev/null +++ b/packages/component/src/Styles/StyleSet/SingleAttachmentActivity.ts @@ -0,0 +1,18 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; + +export default function createSingleCardActivityStyle({ + bubbleMaxWidth, + bubbleMinWidth, + paddingRegular +}: StrictStyleOptions) { + return { + '& > .bubble-box': { + maxWidth: bubbleMaxWidth, + minWidth: bubbleMinWidth + }, + + '& > .filler': { + minWidth: paddingRegular + } + }; +} diff --git a/packages/component/src/Styles/StyleSet/SpinnerAnimation.js b/packages/component/src/Styles/StyleSet/SpinnerAnimation.ts similarity index 99% rename from packages/component/src/Styles/StyleSet/SpinnerAnimation.js rename to packages/component/src/Styles/StyleSet/SpinnerAnimation.ts index f3dc5158ed..293add109a 100644 --- a/packages/component/src/Styles/StyleSet/SpinnerAnimation.js +++ b/packages/component/src/Styles/StyleSet/SpinnerAnimation.ts @@ -1,3 +1,5 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; + import { toByteArray } from 'base64-js'; const DEFAULT_IMAGE_BASE64 = @@ -11,7 +13,7 @@ export default function createSpinnerAnimationStyle({ spinnerAnimationHeight, spinnerAnimationWidth, spinnerAnimationPadding -}) { +}: StrictStyleOptions) { defaultImageBlobURL || (defaultImageBlobURL = URL.createObjectURL( new Blob([toByteArray(DEFAULT_IMAGE_BASE64)], { type: DEFAULT_IMAGE_TYPE }) diff --git a/packages/component/src/Styles/StyleSet/StackedLayout.js b/packages/component/src/Styles/StyleSet/StackedLayout.ts similarity index 96% rename from packages/component/src/Styles/StyleSet/StackedLayout.js rename to packages/component/src/Styles/StyleSet/StackedLayout.ts index 2d38ceb025..78f8b59280 100644 --- a/packages/component/src/Styles/StyleSet/StackedLayout.js +++ b/packages/component/src/Styles/StyleSet/StackedLayout.ts @@ -1,12 +1,14 @@ /* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createStackedLayoutStyle({ avatarSize, bubbleMaxWidth, bubbleMinWidth, paddingRegular, transitionDuration -}) { +}: StrictStyleOptions) { return { '&.webchat__stacked-layout': { marginLeft: paddingRegular, diff --git a/packages/component/src/Styles/StyleSet/SuggestedAction.js b/packages/component/src/Styles/StyleSet/SuggestedAction.ts similarity index 96% rename from packages/component/src/Styles/StyleSet/SuggestedAction.js rename to packages/component/src/Styles/StyleSet/SuggestedAction.ts index a51bbf2fc4..ac37d16fbb 100644 --- a/packages/component/src/Styles/StyleSet/SuggestedAction.js +++ b/packages/component/src/Styles/StyleSet/SuggestedAction.ts @@ -1,5 +1,7 @@ /* eslint no-magic-numbers: "off" */ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createSuggestedActionStyle({ accent, paddingRegular, @@ -20,7 +22,7 @@ export default function createSuggestedActionStyle({ suggestedActionHeight, suggestedActionsStackedLayoutButtonMaxHeight, subtle -}) { +}: StrictStyleOptions) { return { '&.webchat__suggested-action': { display: 'flex', diff --git a/packages/component/src/Styles/StyleSet/SuggestedActions.js b/packages/component/src/Styles/StyleSet/SuggestedActions.ts similarity index 98% rename from packages/component/src/Styles/StyleSet/SuggestedActions.js rename to packages/component/src/Styles/StyleSet/SuggestedActions.ts index 121d0cd5a1..48d631c042 100644 --- a/packages/component/src/Styles/StyleSet/SuggestedActions.js +++ b/packages/component/src/Styles/StyleSet/SuggestedActions.ts @@ -1,6 +1,8 @@ /* eslint no-empty-pattern: "off" */ /* eslint no-magic-numbers: ["error", { "ignore": [1.5, 2] }] */ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createSuggestedActionsStyle({ paddingRegular, suggestedActionsCarouselFlipperSize, @@ -15,7 +17,7 @@ export default function createSuggestedActionsStyle({ transcriptOverlayButtonColorOnDisabled, transcriptOverlayButtonColorOnFocus, transcriptOverlayButtonColorOnHover -}) { +}: StrictStyleOptions) { return { '&.webchat__suggested-actions': { '&.webchat__suggested-actions--carousel-layout': { diff --git a/packages/component/src/Styles/StyleSet/TextContent.js b/packages/component/src/Styles/StyleSet/TextContent.ts similarity index 90% rename from packages/component/src/Styles/StyleSet/TextContent.js rename to packages/component/src/Styles/StyleSet/TextContent.ts index 6aef395d91..11eddddc78 100644 --- a/packages/component/src/Styles/StyleSet/TextContent.js +++ b/packages/component/src/Styles/StyleSet/TextContent.ts @@ -1,12 +1,14 @@ /* eslint no-magic-numbers: "off" */ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createTextContentStyle({ bubbleMaxWidth, bubbleMinHeight, markdownExternalLinkIconImage, primaryFont, paddingRegular -}) { +}: StrictStyleOptions) { return { fontFamily: primaryFont, margin: 0, diff --git a/packages/component/src/Styles/StyleSet/Toast.js b/packages/component/src/Styles/StyleSet/Toast.ts similarity index 95% rename from packages/component/src/Styles/StyleSet/Toast.js rename to packages/component/src/Styles/StyleSet/Toast.ts index 7b07f97ab6..6ee99e58be 100644 --- a/packages/component/src/Styles/StyleSet/Toast.js +++ b/packages/component/src/Styles/StyleSet/Toast.ts @@ -1,4 +1,5 @@ /* eslint no-magic-numbers: ["off"] */ +import { StrictStyleOptions } from 'botframework-webchat-api'; export default function createToastStyle({ primaryFont, @@ -10,7 +11,7 @@ export default function createToastStyle({ toastSuccessColor, toastTextPadding, toastWarnColor -}) { +}: StrictStyleOptions) { return { fontFamily: primaryFont, fontSize: toastFontSize, diff --git a/packages/component/src/Styles/StyleSet/Toaster.js b/packages/component/src/Styles/StyleSet/Toaster.ts similarity index 97% rename from packages/component/src/Styles/StyleSet/Toaster.js rename to packages/component/src/Styles/StyleSet/Toaster.ts index 31d341c0cc..42df1c28fb 100644 --- a/packages/component/src/Styles/StyleSet/Toaster.js +++ b/packages/component/src/Styles/StyleSet/Toaster.ts @@ -1,5 +1,7 @@ /* eslint no-magic-numbers: ["off"] */ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createToasterStyle({ primaryFont, toasterHeight, @@ -16,7 +18,7 @@ export default function createToasterStyle({ toastSuccessColor, toastWarnBackgroundColor, toastWarnColor -}) { +}: StrictStyleOptions) { return { overflowY: 'hidden', diff --git a/packages/component/src/Styles/StyleSet/TypingAnimation.js b/packages/component/src/Styles/StyleSet/TypingAnimation.ts similarity index 98% rename from packages/component/src/Styles/StyleSet/TypingAnimation.js rename to packages/component/src/Styles/StyleSet/TypingAnimation.ts index d9b2ee77b1..132672e61c 100644 --- a/packages/component/src/Styles/StyleSet/TypingAnimation.js +++ b/packages/component/src/Styles/StyleSet/TypingAnimation.ts @@ -1,3 +1,4 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; import { toByteArray } from 'base64-js'; const DEFAULT_IMAGE_BASE64 = @@ -10,7 +11,7 @@ export default function createTypingAnimationStyle({ typingAnimationBackgroundImage, typingAnimationHeight, typingAnimationWidth -}) { +}: StrictStyleOptions) { defaultImageBlobURL || (defaultImageBlobURL = URL.createObjectURL( new Blob([toByteArray(DEFAULT_IMAGE_BASE64)], { type: DEFAULT_IMAGE_TYPE }) diff --git a/packages/component/src/Styles/StyleSet/TypingIndicator.js b/packages/component/src/Styles/StyleSet/TypingIndicator.ts similarity index 75% rename from packages/component/src/Styles/StyleSet/TypingIndicator.js rename to packages/component/src/Styles/StyleSet/TypingIndicator.ts index c615238eac..3101161da4 100644 --- a/packages/component/src/Styles/StyleSet/TypingIndicator.js +++ b/packages/component/src/Styles/StyleSet/TypingIndicator.ts @@ -1,4 +1,6 @@ -export default function createTypingIndicatorStyle({ paddingRegular }) { +import { StrictStyleOptions } from 'botframework-webchat-api'; + +export default function createTypingIndicatorStyle({ paddingRegular }: StrictStyleOptions) { return { paddingBottom: paddingRegular, diff --git a/packages/component/src/Styles/StyleSet/UploadButton.js b/packages/component/src/Styles/StyleSet/UploadButton.ts similarity index 84% rename from packages/component/src/Styles/StyleSet/UploadButton.js rename to packages/component/src/Styles/StyleSet/UploadButton.ts index 923a09b0ba..b1136ebde9 100644 --- a/packages/component/src/Styles/StyleSet/UploadButton.js +++ b/packages/component/src/Styles/StyleSet/UploadButton.ts @@ -1,10 +1,12 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createUploadButtonStyle({ sendBoxButtonColor, sendBoxButtonColorOnFocus, sendBoxButtonColorOnHover, sendBoxHeight, subtle -}) { +}: StrictStyleOptions) { return { // We use the sendBoxHeight, so the button looks square width: sendBoxHeight, diff --git a/packages/component/src/Styles/StyleSet/VideoAttachment.js b/packages/component/src/Styles/StyleSet/VideoAttachment.ts similarity index 100% rename from packages/component/src/Styles/StyleSet/VideoAttachment.js rename to packages/component/src/Styles/StyleSet/VideoAttachment.ts diff --git a/packages/component/src/Styles/StyleSet/VideoContent.js b/packages/component/src/Styles/StyleSet/VideoContent.js deleted file mode 100644 index e8a5796680..0000000000 --- a/packages/component/src/Styles/StyleSet/VideoContent.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function createVideoContentStyle({ videoHeight }) { - return { - height: videoHeight, - width: '100%' - }; -} diff --git a/packages/component/src/Styles/StyleSet/VideoContent.ts b/packages/component/src/Styles/StyleSet/VideoContent.ts new file mode 100644 index 0000000000..9c23dcda52 --- /dev/null +++ b/packages/component/src/Styles/StyleSet/VideoContent.ts @@ -0,0 +1,8 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; + +export default function createVideoContentStyle({ videoHeight }: StrictStyleOptions) { + return { + height: videoHeight, + width: '100%' + }; +} diff --git a/packages/component/src/Styles/StyleSet/VimeoContent.js b/packages/component/src/Styles/StyleSet/VimeoContent.js deleted file mode 100644 index 4be04a759d..0000000000 --- a/packages/component/src/Styles/StyleSet/VimeoContent.js +++ /dev/null @@ -1,7 +0,0 @@ -export default function createVimeoContentStyle({ videoHeight }) { - return { - border: 0, - height: videoHeight, - width: '100%' - }; -} diff --git a/packages/component/src/Styles/StyleSet/VimeoContent.ts b/packages/component/src/Styles/StyleSet/VimeoContent.ts new file mode 100644 index 0000000000..02e2764862 --- /dev/null +++ b/packages/component/src/Styles/StyleSet/VimeoContent.ts @@ -0,0 +1,9 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; + +export default function createVimeoContentStyle({ videoHeight }: StrictStyleOptions) { + return { + border: 0, + height: videoHeight, + width: '100%' + }; +} diff --git a/packages/component/src/Styles/StyleSet/WarningNotification.js b/packages/component/src/Styles/StyleSet/WarningNotification.ts similarity index 91% rename from packages/component/src/Styles/StyleSet/WarningNotification.js rename to packages/component/src/Styles/StyleSet/WarningNotification.ts index f00e105122..7ec46b92a6 100644 --- a/packages/component/src/Styles/StyleSet/WarningNotification.js +++ b/packages/component/src/Styles/StyleSet/WarningNotification.ts @@ -1,3 +1,5 @@ +import { StrictStyleOptions } from 'botframework-webchat-api'; + export default function createWarningNotificationStyle({ connectivityIconPadding, connectivityMarginLeftRight, @@ -6,7 +8,7 @@ export default function createWarningNotificationStyle({ primaryFont, slowConnectivity, notificationText -}) { +}: StrictStyleOptions) { return { alignItems: 'center', color: notificationText, diff --git a/packages/component/src/Styles/StyleSet/YouTubeContent.js b/packages/component/src/Styles/StyleSet/YouTubeContent.ts similarity index 61% rename from packages/component/src/Styles/StyleSet/YouTubeContent.js rename to packages/component/src/Styles/StyleSet/YouTubeContent.ts index fe4aa4cb95..27cfd14749 100644 --- a/packages/component/src/Styles/StyleSet/YouTubeContent.js +++ b/packages/component/src/Styles/StyleSet/YouTubeContent.ts @@ -1,4 +1,6 @@ -export default function createYouTubeContentStyle({ videoHeight }) { +import { StrictStyleOptions } from 'botframework-webchat-api'; + +export default function createYouTubeContentStyle({ videoHeight }: StrictStyleOptions) { return { border: 0, height: videoHeight, diff --git a/packages/component/src/Styles/createStyleSet.js b/packages/component/src/Styles/createStyleSet.ts similarity index 74% rename from packages/component/src/Styles/createStyleSet.js rename to packages/component/src/Styles/createStyleSet.ts index 957291a155..45f913daac 100644 --- a/packages/component/src/Styles/createStyleSet.js +++ b/packages/component/src/Styles/createStyleSet.ts @@ -1,4 +1,6 @@ /* eslint-disable complexity */ +import { normalizeStyleOptions, StyleOptions } from 'botframework-webchat-api'; + import createActivitiesStyle from './StyleSet/Activities'; import createAudioAttachmentStyle from './StyleSet/AudioAttachment'; import createAudioContentStyle from './StyleSet/AudioContent'; @@ -39,69 +41,17 @@ import createVimeoContentStyle from './StyleSet/VimeoContent'; import createWarningNotificationStyle from './StyleSet/WarningNotification'; import createYouTubeContentStyle from './StyleSet/YouTubeContent'; -import defaultStyleOptions from './defaultStyleOptions'; - // TODO: [P4] We should add a notice for people who want to use "styleSet" instead of "styleOptions". // "styleSet" is actually CSS stylesheet and it is based on the DOM tree. // DOM tree may change from time to time, thus, maintaining "styleSet" becomes a constant effort. -export default function createStyleSet(options) { - options = { ...defaultStyleOptions, ...options }; - - // Keep this list flat (no nested style) and serializable (no functions) - - // TODO: [P4] Deprecate this code after bump to v5 - const { bubbleFromUserNubOffset, bubbleNubOffset } = options; - - if (bubbleFromUserNubOffset === 'top') { - options.bubbleFromUserNubOffset = 0; - } else if (typeof bubbleFromUserNubOffset !== 'number') { - options.bubbleFromUserNubOffset = -0; - } - - if (bubbleNubOffset === 'top') { - options.bubbleNubOffset = 0; - } else if (typeof bubbleNubOffset !== 'number') { - options.bubbleNubOffset = -0; - } - - if (options.emojiSet === true) { - options.emojiSet = { - ':)': '😊', - ':-)': '😊', - '(:': '😊', - '(-:': '😊', - ':-|': '😐', - ':|': '😐', - ':-(': '☚ī¸', - ':(': '☚ī¸', - ':-D': '😀', - ':D': '😀', - ':-p': '😛', - ':p': '😛', - ':-P': '😛', - ':P': '😛', - ':-o': '😲', - ':o': '😲', - ':O': '😲', - ':-O': '😲', - ':-0': '😲', - ':0': '😲', - ';-)': '😉', - ';)': '😉', - '<3': '❤ī¸', - ' `'${font}'`).join(', '); -} - -const DEFAULT_ACCENT = '#0063B1'; -const DEFAULT_SUBTLE = '#767676'; // With contrast 4.5:1 to white -const PADDING_REGULAR = 10; - -const DEFAULT_OPTIONS = { - // Color and paddings - accent: DEFAULT_ACCENT, - activeActivityOutlineColor: DEFAULT_SUBTLE, - backgroundColor: 'White', - cardEmphasisBackgroundColor: '#F0F0F0', - paddingRegular: PADDING_REGULAR, - paddingWide: PADDING_REGULAR * 2, - subtle: DEFAULT_SUBTLE, - - // Word break - messageActivityWordBreak: 'break-word', // 'normal' || 'break-all' || 'break-word' || 'keep-all' - - // Fonts - fontSizeSmall: '80%', - monospaceFont: fontFamily(['Consolas', 'Courier New', 'monospace']), - primaryFont: fontFamily(['Calibri', 'Helvetica Neue', 'Arial', 'sans-serif']), - - // Avatar - avatarBorderRadius: '50%', - avatarSize: 40, - botAvatarBackgroundColor: undefined, // defaults to accent color - botAvatarImage: undefined, // Or a string of URL. Can be a data URI or blob. - botAvatarInitials: undefined, // Or a string. Empty strings means it has avatar but not initials inside. - userAvatarBackgroundColor: undefined, // defaults to accent color - userAvatarImage: undefined, // Or a string of URL. Can be a data URI or blob. - userAvatarInitials: undefined, // Or a string. Empty strings means it has avatar but not initials inside. - showAvatarInGroup: 'status', // Or 'sender' or true (on every activity). - - // Bubble - // TODO: Should we make a bubbleFromBot* - bubbleBackground: 'White', - bubbleBorderColor: '#E6E6E6', - bubbleBorderRadius: 2, - bubbleBorderStyle: 'solid', - bubbleBorderWidth: 1, - bubbleFromUserBackground: 'White', - bubbleFromUserBorderColor: '#E6E6E6', - bubbleFromUserBorderRadius: 2, - bubbleFromUserBorderStyle: 'solid', - bubbleFromUserBorderWidth: 1, - bubbleFromUserNubOffset: 0, // Either a positive/negative number, or "bottom" - bubbleFromUserNubSize: undefined, // Or a number. 0 means a sharp corner. - bubbleFromUserTextColor: 'Black', - bubbleImageHeight: 240, - bubbleMaxWidth: 480, // screen width = 600px - bubbleMinHeight: 40, - bubbleMinWidth: 250, // min screen width = 300px, Microsoft Edge requires 372px (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13621468/) - bubbleNubOffset: 0, // Either a positive/negative number, or "bottom" - bubbleNubSize: undefined, // Or a number. 0 means a sharp corner. - bubbleTextColor: 'Black', - - // Markdown - markdownRespectCRLF: true, - - // Rich Cards - richCardWrapTitle: false, // Applies to subtitles as well - - // Root - rootHeight: '100%', - rootWidth: '100%', - rootZIndex: 0, // "z-index" for the root container of Web Chat. This will form a new stacking context so "z-index" used in children won't pollute. - - // Scroll to end button - hideScrollToEndButton: false, - - // Send box - hideSendBox: false, - hideUploadButton: false, - microphoneButtonColorOnDictate: '#F33', - sendBoxBackground: 'White', - sendBoxButtonColor: undefined, // defaults to subtle - sendBoxButtonColorOnDisabled: '#CCC', - sendBoxButtonColorOnFocus: '#333', - sendBoxButtonColorOnHover: '#333', - sendBoxDisabledTextColor: undefined, // defaults to subtle - sendBoxHeight: 40, - sendBoxMaxHeight: 200, - sendBoxTextColor: 'Black', - // TODO: We should deprecate this because there isn't an easy way to make the width of the send box narrower than the transcript - sendBoxBorderBottom: '', - sendBoxBorderLeft: '', - sendBoxBorderRight: '', - sendBoxBorderTop: 'solid 1px #E6E6E6', - sendBoxPlaceholderColor: undefined, // defaults to subtle - sendBoxTextWrap: false, - sendBoxButtonAlignment: 'stretch', // "top", "bottom", or "stretch" - - // Visually show spoken text - showSpokenText: false, - - // Suggested actions - suggestedActionBackground: 'White', - suggestedActionBorder: undefined, // split into 3, null - suggestedActionBorderColor: undefined, // defaults to accent - suggestedActionBorderRadius: 0, - suggestedActionBorderStyle: 'solid', - suggestedActionBorderWidth: 2, - suggestedActionDisabledBackground: undefined, // defaults to suggestedActionBackground - suggestedActionDisabledBorderColor: '#E6E6E6', - suggestedActionDisabledBorderStyle: 'solid', - suggestedActionDisabledBorderWidth: 2, - suggestedActionDisabledTextColor: undefined, // defaults to subtle - suggestedActionHeight: 40, - suggestedActionImageHeight: 20, - suggestedActionLayout: 'carousel', // either 'carousel' or 'stacked' - suggestedActionTextColor: null, - - // Suggested actions carousel layout - suggestedActionsCarouselFlipperCursor: null, // Cursor when mouse over on flipper - suggestedActionsCarouselFlipperBoxWidth: 40, // Flipper bounding box size - suggestedActionsCarouselFlipperSize: 20, // Flipper visible size - - // Suggested actions stacked layout - suggestedActionsStackedHeight: undefined, // sets the container's max height. defaults to 'auto' - suggestedActionsStackedOverflow: undefined, // defaults to 'auto', - suggestedActionsStackedLayoutButtonMaxHeight: undefined, // defaults to 100% if suggestedActionsStackedLayoutButtonTextWrap is true - suggestedActionsStackedLayoutButtonTextWrap: false, // if set to true, buttons with long text will wrap in STACKED mode ONLY - - // Timestamp - groupTimestamp: true, - sendTimeout: 20000, - sendTimeoutForAttachments: 120000, - timestampColor: undefined, // defaults to subtle - timestampFormat: 'relative', // 'absolute' - - // Transcript overlay buttons (e.g. carousel and suggested action flippers, scroll to bottom, etc.) - newMessagesButtonFontSize: '85%', - transcriptOverlayButtonBackground: 'rgba(0, 0, 0, .6)', - transcriptOverlayButtonBackgroundOnFocus: 'rgba(0, 0, 0, .8)', - transcriptOverlayButtonBackgroundOnHover: 'rgba(0, 0, 0, .8)', - transcriptOverlayButtonColor: 'White', - transcriptOverlayButtonColorOnFocus: undefined, // defaults to transcriptOverlayButtonColor - transcriptOverlayButtonColorOnHover: undefined, // defaults to transcriptOverlayButtonColor - - // Video - videoHeight: 270, // based on bubbleMaxWidth: 480 / 16 * 9 = 270 - - // Connectivity UI - connectivityIconPadding: PADDING_REGULAR * 1.2, - connectivityMarginLeftRight: PADDING_REGULAR * 1.4, - connectivityMarginTopBottom: PADDING_REGULAR * 0.8, - connectivityTextSize: '75%', - failedConnectivity: '#C50F1F', - slowConnectivity: '#EAA300', - notificationText: '#5E5E5E', - slowConnectionAfter: 15000, - - typingAnimationBackgroundImage: null, - typingAnimationDuration: 5000, - typingAnimationHeight: 20, - typingAnimationWidth: 64, - - spinnerAnimationBackgroundImage: null, - spinnerAnimationHeight: 16, - spinnerAnimationWidth: 16, - spinnerAnimationPadding: 12, - - enableUploadThumbnail: true, - uploadThumbnailContentType: 'image/jpeg', - uploadThumbnailHeight: 360, - uploadThumbnailQuality: 0.6, - uploadThumbnailWidth: 720, - - // Toast UI - - // New debounce timeout value only affects new notifications. - notificationDebounceTimeout: 400, - - hideToaster: false, - toasterHeight: 32, - toasterMaxHeight: 32 * 5, - toasterSingularMaxHeight: 50, - toastFontSize: '87.5%', - toastIconWidth: 36, - toastSeparatorColor: '#E8EAEC', - toastTextPadding: 6, - - toastErrorBackgroundColor: '#FDE7E9', - toastErrorColor: '#A80000', - toastInfoBackgroundColor: '#CEF1FF', - toastInfoColor: '#105E7D', - toastSuccessBackgroundColor: '#DFF6DD', - toastSuccessColor: '#107C10', - toastWarnBackgroundColor: '#FFF4CE', - toastWarnColor: '#3B3A39', - - // Emoji - emojiSet: true, // true || false || { ':)' : '😊'} - - // Internal - internalLiveRegionFadeAfter: 1000, - - // Transcript - transcriptTerminatorBackgroundColor: '#595959', - transcriptTerminatorBorderRadius: 5, - transcriptTerminatorColor: 'White', - transcriptTerminatorFontSize: 12, - - transcriptActivityVisualKeyboardIndicatorColor: DEFAULT_SUBTLE, - transcriptActivityVisualKeyboardIndicatorStyle: 'dashed', - transcriptActivityVisualKeyboardIndicatorWidth: 1, - - transcriptVisualKeyboardIndicatorColor: 'Black', - transcriptVisualKeyboardIndicatorStyle: 'solid', - transcriptVisualKeyboardIndicatorWidth: 2, - //AdaptiveCard push button - cardPushButtonBackgroundColor: '#0063B1', - cardPushButtonTextColor: 'white' -}; - -export default DEFAULT_OPTIONS; diff --git a/packages/component/src/index.ts b/packages/component/src/index.ts new file mode 100644 index 0000000000..d824610b5a --- /dev/null +++ b/packages/component/src/index.ts @@ -0,0 +1,113 @@ +import ReactWebChat from './ReactWebChat'; + +import Composer from './Composer'; + +import BasicWebChat from './BasicWebChat'; + +import Avatar from './Activity/Avatar'; +import Bubble from './Activity/Bubble'; +import ErrorBox from './ErrorBox'; +import SendStatus, { connectSendStatus } from './Middleware/ActivityStatus/SendStatus/SendStatus'; +import SpeakActivity, { connectSpeakActivity } from './Activity/Speak'; +import Timestamp from './Middleware/ActivityStatus/Timestamp'; + +import AudioContent from './Attachment/AudioContent'; +import FileContent from './Attachment/FileContent'; +import HTMLVideoContent from './Attachment/HTMLVideoContent'; +import ImageContent from './Attachment/ImageContent'; +import TextContent from './Attachment/TextContent'; +import VideoContent from './Attachment/VideoContent'; +import VimeoContent from './Attachment/VimeoContent'; +import YouTubeContent from './Attachment/YouTubeContent'; + +import DictationInterims, { connectDictationInterims } from './SendBox/DictationInterims'; +import MicrophoneButton, { connectMicrophoneButton } from './SendBox/MicrophoneButton'; +import SendButton, { connectSendButton } from './SendBox/SendButton'; +import SendTextBox, { connectSendTextBox } from './SendBox/TextBox'; +import SuggestedActions, { connectSuggestedActions } from './SendBox/SuggestedActions'; +import UploadButton, { connectUploadButton } from './SendBox/UploadButton'; + +import connectToWebChat from './connectToWebChat'; +import Context from './hooks/internal/WebChatUIContext'; +import createCoreActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; +import createCoreActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; +import createCoreAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware'; +import createStyleSet from './Styles/createStyleSet'; +import getTabIndex from './Utils/TypeFocusSink/getTabIndex'; + +declare module 'botframework-webchat-api' { + export function concatMiddleware(): any; + export const hooks: any; + export function Localize(): any; + export function localize(): any; +} + +import { concatMiddleware, hooks as apiHooks, Localize, localize } from 'botframework-webchat-api'; +import * as componentHooks from './hooks/index'; + +const hooks = { + ...apiHooks, + ...componentHooks +}; + +// eslint-disable-next-line no-undef +const version = process.env.npm_package_version; + +const Components = { + BasicWebChat, + Composer, + Localize, + + // Components for recomposing activities and attachments + AudioContent, + FileContent, + HTMLVideoContent, + ImageContent, + TextContent, + VideoContent, + VimeoContent, + YouTubeContent, + + // Components for recomposing transcript + Avatar, + Bubble, + ErrorBox, + SendStatus, + SpeakActivity, + Timestamp, + + connectSendStatus, + connectSpeakActivity, + + // Components for recomposing send box + DictationInterims, + MicrophoneButton, + SendButton, + SendTextBox, + SuggestedActions, + UploadButton, + + connectDictationInterims, + connectMicrophoneButton, + connectSendButton, + connectSendTextBox, + connectSuggestedActions, + connectUploadButton +}; + +export default ReactWebChat; + +export { + Components, + concatMiddleware, + connectToWebChat, + Context, + createCoreActivityMiddleware, + createCoreActivityStatusMiddleware, + createCoreAttachmentMiddleware, + createStyleSet, + getTabIndex, + hooks, + localize, + version +}; diff --git a/packages/component/src/index.tsx b/packages/component/src/index.tsx index 36f4848890..7e7ea124dd 100644 --- a/packages/component/src/index.tsx +++ b/packages/component/src/index.tsx @@ -1,107 +1,35 @@ -import ReactWebChat from './ReactWebChat'; +import { FC } from 'react'; +import { StyleOptions } from 'botframework-webchat-api'; -import Composer from './Composer'; +type Expando = Omit & T; -import BasicWebChat from './BasicWebChat'; +/** Creates a set of styles */ +// eslint-disable-next-line no-unused-vars +declare function createStyleSet(styleOptions: StyleOptions): any; -import Avatar from './Activity/Avatar'; -import Bubble from './Activity/Bubble'; -import ErrorBox from './ErrorBox'; -import SendStatus, { connectSendStatus } from './Middleware/ActivityStatus/SendStatus/SendStatus'; -import SpeakActivity, { connectSpeakActivity } from './Activity/Speak'; -import Timestamp from './Middleware/ActivityStatus/Timestamp'; +type ComposerProps = { + /** Text directionality */ + dir?: 'ltr' | 'rtl' | 'auto'; -import AudioContent from './Attachment/AudioContent'; -import FileContent from './Attachment/FileContent'; -import HTMLVideoContent from './Attachment/HTMLVideoContent'; -import ImageContent from './Attachment/ImageContent'; -import TextContent from './Attachment/TextContent'; -import VideoContent from './Attachment/VideoContent'; -import VimeoContent from './Attachment/VimeoContent'; -import YouTubeContent from './Attachment/YouTubeContent'; - -import DictationInterims, { connectDictationInterims } from './SendBox/DictationInterims'; -import MicrophoneButton, { connectMicrophoneButton } from './SendBox/MicrophoneButton'; -import SendButton, { connectSendButton } from './SendBox/SendButton'; -import SendTextBox, { connectSendTextBox } from './SendBox/TextBox'; -import SuggestedActions, { connectSuggestedActions } from './SendBox/SuggestedActions'; -import UploadButton, { connectUploadButton } from './SendBox/UploadButton'; - -import connectToWebChat from './connectToWebChat'; -import Context from './hooks/internal/WebChatUIContext'; -import createCoreActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; -import createCoreActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; -import createCoreAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware'; -import createStyleSet from './Styles/createStyleSet'; -import defaultStyleOptions from './Styles/defaultStyleOptions'; -import getTabIndex from './Utils/TypeFocusSink/getTabIndex'; - -import { concatMiddleware, hooks as apiHooks, Localize, localize } from 'botframework-webchat-api'; -import * as componentHooks from './hooks/index'; - -const hooks = { - ...apiHooks, - ...componentHooks + /** Style options */ + styleOptions?: StyleOptions; }; -const version = process.env.npm_package_version; - -const Components = { - BasicWebChat, - Composer, - Localize, - - // Components for recomposing activities and attachments - AudioContent, - FileContent, - HTMLVideoContent, - ImageContent, - TextContent, - VideoContent, - VimeoContent, - YouTubeContent, +type ReactWebChatProps = { + /** Text directionality */ + dir?: 'ltr' | 'rtl' | 'auto'; - // Components for recomposing transcript - Avatar, - Bubble, - ErrorBox, - SendStatus, - SpeakActivity, - Timestamp, - - connectSendStatus, - connectSpeakActivity, + /** Style options */ + styleOptions?: StyleOptions; +}; - // Components for recomposing send box - DictationInterims, - MicrophoneButton, - SendButton, - SendTextBox, - SuggestedActions, - UploadButton, +/** React-based Web Chat */ +declare const ReactWebChat: FC>; - connectDictationInterims, - connectMicrophoneButton, - connectSendButton, - connectSendTextBox, - connectSuggestedActions, - connectUploadButton -}; +declare const Components: Expando<{ + Composer: FC>; +}>; export default ReactWebChat; - -export { - Components, - concatMiddleware, - connectToWebChat, - Context, - createCoreActivityMiddleware, - createCoreActivityStatusMiddleware, - createCoreAttachmentMiddleware, - createStyleSet, - defaultStyleOptions, - getTabIndex, - hooks, - localize, - version -}; +export { Components, createStyleSet }; +export type { ComposerProps, ReactWebChatProps }; diff --git a/packages/component/src/tsconfig.json b/packages/component/src/tsconfig.json index ca32a35acf..35417e5ca6 100644 --- a/packages/component/src/tsconfig.json +++ b/packages/component/src/tsconfig.json @@ -3,11 +3,13 @@ "allowSyntheticDefaultImports": true, "declaration": true, "declarationDir": "../lib", + "declarationMap": true, "emitDeclarationOnly": true, - "isolatedModules": true, "jsx": "react", "preserveWatchOutput": true, "pretty": true, - "skipLibCheck": true - } + "skipLibCheck": true, + "sourceMap": true + }, + "files": ["index.tsx"] } diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index fc23f08d7e..c5de2befcf 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -3521,9 +3521,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" diff --git a/packages/core/package.json b/packages/core/package.json index 73b2773c63..0813712bdb 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -33,8 +33,8 @@ "@babel/preset-env": "^7.13.10", "@babel/preset-typescript": "^7.13.0", "@types/node": "^14.14.35", - "@typescript-eslint/eslint-plugin": "^4.18.0", - "@typescript-eslint/parser": "^4.18.0", + "@typescript-eslint/eslint-plugin": "^4.19.0", + "@typescript-eslint/parser": "^4.19.0", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "botframework-directlinejs": "^0.14.1", diff --git a/packages/isomorphic-react-dom/package.json b/packages/isomorphic-react-dom/package.json index 0808a379bf..ee8730e093 100644 --- a/packages/isomorphic-react-dom/package.json +++ b/packages/isomorphic-react-dom/package.json @@ -8,7 +8,6 @@ "build": "npm run build:babel && npm run build:webpack", "build:babel": "babel src --out-dir lib --verbose", "build:webpack": "webpack-cli", - "eslint": "eslint src/**/*.js --fix", "start": "npm run start:note && npm run start:babel && npm run start:webpack", "start:babel": "npm run build:babel", "start:note": "echo \"isomorphic-react-dom is not under active development; running in non-watch mode.\"", diff --git a/packages/isomorphic-react/package.json b/packages/isomorphic-react/package.json index 0065b5d1cb..d218d602e3 100644 --- a/packages/isomorphic-react/package.json +++ b/packages/isomorphic-react/package.json @@ -7,7 +7,6 @@ "build": "npm run build:babel && npm run build:webpack", "build:babel": "babel src --out-dir lib --verbose", "build:webpack": "webpack-cli", - "eslint": "eslint src/**/*.js --fix", "start": "npm run start:note && npm run start:babel && npm run start:webpack", "start:babel": "npm run build:babel", "start:note": "echo \"isomorphic-react is not under active development; running in non-watch mode.\"", diff --git a/packages/playground/src/App.js b/packages/playground/src/App.js index 67b6dee042..c51902ae98 100644 --- a/packages/playground/src/App.js +++ b/packages/playground/src/App.js @@ -199,9 +199,9 @@ function App() { }, [handleUseMockBot]); // Feel free to change the text to whatever will help you dev faster - const handleCurrentCommandClick = useCallback(() => { + const handleCurrentCommandClick = () => { store.dispatch({ type: 'WEB_CHAT/SEND_MESSAGE', payload: { text: 'suggested-actions' } }); - }); + }; /// END CONNECTIVITY diff --git a/samples/02.branding-styling-and-customization/a.branding-web-chat/README.md b/samples/02.branding-styling-and-customization/a.branding-web-chat/README.md index 23581c2812..42b535d483 100644 --- a/samples/02.branding-styling-and-customization/a.branding-web-chat/README.md +++ b/samples/02.branding-styling-and-customization/a.branding-web-chat/README.md @@ -30,7 +30,7 @@ You may have noticed that Web Chat provides two different ways to change the app 1. 'Branding' your bot via `styleSetOptions` (recommended) 1. Idiosyncratic styling via overriding `createStyleSet` (not recommended) -`styleSetOptions` is the Web Chat supported method of changing existing DOM elements in the application, and the currently available options are listed on the [`defaultStyleOptions.js` file](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/component/src/Styles/defaultStyleOptions.js). These options will continue to be updated as we make further as the project grows. +`styleSetOptions` is the Web Chat supported method of changing existing DOM elements in the application, and the currently available options are listed on the [`defaultStyleOptions.ts` file](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/api/src/defaultStyleOptions.ts) and [`adaptiveCards/defaultStyleOptions.ts` file](https://github.com/microsoft/BotFramework-WebChat/blob/master/packages/bundle/src/adaptiveCards/defaultStyleOptions.ts) when Adaptive Cards is enabled. These options will continue to be updated as we make further as the project grows. We provide these options to override for several reasons: