diff --git a/apps/fabric-website/package.json b/apps/fabric-website/package.json index 9181ca3827454f..eb6d3e70eea779 100644 --- a/apps/fabric-website/package.json +++ b/apps/fabric-website/package.json @@ -42,7 +42,7 @@ "source-map-loader": "0.1.5", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "^2.1.5", + "typescript": "^2.2.2", "vinyl-ftp": "0.4.5", "webpack-bundle-analyzer": "^2.2.1" }, diff --git a/apps/todo-app/package.json b/apps/todo-app/package.json index f914783c1af121..254b589270e37f 100644 --- a/apps/todo-app/package.json +++ b/apps/todo-app/package.json @@ -28,6 +28,6 @@ "office-ui-fabric-react": ">=2.10.5 <3.0.0", "react": "^15.4.2", "react-dom": "^15.4.2", - "typescript": "^2.0.6" + "typescript": "^2.2.2" } } \ No newline at end of file diff --git a/common/changes/general-updates_2017-04-04-00-01.json b/common/changes/general-updates_2017-04-04-00-01.json new file mode 100644 index 00000000000000..f3357cb150962a --- /dev/null +++ b/common/changes/general-updates_2017-04-04-00-01.json @@ -0,0 +1,20 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "In components which expose a public API such as `Dropdown` which implements `IDropdown`, to access the exact interface we've exposed a `componentRef` property on all components. This property replaces typical `ref={ c => this._component = c }` usage, as componentRef is guaranteed to access the public contract of the component regardless of the higher-order component or decorator wrapping it. If you are accessing the public API of a component, replace your `ref` usage with `componentRef`.", + "type": "minor" + }, + { + "packageName": "@uifabric/utilities", + "comment": "BaseComponent: added support for resolving `componentRef` automatically. Also added `_warnDeprecations` and `_warnMutualExclusion` helpers for warning on misuse.", + "type": "minor" + }, + { + "comment": "", + "packageName": "@uifabric/example-app-base", + "type": "none" + } + ], + "email": "dzearing@microsoft.com" +} \ No newline at end of file diff --git a/common/npm-shrinkwrap.json b/common/npm-shrinkwrap.json index 7c342e5ac1144e..0e17c9b01ee353 100644 --- a/common/npm-shrinkwrap.json +++ b/common/npm-shrinkwrap.json @@ -5,14 +5,7 @@ "@microsoft/api-extractor": { "version": "2.0.0", "from": "@microsoft/api-extractor@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-2.0.0.tgz", - "dependencies": { - "typescript": { - "version": "2.2.1", - "from": "typescript@>=2.2.1-0 <3.0.0-0", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.2.1.tgz" - } - } + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-2.0.0.tgz" }, "@microsoft/gulp-core-build": { "version": "2.4.3", @@ -161,11 +154,6 @@ "version": "4.0.1", "from": "tslint-microsoft-contrib@>=4.0.0 <4.1.0", "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-4.0.1.tgz" - }, - "typescript": { - "version": "2.2.1", - "from": "typescript@>=2.2.1 <2.3.0", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.2.1.tgz" } } }, @@ -274,14 +262,14 @@ "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz" }, "@types/cheerio": { - "version": "0.22.0", + "version": "0.22.1", "from": "@types/cheerio@*", - "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.0.tgz" + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.1.tgz" }, "@types/enzyme": { - "version": "2.7.6", + "version": "2.7.7", "from": "@types/enzyme@>=2.7.5 <3.0.0", - "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-2.7.6.tgz" + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-2.7.7.tgz" }, "@types/es6-collections": { "version": "0.5.29", @@ -339,9 +327,9 @@ "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz" }, "@types/react": { - "version": "15.0.20", + "version": "15.0.21", "from": "@types/react@>=15.0.16 <16.0.0", - "resolved": "https://registry.npmjs.org/@types/react/-/react-15.0.20.tgz" + "resolved": "https://registry.npmjs.org/@types/react/-/react-15.0.21.tgz" }, "@types/react-addons-test-utils": { "version": "0.14.17", @@ -389,9 +377,9 @@ "resolved": "https://registry.npmjs.org/@types/z-schema/-/z-schema-3.16.31.tgz" }, "@uifabric/utilities": { - "version": "1.3.0", - "from": "@uifabric/utilities@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-1.3.0.tgz" + "version": "1.4.0", + "from": "@uifabric/utilities@1.4.0", + "resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-1.4.0.tgz" }, "abbrev": { "version": "1.0.9", @@ -757,9 +745,9 @@ "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.0.0.tgz", "dependencies": { "camelcase": { - "version": "4.0.0", + "version": "4.1.0", "from": "camelcase@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz" }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -814,9 +802,9 @@ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz" }, "browserify-sign": { - "version": "4.0.0", + "version": "4.0.4", "from": "browserify-sign@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz" }, "browserify-zlib": { "version": "0.1.4", @@ -891,9 +879,9 @@ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.5.3.tgz" }, "caniuse-db": { - "version": "1.0.30000640", + "version": "1.0.30000649", "from": "caniuse-db@>=1.0.30000488 <2.0.0", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000640.tgz" + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000649.tgz" }, "capture-stack-trace": { "version": "1.0.0", @@ -1233,9 +1221,9 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" }, "convert-source-map": { - "version": "1.4.0", + "version": "1.5.0", "from": "convert-source-map@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz" }, "cookie": { "version": "0.3.1", @@ -1722,9 +1710,9 @@ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.6.tgz" }, "electron-to-chromium": { - "version": "1.2.8", + "version": "1.3.2", "from": "electron-to-chromium@>=1.2.7 <2.0.0", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.8.tgz" + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.2.tgz" }, "elliptic": { "version": "6.4.0", @@ -1815,9 +1803,9 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz" }, "enzyme": { - "version": "2.7.1", + "version": "2.8.0", "from": "enzyme@>=2.7.0 <3.0.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.7.1.tgz", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.8.0.tgz", "dependencies": { "lodash": { "version": "4.17.4", @@ -2095,9 +2083,9 @@ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz" }, "fbjs": { - "version": "0.8.11", + "version": "0.8.12", "from": "fbjs@>=0.8.4 <0.9.0", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.11.tgz", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", "dependencies": { "core-js": { "version": "1.2.7", @@ -3352,9 +3340,9 @@ } }, "interpret": { - "version": "1.0.1", + "version": "1.0.2", "from": "interpret@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.2.tgz" }, "invariant": { "version": "2.2.2", @@ -3367,9 +3355,9 @@ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" }, "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" + "version": "1.3.0", + "from": "ipaddr.js@1.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz" }, "irregular-plurals": { "version": "1.2.0", @@ -3891,9 +3879,9 @@ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz" }, "latest-version": { - "version": "3.0.0", + "version": "3.1.0", "from": "latest-version@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz" }, "lazy-cache": { "version": "1.0.4", @@ -4472,14 +4460,14 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.0.3.tgz" }, "method-override": { - "version": "2.3.7", + "version": "2.3.8", "from": "method-override@>=2.3.5 <2.4.0", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.7.tgz", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.8.tgz", "dependencies": { "debug": { - "version": "2.3.3", - "from": "debug@2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz" + "version": "2.6.3", + "from": "debug@2.6.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz" } } }, @@ -4726,9 +4714,9 @@ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.0.2.tgz" }, "node-sass": { - "version": "4.5.1", + "version": "4.5.2", "from": "node-sass@>=4.2.0 <5.0.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.5.1.tgz", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.5.2.tgz", "dependencies": { "gaze": { "version": "1.1.2", @@ -4763,9 +4751,9 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.6.tgz" }, "normalize-path": { - "version": "2.0.1", + "version": "2.1.1", "from": "normalize-path@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" }, "normalize-range": { "version": "0.1.2", @@ -4870,9 +4858,9 @@ "resolved": "https://registry.npmjs.org/office-ui-fabric-core/-/office-ui-fabric-core-5.1.0.tgz" }, "office-ui-fabric-react": { - "version": "2.7.1", + "version": "2.10.5", "from": "office-ui-fabric-react@>=2.7.1-0 <3.0.0-0", - "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-2.7.1.tgz" + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-2.10.5.tgz" }, "on-finished": { "version": "2.3.0", @@ -4998,9 +4986,9 @@ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz" }, "package-json": { - "version": "3.1.0", - "from": "package-json@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-3.1.0.tgz" + "version": "4.0.0", + "from": "package-json@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.0.tgz" }, "pako": { "version": "0.2.9", @@ -5481,9 +5469,9 @@ "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz" }, "proxy-addr": { - "version": "1.1.3", + "version": "1.1.4", "from": "proxy-addr@>=1.1.3 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz" }, "prr": { "version": "0.0.0", @@ -5566,9 +5554,9 @@ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz" }, "rc": { - "version": "1.1.7", + "version": "1.2.0", "from": "rc@>=1.1.6 <2.0.0", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.7.tgz" + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.0.tgz" }, "react": { "version": "15.4.2", @@ -5713,6 +5701,11 @@ "from": "regjsparser@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz" }, + "remove-trailing-separator": { + "version": "1.0.1", + "from": "remove-trailing-separator@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz" + }, "repeat-element": { "version": "1.1.2", "from": "repeat-element@>=1.1.2 <2.0.0", @@ -5869,11 +5862,6 @@ "version": "3.1.2", "from": "supports-color@3.1.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz" - }, - "typescript": { - "version": "2.2.1", - "from": "typescript@>=2.2.1 <3.0.0", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.2.1.tgz" } } }, @@ -5958,11 +5946,6 @@ "version": "3.1.2", "from": "supports-color@3.1.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz" - }, - "typescript": { - "version": "2.2.1", - "from": "typescript@>=2.2.1 <3.0.0", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.2.1.tgz" } } }, @@ -6014,9 +5997,9 @@ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.3.tgz", "dependencies": { "async": { - "version": "2.1.5", + "version": "2.3.0", "from": "async@>=2.1.5 <3.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.3.0.tgz" }, "loader-utils": { "version": "1.1.0", @@ -6845,9 +6828,9 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz" }, "type-is": { - "version": "1.6.14", + "version": "1.6.15", "from": "type-is@>=1.6.14 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" }, "typedarray": { "version": "0.0.6", @@ -6855,9 +6838,9 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" }, "typescript": { - "version": "2.1.6", - "from": "typescript@>=2.1.0 <2.2.0", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.1.6.tgz" + "version": "2.2.2", + "from": "typescript@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.2.2.tgz" }, "ua-parser-js": { "version": "0.7.12", @@ -6865,9 +6848,9 @@ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz" }, "uglify-js": { - "version": "2.8.16", + "version": "2.8.21", "from": "uglify-js@>=2.6.0 <3.0.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.16.tgz", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.21.tgz", "dependencies": { "camelcase": { "version": "1.2.1", @@ -6994,9 +6977,9 @@ "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" }, "useragent": { - "version": "2.1.12", + "version": "2.1.13", "from": "useragent@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.1.12.tgz", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.1.13.tgz", "dependencies": { "lru-cache": { "version": "2.2.4", @@ -7033,9 +7016,9 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz" }, "v8flags": { - "version": "2.0.11", + "version": "2.0.12", "from": "v8flags@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.11.tgz" + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.12.tgz" }, "vali-date": { "version": "1.0.0", @@ -7196,9 +7179,9 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz" }, "async": { - "version": "2.1.5", + "version": "2.3.0", "from": "async@>=2.1.2 <3.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.3.0.tgz" }, "camelcase": { "version": "3.0.0", diff --git a/common/temp_modules/rush-example-app-base/package.json b/common/temp_modules/rush-example-app-base/package.json index fca0ecd29bdc99..31b37749d84f41 100644 --- a/common/temp_modules/rush-example-app-base/package.json +++ b/common/temp_modules/rush-example-app-base/package.json @@ -22,12 +22,12 @@ "source-map-loader": "0.1.5", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "~2.1.0", + "typescript": "^2.2.2", "highlight.js": "^9.9.0", "office-ui-fabric-core": ">=5.0.0 <6.0.0", "office-ui-fabric-react": ">=2.7.1-0 <3.0.0-0" }, "rushDependencies": { - "@uifabric/utilities": "1.3.0" + "@uifabric/utilities": "1.4.0" } } diff --git a/common/temp_modules/rush-example-component/package.json b/common/temp_modules/rush-example-component/package.json index 52d099761d2faa..1fa01b289ee74e 100644 --- a/common/temp_modules/rush-example-component/package.json +++ b/common/temp_modules/rush-example-component/package.json @@ -27,14 +27,14 @@ "sass-loader": "^6.0.3", "style-loader": "^0.13.2", "ts-loader": "^2.0.1", - "typescript": "^2.2.1", + "typescript": "^2.2.2", "webpack": "^2.2.1", "webpack-dev-server": "^2.4.1", "webpack-notifier": "^1.5.0" }, "rushDependencies": { - "@uifabric/example-app-base": "^1.3.2", - "@uifabric/utilities": "^1.3.0", - "office-ui-fabric-react": ">=2.7.1-0 <3.0.0-0" + "@uifabric/example-app-base": "^1.3.4", + "@uifabric/utilities": "^1.4.0", + "office-ui-fabric-react": "2.10.5" } } diff --git a/common/temp_modules/rush-fabric-website/package.json b/common/temp_modules/rush-fabric-website/package.json index be0e366b6155e6..4333f018c8fa42 100644 --- a/common/temp_modules/rush-fabric-website/package.json +++ b/common/temp_modules/rush-fabric-website/package.json @@ -30,7 +30,7 @@ "source-map-loader": "0.1.5", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "^2.1.5", + "typescript": "^2.2.2", "vinyl-ftp": "0.4.5", "webpack-bundle-analyzer": "^2.2.1", "color-functions": "1.1.0", @@ -39,8 +39,8 @@ "office-ui-fabric-core": "5.1.0" }, "rushDependencies": { - "@uifabric/example-app-base": "^1.3.2", - "office-ui-fabric-react": ">=2.7.1-0 <3.0.0-0", - "@uifabric/utilities": ">=1.2.0 <2.0.0" + "@uifabric/example-app-base": "^1.3.4", + "office-ui-fabric-react": "2.10.5", + "@uifabric/utilities": ">=1.3.0 <2.0.0" } } diff --git a/common/temp_modules/rush-office-ui-fabric-react/package.json b/common/temp_modules/rush-office-ui-fabric-react/package.json index 0743efe252cac6..bc6be86345a18d 100644 --- a/common/temp_modules/rush-office-ui-fabric-react/package.json +++ b/common/temp_modules/rush-office-ui-fabric-react/package.json @@ -41,7 +41,7 @@ "ts-loader": "^2.0.1", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "^2.2.1", + "typescript": "^2.2.2", "vinyl-ftp": "0.4.5", "webpack": "^2.2.1", "webpack-bundle-analyzer": "^2.2.1", @@ -50,7 +50,7 @@ "webpack-split-by-path": "0.0.10" }, "rushDependencies": { - "@uifabric/example-app-base": ">=1.1.0-0 <2.0.0-0", - "@uifabric/utilities": ">=1.2.0-0 <2.0.0-0" + "@uifabric/example-app-base": "1.3.4", + "@uifabric/utilities": "1.4.0" } } diff --git a/common/temp_modules/rush-todo-app/package.json b/common/temp_modules/rush-todo-app/package.json index 55045b15059c34..d1e7794d31c80c 100644 --- a/common/temp_modules/rush-todo-app/package.json +++ b/common/temp_modules/rush-todo-app/package.json @@ -19,9 +19,9 @@ "office-ui-fabric-core": ">=5.1.0 <6.0.0", "react": "^15.4.2", "react-dom": "^15.4.2", - "typescript": "^2.0.6" + "typescript": "^2.2.2" }, "rushDependencies": { - "office-ui-fabric-react": ">=2.7.1 <3.0.0" + "office-ui-fabric-react": ">=2.10.5 <3.0.0" } } diff --git a/common/temp_modules/rush-utilities/package.json b/common/temp_modules/rush-utilities/package.json index 22a8c3b9405755..ce9cdc50b9d030 100644 --- a/common/temp_modules/rush-utilities/package.json +++ b/common/temp_modules/rush-utilities/package.json @@ -22,6 +22,6 @@ "source-map-loader": "0.1.5", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "~2.1.0" + "typescript": "^2.2.2" } } diff --git a/packages/example-app-base/package.json b/packages/example-app-base/package.json index a4e019a76ffcbf..ead079d53db5a2 100644 --- a/packages/example-app-base/package.json +++ b/packages/example-app-base/package.json @@ -34,7 +34,7 @@ "source-map-loader": "0.1.5", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "~2.1.0" + "typescript": "^2.2.2" }, "peerDependencies": { "react": "^0.14 || ^15.0.1-0 || ^16.0.0-0", diff --git a/packages/example-component/package.json b/packages/example-component/package.json index 14e7a26e76c4b1..c7e38f286472c6 100644 --- a/packages/example-component/package.json +++ b/packages/example-component/package.json @@ -38,7 +38,7 @@ "sass-loader": "^6.0.3", "style-loader": "^0.13.2", "ts-loader": "^2.0.1", - "typescript": "^2.2.1", + "typescript": "^2.2.2", "webpack": "^2.2.1", "webpack-dev-server": "^2.4.1", "webpack-notifier": "^1.5.0" diff --git a/packages/office-ui-fabric-react/package.json b/packages/office-ui-fabric-react/package.json index 5fe5902967255c..a2a0c33ca19646 100644 --- a/packages/office-ui-fabric-react/package.json +++ b/packages/office-ui-fabric-react/package.json @@ -56,7 +56,7 @@ "ts-loader": "^2.0.1", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "^2.2.1", + "typescript": "^2.2.2", "vinyl-ftp": "0.4.5", "webpack": "^2.2.1", "webpack-bundle-analyzer": "^2.2.1", diff --git a/packages/office-ui-fabric-react/src/common/StoreHost.tsx b/packages/office-ui-fabric-react/src/common/StoreHost.tsx index f9bb2fc47b011b..75cd19994f96ec 100644 --- a/packages/office-ui-fabric-react/src/common/StoreHost.tsx +++ b/packages/office-ui-fabric-react/src/common/StoreHost.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { StoreSet } from './StoreSet'; +import { BaseComponent } from '../Utilities'; export interface IStoreHostProps extends React.Props { stores?: StoreSet; @@ -9,7 +10,7 @@ export interface IStoreHostContext { stores?: StoreSet; } -export class StoreHost extends React.Component { +export class StoreHost extends BaseComponent { public static contextTypes = { stores: React.PropTypes.object }; diff --git a/packages/office-ui-fabric-react/src/components/Breadcrumb/Breadcrumb.Props.ts b/packages/office-ui-fabric-react/src/components/Breadcrumb/Breadcrumb.Props.ts index 2e82caf3fa1307..f7699bbd54c36e 100644 --- a/packages/office-ui-fabric-react/src/components/Breadcrumb/Breadcrumb.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Breadcrumb/Breadcrumb.Props.ts @@ -4,7 +4,16 @@ import * as React from 'react'; import { Breadcrumb } from './Breadcrumb'; import { IRenderFunction } from '../../Utilities'; +export interface IBreadcrumb { + +} + export interface IBreadcrumbProps extends React.Props { + /** + * Optional callback to access the IBreadcrumb interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IBreadcrumb) => void; /** * Collection of breadcrumbs to render diff --git a/packages/office-ui-fabric-react/src/components/Button/BaseButton.tsx b/packages/office-ui-fabric-react/src/components/Button/BaseButton.tsx index 7ac15c291308ee..f2fe19c377c273 100644 --- a/packages/office-ui-fabric-react/src/components/Button/BaseButton.tsx +++ b/packages/office-ui-fabric-react/src/components/Button/BaseButton.tsx @@ -46,7 +46,10 @@ export class BaseButton extends BaseComponent im private _ariaDescriptionId: string; constructor(props: IButtonProps, rootClassName: string, deprecationMap: any) { - super(props, { 'rootProps': null }); + super(props); + + this._warnDeprecations({ 'rootProps': null }); + this._labelId = getId(); this._descriptionId = getId(); this._ariaDescriptionId = getId(); diff --git a/packages/office-ui-fabric-react/src/components/Button/Button.Props.ts b/packages/office-ui-fabric-react/src/components/Button/Button.Props.ts index a8c1f7b8dc2626..6e1b537ca2400c 100644 --- a/packages/office-ui-fabric-react/src/components/Button/Button.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Button/Button.Props.ts @@ -12,6 +12,12 @@ export interface IButton { } export interface IButtonProps extends React.HTMLProps { + /** + * Optional callback to access the IButton interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IButton) => void; + /** * If provided, this component will be rendered as an anchor. * @default ElementType.anchor diff --git a/packages/office-ui-fabric-react/src/components/Calendar/Calendar.Props.ts b/packages/office-ui-fabric-react/src/components/Calendar/Calendar.Props.ts index 18733b2fd9e573..32fba268bc7a1a 100644 --- a/packages/office-ui-fabric-react/src/components/Calendar/Calendar.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Calendar/Calendar.Props.ts @@ -6,10 +6,16 @@ export { DayOfWeek, DateRangeType } export interface ICalendar { /** Sets focus to the selected date. */ - focus(): void; + focus: () => void; } export interface ICalendarProps extends React.Props { + /** + * Optional callback to access the ICalendar interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ICalendar) => void; + /** * Callback issued when a date is selected * @param date - The date the user selected diff --git a/packages/office-ui-fabric-react/src/components/Calendar/CalendarMonth.tsx b/packages/office-ui-fabric-react/src/components/Calendar/CalendarMonth.tsx index 48caf3791c7849..e5c580f088b1a7 100644 --- a/packages/office-ui-fabric-react/src/components/Calendar/CalendarMonth.tsx +++ b/packages/office-ui-fabric-react/src/components/Calendar/CalendarMonth.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, KeyCodes, css, getRTL @@ -15,7 +16,7 @@ export interface ICalendarMonthProps { onNavigateDate: (date: Date, focusOnNavigatedDay: boolean) => void; } -export class CalendarMonth extends React.Component { +export class CalendarMonth extends BaseComponent { private _selectMonthCallbacks: (() => void)[]; public constructor(props: ICalendarMonthProps) { diff --git a/packages/office-ui-fabric-react/src/components/Callout/Callout.Props.ts b/packages/office-ui-fabric-react/src/components/Callout/Callout.Props.ts index 5622590bb03c50..e0d22677b77f2c 100644 --- a/packages/office-ui-fabric-react/src/components/Callout/Callout.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Callout/Callout.Props.ts @@ -7,7 +7,16 @@ import { IRectangle } from '../../Utilities'; +export interface ICallout { + +} + export interface ICalloutProps extends React.Props { + /** + * Optional callback to access the ICallout interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ICallout) => void; /** * The target that the Callout should try to position itself based on. diff --git a/packages/office-ui-fabric-react/src/components/Callout/CalloutContent.tsx b/packages/office-ui-fabric-react/src/components/Callout/CalloutContent.tsx index ffecd1fffe808b..82a9c4e24a59ac 100644 --- a/packages/office-ui-fabric-react/src/components/Callout/CalloutContent.tsx +++ b/packages/office-ui-fabric-react/src/components/Callout/CalloutContent.tsx @@ -49,7 +49,9 @@ export class CalloutContent extends BaseComponent private _target: HTMLElement | MouseEvent; constructor(props: ICalloutProps) { - super(props, { 'beakStyle': 'beakWidth' }); + super(props); + + this._warnDeprecations({ 'beakStyle': 'beakWidth' }); this._didSetInitialFocus = false; this.state = { diff --git a/packages/office-ui-fabric-react/src/components/Check/Check.tsx b/packages/office-ui-fabric-react/src/components/Check/Check.tsx index 591dfe6e6f1a1d..90cdcb39ed6626 100644 --- a/packages/office-ui-fabric-react/src/components/Check/Check.tsx +++ b/packages/office-ui-fabric-react/src/components/Check/Check.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { css } from '../../Utilities'; +import { BaseComponent, css } from '../../Utilities'; import styles = require('./Check.scss'); export interface ICheckProps extends React.Props { @@ -15,7 +15,7 @@ export interface ICheckProps extends React.Props { isChecked?: boolean; } -export class Check extends React.Component { +export class Check extends BaseComponent { public static defaultProps = { isChecked: false }; diff --git a/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.Props.ts b/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.Props.ts index 85b1c3b98ac96c..97224334d7e7e2 100644 --- a/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.Props.ts @@ -8,13 +8,19 @@ export interface ICheckbox { checked: boolean; /** Sets focus to the checkbox. */ - focus(): void; + focus: () => void; } /** * Checkbox properties. */ export interface ICheckboxProps extends React.HTMLProps { + /** + * Optional callback to access the ICheckbox interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ICheckbox) => void; + /** * Additional class name to provide on the root element, in addition to the ms-Checkbox class. */ diff --git a/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.tsx b/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.tsx index e6a0d343536c54..922bc080ea9dd2 100644 --- a/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.tsx +++ b/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.tsx @@ -29,6 +29,10 @@ export class Checkbox extends BaseComponent impl constructor(props: ICheckboxProps) { super(props); + this._warnMutuallyExclusive({ + 'checked': 'defaultChecked' + }); + this._id = getId('checkbox-'); this.state = { isFocused: false, @@ -95,7 +99,7 @@ export class Checkbox extends BaseComponent impl return this._checkBox ? this._checkBox.checked : false; } - public focus() { + public focus(): void { if (this._checkBox) { this._checkBox.focus(); } diff --git a/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.Props.ts b/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.Props.ts index a89e02a2a5390f..54b2a580eb16c1 100644 --- a/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.Props.ts +++ b/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.Props.ts @@ -1,7 +1,17 @@ import * as React from 'react'; import { IIconProps } from '../../Icon'; +export interface IChoiceGroup { + +} + export interface IChoiceGroupProps extends React.HTMLProps { + /** + * Optional callback to access the IChoiceGroup interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IChoiceGroup) => void; + /** * The options for the choice group. */ diff --git a/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.tsx b/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.tsx index 882648b49bb028..d4e0af4c78d031 100644 --- a/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.tsx +++ b/packages/office-ui-fabric-react/src/components/ChoiceGroup/ChoiceGroup.tsx @@ -27,7 +27,13 @@ export class ChoiceGroup extends BaseComponent { +export class ColorPicker extends BaseComponent { constructor(props: IColorPickerProps) { super(props); diff --git a/packages/office-ui-fabric-react/src/components/ColorPicker/ColorRectangle.tsx b/packages/office-ui-fabric-react/src/components/ColorPicker/ColorRectangle.tsx index 461aedad969f47..b7e0bcd8c4a527 100644 --- a/packages/office-ui-fabric-react/src/components/ColorPicker/ColorRectangle.tsx +++ b/packages/office-ui-fabric-react/src/components/ColorPicker/ColorRectangle.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { - EventGroup, + BaseComponent, assign, autobind, css @@ -28,7 +28,7 @@ export interface IColorPickerState { fullColorString?: string; } -export class ColorRectangle extends React.Component { +export class ColorRectangle extends BaseComponent { public static defaultProps = { minSize: 220 }; @@ -38,15 +38,11 @@ export class ColorRectangle extends React.Component { +export class ColorSlider extends BaseComponent { public static defaultProps = { minValue: 0, maxValue: 100, @@ -37,15 +37,11 @@ export class ColorSlider extends React.Component { + /** + * Optional callback to access the ICommandBar interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ICommandBar) => void; + /** * Whether or not the search box is visible * @defaultvalue false diff --git a/packages/office-ui-fabric-react/src/components/CommandBar/CommandBar.tsx b/packages/office-ui-fabric-react/src/components/CommandBar/CommandBar.tsx index 786dc5909499f4..c3663034caedb5 100644 --- a/packages/office-ui-fabric-react/src/components/CommandBar/CommandBar.tsx +++ b/packages/office-ui-fabric-react/src/components/CommandBar/CommandBar.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { - EventGroup, + BaseComponent, autobind, buttonProperties, css, @@ -32,7 +32,7 @@ export interface ICommandBarState { renderedFarItems?: IContextualMenuItem[]; } -export class CommandBar extends React.Component implements ICommandBar { +export class CommandBar extends BaseComponent implements ICommandBar { public static defaultProps = { items: [], overflowItems: [], @@ -51,7 +51,6 @@ export class CommandBar extends React.Component { + /** + * Optional callback to access the IContextualMenu interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IContextualMenu) => void; /** * The target that the ContextualMenu should try to position itself based on. diff --git a/packages/office-ui-fabric-react/src/components/DatePicker/DatePicker.Props.ts b/packages/office-ui-fabric-react/src/components/DatePicker/DatePicker.Props.ts index 975b7513a1b887..a2608b8be4568e 100644 --- a/packages/office-ui-fabric-react/src/components/DatePicker/DatePicker.Props.ts +++ b/packages/office-ui-fabric-react/src/components/DatePicker/DatePicker.Props.ts @@ -2,7 +2,17 @@ import * as React from 'react'; import { DatePicker } from './DatePicker'; import { DayOfWeek } from '../../Calendar'; +export interface IDatePicker { + +} + export interface IDatePickerProps extends React.Props { + /** + * Optional callback to access the IDatePicker interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IDatePicker) => void; + /** * Callback issued when a date is selected */ diff --git a/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.Props.ts b/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.Props.ts index 0b8f9d8b27d633..a072ca36c4f588 100644 --- a/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.Props.ts +++ b/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.Props.ts @@ -27,6 +27,12 @@ export interface IDetailsList { } export interface IDetailsListProps extends React.Props { + /** + * Optional callback to access the IDetailsList interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IDetailsList) => void; + /** A key that uniquely identifies the given items. If provided, the selection will be reset when the key changes. */ setKey?: string; diff --git a/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.tsx b/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.tsx index 5806874f8aad50..48ce4981f26e1e 100644 --- a/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.tsx +++ b/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { - EventGroup, + BaseComponent, KeyCodes, assign, autobind, @@ -52,7 +52,7 @@ const DEFAULT_RENDERED_WINDOWS_AHEAD = 2; const DEFAULT_RENDERED_WINDOWS_BEHIND = 2; @withViewport -export class DetailsList extends React.Component implements IDetailsList { +export class DetailsList extends BaseComponent implements IDetailsList { public static defaultProps = { layoutMode: DetailsListLayoutMode.justified, selectionMode: SelectionMode.multiple, @@ -71,7 +71,6 @@ export class DetailsList extends React.Component { +export class DetailsRow extends BaseComponent { public refs: { [key: string]: React.ReactInstance, root: HTMLElement, cellMeasurer: HTMLElement }; - private _events: EventGroup; private _hasSetFocus: boolean; private _droppingClassNames: string; private _hasMounted: boolean; @@ -83,7 +82,6 @@ export class DetailsRow extends React.Component { +export class DetailsRowFields extends BaseComponent { constructor(props: IDetailsRowFieldsProps) { super(); diff --git a/packages/office-ui-fabric-react/src/components/Dialog/Dialog.Props.ts b/packages/office-ui-fabric-react/src/components/Dialog/Dialog.Props.ts index 8b3676d776f42c..14c74ed7e7280b 100644 --- a/packages/office-ui-fabric-react/src/components/Dialog/Dialog.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Dialog/Dialog.Props.ts @@ -4,7 +4,17 @@ import { IButtonProps } from '../Button/Button.Props'; import { IWithResponsiveModeState } from '../../utilities/decorators/withResponsiveMode'; import { IAccessiblePopupProps } from '../../common/IAccessiblePopupProps'; +export interface IDialog { + +} + export interface IDialogProps extends React.Props, IWithResponsiveModeState, IAccessiblePopupProps { + /** + * Optional callback to access the IDialog interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IDialog) => void; + /** * Whether the dialog is displayed. * @default false diff --git a/packages/office-ui-fabric-react/src/components/Dialog/DialogFooter.tsx b/packages/office-ui-fabric-react/src/components/Dialog/DialogFooter.tsx index 8b11efe7cccf9b..1ecb1d720285ee 100644 --- a/packages/office-ui-fabric-react/src/components/Dialog/DialogFooter.tsx +++ b/packages/office-ui-fabric-react/src/components/Dialog/DialogFooter.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; -import { css } from '../../Utilities'; +import { BaseComponent, css } from '../../Utilities'; import styles = require('./Dialog.scss'); -export class DialogFooter extends React.Component { +export class DialogFooter extends BaseComponent { public render() { return (
diff --git a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.Props.ts b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.Props.ts index c5133483c252fd..bb2e3a18fc32e9 100644 --- a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.Props.ts +++ b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.Props.ts @@ -9,7 +9,17 @@ import { PersonaInitialsColor } from '../../Persona'; import { ImageFit } from '../../Image'; import { IButtonProps } from '../../Button'; +export interface IDocumentCard { + +} + export interface IDocumentCardProps extends React.Props { + /** + * Optional callback to access the IDocumentCard interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IDocumentCard) => void; + /** * The type of DocumentCard to display. * @default DocumentCardType.normal diff --git a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.tsx b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.tsx index 96fe3ae7dfd74e..22fcc97b85d38b 100644 --- a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.tsx +++ b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCard.tsx @@ -1,13 +1,14 @@ import * as React from 'react'; import { IDocumentCardProps, DocumentCardType } from './DocumentCard.Props'; import { + BaseComponent, + KeyCodes, autobind, - css, - KeyCodes + css } from '../../Utilities'; import styles = require('./DocumentCard.scss'); -export class DocumentCard extends React.Component { +export class DocumentCard extends BaseComponent { public static defaultProps: IDocumentCardProps = { type: DocumentCardType.normal }; diff --git a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActions.tsx b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActions.tsx index 9c41f1c8bf746c..41365c4ea0cabf 100644 --- a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActions.tsx +++ b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActions.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; -import { css } from '../../Utilities'; +import { BaseComponent, css } from '../../Utilities'; import { IDocumentCardActionsProps } from './DocumentCard.Props'; import { Button, ButtonType } from '../../Button'; import styles = require('./DocumentCard.scss'); -export class DocumentCardActions extends React.Component { +export class DocumentCardActions extends BaseComponent { public render() { let { actions, views } = this.props; diff --git a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActivity.tsx b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActivity.tsx index f29fd1f39c5239..c5fcf0e2cfa0d7 100644 --- a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActivity.tsx +++ b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardActivity.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; -import { css } from '../../Utilities'; +import { BaseComponent, css } from '../../Utilities'; import { IDocumentCardActivityProps, IDocumentCardActivityPerson } from './DocumentCard.Props'; import { Persona, PersonaSize } from '../../Persona'; import styles = require('./DocumentCard.scss'); -export class DocumentCardActivity extends React.Component { +export class DocumentCardActivity extends BaseComponent { public render() { let { activity, people } = this.props; diff --git a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardLocation.tsx b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardLocation.tsx index 71b5bdbeb731ce..56ac68eb4ca9ec 100644 --- a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardLocation.tsx +++ b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardLocation.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; -import { css } from '../../Utilities'; +import { BaseComponent, css } from '../../Utilities'; import { IDocumentCardLocationProps } from './DocumentCard.Props'; import styles = require('./DocumentCard.scss'); -export class DocumentCardLocation extends React.Component { +export class DocumentCardLocation extends BaseComponent { public render() { let { location, locationHref, ariaLabel, onClick } = this.props; diff --git a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardPreview.tsx b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardPreview.tsx index 18af7712a01677..abb81ac983a748 100644 --- a/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardPreview.tsx +++ b/packages/office-ui-fabric-react/src/components/DocumentCard/DocumentCardPreview.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { IDocumentCardPreviewProps, IDocumentCardPreviewImage } from './DocumentCard.Props'; import { Image } from '../../Image'; import { + BaseComponent, autobind, css } from '../../Utilities'; @@ -9,7 +10,7 @@ import styles = require('./DocumentCard.scss'); const LIST_ITEM_COUNT = 3; -export class DocumentCardPreview extends React.Component { +export class DocumentCardPreview extends BaseComponent { public render() { let { previewImages } = this.props; let style, preview; diff --git a/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.Props.ts b/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.Props.ts index f074db7c9f1910..c27664a411c89a 100644 --- a/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.Props.ts @@ -2,11 +2,21 @@ import * as React from 'react'; import { IRenderFunction } from '../../Utilities'; import { Dropdown } from './Dropdown'; +export interface IDropdown { + +} + export interface IDropdownProps extends React.Props { + /** + * Optional callback to access the IDropdown interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IDropdown) => void; + /** * Descriptive label for the Dropdown */ - label: string; + label?: string; /** * Aria Label for the Dropdown for screen reader users. diff --git a/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.tsx b/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.tsx index 5185becd50299a..9b95b636a5c9e8 100644 --- a/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.tsx +++ b/packages/office-ui-fabric-react/src/components/Dropdown/Dropdown.tsx @@ -49,7 +49,9 @@ export class Dropdown extends BaseComponent, IFabricState> { +export class Fabric extends BaseComponent, IFabricState> { public refs: { [key: string]: React.ReactInstance; root: HTMLElement; }; - private _events: EventGroup; - constructor() { super(); this.state = { isFocusVisible: _lastIsFocusVisible }; - - this._events = new EventGroup(this); } public componentDidMount() { @@ -53,10 +49,6 @@ export class Fabric extends React.Component, IFa this._events.on(document.body, 'keydown', this._onKeyDown, true); } - public componentWillUnmount() { - this._events.dispose(); - } - public render() { const { isFocusVisible } = this.state; const rootClass = css('ms-Fabric ms-font-m', this.props.className, { diff --git a/packages/office-ui-fabric-react/src/components/Facepile/Facepile.Props.ts b/packages/office-ui-fabric-react/src/components/Facepile/Facepile.Props.ts index a4c87ab6610e4a..0ce8ddc139738b 100644 --- a/packages/office-ui-fabric-react/src/components/Facepile/Facepile.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Facepile/Facepile.Props.ts @@ -7,7 +7,17 @@ import { PersonaSize } from '../Persona/index'; +export interface IFacepile { + +} + export interface IFacepileProps extends React.Props { + /** + * Optional callback to access the IFacepile interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IFacepile) => void; + /** * Array of IPersonaProps that define each Persona. Note that the size * is fixed at PersonaSize.extraSmall regardless of what is specified. diff --git a/packages/office-ui-fabric-react/src/components/Facepile/Facepile.tsx b/packages/office-ui-fabric-react/src/components/Facepile/Facepile.tsx index 101f15e835d238..06ae757e504e15 100644 --- a/packages/office-ui-fabric-react/src/components/Facepile/Facepile.tsx +++ b/packages/office-ui-fabric-react/src/components/Facepile/Facepile.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, buttonProperties, css, divProperties, @@ -23,7 +24,7 @@ import { } from '../../Persona'; import styles = require('./Facepile.scss'); -export class Facepile extends React.Component { +export class Facepile extends BaseComponent { public static defaultProps: IFacepileProps = { maxDisplayablePersonas: 5, personas: [], diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.Props.ts b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.Props.ts index 34e02a28a3b6d2..14905c8b238c55 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.Props.ts +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.Props.ts @@ -8,6 +8,12 @@ export interface IFocusTrapZone { } export interface IFocusTrapZoneProps extends React.HTMLProps { + /** + * Optional callback to access the IFocusTrapZone interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IFocusTrapZone) => void; + /** * Sets the HTMLElement to focus on when exiting the FocusTrapZone. * @default The element.target that triggered the FTZ. @@ -31,14 +37,14 @@ export interface IFocusTrapZoneProps extends React.HTMLProps { */ ignoreExternalFocusing?: boolean; - /** - * Indicates whether focus trap zone should force focus inside the focus trap zone - * @default true - */ + /** + * Indicates whether focus trap zone should force focus inside the focus trap zone + * @default true + */ forceFocusInsideTrap?: boolean; - /** - * Indicates the selector for first focusable item - */ + /** + * Indicates the selector for first focusable item + */ firstFocusableSelector?: string; } diff --git a/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.Props.ts b/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.Props.ts index 7ef91d7adb4e10..5b0580078e6771 100644 --- a/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.Props.ts +++ b/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.Props.ts @@ -25,6 +25,12 @@ export interface IFocusZone { * FocusZone component props. */ export interface IFocusZoneProps extends React.HTMLProps { + /** + * Optional callback to access the IFocusZone interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IFocusZone) => void; + /** * Additional class name to provide on the root element, in addition to the ms-FocusZone class. */ diff --git a/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.tsx b/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.tsx index 7684d71ee0f565..e7da9a643bb8ea 100644 --- a/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusZone/FocusZone.tsx @@ -56,7 +56,9 @@ export class FocusZone extends BaseComponent implements IFo private _isInnerZone: boolean; constructor(props) { - super(props, { 'rootProps': null }); + super(props); + + this._warnDeprecations({ 'rootProps': null }); this._id = getId('FocusZone'); _allInstances[this._id] = this; diff --git a/packages/office-ui-fabric-react/src/components/GroupedList/GroupHeader.tsx b/packages/office-ui-fabric-react/src/components/GroupedList/GroupHeader.tsx index ce3aacb91748dc..4257ed2294104a 100644 --- a/packages/office-ui-fabric-react/src/components/GroupedList/GroupHeader.tsx +++ b/packages/office-ui-fabric-react/src/components/GroupedList/GroupHeader.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, autobind, css } from '../../Utilities'; @@ -17,7 +18,7 @@ export interface IGroupHeaderState { isLoadingVisible: boolean; } -export class GroupHeader extends React.Component { +export class GroupHeader extends BaseComponent { constructor(props: IGroupDividerProps) { super(props); diff --git a/packages/office-ui-fabric-react/src/components/GroupedList/GroupedList.Props.ts b/packages/office-ui-fabric-react/src/components/GroupedList/GroupedList.Props.ts index 3c92500d190e6f..a7a42e060c6923 100644 --- a/packages/office-ui-fabric-react/src/components/GroupedList/GroupedList.Props.ts +++ b/packages/office-ui-fabric-react/src/components/GroupedList/GroupedList.Props.ts @@ -32,6 +32,12 @@ export interface IGroupedList { } export interface IGroupedListProps extends React.Props { + /** + * Optional callback to access the IGroupedList interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IGroupedList) => void; + /** Optional class name to add to the root element. */ className?: string; diff --git a/packages/office-ui-fabric-react/src/components/Image/Image.Props.ts b/packages/office-ui-fabric-react/src/components/Image/Image.Props.ts index b0d9a25e81b4e5..869628449bffd7 100644 --- a/packages/office-ui-fabric-react/src/components/Image/Image.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Image/Image.Props.ts @@ -1,6 +1,16 @@ import * as React from 'react'; +export interface IImage { + +} + export interface IImageProps extends React.HTMLProps { + /** + * Optional callback to access the ICheckbox interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IImage) => void; + /** * If true, fades the image in when loaded. * @defaultvalue false; diff --git a/packages/office-ui-fabric-react/src/components/Label/Label.Props.ts b/packages/office-ui-fabric-react/src/components/Label/Label.Props.ts index b62fffd52c6071..71c733f8d479fd 100644 --- a/packages/office-ui-fabric-react/src/components/Label/Label.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Label/Label.Props.ts @@ -2,7 +2,17 @@ import * as React from 'react'; /* tslint:enable:no-unused-variable */ +export interface ILabel { + +} + export interface ILabelProps extends React.HTMLProps { + /** + * Optional callback to access the ILabel interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ILabel) => void; + /** * Whether the associated form field is required or not * @defaultvalue false diff --git a/packages/office-ui-fabric-react/src/components/Label/Label.tsx b/packages/office-ui-fabric-react/src/components/Label/Label.tsx index 6c8ced6af013ac..2ee304beb5b030 100644 --- a/packages/office-ui-fabric-react/src/components/Label/Label.tsx +++ b/packages/office-ui-fabric-react/src/components/Label/Label.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; -import { css, divProperties, getNativeProps } from '../../Utilities'; +import { BaseComponent, css, divProperties, getNativeProps } from '../../Utilities'; import { ILabelProps } from './Label.Props'; import styles = require('./Label.scss'); -export class Label extends React.Component { +export class Label extends BaseComponent { public render() { let { disabled, required, children, className } = this.props; diff --git a/packages/office-ui-fabric-react/src/components/Layer/Layer.Props.ts b/packages/office-ui-fabric-react/src/components/Layer/Layer.Props.ts index 00820c684f83f4..3671781df3343f 100644 --- a/packages/office-ui-fabric-react/src/components/Layer/Layer.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Layer/Layer.Props.ts @@ -1,7 +1,17 @@ import * as React from 'react'; import { Layer } from './Layer'; +export interface ILayer { + +} + export interface ILayerProps extends React.HTMLProps { + /** + * Optional callback to access the ILayer interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ILayer) => void; + /** Callback for when the layer is mounted. */ onLayerMounted?: () => void; diff --git a/packages/office-ui-fabric-react/src/components/Layer/Layer.tsx b/packages/office-ui-fabric-react/src/components/Layer/Layer.tsx index 6944456ab81f65..8304ed64d5334e 100644 --- a/packages/office-ui-fabric-react/src/components/Layer/Layer.tsx +++ b/packages/office-ui-fabric-react/src/components/Layer/Layer.tsx @@ -32,8 +32,9 @@ export class Layer extends BaseComponent { } constructor(props: ILayerProps) { - super(props, { - // Make sure to deprecate old properties. + super(props); + + this._warnDeprecations({ 'onLayerMounted': 'onLayerDidMount' }); diff --git a/packages/office-ui-fabric-react/src/components/Layer/LayerHost.Props.ts b/packages/office-ui-fabric-react/src/components/Layer/LayerHost.Props.ts index b57ab0bf95a6d6..fa539655ff7fcc 100644 --- a/packages/office-ui-fabric-react/src/components/Layer/LayerHost.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Layer/LayerHost.Props.ts @@ -1,6 +1,16 @@ import * as React from 'react'; +export interface ILayerHost { + +} + export interface ILayerHostProps extends React.HTMLProps { + /** + * Optional callback to access the ILayerHost interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ILayerHost) => void; + /** * Defines the id for the layer host that Layers can target (using the hostId property.) */ diff --git a/packages/office-ui-fabric-react/src/components/Link/Link.Props.ts b/packages/office-ui-fabric-react/src/components/Link/Link.Props.ts index eb5c94b0256ac5..2ee4575f686765 100644 --- a/packages/office-ui-fabric-react/src/components/Link/Link.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Link/Link.Props.ts @@ -9,6 +9,12 @@ export interface ILink { } export interface ILinkProps extends React.HTMLProps { + /** + * Optional callback to access the ILink interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ILink) => void; + /** * Whether the link is disabled */ diff --git a/packages/office-ui-fabric-react/src/components/List/List.Props.ts b/packages/office-ui-fabric-react/src/components/List/List.Props.ts index 7159488b125373..0ccd6ee1680607 100644 --- a/packages/office-ui-fabric-react/src/components/List/List.Props.ts +++ b/packages/office-ui-fabric-react/src/components/List/List.Props.ts @@ -2,7 +2,17 @@ import * as React from 'react'; import { IRectangle } from '../../Utilities'; import { List } from './List'; +export interface IList { + +} + export interface IListProps extends React.HTMLProps { + /** + * Optional callback to access the IList interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IList) => void; + /** Optional classname to append to root list. */ className?: string; diff --git a/packages/office-ui-fabric-react/src/components/MarqueeSelection/MarqueeSelection.Props.ts b/packages/office-ui-fabric-react/src/components/MarqueeSelection/MarqueeSelection.Props.ts index cfea80ab96c9b0..91f8ec729dbab3 100644 --- a/packages/office-ui-fabric-react/src/components/MarqueeSelection/MarqueeSelection.Props.ts +++ b/packages/office-ui-fabric-react/src/components/MarqueeSelection/MarqueeSelection.Props.ts @@ -2,7 +2,17 @@ import * as React from 'react'; import { ISelection } from '../../utilities/selection/interfaces'; import { MarqueeSelection } from './MarqueeSelection'; +export interface IMarqueeSelection { + +} + export interface IMarqueeSelectionProps extends React.Props { + /** + * Optional callback to access the IMarqueeSelection interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IMarqueeSelection) => void; + /** * The selection object to interact with when updating selection changes. */ diff --git a/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.Props.ts b/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.Props.ts index 1aa4655e798526..5a23bf5b48cba3 100644 --- a/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.Props.ts +++ b/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.Props.ts @@ -1,6 +1,15 @@ import * as React from 'react'; +export interface IMessageBar { + +} + export interface IMessageBarProps extends React.HTMLProps { + /** + * Optional callback to access the IMessageBar interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IMessageBar) => void; /** * The type of MessageBar to render. @@ -32,9 +41,9 @@ export interface IMessageBarProps extends React.HTMLProps { */ isMultiline?: boolean; - /** - * Aria label on dismiss button if onDismiss is defined. - */ + /** + * Aria label on dismiss button if onDismiss is defined. + */ dismissButtonAriaLabel?: string; } diff --git a/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.tsx b/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.tsx index 5adc0b7c270dc1..b3055e51ab8ba9 100644 --- a/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.tsx +++ b/packages/office-ui-fabric-react/src/components/MessageBar/MessageBar.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, DelayedRender, css, getId @@ -13,7 +14,7 @@ export interface IMessageBarState { showContent?: boolean; } -export class MessageBar extends React.Component { +export class MessageBar extends BaseComponent { public static defaultProps: IMessageBarProps = { messageBarType: MessageBarType.info, diff --git a/packages/office-ui-fabric-react/src/components/Nav/Nav.Props.ts b/packages/office-ui-fabric-react/src/components/Nav/Nav.Props.ts index 1a0b1225537b78..12bb788fd3d112 100644 --- a/packages/office-ui-fabric-react/src/components/Nav/Nav.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Nav/Nav.Props.ts @@ -11,6 +11,12 @@ export interface INav { } export interface INavProps { + /** + * Optional callback to access the INav interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: INav) => void; + /** * A collection of link groups to display in the navigation bar */ diff --git a/packages/office-ui-fabric-react/src/components/Nav/Nav.tsx b/packages/office-ui-fabric-react/src/components/Nav/Nav.tsx index 3baf0dee5849e5..a975e558af53e2 100644 --- a/packages/office-ui-fabric-react/src/components/Nav/Nav.tsx +++ b/packages/office-ui-fabric-react/src/components/Nav/Nav.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, css, getRTL } from '../../Utilities'; @@ -30,7 +31,7 @@ export interface INavState { selectedKey?: string; } -export class Nav extends React.Component implements INav { +export class Nav extends BaseComponent implements INav { public static defaultProps: INavProps = { groups: null, diff --git a/packages/office-ui-fabric-react/src/components/Overlay/Overlay.Props.ts b/packages/office-ui-fabric-react/src/components/Overlay/Overlay.Props.ts index 2b4d2a5636ccab..3796783c3aba08 100644 --- a/packages/office-ui-fabric-react/src/components/Overlay/Overlay.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Overlay/Overlay.Props.ts @@ -1,6 +1,16 @@ import * as React from 'react'; +export interface IOverlay { + +} + export interface IOverlayProps extends React.HTMLProps { + /** + * Optional callback to access the IOverlay interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IOverlay) => void; + /** * Whether to use the dark-themed overlay. * @defaultvalue false diff --git a/packages/office-ui-fabric-react/src/components/Overlay/Overlay.tsx b/packages/office-ui-fabric-react/src/components/Overlay/Overlay.tsx index bb78fbc7002685..fff54ce1e33996 100644 --- a/packages/office-ui-fabric-react/src/components/Overlay/Overlay.tsx +++ b/packages/office-ui-fabric-react/src/components/Overlay/Overlay.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, css, getNativeProps, divProperties, @@ -10,7 +11,7 @@ import { IOverlayProps } from './Overlay.Props'; import styles = require('./Overlay.scss'); -export class Overlay extends React.Component { +export class Overlay extends BaseComponent { public componentDidMount() { disableBodyScroll(); diff --git a/packages/office-ui-fabric-react/src/components/Panel/Panel.Props.ts b/packages/office-ui-fabric-react/src/components/Panel/Panel.Props.ts index 789b34686da5e9..5177cc511314a8 100644 --- a/packages/office-ui-fabric-react/src/components/Panel/Panel.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Panel/Panel.Props.ts @@ -3,7 +3,15 @@ import { Panel } from './Panel'; import { IRenderFunction } from '../../Utilities'; import { ILayerProps } from '../../Layer'; +export interface IPanel { + +} export interface IPanelProps extends React.Props { + /** + * Optional callback to access the IPanel interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IPanel) => void; /** * Whether the panel is displayed. diff --git a/packages/office-ui-fabric-react/src/components/Persona/Persona.Props.ts b/packages/office-ui-fabric-react/src/components/Persona/Persona.Props.ts index 908876b6d5ecfe..34309d0e5979e0 100644 --- a/packages/office-ui-fabric-react/src/components/Persona/Persona.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Persona/Persona.Props.ts @@ -2,7 +2,17 @@ import * as React from 'react'; import { IRenderFunction } from '../../Utilities'; import { Persona } from './Persona'; +export interface IPersona { + +} + export interface IPersonaProps extends React.HTMLProps { + /** + * Optional callback to access the IPersona interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IPersona) => void; + /** * Primary text to display, usually the name of the person. */ diff --git a/packages/office-ui-fabric-react/src/components/Persona/Persona.tsx b/packages/office-ui-fabric-react/src/components/Persona/Persona.tsx index ce86b34c2970e6..3fd640b991669b 100644 --- a/packages/office-ui-fabric-react/src/components/Persona/Persona.tsx +++ b/packages/office-ui-fabric-react/src/components/Persona/Persona.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, autobind, css, divProperties, @@ -47,7 +48,7 @@ export interface IPersonaState { isImageLoaded?: boolean; } -export class Persona extends React.Component { +export class Persona extends BaseComponent { public static defaultProps: IPersonaProps = { primaryText: '', size: PersonaSize.regular, diff --git a/packages/office-ui-fabric-react/src/components/Pivot/Pivot.Props.ts b/packages/office-ui-fabric-react/src/components/Pivot/Pivot.Props.ts index 7a1698d8acecc4..e6dcf8c72a510e 100644 --- a/packages/office-ui-fabric-react/src/components/Pivot/Pivot.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Pivot/Pivot.Props.ts @@ -3,7 +3,17 @@ import * as React from 'react'; import { Pivot } from './Pivot'; import { PivotItem } from './PivotItem'; +export interface IPivot { + +} + export interface IPivotProps extends React.Props { + /** + * Optional callback to access the IPivot interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IPivot) => void; + /** * The index of the pivot item initially selected. * diff --git a/packages/office-ui-fabric-react/src/components/Pivot/Pivot.tsx b/packages/office-ui-fabric-react/src/components/Pivot/Pivot.tsx index 1c6323cc5fcfb7..48c0bd4ed4ee62 100644 --- a/packages/office-ui-fabric-react/src/components/Pivot/Pivot.tsx +++ b/packages/office-ui-fabric-react/src/components/Pivot/Pivot.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, KeyCodes, css, getId, @@ -36,7 +37,7 @@ export interface IPivotState { selectedTabId: string; } -export class Pivot extends React.Component { +export class Pivot extends BaseComponent { private _keyToIndexMapping: { [key: string]: number }; private _keyToTabIds: { [key: string]: string }; private _pivotId: string; diff --git a/packages/office-ui-fabric-react/src/components/Pivot/PivotItem.tsx b/packages/office-ui-fabric-react/src/components/Pivot/PivotItem.tsx index e090ac1fd8527d..caa4c9a7cee99e 100644 --- a/packages/office-ui-fabric-react/src/components/Pivot/PivotItem.tsx +++ b/packages/office-ui-fabric-react/src/components/Pivot/PivotItem.tsx @@ -1,12 +1,13 @@ import * as React from 'react'; +import { BaseComponent } from '../../Utilities'; import { IPivotItemProps } from './PivotItem.Props'; -export class PivotItem extends React.Component { +export class PivotItem extends BaseComponent { public render() { return (
- {this.props.children} + { this.props.children }
); } diff --git a/packages/office-ui-fabric-react/src/components/Popup/Popup.Props.ts b/packages/office-ui-fabric-react/src/components/Popup/Popup.Props.ts index 48df091b5594bb..171e2f735c034b 100644 --- a/packages/office-ui-fabric-react/src/components/Popup/Popup.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Popup/Popup.Props.ts @@ -3,7 +3,17 @@ import * as React from 'react'; /* tslint:enable:no-unused-variable */ import { Popup } from './Popup'; +export interface IPopup { + +} + export interface IPopupProps extends React.HTMLProps { + /** + * Optional callback to access the IPopup interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IPopup) => void; + /** * Aria role for popup */ diff --git a/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.Props.ts b/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.Props.ts index f70af5615252c3..39fde3f9be35eb 100644 --- a/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.Props.ts +++ b/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.Props.ts @@ -1,4 +1,13 @@ +export interface IProgressIndicator { + +} + export interface IProgressIndicatorProps { + /** + * Optional callback to access the IProgressIndicator interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IProgressIndicator) => void; /** * Class name to apply to the root in addition to ms-ProgressIndicator. diff --git a/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.tsx b/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.tsx index d330334a2a2cdd..6ad591f6589a65 100644 --- a/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.tsx +++ b/packages/office-ui-fabric-react/src/components/ProgressIndicator/ProgressIndicator.tsx @@ -22,9 +22,12 @@ export class ProgressIndicator extends BaseComponent { + /** + * Optional callback to access the IRating interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IRating) => void; + /** * Selected rating, has to be an integer between min and max */ diff --git a/packages/office-ui-fabric-react/src/components/SearchBox/SearchBox.Props.ts b/packages/office-ui-fabric-react/src/components/SearchBox/SearchBox.Props.ts index 2cf319614b4c15..725a49ab53ddc7 100644 --- a/packages/office-ui-fabric-react/src/components/SearchBox/SearchBox.Props.ts +++ b/packages/office-ui-fabric-react/src/components/SearchBox/SearchBox.Props.ts @@ -1,7 +1,16 @@ import * as React from 'react'; import { SearchBox } from './SearchBox'; +export interface ISearchBox { + +} + export interface ISearchBoxProps extends React.Props { + /** + * Optional callback to access the ISearchBox interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ISearchBox) => void; /** * Label text for the SearchBox. diff --git a/packages/office-ui-fabric-react/src/components/Slider/Slider.Props.ts b/packages/office-ui-fabric-react/src/components/Slider/Slider.Props.ts index ebe6a70ac43a5b..6b284d4073c253 100644 --- a/packages/office-ui-fabric-react/src/components/Slider/Slider.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Slider/Slider.Props.ts @@ -1,6 +1,18 @@ import * as React from 'react'; +export interface ISlider { + value: number; + + focus: () => void; +} + export interface ISliderProps { + /** + * Optional callback to access the ISlider interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ISlider) => void; + /** * Description label of the Slider */ @@ -67,9 +79,3 @@ export interface ISliderProps { */ buttonProps?: React.HTMLProps; } - -export interface ISlider { - value: number; - - focus: () => void; -} diff --git a/packages/office-ui-fabric-react/src/components/Slider/Slider.test.tsx b/packages/office-ui-fabric-react/src/components/Slider/Slider.test.tsx index df83a474775437..efc0cc1abc42c1 100644 --- a/packages/office-ui-fabric-react/src/components/Slider/Slider.test.tsx +++ b/packages/office-ui-fabric-react/src/components/Slider/Slider.test.tsx @@ -8,6 +8,7 @@ import * as ReactTestUtils from 'react-addons-test-utils'; let { expect } = chai; import { Slider } from './Slider'; +import { ISlider } from './Slider.Props'; describe('Slider', () => { @@ -29,7 +30,7 @@ describe('Slider', () => { let component = ReactTestUtils.renderIntoDocument( + /> ); let renderedDOM = ReactDOM.findDOMNode(component as React.ReactInstance); @@ -79,4 +80,12 @@ describe('Slider', () => { } }); + it('can read the current value', () => { + let slider: ISlider; + + let component = ReactTestUtils.renderIntoDocument( + slider = s } /> + ); + expect(slider.value).equals(12); + }); }); diff --git a/packages/office-ui-fabric-react/src/components/Slider/Slider.tsx b/packages/office-ui-fabric-react/src/components/Slider/Slider.tsx index 566eaad0a99e5a..cad2279f839444 100644 --- a/packages/office-ui-fabric-react/src/components/Slider/Slider.tsx +++ b/packages/office-ui-fabric-react/src/components/Slider/Slider.tsx @@ -44,6 +44,10 @@ export class Slider extends BaseComponent implements constructor(props?: ISliderProps) { super(props); + this._warnMutuallyExclusive({ + 'value': 'defaultValue' + }); + this._id = getId('Slider'); let value = props.value || props.defaultValue || props.min; diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.Props.ts b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.Props.ts index 38783d5da8ffba..4e573592e4f509 100644 --- a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.Props.ts @@ -1,7 +1,16 @@ import * as React from 'react'; import { Spinner } from './Spinner'; +export interface ISpinner { + +} + export interface ISpinnerProps extends React.Props { + /** + * Optional callback to access the ISpinner interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ISpinner) => void; /** * @deprecated diff --git a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx index 5170211c82a963..6b167883ca8ef6 100644 --- a/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx +++ b/packages/office-ui-fabric-react/src/components/Spinner/Spinner.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; -import { css } from '../../Utilities'; +import { BaseComponent, css } from '../../Utilities'; import { ISpinnerProps, SpinnerType, SpinnerSize } from './Spinner.Props'; import styles = require('./Spinner.scss'); -export class Spinner extends React.Component { +export class Spinner extends BaseComponent { public static defaultProps: ISpinnerProps = { size: SpinnerSize.medium }; diff --git a/packages/office-ui-fabric-react/src/components/TeachingBubble/TeachingBubble.Props.ts b/packages/office-ui-fabric-react/src/components/TeachingBubble/TeachingBubble.Props.ts index 859d5b0d92e99d..4b89b02c031a3e 100644 --- a/packages/office-ui-fabric-react/src/components/TeachingBubble/TeachingBubble.Props.ts +++ b/packages/office-ui-fabric-react/src/components/TeachingBubble/TeachingBubble.Props.ts @@ -6,11 +6,21 @@ import { IButtonProps } from '../../Button'; import { IAccessiblePopupProps } from '../../common/IAccessiblePopupProps'; import { ICalloutProps } from '../../Callout'; +export interface ITeachingBubble { + +} + /** * TeachingBubble component props. */ export interface ITeachingBubbleProps extends React.Props, IAccessiblePopupProps { + /** + * Optional callback to access the ISlider interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ITeachingBubble) => void; + /** * Properties to pass through for Callout, reference detail properties in ICalloutProps */ diff --git a/packages/office-ui-fabric-react/src/components/TextField/TextField.Props.ts b/packages/office-ui-fabric-react/src/components/TextField/TextField.Props.ts index a0feff389b1a4e..2e7a5930498db0 100644 --- a/packages/office-ui-fabric-react/src/components/TextField/TextField.Props.ts +++ b/packages/office-ui-fabric-react/src/components/TextField/TextField.Props.ts @@ -1,9 +1,32 @@ import * as React from 'react'; +export interface ITextField { + /** Gets the current value of the input. */ + value: string; + + /** Sets focus to the input. */ + focus: () => void; + + /** Select the value of the text field. */ + select: () => void; + + /** Sets the selection start of the text field to a specified value */ + setSelectionStart: (value: number) => void; + + /** Sets the selection end of the text field to a specified value */ + setSelectionEnd: (value: number) => void; +} + /** * TextField component props. */ export interface ITextFieldProps extends React.HTMLProps { + /** + * Optional callback to access the ITextField interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ITextField) => void; + /** * Whether or not the textfield is a multiline textfield. * @default false @@ -135,20 +158,3 @@ export interface ITextFieldProps extends React.HTMLProps i public constructor(props: ITextFieldProps) { super(props); + this._warnMutuallyExclusive({ + 'value': 'defaultValue' + }); + this._id = getId('TextField'); this._descriptionId = getId('TextFieldDescription'); diff --git a/packages/office-ui-fabric-react/src/components/Toggle/Toggle.Props.ts b/packages/office-ui-fabric-react/src/components/Toggle/Toggle.Props.ts index 8f488d39977ae1..4c811066023a30 100644 --- a/packages/office-ui-fabric-react/src/components/Toggle/Toggle.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Toggle/Toggle.Props.ts @@ -1,9 +1,20 @@ import * as React from 'react'; import { Toggle } from './Toggle'; + +export interface IToggle { + +} + /** * Toggle component props. */ export interface IToggleProps extends React.HTMLProps { + /** + * Optional callback to access the IToggle interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IToggle) => void; + /** * A label for the toggle. */ diff --git a/packages/office-ui-fabric-react/src/components/Toggle/Toggle.tsx b/packages/office-ui-fabric-react/src/components/Toggle/Toggle.tsx index 4ff1548c7aea08..349b7247f1f1e9 100644 --- a/packages/office-ui-fabric-react/src/components/Toggle/Toggle.tsx +++ b/packages/office-ui-fabric-react/src/components/Toggle/Toggle.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + BaseComponent, autobind, css, getId, @@ -14,7 +15,7 @@ export interface IToggleState { isChecked: boolean; } -export class Toggle extends React.Component { +export class Toggle extends BaseComponent { public static initialProps = { label: '', @@ -28,6 +29,10 @@ export class Toggle extends React.Component { constructor(props: IToggleProps) { super(); + this._warnMutuallyExclusive({ + 'checked': 'defaultChecked' + }); + this.state = { isChecked: !!(props.checked || props.defaultChecked) }; diff --git a/packages/office-ui-fabric-react/src/components/Tooltip/Tooltip.Props.ts b/packages/office-ui-fabric-react/src/components/Tooltip/Tooltip.Props.ts index c566f36764ba4d..582e86cd76304c 100644 --- a/packages/office-ui-fabric-react/src/components/Tooltip/Tooltip.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Tooltip/Tooltip.Props.ts @@ -3,11 +3,20 @@ import { Tooltip } from './Tooltip'; import { ICalloutProps } from '../../Callout'; import { DirectionalHint } from '../../common/DirectionalHint'; +export interface ITooltip { + +} + /** * Tooltip component props. */ - export interface ITooltipProps extends React.HTMLProps { + /** + * Optional callback to access the ITooltip interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ITooltip) => void; + /** * Properties to pass through for Callout, reference detail properties in ICalloutProps */ diff --git a/packages/office-ui-fabric-react/src/components/Tooltip/TooltipHost.Props.ts b/packages/office-ui-fabric-react/src/components/Tooltip/TooltipHost.Props.ts index 29b68b0b8fc760..5b169c31b4f93f 100644 --- a/packages/office-ui-fabric-react/src/components/Tooltip/TooltipHost.Props.ts +++ b/packages/office-ui-fabric-react/src/components/Tooltip/TooltipHost.Props.ts @@ -4,11 +4,20 @@ import { TooltipDelay } from './Tooltip.Props'; import { ICalloutProps } from '../../Callout'; import { DirectionalHint } from '../../common/DirectionalHint'; +export interface ITooltipHost { + +} + /** * Tooltip component props. */ - export interface ITooltipHostProps extends React.HTMLProps { + /** + * Optional callback to access the ITooltipHost interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: ITooltipHost) => void; + /** * Additional properties to pass through for Callout, reference detail properties in ICalloutProps */ diff --git a/packages/office-ui-fabric-react/src/components/pickers/PeoplePicker/PeoplePickerItems/SelectedItemWithMenu.tsx b/packages/office-ui-fabric-react/src/components/pickers/PeoplePicker/PeoplePickerItems/SelectedItemWithMenu.tsx index 84eaefd8a13bdf..1f74926c43f627 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/PeoplePicker/PeoplePickerItems/SelectedItemWithMenu.tsx +++ b/packages/office-ui-fabric-react/src/components/pickers/PeoplePicker/PeoplePickerItems/SelectedItemWithMenu.tsx @@ -1,7 +1,7 @@ /* tslint:disable */ import * as React from 'react'; /* tslint:enable */ -import { css } from '../../../../Utilities'; +import { BaseComponent, css } from '../../../../Utilities'; import { IPeoplePickerItemWithMenuProps } from './PeoplePickerItem.Props'; import { Persona, PersonaPresence } from '../../../../Persona'; import { ContextualMenu, DirectionalHint } from '../../../../ContextualMenu'; @@ -13,7 +13,7 @@ export interface IPeoplePickerItemState { contextualMenuVisible: boolean; } -export class SelectedItemWithMenu extends React.Component { +export class SelectedItemWithMenu extends BaseComponent { public refs: { [key: string]: any, ellipsisRef: HTMLElement diff --git a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx index f9d87eac901703..ff8c36053c938a 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx +++ b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx @@ -8,7 +8,7 @@ import { Spinner } from '../../../Spinner'; import { ISuggestionItemProps, ISuggestionsProps } from './Suggestions.Props'; import styles = require('./Suggestions.scss'); -export class SuggestionsItem extends React.Component, {}> { +export class SuggestionsItem extends BaseComponent, {}> { public render() { let { suggestionModel, diff --git a/packages/office-ui-fabric-react/src/utilities/decorators/BaseDecorator.ts b/packages/office-ui-fabric-react/src/utilities/decorators/BaseDecorator.ts index 509d5732578d5f..c58b5f329253ef 100644 --- a/packages/office-ui-fabric-react/src/utilities/decorators/BaseDecorator.ts +++ b/packages/office-ui-fabric-react/src/utilities/decorators/BaseDecorator.ts @@ -6,7 +6,10 @@ import { } from '../../Utilities'; export class BaseDecorator extends BaseComponent { + protected _shouldUpdateComponentRef = false; + protected _composedComponentInstance: React.Component; + private _hoisted: string[]; constructor() { diff --git a/packages/utilities/package.json b/packages/utilities/package.json index feeddb150f82e8..c9656eb61fa652 100644 --- a/packages/utilities/package.json +++ b/packages/utilities/package.json @@ -35,7 +35,7 @@ "source-map-loader": "0.1.5", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.9", - "typescript": "~2.1.0" + "typescript": "^2.2.2" }, "dependencies": {}, "peerDependencies": { diff --git a/packages/utilities/src/BaseComponent.ts b/packages/utilities/src/BaseComponent.ts index aab50ed1530800..5d0e266066afad 100644 --- a/packages/utilities/src/BaseComponent.ts +++ b/packages/utilities/src/BaseComponent.ts @@ -2,35 +2,47 @@ import * as React from 'react'; import { Async } from './Async'; import { EventGroup } from './EventGroup'; import { IDisposable } from './IDisposable'; +import { warnDeprecations, warnMutuallyExclusive, ISettingsMap } from './warn'; -export class BaseComponent extends React.Component { +export interface IBaseProps { + componentRef?: any; +} + +export class BaseComponent

extends React.Component { /** * External consumers should override BaseComponent.onError to hook into error messages that occur from * exceptions thrown from within components. */ public static onError: ((errorMessage?: string, ex?: any) => void); + /** + * Controls whether the componentRef prop will be resolved by this component instance. If you are + * implementing a passthrough (higher-order component), you would set this to false and pass through + * the props to the inner component, allowing it to resolve the componentRef. + * + * @protected + * @type {boolean} + * @memberOf BaseComponent + */ + protected _shouldUpdateComponentRef: boolean; + private __async: Async; private __events: EventGroup; private __disposables: IDisposable[]; private __resolves: { [name: string]: (ref: any) => any }; + private __className: string; /** * BaseComponent constructor * @param {P} props The props for the component. - * @param {Object} deprecatedProps The map of deprecated prop names to new names, where the key is the old name and the + * @param {Object} context The context for the component. * value is the new name. If a prop is removed rather than renamed, leave the value undefined. */ - constructor(props?: P, deprecatedProps?: { [propName: string]: string }) { - super(props); + constructor(props?: P, context?: any) { + super(props, context); - if (deprecatedProps) { - for (let propName in deprecatedProps) { - if (propName in props) { - _warnDeprecation(this, propName, deprecatedProps[propName]); - } - } - } + this.props = props; + this._shouldUpdateComponentRef = true; _makeAllSafe(this, BaseComponent.prototype, [ 'componentWillMount', @@ -44,6 +56,16 @@ export class BaseComponent extends React.Component { ]); } + /** When the component will receive props, make sure the componentRef is updated. */ + public componentWillReceiveProps(newProps?: P, newContext?: any) { + this._updateComponentRef(this.props, newProps); + } + + /** When the component has mounted, update the componentRef. */ + public componentDidMount() { + this._updateComponentRef(undefined, this.props); + } + /** If we have disposables, dispose them automatically on unmount. */ public componentWillUnmount() { if (this.__disposables) { @@ -60,10 +82,14 @@ export class BaseComponent extends React.Component { /** Gets the object's class name. */ public get className() { - let funcNameRegex = /function (.{1,})\(/; - let results = (funcNameRegex).exec((this).constructor.toString()); + if (!this.__className) { + let funcNameRegex = /function (.{1,})\(/; + let results = (funcNameRegex).exec((this).constructor.toString()); + + this.__className = (results && results.length > 1) ? results[1] : ''; + } - return (results && results.length > 1) ? results[1] : ''; + return this.__className; } /** Allows subclasses to push things to this._disposables to be auto disposed. */ @@ -126,8 +152,51 @@ export class BaseComponent extends React.Component { return this[refName] = ref; }; } + return this.__resolves[refName]; } + + /** + * Updates the componentRef (by calling it with "this" when necessary.) + */ + protected _updateComponentRef(currentProps: IBaseProps, newProps: IBaseProps = {}) { + if (this._shouldUpdateComponentRef && + ((!currentProps && newProps.componentRef) || + (currentProps && currentProps.componentRef !== newProps.componentRef))) { + + if (currentProps && currentProps.componentRef) { + currentProps.componentRef(null); + } + + if (newProps.componentRef) { + newProps.componentRef(this); + } + } + } + /** + * Warns when a deprecated props are being used. + * + * @protected + * @param {ISettingsMap

} deprecationMap The map of deprecations, where key is the prop name and the value is + * either null or a replacement prop name. + * + * @memberOf BaseComponent + */ + protected _warnDeprecations(deprecationMap: ISettingsMap

) { + warnDeprecations(this.className, this.props, deprecationMap); + } + + /** + * Warns when props which are mutually exclusive with each other are both used. + * + * @protected + * @param {ISettingsMap

} mutuallyExclusiveMap The map of mutually exclusive props. + * + * @memberOf BaseComponent + */ + protected _warnMutuallyExclusive(mutuallyExclusiveMap: ISettingsMap

) { + warnMutuallyExclusive(this.className, this.props, mutuallyExclusiveMap); + } } /** @@ -153,7 +222,7 @@ function _makeSafe(obj: BaseComponent, prototype: Object, methodName: if (prototypeMethod) { retVal = prototypeMethod.apply(this, arguments); } - if (classMethod) { + if (classMethod !== prototypeMethod) { retVal = classMethod.apply(this, arguments); } } catch (e) { @@ -169,19 +238,9 @@ function _makeSafe(obj: BaseComponent, prototype: Object, methodName: } } -function _warnDeprecation(obj: BaseComponent, propertyName: string, newPropertyName: string) { - if (console && console.warn) { - let deprecationMessage = `${obj.className} property '${propertyName}' was used but has been deprecated.`; - - if (newPropertyName) { - deprecationMessage += ` Use '${newPropertyName}' instead.`; - } - - console.warn(deprecationMessage); - } -} - BaseComponent.onError = (errorMessage) => { console.error(errorMessage); throw errorMessage; }; + +export function nullRender() { return null; } diff --git a/packages/utilities/src/Customizer.tsx b/packages/utilities/src/Customizer.tsx new file mode 100644 index 00000000000000..d007f57250690c --- /dev/null +++ b/packages/utilities/src/Customizer.tsx @@ -0,0 +1,65 @@ +import * as React from 'react'; +import { BaseComponent } from './BaseComponent'; +import { assign } from './object'; + +export interface ISettings { + [key: string]: any; +} + +export interface ICustomizerProps { + settings: ISettings; +} + +export interface ICustomizerState { + injectedProps?: ISettings; +} + +/** + * The Customizer component allows for default props to be mixed into components which + * are decorated with the customizable() decorator. This enables injection scenarios like: + * + * 1. render svg icons instead of the icon font within all buttons + * 2. inject a custom theme object into a component + * + * Props are provided via the settings prop, which should be a json map where the key is + * the name of the customizable component, and the value is are the props to pass in. + * + * @export + * @class Customizer + * @extends {BaseComponent} + */ +export class Customizer extends BaseComponent { + public static contextTypes = { + injectedProps: React.PropTypes.object + }; + + public static childContextTypes = Customizer.contextTypes; + + constructor(props, context) { + super(props); + + this.state = this._getInjectedProps(props, context); + } + + public getChildContext(): any { + return this.state; + } + + public componentWillReceiveProps(newProps, newContext) { + + this.setState(this._getInjectedProps(newProps, newContext)); + } + + public render() { + return React.Children.only(this.props.children); + } + + private _getInjectedProps(props: ICustomizerProps, context: ICustomizerState) { + let { settings: injectedPropsFromSettings = {} as ISettings } = props; + let { injectedProps: injectedPropsFromContext = {} as ISettings } = context; + + return { + injectedProps: assign({}, injectedPropsFromContext, injectedPropsFromSettings) + }; + } +} diff --git a/packages/utilities/src/customizable.tsx b/packages/utilities/src/customizable.tsx new file mode 100644 index 00000000000000..d207069a0b9dbc --- /dev/null +++ b/packages/utilities/src/customizable.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; + +export function customizable

(componentName?: string) { + return function customizableFactory( + ComposedComponent: (new (props: P, ...args: any[]) => React.Component) + ): any { + return class ComponentWithInjectedProps extends React.Component { + public static contextTypes = { + injectedProps: React.PropTypes.object + }; + + public render() { + let defaultProps = ((this.context.injectedProps) ? + this.context.injectedProps[componentName] : + null) || {}; + + return ( + + ); + } + }; + }; +} diff --git a/packages/utilities/src/warn.test.ts b/packages/utilities/src/warn.test.ts new file mode 100644 index 00000000000000..6333468a752e77 --- /dev/null +++ b/packages/utilities/src/warn.test.ts @@ -0,0 +1,51 @@ +import { + setWarningCallback, + warnDeprecations, + warnMutuallyExclusive +} from './warn'; +import { expect } from 'chai'; + +let _lastWarning: string; + +describe('warnDeprecations', () => { + beforeEach(() => { + _lastWarning = undefined; + setWarningCallback(message => _lastWarning = message); + }); + + afterEach(() => setWarningCallback(undefined)); + + it('does not warn when unnecessary', () => { + warnDeprecations('Foo', { bar: 1 }, { 'foo': null } as any); + expect(_lastWarning).equals(undefined); + }); + + it('can warn on a deprecated prop', () => { + warnDeprecations('Foo', { foo: 1 }, { 'foo': null }); + expect(_lastWarning).equals(`Foo property 'foo' was used but has been deprecated.`); + }); + + it('can warn on a deprecated prop with replacement', () => { + warnDeprecations('Foo', { foo: 1 }, { 'foo': 'bar' }); + expect(_lastWarning).equals(`Foo property 'foo' was used but has been deprecated. Use 'bar' instead.`); + }); +}); + +describe('warnMutuallyExclusive', () => { + beforeEach(() => { + _lastWarning = undefined; + setWarningCallback(message => _lastWarning = message); + }); + + afterEach(() => setWarningCallback(undefined)); + + it('does not warn when unnecessary', () => { + warnMutuallyExclusive('Foo', { foo: 1 }, { 'foo': 'bar' }); + expect(_lastWarning).equals(undefined); + }); + + it('can warn on mutual exlusive props', () => { + warnMutuallyExclusive('Foo', { foo: 1, bar: 1 }, { 'foo': 'bar' } as any); + expect(_lastWarning).equals(`Foo property 'foo' is mutually exclusive with 'bar'. Use one or the other.`); + }); +}); diff --git a/packages/utilities/src/warn.ts b/packages/utilities/src/warn.ts new file mode 100644 index 00000000000000..561ab69cd4e81d --- /dev/null +++ b/packages/utilities/src/warn.ts @@ -0,0 +1,63 @@ +let _warningCallback = _warn; + +export type ISettingsMap = { + [P in keyof T]: string; +}; + +/** + * Warns when a deprecated props are being used. + * + * @export + * @param {string} componentName The name of the component being used. + * @param {Object} props The props passed into the component. + * @param {ISettingsMap} deprecationMap The map of deprecations, where key is the prop name and the value is + * either null or a replacement prop name. + */ +export function warnDeprecations

( + componentName: string, + props: P, + deprecationMap: ISettingsMap

): void { + + for (const propName in deprecationMap) { + if (props && propName in props) { + let deprecationMessage = `${componentName} property '${propName}' was used but has been deprecated.`; + const replacementPropName = deprecationMap[propName]; + + if (replacementPropName) { + deprecationMessage += ` Use '${replacementPropName}' instead.`; + } + _warningCallback(deprecationMessage); + } + } +} + +export function warnMutuallyExclusive

( + componentName: string, + props: P, + exclusiveMap: ISettingsMap

): void { + + for (const propName in exclusiveMap) { + if (props && propName in props && exclusiveMap[propName] in props) { + _warningCallback( + `${componentName} property '${propName}' is mutually exclusive with '${exclusiveMap[propName]}'. Use one or the other.` + ); + } + } +} + +/** + * Configures the warning callback. Passing in undefined will reset it to use the default + * console.warn function. + * + * @export + * @param {(message) => void} warningCallback + */ +export function setWarningCallback(warningCallback: (message) => void): void { + _warningCallback = warningCallback === undefined ? _warn : warningCallback; +} + +function _warn(message: string): void { + if (console && console.warn) { + console.warn(message); + } +}