@gravity-ui/navigation 0.14.0 → 0.16.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.
Files changed (43) hide show
  1. package/build/cjs/components/AsideHeader/AsideHeader.d.ts +5 -3
  2. package/build/cjs/components/AsideHeader/__stories__/moc.d.ts +2 -0
  3. package/build/cjs/components/AsideHeader/i18n/index.d.ts +2 -0
  4. package/build/cjs/components/CompositeBar/CompositeBar.d.ts +11 -7
  5. package/build/cjs/components/CompositeBar/utils.d.ts +6 -4
  6. package/build/cjs/components/MobileHeader/Burger/Burger.d.ts +5 -2
  7. package/build/cjs/components/MobileHeader/MobileHeader.d.ts +2 -0
  8. package/build/cjs/components/MobileHeader/i18n/index.d.ts +2 -0
  9. package/build/cjs/components/Settings/Settings.d.ts +4 -7
  10. package/build/cjs/components/Settings/i18n/index.d.ts +2 -0
  11. package/build/cjs/components/Title/Title.d.ts +1 -3
  12. package/build/cjs/components/Title/i18n/index.d.ts +2 -0
  13. package/build/cjs/components/constants.d.ts +0 -7
  14. package/build/cjs/components/index.d.ts +1 -0
  15. package/build/cjs/components/types.d.ts +2 -10
  16. package/build/cjs/components/utils/registerKeyset.d.ts +5 -0
  17. package/build/cjs/i18n.d.ts +2 -0
  18. package/build/cjs/index.js +322 -62
  19. package/build/cjs/index.js.map +1 -1
  20. package/build/esm/components/AsideHeader/AsideHeader.d.ts +5 -3
  21. package/build/esm/components/AsideHeader/__stories__/moc.d.ts +2 -0
  22. package/build/esm/components/AsideHeader/i18n/index.d.ts +2 -0
  23. package/build/esm/components/CompositeBar/CompositeBar.d.ts +11 -7
  24. package/build/esm/components/CompositeBar/utils.d.ts +6 -4
  25. package/build/esm/components/MobileHeader/Burger/Burger.d.ts +5 -2
  26. package/build/esm/components/MobileHeader/MobileHeader.d.ts +2 -0
  27. package/build/esm/components/MobileHeader/i18n/index.d.ts +2 -0
  28. package/build/esm/components/Settings/Settings.d.ts +4 -7
  29. package/build/esm/components/Settings/i18n/index.d.ts +2 -0
  30. package/build/esm/components/Title/Title.d.ts +1 -3
  31. package/build/esm/components/Title/i18n/index.d.ts +2 -0
  32. package/build/esm/components/constants.d.ts +0 -7
  33. package/build/esm/components/index.d.ts +1 -0
  34. package/build/esm/components/types.d.ts +2 -10
  35. package/build/esm/components/utils/registerKeyset.d.ts +5 -0
  36. package/build/esm/i18n.d.ts +2 -0
  37. package/build/esm/index.js +322 -63
  38. package/build/esm/index.js.map +1 -1
  39. package/package.json +2 -1
  40. package/build/cjs/components/CompositeBar/__stories__/CompositeBar.stories.d.ts +0 -5
  41. package/build/cjs/components/CompositeBar/__stories__/moc.d.ts +0 -2
  42. package/build/esm/components/CompositeBar/__stories__/CompositeBar.stories.d.ts +0 -5
  43. package/build/esm/components/CompositeBar/__stories__/moc.d.ts +0 -2
@@ -67,28 +67,9 @@ function block(name) {
67
67
  return _default(`${NAMESPACE}${name}`);
68
68
  }
69
69
 
70
- var MobileHeaderDict;
71
- (function (MobileHeaderDict) {
72
- MobileHeaderDict["CloseBurger"] = "button_close-burger";
73
- MobileHeaderDict["OpenBurger"] = "button_open-burger";
74
- })(MobileHeaderDict || (MobileHeaderDict = {}));
75
- var Dict;
76
- (function (Dict) {
77
- Dict["ExpandButton"] = "button_expand";
78
- Dict["CollapseButton"] = "button_collapse";
79
- Dict["MoreButton"] = "button_more";
80
- })(Dict || (Dict = {}));
81
-
82
70
  const ASIDE_HEADER_FOOTER_ICON_SIZE = 20;
83
71
  const ASIDE_HEADER_COMPACT_WIDTH = 56;
84
72
  const ASIDE_HEADER_EXPANDED_WIDTH = 236;
85
- const defaultDict$2 = {
86
- [Dict.CollapseButton]: 'Collapse',
87
- [Dict.ExpandButton]: 'Expand',
88
- [Dict.MoreButton]: 'More',
89
- [MobileHeaderDict.CloseBurger]: 'Close menu',
90
- [MobileHeaderDict.OpenBurger]: 'Open menu',
91
- };
92
73
 
93
74
  function _extends$2() {
94
75
  _extends$2 = Object.assign ? Object.assign.bind() : function (target) {
@@ -1357,7 +1338,7 @@ function removeClass$1(element, className) {
1357
1338
  }
1358
1339
  }
1359
1340
 
1360
- var config = {
1341
+ var config$1 = {
1361
1342
  disabled: false
1362
1343
  };
1363
1344
 
@@ -1637,7 +1618,7 @@ var Transition = /*#__PURE__*/function (_React$Component) {
1637
1618
  var enterTimeout = appearing ? timeouts.appear : timeouts.enter; // no enter animation skip right to ENTERED
1638
1619
  // if we are mounting and running this it means appear _must_ be set
1639
1620
 
1640
- if (!mounting && !enter || config.disabled) {
1621
+ if (!mounting && !enter || config$1.disabled) {
1641
1622
  this.safeSetState({
1642
1623
  status: ENTERED
1643
1624
  }, function () {
@@ -1669,7 +1650,7 @@ var Transition = /*#__PURE__*/function (_React$Component) {
1669
1650
  var timeouts = this.getTimeouts();
1670
1651
  var maybeNode = this.props.nodeRef ? undefined : ReactDOM.findDOMNode(this); // no exit animation skip right to EXITED
1671
1652
 
1672
- if (!exit || config.disabled) {
1653
+ if (!exit || config$1.disabled) {
1673
1654
  this.safeSetState({
1674
1655
  status: EXITED
1675
1656
  }, function () {
@@ -3608,6 +3589,9 @@ const POPUP_PLACEMENT = ['right-start', 'right-end', 'right'];
3608
3589
  const POPUP_ITEM_HEIGHT = 28;
3609
3590
 
3610
3591
  function getItemHeight$1(item) {
3592
+ if (!isMenuItem(item)) {
3593
+ return ITEM_HEIGHT;
3594
+ }
3611
3595
  switch (item.type) {
3612
3596
  case 'action':
3613
3597
  return 50;
@@ -3645,12 +3629,10 @@ function getItemsMinHeight(items) {
3645
3629
  getItemsHeight(afterMoreButtonItems) +
3646
3630
  (pinnedItems.length === items.length ? 0 : ITEM_HEIGHT));
3647
3631
  }
3648
- function getMoreButtonItem(dict) {
3649
- var _a;
3650
- const title = (_a = dict === null || dict === void 0 ? void 0 : dict[Dict.MoreButton]) !== null && _a !== void 0 ? _a : defaultDict$2[Dict.MoreButton];
3632
+ function getMoreButtonItem(menuMoreTitle) {
3651
3633
  return {
3652
3634
  id: COLLAPSE_ITEM_ID,
3653
- title,
3635
+ title: menuMoreTitle,
3654
3636
  icon: Ellipsis,
3655
3637
  iconSize: 18,
3656
3638
  };
@@ -3694,6 +3676,9 @@ function getAutosizeListItems(items, height, collapseItem) {
3694
3676
  }
3695
3677
  return { listItems, collapseItems };
3696
3678
  }
3679
+ function isMenuItem(item) {
3680
+ return (item === null || item === void 0 ? void 0 : item.id) !== undefined;
3681
+ }
3697
3682
 
3698
3683
  var css_248z$k = ".gn-composite-bar-item {\n --composite-bar-item-action-size: 36px;\n display: flex;\n width: 100%;\n height: 100%;\n align-items: center;\n cursor: pointer;\n}\n.gn-composite-bar-item__icon {\n color: var(--g-color-text-misc);\n}\n.gn-composite-bar-item__icon-place {\n flex-shrink: 0;\n width: var(--aside-header-min-width);\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n.gn-composite-bar-item__title {\n display: flex;\n overflow: hidden;\n}\n.gn-composite-bar-item__title-text {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.gn-composite-bar-item__title-adornment {\n margin: 0 10px;\n}\n.gn-composite-bar-item__collapse-item {\n display: flex;\n padding: 0 16px;\n align-items: center;\n width: 100%;\n height: 100%;\n cursor: pointer;\n}\n.gn-composite-bar-item__collapse-item .gn-composite-bar-item__title-adornment {\n margin-right: 0;\n}\n.gn-composite-bar-item__menu-divider {\n margin: 0 8px;\n width: 100%;\n border-top: 1px solid var(--g-color-line-generic);\n cursor: default;\n}\n.gn-composite-bar-item__collapse-items-popup-content {\n padding: 4px 0;\n}\n.gn-composite-bar-item__link {\n display: flex;\n width: 100%;\n height: 100%;\n align-items: center;\n}\n.gn-composite-bar-item__link, .gn-composite-bar-item__link:hover, .gn-composite-bar-item__link:active, .gn-composite-bar-item__link:visited, .gn-composite-bar-item__link:focus {\n text-decoration: none;\n outline: none;\n color: inherit;\n}\n.gn-composite-bar-item__btn-icon {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.gn-composite-bar-item_type_action {\n justify-content: center;\n height: var(--composite-bar-item-action-size);\n margin: 0 10px 8px;\n background: var(--g-color-base-float);\n box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.03), 0px 5px 6px rgba(0, 0, 0, 0.12);\n border-radius: var(--composite-bar-item-action-size);\n transition: transform 0.1s ease-out, background-color 0.15s linear;\n}\n.gn-composite-bar-item_type_action:focus {\n box-shadow: 0 0 0 2px var(--g-color-line-misc);\n}\n.gn-composite-bar-item_type_action:focus:not(:focus-visible) {\n box-shadow: none;\n}\n.gn-composite-bar-item_type_action:hover {\n background-color: var(--g-color-base-float-hover);\n}\n.gn-composite-bar-item_type_action:active {\n box-shadow: 0 1px 2px var(--g-color-sfx-shadow);\n transition: none;\n transform: scale(0.96);\n}\n.gn-composite-bar-item_type_action .gn-composite-bar-item__icon-place {\n width: var(--composite-bar-item-action-size);\n}\n.gn-composite-bar-item_type_action .gn-composite-bar-item__title {\n margin-right: 16px;\n}\n.gn-composite-bar-item__icon-tooltip_item-type_action {\n margin-left: 10px;\n}\n.gn-composite-bar-item:not(.gn-composite-bar-item_compact).gn-composite-bar-item_current.gn-composite-bar-item_type_regular {\n background-color: var(--g-color-base-selection);\n}\n.gn-composite-bar-item:not(.gn-composite-bar-item_compact):not(.gn-composite-bar-item_current):hover.gn-composite-bar-item_type_regular {\n background-color: var(--g-color-base-simple-hover);\n}\n.gn-composite-bar-item_compact.gn-composite-bar-item_type_action {\n width: var(--composite-bar-item-action-size);\n}\n.gn-composite-bar-item_compact.gn-composite-bar-item_type_action .gn-composite-bar-item__title {\n margin: 0;\n}\n.gn-composite-bar-item_compact.gn-composite-bar-item_current.gn-composite-bar-item_type_regular .gn-composite-bar-item__btn-icon {\n position: relative;\n background-color: transparent;\n}\n.gn-composite-bar-item_compact.gn-composite-bar-item_current.gn-composite-bar-item_type_regular .gn-composite-bar-item__btn-icon::before {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n z-index: -1;\n width: 38px;\n height: 38px;\n margin-top: -19px;\n margin-left: -19px;\n border-radius: 7px;\n}\n.gn-composite-bar-item_compact.gn-composite-bar-item_current.gn-composite-bar-item_type_regular .gn-composite-bar-item__btn-icon::before {\n background-color: var(--g-color-base-selection);\n}\n.gn-composite-bar-item_compact:not(.gn-composite-bar-item_current):hover.gn-composite-bar-item_type_regular .gn-composite-bar-item__btn-icon {\n position: relative;\n background-color: transparent;\n}\n.gn-composite-bar-item_compact:not(.gn-composite-bar-item_current):hover.gn-composite-bar-item_type_regular .gn-composite-bar-item__btn-icon::before {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n z-index: -1;\n width: 38px;\n height: 38px;\n margin-top: -19px;\n margin-left: -19px;\n border-radius: 7px;\n}\n.gn-composite-bar-item_compact:not(.gn-composite-bar-item_current):hover.gn-composite-bar-item_type_regular .gn-composite-bar-item__btn-icon::before {\n background-color: var(--g-color-base-simple-hover);\n}";
3699
3684
  styleInject(css_248z$k);
@@ -3756,7 +3741,7 @@ const Item$1 = (props) => {
3756
3741
  onMouseLeave === null || onMouseLeave === void 0 ? void 0 : onMouseLeave();
3757
3742
  }
3758
3743
  } },
3759
- React__default.createElement("div", { className: b$l('icon-place') }, compact ? (React__default.createElement(Tooltip, { content: tooltipText, disabled: !enableTooltip || (collapsedItem && open), placement: "right", className: b$l('icon-tooltip', { 'item-type': type }) },
3744
+ React__default.createElement("div", { className: b$l('icon-place') }, compact ? (React__default.createElement(Tooltip, { content: tooltipText, disabled: !enableTooltip || (collapsedItem && open) || popupVisible, placement: "right", className: b$l('icon-tooltip', { 'item-type': type }) },
3760
3745
  React__default.createElement("div", { onMouseEnter: () => onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(), onMouseLeave: () => onMouseLeave === null || onMouseLeave === void 0 ? void 0 : onMouseLeave(), className: b$l('btn-icon') }, iconEl))) : (iconEl)),
3761
3746
  React__default.createElement("div", { className: b$l('title'), title: typeof item.title === 'string' ? item.title : undefined }, titleEl),
3762
3747
  renderPopupContent && Boolean(anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) && (React__default.createElement(Popup, { contentClassName: b$l('popup'), open: popupVisible, keepMounted: popupKeepMounted, placement: popupPlacement, offset: popupOffset, anchorRef: anchorRef, onClose: onClose }, renderPopupContent()))));
@@ -3857,7 +3842,7 @@ var css_248z$i = ".gn-composite-bar {\n flex: 1 0 auto;\n width: 100%;\n min-
3857
3842
  styleInject(css_248z$i);
3858
3843
 
3859
3844
  const b$j = block('composite-bar');
3860
- const CompositeBarView = ({ items, onItemClick, collapseItems, multipleTooltip = true, }) => {
3845
+ const CompositeBarView = ({ type, items, onItemClick, collapseItems, multipleTooltip = false, }) => {
3861
3846
  const ref = useRef(null);
3862
3847
  const tooltipRef = useRef(null);
3863
3848
  const { setValue: setMultipleTooltipContextValue, active: multipleTooltipActive, activeIndex, lastClickedItemIndex, } = useContext(MultipleTooltipContext);
@@ -3922,26 +3907,32 @@ const CompositeBarView = ({ items, onItemClick, collapseItems, multipleTooltip =
3922
3907
  }, [lastClickedItemIndex, setMultipleTooltipContextValue]);
3923
3908
  return (React__default.createElement(React__default.Fragment, null,
3924
3909
  React__default.createElement("div", { ref: tooltipRef, onMouseEnter: onTooltipMouseEnter, onMouseLeave: onTooltipMouseLeave },
3925
- React__default.createElement(List, { ref: ref, items: items, selectedItemIndex: getSelectedItemIndex$1(items), itemHeight: getItemHeight$1, itemClassName: b$j('root-menu-item'), itemsHeight: getItemsHeight, virtualized: false, filterable: false, sortable: false, renderItem: (item, _isItemActive, itemIndex) => (React__default.createElement(Item$1, { item: item, onMouseEnter: onMouseEnterByIndex(itemIndex), onMouseLeave: onMouseLeave, onItemClick: onItemClickByIndex(itemIndex), collapseItems: collapseItems, enableTooltip: !multipleTooltip })) })),
3926
- React__default.createElement(MultipleTooltip, { open: compact && multipleTooltip && multipleTooltipActive, anchorRef: tooltipRef, placement: ['right-start'], items: items })));
3910
+ React__default.createElement(List, { ref: ref, items: items, selectedItemIndex: type === 'menu' ? getSelectedItemIndex$1(items) : undefined, itemHeight: getItemHeight$1, itemsHeight: getItemsHeight, itemClassName: b$j('root-menu-item'), virtualized: false, filterable: false, sortable: false, renderItem: (item, _isItemActive, itemIndex) => {
3911
+ const itemExtraProps = isMenuItem(item) ? { item } : item;
3912
+ const enableTooltip = isMenuItem(item)
3913
+ ? !multipleTooltip
3914
+ : item.enableTooltip;
3915
+ return (React__default.createElement(Item$1, Object.assign({}, itemExtraProps, { enableTooltip: enableTooltip, onMouseEnter: onMouseEnterByIndex(itemIndex), onMouseLeave: onMouseLeave, onItemClick: onItemClickByIndex(itemIndex), collapseItems: collapseItems })));
3916
+ } })),
3917
+ type === 'menu' && (React__default.createElement(MultipleTooltip, { open: compact && multipleTooltip && multipleTooltipActive, anchorRef: tooltipRef, placement: ['right-start'], items: items }))));
3927
3918
  };
3928
- const CompositeBar = ({ items, enableCollapsing, dict, onItemClick, multipleTooltip = false, }) => {
3919
+ const CompositeBar = ({ type, items, menuMoreTitle, onItemClick, multipleTooltip = false, }) => {
3929
3920
  if (items.length === 0) {
3930
3921
  return null;
3931
3922
  }
3932
3923
  let node;
3933
- if (enableCollapsing) {
3924
+ if (type === 'menu') {
3934
3925
  const minHeight = getItemsMinHeight(items);
3935
- const collapseItem = getMoreButtonItem(dict);
3926
+ const collapseItem = getMoreButtonItem(menuMoreTitle);
3936
3927
  node = (React__default.createElement("div", { className: b$j({ autosizer: true }), style: { minHeight } }, items.length !== 0 && (React__default.createElement(AutoSizer, null, ({ width, height }) => {
3937
3928
  const { listItems, collapseItems } = getAutosizeListItems(items, height, collapseItem);
3938
3929
  return (React__default.createElement("div", { style: { width, height } },
3939
- React__default.createElement(CompositeBarView, { items: listItems, onItemClick: onItemClick, collapseItems: collapseItems, multipleTooltip: multipleTooltip })));
3930
+ React__default.createElement(CompositeBarView, { type: "menu", items: listItems, onItemClick: onItemClick, collapseItems: collapseItems, multipleTooltip: multipleTooltip })));
3940
3931
  }))));
3941
3932
  }
3942
3933
  else {
3943
3934
  node = (React__default.createElement("div", { className: b$j() },
3944
- React__default.createElement(CompositeBarView, { items: items, onItemClick: onItemClick, multipleTooltip: multipleTooltip })));
3935
+ React__default.createElement(CompositeBarView, { type: "subheader", items: items, onItemClick: onItemClick })));
3945
3936
  }
3946
3937
  return React__default.createElement(MultipleTooltipProvider, null, node);
3947
3938
  };
@@ -3962,6 +3953,237 @@ function fakeDisplayName(newDisplayName, Component) {
3962
3953
  return Fake;
3963
3954
  }
3964
3955
 
3956
+ const PARAM_REGEXP = /{{(.*?)}}/g;
3957
+ function replaceParams(keyValue, params) {
3958
+ let result = '';
3959
+ let lastIndex = (PARAM_REGEXP.lastIndex = 0);
3960
+ let match;
3961
+ while ((match = PARAM_REGEXP.exec(keyValue))) {
3962
+ if (lastIndex !== match.index) {
3963
+ result += keyValue.slice(lastIndex, match.index);
3964
+ }
3965
+ lastIndex = PARAM_REGEXP.lastIndex;
3966
+ const [all, key] = match;
3967
+ if (Object.prototype.hasOwnProperty.call(params, key)) {
3968
+ result += params[key];
3969
+ }
3970
+ else {
3971
+ result += all;
3972
+ }
3973
+ }
3974
+ if (lastIndex < keyValue.length) {
3975
+ result += keyValue.slice(lastIndex);
3976
+ }
3977
+ return result;
3978
+ }
3979
+
3980
+ var PluralForm;
3981
+ (function (PluralForm) {
3982
+ PluralForm[PluralForm["One"] = 0] = "One";
3983
+ PluralForm[PluralForm["Few"] = 1] = "Few";
3984
+ PluralForm[PluralForm["Many"] = 2] = "Many";
3985
+ PluralForm[PluralForm["None"] = 3] = "None";
3986
+ })(PluralForm || (PluralForm = {}));
3987
+
3988
+ function pluralizerEn (count, pluralForms) {
3989
+ if (count === 0) {
3990
+ return pluralForms.None;
3991
+ }
3992
+ if (count === 1 || count === -1) {
3993
+ return pluralForms.One;
3994
+ }
3995
+ return pluralForms.Many;
3996
+ }
3997
+
3998
+ function pluralizerRu (count, pluralForms) {
3999
+ // the rules for negative numbers are the same
4000
+ const lastDigit = Math.abs(count % 10);
4001
+ const last2Digits = Math.abs(count % 100);
4002
+ if (count === 0) {
4003
+ return pluralForms.None;
4004
+ }
4005
+ if (lastDigit === 1 && last2Digits !== 11) {
4006
+ return pluralForms.One;
4007
+ }
4008
+ if ((lastDigit > 1 && lastDigit < 5) && (last2Digits < 10 || last2Digits > 20)) {
4009
+ return pluralForms.Few;
4010
+ }
4011
+ return pluralForms.Many;
4012
+ }
4013
+
4014
+ class I18N {
4015
+ constructor(options) {
4016
+ this.data = {};
4017
+ this.lang = undefined;
4018
+ this.pluralizers = {
4019
+ en: pluralizerEn,
4020
+ ru: pluralizerRu,
4021
+ };
4022
+ this.logger = null;
4023
+ this.logger = (options === null || options === void 0 ? void 0 : options.logger) || null;
4024
+ }
4025
+ setLang(lang) {
4026
+ this.lang = lang;
4027
+ }
4028
+ configurePluralization(pluralizers) {
4029
+ this.pluralizers = Object.assign({}, this.pluralizers, pluralizers);
4030
+ }
4031
+ registerKeyset(lang, keysetName, data = {}) {
4032
+ if (this.data[lang] && Object.prototype.hasOwnProperty.call(this.data[lang], keysetName)) {
4033
+ throw new Error(`Keyset '${keysetName}' is already registered, aborting!`);
4034
+ }
4035
+ this.data[lang] = Object.assign({}, this.data[lang], { [keysetName]: data });
4036
+ }
4037
+ registerKeysets(lang, data) {
4038
+ Object.keys(data).forEach((keysetName) => {
4039
+ this.registerKeyset(lang, keysetName, data[keysetName]);
4040
+ });
4041
+ }
4042
+ has(keysetName, key, lang) {
4043
+ const languageData = this.getLanguageData(lang);
4044
+ return Boolean(languageData && languageData[keysetName] && languageData[keysetName][key]);
4045
+ }
4046
+ i18n(keysetName, key, params) {
4047
+ const languageData = this.getLanguageData(this.lang);
4048
+ if (typeof languageData === 'undefined') {
4049
+ throw new Error(`Language '${this.lang}' is not defined, make sure you call setLang for the same language you called registerKeysets for!`);
4050
+ }
4051
+ if (Object.keys(languageData).length === 0) {
4052
+ this.warn('Language data is empty.');
4053
+ return key;
4054
+ }
4055
+ const keyset = languageData[keysetName];
4056
+ if (!keyset) {
4057
+ this.warn('Keyset not found.', keysetName);
4058
+ return key;
4059
+ }
4060
+ if (Object.keys(keyset).length === 0) {
4061
+ this.warn('Keyset is empty.', keysetName);
4062
+ return key;
4063
+ }
4064
+ const keyValue = keyset && keyset[key];
4065
+ let result;
4066
+ if (typeof keyValue === 'undefined') {
4067
+ this.warn('Missing key.', keysetName, key);
4068
+ return key;
4069
+ }
4070
+ if (Array.isArray(keyValue)) {
4071
+ if (keyValue.length < 3) {
4072
+ this.warn('Missing required plurals', keysetName, key);
4073
+ return key;
4074
+ }
4075
+ const count = Number(params === null || params === void 0 ? void 0 : params.count);
4076
+ if (Number.isNaN(count)) {
4077
+ this.warn('Missing params.count for key.', keysetName, key);
4078
+ return key;
4079
+ }
4080
+ const pluralizer = this.getLanguagePluralizer(this.lang);
4081
+ result = keyValue[pluralizer(count, PluralForm)] || keyValue[PluralForm.Many];
4082
+ if (keyValue[PluralForm.None] === undefined) {
4083
+ this.warn('Missing key for 0', keysetName, key);
4084
+ }
4085
+ }
4086
+ else {
4087
+ result = keyValue;
4088
+ }
4089
+ if (params) {
4090
+ result = replaceParams(result, params);
4091
+ }
4092
+ return result;
4093
+ }
4094
+ keyset(keysetName) {
4095
+ return (key, params) => {
4096
+ return this.i18n(keysetName, key, params);
4097
+ };
4098
+ }
4099
+ warn(msg, keyset, key) {
4100
+ var _a;
4101
+ let cacheKey = '';
4102
+ if (keyset) {
4103
+ cacheKey += keyset;
4104
+ if (key) {
4105
+ cacheKey += `.${key}`;
4106
+ }
4107
+ }
4108
+ else {
4109
+ cacheKey = 'languageData';
4110
+ }
4111
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.log(`I18n: ${msg}`, {
4112
+ level: 'info',
4113
+ logger: cacheKey,
4114
+ extra: {
4115
+ type: 'i18n'
4116
+ }
4117
+ });
4118
+ }
4119
+ getLanguageData(lang) {
4120
+ const langCode = lang || this.lang;
4121
+ return langCode ? this.data[langCode] : undefined;
4122
+ }
4123
+ getLanguagePluralizer(lang) {
4124
+ const pluralizer = lang ? this.pluralizers[lang] : undefined;
4125
+ if (!pluralizer) {
4126
+ this.warn(`Pluralization is not configured for language '${lang}', falling back to the english ruleset`);
4127
+ }
4128
+ return pluralizer || pluralizerEn;
4129
+ }
4130
+ }
4131
+
4132
+ var Lang;
4133
+ (function (Lang) {
4134
+ Lang["Ru"] = "ru";
4135
+ Lang["En"] = "en";
4136
+ })(Lang || (Lang = {}));
4137
+ let subs = [];
4138
+ const config = {
4139
+ lang: Lang.En,
4140
+ };
4141
+ const configure = (newConfig) => {
4142
+ Object.assign(config, newConfig);
4143
+ subs.forEach((sub) => {
4144
+ sub(config);
4145
+ });
4146
+ };
4147
+ const subscribeConfigure = (sub) => {
4148
+ subs.push(sub);
4149
+ return () => {
4150
+ subs = subs.filter((item) => item !== sub);
4151
+ };
4152
+ };
4153
+ const getConfig = () => config;
4154
+
4155
+ const i18n$4 = new I18N();
4156
+ i18n$4.setLang(getConfig().lang);
4157
+ subscribeConfigure((config) => {
4158
+ i18n$4.setLang(config.lang);
4159
+ });
4160
+
4161
+ function registerKeyset(data, keysetName) {
4162
+ Object.entries(data).forEach(([lang, keys]) => i18n$4.registerKeyset(lang, keysetName, keys));
4163
+ return i18n$4.keyset(keysetName);
4164
+ }
4165
+
4166
+ var button_collapse$1 = "Collapse";
4167
+ var button_expand$1 = "Expand";
4168
+ var label_more$1 = "More";
4169
+ var en$3 = {
4170
+ button_collapse: button_collapse$1,
4171
+ button_expand: button_expand$1,
4172
+ label_more: label_more$1
4173
+ };
4174
+
4175
+ var button_collapse = "Свернуть";
4176
+ var button_expand = "Развернуть";
4177
+ var label_more = "Ещё";
4178
+ var ru$3 = {
4179
+ button_collapse: button_collapse,
4180
+ button_expand: button_expand,
4181
+ label_more: label_more
4182
+ };
4183
+
4184
+ const COMPONENT$3 = 'AsideHeader';
4185
+ var i18n$3 = registerKeyset({ en: en$3, ru: ru$3 }, COMPONENT$3);
4186
+
3965
4187
  var _path$1;
3966
4188
  function _extends$1() { _extends$1 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$1.apply(this, arguments); }
3967
4189
  var SvgControlMenuButton = function SvgControlMenuButton(props) {
@@ -4003,13 +4225,13 @@ class AsideHeader extends React__default.Component {
4003
4225
  super(...arguments);
4004
4226
  this.asideRef = React__default.createRef();
4005
4227
  this.renderFirstPane = (size) => {
4006
- const { dict, menuItems, panelItems, headerDecoration, multipleTooltip } = this.props;
4228
+ const { menuItems, panelItems, headerDecoration, multipleTooltip, menuMoreTitle } = this.props;
4007
4229
  return (React__default.createElement(React__default.Fragment, null,
4008
4230
  React__default.createElement("div", { className: b$i('aside'), style: { width: size } },
4009
4231
  React__default.createElement("div", { className: b$i('aside-popup-anchor'), ref: this.asideRef }),
4010
4232
  React__default.createElement("div", { className: b$i('aside-content', { ['with-decoration']: headerDecoration }) },
4011
4233
  this.renderHeader(),
4012
- (menuItems === null || menuItems === void 0 ? void 0 : menuItems.length) ? (React__default.createElement(CompositeBar, { items: menuItems, enableCollapsing: true, dict: dict, onItemClick: this.onItemClick, multipleTooltip: multipleTooltip })) : (React__default.createElement("div", { className: b$i('menu-items') })),
4234
+ (menuItems === null || menuItems === void 0 ? void 0 : menuItems.length) ? (React__default.createElement(CompositeBar, { type: "menu", items: menuItems, menuMoreTitle: menuMoreTitle !== null && menuMoreTitle !== void 0 ? menuMoreTitle : i18n$3('label_more'), onItemClick: this.onItemClick, multipleTooltip: multipleTooltip })) : (React__default.createElement("div", { className: b$i('menu-items') })),
4013
4235
  this.renderFooter(size),
4014
4236
  this.renderCollapseButton())),
4015
4237
  panelItems && this.renderPanels(size)));
@@ -4020,7 +4242,7 @@ class AsideHeader extends React__default.Component {
4020
4242
  this.renderLogo = () => React__default.createElement(Logo$1, Object.assign({}, this.props.logo, { onClick: this.onLogoClick }));
4021
4243
  this.renderHeader = () => (React__default.createElement("div", { className: b$i('header', { ['with-decoration']: this.props.headerDecoration }) },
4022
4244
  this.renderLogo(),
4023
- React__default.createElement(CompositeBar, { items: this.props.subheaderItems, enableCollapsing: false, onItemClick: this.onItemClick }),
4245
+ React__default.createElement(CompositeBar, { type: "subheader", items: this.props.subheaderItems, onItemClick: this.onItemClick }),
4024
4246
  React__default.createElement(Icon, { data: headerDividerCollapsedIcon, className: b$i('header-divider'), width: ASIDE_HEADER_COMPACT_WIDTH, height: "29" })));
4025
4247
  this.renderFooter = (size) => {
4026
4248
  const { renderFooter, compact } = this.props;
@@ -4035,10 +4257,11 @@ class AsideHeader extends React__default.Component {
4035
4257
  return (React__default.createElement(Drawer, { className: b$i('panels'), onVeilClick: this.onCloseDrawer, onEscape: this.onCloseDrawer, style: { left: size } }, panelItems.map((item) => (React__default.createElement(DrawerItem, Object.assign({ key: item.id }, item))))));
4036
4258
  };
4037
4259
  this.renderCollapseButton = () => {
4038
- var _a;
4039
- const { dict, compact } = this.props;
4040
- const typeButton = compact ? Dict.ExpandButton : Dict.CollapseButton;
4041
- return (React__default.createElement(Button, { className: b$i('collapse-button', { compact }), view: "flat", onClick: this.onCollapseButtonClick, title: (_a = dict === null || dict === void 0 ? void 0 : dict[typeButton]) !== null && _a !== void 0 ? _a : defaultDict$2[typeButton] },
4260
+ const { expandTitle, collapseTitle, compact } = this.props;
4261
+ const buttonTitle = compact
4262
+ ? expandTitle || i18n$3('button_expand')
4263
+ : collapseTitle || i18n$3('button_collapse');
4264
+ return (React__default.createElement(Button, { className: b$i('collapse-button', { compact }), view: "flat", onClick: this.onCollapseButtonClick, title: buttonTitle },
4042
4265
  React__default.createElement(NotIcon, { data: controlMenuButtonIcon, className: b$i('collapse-icon'), width: "16", height: "10" })));
4043
4266
  };
4044
4267
  this.onCollapseButtonClick = () => {
@@ -4169,18 +4392,28 @@ const PublicActionBar = Object.assign(ActionBar, {
4169
4392
  Separator: ActionBarSeparator,
4170
4393
  });
4171
4394
 
4395
+ var button_close$1 = "Close";
4396
+ var en$2 = {
4397
+ button_close: button_close$1
4398
+ };
4399
+
4400
+ var button_close = "Закрыть";
4401
+ var ru$2 = {
4402
+ button_close: button_close
4403
+ };
4404
+
4405
+ const COMPONENT$2 = 'Title';
4406
+ var i18n$2 = registerKeyset({ en: en$2, ru: ru$2 }, COMPONENT$2);
4407
+
4172
4408
  var css_248z$a = ".gn-title {\n box-sizing: border-box;\n padding: 14px 10px 14px 20px;\n min-height: 64px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.gn-title_separator {\n border-bottom: 1px solid var(--g-color-line-generic);\n}\n.gn-title__text {\n margin: 0;\n margin-right: 20px;\n}";
4173
4409
  styleInject(css_248z$a);
4174
4410
 
4175
4411
  const b$b = block('title');
4176
- const defaultDict$1 = {
4177
- close: 'Close',
4178
- };
4179
- const Title = ({ children, closeIconSize = 23, hasSeparator, dict = defaultDict$1, onClose, }) => {
4412
+ const Title = ({ children, closeIconSize = 23, hasSeparator, closeTitle = i18n$2('button_close'), onClose, }) => {
4180
4413
  return (React__default.createElement("div", { className: b$b({ separator: hasSeparator }) },
4181
4414
  React__default.createElement(Text, { className: b$b('text'), as: 'h3', variant: 'subheader-3' }, children),
4182
4415
  onClose && (React__default.createElement(Button, { onClick: onClose, view: "flat", size: "l", extraProps: {
4183
- 'aria-label': dict['close'],
4416
+ 'aria-label': closeTitle,
4184
4417
  } },
4185
4418
  React__default.createElement(Icon, { data: Xmark, size: closeIconSize })))));
4186
4419
  };
@@ -4942,6 +5175,23 @@ const SettingsMenuMobile = ({ items, onChange, activeItemId, className, }) => {
4942
5175
  React__default.createElement(Tabs, { items: tabItems, className: b$7(null, className), size: "l", activeTab: activeItemId, onSelectTab: onChange })));
4943
5176
  };
4944
5177
 
5178
+ var label_title$1 = "Settings";
5179
+ var en$1 = {
5180
+ label_title: label_title$1,
5181
+ "label_filter-placeholder": "Search settings",
5182
+ "label_empty-placeholder": "No results found"
5183
+ };
5184
+
5185
+ var label_title = "Настройки";
5186
+ var ru$1 = {
5187
+ label_title: label_title,
5188
+ "label_filter-placeholder": "Найти настройки",
5189
+ "label_empty-placeholder": "Ничего не найдено"
5190
+ };
5191
+
5192
+ const COMPONENT$1 = 'Settings';
5193
+ var i18n$1 = registerKeyset({ en: en$1, ru: ru$1 }, COMPONENT$1);
5194
+
4945
5195
  function getSettingsFromChildren(children, searchText = '') {
4946
5196
  // 'abc def fg' -> abc.*?cde.*?fg
4947
5197
  const preparedFilter = escapeStringForRegExp(searchText).replace(/\s+/g, '.*?');
@@ -5067,11 +5317,6 @@ var css_248z$6 = ".gn-settings {\n display: grid;\n grid-template-columns: 216
5067
5317
  styleInject(css_248z$6);
5068
5318
 
5069
5319
  const b$6 = block('settings');
5070
- const defaultDict = {
5071
- heading_settings: 'Settings',
5072
- placeholder_search: 'Search settings',
5073
- not_found: 'No results found',
5074
- };
5075
5320
  function Settings(_a) {
5076
5321
  var { loading, renderLoading, children, view = 'normal' } = _a, props = __rest(_a, ["loading", "renderLoading", "children", "view"]);
5077
5322
  if (loading) {
@@ -5091,10 +5336,7 @@ const getPageTitleById = (menu, activePage) => {
5091
5336
  }
5092
5337
  return '';
5093
5338
  };
5094
- Settings.defaultProps = {
5095
- dict: defaultDict,
5096
- };
5097
- function SettingsContent({ initialPage, children, renderNotFound, dict, view, onPageChange, onClose, }) {
5339
+ function SettingsContent({ initialPage, children, renderNotFound, title = i18n$1('label_title'), filterPlaceholder = i18n$1('label_filter-placeholder'), emptyPlaceholder = i18n$1('label_empty-placeholder'), view, onPageChange, onClose, }) {
5098
5340
  var _a, _b;
5099
5341
  const [search, setSearch] = React__default.useState('');
5100
5342
  const { menu, pages } = getSettingsFromChildren(children, search);
@@ -5136,7 +5378,7 @@ function SettingsContent({ initialPage, children, renderNotFound, dict, view, on
5136
5378
  });
5137
5379
  const renderPageContent = () => {
5138
5380
  if (!activePage) {
5139
- return typeof renderNotFound === 'function' ? (renderNotFound()) : (React__default.createElement("div", { className: b$6('not-found') }, dict === null || dict === void 0 ? void 0 : dict.not_found));
5381
+ return typeof renderNotFound === 'function' ? (renderNotFound()) : (React__default.createElement("div", { className: b$6('not-found') }, emptyPlaceholder));
5140
5382
  }
5141
5383
  const filteredSections = pages[activePage].sections.filter((section) => !section.hidden);
5142
5384
  return (React__default.createElement(React__default.Fragment, null,
@@ -5163,8 +5405,8 @@ function SettingsContent({ initialPage, children, renderNotFound, dict, view, on
5163
5405
  }
5164
5406
  }
5165
5407
  } },
5166
- React__default.createElement(Title, null, dict === null || dict === void 0 ? void 0 : dict.heading_settings),
5167
- React__default.createElement(SettingsSearch, { inputRef: searchInputRef, className: b$6('search'), onChange: setSearch, placeholder: dict === null || dict === void 0 ? void 0 : dict.placeholder_search, autoFocus: true }),
5408
+ React__default.createElement(Title, null, title),
5409
+ React__default.createElement(SettingsSearch, { inputRef: searchInputRef, className: b$6('search'), onChange: setSearch, placeholder: filterPlaceholder, autoFocus: true }),
5168
5410
  React__default.createElement(SettingsMenu, { ref: menuRef, items: menu, onChange: handlePageChange, activeItemId: activePage }))),
5169
5411
  React__default.createElement("div", { className: b$6('page') }, renderPageContent())));
5170
5412
  }
@@ -5227,7 +5469,7 @@ var css_248z$5 = ".gn-mobile-header-burger {\n margin: 0;\n padding: 0;\n fon
5227
5469
  styleInject(css_248z$5);
5228
5470
 
5229
5471
  const b$5 = block('mobile-header-burger');
5230
- const Burger = React__default.memo(({ opened, className, onClick }) => (React__default.createElement("button", { className: b$5({ opened }, className), onClick: onClick, "aria-label": opened ? defaultDict$2['button_close-burger'] : defaultDict$2['button_open-burger'] },
5472
+ const Burger = React__default.memo(({ closeTitle, openTitle, opened, className, onClick }) => (React__default.createElement("button", { className: b$5({ opened }, className), onClick: onClick, "aria-label": opened ? closeTitle : openTitle },
5231
5473
  React__default.createElement("span", { className: b$5('icon') },
5232
5474
  React__default.createElement("span", { className: b$5('icon-dash') })))));
5233
5475
  Burger.displayName = 'Burger';
@@ -5333,11 +5575,28 @@ const BurgerMenu = React__default.memo(({ items = [], renderFooter, modalItem, c
5333
5575
  });
5334
5576
  BurgerMenu.displayName = 'BurgerMenu';
5335
5577
 
5578
+ var burger_button_close$1 = "Close menu";
5579
+ var burger_button_open$1 = "Open menu";
5580
+ var en = {
5581
+ burger_button_close: burger_button_close$1,
5582
+ burger_button_open: burger_button_open$1
5583
+ };
5584
+
5585
+ var burger_button_close = "Закрыть меню";
5586
+ var burger_button_open = "Открыть меню";
5587
+ var ru = {
5588
+ burger_button_close: burger_button_close,
5589
+ burger_button_open: burger_button_open
5590
+ };
5591
+
5592
+ const COMPONENT = 'MobileHeader';
5593
+ var i18n = registerKeyset({ en, ru }, COMPONENT);
5594
+
5336
5595
  var css_248z$1 = ".gn-mobile-header {\n --mobile-header-min-heigth: 50px;\n --mobile-header-icon-size: 20px;\n background-color: var(--g-color-base-background);\n}\n.gn-mobile-header__header {\n background-color: var(--g-color-base-background);\n border-bottom: 1px solid var(--g-color-line-generic);\n position: sticky;\n top: 0;\n padding: 0 10px;\n box-sizing: border-box;\n display: flex;\n justify-content: space-between;\n align-items: center;\n z-index: 100;\n}\n.gn-mobile-header__burger {\n padding: 12px;\n}\n.gn-mobile-header__burger-menu, .gn-mobile-header__panel-item {\n background-color: var(--g-color-base-background);\n width: 320px;\n max-width: 90vw;\n max-height: 100%;\n}\n.gn-mobile-header__user-menu {\n overflow-y: auto;\n}\n.gn-mobile-header__panels {\n z-index: 98;\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: var(--mobile-header-min-heigth);\n overflow: hidden;\n}\n.gn-mobile-header__content {\n overflow: auto;\n}";
5337
5596
  styleInject(css_248z$1);
5338
5597
 
5339
5598
  const b$1 = block('mobile-header');
5340
- const MobileHeader = React__default.forwardRef(({ logo, burgerMenu, panelItems = [], renderContent, sideItemRenderContent, onClosePanel, onEvent, className, }, ref) => {
5599
+ const MobileHeader = React__default.forwardRef(({ logo, burgerMenu, burgerCloseTitle = i18n('burger_button_close'), burgerOpenTitle = i18n('burger_button_open'), panelItems = [], renderContent, sideItemRenderContent, onClosePanel, onEvent, className, }, ref) => {
5341
5600
  const targetRef = useForwardRef(ref);
5342
5601
  const [compact] = useState(true);
5343
5602
  const [visiblePanel, setVisiblePanel] = useState(null);
@@ -5427,7 +5686,7 @@ const MobileHeader = React__default.forwardRef(({ logo, burgerMenu, panelItems =
5427
5686
  }, [targetRef, onBurgerClose, onBurgerOpen]);
5428
5687
  return (React__default.createElement("div", { className: b$1({ compact }, className), ref: targetRef },
5429
5688
  React__default.createElement("header", { className: b$1('header'), style: { height: size } },
5430
- React__default.createElement(Burger, { opened: visiblePanel === burgerPanelItem.id, onClick: () => onPanelToggle(BURGER_PANEL_ITEM_ID), className: b$1('burger') }),
5689
+ React__default.createElement(Burger, { opened: visiblePanel === burgerPanelItem.id, onClick: () => onPanelToggle(BURGER_PANEL_ITEM_ID), className: b$1('burger'), closeTitle: burgerCloseTitle, openTitle: burgerOpenTitle }),
5431
5690
  React__default.createElement(Logo, Object.assign({}, logo, { compact: compact, onClick: onLogoClick })),
5432
5691
  React__default.createElement("div", { className: b$1('side-item') }, sideItemRenderContent === null || sideItemRenderContent === void 0 ? void 0 : sideItemRenderContent({ size }))),
5433
5692
  React__default.createElement(Drawer, { className: b$1('panels'), onVeilClick: onCloseDrawer, onEscape: onCloseDrawer, style: { top: size } }, [burgerPanelItem, ...panelItems].map((item) => (React__default.createElement(DrawerItem, Object.assign({}, item, { key: item.id, visible: visiblePanel === item.id, className: b$1('panel-item', item.className) }))))),
@@ -5454,5 +5713,5 @@ const FooterItem = ({ icon, iconSize = MOBILE_HEADER_ICON_SIZE, className, modal
5454
5713
  React__default.createElement(Sheet, { id: modalItem.id, title: modalItem.title, visible: modalItem.visible, className: b('modal', modalItem.className), contentClassName: b('modal-content', modalItem.contentClassName), allowHideOnContentScroll: modalItem.modalAllowHideOnContentScroll, onClose: modalItem.onClose }, (_a = modalItem.renderContent) === null || _a === void 0 ? void 0 : _a.call(modalItem))));
5455
5714
  };
5456
5715
 
5457
- export { PublicActionBar as ActionBar, AsideHeader, AsideHeaderContextProvider, Dict, Drawer, DrawerItem, FooterItem$1 as FooterItem, HotkeysPanel, MobileHeader, MobileHeaderDict, FooterItem as MobileHeaderFooterItem, Settings, Title, useAsideHeaderContext };
5716
+ export { PublicActionBar as ActionBar, AsideHeader, AsideHeaderContextProvider, Drawer, DrawerItem, FooterItem$1 as FooterItem, HotkeysPanel, Lang, MobileHeader, FooterItem as MobileHeaderFooterItem, Settings, Title, configure, useAsideHeaderContext };
5458
5717
  //# sourceMappingURL=index.js.map