diff --git a/__tests__/html2/experience/chatLauncher/assets/background.jpg b/__tests__/html2/experience/chatLauncher/assets/background.jpg
new file mode 100644
index 0000000000..d71b08ab57
Binary files /dev/null and b/__tests__/html2/experience/chatLauncher/assets/background.jpg differ
diff --git a/__tests__/html2/experience/chatLauncher/fluentTheme.html b/__tests__/html2/experience/chatLauncher/fluentTheme.html
new file mode 100644
index 0000000000..2193fcc04f
--- /dev/null
+++ b/__tests__/html2/experience/chatLauncher/fluentTheme.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/__tests__/html2/experience/chatLauncher/simple.html b/__tests__/html2/experience/chatLauncher/simple.html
new file mode 100644
index 0000000000..7ef0979ea7
--- /dev/null
+++ b/__tests__/html2/experience/chatLauncher/simple.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/__tests__/html2/livestream/wrongId.html b/__tests__/html2/livestream/wrongId.html
new file mode 100644
index 0000000000..e8e9b2f327
--- /dev/null
+++ b/__tests__/html2/livestream/wrongId.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lint-staged.config.js b/lint-staged.config.js
index 1785a33a54..e1c64dca54 100644
--- a/lint-staged.config.js
+++ b/lint-staged.config.js
@@ -19,6 +19,7 @@ module.exports = {
'packages/core/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:core'],
'packages/debug-theme/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:debug-theme'],
'packages/directlinespeech/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:directlinespeech'],
+ 'packages/experience-chat-launcher/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:experience-chat-launcher'],
'packages/fluent-theme/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:fluent-theme'],
'packages/isomorphic-react/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:isomorphic-react'],
'packages/isomorphic-react-dom/src/**/*.{mjs,js,ts,tsx}': ['npm run precommit:eslint:isomorphic-react-dom'],
diff --git a/package-lock.json b/package-lock.json
index dbbab52530..43c5b238be 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,6 +26,7 @@
"./packages/isomorphic-react",
"./packages/isomorphic-react-dom",
"./packages/component",
+ "./packages/experience-chat-launcher",
"./packages/repack/adaptivecards",
"./packages/repack/base64-js",
"./packages/repack/botframework-directlinejs",
@@ -93,6 +94,8 @@
"minimatch": "^10.0.3",
"node-dev": "^8.0.0",
"prettier": "^3.6.2",
+ "read-package-up": "^11.0.0",
+ "read-pkg": "^9.0.1",
"selenium-webdriver": "^4.34.0",
"serve": "^14.2.4",
"serve-handler": "^6.1.6",
@@ -3051,6 +3054,10 @@
"resolved": "packages/debug-theme",
"link": true
},
+ "node_modules/@msinternal/botframework-webchat-experience-chat-launcher": {
+ "resolved": "packages/experience-chat-launcher",
+ "link": true
+ },
"node_modules/@msinternal/botframework-webchat-react-hooks": {
"resolved": "packages/react-hooks",
"link": true
@@ -3715,7 +3722,6 @@
},
"node_modules/@types/istanbul-reports": {
"version": "3.0.4",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/istanbul-lib-report": "*"
@@ -3942,7 +3948,6 @@
},
"node_modules/@types/yargs": {
"version": "17.0.33",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/yargs-parser": "*"
@@ -6196,6 +6201,8 @@
},
"node_modules/concurrently": {
"version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.0.tgz",
+ "integrity": "sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8388,7 +8395,9 @@
}
},
"node_modules/find-up-simple": {
- "version": "1.0.0",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz",
+ "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -12735,6 +12744,8 @@
},
"node_modules/merge-refs": {
"version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-2.0.0.tgz",
+ "integrity": "sha512-3+B21mYK2IqUWnd2EivABLT7ueDhb0b8/dGK8LoFQPrU61YITeCMn14F7y7qZafWNZhUEKb24cJdiT5Wxs3prg==",
"license": "MIT",
"funding": {
"url": "https://github.com/wojtekmaj/merge-refs?sponsor=1"
@@ -13691,6 +13702,8 @@
},
"node_modules/nodemon": {
"version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
+ "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -14834,10 +14847,42 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/read-package-up": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz",
+ "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up-simple": "^1.0.0",
+ "read-pkg": "^9.0.0",
+ "type-fest": "^4.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-package-up/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/read-pkg": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz",
"integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==",
+ "license": "MIT",
"dependencies": {
"@types/normalize-package-data": "^2.4.3",
"normalize-package-data": "^6.0.0",
@@ -14854,6 +14899,9 @@
},
"node_modules/read-pkg-up": {
"version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-11.0.0.tgz",
+ "integrity": "sha512-LOVbvF1Q0SZdjClSefZ0Nz5z8u+tIE7mV5NibzmE9VYmDe9CaBbAVtz1veOSZbofrdsilxuDAYnFenukZVp8/Q==",
+ "deprecated": "Renamed to read-package-up",
"license": "MIT",
"dependencies": {
"find-up-simple": "^1.0.0",
@@ -17849,6 +17897,8 @@
},
"node_modules/use-ref-from": {
"version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/use-ref-from/-/use-ref-from-0.1.0.tgz",
+ "integrity": "sha512-PRjmfhUGUKghhOjKV1dBU66M7CASdb4NkMsaaWLdJA81yOZFlVL7Pi3O9aD+68pRh0VrRQjZfS6Ux3vPy1VhRg==",
"license": "MIT",
"dependencies": {
"@babel/runtime-corejs3": "^7.24.1",
@@ -18652,7 +18702,7 @@
"@msinternal/botframework-webchat-react-valibot": "^0.0.0-0",
"@types/node": "^22.13.4",
"cross-env": "^7.0.3",
- "type-fest": "^4.34.1",
+ "type-fest": "^4.41.0",
"typescript": "^5.7.3"
},
"peerDependencies": {
@@ -18687,6 +18737,8 @@
},
"packages/api-middleware/node_modules/type-fest": {
"version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
@@ -19064,6 +19116,7 @@
"@msinternal/base64-js": "0.0.0-0",
"@msinternal/botframework-directlinejs": "0.0.0-0",
"@msinternal/botframework-webchat-base": "0.0.0-0",
+ "@msinternal/botframework-webchat-experience-chat-launcher": "0.0.0-0",
"@msinternal/botframework-webchat-react-valibot": "0.0.0-0",
"@msinternal/botframework-webchat-tsconfig": "0.0.0-0",
"@msinternal/isomorphic-react": "0.0.0-0",
@@ -19896,7 +19949,6 @@
"babel-jest": "^29.7.0",
"babel-plugin-istanbul": "^7.0.0",
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
- "concurrently": "^9.2.0",
"cross-env": "^10.0.0",
"dotenv": "^17.2.1",
"eslint": "^8.57.1",
@@ -19928,6 +19980,46 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
+ "packages/experience-chat-launcher": {
+ "name": "@msinternal/botframework-webchat-experience-chat-launcher",
+ "version": "0.0.0-0",
+ "license": "MIT",
+ "dependencies": {
+ "botframework-webchat-api": "0.0.0-0",
+ "botframework-webchat-component": "0.0.0-0",
+ "botframework-webchat-core": "0.0.0-0",
+ "merge-refs": "2.0.0",
+ "use-ref-from": "0.1.0",
+ "valibot": "1.1.0"
+ },
+ "devDependencies": {
+ "@msinternal/botframework-webchat-react-valibot": "0.0.0-0",
+ "@msinternal/botframework-webchat-redux-store": "0.0.0-0",
+ "@msinternal/botframework-webchat-styles": "0.0.0-0",
+ "@types/node": "^22.13.4",
+ "typescript": "^5.7.3"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.6"
+ }
+ },
+ "packages/experience-chat-launcher/node_modules/@types/node": {
+ "version": "22.18.10",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.10.tgz",
+ "integrity": "sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "packages/experience-chat-launcher/node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"packages/fluent-theme": {
"name": "botframework-webchat-fluent-theme",
"version": "0.0.0-0",
@@ -19945,6 +20037,7 @@
"@msinternal/botframework-webchat-tsconfig": "0.0.0-0",
"@types/math-random": "^1.0.2",
"@types/node": "^24.1.0",
+ "concurrently": "^9.2.0",
"tsup": "^8.5.0",
"typescript": "~5.8.3"
},
@@ -20382,7 +20475,6 @@
"packages/repack/react-dom@umd": {
"name": "@msinternal/react-dom-umd",
"version": "0.0.0-0",
- "license": "ISC",
"devDependencies": {
"esbuild": "^0.25.10"
}
@@ -20890,6 +20982,7 @@
"core-js-pure": "3.44.0",
"event-iterator": "2.0.0",
"event-target-shim": "6.0.2",
+ "jest-mock": "28.1.3",
"math-random": "2.0.1",
"microsoft-cognitiveservices-speech-sdk": "1.17.0",
"prop-types": "15.8.1",
@@ -20903,6 +20996,57 @@
"node": ">= 14.0.0"
}
},
+ "packages/test/page-object/node_modules/@jest/schemas": {
+ "version": "28.1.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz",
+ "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==",
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.24.1"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
+ }
+ },
+ "packages/test/page-object/node_modules/@jest/types": {
+ "version": "28.1.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz",
+ "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^28.1.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
+ }
+ },
+ "packages/test/page-object/node_modules/@sinclair/typebox": {
+ "version": "0.24.51",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
+ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==",
+ "license": "MIT"
+ },
+ "packages/test/page-object/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
"packages/test/page-object/node_modules/event-target-shim": {
"version": "6.0.2",
"license": "MIT",
@@ -20913,6 +21057,40 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
+ "packages/test/page-object/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "packages/test/page-object/node_modules/jest-mock": {
+ "version": "28.1.3",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz",
+ "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^28.1.3",
+ "@types/node": "*"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
+ }
+ },
+ "packages/test/page-object/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"packages/test/web-server": {
"name": "@msinternal/test-web-server",
"version": "0.0.0-0",
diff --git a/package.json b/package.json
index cd25e62695..7b8a32877f 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"./packages/isomorphic-react",
"./packages/isomorphic-react-dom",
"./packages/component",
+ "./packages/experience-chat-launcher",
"./packages/repack/adaptivecards",
"./packages/repack/base64-js",
"./packages/repack/botframework-directlinejs",
@@ -79,6 +80,7 @@
"precommit:eslint:core": "cd packages && cd core && npm run precommit:eslint",
"precommit:eslint:debug-theme": "cd packages && cd debug-theme && npm run precommit:eslint",
"precommit:eslint:directlinespeech": "cd packages && cd directlinespeech && npm run precommit:eslint",
+ "precommit:eslint:experience-chat-launcher": "cd packages && cd experience-chat-launcher && npm run precommit:eslint",
"precommit:eslint:fluent-theme": "cd packages && cd fluent-theme && npm run precommit:eslint",
"precommit:eslint:isomorphic-react": "cd packages && cd isomorphic-react && npm run precommit:eslint",
"precommit:eslint:isomorphic-react-dom": "cd packages && cd isomorphic-react-dom && npm run precommit:eslint",
@@ -112,6 +114,7 @@
"precommit:typecheck:component": "cd packages && cd component && npm run precommit:typecheck",
"precommit:typecheck:core": "cd packages && cd core && npm run precommit:typecheck",
"precommit:typecheck:debug-theme": "cd packages && cd debug-theme && npm run precommit:typecheck",
+ "precommit:typecheck:experience-chat-launcher": "cd packages && cd experience-chat-launcher && npm run precommit:typecheck",
"precommit:typecheck:fluent-theme": "cd packages && cd fluent-theme && npm run precommit:typecheck",
"precommit:typecheck:react-hooks": "cd packages && cd react-hooks && npm run precommit:typecheck",
"precommit:typecheck:react-valibot": "cd packages && cd react-valibot && npm run precommit:typecheck",
@@ -139,6 +142,7 @@
"start:core": "cd packages && cd core && npm start",
"start:debug-theme": "cd packages && cd debug-theme && npm start",
"start:directlinespeech": "cd packages && cd directlinespeech && npm start",
+ "start:experience-chat-launcher": "cd packages && cd experience-chat-launcher && npm start",
"start:fluent-theme": "cd packages && cd fluent-theme && npm start",
"start:react-hooks": "cd packages && cd react-hooks && npm start",
"start:react-valibot": "cd packages && cd react-valibot && npm start",
@@ -256,6 +260,8 @@
"minimatch": "^10.0.3",
"node-dev": "^8.0.0",
"prettier": "^3.6.2",
+ "read-package-up": "^11.0.0",
+ "read-pkg": "^9.0.1",
"selenium-webdriver": "^4.34.0",
"serve": "^14.2.4",
"serve-handler": "^6.1.6",
diff --git a/packages/api-middleware/.gitignore b/packages/api-middleware/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/api-middleware/.gitignore
+++ b/packages/api-middleware/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/api-middleware/package.json b/packages/api-middleware/package.json
index eb14dcf2a3..b3c1700b98 100644
--- a/packages/api-middleware/package.json
+++ b/packages/api-middleware/package.json
@@ -55,24 +55,30 @@
"./src/**/*",
"*.js"
],
- "localDependencies": {
- "@msinternal/botframework-webchat-base": "development",
- "@msinternal/botframework-webchat-react-hooks": "development",
- "@msinternal/botframework-webchat-react-valibot": "development"
- },
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/api-middleware#readme",
"scripts": {
- "build": "tsup --config ./tsup.config.ts",
- "bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
- "bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
- "bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
+ "bump": "npm run bump:prod && npm run bump:dev && npm run bump:peer && (npm audit fix || exit 0)",
+ "bump:dev": "../../scripts/npm/bump-dev.sh",
+ "bump:peer": "../../scripts/npm/bump-peer.sh",
+ "bump:prod": "../../scripts/npm/bump-prod.sh",
"eslint": "npm run precommit",
- "postversion": "cat package.json | jq '.version as $V | (.localDependencies // {} | with_entries(select(.value == \"production\") | { key: .key, value: $V })) as $L1 | (.localDependencies // {} | with_entries(select(.value == \"development\") | { key: .key, value: $V })) as $L2 | ((.dependencies // {}) + $L1 | to_entries | sort_by(.key) | from_entries) as $D1 | ((.devDependencies // {}) + $L2 | to_entries | sort_by(.key) | from_entries) as $D2 | . + { dependencies: $D1, devDependencies: $D2 }' > package-temp.json && mv package-temp.json package.json",
+ "postversion": "node ../../scripts/npm/postversion.sh",
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
+ "preversion": "node ../../scripts/npm/preversion.sh",
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../base/package.json\" \"../react-hooks/package.json\" \"../react-valibot/package.json\""
+ },
+ "pinDependencies": {},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-base": "development",
+ "@msinternal/botframework-webchat-react-hooks": "development",
+ "@msinternal/botframework-webchat-react-valibot": "development"
},
"devDependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -81,16 +87,16 @@
"@msinternal/botframework-webchat-react-valibot": "^0.0.0-0",
"@types/node": "^22.13.4",
"cross-env": "^7.0.3",
- "type-fest": "^4.34.1",
+ "type-fest": "^4.41.0",
"typescript": "^5.7.3"
},
- "peerDependencies": {
- "react-chain-of-responsibility": "0.4.0-main.c2f17da",
- "react": ">= 16.8.6"
- },
"dependencies": {
"handler-chain": "^0.1.0",
"react-wrap-with": "0.1.0",
"valibot": "1.1.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.6",
+ "react-chain-of-responsibility": "0.4.0-main.c2f17da"
}
}
diff --git a/packages/api-middleware/src/PolymiddlewareComposer.tsx b/packages/api-middleware/src/PolymiddlewareComposer.tsx
index 4780e3fc86..1ab3beff1e 100644
--- a/packages/api-middleware/src/PolymiddlewareComposer.tsx
+++ b/packages/api-middleware/src/PolymiddlewareComposer.tsx
@@ -15,7 +15,13 @@ import {
} from 'valibot';
import { ActivityPolymiddlewareProvider, extractActivityEnhancer } from './activityPolymiddleware';
+import { ButtonPolymiddlewareProvider, extractButtonEnhancer } from './buttonPolymiddleware';
+import {
+ ChatLauncherButtonPolymiddlewareProvider,
+ extractChatLauncherButtonEnhancer
+} from './chatLauncherButtonPolymiddleware';
import { ErrorBoxPolymiddlewareProvider, extractErrorBoxEnhancer } from './errorBoxPolymiddleware';
+import { PopoverPolymiddlewareProvider, extractPopoverEnhancer } from './popoverPolymiddleware';
import { Polymiddleware } from './types/Polymiddleware';
const polymiddlewareComposerPropsSchema = pipe(
@@ -49,6 +55,41 @@ function PolymiddlewareComposer(props: PolymiddlewareComposerProps) {
const activityPolymiddleware = useMemo(() => activityEnhancers.map(enhancer => () => enhancer), [activityEnhancers]);
+ const buttonEnhancers = useMemoWithPrevious>(
+ (prevButtonEnhancers = []) => {
+ const buttonEnhancers = extractButtonEnhancer(polymiddleware);
+
+ // Checks for array equality, return previous version if nothing has changed.
+ return prevButtonEnhancers.length === buttonEnhancers.length &&
+ buttonEnhancers.every((middleware, index) => Object.is(middleware, prevButtonEnhancers.at(index)))
+ ? prevButtonEnhancers
+ : buttonEnhancers;
+ },
+ [polymiddleware]
+ );
+
+ const buttonPolymiddleware = useMemo(() => buttonEnhancers.map(enhancer => () => enhancer), [buttonEnhancers]);
+
+ const chatLauncherButtonEnhancers = useMemoWithPrevious>(
+ (prevChatLauncherButtonEnhancers = []) => {
+ const chatLauncherButtonEnhancers = extractChatLauncherButtonEnhancer(polymiddleware);
+
+ // Checks for array equality, return previous version if nothing has changed.
+ return prevChatLauncherButtonEnhancers.length === chatLauncherButtonEnhancers.length &&
+ chatLauncherButtonEnhancers.every((middleware, index) =>
+ Object.is(middleware, prevChatLauncherButtonEnhancers.at(index))
+ )
+ ? prevChatLauncherButtonEnhancers
+ : chatLauncherButtonEnhancers;
+ },
+ [polymiddleware]
+ );
+
+ const chatLauncherButtonPolymiddleware = useMemo(
+ () => chatLauncherButtonEnhancers.map(enhancer => () => enhancer),
+ [chatLauncherButtonEnhancers]
+ );
+
const errorBoxEnhancers = useMemoWithPrevious>(
(prevErrorBoxEnhancers = []) => {
const errorBoxEnhancers = extractErrorBoxEnhancer(polymiddleware);
@@ -64,6 +105,21 @@ function PolymiddlewareComposer(props: PolymiddlewareComposerProps) {
const errorBoxPolymiddleware = useMemo(() => errorBoxEnhancers.map(enhancer => () => enhancer), [errorBoxEnhancers]);
+ const popoverEnhancers = useMemoWithPrevious>(
+ (prevPopoverEnhancers = []) => {
+ const popoverEnhancers = extractPopoverEnhancer(polymiddleware);
+
+ // Checks for array equality, return previous version if nothing has changed.
+ return prevPopoverEnhancers.length === popoverEnhancers.length &&
+ popoverEnhancers.every((middleware, index) => Object.is(middleware, prevPopoverEnhancers.at(index)))
+ ? prevPopoverEnhancers
+ : popoverEnhancers;
+ },
+ [polymiddleware]
+ );
+
+ const popoverPolymiddleware = useMemo(() => popoverEnhancers.map(enhancer => () => enhancer), [popoverEnhancers]);
+
// Didn't thoroughly think through this part yet, but I am using the first approach for now:
// 1. for every type of middleware
@@ -75,7 +131,13 @@ function PolymiddlewareComposer(props: PolymiddlewareComposerProps) {
return (
- {children}
+
+
+
+ {children}
+
+
+
);
}
diff --git a/packages/api-middleware/src/buttonPolymiddleware.tsx b/packages/api-middleware/src/buttonPolymiddleware.tsx
new file mode 100644
index 0000000000..e47ad8a5e6
--- /dev/null
+++ b/packages/api-middleware/src/buttonPolymiddleware.tsx
@@ -0,0 +1,126 @@
+import { forwardedRef, reactNode, refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import React, { forwardRef, memo, useMemo, type ForwardedRef, type ReactNode, type RefObject } from 'react';
+import { function_, object, optional, picklist, pipe, readonly, string, type InferInput } from 'valibot';
+
+import createErrorBoundaryMiddleware from './private/createErrorBoundaryMiddleware';
+import templatePolymiddleware, {
+ type InferHandler,
+ type InferHandlerResult,
+ type InferMiddleware,
+ type InferProps,
+ type InferProviderProps,
+ type InferRenderer,
+ type InferRequest
+} from './private/templatePolymiddleware';
+
+const {
+ createMiddleware: createButtonPolymiddleware,
+ extractEnhancer: extractButtonEnhancer,
+ Provider,
+ Proxy,
+ reactComponent: buttonComponent,
+ useBuildRenderCallback: useBuildRenderButtonCallback
+} = templatePolymiddleware<
+ {
+ readonly appearance?: 'elevated' | 'flat' | undefined;
+ readonly size?: 'hero' | 'normal' | undefined;
+ },
+ {
+ readonly children?: ReactNode | undefined;
+ readonly className?: string | undefined;
+ readonly forwardedRef?: ForwardedRef | undefined;
+ readonly onClick?: (() => void) | undefined;
+ readonly popoverTargetAction?: 'hide' | 'show' | 'toggle' | undefined;
+ readonly popoverTargetRef?: RefObject | undefined;
+ }
+>('Button');
+
+type ButtonPolymiddleware = InferMiddleware;
+type ButtonPolymiddlewareHandler = InferHandler;
+type ButtonPolymiddlewareHandlerResult = InferHandlerResult;
+type ButtonPolymiddlewareProps = InferProps;
+type ButtonPolymiddlewareRenderer = InferRenderer;
+type ButtonPolymiddlewareRequest = InferRequest;
+type ButtonPolymiddlewareProviderProps = InferProviderProps;
+
+const buttonPolymiddlewareProxyPropsSchema = pipe(
+ object({
+ appearance: optional(picklist(['elevated', 'flat'])),
+ children: optional(reactNode()),
+ className: optional(string()),
+ forwardedRef: optional(forwardedRef()),
+ onClick: optional(function_()),
+ popoverTargetAction: optional(picklist(['hide', 'show', 'toggle'])),
+ popoverTargetRef: optional(refObject()),
+ size: optional(picklist(['hero', 'normal']))
+ }),
+ readonly()
+);
+
+type ButtonPolymiddlewareProxyProps = Readonly>;
+
+// A friendlier version than the organic .
+const ButtonPolymiddlewareProxy = memo(
+ forwardRef(function ButtonPolymiddlewareProxy(props: ButtonPolymiddlewareProxyProps, ref: ForwardedRef) {
+ const { appearance, children, className, onClick, popoverTargetAction, popoverTargetRef, size } = validateProps(
+ buttonPolymiddlewareProxyPropsSchema,
+ props
+ );
+
+ const request = useMemo(() => Object.freeze({ appearance, size }), [appearance, size]);
+
+ return (
+
+ {children}
+
+ );
+ })
+);
+
+const ButtonPolymiddlewareProvider = memo(function ButtonPolymiddlewareProvider({
+ children,
+ middleware
+}: ButtonPolymiddlewareProviderProps) {
+ // Decorates middleware with .
+ const middlewareWithErrorBoundary = useMemo(
+ () =>
+ Object.freeze([
+ // TODO: [P1] Should we simplify this middleware signature and allow error boundary middleware to run on every type of middleware?
+ // (init: any) => next => (request: undefined) => reactComponentForAll()
+ // We can't do it today because we have sanity check that prevent `reactComponent()` from different middleware cross-polluting each other.
+ createErrorBoundaryMiddleware({
+ createMiddleware: createButtonPolymiddleware,
+ reactComponent: buttonComponent,
+ where: 'Button polymiddleware'
+ }),
+ ...middleware
+ ]),
+ [middleware]
+ );
+
+ return {children};
+});
+
+export {
+ buttonComponent,
+ ButtonPolymiddlewareProvider,
+ ButtonPolymiddlewareProxy,
+ createButtonPolymiddleware,
+ extractButtonEnhancer,
+ useBuildRenderButtonCallback,
+ type ButtonPolymiddleware,
+ type ButtonPolymiddlewareHandler,
+ type ButtonPolymiddlewareHandlerResult,
+ type ButtonPolymiddlewareProps,
+ type ButtonPolymiddlewareProviderProps,
+ type ButtonPolymiddlewareProxyProps,
+ type ButtonPolymiddlewareRenderer,
+ type ButtonPolymiddlewareRequest
+};
diff --git a/packages/api-middleware/src/chatLauncherButtonPolymiddleware.tsx b/packages/api-middleware/src/chatLauncherButtonPolymiddleware.tsx
new file mode 100644
index 0000000000..16456a65e3
--- /dev/null
+++ b/packages/api-middleware/src/chatLauncherButtonPolymiddleware.tsx
@@ -0,0 +1,103 @@
+import { refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import React, { memo, useMemo, type RefObject } from 'react';
+import { type EmptyObject } from 'type-fest';
+import { boolean, object, pipe, readonly, type InferInput } from 'valibot';
+
+import createErrorBoundaryMiddleware from './private/createErrorBoundaryMiddleware';
+import templatePolymiddleware, {
+ type InferHandler,
+ type InferHandlerResult,
+ type InferMiddleware,
+ type InferProps,
+ type InferProviderProps,
+ type InferRenderer,
+ type InferRequest
+} from './private/templatePolymiddleware';
+
+const {
+ createMiddleware: createChatLauncherButtonPolymiddleware,
+ extractEnhancer: extractChatLauncherButtonEnhancer,
+ Provider,
+ Proxy,
+ reactComponent: chatLauncherButtonComponent,
+ useBuildRenderCallback: useBuildRenderChatLauncherButtonCallback
+} = templatePolymiddleware<
+ EmptyObject,
+ {
+ readonly children?: never;
+ readonly hasMessage: boolean;
+ readonly popoverTargetRef: RefObject;
+ }
+>('ChatLauncherButton');
+
+type ChatLauncherButtonPolymiddleware = InferMiddleware;
+type ChatLauncherButtonPolymiddlewareHandler = InferHandler;
+type ChatLauncherButtonPolymiddlewareHandlerResult = InferHandlerResult;
+type ChatLauncherButtonPolymiddlewareProps = InferProps;
+type ChatLauncherButtonPolymiddlewareRenderer = InferRenderer;
+type ChatLauncherButtonPolymiddlewareRequest = InferRequest;
+type ChatLauncherButtonPolymiddlewareProviderProps = InferProviderProps;
+
+const chatLauncherButtonPolymiddlewareProxyPropsSchema = pipe(
+ object({
+ hasMessage: boolean(),
+ popoverTargetRef: refObject()
+ }),
+ readonly()
+);
+
+type ChatLauncherButtonPolymiddlewareProxyProps = Readonly<
+ InferInput
+>;
+
+const EMPTY_OBJECT = Object.freeze({});
+
+// A friendlier version than the organic .
+const ChatLauncherButtonPolymiddlewareProxy = memo(function ChatLauncherButtonPolymiddlewareProxy(
+ props: ChatLauncherButtonPolymiddlewareProxyProps
+) {
+ const { hasMessage, popoverTargetRef } = validateProps(chatLauncherButtonPolymiddlewareProxyPropsSchema, props);
+
+ return ;
+});
+
+const ChatLauncherButtonPolymiddlewareProvider = memo(function ChatLauncherButtonPolymiddlewareProvider({
+ children,
+ middleware
+}: ChatLauncherButtonPolymiddlewareProviderProps) {
+ // Decorates middleware with .
+ const middlewareWithErrorBoundary = useMemo(
+ () =>
+ Object.freeze([
+ // TODO: [P1] Should we simplify this middleware signature and allow error boundary middleware to run on every type of middleware?
+ // (init: any) => next => (request: undefined) => reactComponentForAll()
+ // We can't do it today because we have sanity check that prevent `reactComponent()` from different middleware cross-polluting each other.
+ createErrorBoundaryMiddleware({
+ createMiddleware: createChatLauncherButtonPolymiddleware,
+ reactComponent: chatLauncherButtonComponent,
+ where: 'Chat launcher polymiddleware'
+ }),
+ ...middleware
+ ]),
+ [middleware]
+ );
+
+ return {children};
+});
+
+export {
+ chatLauncherButtonComponent,
+ ChatLauncherButtonPolymiddlewareProvider,
+ ChatLauncherButtonPolymiddlewareProxy,
+ createChatLauncherButtonPolymiddleware,
+ extractChatLauncherButtonEnhancer,
+ useBuildRenderChatLauncherButtonCallback,
+ type ChatLauncherButtonPolymiddleware,
+ type ChatLauncherButtonPolymiddlewareHandler,
+ type ChatLauncherButtonPolymiddlewareHandlerResult,
+ type ChatLauncherButtonPolymiddlewareProps,
+ type ChatLauncherButtonPolymiddlewareProviderProps,
+ type ChatLauncherButtonPolymiddlewareProxyProps,
+ type ChatLauncherButtonPolymiddlewareRenderer,
+ type ChatLauncherButtonPolymiddlewareRequest
+};
diff --git a/packages/api-middleware/src/index.ts b/packages/api-middleware/src/index.ts
index 9e0a8aeb8e..a43438f023 100644
--- a/packages/api-middleware/src/index.ts
+++ b/packages/api-middleware/src/index.ts
@@ -12,6 +12,34 @@ export {
type ActivityPolymiddlewareRequest
} from './activityPolymiddleware';
+export {
+ buttonComponent,
+ ButtonPolymiddlewareProxy,
+ createButtonPolymiddleware,
+ useBuildRenderButtonCallback,
+ type ButtonPolymiddleware,
+ type ButtonPolymiddlewareHandler,
+ type ButtonPolymiddlewareHandlerResult,
+ type ButtonPolymiddlewareProps,
+ type ButtonPolymiddlewareProxyProps,
+ type ButtonPolymiddlewareRenderer,
+ type ButtonPolymiddlewareRequest
+} from './buttonPolymiddleware';
+
+export {
+ chatLauncherButtonComponent,
+ ChatLauncherButtonPolymiddlewareProxy,
+ createChatLauncherButtonPolymiddleware,
+ useBuildRenderChatLauncherButtonCallback,
+ type ChatLauncherButtonPolymiddleware,
+ type ChatLauncherButtonPolymiddlewareHandler,
+ type ChatLauncherButtonPolymiddlewareHandlerResult,
+ type ChatLauncherButtonPolymiddlewareProps,
+ type ChatLauncherButtonPolymiddlewareProxyProps,
+ type ChatLauncherButtonPolymiddlewareRenderer,
+ type ChatLauncherButtonPolymiddlewareRequest
+} from './chatLauncherButtonPolymiddleware';
+
export {
createErrorBoxPolymiddleware,
errorBoxComponent,
@@ -26,6 +54,20 @@ export {
type ErrorBoxPolymiddlewareRequest
} from './errorBoxPolymiddleware';
+export {
+ createPopoverPolymiddleware,
+ popoverComponent,
+ PopoverPolymiddlewareProxy,
+ useBuildRenderPopoverCallback,
+ type PopoverPolymiddleware,
+ type PopoverPolymiddlewareHandler,
+ type PopoverPolymiddlewareHandlerResult,
+ type PopoverPolymiddlewareProps,
+ type PopoverPolymiddlewareProxyProps,
+ type PopoverPolymiddlewareRenderer,
+ type PopoverPolymiddlewareRequest
+} from './popoverPolymiddleware';
+
// TODO: [P0] Add tests for nesting `polymiddleware`.
export { default as PolymiddlewareComposer } from './PolymiddlewareComposer';
export { type Polymiddleware } from './types/Polymiddleware';
diff --git a/packages/api-middleware/src/popoverPolymiddleware.tsx b/packages/api-middleware/src/popoverPolymiddleware.tsx
new file mode 100644
index 0000000000..4ae3dae8f8
--- /dev/null
+++ b/packages/api-middleware/src/popoverPolymiddleware.tsx
@@ -0,0 +1,108 @@
+import { forwardedRef, reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import React, { forwardRef, memo, useMemo, type ForwardedRef, type ReactNode } from 'react';
+import { literal, object, optional, picklist, pipe, readonly, string, type InferInput } from 'valibot';
+
+import createErrorBoundaryMiddleware from './private/createErrorBoundaryMiddleware';
+import templatePolymiddleware, {
+ type InferHandler,
+ type InferHandlerResult,
+ type InferMiddleware,
+ type InferProps,
+ type InferProviderProps,
+ type InferRenderer,
+ type InferRequest
+} from './private/templatePolymiddleware';
+
+const {
+ createMiddleware: createPopoverPolymiddleware,
+ extractEnhancer: extractPopoverEnhancer,
+ Provider,
+ Proxy,
+ reactComponent: popoverComponent,
+ useBuildRenderCallback: useBuildRenderPopoverCallback
+} = templatePolymiddleware<
+ { readonly type: 'nonmodal' },
+ {
+ readonly children?: ReactNode | undefined;
+ readonly className?: string | undefined;
+ readonly forwardedRef?: ForwardedRef | undefined;
+ readonly popover?: 'auto' | 'hint' | 'manual' | undefined;
+ }
+>('Popover');
+
+type PopoverPolymiddleware = InferMiddleware;
+type PopoverPolymiddlewareHandler = InferHandler;
+type PopoverPolymiddlewareHandlerResult = InferHandlerResult;
+type PopoverPolymiddlewareProps = InferProps;
+type PopoverPolymiddlewareRenderer = InferRenderer;
+type PopoverPolymiddlewareRequest = InferRequest;
+type PopoverPolymiddlewareProviderProps = InferProviderProps;
+
+const popoverPolymiddlewareProxyPropsSchema = pipe(
+ object({
+ children: optional(reactNode()),
+ className: optional(string()),
+ forwardedRef: optional(forwardedRef()),
+ popover: optional(picklist(['auto', 'hint', 'manual'])),
+ type: literal('nonmodal')
+ }),
+ readonly()
+);
+
+type PopoverPolymiddlewareProxyProps = Readonly>;
+
+// A friendlier version than the organic .
+const PopoverPolymiddlewareProxy = memo(
+ forwardRef(function PopoverPolymiddlewareProxy(props: PopoverPolymiddlewareProxyProps, ref: ForwardedRef) {
+ const { children, className, popover, type } = validateProps(popoverPolymiddlewareProxyPropsSchema, props);
+
+ const request = useMemo(() => ({ type }), [type]);
+
+ return (
+
+ {children}
+
+ );
+ })
+);
+
+const PopoverPolymiddlewareProvider = memo(function PopoverPolymiddlewareProvider({
+ children,
+ middleware
+}: PopoverPolymiddlewareProviderProps) {
+ // Decorates middleware with .
+ const middlewareWithErrorBoundary = useMemo(
+ () =>
+ Object.freeze([
+ // TODO: [P1] Should we simplify this middleware signature and allow error boundary middleware to run on every type of middleware?
+ // (init: any) => next => (request: undefined) => reactComponentForAll()
+ // We can't do it today because we have sanity check that prevent `reactComponent()` from different middleware cross-polluting each other.
+ createErrorBoundaryMiddleware({
+ createMiddleware: createPopoverPolymiddleware,
+ reactComponent: popoverComponent,
+ where: 'Popover polymiddleware'
+ }),
+ ...middleware
+ ]),
+ [middleware]
+ );
+
+ return {children};
+});
+
+export {
+ createPopoverPolymiddleware,
+ extractPopoverEnhancer,
+ popoverComponent,
+ PopoverPolymiddlewareProvider,
+ PopoverPolymiddlewareProxy,
+ useBuildRenderPopoverCallback,
+ type PopoverPolymiddleware,
+ type PopoverPolymiddlewareHandler,
+ type PopoverPolymiddlewareHandlerResult,
+ type PopoverPolymiddlewareProps,
+ type PopoverPolymiddlewareProviderProps,
+ type PopoverPolymiddlewareProxyProps,
+ type PopoverPolymiddlewareRenderer,
+ type PopoverPolymiddlewareRequest
+};
diff --git a/packages/api-middleware/src/private/templatePolymiddleware.tsx b/packages/api-middleware/src/private/templatePolymiddleware.tsx
index 9b9cd80541..02cb85a1e2 100644
--- a/packages/api-middleware/src/private/templatePolymiddleware.tsx
+++ b/packages/api-middleware/src/private/templatePolymiddleware.tsx
@@ -74,7 +74,7 @@ function templatePolymiddleware(name: string) {
return false;
} else if (!safeParse(middlewareSchema, result).success) {
- console.warn(`botframework-webchat: ${name}.middleware must be created using factory function`);
+ console.warn(`botframework-webchat: ${name}.middleware must be created using factory function`, result);
return false;
}
diff --git a/packages/api-middleware/src/types/Polymiddleware.ts b/packages/api-middleware/src/types/Polymiddleware.ts
index 729d27c87d..9711740175 100644
--- a/packages/api-middleware/src/types/Polymiddleware.ts
+++ b/packages/api-middleware/src/types/Polymiddleware.ts
@@ -1,4 +1,12 @@
import { type ActivityPolymiddleware } from '../activityPolymiddleware';
+import { type ButtonPolymiddleware } from '../buttonPolymiddleware';
+import { type ChatLauncherButtonPolymiddleware } from '../chatLauncherButtonPolymiddleware';
import { type ErrorBoxPolymiddleware } from '../errorBoxPolymiddleware';
+import { type PopoverPolymiddleware } from '../popoverPolymiddleware';
-export type Polymiddleware = ActivityPolymiddleware | ErrorBoxPolymiddleware;
+export type Polymiddleware =
+ | ActivityPolymiddleware
+ | ButtonPolymiddleware
+ | ChatLauncherButtonPolymiddleware
+ | ErrorBoxPolymiddleware
+ | PopoverPolymiddleware;
diff --git a/packages/api-middleware/tsup.config.ts b/packages/api-middleware/tsup.config.ts
index d2bfd849cf..fbfa7926c2 100644
--- a/packages/api-middleware/tsup.config.ts
+++ b/packages/api-middleware/tsup.config.ts
@@ -2,22 +2,19 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['api/src/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-api-middleware': './src/index.ts',
'botframework-webchat-api-middleware.legacy': './src/legacy.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
{
...commonConfig,
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/api/.gitignore b/packages/api/.gitignore
index d6ea368dc0..6df6822463 100644
--- a/packages/api/.gitignore
+++ b/packages/api/.gitignore
@@ -1,6 +1,5 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/api/package.json b/packages/api/package.json
index 3cef62ebcd..0e42f533ea 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -75,12 +75,15 @@
],
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/component#readme",
"scripts": {
- "build": "npm run build:globalize && npm run build:tsup && npm run build:dtsroll && npm run build:validate",
- "build:globalize": "node scripts/createPrecompiledGlobalize.mjs",
- "build:tsup": "tsup",
- "build:dtsroll": "dtsroll ./dist/*.d.*",
- "build:validate": "npm run build:validate:dts",
- "build:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:post": "npm run build:post:dtsroll && npm run build:post:validate:dts",
+ "build:post:dtsroll": "dtsroll ./dist/*.d.*",
+ "build:post:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch && npm run build:pre:globalize",
+ "build:pre:globalize": "node scripts/createPrecompiledGlobalize.mjs",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -90,17 +93,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build:tsup -- --watch"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-api-middleware": "development",
- "@msinternal/botframework-webchat-base": "development",
- "@msinternal/botframework-webchat-cldr-data": "development",
- "@msinternal/botframework-webchat-react-hooks": "development",
- "@msinternal/botframework-webchat-react-valibot": "development",
- "@msinternal/botframework-webchat-redux-store": "development",
- "@msinternal/botframework-webchat-tsconfig": "development",
- "botframework-webchat-core": "production"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../api-middleware/package.json\" \"../base/package.json\" \"../support/cldr-data/package.json\" \"../react-hooks/package.json\" \"../react-valibot/package.json\" \"../redux-store/package.json\" \"../tsconfig/package.json\" \"../core/package.json\""
},
"pinDependencies": {
"@types/react": [
@@ -116,6 +109,16 @@
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-api-middleware": "development",
+ "@msinternal/botframework-webchat-base": "development",
+ "@msinternal/botframework-webchat-cldr-data": "development",
+ "@msinternal/botframework-webchat-react-hooks": "development",
+ "@msinternal/botframework-webchat-react-valibot": "development",
+ "@msinternal/botframework-webchat-redux-store": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development",
+ "botframework-webchat-core": "production"
+ },
"devDependencies": {
"@babel/core": "^7.28.0",
"@babel/preset-env": "^7.28.0",
diff --git a/packages/api/src/StyleOptions.ts b/packages/api/src/StyleOptions.ts
index aa846b7cf6..44f9427c54 100644
--- a/packages/api/src/StyleOptions.ts
+++ b/packages/api/src/StyleOptions.ts
@@ -894,7 +894,7 @@ type StyleOptions = {
*
* @default document.head
*/
- stylesRoot?: Node;
+ stylesRoot?: Node | undefined;
/**
* Border animation
diff --git a/packages/api/src/boot/middleware.ts b/packages/api/src/boot/middleware.ts
index 8d42eb1069..35fdde598a 100644
--- a/packages/api/src/boot/middleware.ts
+++ b/packages/api/src/boot/middleware.ts
@@ -16,6 +16,34 @@ export {
type ActivityPolymiddlewareRequest
} from '@msinternal/botframework-webchat-api-middleware';
+export {
+ buttonComponent,
+ ButtonPolymiddlewareProxy,
+ createButtonPolymiddleware,
+ useBuildRenderButtonCallback,
+ type ButtonPolymiddleware,
+ type ButtonPolymiddlewareHandler,
+ type ButtonPolymiddlewareHandlerResult,
+ type ButtonPolymiddlewareProps,
+ type ButtonPolymiddlewareProxyProps,
+ type ButtonPolymiddlewareRenderer,
+ type ButtonPolymiddlewareRequest
+} from '@msinternal/botframework-webchat-api-middleware';
+
+export {
+ chatLauncherButtonComponent,
+ ChatLauncherButtonPolymiddlewareProxy,
+ createChatLauncherButtonPolymiddleware,
+ useBuildRenderChatLauncherButtonCallback,
+ type ChatLauncherButtonPolymiddleware,
+ type ChatLauncherButtonPolymiddlewareHandler,
+ type ChatLauncherButtonPolymiddlewareHandlerResult,
+ type ChatLauncherButtonPolymiddlewareProps,
+ type ChatLauncherButtonPolymiddlewareProxyProps,
+ type ChatLauncherButtonPolymiddlewareRenderer,
+ type ChatLauncherButtonPolymiddlewareRequest
+} from '@msinternal/botframework-webchat-api-middleware';
+
export {
createErrorBoxPolymiddleware,
errorBoxComponent,
@@ -30,4 +58,18 @@ export {
type ErrorBoxPolymiddlewareRequest
} from '@msinternal/botframework-webchat-api-middleware';
+export {
+ createPopoverPolymiddleware,
+ popoverComponent,
+ PopoverPolymiddlewareProxy,
+ useBuildRenderPopoverCallback,
+ type PopoverPolymiddleware,
+ type PopoverPolymiddlewareHandler,
+ type PopoverPolymiddlewareHandlerResult,
+ type PopoverPolymiddlewareProps,
+ type PopoverPolymiddlewareProxyProps,
+ type PopoverPolymiddlewareRenderer,
+ type PopoverPolymiddlewareRequest
+} from '@msinternal/botframework-webchat-api-middleware';
+
export { default as createActivityPolymiddlewareFromLegacy } from '../legacy/createActivityPolymiddlewareFromLegacy';
diff --git a/packages/api/tsup.config.ts b/packages/api/tsup.config.ts
index 5ad48a19c5..fb023e1519 100644
--- a/packages/api/tsup.config.ts
+++ b/packages/api/tsup.config.ts
@@ -2,9 +2,6 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['component/src/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
@@ -13,8 +10,7 @@ const commonConfig = applyConfig(config => ({
'botframework-webchat-api.hook': './src/boot/hook.ts',
'botframework-webchat-api.internal': './src/boot/internal.ts',
'botframework-webchat-api.middleware': './src/boot/middleware.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
@@ -25,7 +21,8 @@ export default defineConfig([
'globalThis.WEB_CHAT_BUILD_INFO_MODULE_FORMAT': '"esmodules"'
},
format: 'esm',
- noExternal: [...(commonConfig.noExternal ?? []), 'globalize']
+ noExternal: [...(commonConfig.noExternal ?? []), 'globalize'],
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/base/.gitignore b/packages/base/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/base/.gitignore
+++ b/packages/base/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/base/package.json b/packages/base/package.json
index eae50cbffe..51cf552aa8 100644
--- a/packages/base/package.json
+++ b/packages/base/package.json
@@ -43,7 +43,11 @@
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/component#readme",
"private": true,
"scripts": {
- "build": "tsup",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -53,7 +57,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../tsconfig/package.json\""
},
"localDependencies": {
"@msinternal/botframework-webchat-tsconfig": "development"
diff --git a/packages/base/tsup.config.ts b/packages/base/tsup.config.ts
index 12174d0851..86d8e13469 100644
--- a/packages/base/tsup.config.ts
+++ b/packages/base/tsup.config.ts
@@ -2,30 +2,19 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = [
- 'api/src/index.ts',
- 'api-middleware/src/index.ts',
- 'bundle/src/boot/exports/index.ts',
- 'component/src/index.ts',
- 'core/src/index.ts',
- 'debug-theme/src/index.ts',
- 'fluent-theme/src/index.ts'
-];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-base': './src/index.ts',
'botframework-webchat-base.utils': './src/utils/index.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
{
...commonConfig,
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/bundle/.gitignore b/packages/bundle/.gitignore
index d412f912e3..7f3c011f4b 100644
--- a/packages/bundle/.gitignore
+++ b/packages/bundle/.gitignore
@@ -1,6 +1,5 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/static/
/tsup.config.bundled_*.mjs
diff --git a/packages/bundle/esbuild.static.mjs b/packages/bundle/esbuild.static.mjs
index 439dafe42b..3030ae06e9 100644
--- a/packages/bundle/esbuild.static.mjs
+++ b/packages/bundle/esbuild.static.mjs
@@ -11,28 +11,6 @@ import { readPackage } from 'read-pkg';
import { fileURLToPath } from 'url';
import { cssPlugin } from '../../esbuildPlugins.mjs';
-// eslint-disable-next-line no-unused-vars
-const isomorphicReactPlugin = {
- name: 'isomorphic-react',
- setup(build) {
- // eslint-disable-next-line require-unicode-regexp
- build.onResolve({ filter: /^(react|react-dom)$/, namespace: 'file' }, ({ path }) => ({
- namespace: 'isomorphic-react',
- path
- }));
-
- // eslint-disable-next-line require-unicode-regexp
- build.onLoad({ filter: /^react$/, namespace: 'isomorphic-react' }, () => ({
- contents: "import React from 'react'; module.exports = globalThis.React || React;"
- }));
-
- // eslint-disable-next-line require-unicode-regexp
- build.onLoad({ filter: /^react-dom$/, namespace: 'isomorphic-react' }, () => ({
- contents: "import ReactDOM from 'react-dom'; module.exports = globalThis.ReactDOM || ReactDOM;"
- }));
- }
-};
-
function createWatcherPlugin(name) {
/** @type { import('esbuild').Plugin } */
return {
@@ -130,6 +108,7 @@ const IGNORED_OWN_PACKAGES = [
'botframework-webchat': './src/boot/exports/index.ts',
'botframework-webchat/component': './src/boot/exports/component.ts',
'botframework-webchat/decorator': './src/boot/exports/decorator.ts',
+ 'botframework-webchat/experience/chatLauncher': './src/boot/exports/experience/chatLauncher.ts',
'botframework-webchat/hook': './src/boot/exports/hook.ts',
'botframework-webchat/internal': './src/boot/exports/internal.ts',
'botframework-webchat/middleware': './src/boot/exports/middleware.ts',
diff --git a/packages/bundle/experience/chatLauncher.js b/packages/bundle/experience/chatLauncher.js
new file mode 100644
index 0000000000..aeceb7f170
--- /dev/null
+++ b/packages/bundle/experience/chatLauncher.js
@@ -0,0 +1,3 @@
+// This is required for Webpack 4 which does not support named exports.
+// eslint-disable-next-line no-undef
+module.exports = require('./dist/botframework-webchat.experience.chat-launcher.js');
diff --git a/packages/bundle/package.json b/packages/bundle/package.json
index 432a98e834..418f2c1bd3 100644
--- a/packages/bundle/package.json
+++ b/packages/bundle/package.json
@@ -35,6 +35,12 @@
"default": "./dist/botframework-webchat.decorator.js"
}
},
+ "./experience/chatLauncher": {
+ "import": {
+ "types": "./dist/botframework-webchat.experience.chat-launcher.d.mts",
+ "default": "./dist/botframework-webchat.experience.chat-launcher.mjs"
+ }
+ },
"./hook": {
"import": {
"types": "./dist/botframework-webchat.hook.d.mts",
@@ -82,6 +88,7 @@
"homepage": "https://github.com/microsoft/BotFramework-WebChat/#readme",
"files": [
"./dist/**/*",
+ "./experience/**/*",
"./src/**/*",
"./static/**/*"
],
@@ -98,12 +105,16 @@
}
},
"scripts": {
- "build": "npm run build:static && npm run build:tsup && npm run build:dtsroll && npm run build:validate",
- "build:static": "node ./esbuild.static.mjs",
- "build:tsup": "tsup",
- "build:dtsroll": "dtsroll ./dist/*.d.*",
- "build:validate": "npm run build:validate:dts",
- "build:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:post": "npm run build:post:dtsroll && npm run build:post:validate:dts",
+ "build:post:dtsroll": "dtsroll ./dist/*.d.*",
+ "build:post:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "concurrently --prefix-colors \"auto\" \"npm:build:run:*\"",
+ "build:run:static": "node ./esbuild.static.mjs",
+ "build:run:tsup": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -113,38 +124,9 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "cross-env NODE_OPTIONS=--no-deprecation concurrently --kill-others --prefix-colors \"auto\" \"npm:start:*\"",
- "start:static": "npm run build:static -- --watch",
- "start:tsup": "npm run build:tsup -- --watch",
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../repack/adaptivecards/package.json\" \"../repack/base64-js/package.json\" \"../repack/botframework-directlinejs/package.json\" \"../base/package.json\" \"../experience-chat-launcher/package.json\" \"../react-valibot/package.json\" \"../tsconfig/package.json\" \"../isomorphic-react/package.json\" \"../isomorphic-react-dom/package.json\" \"../repack/microsoft-cognitiveservices-speech-sdk/package.json\" \"../repack/object-assign/package.json\" \"../repack/react/package.json\" \"../repack/react@baseline/package.json\" \"../repack/react-dom/package.json\" \"../repack/react-dom@baseline/package.json\" \"../repack/react-dom@umd/package.json\" \"../repack/react-is/package.json\" \"../repack/react@umd/package.json\" \"../directlinespeech/package.json\" \"../api/package.json\" \"../component/package.json\" \"../core/package.json\"",
"test:tsd": "tsd"
},
- "localDependencies": {
- "@msinternal/adaptivecards": "development",
- "@msinternal/base64-js": "development",
- "@msinternal/botframework-webchat-base": "development",
- "@msinternal/botframework-directlinejs": "development",
- "@msinternal/botframework-webchat-react-valibot": "development",
- "@msinternal/botframework-webchat-tsconfig": "development",
- "@msinternal/isomorphic-react-baseline": "development",
- "@msinternal/isomorphic-react-dom-baseline": "development",
- "@msinternal/isomorphic-react-dom-umd": "development",
- "@msinternal/isomorphic-react-dom": "development",
- "@msinternal/isomorphic-react-umd": "development",
- "@msinternal/isomorphic-react": "development",
- "@msinternal/microsoft-cognitiveservices-speech-sdk": "development",
- "@msinternal/object-assign": "development",
- "@msinternal/react-baseline": "development",
- "@msinternal/react-dom-baseline": "development",
- "@msinternal/react-dom-umd": "development",
- "@msinternal/react-dom": "development",
- "@msinternal/react-is": "development",
- "@msinternal/react-umd": "development",
- "@msinternal/react": "development",
- "botframework-directlinespeech-sdk": "production",
- "botframework-webchat-api": "production",
- "botframework-webchat-component": "production",
- "botframework-webchat-core": "production"
- },
"pinDependencies": {
"@types/react": [
"16",
@@ -171,36 +153,29 @@
"uuid@9 emit non-ES5 build because of default parameters"
]
},
- "dependencies": {
- "@babel/runtime": "7.28.2",
- "adaptivecards": "3.0.2",
- "botframework-directlinejs": "0.15.6",
- "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.5.1",
- "core-js": "3.44.0",
- "katex": "0.16.22",
- "math-random": "2.0.1",
- "mdast-util-from-markdown": "2.0.2",
- "memoize-one": "6.0.0",
- "micromark": "4.0.2",
- "micromark-extension-gfm": "3.0.0",
- "micromark-util-character": "2.1.1",
- "micromark-util-sanitize-uri": "^2.0.1",
- "microsoft-cognitiveservices-speech-sdk": "1.17.0",
- "prop-types": "15.8.1",
- "punycode": "2.3.1",
- "sanitize-html": "2.17.0",
- "shiki": "2.5.0",
- "swiper": "8.4.7",
- "url-search-params-polyfill": "8.2.5",
- "use-ref-from": "0.1.0",
- "uuid": "8.3.2",
- "valibot": "1.1.0",
- "web-speech-cognitive-services": "8.1.3",
- "whatwg-fetch": "3.6.20"
+ "localDependencies": {
+ "@msinternal/adaptivecards": "development",
+ "@msinternal/base64-js": "development",
+ "@msinternal/botframework-directlinejs": "development",
+ "@msinternal/botframework-webchat-base": "development",
+ "@msinternal/botframework-webchat-experience-chat-launcher": "development",
+ "@msinternal/botframework-webchat-react-valibot": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development",
+ "@msinternal/isomorphic-react": "development",
+ "@msinternal/isomorphic-react-dom": "development",
+ "@msinternal/microsoft-cognitiveservices-speech-sdk": "development",
+ "@msinternal/object-assign": "development",
+ "@msinternal/react": "development",
+ "@msinternal/react-baseline": "development",
+ "@msinternal/react-dom": "development",
+ "@msinternal/react-dom-baseline": "development",
+ "@msinternal/react-dom-umd": "development",
+ "@msinternal/react-is": "development",
+ "@msinternal/react-umd": "development",
+ "botframework-directlinespeech-sdk": "production",
+ "botframework-webchat-api": "production",
+ "botframework-webchat-component": "production",
+ "botframework-webchat-core": "production"
},
"devDependencies": {
"@babel/core": "^7.28.0",
@@ -212,6 +187,7 @@
"@msinternal/base64-js": "0.0.0-0",
"@msinternal/botframework-directlinejs": "0.0.0-0",
"@msinternal/botframework-webchat-base": "0.0.0-0",
+ "@msinternal/botframework-webchat-experience-chat-launcher": "0.0.0-0",
"@msinternal/botframework-webchat-react-valibot": "0.0.0-0",
"@msinternal/botframework-webchat-tsconfig": "0.0.0-0",
"@msinternal/isomorphic-react": "0.0.0-0",
@@ -239,6 +215,37 @@
"type-fest": "^4.41.0",
"typescript": "~5.8.3"
},
+ "dependencies": {
+ "@babel/runtime": "7.28.2",
+ "adaptivecards": "3.0.2",
+ "botframework-directlinejs": "0.15.6",
+ "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.5.1",
+ "core-js": "3.44.0",
+ "katex": "0.16.22",
+ "math-random": "2.0.1",
+ "mdast-util-from-markdown": "2.0.2",
+ "memoize-one": "6.0.0",
+ "micromark": "4.0.2",
+ "micromark-extension-gfm": "3.0.0",
+ "micromark-util-character": "2.1.1",
+ "micromark-util-sanitize-uri": "^2.0.1",
+ "microsoft-cognitiveservices-speech-sdk": "1.17.0",
+ "prop-types": "15.8.1",
+ "punycode": "2.3.1",
+ "sanitize-html": "2.17.0",
+ "shiki": "2.5.0",
+ "swiper": "8.4.7",
+ "url-search-params-polyfill": "8.2.5",
+ "use-ref-from": "0.1.0",
+ "uuid": "8.3.2",
+ "valibot": "1.1.0",
+ "web-speech-cognitive-services": "8.1.3",
+ "whatwg-fetch": "3.6.20"
+ },
"peerDependencies": {
"@types/react": "^16.14.65",
"react": ">= 16.8.6",
diff --git a/packages/bundle/src/boot/actual/experience/chatLauncher.ts b/packages/bundle/src/boot/actual/experience/chatLauncher.ts
new file mode 100644
index 0000000000..b5a7a7a54a
--- /dev/null
+++ b/packages/bundle/src/boot/actual/experience/chatLauncher.ts
@@ -0,0 +1 @@
+export { ChatLauncher } from '@msinternal/botframework-webchat-experience-chat-launcher';
diff --git a/packages/bundle/src/boot/actual/middleware.ts b/packages/bundle/src/boot/actual/middleware.ts
index 9641816786..7cb70c59a2 100644
--- a/packages/bundle/src/boot/actual/middleware.ts
+++ b/packages/bundle/src/boot/actual/middleware.ts
@@ -9,8 +9,35 @@ export {
type ActivityPolymiddlewareProps,
type ActivityPolymiddlewareProxyProps,
type ActivityPolymiddlewareRenderer,
- type ActivityPolymiddlewareRequest,
- type Polymiddleware
+ type ActivityPolymiddlewareRequest
+} from 'botframework-webchat-api/middleware';
+
+export {
+ buttonComponent,
+ ButtonPolymiddlewareProxy,
+ createButtonPolymiddleware,
+ useBuildRenderButtonCallback,
+ type ButtonPolymiddleware,
+ type ButtonPolymiddlewareHandler,
+ type ButtonPolymiddlewareHandlerResult,
+ type ButtonPolymiddlewareProps,
+ type ButtonPolymiddlewareProxyProps,
+ type ButtonPolymiddlewareRenderer,
+ type ButtonPolymiddlewareRequest
+} from 'botframework-webchat-api/middleware';
+
+export {
+ chatLauncherButtonComponent,
+ ChatLauncherButtonPolymiddlewareProxy,
+ createChatLauncherButtonPolymiddleware,
+ useBuildRenderChatLauncherButtonCallback,
+ type ChatLauncherButtonPolymiddleware,
+ type ChatLauncherButtonPolymiddlewareHandler,
+ type ChatLauncherButtonPolymiddlewareHandlerResult,
+ type ChatLauncherButtonPolymiddlewareProps,
+ type ChatLauncherButtonPolymiddlewareProxyProps,
+ type ChatLauncherButtonPolymiddlewareRenderer,
+ type ChatLauncherButtonPolymiddlewareRequest
} from 'botframework-webchat-api/middleware';
export {
@@ -27,4 +54,18 @@ export {
type ErrorBoxPolymiddlewareRequest
} from 'botframework-webchat-api/middleware';
-export { createActivityPolymiddlewareFromLegacy } from 'botframework-webchat-api/middleware';
+export {
+ createPopoverPolymiddleware,
+ popoverComponent,
+ PopoverPolymiddlewareProxy,
+ useBuildRenderPopoverCallback,
+ type PopoverPolymiddleware,
+ type PopoverPolymiddlewareHandler,
+ type PopoverPolymiddlewareHandlerResult,
+ type PopoverPolymiddlewareProps,
+ type PopoverPolymiddlewareProxyProps,
+ type PopoverPolymiddlewareRenderer,
+ type PopoverPolymiddlewareRequest
+} from 'botframework-webchat-api/middleware';
+
+export { createActivityPolymiddlewareFromLegacy, type Polymiddleware } from 'botframework-webchat-api/middleware';
diff --git a/packages/bundle/src/boot/exports/experience/chatLauncher.ts b/packages/bundle/src/boot/exports/experience/chatLauncher.ts
new file mode 100644
index 0000000000..a7d1e88959
--- /dev/null
+++ b/packages/bundle/src/boot/exports/experience/chatLauncher.ts
@@ -0,0 +1 @@
+export * from '../../actual/experience/chatLauncher';
diff --git a/packages/bundle/src/index.ts b/packages/bundle/src/index.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/bundle/tsup.config.ts b/packages/bundle/tsup.config.ts
index c885f394f9..f323c70d18 100644
--- a/packages/bundle/tsup.config.ts
+++ b/packages/bundle/tsup.config.ts
@@ -21,6 +21,7 @@ const commonConfig = applyConfig(config => ({
'botframework-webchat': './src/boot/exports/index.ts',
'botframework-webchat.component': './src/boot/exports/component.ts',
'botframework-webchat.decorator': './src/boot/exports/decorator.ts',
+ 'botframework-webchat.experience.chatLauncher': './src/boot/exports/experience/chatLauncher.ts',
'botframework-webchat.hook': './src/boot/exports/hook.ts',
'botframework-webchat.internal': './src/boot/exports/internal.ts',
'botframework-webchat.middleware': './src/boot/exports/middleware.ts'
@@ -76,7 +77,8 @@ export default defineConfig([
...commonConfig.define,
'globalThis.WEB_CHAT_BUILD_INFO_MODULE_FORMAT': '"esmodules"'
},
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/component/.gitignore b/packages/component/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/component/.gitignore
+++ b/packages/component/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/component/package.json b/packages/component/package.json
index ca1f90a291..a339acd58f 100644
--- a/packages/component/package.json
+++ b/packages/component/package.json
@@ -75,12 +75,15 @@
],
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/component#readme",
"scripts": {
- "build": "npm run build:tsup && npm run build:dtsroll && npm run build:validate",
- "build:tsup": "tsup",
- "build:dtsroll": "dtsroll ./dist/*.d.*",
- "build:validate": "npm run build:validate:css && npm run build:validate:dts",
- "build:validate:css": "grep -q -P '\\.webchat \\.w([a-zA-Z-]){6}_' dist/*.css 2>/dev/null || { echo \"Error: dist/*.css is not compiled by Lightning CSS\" >&2; exit 1; }",
- "build:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:post": "npm run build:post:dtsroll && npm run build:post:validate:css && npm run build:post:validate:dts",
+ "build:post:dtsroll": "dtsroll ./dist/*.d.*",
+ "build:post:validate:css": "grep -q -P '\\.webchat \\.w([a-zA-Z-]){6}_' dist/*.css 2>/dev/null || { echo \"Error: dist/*.css is not compiled by Lightning CSS\" >&2; exit 1; }",
+ "build:post:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -90,16 +93,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build:tsup -- --watch"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-base": "development",
- "@msinternal/botframework-webchat-react-hooks": "development",
- "@msinternal/botframework-webchat-react-valibot": "development",
- "@msinternal/botframework-webchat-styles": "development",
- "@msinternal/botframework-webchat-tsconfig": "development",
- "botframework-webchat-api": "production",
- "botframework-webchat-core": "production"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../base/package.json\" \"../react-hooks/package.json\" \"../react-valibot/package.json\" \"../styles/package.json\" \"../tsconfig/package.json\" \"../api/package.json\" \"../core/package.json\""
},
"pinDependencies": {
"@types/react": [
@@ -125,6 +119,15 @@
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-base": "development",
+ "@msinternal/botframework-webchat-react-hooks": "development",
+ "@msinternal/botframework-webchat-react-valibot": "development",
+ "@msinternal/botframework-webchat-styles": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development",
+ "botframework-webchat-api": "production",
+ "botframework-webchat-core": "production"
+ },
"devDependencies": {
"@babel/core": "^7.28.0",
"@babel/preset-env": "^7.28.0",
diff --git a/packages/component/tsup.config.ts b/packages/component/tsup.config.ts
index 186ce2fda5..9ff33e0e85 100644
--- a/packages/component/tsup.config.ts
+++ b/packages/component/tsup.config.ts
@@ -5,9 +5,6 @@ import { applyConfig } from '../../tsup.base.config';
import { decoratorStyleContent as decoratorStyleContentPlaceholder } from './src/decorator/stylesheet/createDecoratorStyleElements';
import { componentStyleContent as componentStyleContentPlaceholder } from './src/stylesheet/createComponentStyleElements';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['bundle/src/boot/exports/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
@@ -27,8 +24,7 @@ const commonConfig = applyConfig(config => ({
stylesPlaceholder: componentStyleContentPlaceholder
}),
injectCSSPlugin({ stylesPlaceholder: decoratorStyleContentPlaceholder })
- ],
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ ]
}));
export default defineConfig([
@@ -38,7 +34,8 @@ export default defineConfig([
...commonConfig.define,
'globalThis.WEB_CHAT_BUILD_INFO_MODULE_FORMAT': '"esmodules"'
},
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/core/.gitignore b/packages/core/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/core/.gitignore
+++ b/packages/core/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/core/package.json b/packages/core/package.json
index 647c86544a..876eb81803 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -24,6 +24,16 @@
"types": "./dist/botframework-webchat-core.internal.d.ts",
"default": "./dist/botframework-webchat-core.internal.js"
}
+ },
+ "./schema": {
+ "import": {
+ "types": "./dist/botframework-webchat-core.schema.d.mts",
+ "default": "./dist/botframework-webchat-core.schema.mjs"
+ },
+ "require": {
+ "types": "./dist/botframework-webchat-core.schema.d.ts",
+ "default": "./dist/botframework-webchat-core.schema.js"
+ }
}
},
"publishConfig": {
@@ -57,11 +67,14 @@
}
},
"scripts": {
- "build": "npm run build:tsup && npm run build:dtsroll && npm run build:validate",
- "build:dtsroll": "dtsroll ./dist/*.d.*",
- "build:tsup": "tsup",
- "build:validate": "npm run build:validate:dts",
- "build:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:post": "npm run build:post:dtsroll && npm run build:post:validate:dts",
+ "build:post:dtsroll": "dtsroll ./dist/*.d.*",
+ "build:post:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -71,22 +84,22 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build:tsup -- --watch",
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../base/package.json\" \"../tsconfig/package.json\"",
"test:tsd": "tsd"
},
"engines": {
"node": ">=12.0.0"
},
- "localDependences": {
- "@msinternal/botframework-webchat-base": "development",
- "@msinternal/botframework-webchat-tsconfig": "development"
- },
"pinDependencies": {
"typescript": [
"~5.8.3",
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-base": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development"
+ },
"devDependencies": {
"@babel/core": "^7.28.0",
"@babel/plugin-transform-runtime": "^7.28.0",
diff --git a/packages/core/schema.js b/packages/core/schema.js
new file mode 100644
index 0000000000..32fd97f48f
--- /dev/null
+++ b/packages/core/schema.js
@@ -0,0 +1,3 @@
+// This is required for Webpack 4 which does not support named exports.
+// eslint-disable-next-line no-undef
+module.exports = require('./dist/botframework-webchat-core.schema.js');
diff --git a/packages/core/src/schema/directLineJSBotConnection.ts b/packages/core/src/schema/directLineJSBotConnection.ts
new file mode 100644
index 0000000000..34d8da2e54
--- /dev/null
+++ b/packages/core/src/schema/directLineJSBotConnection.ts
@@ -0,0 +1,46 @@
+import {
+ custom,
+ object,
+ optional,
+ safeParse,
+ string,
+ type CustomIssue,
+ type CustomSchema,
+ type ErrorMessage,
+ type InferOutput
+} from 'valibot';
+
+import { type WebChatActivity } from '../types/WebChatActivity';
+import observable, { type Observable } from './observable';
+import customFunction from './private/customFunction';
+
+const directLineJSBotConnectionSchema = object({
+ activity$: observable('activity$ must be an observable'),
+ connectionStatus$: observable('connectionStatus$ must be an observable'),
+ end: optional(customFunction<() => void>('end must be a function')),
+ getSessionId: optional(customFunction<() => Observable>('getSessionId must be a function')),
+ postActivity: customFunction<() => Observable>('postActivity must be a function'),
+ referenceGrammarId: optional(string('referenceGrammarId must be a string')),
+ setUserId: optional(customFunction<(userId: string | undefined) => void>('setUserId must be a function'))
+});
+
+type DirectLineJSBotConnection = InferOutput;
+
+function directLineJSBotConnection(): CustomSchema;
+
+function directLineJSBotConnection<
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message: TMessage): CustomSchema;
+
+function directLineJSBotConnection<
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema {
+ return custom(
+ value => safeParse(directLineJSBotConnectionSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default directLineJSBotConnection;
+export { type DirectLineJSBotConnection };
diff --git a/packages/core/src/schema/index.ts b/packages/core/src/schema/index.ts
new file mode 100644
index 0000000000..49e2dce348
--- /dev/null
+++ b/packages/core/src/schema/index.ts
@@ -0,0 +1,2 @@
+export { default as directLineJSBotConnection, type DirectLineJSBotConnection } from './directLineJSBotConnection';
+export { default as observable, type Observable } from './observable';
diff --git a/packages/core/src/schema/observable.ts b/packages/core/src/schema/observable.ts
new file mode 100644
index 0000000000..2c0a54a680
--- /dev/null
+++ b/packages/core/src/schema/observable.ts
@@ -0,0 +1,28 @@
+import { custom, function_, object, safeParse, type CustomIssue, type CustomSchema, type ErrorMessage } from 'valibot';
+
+import { type Observable } from '../types/external/Observable';
+
+const observableSchema = object({ subscribe: function_() });
+
+function observable(): CustomSchema, undefined>;
+
+function observable(): CustomSchema, undefined>;
+
+function observable<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message: TMessage): CustomSchema, TMessage>;
+
+function observable<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema, TMessage> {
+ return custom, TMessage>(
+ value => safeParse(observableSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default observable;
+export { type Observable };
diff --git a/packages/core/src/schema/private/customFunction.ts b/packages/core/src/schema/private/customFunction.ts
new file mode 100644
index 0000000000..1754465cd9
--- /dev/null
+++ b/packages/core/src/schema/private/customFunction.ts
@@ -0,0 +1,16 @@
+import { custom, function_, safeParse, type CustomIssue, type CustomSchema, type ErrorMessage } from 'valibot';
+
+function customFunction(): CustomSchema<(...args: any[]) => any, undefined>;
+
+function customFunction any>(): CustomSchema;
+
+function customFunction<
+ T extends (...args: any[]) => any,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema;
+
+function customFunction any>() {
+ return custom(value => safeParse(function_(), value).success);
+}
+
+export default customFunction;
diff --git a/packages/core/tsup.config.ts b/packages/core/tsup.config.ts
index 6b9b56867b..e54948934e 100644
--- a/packages/core/tsup.config.ts
+++ b/packages/core/tsup.config.ts
@@ -2,16 +2,13 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['api/src/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-core': './src/index.ts',
- 'botframework-webchat-core.internal': './src/internal/index.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ 'botframework-webchat-core.internal': './src/internal/index.ts',
+ 'botframework-webchat-core.schema': './src/schema/index.ts'
+ }
}));
export default defineConfig([
@@ -21,7 +18,8 @@ export default defineConfig([
...commonConfig.define,
'globalThis.WEB_CHAT_BUILD_INFO_MODULE_FORMAT': '"esmodules"'
},
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/debug-theme/.gitignore b/packages/debug-theme/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/debug-theme/.gitignore
+++ b/packages/debug-theme/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/debug-theme/package.json b/packages/debug-theme/package.json
index c2607c5747..e1070a2ff6 100644
--- a/packages/debug-theme/package.json
+++ b/packages/debug-theme/package.json
@@ -35,10 +35,13 @@
"./src/**/*",
"*.js"
],
- "localDependencies": {},
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/debug-theme#readme",
"scripts": {
- "build": "tsup --config ./tsup.config.ts",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -48,13 +51,17 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../api/package.json\" \"../component/package.json\""
},
- "peerDependencies": {
- "react": ">= 16.8.6"
+ "localDependencies": {
+ "botframework-webchat-api": "production",
+ "botframework-webchat-component": "production"
},
"dependencies": {
"botframework-webchat-api": "^0.0.0-0",
"botframework-webchat-component": "^0.0.0-0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.6"
}
}
diff --git a/packages/debug-theme/tsup.config.ts b/packages/debug-theme/tsup.config.ts
index 089a22e198..329296705e 100644
--- a/packages/debug-theme/tsup.config.ts
+++ b/packages/debug-theme/tsup.config.ts
@@ -49,7 +49,8 @@ export default defineConfig([
entry: {
'botframework-webchat-debug-theme': './src/index.ts'
},
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
})),
applyConfig(config => ({
...config,
diff --git a/packages/directlinespeech/.gitignore b/packages/directlinespeech/.gitignore
index 3e330334ba..06e76e78ad 100644
--- a/packages/directlinespeech/.gitignore
+++ b/packages/directlinespeech/.gitignore
@@ -1,6 +1,5 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/directlinespeech/package.json b/packages/directlinespeech/package.json
index 9a21bccfa4..057e119def 100644
--- a/packages/directlinespeech/package.json
+++ b/packages/directlinespeech/package.json
@@ -20,13 +20,20 @@
}
}
},
+ "engines": {
+ "node": ">= 10.14.2"
+ },
"scripts": {
- "build": "npm run build:tsup && npm run build:babel && npm run build:webpack",
- "build:babel": "cross-env build_tool=babel module_format=commonjs babel src --ignore **/*.spec.js,**/*.test.js,__tests__/**/*.js --out-dir lib --verbose",
- "build:tsup": "tsup",
- "build:webpack": "npm run build:webpack:development && npm run build:webpack:production",
- "build:webpack:development": "cross-env node_env=development webpack-cli",
- "build:webpack:production": "cross-env node_env=production webpack-cli",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "npm run build:run:tsup && npm run build:run:babel && npm run build:run:webpack",
+ "build:run:babel": "cross-env build_tool=babel module_format=commonjs babel src --ignore **/*.spec.js,**/*.test.js,__tests__/**/*.js --out-dir lib --verbose",
+ "build:run:tsup": "tsup",
+ "build:run:webpack": "npm run build:run:webpack:development && npm run build:run:webpack:production",
+ "build:run:webpack:development": "cross-env node_env=development webpack-cli",
+ "build:run:webpack:production": "cross-env node_env=production webpack-cli",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -36,16 +43,12 @@
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"prettier": "prettier --check src/**/*.{js,ts}",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "concurrently --kill-others --prefix-colors \"auto\" \"npm:start:*\"",
- "start:babel": "npm run build:babel -- --skip-initial-build --watch",
+ "start": "../../scripts/npm/notify-build.sh \"./src/\"",
"start:serve": "serve",
- "start:tsup": "npm run build:tsup -- --watch",
- "start:webpack": "npm run build:webpack:development -- --watch",
"test": "jest --watch"
},
"author": "Microsoft Corporation",
"license": "MIT",
- "localDependencies": {},
"pinDependencies": {
"@types/jest": [
"29",
@@ -68,6 +71,7 @@
"needs to bump manually"
]
},
+ "localDependencies": {},
"devDependencies": {
"@babel/cli": "^7.28.0",
"@babel/core": "^7.28.0",
@@ -79,7 +83,6 @@
"babel-jest": "^29.7.0",
"babel-plugin-istanbul": "^7.0.0",
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
- "concurrently": "^9.2.0",
"cross-env": "^10.0.0",
"dotenv": "^17.2.1",
"eslint": "^8.57.1",
@@ -108,8 +111,5 @@
"math-random": "2.0.1",
"microsoft-cognitiveservices-speech-sdk": "1.17.0",
"web-speech-cognitive-services": "8.1.3"
- },
- "engines": {
- "node": ">= 10.14.2"
}
}
diff --git a/packages/directlinespeech/tsup.config.ts b/packages/directlinespeech/tsup.config.ts
index 1dd19e1744..d3ac54b07a 100644
--- a/packages/directlinespeech/tsup.config.ts
+++ b/packages/directlinespeech/tsup.config.ts
@@ -43,7 +43,8 @@ export default defineConfig([
...config.env,
module_format: 'esmodules'
},
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...config,
diff --git a/packages/experience-chat-launcher/.eslintrc.yml b/packages/experience-chat-launcher/.eslintrc.yml
new file mode 100644
index 0000000000..6ba5244054
--- /dev/null
+++ b/packages/experience-chat-launcher/.eslintrc.yml
@@ -0,0 +1,14 @@
+extends:
+ - ../../.eslintrc.production.yml
+ - ../../.eslintrc.react.yml
+
+# This package is compatible with web browser.
+env:
+ browser: true
+
+rules:
+ # React functional component is better in function style than arrow style.
+ prefer-arrow-callback: off
+
+ # React already deprecated default props.
+ react/require-default-props: off
diff --git a/packages/experience-chat-launcher/.gitignore b/packages/experience-chat-launcher/.gitignore
new file mode 100644
index 0000000000..52536cb56d
--- /dev/null
+++ b/packages/experience-chat-launcher/.gitignore
@@ -0,0 +1,4 @@
+/*.tgz
+/dist/
+/node_modules/
+/tsup.config.bundled_*.mjs
diff --git a/packages/experience-chat-launcher/README.md b/packages/experience-chat-launcher/README.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/experience-chat-launcher/package.json b/packages/experience-chat-launcher/package.json
new file mode 100644
index 0000000000..2374223aae
--- /dev/null
+++ b/packages/experience-chat-launcher/package.json
@@ -0,0 +1,76 @@
+{
+ "name": "@msinternal/botframework-webchat-experience-chat-launcher",
+ "version": "0.0.0-0",
+ "description": "botframework-webchat-api/middleware package",
+ "main": "./dist/botframework-webchat-experience-chat-launcher.js",
+ "types": "./dist/botframework-webchat-experience-chat-launcher.d.ts",
+ "exports": {
+ ".": {
+ "import": {
+ "types": "./dist/botframework-webchat-experience-chat-launcher.d.mts",
+ "default": "./dist/botframework-webchat-experience-chat-launcher.mjs"
+ }
+ }
+ },
+ "author": "Microsoft Corporation",
+ "license": "MIT",
+ "private": true,
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/microsoft/BotFramework-WebChat.git"
+ },
+ "bugs": {
+ "url": "https://github.com/microsoft/BotFramework-WebChat/issues"
+ },
+ "files": [
+ "./dist/**/*",
+ "./src/**/*",
+ "*.js"
+ ],
+ "homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/experience-chat-launcher#readme",
+ "scripts": {
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
+ "bump": "npm run bump:prod && npm run bump:dev && npm run bump:peer && (npm audit fix || exit 0)",
+ "bump:dev": "../../scripts/npm/bump-dev.sh",
+ "bump:peer": "../../scripts/npm/bump-peer.sh",
+ "bump:prod": "../../scripts/npm/bump-prod.sh",
+ "eslint": "npm run precommit",
+ "postversion": "../../scripts/npm/postversion.sh",
+ "precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
+ "precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
+ "precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
+ "preversion": "../../scripts/npm/preversion.sh",
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../react-valibot/package.json\" \"../redux-store/package.json\" \"../styles/package.json\" \"../api/package.json\" \"../component/package.json\" \"../core/package.json\""
+ },
+ "pinDependencies": {},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-react-valibot": "development",
+ "@msinternal/botframework-webchat-redux-store": "development",
+ "@msinternal/botframework-webchat-styles": "development",
+ "botframework-webchat-api": "production",
+ "botframework-webchat-component": "production",
+ "botframework-webchat-core": "production"
+ },
+ "devDependencies": {
+ "@msinternal/botframework-webchat-react-valibot": "0.0.0-0",
+ "@msinternal/botframework-webchat-redux-store": "0.0.0-0",
+ "@msinternal/botframework-webchat-styles": "0.0.0-0",
+ "@types/node": "^22.13.4",
+ "typescript": "^5.7.3"
+ },
+ "dependencies": {
+ "botframework-webchat-api": "0.0.0-0",
+ "botframework-webchat-component": "0.0.0-0",
+ "botframework-webchat-core": "0.0.0-0",
+ "merge-refs": "2.0.0",
+ "use-ref-from": "0.1.0",
+ "valibot": "1.1.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.6"
+ }
+}
diff --git a/packages/experience-chat-launcher/src/env.d.ts b/packages/experience-chat-launcher/src/env.d.ts
new file mode 100644
index 0000000000..a8694ad586
--- /dev/null
+++ b/packages/experience-chat-launcher/src/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/packages/experience-chat-launcher/src/index.ts b/packages/experience-chat-launcher/src/index.ts
new file mode 100644
index 0000000000..26aeff895f
--- /dev/null
+++ b/packages/experience-chat-launcher/src/index.ts
@@ -0,0 +1 @@
+export { default as ChatLauncher } from './private/ChatLauncher';
diff --git a/packages/experience-chat-launcher/src/private/ChatLauncher.module.css b/packages/experience-chat-launcher/src/private/ChatLauncher.module.css
new file mode 100644
index 0000000000..763c0e63ba
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/ChatLauncher.module.css
@@ -0,0 +1,3 @@
+:global(.webchat).webchat-experience-chat-launcher {
+ display: contents;
+}
diff --git a/packages/experience-chat-launcher/src/private/ChatLauncher.tsx b/packages/experience-chat-launcher/src/private/ChatLauncher.tsx
new file mode 100644
index 0000000000..ba230092c1
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/ChatLauncher.tsx
@@ -0,0 +1,73 @@
+import { validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { reduxStoreSchema } from '@msinternal/botframework-webchat-redux-store';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import {
+ buttonComponent,
+ chatLauncherButtonComponent,
+ ChatLauncherButtonPolymiddlewareProxy,
+ createButtonPolymiddleware,
+ createChatLauncherButtonPolymiddleware,
+ createPopoverPolymiddleware,
+ popoverComponent,
+ type Polymiddleware
+} from 'botframework-webchat-api/middleware';
+import { Composer } from 'botframework-webchat-component/component';
+import { directLineJSBotConnection } from 'botframework-webchat-core/schema';
+import cx from 'classnames';
+import React, { memo, useMemo, useRef } from 'react';
+import { instance, object, optional, pipe, readonly, string, type InferInput } from 'valibot';
+
+import ChatLauncherStylesheet from '../stylesheet/ChatLauncherStylesheet';
+import styles from './ChatLauncher.module.css';
+import ChatLauncherButton from './private/ChatLauncherButton';
+import ChatLauncherPopover from './private/ChatLauncherPopover';
+import Button from './private/polymiddleware/Button';
+import NonModalPopover from './private/polymiddleware/NonModalPopover';
+
+const chatLauncherPropsSchema = pipe(
+ object({
+ directLine: directLineJSBotConnection(),
+ nonce: optional(string()),
+ store: reduxStoreSchema,
+ stylesRoot: optional(instance(Node))
+ }),
+ readonly()
+);
+
+type ChatLauncherProps = InferInput;
+
+function ChatLauncher(props: ChatLauncherProps) {
+ const { directLine, nonce, store, stylesRoot } = validateProps(chatLauncherPropsSchema, props);
+
+ const classNames = useStyles(styles);
+ const styleOptions = useMemo(() => ({ stylesRoot }), [stylesRoot]);
+ const popoverTargetRef = useRef(null);
+
+ const polymiddleware = useMemo(
+ () =>
+ Object.freeze([
+ createButtonPolymiddleware(
+ () => request => buttonComponent(Button, { appearance: request.appearance, size: request.size })
+ ),
+ createChatLauncherButtonPolymiddleware(() => () => chatLauncherButtonComponent(ChatLauncherButton)),
+ createPopoverPolymiddleware(
+ next => request => (request.type === 'nonmodal' ? popoverComponent(NonModalPopover) : next(request))
+ )
+ ]),
+ []
+ );
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+ChatLauncher.displayName = 'ChatLauncher';
+
+export default memo(ChatLauncher);
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherButton.module.css b/packages/experience-chat-launcher/src/private/private/ChatLauncherButton.module.css
new file mode 100644
index 0000000000..93805ef4d2
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherButton.module.css
@@ -0,0 +1,9 @@
+:global(.webchat-experience-chat-launcher) .chat-launcher-button {
+ /* TODO: [P*] Is this a good naming system? Sorry I forgot if we should still go CSS BEM-alike or not. */
+ --webchat-chatLauncherButton-margin: 40px;
+
+ bottom: 0;
+ position: fixed;
+ margin: var(--webchat-chatLauncherButton-margin);
+ right: 0;
+}
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherButton.tsx b/packages/experience-chat-launcher/src/private/private/ChatLauncherButton.tsx
new file mode 100644
index 0000000000..e86e609b4c
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherButton.tsx
@@ -0,0 +1,41 @@
+import { refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import { ButtonPolymiddlewareProxy } from 'botframework-webchat-api/middleware';
+import React, { memo } from 'react';
+import { boolean, object, pipe, readonly, type InferInput } from 'valibot';
+
+import styles from './ChatLauncherButton.module.css';
+import Icon from './Icon';
+
+const chatLauncherButtonPropsSchema = pipe(
+ object({
+ hasMessage: boolean(),
+ popoverTargetRef: refObject()
+ }),
+ readonly()
+);
+
+type ChatLauncherButtonProps = InferInput;
+
+// TODO: [P0] Should we make an IconButton polymiddleware and ChatLauncherButton is based from that?
+function ChatLauncherButton(props: ChatLauncherButtonProps) {
+ const { hasMessage, popoverTargetRef } = validateProps(chatLauncherButtonPropsSchema, props);
+
+ const classNames = useStyles(styles);
+
+ return (
+
+ {hasMessage ? : }
+
+ );
+}
+
+ChatLauncherButton.displayName = 'ChatLauncherButton';
+
+export default memo(ChatLauncherButton);
+export { chatLauncherButtonPropsSchema, type ChatLauncherButtonProps };
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/DismissButton.tsx b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/DismissButton.tsx
new file mode 100644
index 0000000000..35e9889944
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/DismissButton.tsx
@@ -0,0 +1,30 @@
+import { refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { ButtonPolymiddlewareProxy } from 'botframework-webchat-api/middleware';
+import React, { memo } from 'react';
+import { object, optional, pipe, readonly, type InferInput } from 'valibot';
+
+import Icon from '../Icon';
+
+const dismissButtonPropsSchema = pipe(
+ object({
+ popoverRef: optional(refObject())
+ }),
+ readonly()
+);
+
+type DismissButtonProps = InferInput;
+
+function DismissButton(props: DismissButtonProps) {
+ const { popoverRef } = validateProps(dismissButtonPropsSchema, props);
+
+ return (
+
+
+
+ );
+}
+
+DismissButton.displayName = 'ChatLauncherPopover/DismissButton';
+
+export default memo(DismissButton);
+export { dismissButtonPropsSchema, type DismissButtonProps };
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/RestartButton.tsx b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/RestartButton.tsx
new file mode 100644
index 0000000000..a802852bc1
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/RestartButton.tsx
@@ -0,0 +1,22 @@
+import { ButtonPolymiddlewareProxy } from 'botframework-webchat-api/middleware';
+import React, { memo } from 'react';
+import { object, pipe, readonly, type InferInput } from 'valibot';
+
+import Icon from '../Icon';
+
+const restartButtonPropsSchema = pipe(object({}), readonly());
+
+type RestartButtonProps = InferInput;
+
+function RestartButton(_: RestartButtonProps) {
+ return (
+
+
+
+ );
+}
+
+RestartButton.displayName = 'ChatLauncherPopover/RestartButton';
+
+export default memo(RestartButton);
+export { restartButtonPropsSchema, type RestartButtonProps };
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleBar.module.css b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleBar.module.css
new file mode 100644
index 0000000000..1837b32a4b
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleBar.module.css
@@ -0,0 +1,20 @@
+:global(.webchat-experience-chat-launcher) .chat-launcher-popover__title-bar {
+ --webchat-spacingHorizontalL: var(--spacingHorizontalL, 16px);
+ --webchat-spacingHorizontalS: var(--spacingHorizontalS, 8px);
+ --webchat-spacingVerticalM: var(--spacingVerticalM, 12px);
+ --webchat-spacingVerticalS: var(--spacingVerticalS, 8px);
+ --webchat-colorNeutralStroke3: var(--colorNeutralStroke3, #f0f0f0);
+ --webchat-strokeWidthThin: var(--strokeWidthThin, 1px);
+
+ --webchat-chatLauncherPopoverTitleBar-border-block-end-width: var(--webchat-strokeWidthThin);
+ --webchat-chatLauncherPopoverTitleBar-border-block-end-color: var(--webchat-colorNeutralStroke3);
+ --webchat-chatLauncherPopoverTitleBar-padding: var(--webchat-spacingVerticalM) var(--webchat-spacingHorizontalL);
+
+ align-items: center;
+ border-block-end-color: var(--webchat-chatLauncherPopoverTitleBar-border-block-end-color);
+ border-block-end-style: solid;
+ border-block-end-width: var(--webchat-chatLauncherPopoverTitleBar-border-block-end-width);
+ display: grid;
+ grid-template-columns: 1fr auto auto;
+ padding: var(--webchat-chatLauncherPopoverTitleBar-padding);
+}
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleBar.tsx b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleBar.tsx
new file mode 100644
index 0000000000..8a6f4cd703
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleBar.tsx
@@ -0,0 +1,37 @@
+import { refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import React, { forwardRef, memo } from 'react';
+import { object, optional, pipe, readonly, type InferInput } from 'valibot';
+
+import DismissButton from './DismissButton';
+import RestartButton from './RestartButton';
+import styles from './TitleBar.module.css';
+import TitleText from './TitleText';
+
+const titleBarPropsSchema = pipe(
+ object({
+ popoverRef: optional(refObject())
+ }),
+ readonly()
+);
+
+type TitleBarProps = InferInput;
+
+function TitleBar(props: TitleBarProps) {
+ const { popoverRef } = validateProps(titleBarPropsSchema, props);
+
+ const classNames = useStyles(styles);
+
+ return (
+
+ {'Contoso agent'}
+
+
+
+ );
+}
+
+TitleBar.displayName = 'ChatLauncherPopover/TitleBar';
+
+export default memo(forwardRef(TitleBar));
+export { titleBarPropsSchema, type TitleBarProps };
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleText.module.css b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleText.module.css
new file mode 100644
index 0000000000..01dc4f7d74
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleText.module.css
@@ -0,0 +1,27 @@
+:global(.webchat-experience-chat-launcher) .chat-launcher-popover__title-text {
+ /* TODO: [P0] Refactor variables to global or upper layer. */
+ --webchat-colorNeutralForeground1: var(--colorNeutralForeground1, #242424);
+ --webchat-fontFamilyBase: var(
+ --fontFamilyBase,
+ 'Segoe UI',
+ 'Segoe UI Web (West European)',
+ -apple-system,
+ BlinkMacSystemFont,
+ Roboto,
+ 'Helvetica Neue',
+ sans-serif
+ );
+ --webchat-fontSizeBase400: var(--fontSizeBase400, 16px);
+ --webchat-fontWeightSemibold: var(--fontWeightSemibold, 600);
+
+ /* TODO: [P*] Is this a good naming system? Sorry I forgot if we should still go CSS BEM-alike or not. */
+ --webchat-chatLauncherPopoverTitleText-color: var(--webchat-colorNeutralForeground1);
+ --webchat-chatLauncherPopoverTitleText-fontFamily: var(--webchat-fontFamilyBase);
+ --webchat-chatLauncherPopoverTitleText-fontSize: var(--webchat-fontSizeBase400);
+ --webchat-chatLauncherPopoverTitleText-fontWeight: var(--webchat-fontWeightSemibold);
+
+ color: var(--webchat-chatLauncherPopoverTitleText-color);
+ font-family: var(--webchat-chatLauncherPopoverTitleText-fontFamily);
+ font-size: var(--webchat-chatLauncherPopoverTitleText-fontSize);
+ font-weight: var(--webchat-chatLauncherPopoverTitleText-fontWeight);
+}
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleText.tsx b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleText.tsx
new file mode 100644
index 0000000000..db51d262c5
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/TitleText.tsx
@@ -0,0 +1,28 @@
+import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import React, { memo } from 'react';
+import { object, optional, pipe, readonly, type InferInput } from 'valibot';
+
+import styles from './TitleText.module.css';
+
+const titleTextPropsSchema = pipe(
+ object({
+ children: optional(reactNode())
+ }),
+ readonly()
+);
+
+type TitleTextProps = InferInput;
+
+function TitleText(props: TitleTextProps) {
+ const { children } = validateProps(titleTextPropsSchema, props);
+
+ const classNames = useStyles(styles);
+
+ return {children}
;
+}
+
+TitleText.displayName = 'ChatLauncherPopover/TitleText';
+
+export default memo(TitleText);
+export { titleTextPropsSchema, type TitleTextProps };
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/index.module.css b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/index.module.css
new file mode 100644
index 0000000000..8bbdb9297a
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/index.module.css
@@ -0,0 +1,19 @@
+:global(.webchat-experience-chat-launcher) .chat-launcher-popover {
+ --webchat-spacingHorizontalSNudge: var(--spacingHorizontalSNudge, 6px);
+ --webchat-spacingVerticalMNudge: var(--spacingVerticalMNudge, 10px);
+ --webchat-spacingVerticalSNudge: var(--spacingVerticalSNudge, 6px);
+}
+
+:global(.webchat-experience-chat-launcher) .chat-launcher-popover__box {
+ display: grid;
+ grid-template-rows: auto 1fr;
+ height: 100%;
+ overflow: hidden;
+ width: 100%;
+}
+
+:global(.webchat-experience-chat-launcher) .chat-launcher-popover .chat-launcher-popover__webchat {
+ box-sizing: border-box;
+ overflow: hidden;
+ padding: 0 var(--webchat-spacingHorizontalSNudge) var(--webchat-spacingVerticalMNudge);
+}
diff --git a/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/index.tsx b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/index.tsx
new file mode 100644
index 0000000000..03921d717f
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/ChatLauncherPopover/index.tsx
@@ -0,0 +1,39 @@
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import { PopoverPolymiddlewareProxy } from 'botframework-webchat-api/middleware';
+import { BasicWebChat } from 'botframework-webchat-component/component';
+import mergeRefs from 'merge-refs';
+import React, { forwardRef, memo, useRef, type ForwardedRef } from 'react';
+import { object, pipe, readonly, type InferInput } from 'valibot';
+
+import TitleBar from './TitleBar';
+import styles from './index.module.css';
+
+const chatLauncherPopoverPropsSchema = pipe(object({}), readonly());
+
+type ChatLauncherPopoverProps = InferInput;
+
+function ChatLauncherPopover(_: ChatLauncherPopoverProps, ref: ForwardedRef) {
+ const popoverRef = useRef(null);
+
+ const classNames = useStyles(styles);
+
+ return (
+ // TODO: [P2] Is it correct to force-cast ref to HTMLDivElement?
+
+
+
+
+
+
+ );
+}
+
+ChatLauncherPopover.displayName = 'ChatLauncherPopover';
+
+export default memo(forwardRef(ChatLauncherPopover));
+export { chatLauncherPopoverPropsSchema, type ChatLauncherPopoverProps };
diff --git a/packages/experience-chat-launcher/src/private/private/Icon.module.css b/packages/experience-chat-launcher/src/private/private/Icon.module.css
new file mode 100644
index 0000000000..a86bca41d9
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/Icon.module.css
@@ -0,0 +1,70 @@
+/* TODO: [P0] Dupe from packages/fluent-theme/src/components/icon/FluentIcon.module.css, should dedupe. */
+:global(.webchat-experience-chat-launcher) .icon {
+ min-width: var(--webchat__icon--size, 1em);
+ min-height: var(--webchat__icon--size, 1em);
+ place-self: center;
+
+ /* Use the image as texture. */
+ background-image: var(--webchat__icon--image, none);
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: var(--webchat__icon--size, 1em);
+
+ /* If image is not set, fallback to solid color. */
+ background-color: var(--webchat__icon--color, transparent);
+
+ /* 3. Set the mask if any. */
+ -webkit-mask-image: var(--webchat__icon--mask);
+ -webkit-mask-position: center;
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: var(--webchat__icon--size, 1em);
+ mask-image: var(--webchat__icon--mask);
+ mask-position: center;
+ mask-repeat: no-repeat;
+ mask-size: var(--webchat__icon--size, 1em);
+}
+
+/* #region: Appearance */
+:global(.webchat) .appearance--hero {
+ --webchat__icon--color: currentColor;
+ --webchat__icon--size: 32px;
+}
+
+:global(.webchat) .appearance--button {
+ --webchat__icon--color: currentColor;
+ --webchat__icon--size: 20px;
+}
+
+:global(.webchat) .appearance--text {
+ --webchat__icon--color: currentColor;
+}
+/* #endregion */
+
+/* #region: Icons */
+:global(.webchat) .icon--chat-multiple {
+ --webchat__icon--mask: url('data:image/svg+xml;utf8,');
+}
+
+/* TODO: [P0] This is ugly way to show a different (filled) icon when its parent is hovered. */
+:global(.webchat button:is(:focus, :hover)) .icon--chat-multiple {
+ --webchat__icon--mask: url('data:image/svg+xml;utf8,');
+}
+
+:global(.webchat) .icon--chat-sparkle {
+ --webchat__icon--mask: url('data:image/svg+xml;utf8,');
+}
+
+/* TODO: [P0] This is ugly way to show a different (filled) icon when its parent is hovered. */
+:global(.webchat button:is(:focus, :hover)) .icon--chat-sparkle {
+ --webchat__icon--mask: url('data:image/svg+xml;utf8,');
+}
+
+:global(.webchat) .icon--dismiss {
+ --webchat__icon--mask: url('data:image/svg+xml;utf8,');
+}
+
+:global(.webchat) .icon--arrow-clockwise {
+ --webchat__icon--mask: url('data:image/svg+xml;utf8,');
+}
+
+/* #endregion */
diff --git a/packages/experience-chat-launcher/src/private/private/Icon.tsx b/packages/experience-chat-launcher/src/private/private/Icon.tsx
new file mode 100644
index 0000000000..54e553816f
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/Icon.tsx
@@ -0,0 +1,42 @@
+/* TODO: [P0] Dupe from packages/fluent-theme/src/components/icon/FluentIcon.tsx, should dedupe. */
+import { validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import { createIconComponent } from 'botframework-webchat-component/internal';
+import cx from 'classnames';
+import React, { memo, useMemo, type CSSProperties } from 'react';
+import { object, optional, pipe, readonly, string, union, type InferInput } from 'valibot';
+
+import styles from './Icon.module.css';
+
+const baseIconPropsSchema = pipe(
+ object({
+ 'aria-label': optional(string()),
+ className: optional(string()),
+ mask: optional(string())
+ }),
+ readonly()
+);
+
+function BaseIcon(props: InferInput) {
+ const { 'aria-label': ariaLabel, className, mask } = validateProps(baseIconPropsSchema, props);
+
+ const classNames = useStyles(styles);
+
+ const maskStyle = useMemo(
+ () => (mask ? ({ '--webchat__icon--mask': `url(${JSON.stringify(mask)})` } as CSSProperties) : {}),
+ [mask]
+ );
+
+ return ;
+}
+
+const { component: Icon, modifierPropsSchema } = createIconComponent(styles, ['appearance', 'icon'], BaseIcon);
+
+Icon.displayName = 'Icon';
+
+const iconPropsSchema = pipe(union([baseIconPropsSchema, modifierPropsSchema]), readonly());
+
+type IconProps = InferInput;
+
+export default memo(Icon);
+export { iconPropsSchema, type IconProps };
diff --git a/packages/experience-chat-launcher/src/private/private/polymiddleware/Button.module.css b/packages/experience-chat-launcher/src/private/private/polymiddleware/Button.module.css
new file mode 100644
index 0000000000..57749bcfb0
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/polymiddleware/Button.module.css
@@ -0,0 +1,67 @@
+/* TODO: [P0] Put this inside botframework-webchat-component as default implementation. */
+:global(.webchat-experience-chat-launcher) .button {
+ /* TODO: [P0] Expose some CSS classes to white-label. */
+ --webchat-borderRadiusMedium: var(--borderRadiusMedium, 4px);
+ --webchat-colorNeutralBackground1: var(--colorNeutralBackground1, #ffffff);
+ --webchat-colorNeutralBackground1Hover: var(--colorNeutralBackground1Hover, #f5f5f5);
+ --webchat-colorNeutralBackground1Pressed: var(--colorNeutralBackground1Pressed, #e0e0e0);
+ --webchat-colorNeutralBackground1Selected: var(--colorNeutralBackground1Selected, #ebebeb);
+ --webchat-colorNeutralForeground1: var(--colorNeutralForeground1, #242424);
+ --webchat-colorNeutralStroke1: var(--colorNeutralStroke1, #d1d1d1);
+ --webchat-colorNeutralStroke1Hover: var(--colorNeutralStroke1Hover, #c7c7c7);
+ --webchat-colorNeutralStroke1Pressed: var(--colorNeutralStroke1Pressed, #b3b3b3);
+ --webchat-colorNeutralStrokeDisabled: var(--colorNeutralStrokeDisabled, #e0e0e0);
+ --webchat-shadow8: var(--shadow8, 0 0 2px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(0, 0, 0, 0.14));
+
+ /* TODO: [P*] Is this a good naming system? Sorry I forgot if we should still go CSS BEM-alike or not. */
+ /* TODO: [P0] Should we expose some customizable CSS variables? */
+ /* TODO: [P0] Should it be customizable to anchor to bottom/left instead? */
+ --webchat-button-background: var(--webchat-colorNeutralBackground1);
+ --webchat-button-borderColor: var(--webchat-colorNeutralStroke1);
+ --webchat-button-borderColor--active: var(--webchat-colorNeutralStroke1Pressed);
+ --webchat-button-borderColor--hover: var(--webchat-colorNeutralStroke1Hover);
+ --webchat-button-borderColor--disabled: var(--webchat-colorNeutralStrokeDisabled);
+ --webchat-button-borderRadius: var(--webchat-borderRadiusMedium);
+ --webchat-button-borderWidth: 0px;
+ --webchat-button-color: var(--webchat-colorNeutralForeground1);
+ --webchat-button-shadow: 0;
+ --webchat-button-size: 32px;
+
+ appearance: none;
+ background: var(--webchat-button-background);
+ border-color: var(--webchat-button-borderColor);
+ border-radius: var(--webchat-button-borderRadius);
+ border-style: solid;
+ border-width: var(--webchat-button-borderWidth);
+ box-shadow: var(--webchat-button-shadow);
+ color: var(--webchat-button-color);
+ height: var(--webchat-button-size);
+ min-width: var(--webchat-button-size);
+ padding: 0;
+}
+
+:global(.webchat-experience-chat-launcher) .button:hover {
+ --webchat-button-background: var(--webchat-colorNeutralBackground1Hover);
+ --webchat-button-borderColor: var(--webchat-button-borderColor--hover);
+}
+
+:global(.webchat-experience-chat-launcher) .button:active {
+ --webchat-button-background: var(--webchat-colorNeutralBackground1Pressed);
+ --webchat-button-borderColor: var(--webchat-button-borderColor--active);
+}
+
+:global(.webchat-experience-chat-launcher) .button:disabled {
+ --webchat-button-background: var(--webchat-colorNeutralBackground1Pressed);
+ --webchat-button-borderColor: var(--webchat-button-borderColor--disabled);
+}
+
+:global(.webchat-experience-chat-launcher) .button.button--appearance-elevated {
+ /* We think elevated button is perfectly round, while others has rounded corners. */
+ --webchat-button-borderRadius: var(--webchat-button-size);
+ --webchat-button-borderWidth: 1px;
+ --webchat-button-shadow: var(--webchat-shadow8);
+}
+
+:global(.webchat-experience-chat-launcher) .button.button--size-hero {
+ --webchat-button-size: 60px;
+}
diff --git a/packages/experience-chat-launcher/src/private/private/polymiddleware/Button.tsx b/packages/experience-chat-launcher/src/private/private/polymiddleware/Button.tsx
new file mode 100644
index 0000000000..1e058ee17c
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/polymiddleware/Button.tsx
@@ -0,0 +1,74 @@
+import { forwardedRef, reactNode, refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import cx from 'classnames';
+import React, { memo, useCallback, useEffect, useRef } from 'react';
+import { useRefFrom } from 'use-ref-from';
+import { function_, object, optional, picklist, pipe, readonly, string, type InferInput } from 'valibot';
+
+import styles from './Button.module.css';
+
+const buttonPropsSchema = pipe(
+ object({
+ appearance: optional(picklist(['flat', 'elevated'])),
+ children: optional(reactNode()),
+ className: optional(string()),
+ forwardedRef: optional(forwardedRef()),
+ onClick: optional(function_()),
+ popoverTargetAction: optional(picklist(['hide', 'show', 'toggle'])),
+ popoverTargetRef: optional(refObject()),
+ size: optional(picklist(['hero', 'normal']))
+ }),
+ readonly()
+);
+
+type ButtonProps = InferInput;
+
+function Button(props: ButtonProps) {
+ const { appearance, children, className, onClick, popoverTargetAction, popoverTargetRef, size } = validateProps(
+ buttonPropsSchema,
+ props
+ );
+ const classNames = useStyles(styles);
+
+ const onClickRef = useRefFrom(onClick);
+ const ref = useRef(null);
+
+ const handleClick = useCallback(() => onClickRef.current?.(), [onClickRef]);
+
+ useEffect(() => {
+ if (ref.current) {
+ if (popoverTargetAction) {
+ ref.current.popoverTargetAction = popoverTargetAction;
+ } else {
+ ref.current.removeAttribute('popovertargetaction');
+ }
+
+ ref.current.popoverTargetElement = popoverTargetRef?.current || null;
+ }
+ }, [popoverTargetAction, popoverTargetRef, ref]);
+
+ return (
+
+ );
+}
+
+Button.displayName = 'Button';
+
+export default memo(Button);
+export { buttonPropsSchema, type ButtonProps };
diff --git a/packages/experience-chat-launcher/src/private/private/polymiddleware/NonModalPopover.module.css b/packages/experience-chat-launcher/src/private/private/polymiddleware/NonModalPopover.module.css
new file mode 100644
index 0000000000..7ac39bb18b
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/polymiddleware/NonModalPopover.module.css
@@ -0,0 +1,20 @@
+:global(.webchat-experience-chat-launcher) .popover--non-modal {
+ /* TODO: [P0] Refactor variables to global or upper layer. */
+ --webchat-colorNeutralBackground1: var(--colorNeutralBackground1, #ffffff);
+ --webchat-shadow64: var(--shadow64, 0 0 8px rgba(0, 0, 0, 0.12), 0 32px 64px rgba(0, 0, 0, 0.14));
+
+ /* TODO: [P*] Is this a good naming system? Sorry I forgot if we should still go CSS BEM-alike or not. */
+ --webchat-popover-background: var(--webchat-colorNeutralBackground1);
+ --webchat-popover-box-shadow: var(--webchat-shadow64);
+ --webchat-popover-border-radius: 20px;
+ --webchat-popover-height: 610px;
+ --webchat-popover-width: 340px;
+
+ background: var(--webchat-popover-background);
+ border: 0;
+ border-radius: var(--webchat-popover-border-radius);
+ box-shadow: var(--webchat-popover-box-shadow);
+ height: var(--webchat-popover-height);
+ padding: 0;
+ width: var(--webchat-popover-width);
+}
diff --git a/packages/experience-chat-launcher/src/private/private/polymiddleware/NonModalPopover.tsx b/packages/experience-chat-launcher/src/private/private/polymiddleware/NonModalPopover.tsx
new file mode 100644
index 0000000000..3a3934aca5
--- /dev/null
+++ b/packages/experience-chat-launcher/src/private/private/polymiddleware/NonModalPopover.tsx
@@ -0,0 +1,49 @@
+import { forwardedRef, reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { useStyles } from '@msinternal/botframework-webchat-styles/react';
+import cx from 'classnames';
+import mergeRefs from 'merge-refs';
+import React, { memo, useEffect, useRef } from 'react';
+import { object, optional, picklist, pipe, readonly, string, type InferInput } from 'valibot';
+
+import styles from './NonModalPopover.module.css';
+
+const popoverPropsSchema = pipe(
+ object({
+ children: optional(reactNode()),
+ className: optional(string()),
+ forwardedRef: optional(forwardedRef()),
+ popover: optional(picklist(['auto', 'hint', 'manual']))
+ }),
+ readonly()
+);
+
+type PopoverProps = InferInput;
+
+function Popover(props: PopoverProps) {
+ const { className, children, forwardedRef, popover } = validateProps(popoverPropsSchema, props);
+
+ const ref = useRef(null);
+
+ const classNames = useStyles(styles);
+
+ // React 16.8.6 does not support "popover" prop yet.
+ useEffect(() => {
+ ref &&
+ typeof ref === 'object' &&
+ 'current' in ref &&
+ ref.current &&
+ ref.current.setAttribute('popover', popover || '');
+ }, [popover, ref]);
+
+ return (
+ // TODO: [P2] Is it correct to force-cast ref to HTMLDivElement?
+
+ {children}
+
+ );
+}
+
+Popover.displayName = 'Popover';
+
+export default memo(Popover);
+export { popoverPropsSchema, type PopoverProps };
diff --git a/packages/experience-chat-launcher/src/stylesheet/ChatLauncherStylesheet.tsx b/packages/experience-chat-launcher/src/stylesheet/ChatLauncherStylesheet.tsx
new file mode 100644
index 0000000000..a894609ac3
--- /dev/null
+++ b/packages/experience-chat-launcher/src/stylesheet/ChatLauncherStylesheet.tsx
@@ -0,0 +1,33 @@
+// TODO: [P2] This component can be replaced by `bindProps`.
+import { validateProps } from '@msinternal/botframework-webchat-react-valibot';
+import { InjectStyleElements } from '@msinternal/botframework-webchat-styles/react';
+import { useStyleOptions } from 'botframework-webchat-api/hook';
+import React, { memo, type FunctionComponent } from 'react';
+import { never, object, optional, pipe, readonly, string, undefinedable, type InferInput } from 'valibot';
+
+import createChatLauncherStyleElements from './createChatLauncherStyleElements';
+
+const componentStylesheetPropsSchema = pipe(
+ object({
+ children: optional(never()),
+ nonce: undefinedable(string())
+ }),
+ readonly()
+);
+
+type ComponentStylesheetProps = InferInput;
+
+const styleElements = createChatLauncherStyleElements('experience-chat-launcher');
+
+function ChatLauncherStylesheet(props: ComponentStylesheetProps) {
+ const { nonce } = validateProps(componentStylesheetPropsSchema, props);
+
+ const [{ stylesRoot }] = useStyleOptions();
+
+ return ;
+}
+
+ChatLauncherStylesheet.displayName = 'ChatLauncherStylesheet';
+
+export default memo(ChatLauncherStylesheet as FunctionComponent);
+export { componentStylesheetPropsSchema, type ComponentStylesheetProps };
diff --git a/packages/experience-chat-launcher/src/stylesheet/createChatLauncherStyleElements.ts b/packages/experience-chat-launcher/src/stylesheet/createChatLauncherStyleElements.ts
new file mode 100644
index 0000000000..6d1acf99f6
--- /dev/null
+++ b/packages/experience-chat-launcher/src/stylesheet/createChatLauncherStyleElements.ts
@@ -0,0 +1,8 @@
+import { makeCreateStyles } from '@msinternal/botframework-webchat-styles';
+
+const chatLauncherStyleContent = '@--CHAT-LAUNCHER-STYLES-CONTENT--@';
+
+const createChatLauncherStyleElements = makeCreateStyles(chatLauncherStyleContent);
+
+export default createChatLauncherStyleElements;
+export { chatLauncherStyleContent };
diff --git a/packages/experience-chat-launcher/src/tsconfig.json b/packages/experience-chat-launcher/src/tsconfig.json
new file mode 100644
index 0000000000..e6a6f30a92
--- /dev/null
+++ b/packages/experience-chat-launcher/src/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "extends": [
+ "@msinternal/botframework-webchat-tsconfig/current",
+ "@msinternal/botframework-webchat-tsconfig/features/cssModules"
+ ]
+}
diff --git a/packages/experience-chat-launcher/tsup.config.ts b/packages/experience-chat-launcher/tsup.config.ts
new file mode 100644
index 0000000000..7d12dc2106
--- /dev/null
+++ b/packages/experience-chat-launcher/tsup.config.ts
@@ -0,0 +1,54 @@
+import { injectCSSPlugin } from '@msinternal/botframework-webchat-styles/build';
+import { type Plugin } from 'esbuild';
+import { defineConfig } from 'tsup';
+
+import { applyConfig } from '../../tsup.base.config';
+import { chatLauncherStyleContent as chatLauncherStyleContentPlaceholder } from './src/stylesheet/createChatLauncherStyleElements';
+
+// eslint-disable-next-line no-unused-vars
+const isomorphicReactPlugin: Plugin = {
+ name: 'isomorphic-react',
+ setup(build) {
+ // eslint-disable-next-line require-unicode-regexp
+ build.onResolve({ filter: /^(react|react-dom)$/, namespace: 'file' }, ({ path }) => ({
+ namespace: 'isomorphic-react',
+ path
+ }));
+
+ // eslint-disable-next-line require-unicode-regexp
+ build.onLoad({ filter: /^react$/, namespace: 'isomorphic-react' }, () => ({
+ contents: "import React from 'react'; module.exports = globalThis.React || React;"
+ }));
+
+ // eslint-disable-next-line require-unicode-regexp
+ build.onLoad({ filter: /^react-dom$/, namespace: 'isomorphic-react' }, () => ({
+ contents: "import ReactDOM from 'react-dom'; module.exports = globalThis.ReactDOM || ReactDOM;"
+ }));
+ }
+};
+
+const commonConfig = applyConfig(config => ({
+ ...config,
+ entry: {
+ 'botframework-webchat-experience-chat-launcher': './src/index.ts'
+ },
+ external: ['botframework-webchat-component', 'react', 'react-dom'],
+ esbuildPlugins: [
+ ...config.esbuildPlugins,
+ isomorphicReactPlugin,
+ injectCSSPlugin({ stylesPlaceholder: chatLauncherStyleContentPlaceholder })
+ ]
+}));
+
+export default defineConfig([
+ {
+ ...commonConfig,
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
+ },
+ {
+ ...commonConfig,
+ format: 'cjs',
+ target: [...commonConfig.target, 'es2019']
+ }
+]);
diff --git a/packages/fluent-theme/.gitignore b/packages/fluent-theme/.gitignore
index d412f912e3..7f3c011f4b 100644
--- a/packages/fluent-theme/.gitignore
+++ b/packages/fluent-theme/.gitignore
@@ -1,6 +1,5 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/static/
/tsup.config.bundled_*.mjs
diff --git a/packages/fluent-theme/package.json b/packages/fluent-theme/package.json
index 056d1f4de3..41c24292a9 100644
--- a/packages/fluent-theme/package.json
+++ b/packages/fluent-theme/package.json
@@ -40,13 +40,18 @@
"static/**/*"
],
"scripts": {
- "build": "npm run build:static && npm run build:tsup && npm run build:dtsroll && npm run build:validate",
- "build:dtsroll": "dtsroll ./dist/*.d.*",
- "build:static": "node ./esbuild.static.mjs",
- "build:tsup": "tsup",
- "build:validate": "npm run build:validate:css && npm run build:validate:dts",
- "build:validate:css": "grep -q -P '\\.webchat-fluent \\.w([a-zA-Z-]){6}_' dist/*.css 2>/dev/null || { echo \"Error: dist/*.css is not compiled by Lightning CSS\" >&2; exit 1; }",
- "build:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:post": "npm run build:post:dtsroll && npm run build:post:validate",
+ "build:post:dtsroll": "dtsroll ./dist/*.d.*",
+ "build:post:validate": "npm run build:post:validate:css && npm run build:post:validate:dts",
+ "build:post:validate:css": "grep -q -P '\\.webchat-fluent \\.w([a-zA-Z-]){6}_' dist/*.css 2>/dev/null || { echo \"Error: dist/*.css is not compiled by Lightning CSS\" >&2; exit 1; }",
+ "build:post:validate:dts": "if grep -q -P '@msinternal\\/' dist/*.d.* 2>/dev/null; then echo \"Error: dist/*.d.* is not compiled by dtsroll\" >&2; exit 1; fi",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "concurrently --prefix-colors \"auto\" \"npm:build:run:*\"",
+ "build:run:static": "node ./esbuild.static.mjs",
+ "build:run:tsup": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -56,14 +61,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "cross-env NODE_OPTIONS=--no-deprecation concurrently --kill-others --prefix-colors \"auto\" \"npm:start:*\"",
- "start:static": "npm run build:static -- --watch",
- "start:tsup": "npm run build:tsup -- --watch"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-styles": "development",
- "@msinternal/botframework-webchat-tsconfig": "development",
- "botframework-webchat": "production"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../styles/package.json\" \"../tsconfig/package.json\" \"../bundle/package.json\""
},
"pinDependencies": {
"@types/react": [
@@ -75,11 +73,17 @@
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-styles": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development",
+ "botframework-webchat": "production"
+ },
"devDependencies": {
"@msinternal/botframework-webchat-styles": "0.0.0-0",
"@msinternal/botframework-webchat-tsconfig": "0.0.0-0",
"@types/math-random": "^1.0.2",
"@types/node": "^24.1.0",
+ "concurrently": "^9.2.0",
"tsup": "^8.5.0",
"typescript": "~5.8.3"
},
diff --git a/packages/fluent-theme/src/components/theme/Theme.module.css b/packages/fluent-theme/src/components/theme/Theme.module.css
index 25f1979a5a..1fa15fae83 100644
--- a/packages/fluent-theme/src/components/theme/Theme.module.css
+++ b/packages/fluent-theme/src/components/theme/Theme.module.css
@@ -19,6 +19,7 @@
--webchat-colorNeutralBackground1: var(--colorNeutralBackground1, #ffffff);
--webchat-colorNeutralBackground1Hover: var(--colorNeutralBackground1Hover, #f5f5f5);
--webchat-colorNeutralBackground1Pressed: var(--colorNeutralBackground1Pressed, #e0e0e0);
+ --webchat-colorNeutralBackground1Selected: var(--colorNeutralBackground1Selected, #ebebeb);
--webchat-colorNeutralBackground3: var(--colorNeutralBackground3, #f5f5f5);
--webchat-colorNeutralBackground4: var(--colorNeutralBackground4, #f0f0f0);
--webchat-colorNeutralBackground5: var(--colorNeutralBackground5, #ebebeb);
@@ -81,6 +82,7 @@
/* https://github.com/microsoft/fluentui/blob/master/packages/tokens/src/utils/shadows.ts */
--webchat-shadow2: var(--shadow2, 0 0 2px rgba(0, 0, 0, 12%), 0 1px 2px rgba(0, 0, 0, 14%));
--webchat-shadow4: var(--shadow4, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.14));
+ --webchat-shadow8: var(--shadow8, 0 0 2px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(0, 0, 0, 0.14));
--webchat-shadow16: var(--shadow16, 0 6.4px 14.4px 0 rgba(0, 0, 0, 0.132), 0 1.2px 3.6px 0 rgba(0, 0, 0, 0.108));
--webchat-shadow64: var(--shadow64, 0 0 8px rgba(0, 0, 0, 0.12), 0 32px 64px rgba(0, 0, 0, 0.14));
diff --git a/packages/fluent-theme/tsup.config.ts b/packages/fluent-theme/tsup.config.ts
index 39ef2f430a..2786f66cee 100644
--- a/packages/fluent-theme/tsup.config.ts
+++ b/packages/fluent-theme/tsup.config.ts
@@ -73,7 +73,8 @@ export default defineConfig([
...(config.esbuildPlugins ?? []),
injectCSSPlugin({ stylesPlaceholder: fluentStyleContentPlaceholder })
],
- format: ['esm']
+ format: ['esm'],
+ onSuccess: 'touch ./package.json'
})),
applyConfig(config => ({
...config,
diff --git a/packages/isomorphic-react-dom/package.json b/packages/isomorphic-react-dom/package.json
index a6f23cffe0..defaa70823 100644
--- a/packages/isomorphic-react-dom/package.json
+++ b/packages/isomorphic-react-dom/package.json
@@ -5,9 +5,12 @@
"main": "dist/react-dom.js",
"private": true,
"scripts": {
- "build": "npm run build:babel && npm run build:webpack",
- "build:babel": "babel src --out-dir lib --verbose",
- "build:webpack": "webpack-cli",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:run": "npm run build:run:babel && npm run build:run:webpack && touch ./package.json",
+ "build:run:babel": "babel src --out-dir lib --verbose",
+ "build:run:webpack": "webpack-cli",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -19,8 +22,8 @@
},
"author": "Microsoft Corporation",
"license": "MIT",
- "localDependencies": {},
"pinDependencies": {},
+ "localDependencies": {},
"devDependencies": {
"@babel/cli": "^7.28.0",
"@babel/core": "^7.28.0",
diff --git a/packages/isomorphic-react/package.json b/packages/isomorphic-react/package.json
index f7acce60d8..04b4562619 100644
--- a/packages/isomorphic-react/package.json
+++ b/packages/isomorphic-react/package.json
@@ -5,9 +5,12 @@
"main": "dist/react.js",
"private": true,
"scripts": {
- "build": "npm run build:babel && npm run build:webpack",
- "build:babel": "babel src --out-dir lib --verbose",
- "build:webpack": "webpack-cli",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:run": "npm run build:run:babel && npm run build:run:webpack && touch ./package.json",
+ "build:run:babel": "babel src --out-dir lib --verbose",
+ "build:run:webpack": "webpack-cli",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -19,8 +22,8 @@
},
"author": "Microsoft Corporation",
"license": "MIT",
- "localDependencies": {},
"pinDependencies": {},
+ "localDependencies": {},
"devDependencies": {
"@babel/cli": "^7.28.0",
"@babel/core": "^7.28.0",
diff --git a/packages/react-hooks/.gitignore b/packages/react-hooks/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/react-hooks/.gitignore
+++ b/packages/react-hooks/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/react-hooks/package.json b/packages/react-hooks/package.json
index b3b4710f55..fcc3a915eb 100644
--- a/packages/react-hooks/package.json
+++ b/packages/react-hooks/package.json
@@ -35,10 +35,13 @@
"./src/**/*",
"*.js"
],
- "localDependencies": {},
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/react-hooks#readme",
"scripts": {
- "build": "tsup --config ./tsup.config.ts",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -48,9 +51,10 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\""
},
"peerDependencies": {
"react": ">= 16.8.6"
- }
+ },
+ "localDependencies": {}
}
diff --git a/packages/react-hooks/tsup.config.ts b/packages/react-hooks/tsup.config.ts
index cd7a9b44f8..f7b5e83bce 100644
--- a/packages/react-hooks/tsup.config.ts
+++ b/packages/react-hooks/tsup.config.ts
@@ -2,21 +2,18 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['api/src/index.ts', 'api-middleware/src/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-react-hooks': './src/index.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
{
...commonConfig,
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/react-valibot/.gitignore b/packages/react-valibot/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/react-valibot/.gitignore
+++ b/packages/react-valibot/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/react-valibot/package.json b/packages/react-valibot/package.json
index 4d85aad21f..da2dfa3f52 100644
--- a/packages/react-valibot/package.json
+++ b/packages/react-valibot/package.json
@@ -32,7 +32,11 @@
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/react-valibot#readme",
"private": true,
"scripts": {
- "build": "tsup",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -42,10 +46,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-tsconfig": "development"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../tsconfig/package.json\""
},
"pinDependencies": {
"@types/react": [
@@ -56,6 +57,9 @@
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-tsconfig": "development"
+ },
"devDependencies": {
"@msinternal/botframework-webchat-tsconfig": "^0.0.0-0",
"@types/jest": "^30.0.0",
diff --git a/packages/react-valibot/src/forwardedRef.ts b/packages/react-valibot/src/forwardedRef.ts
new file mode 100644
index 0000000000..1f9c90a4f7
--- /dev/null
+++ b/packages/react-valibot/src/forwardedRef.ts
@@ -0,0 +1,28 @@
+import { type ForwardedRef } from 'react';
+import { custom, nullable, safeParse, union, type CustomIssue, type CustomSchema, type ErrorMessage } from 'valibot';
+
+import mutableRefObject from './mutableRefObject';
+import refCallback from './refCallback';
+
+const forwardedRefSchema = nullable(union([refCallback(), mutableRefObject()]));
+
+function forwardedRef(): CustomSchema, undefined>;
+function forwardedRef(): CustomSchema, undefined>;
+
+function forwardedRef<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message: TMessage): CustomSchema, TMessage>;
+
+function forwardedRef<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema, TMessage> {
+ return custom, TMessage>(
+ value => safeParse(forwardedRefSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default forwardedRef;
diff --git a/packages/react-valibot/src/index.ts b/packages/react-valibot/src/index.ts
index d1e6fe3bb5..4e15bbea37 100644
--- a/packages/react-valibot/src/index.ts
+++ b/packages/react-valibot/src/index.ts
@@ -1,2 +1,7 @@
+export { default as forwardedRef } from './forwardedRef';
+export { default as mutableRefObject } from './mutableRefObject';
export { default as reactNode } from './reactNode';
+export { default as ref } from './ref';
+export { default as refCallback } from './refCallback';
+export { default as refObject } from './refObject';
export { default as validateProps } from './validateProps';
diff --git a/packages/react-valibot/src/mutableRefObject.ts b/packages/react-valibot/src/mutableRefObject.ts
new file mode 100644
index 0000000000..efc2e625c3
--- /dev/null
+++ b/packages/react-valibot/src/mutableRefObject.ts
@@ -0,0 +1,25 @@
+import { type RefObject } from 'react';
+import { any, custom, object, safeParse, type CustomIssue, type CustomSchema, type ErrorMessage } from 'valibot';
+
+const mutableRefObjectSchema = object({ current: any() });
+
+function mutableRefObject(): CustomSchema, undefined>;
+function mutableRefObject(): CustomSchema, undefined>;
+
+function mutableRefObject<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message: TMessage): CustomSchema, TMessage>;
+
+function mutableRefObject<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema, TMessage> {
+ return custom, TMessage>(
+ value => safeParse(mutableRefObjectSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default mutableRefObject;
diff --git a/packages/react-valibot/src/ref.ts b/packages/react-valibot/src/ref.ts
new file mode 100644
index 0000000000..ed4db72581
--- /dev/null
+++ b/packages/react-valibot/src/ref.ts
@@ -0,0 +1,26 @@
+import { type Ref } from 'react';
+import { custom, nullable, safeParse, union, type CustomIssue, type CustomSchema, type ErrorMessage } from 'valibot';
+
+import refCallback from './refCallback';
+import refObject from './refObject';
+
+const refSchema = nullable(union([refCallback(), refObject()]));
+
+function ref(): CustomSchema[, undefined>;
+function ref(): CustomSchema][, undefined>;
+
+function ref | undefined = ErrorMessage | undefined>(
+ message: TMessage
+): CustomSchema][, TMessage>;
+
+function ref | undefined = ErrorMessage | undefined>(
+ message?: TMessage
+): CustomSchema][, TMessage> {
+ return custom][, TMessage>(
+ value => safeParse(refSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default ref;
diff --git a/packages/react-valibot/src/refCallback.ts b/packages/react-valibot/src/refCallback.ts
new file mode 100644
index 0000000000..7e0a2192b7
--- /dev/null
+++ b/packages/react-valibot/src/refCallback.ts
@@ -0,0 +1,25 @@
+import { type RefCallback } from 'react';
+import { custom, safeParse, type CustomIssue, type CustomSchema, type ErrorMessage } from 'valibot';
+
+const refCallbackSchema = custom<(current: any) => void>(value => typeof value === 'function');
+
+function refCallback(): CustomSchema, undefined>;
+function refCallback(): CustomSchema, undefined>;
+
+function refCallback<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message: TMessage): CustomSchema, TMessage>;
+
+function refCallback<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema, TMessage> {
+ return custom, TMessage>(
+ value => safeParse(refCallbackSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default refCallback;
diff --git a/packages/react-valibot/src/refObject.ts b/packages/react-valibot/src/refObject.ts
new file mode 100644
index 0000000000..e9394568d4
--- /dev/null
+++ b/packages/react-valibot/src/refObject.ts
@@ -0,0 +1,35 @@
+import { type RefObject } from 'react';
+import {
+ any,
+ custom,
+ object,
+ pipe,
+ readonly,
+ safeParse,
+ type CustomIssue,
+ type CustomSchema,
+ type ErrorMessage
+} from 'valibot';
+
+const refObjectSchema = pipe(object({ current: any() }), readonly());
+
+function refObject(): CustomSchema, undefined>;
+function refObject(): CustomSchema, undefined>;
+
+function refObject<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message: TMessage): CustomSchema, TMessage>;
+
+function refObject<
+ T,
+ const TMessage extends ErrorMessage | undefined = ErrorMessage | undefined
+>(message?: TMessage): CustomSchema, TMessage> {
+ return custom, TMessage>(
+ value => safeParse(refObjectSchema, value).success,
+ // TODO: Probably lacking some undefined checks, thus, we need to force cast.
+ message as TMessage
+ );
+}
+
+export default refObject;
diff --git a/packages/react-valibot/tsup.config.ts b/packages/react-valibot/tsup.config.ts
index f832eff721..9526b6e770 100644
--- a/packages/react-valibot/tsup.config.ts
+++ b/packages/react-valibot/tsup.config.ts
@@ -2,29 +2,18 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = [
- 'api/src/index.ts',
- 'api-middleware/src/index.ts',
- 'bundle/src/boot/exports/index.ts',
- 'component/src/index.ts',
- 'debug-theme/src/index.ts',
- 'fluent-theme/src/index.ts',
- 'redux-store/src/index.ts'
-];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-react-valibot': './src/index.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
{
...commonConfig,
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/redux-store/.gitignore b/packages/redux-store/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/redux-store/.gitignore
+++ b/packages/redux-store/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/redux-store/package.json b/packages/redux-store/package.json
index 349ccb1230..caffe32483 100644
--- a/packages/redux-store/package.json
+++ b/packages/redux-store/package.json
@@ -31,7 +31,11 @@
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/redux-store#readme",
"private": true,
"scripts": {
- "build": "tsup",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -41,12 +45,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-react-valibot": "development",
- "@msinternal/botframework-webchat-tsconfig": "development",
- "botframework-webchat-core": "production"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../react-valibot/package.json\" \"../tsconfig/package.json\" \"../core/package.json\""
},
"pinDependencies": {
"@types/react": [
@@ -57,6 +56,11 @@
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-react-valibot": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development",
+ "botframework-webchat-core": "production"
+ },
"devDependencies": {
"@msinternal/botframework-webchat-react-valibot": "^0.0.0-0",
"@msinternal/botframework-webchat-tsconfig": "^0.0.0-0",
diff --git a/packages/redux-store/src/index.ts b/packages/redux-store/src/index.ts
index 9ae00a060e..191af8a2cf 100644
--- a/packages/redux-store/src/index.ts
+++ b/packages/redux-store/src/index.ts
@@ -1,2 +1,3 @@
+export { default as reduxStoreSchema } from './private/reduxStoreSchema';
export { default as ReduxStoreComposer } from './ReduxStoreComposer';
export { default as useSuggestedActionsHooks } from './suggestedActions/useSuggestedActionsHooks';
diff --git a/packages/redux-store/tsup.config.ts b/packages/redux-store/tsup.config.ts
index 78f7b8aca0..6901da8420 100644
--- a/packages/redux-store/tsup.config.ts
+++ b/packages/redux-store/tsup.config.ts
@@ -2,21 +2,18 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['api/src/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-redux-store': './src/index.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
{
...commonConfig,
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/repack/adaptivecards/package.json b/packages/repack/adaptivecards/package.json
index 54416b0dbb..fe79193cb7 100644
--- a/packages/repack/adaptivecards/package.json
+++ b/packages/repack/adaptivecards/package.json
@@ -7,7 +7,11 @@
"type": "module",
"main": "./dist/index.js",
"scripts": {
- "build": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -15,19 +19,19 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {
"adaptivecards": [
"3.0.2",
"Bump manually to ensure compatibility"
]
},
- "dependencies": {
- "adaptivecards": "3.0.2"
- },
+ "localDependencies": {},
"devDependencies": {
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "adaptivecards": "3.0.2"
}
}
diff --git a/packages/repack/base64-js/package.json b/packages/repack/base64-js/package.json
index fad25667f4..64ba943cf0 100644
--- a/packages/repack/base64-js/package.json
+++ b/packages/repack/base64-js/package.json
@@ -7,7 +7,11 @@
"type": "module",
"main": "./dist/index.js",
"scripts": {
- "build": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -15,14 +19,14 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {},
- "dependencies": {
- "base64-js": "1.5.1"
- },
+ "localDependencies": {},
"devDependencies": {
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "base64-js": "1.5.1"
}
}
diff --git a/packages/repack/botframework-directlinejs/package.json b/packages/repack/botframework-directlinejs/package.json
index c1620759cc..ba22a59c3b 100644
--- a/packages/repack/botframework-directlinejs/package.json
+++ b/packages/repack/botframework-directlinejs/package.json
@@ -7,7 +7,11 @@
"type": "module",
"main": "./dist/index.js",
"scripts": {
- "build": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -15,14 +19,14 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {},
- "devDependencies": {
- "esbuild": "^0.25.10"
- },
+ "localDependencies": {},
"dependencies": {
"botframework-directlinejs": "0.15.6"
+ },
+ "devDependencies": {
+ "esbuild": "^0.25.10"
}
}
diff --git a/packages/repack/html-react-parser/package.json b/packages/repack/html-react-parser/package.json
index d646be1588..c26be99926 100644
--- a/packages/repack/html-react-parser/package.json
+++ b/packages/repack/html-react-parser/package.json
@@ -9,7 +9,11 @@
".": "./dist/index.js"
},
"scripts": {
- "build": "node ./build.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "node ./build.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -17,14 +21,14 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {},
- "dependencies": {
- "html-react-parser": "5.2.6"
- },
+ "localDependencies": {},
"devDependencies": {
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "html-react-parser": "5.2.6"
}
}
diff --git a/packages/repack/microsoft-cognitiveservices-speech-sdk/package.json b/packages/repack/microsoft-cognitiveservices-speech-sdk/package.json
index 9991042979..6b99d69057 100644
--- a/packages/repack/microsoft-cognitiveservices-speech-sdk/package.json
+++ b/packages/repack/microsoft-cognitiveservices-speech-sdk/package.json
@@ -16,7 +16,11 @@
"./distrib/lib/src/sdk/Exports.js": "./dist/sdk/Exports.js"
},
"scripts": {
- "build": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index.js ./src/common/AudioSourceEvents.js ./src/common/Exports.js ./src/common.browser/Exports.js ./src/common.speech/Exports.js ./src/sdk/Audio/AudioStreamFormat.js ./src/sdk/Exports.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index.js ./src/common/AudioSourceEvents.js ./src/common/Exports.js ./src/common.browser/Exports.js ./src/common.speech/Exports.js ./src/sdk/Audio/AudioStreamFormat.js ./src/sdk/Exports.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -24,19 +28,19 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {
"microsoft-cognitiveservices-speech-sdk": [
"1.17.0",
"<=1.45.0 is using new protocol that does not connect may need some tune."
]
},
- "dependencies": {
- "microsoft-cognitiveservices-speech-sdk": "1.17.0"
- },
+ "localDependencies": {},
"devDependencies": {
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "microsoft-cognitiveservices-speech-sdk": "1.17.0"
}
}
diff --git a/packages/repack/object-assign/package.json b/packages/repack/object-assign/package.json
index e9f319db07..bbc38b46a6 100644
--- a/packages/repack/object-assign/package.json
+++ b/packages/repack/object-assign/package.json
@@ -9,13 +9,19 @@
".": "./src/index.js"
},
"scripts": {
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "echo This package does not need to be built.",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
"eslint": "npm run precommit",
"precommit": "npm run precommit:eslint -- src",
- "precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0"
+ "precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
- "pinDependencies": {}
+ "pinDependencies": {},
+ "localDependencies": {}
}
diff --git a/packages/repack/react-dom/package.json b/packages/repack/react-dom/package.json
index da27fdd324..784ebd3f64 100644
--- a/packages/repack/react-dom/package.json
+++ b/packages/repack/react-dom/package.json
@@ -10,7 +10,11 @@
"./client": "./dist/react-dom/client.js"
},
"scripts": {
- "build": "node ./build.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "node ./build.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -18,9 +22,8 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {
"@types/react-dom": [
"~18.3",
@@ -31,11 +34,12 @@
"Bump React manually"
]
},
- "dependencies": {
- "react-dom": "18.3.1"
- },
+ "localDependencies": {},
"devDependencies": {
"@types/react-dom": "^18.3.7",
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "react-dom": "18.3.1"
}
}
diff --git a/packages/repack/react-dom@baseline/package.json b/packages/repack/react-dom@baseline/package.json
index bacfe14a6f..d3a2ed6704 100644
--- a/packages/repack/react-dom@baseline/package.json
+++ b/packages/repack/react-dom@baseline/package.json
@@ -9,7 +9,11 @@
".": "./dist/react-dom.js"
},
"scripts": {
- "build": "node ./build.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "node ./build.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -17,10 +21,7 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch"
- },
- "localDependencies": {
- "@msinternal/object-assign": "development"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\" \"../object-assign/package.json\""
},
"pinDependencies": {
"react-dom": [
@@ -28,12 +29,15 @@
"Bump React manually"
]
},
- "dependencies": {
- "react-dom": "16.8.6"
+ "localDependencies": {
+ "@msinternal/object-assign": "development"
},
"devDependencies": {
"@msinternal/object-assign": "0.0.0-0",
"@types/react-dom": "^16.9.25",
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "react-dom": "16.8.6"
}
}
diff --git a/packages/repack/react-dom@umd/package.json b/packages/repack/react-dom@umd/package.json
index 02d93405fb..95ce9ab565 100644
--- a/packages/repack/react-dom@umd/package.json
+++ b/packages/repack/react-dom@umd/package.json
@@ -9,7 +9,11 @@
".": "./dist/react-dom.js"
},
"scripts": {
- "build": "esbuild --bundle=true --chunk-names=react-dom/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react-dom=./src/index.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --chunk-names=react-dom/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react-dom=./src/index.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -17,15 +21,11 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
- },
- "localDependencies": {
- "@msinternal/object-assign": "development"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
"pinDependencies": {},
+ "localDependencies": {},
"devDependencies": {
"esbuild": "^0.25.10"
- },
- "main": "index.js",
- "license": "ISC"
+ }
}
diff --git a/packages/repack/react-is/package.json b/packages/repack/react-is/package.json
index d0b61e620b..648d4822dd 100644
--- a/packages/repack/react-is/package.json
+++ b/packages/repack/react-is/package.json
@@ -9,7 +9,11 @@
".": "./dist/index.js"
},
"scripts": {
- "build": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --format=esm --outdir=dist --platform=browser --splitting --sourcemap ./src/index.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -17,20 +21,20 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {
"react-is": [
"16.13.1",
"Bump with React"
]
},
- "dependencies": {
- "react-is": "16.13.1"
- },
+ "localDependencies": {},
"devDependencies": {
"@types/react-is": "^16.7.5",
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "react-is": "16.13.1"
}
}
diff --git a/packages/repack/react/package.json b/packages/repack/react/package.json
index 121bc9f6fc..9de616e0e0 100644
--- a/packages/repack/react/package.json
+++ b/packages/repack/react/package.json
@@ -11,7 +11,11 @@
"./jsx-runtime": "./dist/react/jsx-runtime.js"
},
"scripts": {
- "build": "esbuild --bundle=true --chunk-names=react/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react=./src/index.js react/jsx-dev-runtime=./src/jsx-dev-runtime.ts react/jsx-runtime=./src/jsx-runtime.ts",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --chunk-names=react/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react=./src/index.js react/jsx-dev-runtime=./src/jsx-dev-runtime.ts react/jsx-runtime=./src/jsx-runtime.ts && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -19,10 +23,7 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
- },
- "localDependencies": {
- "@msinternal/object-assign": "development"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
"pinDependencies": {
"@types/react": [
@@ -34,11 +35,12 @@
"Bump React manually"
]
},
- "dependencies": {
- "react": "18.3.1"
- },
+ "localDependencies": {},
"devDependencies": {
"@types/react": "^18.3.24",
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "react": "18.3.1"
}
}
diff --git a/packages/repack/react@baseline/package.json b/packages/repack/react@baseline/package.json
index 6f4e3b22c0..db586812b8 100644
--- a/packages/repack/react@baseline/package.json
+++ b/packages/repack/react@baseline/package.json
@@ -9,7 +9,11 @@
".": "./dist/react.js"
},
"scripts": {
- "build": "esbuild --alias:object-assign=@msinternal/object-assign --bundle=true --chunk-names=react/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react=./src/index.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --alias:object-assign=@msinternal/object-assign --bundle=true --chunk-names=react/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react=./src/index.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -17,10 +21,7 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
- },
- "localDependencies": {
- "@msinternal/object-assign": "development"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\" \"../object-assign/package.json\""
},
"pinDependencies": {
"react": [
@@ -28,12 +29,15 @@
"Bump React manually"
]
},
- "dependencies": {
- "react": "16.8.6"
+ "localDependencies": {
+ "@msinternal/object-assign": "development"
},
"devDependencies": {
"@msinternal/object-assign": "0.0.0-0",
"@types/react": "^16.14.65",
"esbuild": "^0.25.10"
+ },
+ "dependencies": {
+ "react": "16.8.6"
}
}
diff --git a/packages/repack/react@umd/package.json b/packages/repack/react@umd/package.json
index f70ba08e4b..d400956182 100644
--- a/packages/repack/react@umd/package.json
+++ b/packages/repack/react@umd/package.json
@@ -9,7 +9,11 @@
".": "./dist/react.js"
},
"scripts": {
- "build": "esbuild --bundle=true --chunk-names=react/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react=./src/index.js",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "esbuild --bundle=true --chunk-names=react/[name]-[hash] --entry-names=[dir]/[name] --format=esm --outdir=dist --platform=browser --splitting --sourcemap react=./src/index.js && touch ./package.json",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -17,12 +21,10 @@
"precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
"precommit:eslint": "eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
- "start": "npm run build -- --watch --watch-delay=200"
- },
- "localDependencies": {
- "@msinternal/object-assign": "development"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
"pinDependencies": {},
+ "localDependencies": {},
"devDependencies": {
"esbuild": "^0.25.10"
}
diff --git a/packages/styles/.gitignore b/packages/styles/.gitignore
index 515a303349..52536cb56d 100644
--- a/packages/styles/.gitignore
+++ b/packages/styles/.gitignore
@@ -1,5 +1,4 @@
/*.tgz
/dist/
-/dist.tmp/
/node_modules/
/tsup.config.bundled_*.mjs
diff --git a/packages/styles/package.json b/packages/styles/package.json
index 81938f7fb1..633622c925 100644
--- a/packages/styles/package.json
+++ b/packages/styles/package.json
@@ -56,7 +56,11 @@
],
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/styles#readme",
"scripts": {
- "build": "tsup",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -66,11 +70,7 @@
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --watch"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-base": "development",
- "@msinternal/botframework-webchat-tsconfig": "development"
+ "start": "../../scripts/npm/notify-build.sh \"./src/\" \"../base/package.json\" \"../tsconfig/package.json\""
},
"pinDependencies": {
"typescript": [
@@ -78,6 +78,10 @@
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-base": "development",
+ "@msinternal/botframework-webchat-tsconfig": "development"
+ },
"devDependencies": {
"@jridgewell/sourcemap-codec": "^1.5.4",
"@msinternal/botframework-webchat-base": "0.0.0-0",
diff --git a/packages/styles/tsup.config.ts b/packages/styles/tsup.config.ts
index 3498f2c4d7..f6f428b43f 100644
--- a/packages/styles/tsup.config.ts
+++ b/packages/styles/tsup.config.ts
@@ -2,23 +2,20 @@ import { defineConfig } from 'tsup';
import { applyConfig } from '../../tsup.base.config';
-// TODO: [P1] Compute this automatically.
-const DEPENDENT_PATHS = ['component/src/index.ts', 'fluent-theme/src/index.ts'];
-
const commonConfig = applyConfig(config => ({
...config,
entry: {
'botframework-webchat-styles': './src/index.ts',
'botframework-webchat-styles.build': './src/build/index.ts',
'botframework-webchat-styles.react': './src/react/index.ts'
- },
- onSuccess: `touch ${DEPENDENT_PATHS.map(path => `../${path}`).join(' ')}`
+ }
}));
export default defineConfig([
{
...commonConfig,
- format: 'esm'
+ format: 'esm',
+ onSuccess: 'touch ./package.json'
},
{
...commonConfig,
diff --git a/packages/support/cldr-data-downloader/package.json b/packages/support/cldr-data-downloader/package.json
index 347dc5bb6c..91b85e9d23 100644
--- a/packages/support/cldr-data-downloader/package.json
+++ b/packages/support/cldr-data-downloader/package.json
@@ -39,6 +39,11 @@
"cldr-data-downloader": "./bin/download.sh"
},
"scripts": {
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "echo This package does not need to be built.",
"bump": "npm run bump:dev && npm run bump:prod && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -46,8 +51,10 @@
"postversion": "cat package.json | jq '.version as $V | (.localDependencies // {} | with_entries(select(.value == \"production\") | { key: .key, value: $V })) as $L1 | (.localDependencies // {} | with_entries(select(.value == \"development\") | { key: .key, value: $V })) as $L2 | ((.dependencies // {}) + $L1 | to_entries | sort_by(.key) | from_entries) as $D1 | ((.devDependencies // {}) + $L2 | to_entries | sort_by(.key) | from_entries) as $D2 | . + { dependencies: $D1, devDependencies: $D2 }' > package-temp.json && mv package-temp.json package.json",
"precommit": "npm run precommit:eslint -- src",
"precommit:eslint": "node ../../../node_modules/eslint/bin/eslint.js --report-unused-disable-directives --max-warnings 0",
- "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json"
+ "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
+ "pinDependencies": {},
"localDependencies": {},
"dependencies": {
"adm-zip": "0.5.16",
diff --git a/packages/support/cldr-data/package.json b/packages/support/cldr-data/package.json
index 96fb9b63e0..724025ab59 100644
--- a/packages/support/cldr-data/package.json
+++ b/packages/support/cldr-data/package.json
@@ -39,7 +39,11 @@
"urls.json"
],
"scripts": {
- "build": "node ./src/install.mjs && node ./src/patch.mjs",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "node ./src/install.mjs && node ./src/patch.mjs && touch ./package.json",
"bump": "npm run bump:dev && npm run bump:prod && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -47,10 +51,8 @@
"postversion": "cat package.json | jq '.version as $V | (.localDependencies // {} | with_entries(select(.value == \"production\") | { key: .key, value: $V })) as $L1 | (.localDependencies // {} | with_entries(select(.value == \"development\") | { key: .key, value: $V })) as $L2 | ((.dependencies // {}) + $L1 | to_entries | sort_by(.key) | from_entries) as $D1 | ((.devDependencies // {}) + $L2 | to_entries | sort_by(.key) | from_entries) as $D2 | . + { dependencies: $D1, devDependencies: $D2 }' > package-temp.json && mv package-temp.json package.json",
"precommit": "npm run precommit:eslint -- src",
"precommit:eslint": "node ../../../node_modules/eslint/bin/eslint.js --report-unused-disable-directives --max-warnings 0",
- "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json"
- },
- "localDependencies": {
- "@msinternal/botframework-webchat-cldr-data-downloader": "production"
+ "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\" \"../cldr-data-downloader/package.json\""
},
"pinDependencies": {
"glob": [
@@ -58,6 +60,9 @@
"glob@10 updated the entrypoint, need funding to upgrade"
]
},
+ "localDependencies": {
+ "@msinternal/botframework-webchat-cldr-data-downloader": "production"
+ },
"dependencies": {
"@msinternal/botframework-webchat-cldr-data-downloader": "0.3.5-0",
"glob": "8.1.0",
diff --git a/packages/test/dev-server/package.json b/packages/test/dev-server/package.json
index 66054cba3c..a9a043e439 100644
--- a/packages/test/dev-server/package.json
+++ b/packages/test/dev-server/package.json
@@ -6,7 +6,12 @@
"author": "Microsoft Corporation",
"license": "MIT",
"private": true,
+ "type": "module",
"scripts": {
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:run": "echo This project does not need to be built.",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -14,9 +19,8 @@
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
"start": "node ."
},
- "type": "module",
- "localDependencies": {},
"pinDependencies": {},
+ "localDependencies": {},
"devDependencies": {
"compression": "^1.8.1",
"express": "^5.1.0",
diff --git a/packages/test/harness/package.json b/packages/test/harness/package.json
index 7ed228286e..3afb2510a3 100644
--- a/packages/test/harness/package.json
+++ b/packages/test/harness/package.json
@@ -12,10 +12,14 @@
"node": ">= 14.0.0"
},
"scripts": {
- "build": "npm run build:esbuild:esm && npm run build:esbuild:iife",
- "build:esbuild:base": "esbuild test-harness=./src/browser/index.js --bundle --define:define=undefined --define:process.env.CI=undefined --minify --outdir=dist --sourcemap --target=chrome100",
- "build:esbuild:esm": "npm run build:esbuild:base -- --format=esm --out-extension:.js=.mjs",
- "build:esbuild:iife": "npm run build:esbuild:base -- --format=iife",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "concurrently --prefix-colors \"auto\" \"npm:build:run:esbuild:esm\" \"npm:build:run:esbuild:iife\" && touch ./package.json",
+ "build:run:esbuild:base": "esbuild test-harness=./src/browser/index.js --bundle --define:define=undefined --define:process.env.CI=undefined --minify --outdir=dist --sourcemap --target=chrome100",
+ "build:run:esbuild:esm": "npm run build:run:esbuild:base -- --format=esm --out-extension:.js=.mjs",
+ "build:run:esbuild:iife": "npm run build:run:esbuild:base -- --format=iife",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -24,12 +28,9 @@
"precommit": "npm run precommit:eslint -- src",
"precommit:eslint": "../../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "concurrently --kill-others --prefix-colors \"auto\" \"npm:start:*\"",
- "start:esbuild:esm": "npm run build:esbuild:esm -- --watch --watch-delay=200",
- "start:esbuild:iife": "npm run build:esbuild:iife -- --watch --watch-delay=200",
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\"",
"test": "node node_modules/.bin/jest --maxWorkers=4"
},
- "localDependencies": {},
"pinDependencies": {
"expect": [
"25",
@@ -52,16 +53,7 @@
"strip-ansi@7 dropped support of CommonJS"
]
},
- "dependencies": {
- "abort-controller": "3.0.0",
- "axe-core": "4.10.3",
- "core-js": "3.44.0",
- "core-js-pure": "3.44.0",
- "event-target-shim": "6.0.2",
- "expect": "25.5.0",
- "lolex": "6.0.0",
- "math-random": "2.0.1"
- },
+ "localDependencies": {},
"devDependencies": {
"concurrently": "^9.2.0",
"esbuild": "^0.25.8",
@@ -75,5 +67,15 @@
"selenium-webdriver": "^4.34.0",
"serve": "^14.2.4",
"strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "abort-controller": "3.0.0",
+ "axe-core": "4.10.3",
+ "core-js": "3.44.0",
+ "core-js-pure": "3.44.0",
+ "event-target-shim": "6.0.2",
+ "expect": "25.5.0",
+ "lolex": "6.0.0",
+ "math-random": "2.0.1"
}
}
diff --git a/packages/test/page-object/package.json b/packages/test/page-object/package.json
index c08a496755..f49c18caa9 100644
--- a/packages/test/page-object/package.json
+++ b/packages/test/page-object/package.json
@@ -9,10 +9,14 @@
"node": ">= 14.0.0"
},
"scripts": {
- "build": "npm run build:esbuild:esm && npm run build:esbuild:iife",
- "build:esbuild:base": "esbuild test-page-object=./src/index.js --bundle --define:define=undefined --loader:.js=jsx --minify --outdir=dist --sourcemap --target=chrome100",
- "build:esbuild:esm": "npm run build:esbuild:base -- --format=esm --out-extension:.js=.mjs",
- "build:esbuild:iife": "npm run build:esbuild:base -- --format=iife",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "concurrently --prefix-colors \"auto\" \"npm:build:run:esbuild:esm\" \"npm:build:run:esbuild:iife\" && touch ./package.json",
+ "build:run:esbuild:base": "esbuild test-page-object=./src/index.js --bundle --define:define=undefined --loader:.js=jsx --minify --outdir=dist --sourcemap --target=chrome100",
+ "build:run:esbuild:esm": "npm run build:run:esbuild:base -- --format=esm --out-extension:.js=.mjs",
+ "build:run:esbuild:iife": "npm run build:run:esbuild:base -- --format=iife",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -21,12 +25,19 @@
"precommit": "npm run precommit:eslint -- src",
"precommit:eslint": "../../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "concurrently --kill-others --prefix-colors \"auto\" \"npm:start:*\"",
- "start:esbuild:esm": "npm run build:esbuild:esm -- --watch --watch-delay=200",
- "start:esbuild:iife": "npm run build:esbuild:iife -- --watch --watch-delay=200"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
+ },
+ "pinDependencies": {
+ "jest-mock": [
+ "28",
+ ">= 29 will pull in Node.js dependencies"
+ ]
},
"localDependencies": {},
- "pinDependencies": {},
+ "devDependencies": {
+ "concurrently": "^9.2.0",
+ "esbuild": "^0.25.8"
+ },
"dependencies": {
"base64-arraybuffer": "1.0.2",
"bent": "7.3.12",
@@ -35,13 +46,10 @@
"core-js-pure": "3.44.0",
"event-iterator": "2.0.0",
"event-target-shim": "6.0.2",
+ "jest-mock": "28.1.3",
"math-random": "2.0.1",
"microsoft-cognitiveservices-speech-sdk": "1.17.0",
"prop-types": "15.8.1",
"simple-update-in": "2.2.0"
- },
- "devDependencies": {
- "concurrently": "^9.2.0",
- "esbuild": "^0.25.8"
}
}
diff --git a/packages/test/page-object/src/globals/testHelpers/ignoreReactDeprecation.js b/packages/test/page-object/src/globals/testHelpers/ignoreReactDeprecation.js
new file mode 100644
index 0000000000..57180bf205
--- /dev/null
+++ b/packages/test/page-object/src/globals/testHelpers/ignoreReactDeprecation.js
@@ -0,0 +1,21 @@
+import { spyOn } from 'jest-mock';
+
+export default function ignoreReactDeprecation(init = {}) {
+ const consoleError = console.error.bind(console);
+
+ spyOn(console, 'error').mockImplementation((...args) => {
+ let shouldIgnore = false;
+
+ if (
+ init.defaultProps &&
+ typeof args[0] === 'string' &&
+ args[0].includes(
+ 'Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.'
+ )
+ ) {
+ shouldIgnore = true;
+ }
+
+ shouldIgnore || consoleError(...args);
+ });
+}
diff --git a/packages/test/page-object/src/globals/testHelpers/index.js b/packages/test/page-object/src/globals/testHelpers/index.js
index 0c1024b04a..b5fabd342f 100644
--- a/packages/test/page-object/src/globals/testHelpers/index.js
+++ b/packages/test/page-object/src/globals/testHelpers/index.js
@@ -1,40 +1,19 @@
-import * as accessibility from './accessibility/index';
-import * as activityGrouping from './activityGrouping/index';
-import * as speech from './speech/index';
-import * as token from './token/index';
-import * as transcriptNavigation from './transcriptNavigation';
-import arrayBufferToBase64 from './arrayBufferToBase64';
-import createAudioInputStreamFromRiffWavArrayBuffer from './speech/audioConfig/createAudioInputStreamFromRiffWavArrayBuffer';
-import createDirectLineEmulator from './createDirectLineEmulator';
-import createDirectLineWithTranscript from './createDirectLineWithTranscript';
-import createRenderWebChatWithHook from './createRenderWebChatWithHook';
-import createRunHookActivityMiddleware from './createRunHookActivityMiddleware';
-import createStore, { createStoreWithOptions } from './createStore';
-import depthFirstWalk from './depthFirstWalk';
-import getAllTextContents from './getAllTextContents';
-import iterateAsyncIterable from './iterateAsyncIterable';
-import shareObservable from './shareObservable';
-import sleep from './sleep';
-import stringToArrayBuffer from './stringToArrayBuffer';
-
-export {
- accessibility,
- activityGrouping,
- arrayBufferToBase64,
- createAudioInputStreamFromRiffWavArrayBuffer,
- createDirectLineEmulator,
- createDirectLineWithTranscript,
- createRenderWebChatWithHook,
- createRunHookActivityMiddleware,
- createStore,
- createStoreWithOptions,
- depthFirstWalk,
- getAllTextContents,
- iterateAsyncIterable,
- shareObservable,
- sleep,
- speech,
- stringToArrayBuffer,
- token,
- transcriptNavigation
-};
+export * as accessibility from './accessibility/index';
+export * as activityGrouping from './activityGrouping/index';
+export { default as arrayBufferToBase64 } from './arrayBufferToBase64';
+export { default as createDirectLineEmulator } from './createDirectLineEmulator';
+export { default as createDirectLineWithTranscript } from './createDirectLineWithTranscript';
+export { default as createRenderWebChatWithHook } from './createRenderWebChatWithHook';
+export { default as createRunHookActivityMiddleware } from './createRunHookActivityMiddleware';
+export { default as createStore, createStoreWithOptions } from './createStore';
+export { default as depthFirstWalk } from './depthFirstWalk';
+export { default as getAllTextContents } from './getAllTextContents';
+export { default as ignoreReactDeprecation } from './ignoreReactDeprecation';
+export { default as iterateAsyncIterable } from './iterateAsyncIterable';
+export { default as shareObservable } from './shareObservable';
+export { default as sleep } from './sleep';
+export { default as createAudioInputStreamFromRiffWavArrayBuffer } from './speech/audioConfig/createAudioInputStreamFromRiffWavArrayBuffer';
+export * as speech from './speech/index';
+export { default as stringToArrayBuffer } from './stringToArrayBuffer';
+export * as token from './token/index';
+export * as transcriptNavigation from './transcriptNavigation';
diff --git a/packages/test/web-server/package.json b/packages/test/web-server/package.json
index 9d7718bf23..715ef9061d 100644
--- a/packages/test/web-server/package.json
+++ b/packages/test/web-server/package.json
@@ -7,7 +7,11 @@
"license": "MIT",
"main": "./dist/index.js",
"scripts": {
- "build": "tsup",
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../../scripts/npm/build-watch.sh",
+ "build:run": "tsup",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
@@ -16,21 +20,21 @@
"precommit": "npm run precommit:eslint -- src",
"precommit:eslint": "../../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
- "start": "npm run build -- --onSuccess=\"node .\" --watch"
+ "start": "../../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {
"typescript": [
"~5.8.3",
"@typescript-eslint/parser@8.38.0 does not support typescript@5.9.2 yet"
]
},
- "dependencies": {
- "selfsigned": "3.0.1",
- "serve-handler": "6.1.6"
- },
+ "localDependencies": {},
"devDependencies": {
"tsup": "^8.5.0",
"typescript": "~5.8.3"
+ },
+ "dependencies": {
+ "selfsigned": "3.0.1",
+ "serve-handler": "6.1.6"
}
}
diff --git a/packages/test/web-server/tsup.config.ts b/packages/test/web-server/tsup.config.ts
index fe084a9c43..4143bcce57 100644
--- a/packages/test/web-server/tsup.config.ts
+++ b/packages/test/web-server/tsup.config.ts
@@ -6,5 +6,6 @@ export default defineConfig({
},
format: 'cjs',
platform: 'node',
- noExternal: ['selfsigned', 'serve-handler']
+ noExternal: ['selfsigned', 'serve-handler'],
+ onSuccess: 'touch ./package.json'
});
diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json
index 752e7a0ebd..bf95fe6ca8 100644
--- a/packages/tsconfig/package.json
+++ b/packages/tsconfig/package.json
@@ -22,16 +22,22 @@
],
"homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/main/packages/tsconfig#readme",
"scripts": {
+ "build": "npm run --if-present build:pre && npm run build:run && npm run --if-present build:post",
+ "build:pre": "npm run build:pre:local-dependencies && npm run build:pre:watch",
+ "build:pre:local-dependencies": "../../scripts/npm/build-local-dependencies.sh",
+ "build:pre:watch": "../../scripts/npm/build-watch.sh",
+ "build:run": "echo This project does not need to be built.",
"bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
"bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
"bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
"eslint": "npm run precommit",
"postversion": "cat package.json | jq '.version as $V | (.localDependencies // {} | with_entries(select(.value == \"production\") | { key: .key, value: $V })) as $L1 | (.localDependencies // {} | with_entries(select(.value == \"development\") | { key: .key, value: $V })) as $L2 | ((.dependencies // {}) + $L1 | to_entries | sort_by(.key) | from_entries) as $D1 | ((.devDependencies // {}) + $L2 | to_entries | sort_by(.key) | from_entries) as $D2 | . + { dependencies: $D1, devDependencies: $D2 }' > package-temp.json && mv package-temp.json package.json",
"precommit": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
- "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json"
+ "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
+ "start": "../../scripts/npm/notify-build.sh \"./src/\""
},
- "localDependencies": {},
"pinDependencies": {},
+ "localDependencies": {},
"devDependencies": {
"@tsconfig/strictest": "^2.0.5",
"typescript-plugin-css-modules": "^5.2.0"
diff --git a/scripts/buildWatch.mjs b/scripts/buildWatch.mjs
new file mode 100644
index 0000000000..d93dfb786c
--- /dev/null
+++ b/scripts/buildWatch.mjs
@@ -0,0 +1,44 @@
+import { relative, resolve } from 'path';
+import { readPackageUp } from 'read-package-up';
+import { readPackage } from 'read-pkg';
+
+const cwd = process.cwd();
+const currentPackageJSON = await readPackage();
+
+const {
+ packageJson: { workspaces },
+ path: rootPackageJSONPath
+} = await readPackageUp({ cwd: resolve(cwd, '../') });
+
+const root = resolve(rootPackageJSONPath, '../');
+
+const watchPaths = ['./src/'];
+
+for (const [packageName] of Object.entries(currentPackageJSON.localDependencies || {})) {
+ for (const workspace of workspaces) {
+ const packageJSON = await readPackage({ cwd: resolve(root, workspace) });
+
+ if (packageJSON.name === packageName) {
+ watchPaths.push(relative(cwd, resolve(root, workspace, 'package.json')));
+ }
+ }
+}
+
+// "nodemon" will pick up every file change, trigger build too many times.
+// console.log(
+// `node --watch ${watchPaths.map(path => `--watch-path "${path}"`).join(' ')} --watch-preserve-output $(which npm) run build:run`
+// );
+
+// "inotifywait without --monitor" will not pick up changes while it is building
+// console.log(
+// `while true; do inotifywait ${['close_write', 'create', 'delete', 'modify', 'move'].map(event => `--event ${event}`).join(' ')} --recursive ${watchPaths.map(path => `"${path}"`).join(' ')}; $(which npm) run build:run; done`
+// );
+
+// "inotifywait with --monitor" will pick up every file change, trigger build too many times.
+// console.log(
+// `inotifywait ${['close_write', 'create', 'delete', 'modify', 'move'].map(event => `--event ${event}`).join(' ')} --monitor --recursive ${watchPaths.map(path => `"${path}"`).join(' ')} | while read changed; do $(which npm) run build:run; done`
+// );
+
+console.log(
+ `${relative(cwd, resolve(root, './scripts/npm/notify-build.sh'))} ${watchPaths.map(path => `"${path}"`).join(' ')}`
+);
diff --git a/scripts/npm/build-local-dependencies.sh b/scripts/npm/build-local-dependencies.sh
new file mode 100755
index 0000000000..4b0e87b4be
--- /dev/null
+++ b/scripts/npm/build-local-dependencies.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+set -euo pipefail
+
+cat package.json | jq -r '
+ .localDependencies =
+ (
+ (
+ .dependencies // {}
+ | to_entries
+ | map(select((.key | startswith("@msinternal/")) or .value == "0.0.0-0" or .value == "^0.0.0-0") | .value = "production")
+ | from_entries
+ )
+ + (
+ .devDependencies // {}
+ | to_entries
+ | map(select((.key | startswith("@msinternal/")) or .value == "0.0.0-0" or .value == "^0.0.0-0") | .value = "development")
+ | from_entries
+ )
+ + (
+ .peerDependencies // {}
+ | to_entries
+ | map(select((.key | startswith("@msinternal/")) or .value == "0.0.0-0" or .value == "^0.0.0-0") | .value = "peer")
+ | from_entries
+ )
+ | to_entries
+ | sort_by(.key)
+ | from_entries
+ )
+ | .
+' > package-temp.json && mv package-temp.json package.json
diff --git a/scripts/npm/build-watch.sh b/scripts/npm/build-watch.sh
new file mode 100755
index 0000000000..93332629cf
--- /dev/null
+++ b/scripts/npm/build-watch.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+WATCH_SCRIPT=$(node "$SCRIPT_DIR/../buildWatch.mjs")
+
+cat package.json | jq --arg W "$WATCH_SCRIPT" -r '
+ .scripts.start = $W
+ | .
+' > package-temp.json && mv package-temp.json package.json
diff --git a/scripts/npm/bump-dev.sh b/scripts/npm/bump-dev.sh
new file mode 100755
index 0000000000..7e8a86c082
--- /dev/null
+++ b/scripts/npm/bump-dev.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -euo pipefail
+
+PACKAGES_TO_BUMP=$(cat package.json | jq -r '
+ (.pinDependencies // {}) as $P
+ | (.localDependencies // {} | keys) as $L
+ | (.devDependencies // {})
+ | to_entries
+ | map(select(.key as $K | $L | contains([$K]) | not))
+ | map(.key + "@" + ($P[.key] // ["latest"])[0])
+ | join(" ")
+')
+
+[ ! -z "$PACKAGES_TO_BUMP" ] && npm install --save-dev $PACKAGES_TO_BUMP || true
diff --git a/scripts/npm/bump-peer.sh b/scripts/npm/bump-peer.sh
new file mode 100644
index 0000000000..c03b9743ac
--- /dev/null
+++ b/scripts/npm/bump-peer.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -euo pipefail
+
+PACKAGES_TO_BUMP=$(cat package.json | jq -r '
+ (.pinDependencies // {}) as $P
+ | (.localDependencies // {} | keys) as $L
+ | (.peerDependencies // {})
+ | to_entries
+ | map(select(.key as $K | $L | contains([$K]) | not))
+ | map(.key + "@" + ($P[.key] // ["latest"])[0])
+ | join(" ")
+')
+
+[ ! -z "$PACKAGES_TO_BUMP" ] && npm install --save-exact --save-peer $PACKAGES_TO_BUMP || true
diff --git a/scripts/npm/bump-prod.sh b/scripts/npm/bump-prod.sh
new file mode 100755
index 0000000000..fcd3180ea6
--- /dev/null
+++ b/scripts/npm/bump-prod.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -euo pipefail
+
+PACKAGES_TO_BUMP=$(cat package.json | jq -r '
+ (.pinDependencies // {}) as $P
+ | (.localDependencies // {} | keys) as $L
+ | (.dependencies // {})
+ | to_entries
+ | map(select(.key as $K | $L | contains([$K]) | not))
+ | map(.key + "@" + ($P[.key] // ["latest"])[0])
+ | join(" ")
+')
+
+[ ! -z "$PACKAGES_TO_BUMP" ] && npm install --save-exact $PACKAGES_TO_BUMP || true
diff --git a/scripts/npm/notify-build.sh b/scripts/npm/notify-build.sh
new file mode 100755
index 0000000000..3c2615f1c9
--- /dev/null
+++ b/scripts/npm/notify-build.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+set -euo pipefail
+
+if [ "$#" -lt 1 ]; then
+ echo "Usage: $0 [directory_or_file2 ...]"
+ exit 1
+fi
+
+WATCH_DIRS=("$@")
+EVENT_QUEUE="/tmp/inotify_event_queue_$$"
+
+# Create or clear the event queue
+> "$EVENT_QUEUE"
+
+# Kill all background processes on exit
+trap 'kill $(jobs -p)' EXIT
+
+# Monitor all directories/files and write events to the queue
+# "close_write" is for touch
+inotifywait --event close_write,create,delete,modify,move --monitor --outfile "$EVENT_QUEUE" --recursive ../tsconfig/package.json "${WATCH_DIRS[@]}" &
+
+while true; do
+ if [ -s "$EVENT_QUEUE" ]; then
+ # Clear the queue and execute the command
+
+ echo "📫 Change detected: $(head -n 1 "$EVENT_QUEUE")"
+
+ # VSCode fire MODIFY + CLOSE_WRITE on save.
+ # Group all changes within 100 ms, so we don't trigger it twice.
+ sleep 0.1s
+
+ # Clear the event queue
+ > "$EVENT_QUEUE"
+
+ echo "🚥 Build started."
+
+ START_TIME=$(date +%s.%N)
+
+ # Ignore error, let it rebuild
+ npm run build:run || true
+
+ END_TIME=$(date +%s.%N)
+
+ DURATION=$(awk "BEGIN {printf \"%.2f\", $END_TIME - $START_TIME}")
+
+ # Display duration in light purple color
+ echo -e "🏁 Build completed in \033[1;35m${DURATION}\033[0m seconds."
+ else
+ inotifywait --event modify --quiet "$EVENT_QUEUE" >/dev/null 2>&1
+ fi
+done
diff --git a/scripts/npm/postversion.sh b/scripts/npm/postversion.sh
new file mode 100755
index 0000000000..8150a2b529
--- /dev/null
+++ b/scripts/npm/postversion.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+set -euo pipefail
+
+cat package.json | jq '
+ .version as $V
+ | (
+ .localDependencies // {}
+ | with_entries(select(.value == "production")
+ | { key: .key, value: $V })
+ ) as $L1
+ | (
+ .localDependencies // {}
+ | with_entries(select(.value == "development")
+ | { key: .key, value: $V })
+ ) as $L2
+ | (
+ .localDependencies // {}
+ | with_entries(select(.value == "peer")
+ | { key: .key, value: $V })
+ ) as $L3
+ | (
+ (.dependencies // {}) + $L1
+ | to_entries
+ | sort_by(.key)
+ | from_entries
+ ) as $D1
+ | (
+ (.devDependencies // {}) + $L2
+ | to_entries
+ | sort_by(.key)
+ | from_entries
+ ) as $D2
+ | (
+ (.peerDependencies // {}) + $L3
+ | to_entries
+ | sort_by(.key)
+ | from_entries
+ ) as $D3
+ | . + {
+ dependencies: $D1,
+ devDependencies: $D2,
+ peerDependencies: $D3
+ }
+' > package-temp.json && mv package-temp.json package.json
diff --git a/scripts/npm/preversion.sh b/scripts/npm/preversion.sh
new file mode 100755
index 0000000000..f8a1d0d734
--- /dev/null
+++ b/scripts/npm/preversion.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+set -euo pipefail
+
+cat package.json | jq '
+ (
+ .localDependencies // {}
+ | to_entries
+ | map([
+ if .value == "production" then
+ "dependencies"
+ elif .value == "development" then
+ "devDependencies"
+ else
+ "peerDependencies"
+ end,
+ .key
+ ])
+ ) as $P
+ | delpaths($P)
+' > package-temp.json && mv package-temp.json package.json
diff --git a/serve-test.json b/serve-test.json
index 37386abc8a..771b0d2c71 100644
--- a/serve-test.json
+++ b/serve-test.json
@@ -87,6 +87,10 @@
"source": "/__dist__/packages/bundle/static/:filename",
"destination": "packages/bundle/static/:filename"
},
+ {
+ "source": "/__dist__/packages/bundle/static/:dirname1/:dirname2/:filename",
+ "destination": "packages/bundle/static/:dirname1/:dirname2/:filename"
+ },
{
"source": "/__dist__/packages/bundle/static/:dirname/:filename",
"destination": "packages/bundle/static/:dirname/:filename"
diff --git a/tsup.base.config.ts b/tsup.base.config.ts
index 929cf13d85..588d7e5742 100644
--- a/tsup.base.config.ts
+++ b/tsup.base.config.ts
@@ -22,22 +22,22 @@ const disablePlugin = (pluginName: string): EsbuildPlugin => ({
function applyConfig(
overrideOptions: (
- options: Omit & {
+ options: Omit & {
define: Record;
esbuildPlugins: EsbuildPlugin[];
target: Target[];
}
- ) => Omit & {
+ ) => Options & {
define: Record;
esbuildPlugins: EsbuildPlugin[];
target: Target[];
- } & { outDirWithTemp?: [`./${string}/`, `./${string}/`] | undefined }
+ }
): Options & {
define: Record;
esbuildPlugins: EsbuildPlugin[];
target: Target[];
} {
- const nextOptions = overrideOptions({
+ return overrideOptions({
define: {
// TSD does not support define, thus we need to use `globalThis.*` instead.
'globalThis.WEB_CHAT_BUILD_INFO_BUILD_TOOL': '"tsup"',
@@ -112,40 +112,6 @@ function applyConfig(
splitting: true,
target: ['chrome100', 'firefox100', 'safari15'] satisfies Target[]
});
-
- // tsup@8.5.0 do not write to output atomically.
- // Thus, when building in parallel, some of the files will be emptied.
-
- // Writing output to /dist.tmp/ and copy everything back to /dist/ for better atomicity.
-
- // "onSuccess" runs in parallel of DTS, we need to wait until *.d.ts are emitted.
- // Filed a bug, https://github.com/egoist/tsup/issues/1363.
-
- // All instances of tsup will try to copy at the same time and could fail with "cp: cannot create regular file './dist/...': File exists".
- // We can have multiple config writing to their own folder and copy-merge. But then each config will own their version of `onSuccess`, could be messy.
-
- const [outDir = './dist/', tmpDir = './dist.tmp/'] = nextOptions.outDirWithTemp || [];
-
- // TODO: [P1] This merge is not elegant, we should move to Promise.
- const rectifiedOptions = {
- ...nextOptions,
- onSuccess: nextOptions.dts
- ? [
- `while [ -z "$(find ${tmpDir} \\( -name '*.d.ts' -o -name '*.d.mts' \\) -print -quit)" ]; do sleep 0.2; done; mkdir -p ${outDir}; sleep 0.5; until cp --recursive ${tmpDir}/* ${outDir} 2>/dev/null; do sleep 0.5; done`,
- nextOptions.onSuccess
- ]
- .filter(Boolean)
- .join(' && ')
- : [
- `mkdir -p ${outDir}; sleep 0.5; until cp --recursive ${tmpDir}/* ${outDir} 2>/dev/null; do sleep 0.5; done`,
- nextOptions.onSuccess
- ]
- .filter(Boolean)
- .join(' && '),
- outDir: tmpDir
- };
-
- return rectifiedOptions;
}
export { applyConfig };
]