UNPKG

mui-language-picker

Version:
477 lines (476 loc) 24.7 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LanguagePicker = void 0; var react_1 = __importStar(require("react")); var material_1 = require("@mui/material"); var Clear_1 = __importDefault(require("@mui/icons-material/Clear")); var Settings_1 = __importDefault(require("@mui/icons-material/Settings")); var BorderColor_1 = __importDefault(require("@mui/icons-material/BorderColor")); var LanguageChoice_1 = __importDefault(require("./LanguageChoice")); var bcp47_1 = require("./bcp47"); var langTags_1 = require("./langTags"); var useDebounce_1 = __importDefault(require("./useDebounce")); var GrowingSpacer_1 = require("./GrowingSpacer"); var ChangeName_1 = __importDefault(require("./ChangeName")); var getDisplayName_1 = require("./getDisplayName"); var rtlScripts_1 = __importDefault(require("./data/rtlScripts")); var ChangeFeat_1 = __importDefault(require("./ChangeFeat")); var localization_1 = require("./localization"); // const MAXOPTIONS = 50; var StyledDialog = (0, material_1.styled)(material_1.Dialog)(function () { return ({ '& .MuiDialog-paperScrollPaper': { marginBottom: 'auto', width: '90%', }, }); }); var LanguagePicker = function (props) { var _a; var disabled = props.disabled, offline = props.offline, required = props.required, filter = props.filter, noScript = props.noScript, noFont = props.noFont; var value = props.value, name = props.name, font = props.font, setCode = props.setCode, setName = props.setName, setFont = props.setFont, setInfo = props.setInfo, setDir = props.setDir, t = props.t; var feats = props.feats, setFeats = props.setFeats; var displayName = props.displayName; var _b = react_1.default.useState(false), open = _b[0], setOpen = _b[1]; var _c = react_1.default.useState(value), curValue = _c[0], setCurValue = _c[1]; var _d = react_1.default.useState(name), curName = _d[0], setCurName = _d[1]; var _e = react_1.default.useState(font), curFont = _e[0], setCurFont = _e[1]; var _f = react_1.default.useState(feats), curFeats = _f[0], setCurFeats = _f[1]; var _g = react_1.default.useState(true), secondary = _g[0], setSecondary = _g[1]; var _h = react_1.default.useState(''), response = _h[0], setResponse = _h[1]; var _j = react_1.default.useState(), tag = _j[0], setTag = _j[1]; var _k = react_1.default.useState(''), defaultScript = _k[0], setDefaultScript = _k[1]; var _l = react_1.default.useState(Array()), fontOpts = _l[0], setFontOpts = _l[1]; var _m = react_1.default.useState(false), newName = _m[0], setNewName = _m[1]; var _o = react_1.default.useState(false), newFeat = _o[0], setNewFeat = _o[1]; var langEl = react_1.default.useRef(null); var debouncedResponse = (0, useDebounce_1.default)({ value: response, delay: 500 }); var IpaTag = 'fonipa'; if (!langTags_1.scriptName.has(IpaTag)) langTags_1.scriptName.set(IpaTag, t.phonetic); var respFormat = function (iname, tagVal) { return "".concat(iname, " (").concat(tagVal, ")"); }; var getDefScript = function (val, script) { return val.indexOf(IpaTag) > 0 ? IpaTag : script; }; var handleClickOpen = function (e) { if (disabled) return; if ((e === null || e === void 0 ? void 0 : e.key) && ['Tab', 'Shift', 'Control'].indexOf(e.key) !== -1) return; var found = (0, bcp47_1.bcp47Find)(curValue); if (curValue !== 'und') { if (found && !Array.isArray(found)) { found = __assign(__assign({}, found), { tag: curValue }); var tagName = (0, getDisplayName_1.getDisplayName)(curName, found, displayName); setResponse(respFormat(tagName, curValue)); setTag(found); selectFont(found); setDefaultScript(getDefScript(curValue, found.script)); } else { var key = curValue !== null && curValue !== void 0 ? curValue : ''; if ((0, langTags_1.hasExact)(key)) { setResponse(respFormat(curName, curValue)); var langTag = (0, langTags_1.getExact)(key); if (langTag) { setTag(langTag); selectFont(langTag); setDefaultScript(getDefScript(key, langTag.script)); } } else { handleClear(); } } } setOpen(true); }; react_1.default.useEffect(function () { if (open && curValue === 'und') { setTimeout(function () { if (langEl.current) { langEl.current.click(); } }, 100); } }, [open, curValue]); var handleClear = function () { setFontOpts([]); setResponse(''); setTag(undefined); setDefaultScript(''); if (langEl.current) langEl.current.click(); }; var handleCancel = function () { setCurValue(value); setCurName(name); setCurFont(font); setCurFeats(feats); if (setCode) setCode(value); if (setName) setName(name); if (setFont) setFont(font); setTag(undefined); setDefaultScript(''); setResponse(''); setOpen(false); }; var displayTag = function (tagP, val) { if (tagP && tagP.name) { var tagName = (0, getDisplayName_1.getDisplayName)(tagP.name, tagP, displayName); setResponse(respFormat(tagName, tagP.tag)); setCurValue(val || tagP.tag); setCurName(tagP.name); } }; var handleSelect = function () { if (setCode) setCode(curValue); if (setName) setName(curName); if (setFont) setFont(curFont); if (setFeats) setFeats(curFeats); if (setDir) setDir(rtlScripts_1.default.includes(defaultScript)); if (setInfo && tag) setInfo(tag); if (tag) { displayTag(tag, curValue); } else { setResponse(''); } setTimeout(function () { return setOpen(false); }, 200); }; var handleChange = function (e) { setResponse(e.target.value); }; var addFontInfo = function (e) { setCurFont(e.target.value); }; var safeFonts = [ { value: 'charissil', label: 'Charis SIL (Recommended)', rtl: false }, { value: 'annapurnasil', label: 'Annapurna SIL (Indic)', rtl: false }, { value: 'scheherazadenew', label: 'Scheherazade New (Arabic)', rtl: true }, { value: 'notosanstc', label: 'Noto Sans TC (Chinese)', rtl: false }, ]; var selectDefaultFont = function (iTag, scriptKey) { var _a; var fontFamilies = (_a = langTags_1.fontMap.get(iTag)) !== null && _a !== void 0 ? _a : langTags_1.fontMap.get(scriptKey); if (fontFamilies) { var familyId = fontFamilies[0]; var fontFamily = (0, langTags_1.getFamily)(familyId); if (familyId && fontFamily) { setCurFont(fontFamily.familyid); setFontOpts(fontFamilies.filter(function (f) { return (0, langTags_1.getFamily)(f); })); } } }; var selectFont = function (tagP) { var _a, _b; if (!tagP || tagP.tag === 'und') return; var parse = (0, bcp47_1.bcp47Parse)(tagP.tag); var script = getDefScript(tagP.tag, (_a = parse.script) !== null && _a !== void 0 ? _a : tagP.script); var region = (_b = parse.region) !== null && _b !== void 0 ? _b : tagP.region; var key = script; if (region) { key = script + '-' + region; if (!langTags_1.fontMap.has(key)) { key = script; } } if (!langTags_1.fontMap.has(key)) { setCurFont(safeFonts[0].value); setFontOpts(safeFonts.map(function (f) { return f.value; })); } else selectDefaultFont(tagP.tag, key); }; var hasFonts = (0, react_1.useMemo)(function () { return fontOpts && fontOpts.length > 0; }, [fontOpts]); var handleNewName = function () { setNewName(true); }; var handleCloseName = function () { setNewName(false); }; var handleSetName = function (iname) { setCurName(iname); var tagName = (0, getDisplayName_1.getDisplayName)(iname, tag, displayName); if (tag) setResponse(respFormat(tagName, tag.tag)); }; var handleNewFeat = function () { setNewFeat(true); }; var handleCloseFeat = function () { setNewFeat(false); }; var handleSetFeat = function (iFeats) { setCurFeats(iFeats); }; react_1.default.useEffect(function () { if (response === '') handleClear(); }, [response]); react_1.default.useEffect(function () { setCurValue(value); setCurName(name); setCurFont(font); setResponse(value !== 'und' ? name + ' (' + value + ')' : ''); }, [value, name, font]); var handleScriptChange = function (tagP) { return function (e) { var val = e.target.value; setDefaultScript(val); var parse = (0, bcp47_1.bcp47Parse)(curValue); var script = parse.variant === IpaTag ? IpaTag : parse.script ? parse.script : tagP === null || tagP === void 0 ? void 0 : tagP.script; if (script !== val) { var newTag = parse.language || 'und'; if (val !== IpaTag) newTag += '-' + val; if (parse.region) newTag += '-' + parse.region; var found = (0, bcp47_1.bcp47Find)(newTag); if (found) { var firstFind = Array.isArray(found) ? found[0] : found; setTag(firstFind); var myTag_1 = firstFind.tag; if (val === IpaTag) myTag_1 += "-".concat(IpaTag); else if (parse.variant && parse.variant !== IpaTag) myTag_1 += '-' + parse.variant; if (parse.extension) myTag_1 += '-' + parse.extension; parse.privateUse.forEach(function (i) { myTag_1 += '-x-' + i; }); displayTag(__assign(__assign({}, firstFind), { tag: myTag_1 })); if (val === IpaTag) selectDefaultFont('en', 'Latn'); else selectFont(firstFind); } } }; }; var selectScript = function (tagP) { var _a; var tagParts = (0, bcp47_1.bcp47Parse)(tagP.tag); selectFont(tagP); setDefaultScript(getDefScript(tagP.tag, (_a = tagParts.script) !== null && _a !== void 0 ? _a : tagP.script)); }; var scriptList = function (tagP) { if (!tagP) return []; return (0, langTags_1.getScripts)(tagP.tag.split('-')[0]).concat(IpaTag); }; var handleLanguageClick = function () { if (tag) selectScript(tag); setTag(undefined); }; var handleChoose = function (tagP) { var newTag = tagP; var found = (0, bcp47_1.bcp47Find)(response); var maxMatch = ''; var tagList = [tagP.full, tagP.tag]; if (tagP.iso639_3) { tagList.push(tagP.iso639_3); tagList.push(tagP.iso639_3 + '-' + tagP.script); if (tagP.region) { tagList.push(tagP.iso639_3 + '-' + tagP.region); tagList.push(tagP.iso639_3 + '-' + tagP.script + '-' + tagP.region); } } var parse = (0, bcp47_1.bcp47Parse)(response); if (parse.extlang && parse.language) { tagList.push(parse.language); tagList.push(parse.language + '-' + tagP.script); if (tagP.region) { tagList.push(parse.language + '-' + tagP.region); tagList.push(parse.language + '-' + tagP.script + '-' + tagP.region); } } if (tagP.tags) { tagList = tagList.concat(tagP.tags.map(function (p) { return p; })); } tagList.forEach(function (i) { var tLen = i.length; if (tLen > maxMatch.length) { if (i === response.slice(0, tLen)) { if (response.length === tLen || response[tLen] === '-') { maxMatch = i; } } } }); if (maxMatch !== '') { var newCode = tagP.tag; if (parse.variant && tagP.tag.indexOf(tagP.script) > 0) { newCode = tagP.tag.replace("-".concat(tagP.script), ''); } newTag = __assign(__assign({}, tagP), { tag: newCode + response.slice(maxMatch.length) }); displayTag(newTag); } setTag(newTag); if (maxMatch === '') { if (found === tagP) { newTag = __assign(__assign({}, tagP), { tag: response }); } else if (Array.isArray(found) && found.indexOf(tagP) !== -1) { newTag = __assign(__assign({}, tagP), { tag: response }); } } displayTag(newTag); selectScript(newTag); selectFont(newTag); }; var optList = function () { if (!tag && debouncedResponse) { var list = []; // special case for zh macro language (zh-CN) var search = debouncedResponse.toLowerCase() === 'zh' ? 'zh-CN' : debouncedResponse; var tagLookup = (0, langTags_1.getLangTag)(search); if (tagLookup) { list.push(tagLookup); } // check for a part match var words = debouncedResponse.split(' '); var firstWord = words[0]; if ((0, langTags_1.hasPart)(firstWord)) { var matches = (0, langTags_1.getPart)(firstWord); if (matches) { var result_1 = matches.result; if (list.length > 0) { var exact_1 = list[0].tag; result_1 = result_1.filter(function (e) { return e.tag !== exact_1; }); } if (words.length > 1) { words.slice(1).forEach(function (word) { var nextMatches = (0, langTags_1.getPart)(word); if (nextMatches) { result_1 = result_1.filter(function (e) { return nextMatches.result.includes(e); }); } }); } // put canonical name matches first var canonical_1 = []; var nonCanonical_1 = []; var lcFirst_1 = firstWord.toLowerCase(); result_1.forEach(function (e) { if (e === null || e === void 0 ? void 0 : e.name) { // all valid entries have a name if (e.name.toLowerCase() === lcFirst_1) { canonical_1.push(e); } else { nonCanonical_1.push(e); } } }); list.push.apply(list, __spreadArray(__spreadArray([], canonical_1, false), nonCanonical_1, false)); } } var filtered = list.filter(function (i) { return !filter || filter(i.tag); }); if (filtered.length > 0) { return (react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement(material_1.FormGroup, { row: true, sx: { justifyContent: 'flex-end' } }, react_1.default.createElement(material_1.FormControlLabel, { sx: { flexDirection: 'row-reverse', mr: 0 }, control: react_1.default.createElement(material_1.Checkbox, { checked: secondary, onChange: function (event) { return setSecondary(event.target.checked); }, value: "secondary" }), label: t.details })), react_1.default.createElement(LanguageChoice_1.default, { list: filtered, secondary: secondary, choose: handleChoose, displayName: displayName, t: t }))); } } return react_1.default.createElement(react_1.default.Fragment, null); }; return (react_1.default.createElement("div", { id: "LangBcp47" }, react_1.default.createElement(material_1.TextField, { variant: "filled", margin: "dense", id: "lang-bcp47", label: t.language, required: required, style: { width: 300 }, value: value !== 'und' ? name + ' (' + value + ')' : '', onClick: handleClickOpen, onKeyDown: handleClickOpen, disabled: disabled !== null && disabled !== void 0 ? disabled : false }), react_1.default.createElement(StyledDialog, { id: "LanguagePicker", open: open, onClose: handleCancel, "aria-labelledby": "form-dialog-title" }, react_1.default.createElement(material_1.DialogTitle, { id: "form-dialog-title" }, t.selectLanguage), react_1.default.createElement(material_1.DialogContent, { dividers: true }, react_1.default.createElement(material_1.TextField, { margin: "normal", id: "language", label: t.findALanguage, fullWidth: true, value: response, onChange: handleChange, onClick: handleLanguageClick, variant: "outlined", InputProps: { ref: langEl, endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" }, react_1.default.createElement(material_1.IconButton, { edge: "end", "aria-label": "clear language", onClick: handleClear }, react_1.default.createElement(Clear_1.default, { color: "primary" })))), } }), optList(), !noScript && (react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.TextField, { id: "select-script", "data-testid": "select-script", select: true, sx: { mx: 1 }, fullWidth: true, label: "".concat(t.script, " *"), value: defaultScript, onChange: handleScriptChange(tag), margin: "normal", variant: "filled" }, scriptList(tag) .map(function (s) { return (react_1.default.createElement(material_1.MenuItem, { key: s, value: s }, langTags_1.scriptName.get(s) + ' - ' + s)); }) .concat(scriptList(tag).includes(defaultScript) ? [] : [ react_1.default.createElement(material_1.MenuItem, { key: defaultScript, value: defaultScript }, defaultScript), ])), label: "", sx: { width: '95%' } })), !noFont && (react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Stack, { direction: "row", spacing: 1, sx: { display: 'flex', flexGrow: 1, p: 1 } }, react_1.default.createElement(material_1.TextField, { id: "select-font", "data-testid": "select-font", select: hasFonts, helperText: !hasFonts ? t.noFonts : undefined, sx: { mx: 1 }, fullWidth: true, label: "".concat(t.font).concat(hasFonts ? ' *' : ''), value: fontOpts.includes(curFont) ? curFont : '', onChange: addFontInfo, margin: "normal", variant: "filled" }, fontOpts.map(function (s) { return (react_1.default.createElement(material_1.MenuItem, { key: s, value: s }, (0, langTags_1.displayFamily)(s))); })), setFeats && (react_1.default.createElement(material_1.IconButton, { onClick: handleNewFeat, "data-testid": "change-features", title: t.changeFeatures || localization_1.languagePickerStrings_en.changeFeatures, disabled: !curFont }, react_1.default.createElement(Settings_1.default, { fontSize: "small" })))), label: "", sx: { width: '95%' } }))), react_1.default.createElement(material_1.DialogActions, null, !offline && (react_1.default.createElement("a", { href: "https://www.w3.org/International/questions/qa-choosing-language-tags", target: "_blank", rel: "noopener noreferrer" }, react_1.default.createElement(material_1.Typography, null, t.codeExplained))), curName !== '' && (react_1.default.createElement(material_1.Tooltip, { title: (_a = t.changeName) !== null && _a !== void 0 ? _a : 'Change name' }, react_1.default.createElement(material_1.IconButton, { color: "primary", size: "small", "data-testid": "change-name", onClick: handleNewName }, react_1.default.createElement(BorderColor_1.default, { fontSize: "small" })))), react_1.default.createElement(GrowingSpacer_1.GrowingSpacer, null), react_1.default.createElement(material_1.Button, { onClick: handleCancel, color: "primary" }, react_1.default.createElement(material_1.Typography, null, t.cancel)), react_1.default.createElement(material_1.Button, { onClick: handleSelect, color: "primary", disabled: required && (tag === undefined || (tag === null || tag === void 0 ? void 0 : tag.tag) === 'und' || defaultScript === '') }, react_1.default.createElement(material_1.Typography, null, t.select)))), newName && (react_1.default.createElement(ChangeName_1.default, { isOpen: newName, onClose: handleCloseName, curName: curName, onNewName: handleSetName, t: t })), newFeat && (react_1.default.createElement(ChangeFeat_1.default, { isOpen: newFeat, onClose: handleCloseFeat, curFeats: curFeats, onNewFeat: handleSetFeat, offline: offline, t: t })))); }; exports.LanguagePicker = LanguagePicker; exports.default = exports.LanguagePicker;