@megafon/ui-core 4.15.2 → 4.15.4

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/CHANGELOG.md CHANGED
@@ -3,6 +3,29 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [4.15.4](https://github.com/MegafonWebLab/megafon-ui/compare/@megafon/ui-core@4.15.3...@megafon/ui-core@4.15.4) (2023-04-17)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **tabs:** fixed gradient on swiper edges ([650e9be](https://github.com/MegafonWebLab/megafon-ui/commit/650e9beea8318ccf7bf564b4473a9d3487457694))
12
+
13
+
14
+
15
+
16
+
17
+ ## [4.15.3](https://github.com/MegafonWebLab/megafon-ui/compare/@megafon/ui-core@4.15.2...@megafon/ui-core@4.15.3) (2023-04-14)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **tabs:** fixed tabs scroll on mobile resolution, set hover for desktop ([f18da75](https://github.com/MegafonWebLab/megafon-ui/commit/f18da7552911bca92ea1b1229c70ecad810d30ae))
23
+ * **textfield:** add a correct count of the graphemes entered ([8e51585](https://github.com/MegafonWebLab/megafon-ui/commit/8e515856193eefa8a63fd17cab3faab7737ad41d))
24
+
25
+
26
+
27
+
28
+
6
29
  ## [4.15.2](https://github.com/MegafonWebLab/megafon-ui/compare/@megafon/ui-core@4.15.1...@megafon/ui-core@4.15.2) (2023-04-11)
7
30
 
8
31
 
@@ -15,50 +15,52 @@
15
15
  justify-content: center;
16
16
  }
17
17
  .mfui-tabs__swiper-wrapper {
18
+ position: relative;
18
19
  display: -webkit-box;
19
20
  display: -ms-flexbox;
20
21
  display: flex;
21
22
  width: 100%;
22
23
  }
23
- .mfui-tabs__swiper {
24
- font-family: inherit;
25
- font-size: 15px;
26
- line-height: 24px;
27
- font-weight: 500;
28
- position: relative;
29
- display: inline-block;
30
- width: 100%;
31
- padding: 4px;
32
- border-radius: 12px;
33
- overflow: hidden;
34
- background-color: var(--spbSky0);
35
- }
36
- .mfui-tabs__swiper:before,
37
- .mfui-tabs__swiper:after {
24
+ .mfui-tabs__swiper-wrapper:before,
25
+ .mfui-tabs__swiper-wrapper:after {
38
26
  content: '';
39
27
  position: absolute;
40
28
  top: 0;
41
29
  bottom: 0;
42
30
  z-index: 1;
43
31
  width: 64px;
32
+ border-radius: 0 12px 12px 0;
44
33
  background: -webkit-gradient(linear, right top, left top, from(var(--stcBlack5)), color-stop(64%, transparent));
45
34
  background: linear-gradient(270deg, var(--stcBlack5) 0%, transparent 64%);
46
35
  pointer-events: none;
47
36
  }
48
- .mfui-tabs__swiper:before {
37
+ .mfui-tabs__swiper-wrapper:before {
49
38
  left: 0;
50
39
  -webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
51
40
  transform: matrix(-1, 0, 0, 1, 0, 0);
52
41
  }
53
- .mfui-tabs__swiper:after {
42
+ .mfui-tabs__swiper-wrapper:after {
54
43
  right: 0;
55
44
  }
56
- .mfui-tabs__swiper_beginning:before {
45
+ .mfui-tabs__swiper-wrapper_beginning:before {
57
46
  display: none;
58
47
  }
59
- .mfui-tabs__swiper_end:after {
48
+ .mfui-tabs__swiper-wrapper_end:after {
60
49
  display: none;
61
50
  }
51
+ .mfui-tabs__swiper {
52
+ font-family: inherit;
53
+ font-size: 15px;
54
+ line-height: 24px;
55
+ font-weight: 500;
56
+ position: relative;
57
+ display: inline-block;
58
+ width: 100%;
59
+ padding: 4px;
60
+ border-radius: 12px;
61
+ overflow: hidden;
62
+ background-color: var(--spbSky0);
63
+ }
62
64
  .mfui-tabs__slide {
63
65
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
64
66
  -webkit-box-flex: 1;
@@ -160,9 +162,11 @@
160
162
  .mfui-tabs__tab-inner:hover {
161
163
  text-decoration: none;
162
164
  }
163
- .mfui-tabs__tab-inner:not(.mfui-tabs__tab-inner_current):hover {
164
- color: var(--content);
165
- fill: var(--content);
165
+ @media screen and (min-width: 1024px) {
166
+ .mfui-tabs__tab-inner:not(.mfui-tabs__tab-inner_current):hover {
167
+ color: var(--content);
168
+ fill: var(--content);
169
+ }
166
170
  }
167
171
  .mfui-tabs__tab-inner:not(.mfui-tabs__tab-inner_current):active {
168
172
  color: var(--buttonDown);
@@ -249,11 +249,11 @@ var Tabs = function Tabs(_ref) {
249
249
  var handleNextArrowClick = React.useCallback(function () {
250
250
  swiperInstance === null || swiperInstance === void 0 ? void 0 : swiperInstance.slideNext();
251
251
  }, [swiperInstance]);
252
- var handleReachBeginning = React.useCallback(function (swiper) {
253
- setBeginning(swiper.isBeginning);
252
+ var handleReachBeginning = React.useCallback(function () {
253
+ setBeginning(true);
254
254
  }, []);
255
- var handleReachEnd = React.useCallback(function (swiper) {
256
- setEnd(swiper.isEnd);
255
+ var handleReachEnd = React.useCallback(function () {
256
+ setEnd(true);
257
257
  }, []);
258
258
  var handleFromEdge = React.useCallback(function (swiper) {
259
259
  setBeginning(swiper.isBeginning);
@@ -316,7 +316,7 @@ var Tabs = function Tabs(_ref) {
316
316
  ref: setTabRef(i)
317
317
  }, filterDataAttrs(data === null || data === void 0 ? void 0 : data.root, i + 1)), renderTabWrapper ? renderTabWrapper(tab) : tab));
318
318
  });
319
- }, [renderTab, children, classes === null || classes === void 0 ? void 0 : classes.activeTab, currentIndex, setTabRef, classes === null || classes === void 0 ? void 0 : classes.tab]);
319
+ }, [children, renderTab, currentIndex, classes === null || classes === void 0 ? void 0 : classes.activeTab, classes === null || classes === void 0 ? void 0 : classes.tab, setTabRef]);
320
320
  var renderPanels = React.useCallback(function () {
321
321
  return React.Children.map(children, function (child, i) {
322
322
  var panel = child.props.children;
@@ -402,17 +402,17 @@ var Tabs = function Tabs(_ref) {
402
402
  }, filterDataAttrs(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.wrapper), {
403
403
  className: cn('wrapper', [classes === null || classes === void 0 ? void 0 : classes.wrapper])
404
404
  }), /*#__PURE__*/React.createElement("div", _extends({
405
- className: cn('swiper-wrapper', [classes === null || classes === void 0 ? void 0 : classes.swiperWrapper]),
405
+ className: cn('swiper-wrapper', {
406
+ beginning: isBeginning,
407
+ end: isEnd
408
+ }, [classes === null || classes === void 0 ? void 0 : classes.swiperWrapper]),
406
409
  style: {
407
410
  paddingLeft: stickyOffset.left,
408
411
  paddingRight: stickyOffset.right
409
412
  }
410
413
  }, filterDataAttrs(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.swiperWrapper)), /*#__PURE__*/React.createElement(Swiper, _extends({}, filterDataAttrs(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.slider), {
411
414
  simulateTouch: false,
412
- className: cn('swiper', {
413
- beginning: isBeginning,
414
- end: isEnd
415
- }, [classes === null || classes === void 0 ? void 0 : classes.innerIndents]),
415
+ className: cn('swiper', [classes === null || classes === void 0 ? void 0 : classes.innerIndents]),
416
416
  watchOverflow: true,
417
417
  slidesPerView: "auto",
418
418
  initialSlide: currentIndex,
@@ -56,6 +56,14 @@ export declare type TextFieldProps = {
56
56
  maxLength?: number;
57
57
  /** Показывает счетчик с подсчетом введенных символов. Только для textarea. */
58
58
  symbolCounter?: number;
59
+ /** Включает подсчет введенных [графем](https://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D1%84%D0%B5%D0%BC%D0%B0) и символов при `symbolCounter=true`
60
+ *
61
+ * **Пример**: эмоджи 👩‍💻 - это одна графема, состоящая из 5 символов.
62
+ *
63
+ * - для `true` Количество символов в строке "hello world👩‍💻" = 12
64
+ * - для `false` Количество символов в строке "hello world👩‍💻" = 16
65
+ */
66
+ graphemesCounter?: boolean;
59
67
  /** Иконка */
60
68
  customIcon?: JSX.Element;
61
69
  /** Маска для поля. Не работает с textarea=true. */
@@ -15,6 +15,7 @@ import throttle from 'lodash.throttle';
15
15
  import * as PropTypes from 'prop-types';
16
16
  import InputMask from 'react-input-mask';
17
17
  import throttleTime from "../../constants/throttleTime";
18
+ import countGraphemes from "./utils/countGraphemes";
18
19
  import "./TextField.css";
19
20
 
20
21
  var Hide = function Hide(props) {
@@ -96,6 +97,7 @@ var TextField = function TextField(_ref) {
96
97
  mask = _ref.mask,
97
98
  maskChar = _ref.maskChar,
98
99
  maxLength = _ref.maxLength,
100
+ graphemesCounter = _ref.graphemesCounter,
99
101
  symbolCounter = _ref.symbolCounter,
100
102
  _ref$textarea = _ref.textarea,
101
103
  textarea = _ref$textarea === void 0 ? false : _ref$textarea,
@@ -191,8 +193,9 @@ var TextField = function TextField(_ref) {
191
193
  return;
192
194
  }
193
195
 
194
- setIsMaxLimitExceeded(symbolCounter < String(textareaValue).length);
195
- }, [symbolCounter]);
196
+ var countValue = graphemesCounter ? countGraphemes(String(textareaValue)) : String(textareaValue).length;
197
+ setIsMaxLimitExceeded(symbolCounter < countValue);
198
+ }, [graphemesCounter, symbolCounter]);
196
199
  useEffect(function () {
197
200
  if (!textarea || !fieldNode.current || isTextareaResized) {
198
201
  return;
@@ -325,7 +328,7 @@ var TextField = function TextField(_ref) {
325
328
  onBlur: handleBlur,
326
329
  onFocus: handleFocus,
327
330
  onKeyUp: onKeyUp,
328
- maxLength: maxLength,
331
+ maxLength: (graphemesCounter && maxLength && countGraphemes(String(inputValue)) < maxLength ? -1 : maxLength) || maxLength,
329
332
  placeholder: hidePlaceholder ? ' ' : actualPlaceholder,
330
333
  required: required,
331
334
  inputMode: inputMode
@@ -451,7 +454,7 @@ var TextField = function TextField(_ref) {
451
454
 
452
455
  var isPlaceholderShowed = isPasswordType && isPasswordHidden && !!inputValue;
453
456
  var valueHasSymbols = inputValue !== null && inputValue !== undefined;
454
- var currentSymbolCount = valueHasSymbols && String(inputValue).length || 0;
457
+ var currentSymbolCount = valueHasSymbols && (graphemesCounter && countGraphemes(String(inputValue)) || String(inputValue).length) || 0;
455
458
  return /*#__PURE__*/React.createElement("div", _extends({}, filterDataAttrs(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.root), {
456
459
  className: cn({
457
460
  disabled: disabled,
@@ -503,6 +506,7 @@ TextField.propTypes = {
503
506
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
504
507
  maxLength: PropTypes.number,
505
508
  symbolCounter: PropTypes.number,
509
+ graphemesCounter: PropTypes.bool,
506
510
  customIcon: PropTypes.element,
507
511
  mask: PropTypes.string,
508
512
  maskChar: PropTypes.string,
@@ -0,0 +1,2 @@
1
+ declare const countGraphemes: (text: string) => number;
2
+ export default countGraphemes;
@@ -0,0 +1,52 @@
1
+ import "core-js/modules/es.array.from";
2
+ import "core-js/modules/es.date.to-string";
3
+ import "core-js/modules/es.object.to-string";
4
+ import "core-js/modules/es.regexp.exec";
5
+ import "core-js/modules/es.regexp.to-string";
6
+ import "core-js/modules/es.string.iterator";
7
+ import "core-js/modules/es.string.replace";
8
+ var regex = /[\uFE00-\uFE0F]|(?:\uD83C[\uDFFB-\uDFFF])/g;
9
+ var regexSymbolWithCombiningMarks = /((?:[\0-\u02FF\u0370-\u0482\u048A-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u060F\u061B-\u064A\u0660-\u066F\u0671-\u06D5\u06DD\u06DE\u06E5\u06E6\u06E9\u06EE-\u0710\u0712-\u072F\u074B-\u07A5\u07B1-\u07EA\u07F4-\u07FC\u07FE-\u0815\u081A\u0824\u0828\u082E-\u0858\u085C-\u08D2\u08E2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0964-\u0980\u0984-\u09BB\u09BD\u09C5\u09C6\u09C9\u09CA\u09CE-\u09D6\u09D8-\u09E1\u09E4-\u09FD\u09FF\u0A00\u0A04-\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A6F\u0A72-\u0A74\u0A76-\u0A80\u0A84-\u0ABB\u0ABD\u0AC6\u0ACA\u0ACE-\u0AE1\u0AE4-\u0AF9\u0B00\u0B04-\u0B3B\u0B3D\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B61\u0B64-\u0B81\u0B83-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE-\u0BD6\u0BD8-\u0BFF\u0C05-\u0C3D\u0C45\u0C49\u0C4E-\u0C54\u0C57-\u0C61\u0C64-\u0C80\u0C84-\u0CBB\u0CBD\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CE1\u0CE4-\u0CFF\u0D04-\u0D3A\u0D3D\u0D45\u0D49\u0D4E-\u0D56\u0D58-\u0D61\u0D64-\u0D80\u0D84-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF4-\u0E30\u0E32\u0E33\u0E3B-\u0E46\u0E4F-\u0EB0\u0EB2\u0EB3\u0EBD-\u0EC7\u0ECE-\u0F17\u0F1A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F40-\u0F70\u0F85\u0F88-\u0F8C\u0F98\u0FBD-\u0FC5\u0FC7-\u102A\u103F-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u109E-\u135C\u1360-\u1711\u1715-\u1731\u1735-\u1751\u1754-\u1771\u1774-\u17B3\u17D4-\u17DC\u17DE-\u180A\u180E-\u1884\u1887-\u18A8\u18AA-\u191F\u192C-\u192F\u193C-\u1A16\u1A1C-\u1A54\u1A5F\u1A7D\u1A7E\u1A80-\u1AAF\u1AC1-\u1AFF\u1B05-\u1B33\u1B45-\u1B6A\u1B74-\u1B7F\u1B83-\u1BA0\u1BAE-\u1BE5\u1BF4-\u1C23\u1C38-\u1CCF\u1CD3\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA-\u1DBF\u1DFA\u1E00-\u20CF\u20F1-\u2CEE\u2CF2-\u2D7E\u2D80-\u2DDF\u2E00-\u3029\u3030-\u3098\u309B-\uA66E\uA673\uA67E-\uA69D\uA6A0-\uA6EF\uA6F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA828-\uA82B\uA82D-\uA87F\uA882-\uA8B3\uA8C6-\uA8DF\uA8F2-\uA8FE\uA900-\uA925\uA92E-\uA946\uA954-\uA97F\uA984-\uA9B2\uA9C1-\uA9E4\uA9E6-\uAA28\uAA37-\uAA42\uAA44-\uAA4B\uAA4E-\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2-\uAAEA\uAAF0-\uAAF4\uAAF7-\uABE2\uABEB\uABEE-\uD7FF\uE000-\uFB1D\uFB1F-\uFDFF\uFE10-\uFE1F\uFE30-\uFFFF]|\uD800[\uDC00-\uDDFC\uDDFE-\uDEDF\uDEE1-\uDF75\uDF7B-\uDFFF]|[\uD801\uD808-\uD819\uD81C-\uD82E\uD830-\uD833\uD835\uD837\uD839\uD83B-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD802[\uDC00-\uDE00\uDE04\uDE07-\uDE0B\uDE10-\uDE37\uDE3B-\uDE3E\uDE40-\uDEE4\uDEE7-\uDFFF]|\uD803[\uDC00-\uDD23\uDD28-\uDEAA\uDEAD-\uDF45\uDF51-\uDFFF]|\uD804[\uDC03-\uDC37\uDC47-\uDC7E\uDC83-\uDCAF\uDCBB-\uDCFF\uDD03-\uDD26\uDD35-\uDD44\uDD47-\uDD72\uDD74-\uDD7F\uDD83-\uDDB2\uDDC1-\uDDC8\uDDCD\uDDD0-\uDE2B\uDE38-\uDE3D\uDE3F-\uDEDE\uDEEB-\uDEFF\uDF04-\uDF3A\uDF3D\uDF45\uDF46\uDF49\uDF4A\uDF4E-\uDF56\uDF58-\uDF61\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC00-\uDC34\uDC47-\uDC5D\uDC5F-\uDCAF\uDCC4-\uDDAE\uDDB6\uDDB7\uDDC1-\uDDDB\uDDDE-\uDE2F\uDE41-\uDEAA\uDEB8-\uDF1C\uDF2C-\uDFFF]|\uD806[\uDC00-\uDC2B\uDC3B-\uDD2F\uDD36\uDD39\uDD3A\uDD3F\uDD41\uDD44-\uDDD0\uDDD8\uDDD9\uDDE1-\uDDE3\uDDE5-\uDE00\uDE0B-\uDE32\uDE3A\uDE3F-\uDE46\uDE48-\uDE50\uDE5C-\uDE89\uDE9A-\uDFFF]|\uD807[\uDC00-\uDC2E\uDC37\uDC40-\uDC91\uDCA8\uDCB7-\uDD30\uDD37-\uDD39\uDD3B\uDD3E\uDD46\uDD48-\uDD89\uDD8F\uDD92\uDD98-\uDEF2\uDEF7-\uDFFF]|\uD81A[\uDC00-\uDEEF\uDEF5-\uDF2F\uDF37-\uDFFF]|\uD81B[\uDC00-\uDF4E\uDF50\uDF88-\uDF8E\uDF93-\uDFE3\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD82F[\uDC00-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDD2F\uDD37-\uDEEB\uDEF0-\uDFFF]|\uD83A[\uDC00-\uDCCF\uDCD7-\uDD43\uDD4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))((?:[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1AC0\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD24-\uDD27\uDEAB\uDEAC\uDF46-\uDF50]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD45\uDD46\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDC9-\uDDCC\uDDCE\uDDCF\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3B\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDC5E\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7\uDF1D-\uDF2B]|\uD806[\uDC2C-\uDC3A\uDD30-\uDD35\uDD37\uDD38\uDD3B-\uDD3E\uDD40\uDD42\uDD43\uDDD1-\uDDD7\uDDDA-\uDDE0\uDDE4\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE3E\uDE47\uDE51-\uDE5B\uDE8A-\uDE99]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD31-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD45\uDD47\uDD8A-\uDD8E\uDD90\uDD91\uDD93-\uDD97\uDEF3-\uDEF6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF4F\uDF51-\uDF87\uDF8F-\uDF92\uDFE4\uDFF0\uDFF1]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD30-\uDD36\uDEEC-\uDEEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDD00-\uDDEF])+)/g;
10
+ var joiner = '200d'; // eslint-disable-next-line no-magic-numbers
11
+
12
+ var isJoiner = function isJoiner(_char) {
13
+ return _char.charCodeAt(0).toString(16) === joiner;
14
+ };
15
+
16
+ var countGraphemes = function countGraphemes(text) {
17
+ var normalizedText = text.normalize('NFC').replace(regex, '').replace(regexSymbolWithCombiningMarks, function (_, symbol) {
18
+ return symbol;
19
+ });
20
+ var tokens = Array.from(normalizedText);
21
+ var length = 0;
22
+ var isComplexChar = false;
23
+
24
+ for (var i = 0; i < tokens.length; i++) {
25
+ var _char2 = tokens[i];
26
+ var nextChar = tokens[i + 1];
27
+
28
+ if (!nextChar) {
29
+ length += 1; // eslint-disable-next-line no-continue
30
+
31
+ continue;
32
+ }
33
+
34
+ if (isJoiner(nextChar)) {
35
+ isComplexChar = true; // eslint-disable-next-line no-continue
36
+
37
+ continue;
38
+ }
39
+
40
+ if (!isJoiner(_char2) && isComplexChar) {
41
+ isComplexChar = false;
42
+ }
43
+
44
+ if (!isComplexChar) {
45
+ length += 1;
46
+ }
47
+ }
48
+
49
+ return length;
50
+ };
51
+
52
+ export default countGraphemes;
@@ -10,6 +10,7 @@ export { default as checkBreakpointsPropTypes } from './components/Carousel/chec
10
10
  export { default as Collapse } from './components/Collapse/Collapse';
11
11
  export { default as ContentArea } from './components/ContentArea/ContentArea';
12
12
  export { default as Counter } from './components/Counter/Counter';
13
+ export { default as countGraphemes } from './components/TextField/utils/countGraphemes';
13
14
  export { default as Day } from './components/Calendar/components/Day/Day';
14
15
  export { default as Grid } from './components/Grid/Grid';
15
16
  export { default as GridColumn } from './components/Grid/GridColumn';
package/dist/es/index.js CHANGED
@@ -10,6 +10,7 @@ export { default as checkBreakpointsPropTypes } from "./components/Carousel/chec
10
10
  export { default as Collapse } from "./components/Collapse/Collapse";
11
11
  export { default as ContentArea } from "./components/ContentArea/ContentArea";
12
12
  export { default as Counter } from "./components/Counter/Counter";
13
+ export { default as countGraphemes } from "./components/TextField/utils/countGraphemes";
13
14
  export { default as Day } from "./components/Calendar/components/Day/Day";
14
15
  export { default as Grid } from "./components/Grid/Grid";
15
16
  export { default as GridColumn } from "./components/Grid/GridColumn";
@@ -15,50 +15,52 @@
15
15
  justify-content: center;
16
16
  }
17
17
  .mfui-tabs__swiper-wrapper {
18
+ position: relative;
18
19
  display: -webkit-box;
19
20
  display: -ms-flexbox;
20
21
  display: flex;
21
22
  width: 100%;
22
23
  }
23
- .mfui-tabs__swiper {
24
- font-family: inherit;
25
- font-size: 15px;
26
- line-height: 24px;
27
- font-weight: 500;
28
- position: relative;
29
- display: inline-block;
30
- width: 100%;
31
- padding: 4px;
32
- border-radius: 12px;
33
- overflow: hidden;
34
- background-color: var(--spbSky0);
35
- }
36
- .mfui-tabs__swiper:before,
37
- .mfui-tabs__swiper:after {
24
+ .mfui-tabs__swiper-wrapper:before,
25
+ .mfui-tabs__swiper-wrapper:after {
38
26
  content: '';
39
27
  position: absolute;
40
28
  top: 0;
41
29
  bottom: 0;
42
30
  z-index: 1;
43
31
  width: 64px;
32
+ border-radius: 0 12px 12px 0;
44
33
  background: -webkit-gradient(linear, right top, left top, from(var(--stcBlack5)), color-stop(64%, transparent));
45
34
  background: linear-gradient(270deg, var(--stcBlack5) 0%, transparent 64%);
46
35
  pointer-events: none;
47
36
  }
48
- .mfui-tabs__swiper:before {
37
+ .mfui-tabs__swiper-wrapper:before {
49
38
  left: 0;
50
39
  -webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
51
40
  transform: matrix(-1, 0, 0, 1, 0, 0);
52
41
  }
53
- .mfui-tabs__swiper:after {
42
+ .mfui-tabs__swiper-wrapper:after {
54
43
  right: 0;
55
44
  }
56
- .mfui-tabs__swiper_beginning:before {
45
+ .mfui-tabs__swiper-wrapper_beginning:before {
57
46
  display: none;
58
47
  }
59
- .mfui-tabs__swiper_end:after {
48
+ .mfui-tabs__swiper-wrapper_end:after {
60
49
  display: none;
61
50
  }
51
+ .mfui-tabs__swiper {
52
+ font-family: inherit;
53
+ font-size: 15px;
54
+ line-height: 24px;
55
+ font-weight: 500;
56
+ position: relative;
57
+ display: inline-block;
58
+ width: 100%;
59
+ padding: 4px;
60
+ border-radius: 12px;
61
+ overflow: hidden;
62
+ background-color: var(--spbSky0);
63
+ }
62
64
  .mfui-tabs__slide {
63
65
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
64
66
  -webkit-box-flex: 1;
@@ -160,9 +162,11 @@
160
162
  .mfui-tabs__tab-inner:hover {
161
163
  text-decoration: none;
162
164
  }
163
- .mfui-tabs__tab-inner:not(.mfui-tabs__tab-inner_current):hover {
164
- color: var(--content);
165
- fill: var(--content);
165
+ @media screen and (min-width: 1024px) {
166
+ .mfui-tabs__tab-inner:not(.mfui-tabs__tab-inner_current):hover {
167
+ color: var(--content);
168
+ fill: var(--content);
169
+ }
166
170
  }
167
171
  .mfui-tabs__tab-inner:not(.mfui-tabs__tab-inner_current):active {
168
172
  color: var(--buttonDown);
@@ -280,11 +280,11 @@ var Tabs = function Tabs(_ref) {
280
280
  var handleNextArrowClick = React.useCallback(function () {
281
281
  swiperInstance === null || swiperInstance === void 0 ? void 0 : swiperInstance.slideNext();
282
282
  }, [swiperInstance]);
283
- var handleReachBeginning = React.useCallback(function (swiper) {
284
- setBeginning(swiper.isBeginning);
283
+ var handleReachBeginning = React.useCallback(function () {
284
+ setBeginning(true);
285
285
  }, []);
286
- var handleReachEnd = React.useCallback(function (swiper) {
287
- setEnd(swiper.isEnd);
286
+ var handleReachEnd = React.useCallback(function () {
287
+ setEnd(true);
288
288
  }, []);
289
289
  var handleFromEdge = React.useCallback(function (swiper) {
290
290
  setBeginning(swiper.isBeginning);
@@ -347,7 +347,7 @@ var Tabs = function Tabs(_ref) {
347
347
  ref: setTabRef(i)
348
348
  }, (0, _uiHelpers.filterDataAttrs)(data === null || data === void 0 ? void 0 : data.root, i + 1)), renderTabWrapper ? renderTabWrapper(tab) : tab));
349
349
  });
350
- }, [renderTab, children, classes === null || classes === void 0 ? void 0 : classes.activeTab, currentIndex, setTabRef, classes === null || classes === void 0 ? void 0 : classes.tab]);
350
+ }, [children, renderTab, currentIndex, classes === null || classes === void 0 ? void 0 : classes.activeTab, classes === null || classes === void 0 ? void 0 : classes.tab, setTabRef]);
351
351
  var renderPanels = React.useCallback(function () {
352
352
  return React.Children.map(children, function (child, i) {
353
353
  var panel = child.props.children;
@@ -433,17 +433,17 @@ var Tabs = function Tabs(_ref) {
433
433
  }, (0, _uiHelpers.filterDataAttrs)(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.wrapper), {
434
434
  className: cn('wrapper', [classes === null || classes === void 0 ? void 0 : classes.wrapper])
435
435
  }), /*#__PURE__*/React.createElement("div", (0, _extends2["default"])({
436
- className: cn('swiper-wrapper', [classes === null || classes === void 0 ? void 0 : classes.swiperWrapper]),
436
+ className: cn('swiper-wrapper', {
437
+ beginning: isBeginning,
438
+ end: isEnd
439
+ }, [classes === null || classes === void 0 ? void 0 : classes.swiperWrapper]),
437
440
  style: {
438
441
  paddingLeft: stickyOffset.left,
439
442
  paddingRight: stickyOffset.right
440
443
  }
441
444
  }, (0, _uiHelpers.filterDataAttrs)(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.swiperWrapper)), /*#__PURE__*/React.createElement(_react2.Swiper, (0, _extends2["default"])({}, (0, _uiHelpers.filterDataAttrs)(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.slider), {
442
445
  simulateTouch: false,
443
- className: cn('swiper', {
444
- beginning: isBeginning,
445
- end: isEnd
446
- }, [classes === null || classes === void 0 ? void 0 : classes.innerIndents]),
446
+ className: cn('swiper', [classes === null || classes === void 0 ? void 0 : classes.innerIndents]),
447
447
  watchOverflow: true,
448
448
  slidesPerView: "auto",
449
449
  initialSlide: currentIndex,
@@ -56,6 +56,14 @@ export declare type TextFieldProps = {
56
56
  maxLength?: number;
57
57
  /** Показывает счетчик с подсчетом введенных символов. Только для textarea. */
58
58
  symbolCounter?: number;
59
+ /** Включает подсчет введенных [графем](https://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D1%84%D0%B5%D0%BC%D0%B0) и символов при `symbolCounter=true`
60
+ *
61
+ * **Пример**: эмоджи 👩‍💻 - это одна графема, состоящая из 5 символов.
62
+ *
63
+ * - для `true` Количество символов в строке "hello world👩‍💻" = 12
64
+ * - для `false` Количество символов в строке "hello world👩‍💻" = 16
65
+ */
66
+ graphemesCounter?: boolean;
59
67
  /** Иконка */
60
68
  customIcon?: JSX.Element;
61
69
  /** Маска для поля. Не работает с textarea=true. */
@@ -35,6 +35,8 @@ var _reactInputMask = _interopRequireDefault(require("react-input-mask"));
35
35
 
36
36
  var _throttleTime = _interopRequireDefault(require("../../constants/throttleTime"));
37
37
 
38
+ var _countGraphemes = _interopRequireDefault(require("./utils/countGraphemes"));
39
+
38
40
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
39
41
 
40
42
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -124,6 +126,7 @@ var TextField = function TextField(_ref) {
124
126
  mask = _ref.mask,
125
127
  maskChar = _ref.maskChar,
126
128
  maxLength = _ref.maxLength,
129
+ graphemesCounter = _ref.graphemesCounter,
127
130
  symbolCounter = _ref.symbolCounter,
128
131
  _ref$textarea = _ref.textarea,
129
132
  textarea = _ref$textarea === void 0 ? false : _ref$textarea,
@@ -219,8 +222,9 @@ var TextField = function TextField(_ref) {
219
222
  return;
220
223
  }
221
224
 
222
- setIsMaxLimitExceeded(symbolCounter < String(textareaValue).length);
223
- }, [symbolCounter]);
225
+ var countValue = graphemesCounter ? (0, _countGraphemes["default"])(String(textareaValue)) : String(textareaValue).length;
226
+ setIsMaxLimitExceeded(symbolCounter < countValue);
227
+ }, [graphemesCounter, symbolCounter]);
224
228
  (0, React.useEffect)(function () {
225
229
  if (!textarea || !fieldNode.current || isTextareaResized) {
226
230
  return;
@@ -352,7 +356,7 @@ var TextField = function TextField(_ref) {
352
356
  onBlur: handleBlur,
353
357
  onFocus: handleFocus,
354
358
  onKeyUp: onKeyUp,
355
- maxLength: maxLength,
359
+ maxLength: (graphemesCounter && maxLength && (0, _countGraphemes["default"])(String(inputValue)) < maxLength ? -1 : maxLength) || maxLength,
356
360
  placeholder: hidePlaceholder ? ' ' : actualPlaceholder,
357
361
  required: required,
358
362
  inputMode: inputMode
@@ -475,7 +479,7 @@ var TextField = function TextField(_ref) {
475
479
 
476
480
  var isPlaceholderShowed = isPasswordType && isPasswordHidden && !!inputValue;
477
481
  var valueHasSymbols = inputValue !== null && inputValue !== undefined;
478
- var currentSymbolCount = valueHasSymbols && String(inputValue).length || 0;
482
+ var currentSymbolCount = valueHasSymbols && (graphemesCounter && (0, _countGraphemes["default"])(String(inputValue)) || String(inputValue).length) || 0;
479
483
  return /*#__PURE__*/React.createElement("div", (0, _extends2["default"])({}, (0, _uiHelpers.filterDataAttrs)(dataAttrs === null || dataAttrs === void 0 ? void 0 : dataAttrs.root), {
480
484
  className: cn({
481
485
  disabled: disabled,
@@ -527,6 +531,7 @@ TextField.propTypes = {
527
531
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
528
532
  maxLength: PropTypes.number,
529
533
  symbolCounter: PropTypes.number,
534
+ graphemesCounter: PropTypes.bool,
530
535
  customIcon: PropTypes.element,
531
536
  mask: PropTypes.string,
532
537
  maskChar: PropTypes.string,
@@ -0,0 +1,2 @@
1
+ declare const countGraphemes: (text: string) => number;
2
+ export default countGraphemes;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+
8
+ require("core-js/modules/es.array.from");
9
+
10
+ require("core-js/modules/es.date.to-string");
11
+
12
+ require("core-js/modules/es.object.to-string");
13
+
14
+ require("core-js/modules/es.regexp.exec");
15
+
16
+ require("core-js/modules/es.regexp.to-string");
17
+
18
+ require("core-js/modules/es.string.iterator");
19
+
20
+ require("core-js/modules/es.string.replace");
21
+
22
+ var regex = /[\uFE00-\uFE0F]|(?:\uD83C[\uDFFB-\uDFFF])/g;
23
+ var regexSymbolWithCombiningMarks = /((?:[\0-\u02FF\u0370-\u0482\u048A-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u060F\u061B-\u064A\u0660-\u066F\u0671-\u06D5\u06DD\u06DE\u06E5\u06E6\u06E9\u06EE-\u0710\u0712-\u072F\u074B-\u07A5\u07B1-\u07EA\u07F4-\u07FC\u07FE-\u0815\u081A\u0824\u0828\u082E-\u0858\u085C-\u08D2\u08E2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0964-\u0980\u0984-\u09BB\u09BD\u09C5\u09C6\u09C9\u09CA\u09CE-\u09D6\u09D8-\u09E1\u09E4-\u09FD\u09FF\u0A00\u0A04-\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A6F\u0A72-\u0A74\u0A76-\u0A80\u0A84-\u0ABB\u0ABD\u0AC6\u0ACA\u0ACE-\u0AE1\u0AE4-\u0AF9\u0B00\u0B04-\u0B3B\u0B3D\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B61\u0B64-\u0B81\u0B83-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE-\u0BD6\u0BD8-\u0BFF\u0C05-\u0C3D\u0C45\u0C49\u0C4E-\u0C54\u0C57-\u0C61\u0C64-\u0C80\u0C84-\u0CBB\u0CBD\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CE1\u0CE4-\u0CFF\u0D04-\u0D3A\u0D3D\u0D45\u0D49\u0D4E-\u0D56\u0D58-\u0D61\u0D64-\u0D80\u0D84-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF4-\u0E30\u0E32\u0E33\u0E3B-\u0E46\u0E4F-\u0EB0\u0EB2\u0EB3\u0EBD-\u0EC7\u0ECE-\u0F17\u0F1A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F40-\u0F70\u0F85\u0F88-\u0F8C\u0F98\u0FBD-\u0FC5\u0FC7-\u102A\u103F-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u109E-\u135C\u1360-\u1711\u1715-\u1731\u1735-\u1751\u1754-\u1771\u1774-\u17B3\u17D4-\u17DC\u17DE-\u180A\u180E-\u1884\u1887-\u18A8\u18AA-\u191F\u192C-\u192F\u193C-\u1A16\u1A1C-\u1A54\u1A5F\u1A7D\u1A7E\u1A80-\u1AAF\u1AC1-\u1AFF\u1B05-\u1B33\u1B45-\u1B6A\u1B74-\u1B7F\u1B83-\u1BA0\u1BAE-\u1BE5\u1BF4-\u1C23\u1C38-\u1CCF\u1CD3\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA-\u1DBF\u1DFA\u1E00-\u20CF\u20F1-\u2CEE\u2CF2-\u2D7E\u2D80-\u2DDF\u2E00-\u3029\u3030-\u3098\u309B-\uA66E\uA673\uA67E-\uA69D\uA6A0-\uA6EF\uA6F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA828-\uA82B\uA82D-\uA87F\uA882-\uA8B3\uA8C6-\uA8DF\uA8F2-\uA8FE\uA900-\uA925\uA92E-\uA946\uA954-\uA97F\uA984-\uA9B2\uA9C1-\uA9E4\uA9E6-\uAA28\uAA37-\uAA42\uAA44-\uAA4B\uAA4E-\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2-\uAAEA\uAAF0-\uAAF4\uAAF7-\uABE2\uABEB\uABEE-\uD7FF\uE000-\uFB1D\uFB1F-\uFDFF\uFE10-\uFE1F\uFE30-\uFFFF]|\uD800[\uDC00-\uDDFC\uDDFE-\uDEDF\uDEE1-\uDF75\uDF7B-\uDFFF]|[\uD801\uD808-\uD819\uD81C-\uD82E\uD830-\uD833\uD835\uD837\uD839\uD83B-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD802[\uDC00-\uDE00\uDE04\uDE07-\uDE0B\uDE10-\uDE37\uDE3B-\uDE3E\uDE40-\uDEE4\uDEE7-\uDFFF]|\uD803[\uDC00-\uDD23\uDD28-\uDEAA\uDEAD-\uDF45\uDF51-\uDFFF]|\uD804[\uDC03-\uDC37\uDC47-\uDC7E\uDC83-\uDCAF\uDCBB-\uDCFF\uDD03-\uDD26\uDD35-\uDD44\uDD47-\uDD72\uDD74-\uDD7F\uDD83-\uDDB2\uDDC1-\uDDC8\uDDCD\uDDD0-\uDE2B\uDE38-\uDE3D\uDE3F-\uDEDE\uDEEB-\uDEFF\uDF04-\uDF3A\uDF3D\uDF45\uDF46\uDF49\uDF4A\uDF4E-\uDF56\uDF58-\uDF61\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC00-\uDC34\uDC47-\uDC5D\uDC5F-\uDCAF\uDCC4-\uDDAE\uDDB6\uDDB7\uDDC1-\uDDDB\uDDDE-\uDE2F\uDE41-\uDEAA\uDEB8-\uDF1C\uDF2C-\uDFFF]|\uD806[\uDC00-\uDC2B\uDC3B-\uDD2F\uDD36\uDD39\uDD3A\uDD3F\uDD41\uDD44-\uDDD0\uDDD8\uDDD9\uDDE1-\uDDE3\uDDE5-\uDE00\uDE0B-\uDE32\uDE3A\uDE3F-\uDE46\uDE48-\uDE50\uDE5C-\uDE89\uDE9A-\uDFFF]|\uD807[\uDC00-\uDC2E\uDC37\uDC40-\uDC91\uDCA8\uDCB7-\uDD30\uDD37-\uDD39\uDD3B\uDD3E\uDD46\uDD48-\uDD89\uDD8F\uDD92\uDD98-\uDEF2\uDEF7-\uDFFF]|\uD81A[\uDC00-\uDEEF\uDEF5-\uDF2F\uDF37-\uDFFF]|\uD81B[\uDC00-\uDF4E\uDF50\uDF88-\uDF8E\uDF93-\uDFE3\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD82F[\uDC00-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDD2F\uDD37-\uDEEB\uDEF0-\uDFFF]|\uD83A[\uDC00-\uDCCF\uDCD7-\uDD43\uDD4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))((?:[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1AC0\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD24-\uDD27\uDEAB\uDEAC\uDF46-\uDF50]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD45\uDD46\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDC9-\uDDCC\uDDCE\uDDCF\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3B\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDC5E\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7\uDF1D-\uDF2B]|\uD806[\uDC2C-\uDC3A\uDD30-\uDD35\uDD37\uDD38\uDD3B-\uDD3E\uDD40\uDD42\uDD43\uDDD1-\uDDD7\uDDDA-\uDDE0\uDDE4\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE3E\uDE47\uDE51-\uDE5B\uDE8A-\uDE99]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD31-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD45\uDD47\uDD8A-\uDD8E\uDD90\uDD91\uDD93-\uDD97\uDEF3-\uDEF6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF4F\uDF51-\uDF87\uDF8F-\uDF92\uDFE4\uDFF0\uDFF1]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD30-\uDD36\uDEEC-\uDEEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDD00-\uDDEF])+)/g;
24
+ var joiner = '200d'; // eslint-disable-next-line no-magic-numbers
25
+
26
+ var isJoiner = function isJoiner(_char) {
27
+ return _char.charCodeAt(0).toString(16) === joiner;
28
+ };
29
+
30
+ var countGraphemes = function countGraphemes(text) {
31
+ var normalizedText = text.normalize('NFC').replace(regex, '').replace(regexSymbolWithCombiningMarks, function (_, symbol) {
32
+ return symbol;
33
+ });
34
+ var tokens = Array.from(normalizedText);
35
+ var length = 0;
36
+ var isComplexChar = false;
37
+
38
+ for (var i = 0; i < tokens.length; i++) {
39
+ var _char2 = tokens[i];
40
+ var nextChar = tokens[i + 1];
41
+
42
+ if (!nextChar) {
43
+ length += 1; // eslint-disable-next-line no-continue
44
+
45
+ continue;
46
+ }
47
+
48
+ if (isJoiner(nextChar)) {
49
+ isComplexChar = true; // eslint-disable-next-line no-continue
50
+
51
+ continue;
52
+ }
53
+
54
+ if (!isJoiner(_char2) && isComplexChar) {
55
+ isComplexChar = false;
56
+ }
57
+
58
+ if (!isComplexChar) {
59
+ length += 1;
60
+ }
61
+ }
62
+
63
+ return length;
64
+ };
65
+
66
+ var _default = countGraphemes;
67
+ exports["default"] = _default;
@@ -10,6 +10,7 @@ export { default as checkBreakpointsPropTypes } from './components/Carousel/chec
10
10
  export { default as Collapse } from './components/Collapse/Collapse';
11
11
  export { default as ContentArea } from './components/ContentArea/ContentArea';
12
12
  export { default as Counter } from './components/Counter/Counter';
13
+ export { default as countGraphemes } from './components/TextField/utils/countGraphemes';
13
14
  export { default as Day } from './components/Calendar/components/Day/Day';
14
15
  export { default as Grid } from './components/Grid/Grid';
15
16
  export { default as GridColumn } from './components/Grid/GridColumn';
package/dist/lib/index.js CHANGED
@@ -75,6 +75,12 @@ Object.defineProperty(exports, "Counter", {
75
75
  return _Counter["default"];
76
76
  }
77
77
  });
78
+ Object.defineProperty(exports, "countGraphemes", {
79
+ enumerable: true,
80
+ get: function get() {
81
+ return _countGraphemes["default"];
82
+ }
83
+ });
78
84
  Object.defineProperty(exports, "Day", {
79
85
  enumerable: true,
80
86
  get: function get() {
@@ -310,6 +316,8 @@ var _ContentArea = _interopRequireDefault(require("./components/ContentArea/Cont
310
316
 
311
317
  var _Counter = _interopRequireDefault(require("./components/Counter/Counter"));
312
318
 
319
+ var _countGraphemes = _interopRequireDefault(require("./components/TextField/utils/countGraphemes"));
320
+
313
321
  var _Day = _interopRequireDefault(require("./components/Calendar/components/Day/Day"));
314
322
 
315
323
  var _Grid = _interopRequireDefault(require("./components/Grid/Grid"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@megafon/ui-core",
3
- "version": "4.15.2",
3
+ "version": "4.15.4",
4
4
  "files": [
5
5
  "dist",
6
6
  "styles"
@@ -100,5 +100,5 @@
100
100
  "react-popper": "^2.2.3",
101
101
  "swiper": "^6.5.6"
102
102
  },
103
- "gitHead": "c2d54353eccef1c32cac6aa03b91d48e98dcdb84"
103
+ "gitHead": "72a7d359c1674e80571a8af13466bedefdbbcecd"
104
104
  }