mui-language-picker 2.4.2 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,227 +1,236 @@
1
- # mui-language-picker
2
-
3
- Material UI react language picker
4
-
5
- ## Installation
6
-
7
- Complete information for [material-ui](https://mui.com/material-ui/).
8
-
9
- ```sh
10
- npm install mui-language-picker --save
11
- ```
12
-
13
- ## Demo
14
-
15
- [Demo of mui-language-picker](https://giphy.com/embed/5OkWd7aMlxOClWuF0J) / [Same demo as a video](https://youtu.be/aviV8aEaNOo) / [Try it yourself](http://mui-language-picker-demo.org.s3-website-us-east-1.amazonaws.com)
16
-
17
- see also: [demo repo](https://github.com/sillsdev/mui-language-picker-demo)
18
-
19
- ## Usage
20
-
21
- ### TypeScript React 18 code
22
-
23
- ```typescript
24
- import {
25
- LanguagePicker,
26
- ILanguagePickerStrings,
27
- languagePickerStrings_en,
28
- LangTag,
29
- } from "mui-language-picker";
30
-
31
- const MyComponent = (props: any) => {
32
- const [bcp47, setBcp47] = React.useState("und");
33
- const [lgName, setLgName] = React.useState("");
34
- const [fontName, setFontName] = React.useState("");
35
- const [rtl, setRtl] = React.useState(false);
36
- const [tag, setTag] = React.useState<LangTag>();
37
-
38
- const displayName = (name: string, tag?: LangTag) => {
39
- return tag?.localname ? `${tag?.localname} / ${name}` : tag?.name || name;
40
- };
41
-
42
- return (
43
- <LanguagePicker
44
- value={bcp47}
45
- setCode={setBcp47}
46
- name={lgName}
47
- setName={setLgName}
48
- font={fontName}
49
- setFont={setFontName}
50
- setDir={setRtl}
51
- displayName={displayName}
52
- setInfo={setTag}
53
- t={languagePickerStrings_en}
54
- />
55
- );
56
- };
57
- ```
58
-
59
- ```sh
60
- Output should be a Language Picker when entered opens a dialog
61
- ```
62
-
63
- ### Parameter definitions
64
-
65
- | Parameter | Type | Meaning |
66
- | ---------- | ----------------------- | ----------------------------------- |
67
- | value | string | BCP 47 language code |
68
- | setCode\* | (value: string) => void | callback to change BCP 47 value |
69
- | name | string | language name |
70
- | setName\* | (name: string) => void | callback to change language name |
71
- | font | string | font family name |
72
- | setFont\* | (font: string) => void | callback to change font family name |
73
- | setDir\* | (rtl: boolean) => void | callback to change script direction |
74
- | displayName\* | DisplayName | function to control display of name |
75
- | setInfo\* | (tag: LangTag) => void | callback to receive tag information |
76
- | filter\* | (tag: LangTag) => boolean | allows filtering languages found by tag |
77
- | disabled\* | boolean | true if control disabled |
78
- | offline\* | boolean | true if picker in offline setting |
79
- | required\* | boolean | true if language required (show *) |
80
- | t | ILanguagePickerStrings | localization strings (see below) |
81
-
82
- \* parameters marked with an asterisk are optional
83
-
84
- ### Helper functions
85
-
86
- ```typescript
87
- import {
88
- getLangTag,
89
- getRtl,
90
- getFamily
91
- } from "mui-language-picker";
92
-
93
- console.log(getLangTag(tag)) // Return langTag object (see below)
94
- console.log(getRtl(tag)) // returns true if rtl script
95
- console.log(getFamily(familyId)) // Returns fontFamily object (see below)
96
- ```
97
-
98
- The `fontName` returned by the Language Picker is the `familyId`. Refer to [fonts.languagetechnology.org](https://fonts.languagetechnology.org/) for more information.
99
-
100
- ### Localization Strings
101
-
102
- ```typescript
103
- export const languagePickerStrings_en = {
104
- font: 'Font',
105
- script: 'Script',
106
- language: 'Language',
107
- selectLanguage: 'Choose Language Details',
108
- findALanguage: 'Find a language by name, code, or country',
109
- codeExplained: 'Code Explained',
110
- subtags: 'Subtags',
111
- details: 'Details',
112
- languageOf: 'A Language of $1$2.',
113
- inScript: ' in the $1 script',
114
- select: 'Save',
115
- cancel: 'Cancel',
116
- phonetic: 'Phonetic',
117
- changeName: 'Change Name',
118
- nameInstruction:
119
- 'If you would like to change the language name enter the new name here.',
120
- newName: 'New Language Name',
121
- change: 'Change',
122
- noFonts: 'No recommended fonts',
123
- } as ILanguagePickerStrings;
124
- ```
125
-
126
- ### Information returned by setInfo
127
-
128
- ```typescript
129
- export interface LangTag {
130
- full: string;
131
- iana?: string[];
132
- iso639_3?: string;
133
- localname?: string;
134
- localnames?: string[];
135
- name: string;
136
- names?: string[];
137
- nophonvars?: boolean;
138
- region?: string;
139
- regionname?: string;
140
- regions?: string[];
141
- script: string;
142
- sldr: boolean;
143
- suppress?: boolean;
144
- tag: string;
145
- tags?: string[];
146
- variants?: string[];
147
- defaultFont?: string;
148
- fonts?: string[];
149
- windows?: string;
150
- }
151
- ```
152
-
153
- ### Information returned by getFamily
154
-
155
- ```typescript
156
- export interface IFamily {
157
- defaults?: {
158
- ttf: string;
159
- woff?: string;
160
- woff2?: string;
161
- };
162
- distributable: boolean;
163
- fallback?: string;
164
- family: string;
165
- familyid: string;
166
- files?: {
167
- [fileid: string]: {
168
- axes: {
169
- ital?: number;
170
- wght: number;
171
- };
172
- flourl?: string;
173
- packagepath: string;
174
- url?: string;
175
- zippath?: string;
176
- };
177
- };
178
- license?: 'OFL' | 'GPL3' | 'GPL' | 'Freeware' | 'proprietary' | 'shareware';
179
- packageurl?: string;
180
- siteurl?: string;
181
- source?:
182
- | 'SIL'
183
- | 'Google'
184
- | 'Microsoft'
185
- | 'NLCI'
186
- | 'STAR'
187
- | 'Evertype'
188
- | 'Lao Script';
189
- status?: 'current' | 'archived' | 'deprecated';
190
- version?: string;
191
- ziproot?: string;
192
- }
193
- ```
194
-
195
- ### Change control background
196
-
197
- If the theme involves using a dark background, the control background can be changed with css. See also [material-ui](https://mui.com/) documentation.
198
-
199
- ```css
200
- #LangBcp47 .MuiFilledInput-root {
201
- background-color: rgba(255, 255, 255, 0.9);
202
- }
203
- ```
204
-
205
- ### Build
206
-
207
- ```sh
208
- npm install
209
- npm run data
210
- npm run index
211
- npm run build
212
- ```
213
-
214
- ### Test
215
-
216
- ```sh
217
- npm run clean
218
- npm test
219
- ```
220
-
221
- ### Testing Individual Suites
222
-
223
- Here is an example for Language Picker tests:
224
-
225
- ```sh
226
- npm test -- --watch LanguagePicker
227
- ```
1
+ # mui-language-picker
2
+
3
+ Material UI react language picker
4
+
5
+ ## Installation
6
+
7
+ Complete information for [material-ui](https://mui.com/material-ui/).
8
+
9
+ ```sh
10
+ npm install mui-language-picker --save
11
+ ```
12
+
13
+ ## Demo
14
+
15
+ [Demo of mui-language-picker](https://giphy.com/embed/5OkWd7aMlxOClWuF0J) / [Same demo as a video](https://youtu.be/aviV8aEaNOo) / [Try it yourself](http://mui-language-picker-demo.org.s3-website-us-east-1.amazonaws.com)
16
+
17
+ see also: [demo repo](https://github.com/sillsdev/mui-language-picker-demo)
18
+
19
+ ## Usage
20
+
21
+ ### TypeScript React 18 code
22
+
23
+ ```typescript
24
+ import {
25
+ LanguagePicker,
26
+ ILanguagePickerStrings,
27
+ languagePickerStrings_en,
28
+ LangTag,
29
+ } from "mui-language-picker";
30
+
31
+ const MyComponent = (props: any) => {
32
+ const [bcp47, setBcp47] = React.useState("und");
33
+ const [lgName, setLgName] = React.useState("");
34
+ const [fontName, setFontName] = React.useState("");
35
+ const [rtl, setRtl] = React.useState(false);
36
+ const [tag, setTag] = React.useState<LangTag>();
37
+
38
+ const displayName = (name: string, tag?: LangTag) => {
39
+ return tag?.localname ? `${tag?.localname} / ${name}` : tag?.name || name;
40
+ };
41
+
42
+ return (
43
+ <LanguagePicker
44
+ value={bcp47}
45
+ setCode={setBcp47}
46
+ name={lgName}
47
+ setName={setLgName}
48
+ font={fontName}
49
+ setFont={setFontName}
50
+ setDir={setRtl}
51
+ displayName={displayName}
52
+ setInfo={setTag}
53
+ t={languagePickerStrings_en}
54
+ />
55
+ );
56
+ };
57
+ ```
58
+
59
+ ```sh
60
+ Output should be a Language Picker when entered opens a dialog
61
+ ```
62
+
63
+ ### Parameter definitions
64
+
65
+ | Parameter | Type | Meaning |
66
+ | ---------- | ----------------------- | ----------------------------------- |
67
+ | value | string | BCP 47 language code |
68
+ | setCode\* | (value: string) => void | callback to change BCP 47 value |
69
+ | name | string | language name |
70
+ | setName\* | (name: string) => void | callback to change language name |
71
+ | font | string | font family name |
72
+ | setFont\* | (font: string) => void | callback to change font family name |
73
+ | feats\* | string | font features |
74
+ | setFeats\* | (feats: string) => void | callback to change font features |
75
+ | setDir\* | (rtl: boolean) => void | callback to change script direction |
76
+ | displayName\* | DisplayName | function to control display of name |
77
+ | setInfo\* | (tag: LangTag) => void | callback to receive tag information |
78
+ | filter\* | (tag: LangTag) => boolean | allows filtering languages found by tag |
79
+ | disabled\* | boolean | true if control disabled |
80
+ | offline\* | boolean | true if picker in offline setting |
81
+ | required\* | boolean | true if language required (show *) |
82
+ | t | ILanguagePickerStrings | localization strings (see below) |
83
+
84
+ \* parameters marked with an asterisk are optional
85
+
86
+ The `feats` parameter is formtted like the font-feature-settings css property.
87
+ See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings) for more information.
88
+
89
+ ### Helper functions
90
+
91
+ ```typescript
92
+ import {
93
+ getLangTag,
94
+ getRtl,
95
+ getFamily
96
+ } from "mui-language-picker";
97
+
98
+ console.log(getLangTag(tag)) // Return langTag object (see below)
99
+ console.log(getRtl(tag)) // returns true if rtl script
100
+ console.log(getFamily(familyId)) // Returns fontFamily object (see below)
101
+ ```
102
+
103
+ The `fontName` returned by the Language Picker is the `familyId`. Refer to [fonts.languagetechnology.org](https://fonts.languagetechnology.org/) for more information.
104
+
105
+ ### Localization Strings
106
+
107
+ ```typescript
108
+ export const languagePickerStrings_en = {
109
+ font: 'Font',
110
+ script: 'Script',
111
+ language: 'Language',
112
+ selectLanguage: 'Choose Language Details',
113
+ findALanguage: 'Find a language by name, code, or country',
114
+ codeExplained: 'Code Explained',
115
+ subtags: 'Subtags',
116
+ details: 'Details',
117
+ languageOf: 'A Language of $1$2.',
118
+ inScript: ' in the $1 script',
119
+ select: 'Save',
120
+ cancel: 'Cancel',
121
+ phonetic: 'Phonetic',
122
+ changeName: 'Change Name',
123
+ nameInstruction:
124
+ 'If you would like to change the language name enter the new name here.',
125
+ changeFeatures: 'Change Features',
126
+ featureInstruction:
127
+ 'Font feastures are optional. They are four characters followed by an optional number.',
128
+ invalidFeature: 'Invalid Feature',
129
+ newName: 'New Language Name',
130
+ change: 'Change',
131
+ noFonts: 'No recommended fonts',
132
+ } as ILanguagePickerStrings;
133
+ ```
134
+
135
+ ### Information returned by setInfo
136
+
137
+ ```typescript
138
+ export interface LangTag {
139
+ full: string;
140
+ iana?: string[];
141
+ iso639_3?: string;
142
+ localname?: string;
143
+ localnames?: string[];
144
+ name: string;
145
+ names?: string[];
146
+ nophonvars?: boolean;
147
+ region?: string;
148
+ regionname?: string;
149
+ regions?: string[];
150
+ script: string;
151
+ sldr: boolean;
152
+ suppress?: boolean;
153
+ tag: string;
154
+ tags?: string[];
155
+ variants?: string[];
156
+ defaultFont?: string;
157
+ fonts?: string[];
158
+ windows?: string;
159
+ }
160
+ ```
161
+
162
+ ### Information returned by getFamily
163
+
164
+ ```typescript
165
+ export interface IFamily {
166
+ defaults?: {
167
+ ttf: string;
168
+ woff?: string;
169
+ woff2?: string;
170
+ };
171
+ distributable: boolean;
172
+ fallback?: string;
173
+ family: string;
174
+ familyid: string;
175
+ files?: {
176
+ [fileid: string]: {
177
+ axes: {
178
+ ital?: number;
179
+ wght: number;
180
+ };
181
+ flourl?: string;
182
+ packagepath: string;
183
+ url?: string;
184
+ zippath?: string;
185
+ };
186
+ };
187
+ license?: 'OFL' | 'GPL3' | 'GPL' | 'Freeware' | 'proprietary' | 'shareware';
188
+ packageurl?: string;
189
+ siteurl?: string;
190
+ source?:
191
+ | 'SIL'
192
+ | 'Google'
193
+ | 'Microsoft'
194
+ | 'NLCI'
195
+ | 'STAR'
196
+ | 'Evertype'
197
+ | 'Lao Script';
198
+ status?: 'current' | 'archived' | 'deprecated';
199
+ version?: string;
200
+ ziproot?: string;
201
+ }
202
+ ```
203
+
204
+ ### Change control background
205
+
206
+ If the theme involves using a dark background, the control background can be changed with css. See also [material-ui](https://mui.com/) documentation.
207
+
208
+ ```css
209
+ #LangBcp47 .MuiFilledInput-root {
210
+ background-color: rgba(255, 255, 255, 0.9);
211
+ }
212
+ ```
213
+
214
+ ### Build
215
+
216
+ ```sh
217
+ npm install
218
+ npm run data
219
+ npm run index
220
+ npm run build
221
+ ```
222
+
223
+ ### Test
224
+
225
+ ```sh
226
+ npm run clean
227
+ npm test
228
+ ```
229
+
230
+ ### Testing Individual Suites
231
+
232
+ Here is an example for Language Picker tests:
233
+
234
+ ```sh
235
+ npm test -- --watch LanguagePicker
236
+ ```
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { ILanguagePickerStrings } from './model';
3
+ interface IProps {
4
+ isOpen: boolean;
5
+ onClose?: () => void;
6
+ curFeats?: string;
7
+ onNewFeat?: (feats: string) => void;
8
+ offline?: boolean;
9
+ t?: ILanguagePickerStrings;
10
+ }
11
+ export default function ChangeFeat({ isOpen, onClose, curFeats, onNewFeat, offline, t, }: IProps): React.JSX.Element;
12
+ export {};
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ var react_1 = __importDefault(require("react"));
7
+ var Button_1 = __importDefault(require("@mui/material/Button"));
8
+ var TextField_1 = __importDefault(require("@mui/material/TextField"));
9
+ var Dialog_1 = __importDefault(require("@mui/material/Dialog"));
10
+ var DialogActions_1 = __importDefault(require("@mui/material/DialogActions"));
11
+ var DialogContent_1 = __importDefault(require("@mui/material/DialogContent"));
12
+ var DialogContentText_1 = __importDefault(require("@mui/material/DialogContentText"));
13
+ var DialogTitle_1 = __importDefault(require("@mui/material/DialogTitle"));
14
+ var Info_1 = __importDefault(require("@mui/icons-material/Info"));
15
+ var localization_1 = require("./localization");
16
+ var material_1 = require("@mui/material");
17
+ function ChangeFeat(_a) {
18
+ var isOpen = _a.isOpen, onClose = _a.onClose, curFeats = _a.curFeats, onNewFeat = _a.onNewFeat, _b = _a.offline, offline = _b === void 0 ? false : _b, t = _a.t;
19
+ var _c = react_1.default.useState(isOpen), openFeat = _c[0], setOpenFeat = _c[1];
20
+ var _d = react_1.default.useState(false), openAdd = _d[0], setOpenAdd = _d[1];
21
+ var _e = react_1.default.useState([]), chipData = _e[0], setChipData = _e[1];
22
+ var _f = react_1.default.useState(''), oneFeat = _f[0], setOneFeat = _f[1];
23
+ var _g = react_1.default.useState(1), nextKey = _g[0], setNextKey = _g[1];
24
+ var _h = react_1.default.useState(''), helpText = _h[0], setHelpText = _h[1];
25
+ react_1.default.useEffect(function () {
26
+ if (curFeats) {
27
+ var n_1 = 0;
28
+ var feats = curFeats
29
+ .split(',')
30
+ .map(function (feat) {
31
+ var m = /^"(\w\w\w\w)"\s*([0-9]?)$/.exec(feat.trim());
32
+ if (!m)
33
+ return undefined;
34
+ return {
35
+ key: ++n_1,
36
+ label: m[2] ? "".concat(m[1], " ").concat(m[2]) : m[1],
37
+ };
38
+ })
39
+ .filter(function (v) { return Boolean(v); });
40
+ setChipData(feats);
41
+ }
42
+ }, [curFeats]);
43
+ var makeCssFeat = function (chipValue) {
44
+ var m = /^(\w\w\w\w)\s*([0-9]?)$/.exec(chipValue.trim());
45
+ return m ? (m[2] ? "\"".concat(m[1], "\" ").concat(m[2]) : "\"".concat(m[1], "\"")) : '';
46
+ };
47
+ var handleCloseFeatures = function (save) { return function () {
48
+ if (save && onNewFeat) {
49
+ onNewFeat(chipData.map(function (chip) { return makeCssFeat(chip.label); }).join(', '));
50
+ }
51
+ if (onClose)
52
+ onClose();
53
+ setOpenFeat(false);
54
+ }; };
55
+ react_1.default.useEffect(function () {
56
+ setOpenFeat(isOpen);
57
+ }, [isOpen]);
58
+ var handleDelete = function (chipToDelete) { return function () {
59
+ setChipData(function (chips) {
60
+ return chips.filter(function (chip) { return chip.key !== chipToDelete.key; });
61
+ });
62
+ }; };
63
+ var handleAdd = function () {
64
+ setOneFeat('');
65
+ setOpenAdd(true);
66
+ };
67
+ var handleCloseAdd = function (label) { return function () {
68
+ if (label && !makeCssFeat(label)) {
69
+ setHelpText((t === null || t === void 0 ? void 0 : t.invalidFeature) || localization_1.languagePickerStrings_en.invalidFeature || '');
70
+ return;
71
+ }
72
+ if (label) {
73
+ setChipData(chipData.concat([{ key: nextKey, label: label }]));
74
+ setNextKey(nextKey + 1);
75
+ }
76
+ setOpenAdd(false);
77
+ setHelpText('');
78
+ }; };
79
+ var handleSelect = function (chipToSelect) { return function () {
80
+ setOneFeat(chipToSelect.label);
81
+ setOpenAdd(true);
82
+ }; };
83
+ var handleChange = function (event) {
84
+ setOneFeat(event.target.value);
85
+ };
86
+ return (react_1.default.createElement(Dialog_1.default, { open: openFeat, onClose: handleCloseFeatures() },
87
+ react_1.default.createElement(DialogTitle_1.default, null, (t === null || t === void 0 ? void 0 : t.changeFeatures) || localization_1.languagePickerStrings_en.changeFeatures),
88
+ react_1.default.createElement(DialogContent_1.default, null,
89
+ react_1.default.createElement(DialogContentText_1.default, null,
90
+ react_1.default.createElement(react_1.default.Fragment, null,
91
+ (t === null || t === void 0 ? void 0 : t.featureInstruction) || localization_1.languagePickerStrings_en.featureInstruction,
92
+ ' ',
93
+ !offline && (react_1.default.createElement("a", { href: "https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/OpenType_fonts_guide#Font_features", title: (t === null || t === void 0 ? void 0 : t.openTypeFeatures) || localization_1.languagePickerStrings_en.openTypeFeatures, target: "_blank", rel: "noopener noreferrer" },
94
+ react_1.default.createElement(Info_1.default, { fontSize: "small" }))))),
95
+ react_1.default.createElement(react_1.default.Fragment, null,
96
+ react_1.default.createElement(material_1.Paper, { sx: {
97
+ display: 'flex',
98
+ justifyContent: 'center',
99
+ flexWrap: 'wrap',
100
+ listStyle: 'none',
101
+ flexDirection: 'row',
102
+ p: 0.5,
103
+ m: 0,
104
+ }, component: "ul" }, chipData
105
+ .map(function (data) {
106
+ return (react_1.default.createElement(material_1.ListItem, { key: data.key, sx: { width: 'auto' } },
107
+ react_1.default.createElement(material_1.Chip, { label: data.label, onClick: handleSelect(data), onDelete: chipData.length > 0 ? handleDelete(data) : undefined })));
108
+ })
109
+ .concat([
110
+ react_1.default.createElement(material_1.ListItem, { key: 99, sx: { width: 'auto' } },
111
+ react_1.default.createElement(material_1.Chip, { label: (t === null || t === void 0 ? void 0 : t.addFeature) || localization_1.languagePickerStrings_en.addFeature, "data-testid": "add-feature", onClick: handleAdd })),
112
+ ])),
113
+ react_1.default.createElement(Dialog_1.default, { open: openAdd, onClose: handleCloseAdd(undefined) },
114
+ react_1.default.createElement(DialogTitle_1.default, null, (t === null || t === void 0 ? void 0 : t.addFeatureTitle) || localization_1.languagePickerStrings_en.addFeatureTitle),
115
+ react_1.default.createElement(DialogContent_1.default, null,
116
+ react_1.default.createElement(DialogContentText_1.default, null, (t === null || t === void 0 ? void 0 : t.addFeatureInstruction) || localization_1.languagePickerStrings_en.addFeatureInstruction),
117
+ react_1.default.createElement(TextField_1.default, { autoFocus: true, margin: "dense", id: "feature", "data-testid": "feature-input", label: (t === null || t === void 0 ? void 0 : t.featureInput) || localization_1.languagePickerStrings_en.featureInput, fullWidth: true, variant: "standard", value: oneFeat, onChange: handleChange, helperText: helpText })),
118
+ react_1.default.createElement(DialogActions_1.default, null,
119
+ react_1.default.createElement(Button_1.default, { onClick: handleCloseAdd(undefined) }, (t === null || t === void 0 ? void 0 : t.cancel) || localization_1.languagePickerStrings_en.cancel),
120
+ react_1.default.createElement(Button_1.default, { onClick: handleCloseAdd(oneFeat), "data-testid": "do-add-feature" }, (t === null || t === void 0 ? void 0 : t.addFeature) || localization_1.languagePickerStrings_en.addFeature))))),
121
+ react_1.default.createElement(DialogActions_1.default, null,
122
+ react_1.default.createElement(Button_1.default, { onClick: handleCloseFeatures() }, (t === null || t === void 0 ? void 0 : t.cancel) || localization_1.languagePickerStrings_en.cancel),
123
+ react_1.default.createElement(Button_1.default, { onClick: handleCloseFeatures(true) }, (t === null || t === void 0 ? void 0 : t.change) || localization_1.languagePickerStrings_en.change))));
124
+ }
125
+ exports.default = ChangeFeat;
@@ -9,10 +9,12 @@ interface IProps extends IStateProps {
9
9
  value: string;
10
10
  name: string;
11
11
  font: string;
12
+ feats?: string;
12
13
  displayName?: DisplayName;
13
14
  setCode?: (code: string) => void;
14
15
  setName?: (name: string) => void;
15
16
  setFont?: (font: string) => void;
17
+ setFeats?: (features?: string) => void;
16
18
  setInfo?: (tag: LangTag) => void;
17
19
  setDir?: (rtl: boolean) => void;
18
20
  filter?: (code: string) => boolean;