UNPKG

modaq

Version:

Quiz Bowl Reader using TypeScript, React, and MobX

207 lines 11 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FontDialog = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = __importDefault(require("react")); const mobx_react_lite_1 = require("mobx-react-lite"); const react_2 = require("@fluentui/react"); const FontDialogController = __importStar(require("./FontDialogController")); require("../../state/AppState"); const StateContext_1 = require("../../contexts/StateContext"); require("../../state/FontDialogState"); const ModalVisibilityStatus_1 = require("../../state/ModalVisibilityStatus"); const ModalDialog_1 = require("./ModalDialog"); const defaultFont = "Segoe UI"; const knownFonts = [ "Arial", "Century Schoolbook L", "Consolas", "Courier New", "Garamond", "Georgia", "Helvetica", "Liberation Serif", "Palatino", "serif", "Segoe UI", "Tahoma", "Times New Roman", "Verdana", ]; const minimumFontSize = 12; const maximumFontSize = 40; const stackTokens = { childrenGap: 10 }; exports.FontDialog = mobx_react_lite_1.observer(function FontDialog() { return (jsx_runtime_1.jsxs(ModalDialog_1.ModalDialog, Object.assign({ title: "Font", visibilityStatus: ModalVisibilityStatus_1.ModalVisibilityStatus.Font, maxWidth: "40vw", onDismiss: FontDialogController.cancel }, { children: [jsx_runtime_1.jsx(FontDialogBody, {}, void 0), jsx_runtime_1.jsxs(react_2.DialogFooter, { children: [jsx_runtime_1.jsx(react_2.PrimaryButton, { text: "OK", onClick: FontDialogController.update }, void 0), jsx_runtime_1.jsx(react_2.DefaultButton, { text: "Cancel", onClick: FontDialogController.cancel }, void 0)] }, void 0)] }), void 0)); }); // If we really want flexibility for text/pronunciation guide colors we can use a ColorPicker, but it takes up a lot of // space and users realistically won't use most of the colors const FontDialogBody = mobx_react_lite_1.observer(function FontDialogBody() { var _a, _b, _c, _d, _e; const [fonts] = react_1.default.useState(getAvailableFonts(knownFonts)); const appState = react_1.default.useContext(StateContext_1.StateContext); const dialogState = appState.uiState.dialogState.fontDialog; if (dialogState == undefined) { return jsx_runtime_1.jsx(jsx_runtime_1.Fragment, {}, void 0); } const value = ((_a = dialogState.fontSize) !== null && _a !== void 0 ? _a : appState.uiState.questionFontSize).toString(); let fontSelected = false; const fontOptions = fonts.map((font) => { // fontFamily has several fonts, but the one we choose should be the primary font, so look for that const selected = dialogState.fontFamily ? dialogState.fontFamily.startsWith(font) : appState.uiState.fontFamily.startsWith(font); fontSelected = fontSelected || selected; return { key: font, text: font, selected, }; }); if (!fontSelected && fontOptions.length > 0) { fontOptions[0].selected = true; } const blackTextCheckbox = (jsx_runtime_1.jsx(react_2.Checkbox, { label: "Use pure black for text", onChange: (ev, checked) => { // Dark mode already uses pure white if (checked === true && !appState.uiState.useDarkMode) { FontDialogController.changeTextColor("black"); } else { FontDialogController.changeTextColor(undefined); } }, checked: dialogState.textColor === "black", disabled: appState.uiState.useDarkMode }, void 0)); const textColor = dialogState.textColor; const pronunciationGuideOptions = [ { key: "default", text: "Default", data: "#777777", // There are cases where the color isn't set yet, so undefined and 777777 should match with this selected: dialogState.pronunciationGuideColor == undefined, }, { key: "burgundy", text: "Burgundy", data: "#770077", }, { key: "black", text: "Black", data: "#000000", }, { key: "darkGray", text: "Dark Gray", data: "#555555", }, { key: "lightGray", text: "Light Gray", data: "#888888", }, { key: "purple", text: "Purple", data: "#6666FF", }, { key: "teal", text: "Teal", data: "#007777", }, ]; for (const option of pronunciationGuideOptions) { if (dialogState.pronunciationGuideColor === option.data) { option.selected = true; } } const pronunciationGuideDropdown = (jsx_runtime_1.jsx(react_2.Dropdown, { label: "Pronunciation guide color", options: pronunciationGuideOptions, onChange: (ev, option) => { FontDialogController.changePronunciationGuideColor(option === null || option === void 0 ? void 0 : option.data); }, onRenderItem: (props, defaultRender) => { var _a; if (props == undefined || defaultRender == undefined) { return jsx_runtime_1.jsx(jsx_runtime_1.Fragment, {}, void 0); } const elements = defaultRender(props); return (jsx_runtime_1.jsxs(react_2.Stack, Object.assign({ horizontal: true }, { children: [jsx_runtime_1.jsx(react_2.StackItem, { children: jsx_runtime_1.jsx("div", { style: { backgroundColor: (_a = props === null || props === void 0 ? void 0 : props.data) !== null && _a !== void 0 ? _a : dialogState.textColor, width: 36, height: "100%", } }, `block_${props.key}`) }, void 0), jsx_runtime_1.jsx(react_2.StackItem, { children: elements }, void 0)] }), void 0)); } }, void 0)); return (jsx_runtime_1.jsxs(react_2.Stack, Object.assign({ tokens: stackTokens }, { children: [jsx_runtime_1.jsx(react_2.StackItem, { children: jsx_runtime_1.jsx(react_2.Dropdown, { label: "Font", options: fontOptions, onRenderOption: (props, defaultRender) => { if (props == undefined || defaultRender == undefined) { return jsx_runtime_1.jsx(jsx_runtime_1.Fragment, {}, void 0); } // Fall back to the default UI if it's not loaded in the system return (jsx_runtime_1.jsx(react_2.Label, Object.assign({ styles: { root: { fontFamily: props.text + ", " + defaultFont } } }, { children: props.text }), props.key)); }, onChange: (event, option) => { FontDialogController.changeFontFamily(option === null || option === void 0 ? void 0 : option.text); } }, void 0) }, void 0), jsx_runtime_1.jsx(react_2.StackItem, { children: jsx_runtime_1.jsx(react_2.SpinButton, { label: "Font size", onChange: changeFontSize, value: value, min: minimumFontSize, max: maximumFontSize, step: 1, incrementButtonAriaLabel: "Increase font size by 1", decrementButtonAriaLabel: "Decrease font size by 1" }, void 0) }, void 0), jsx_runtime_1.jsx(react_2.StackItem, { children: pronunciationGuideDropdown }, void 0), jsx_runtime_1.jsx(react_2.StackItem, { children: blackTextCheckbox }, void 0), jsx_runtime_1.jsxs(react_2.StackItem, { children: [jsx_runtime_1.jsx("span", Object.assign({ style: { fontFamily: (_b = dialogState.fontFamily) !== null && _b !== void 0 ? _b : appState.uiState.fontFamily, fontSize: (_c = dialogState.fontSize) !== null && _c !== void 0 ? _c : appState.uiState.questionFontSize, color: textColor, } }, { children: "Sample text" }), void 0), jsx_runtime_1.jsxs("span", Object.assign({ style: { fontFamily: (_d = dialogState.fontFamily) !== null && _d !== void 0 ? _d : appState.uiState.fontFamily, fontSize: (_e = dialogState.fontSize) !== null && _e !== void 0 ? _e : appState.uiState.questionFontSize, color: dialogState.pronunciationGuideColor, } }, { children: [" ", "(text)"] }), void 0)] }, void 0)] }), void 0)); }); function changeFontSize(event, newValue) { if (newValue == undefined) { return; } const size = Number.parseInt(newValue, 10); if (!isNaN(size)) { FontDialogController.changePendingSize(newValue); } } // Returns only the fonts that don't fallback to the system default // Based off of https://www.samclarke.com/javascript-is-font-available/ function getAvailableFonts(fonts) { // This creates an element with a large string outside of the view of the browser const container = document.createElement("span"); container.innerHTML = Array(100).join("wi"); container.style.cssText = ["position:absolute", "width:auto", "font-size:128px", "left:-99999px"].join(" !important;"); document.body.append(container); // We're never using a fantasy font like Papyrus, so check if we use the fallback font container.style.fontFamily = "fantasy"; const defaultFontWidth = container.clientWidth; const availableFonts = fonts.filter((font) => { container.style.fontFamily = `${font}, fantasy`; return container.clientWidth !== defaultFontWidth; }); document.body.removeChild(container); return availableFonts; } //# sourceMappingURL=FontDialog.js.map