UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Office 365.

395 lines • 26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var React = require("react"); require("./ThemeGeneratorPage.scss"); var Utilities_1 = require("office-ui-fabric-react/lib/Utilities"); var Styling_1 = require("office-ui-fabric-react/lib/Styling"); var index_1 = require("office-ui-fabric-react/lib/utilities/color/index"); var ThemeGenerator_1 = require("office-ui-fabric-react/lib/ThemeGenerator"); var Callout_1 = require("office-ui-fabric-react/lib/Callout"); var ColorPicker_1 = require("office-ui-fabric-react/lib/ColorPicker"); var ChoiceGroup_1 = require("office-ui-fabric-react/lib/ChoiceGroup"); var TeachingBubble_Basic_Example_1 = require("../../components/TeachingBubble/examples/TeachingBubble.Basic.Example"); var TextField_Basic_Example_1 = require("../TextField/examples/TextField.Basic.Example"); var Toggle_Basic_Example_1 = require("../../components/Toggle/examples/Toggle.Basic.Example"); var ProgressIndicator_Basic_Example_1 = require("../ProgressIndicator/examples/ProgressIndicator.Basic.Example"); var BackgroundImageUriKey = 'backgroundImageUri'; var BackgroundOverlayKey = 'backgroundOverlay'; var ThemeGeneratorPage = /** @class */ (function (_super) { tslib_1.__extends(ThemeGeneratorPage, _super); function ThemeGeneratorPage(props) { var _this = _super.call(this, props) || this; var themeRules = ThemeGenerator_1.themeRulesStandardCreator(); ThemeGenerator_1.ThemeGenerator.insureSlots(themeRules, index_1.isDark(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]].color)); _this.state = { themeRules: themeRules, colorPickerSlotRule: null, colorPickerElement: null, colorPickerVisible: false }; return _this; } ThemeGeneratorPage.prototype.componentWillUnmount = function () { // remove temp styles var root = document.querySelector('.App-content'); if (root) { root.style.backgroundColor = ''; root.style.color = ''; } document.body.style.backgroundColor = ''; document.body.style.color = ''; // and apply the default theme to overwrite any existing custom theme var themeRules = ThemeGenerator_1.themeRulesStandardCreator(); ThemeGenerator_1.ThemeGenerator.insureSlots(themeRules, false); Styling_1.loadTheme({ palette: themeRules }); }; ThemeGeneratorPage.prototype.render = function () { var _a = this.state, colorPickerVisible = _a.colorPickerVisible, colorPickerSlotRule = _a.colorPickerSlotRule, colorPickerElement = _a.colorPickerElement; var fabricThemeSlots = [this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeDarker), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeDark), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeDarkAlt), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themePrimary), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeSecondary), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeTertiary), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeLight), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeLighter), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.themeLighterAlt)]; var fabricNeutralForegroundSlots = [this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.black), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralDark), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralPrimary), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralPrimaryAlt), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralSecondary), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralTertiary) ]; var fabricNeutralBackgroundSlots = [this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralTertiaryAlt), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralQuaternary), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralQuaternaryAlt), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralLight), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralLighter), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.neutralLighterAlt), this._fabricSlotWidget(ThemeGenerator_1.FabricSlots.white)]; return (React.createElement("div", { className: 'ms-themer' }, React.createElement("p", null, "This tool helps you easily create all the shades and slots for a custom theme. The theme can be used by Fabric React's styling package, see the ", React.createElement("a", { href: 'https://github.com/OfficeDev/office-ui-fabric-react/tree/master/packages/styling' }, "documentation"), ".", React.createElement("br", null), "As you modify one of the three base colors, the theme will update automatically based on predefined rules. You can modify each individual slot below as well."), colorPickerVisible && colorPickerSlotRule !== null && colorPickerSlotRule !== undefined && colorPickerElement && React.createElement(Callout_1.Callout, { key: colorPickerSlotRule.name, gapSpace: 10, target: colorPickerElement, setInitialFocus: true, onDismiss: this._colorPickerOnDismiss }, React.createElement(ColorPicker_1.ColorPicker, { color: colorPickerSlotRule.color.str, onColorChanged: this._semanticSlotRuleChanged.bind(this, colorPickerSlotRule) })), React.createElement("div", { style: { display: 'flex' } }, [this._baseColorSlotPicker(ThemeGenerator_1.BaseSlots.primaryColor, 'Primary theme color'), this._baseColorSlotPicker(ThemeGenerator_1.BaseSlots.foregroundColor, 'Body text color'), this._baseColorSlotPicker(ThemeGenerator_1.BaseSlots.backgroundColor, 'Body background color')]), React.createElement("br", null), this._outputSection(), React.createElement("br", null), React.createElement("h2", null, "Fabric Palette"), React.createElement("p", null, "The original Fabric palette slots. These are raw colors with no prescriptive uses. Each one is a shade or tint of a base color."), React.createElement("div", { className: 'ms-themer-fabricPalette-root' }, React.createElement("div", null, fabricThemeSlots), React.createElement("div", null, React.createElement("p", null, "generally used for text and foregrounds"), fabricNeutralForegroundSlots), React.createElement("div", null, React.createElement("p", null, "generally used for backgrounds"), fabricNeutralBackgroundSlots)), React.createElement("br", null), React.createElement("h3", null, "Samples"), React.createElement("div", { style: { display: 'flex', flexDirection: 'row' } }, React.createElement("div", { className: 'ms-themer-example' }, React.createElement(TextField_Basic_Example_1.TextFieldBasicExample, null)), React.createElement("div", { className: 'ms-themer-example' }, React.createElement(Toggle_Basic_Example_1.ToggleBasicExample, null), React.createElement(ChoiceGroup_1.ChoiceGroup, { options: [ { key: 'A', text: 'Option A' }, { key: 'B', text: 'Option B', checked: true } ], label: 'Pick one', required: true }), ",", React.createElement(ChoiceGroup_1.ChoiceGroup, { options: [ { key: 'C', text: 'Option C', disabled: true }, { key: 'D', text: 'Option D', checked: true, disabled: true } ], label: 'Pick one', required: true })), React.createElement("div", { className: 'ms-themer-example' }, React.createElement(TeachingBubble_Basic_Example_1.TeachingBubbleBasicExample, null), React.createElement("br", null), React.createElement(ProgressIndicator_Basic_Example_1.ProgressIndicatorBasicExample, null))), React.createElement("h3", null, "Accessibility"), React.createElement("p", null, "Each pair of colors below should produce legible text and have a minimum contrast ratio of 4.5."), React.createElement("table", { className: 'ms-themer-accessibilityTable' }, React.createElement("thead", null, React.createElement("td", null, "Sample text"), React.createElement("td", null, "Contrast ratio"), React.createElement("td", null, "Slot pair")), React.createElement("tbody", null, [this._accessibilityRow(ThemeGenerator_1.FabricSlots.neutralPrimary, ThemeGenerator_1.FabricSlots.white)])))); }; ThemeGeneratorPage.prototype._makeThemeFromImg = function () { /* tslint:enable:no-unused-variable */ this._imgUrl = document.getElementById('imageUrl').value; document.getElementById('imagePreview').src = this._imgUrl; if (this._imgUrl) { var xhr = new XMLHttpRequest(); xhr.addEventListener('load', this._cognitiveVisionCallback.bind(this)); // you may need to change the URL here xhr.open('POST', 'https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Description%2CColor&details=&language=en'); xhr.setRequestHeader('Content-Type', 'application/json'); alert('You forgot to set the subscription key!'); xhr.setRequestHeader('Ocp-Apim-Subscription-Key', 'YourSubscriptionKeyHere'); // put your subscription key here xhr.send('{ "url": "' + this._imgUrl + '" }'); } else { // remove related properties from theme var themeRules = this.state.themeRules; if (themeRules.hasOwnProperty(BackgroundImageUriKey)) { delete themeRules[BackgroundImageUriKey]; } if (themeRules.hasOwnProperty(BackgroundOverlayKey)) { delete themeRules[BackgroundOverlayKey]; } this.setState({ themeRules: themeRules }, this._makeNewTheme); } }; ThemeGeneratorPage.prototype._cognitiveVisionCallback = function (e) { var xhr = e.target; if (xhr.status === 200) { var response = JSON.parse(xhr.response); document.getElementById('imageDescription').innerHTML = response.description.captions[0].text; /* API returns: response.color.accentColor response.color.dominantColorBackground response.color.dominantColorForeground */ // converts a returned color from a word into a hex value conforming to our palette var getHexFromColor = function (color, isBg) { // todo: could use more logic based on isInverted and isBg switch (color.toLowerCase()) { case 'black': return '#1f1f1f'; case 'blue': return '#0078d7'; case 'brown': return '#754d12'; case 'gray': case 'grey': return isBg ? '#444' : '#ccc'; case 'green': return '#107c10'; case 'orange': return '#ff8c00'; case 'pink': return '#e3008c'; case 'purple': return '#5c2d91'; case 'red': return '#e81123'; case 'teal': return '#008272'; case 'white': return '#fff'; case 'yellow': return '#fff100'; } alert('Error: Unexpected color passed to getHexFromColor(): ' + color); return '#fff'; }; var themeRules = this.state.themeRules; var bgColor = getHexFromColor(response.color.dominantColorBackground, true); var bgColorIsDark = index_1.isDark(index_1.getColorFromString(bgColor)); ThemeGenerator_1.ThemeGenerator.setSlot(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]], bgColor, bgColorIsDark, true, true); ThemeGenerator_1.ThemeGenerator.setSlot(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.primaryColor]], '#' + response.color.accentColor, bgColorIsDark, true, true); ThemeGenerator_1.ThemeGenerator.setSlot(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.foregroundColor]], getHexFromColor(response.color.dominantColorForeground, false), bgColorIsDark, true, true); themeRules[BackgroundImageUriKey] = { name: BackgroundImageUriKey, value: 'url(\'' + this._imgUrl + '\')', dependentRules: [] }; themeRules[BackgroundOverlayKey] = { name: BackgroundOverlayKey, color: index_1.updateA((themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]]).color, 50), dependentRules: [] }; this.setState({ themeRules: themeRules }, this._makeNewTheme); } else { alert('Error ' + xhr.status + ': ' + xhr.statusText); } }; ThemeGeneratorPage.prototype._colorPickerOnDismiss = function () { this.setState({ colorPickerVisible: false }); }; ThemeGeneratorPage.prototype._semanticSlotRuleChanged = function (slotRule, color) { var _this = this; if (this._semanticSlotColorChangeTimeout) { clearTimeout(this._semanticSlotColorChangeTimeout); } this._semanticSlotColorChangeTimeout = this._async.setTimeout(function () { var themeRules = _this.state.themeRules; ThemeGenerator_1.ThemeGenerator.setSlot(slotRule, color, index_1.isDark(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]].color), true, true); _this.setState({ themeRules: themeRules }, _this._makeNewTheme); }, 20); // 20ms is low enough that you can slowly drag to change color and see that theme, // but high enough that quick changes don't get bogged down by a million changes inbetween }; ThemeGeneratorPage.prototype._onSwatchClick = function (slotRule, ev) { var _a = this.state, colorPickerSlotRule = _a.colorPickerSlotRule, colorPickerElement = _a.colorPickerElement; if (colorPickerSlotRule !== null && colorPickerSlotRule !== undefined && !!colorPickerElement && colorPickerSlotRule === slotRule && colorPickerElement === ev.target) { this.setState({ colorPickerVisible: false, colorPickerSlotRule: null, colorPickerElement: null }); } else { this.setState({ colorPickerVisible: true, colorPickerSlotRule: slotRule, colorPickerElement: ev.target }); } }; ThemeGeneratorPage.prototype._slotWidget = function (slotRule) { return (React.createElement("div", { key: slotRule.name, className: 'ms-themer-slot' }, this._colorSquareSwatchWidget(slotRule), React.createElement("div", null, React.createElement("div", null, slotRule.name), !slotRule.isCustomized ? React.createElement("div", null, "Inherits from: ", slotRule.inherits.name) : React.createElement("div", null, "Customized")))); }; ThemeGeneratorPage.prototype._fabricSlotWidget = function (fabricSlot) { return this._slotWidget(this.state.themeRules[ThemeGenerator_1.FabricSlots[fabricSlot]]); }; ThemeGeneratorPage.prototype._colorSquareSwatchWidget = function (slotRule) { return (React.createElement("div", { key: slotRule.name, className: 'ms-themer-swatch', style: { backgroundColor: slotRule.color.str }, onClick: this._onSwatchClick.bind(this, slotRule) })); }; ThemeGeneratorPage.prototype._accessibilityRow = function (foreground, background) { var themeRules = this.state.themeRules; var bgc = themeRules[ThemeGenerator_1.FabricSlots[background]].color; var fgc = themeRules[ThemeGenerator_1.FabricSlots[foreground]].color; var contrastRatio = index_1.getContrastRatio(bgc, fgc); var contrastRatioString = String(contrastRatio); contrastRatioString = contrastRatioString.substr(0, contrastRatioString.indexOf('.') + 3); if (contrastRatio < 4.5) { contrastRatioString = '**' + contrastRatioString + '**'; } return (React.createElement("tr", { key: String(foreground) + String(background) }, React.createElement("td", { style: { backgroundColor: bgc.str, color: fgc.str } }, "The quick brown fox jumps over the lazy dog."), React.createElement("td", null, contrastRatioString), React.createElement("td", null, ThemeGenerator_1.FabricSlots[foreground] + ' + ' + ThemeGenerator_1.FabricSlots[background]))); }; ThemeGeneratorPage.prototype._outputSection = function () { var themeRules = this.state.themeRules; // strip out the unnecessary shade slots from the final output theme var abridgedTheme = {}; for (var ruleName in themeRules) { if (themeRules.hasOwnProperty(ruleName)) { if (ruleName.indexOf('ColorShade') === -1 && ruleName !== 'primaryColor' && ruleName !== 'backgroundColor' && ruleName !== 'foregroundColor') { abridgedTheme[ruleName] = themeRules[ruleName]; } } } var themeAsJson = ThemeGenerator_1.ThemeGenerator.getThemeAsJson(abridgedTheme); // todo: need to start outputting the real ITheme object: /* createTheme({ palette: ThemeGenerator.getThemeAsJson(abridgedTheme), semanticColors: ThemeGenerator.getThemeAsJson(abridgedTheme) }) */ return (React.createElement("div", null, React.createElement("h2", null, "Output"), React.createElement("div", { className: 'ms-themer-output-root' }, React.createElement("div", null, React.createElement("h3", null, "JSON"), React.createElement("textarea", { readOnly: true, spellCheck: false, value: JSON.stringify(ThemeGenerator_1.ThemeGenerator.getThemeAsJson(abridgedTheme), void 0, 2) })), React.createElement("div", null, React.createElement("h3", null, "SASS"), React.createElement("textarea", { readOnly: true, spellCheck: false, value: ThemeGenerator_1.ThemeGenerator.getThemeAsSass(abridgedTheme) })), React.createElement("div", null, React.createElement("h3", null, "PowerShell"), React.createElement("textarea", { readOnly: true, spellCheck: false, value: ThemeGenerator_1.ThemeGenerator.getThemeForPowerShell(abridgedTheme) }))))); }; ThemeGeneratorPage.prototype._makeNewTheme = function () { var themeAsJson = ThemeGenerator_1.ThemeGenerator.getThemeAsJson(this.state.themeRules); console.log('New theme...', themeAsJson); var finalTheme = Styling_1.loadTheme(tslib_1.__assign({ palette: themeAsJson }, { isInverted: index_1.isDark(this.state.themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]].color) })); var root = document.querySelector('.App-content'); if (root) { root.style.backgroundColor = finalTheme.semanticColors.bodyBackground; root.style.color = finalTheme.semanticColors.bodyText; } document.body.style.backgroundColor = finalTheme.semanticColors.bodyBackground; document.body.style.color = finalTheme.semanticColors.bodyText; console.log('New theme:', finalTheme); }; ThemeGeneratorPage.prototype._baseColorSlotPicker = function (baseSlot, title) { var colorChangeTimeout; function _onColorChanged(newColor) { var _this = this; if (colorChangeTimeout) { clearTimeout(colorChangeTimeout); } colorChangeTimeout = this._async.setTimeout(function () { var themeRules = _this.state.themeRules; var currentIsDark = index_1.isDark(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]].color); ThemeGenerator_1.ThemeGenerator.setSlot(themeRules[ThemeGenerator_1.BaseSlots[baseSlot]], newColor, currentIsDark, true, true); if (currentIsDark !== index_1.isDark(themeRules[ThemeGenerator_1.BaseSlots[ThemeGenerator_1.BaseSlots.backgroundColor]].color)) { // isInverted got swapped, so need to refresh slots with new shading rules ThemeGenerator_1.ThemeGenerator.insureSlots(themeRules, !currentIsDark); } _this.setState({ themeRules: themeRules }, _this._makeNewTheme); }, 20); // 20ms is low enough that you can slowly drag to change color and see that theme, // but high enough that quick changes don't get bogged down by a million changes inbetween } return (React.createElement("div", { className: 'ms-themer-paletteSlot', key: baseSlot }, React.createElement("h3", null, title), React.createElement("div", null, React.createElement(ColorPicker_1.ColorPicker, { key: 'baseslotcolorpicker' + baseSlot, color: this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot]].color.str, /* tslint:disable:jsx-no-bind */ onColorChanged: _onColorChanged.bind(this) })), React.createElement("div", { className: 'ms-themer-swatchBg', style: { backgroundColor: this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot]].color.str } }, React.createElement("div", { className: 'ms-themer-swatch', style: { backgroundColor: this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot]].color.str } }), [this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade1']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade2']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade3']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade4']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade5']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade6']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade7']), this._colorSquareSwatchWidget(this.state.themeRules[ThemeGenerator_1.BaseSlots[baseSlot] + 'Shade8'])]))); }; tslib_1.__decorate([ Utilities_1.autobind /* tslint:disable:no-unused-variable */ ], ThemeGeneratorPage.prototype, "_makeThemeFromImg", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_cognitiveVisionCallback", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_colorPickerOnDismiss", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_semanticSlotRuleChanged", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_onSwatchClick", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_slotWidget", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_fabricSlotWidget", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_accessibilityRow", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_outputSection", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_makeNewTheme", null); tslib_1.__decorate([ Utilities_1.autobind ], ThemeGeneratorPage.prototype, "_baseColorSlotPicker", null); return ThemeGeneratorPage; }(Utilities_1.BaseComponent)); exports.ThemeGeneratorPage = ThemeGeneratorPage; //# sourceMappingURL=ThemeGeneratorPage.js.map