ru.coon 2.8.66 → 3.0.2

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 (128) hide show
  1. package/CHANGELOG.md +317 -10
  2. package/package.json +1 -1
  3. package/src/Function.js +1 -1
  4. package/src/VisualLinker.js +610 -0
  5. package/src/VisualLinker.scss +219 -0
  6. package/src/app/Application.js +1 -0
  7. package/src/app/ApplicationSettings.js +49 -0
  8. package/src/app/Config.js +60 -0
  9. package/src/app/Router.js +37 -21
  10. package/src/app/viewPort/CVWrapperPanel.js +53 -0
  11. package/src/app/viewPort/CenterView.js +153 -46
  12. package/src/app/viewPort/CenterView.scss +151 -0
  13. package/src/app/viewPort/ComponentContextManager.js +24 -0
  14. package/src/app/viewPort/Main.js +4 -1
  15. package/src/app/viewPort/Routing.d2 +23 -0
  16. package/src/app/viewPort/TabHistory.js +81 -0
  17. package/src/common/ComponentFactory.js +167 -0
  18. package/src/common/button/DropdownContentButton.js +146 -0
  19. package/src/common/button/DropdownContentButton.scss +92 -0
  20. package/src/common/button/DropdownContentButtonController.js +60 -0
  21. package/src/common/component/formeditor/UiCustomFilterForm.scss +0 -1
  22. package/src/common/component/settings/modules/settingClosePageConfirmation.js +1 -3
  23. package/src/common/component/settings/modules/settingFavoritePanelShow.js +21 -0
  24. package/src/common/component/settings/modules/settingReportCalculator.js +22 -0
  25. package/src/common/component/settings/modules/settingShowNeedReloadMessage.js +1 -3
  26. package/src/common/component/settings/modules/settingwindowHolder.js +2 -3
  27. package/src/common/panel/WindowWrap.js +19 -11
  28. package/src/common/tree/BaseContextMenu.js +4 -3
  29. package/src/log.js +4 -5
  30. package/src/nav/AppNavCalcButton.js +23 -0
  31. package/src/nav/AppNavCalcButton.scss +6 -0
  32. package/src/nav/AppNavigationBar.js +1 -1
  33. package/src/nav/AppNavigationMenuController.js +2 -2
  34. package/src/nav/AppNavigationMenuMinimized.js +61 -0
  35. package/src/nav/AppNavigationPanel.js +115 -0
  36. package/src/nav/AppNavigationPanel.scss +178 -0
  37. package/src/nav/AppNavigationPanelController.js +386 -0
  38. package/src/nav/FavoriteCfg.js +18 -0
  39. package/src/nav/MenuEntity.js +23 -15
  40. package/src/nav/MenuFavoritesBar.js +100 -0
  41. package/src/nav/MenuFavoritesBar.scss +92 -0
  42. package/src/nav/editor/NavigateElementEditorView.js +2 -2
  43. package/src/nav/editor/workspace/NavWorkspaceListView.js +1 -4
  44. package/src/nav/menu/WorkspaceMenuViewMinimized.js +22 -0
  45. package/src/overrides/panel/TabPanel.js +36 -0
  46. package/src/overrides/panel/TabPanel.scss +65 -0
  47. package/src/report/component/ClearFiltersButton.js +4 -1
  48. package/src/report/component/CopyCellValueMenuItem.js +18 -0
  49. package/src/report/component/ReportFieldMap.js +274 -0
  50. package/src/report/component/ReportPanel.js +73 -44
  51. package/src/report/component/ReportPanel.scss +2 -2
  52. package/src/report/component/ReportTagLookup.js +59 -2
  53. package/src/report/component/calculator/ReportCalculatorController.js +266 -0
  54. package/src/report/component/calculator/ReportCalculatorField.js +47 -0
  55. package/src/report/component/calculator/ReportCalculatorHistoryPlugin.js +128 -0
  56. package/src/report/component/calculator/ReportCalculatorHistoryPlugin.scss +33 -0
  57. package/src/report/component/calculator/ReportCalculatorMenuItem.js +101 -0
  58. package/src/report/component/calculator/ReportCalculatorMenuItem.scss +41 -0
  59. package/src/report/component/calculator/ReportCalculatorPanel.js +363 -0
  60. package/src/report/component/calculator/ReportCalculatorPanel.scss +86 -0
  61. package/src/report/component/reportpanel/CopyReportPanelController.js +1 -1
  62. package/src/report/component/reportpanel/FilterPanel.js +13 -15
  63. package/src/report/component/reportpanel/FilterPanel.scss +5 -1
  64. package/src/report/component/reportpanel/FormFieldFocusPlugin.js +157 -0
  65. package/src/report/component/reportpanel/FormFieldFocusPlugin.scss +14 -0
  66. package/src/report/component/reportpanel/NorthPanel.js +16 -17
  67. package/src/report/component/reportpanel/NorthPanel.scss +1 -1
  68. package/src/report/component/reportpanel/ReportContextMenu.js +219 -0
  69. package/src/report/component/reportpanel/ReportGrid.js +1 -0
  70. package/src/report/component/reportpanel/ReportGrid.scss +4 -0
  71. package/src/report/component/settings/field/ReportFormFieldsGrid.js +2 -2
  72. package/src/report/component/settings/field/ReportFormFieldsGridController.js +2 -2
  73. package/src/report/component/settings/property/ReportPropertiesPanelController.js +1 -1
  74. package/src/report/component/settings/property/ReportPropertyDictionary.js +7 -0
  75. package/src/report/plugin/configPanel/AddFilterConditionPluginConfigPanel.js +34 -11
  76. package/src/report/plugin/configPanel/GridFiltersPluginConfigPanelFiltersGrid.js +3 -2
  77. package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.js +274 -255
  78. package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.scss +17 -0
  79. package/src/report/plugin/grid/AddFilterConditionPlugin.js +530 -87
  80. package/src/report/plugin/grid/CalculatorPlugin.js +90 -0
  81. package/src/report/plugin/grid/GridContextMenu.js +12 -10
  82. package/src/report/plugin/grid/GridRowCountPlugin.js +0 -1
  83. package/src/report/plugin/grid/GridToolbarButtonPlugin.js +11 -2
  84. package/src/report/plugin/grid/OpenCustomPanelButtonPlugin.js +126 -89
  85. package/src/report/plugin/grid/ReportColumnStatePlugin.js +15 -3
  86. package/src/report/plugin/grid/SetSingleParameterPlugin.js +1 -1
  87. package/src/report/plugin/grid/ToolbarButtonPlugin.js +1 -1
  88. package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanel.js +55 -0
  89. package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanelController.js +226 -0
  90. package/src/report/plugin/grid/addFilterConditionPlugin/FilterConfigMixin.js +138 -0
  91. package/src/report/plugin/grid/addFilterConditionPlugin/FilterFieldFactory.js +223 -0
  92. package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.js +164 -0
  93. package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.scss +21 -0
  94. package/src/report/plugin/grid/addFilterConditionPlugin/FilterMenu.js +29 -0
  95. package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanel.js +53 -0
  96. package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanelController.js +57 -0
  97. package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.js +111 -0
  98. package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.scss +83 -0
  99. package/src/report/plugin/grid/addFilterConditionPlugin/SelectColumnPanel.js +102 -0
  100. package/src/report/selectionModels/MixedRowSelectionModel.js +36 -45
  101. package/src/report/toolbar/dropdown/ToolbarOverflowButton.js +16 -5
  102. package/src/report/toolbar/dropdown/ToolbarOverflowPanel.scss +26 -14
  103. package/src/report/toolbar/layout/ReportToolbarOverflow.js +5 -2
  104. package/src/ringBuffer.js +7 -3
  105. package/src/uielement/command/GetUIElementCommand.js +0 -1
  106. package/src/uielement/component/UiCPWrapper.js +26 -36
  107. package/src/uielement/component/UiCustomController.js +7 -0
  108. package/src/uielement/component/UiCustomPanel.js +46 -2
  109. package/src/uielement/component/settings/UiCustomPanelEditorController.js +35 -29
  110. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.js +146 -33
  111. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.scss +28 -0
  112. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGridController.js +366 -22
  113. package/src/uielement/component/settings/plugin/UiCustomPanelPluginModel.js +1 -0
  114. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanel.js +10 -4
  115. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanelController.js +28 -30
  116. package/src/uielement/plugin/UnifiedButtonToolbarPlugin.js +203 -22
  117. package/src/uielement/plugin/configPanel/ExecuteFunctionPluginConfigPanelFormEditor.js +4 -36
  118. package/src/uielement/plugin/configPanel/FireEventPluginConfigPanelFormEditor.js +5 -36
  119. package/src/uielement/plugin/configPanel/MethodChainPluginConfigPanelFormEditor.js +4 -36
  120. package/src/uielement/plugin/configPanel/OpenPanelPluginConfigPanelFormEditor.js +2 -38
  121. package/src/uielement/plugin/configPanel/PrintPdfPluginConfigPanelFormEditor.js +2 -35
  122. package/src/uielement/plugin/configPanel/UiCPPluginFormPanel.js +54 -0
  123. package/src/uielement/plugin/configPanel/UnifiedButtonToolbarPluginConfigPanelFormEditor.js +28 -18
  124. package/src/userSettings.js +1 -0
  125. package/src/util/ContextManager.js +109 -0
  126. package/src/util.js +96 -15
  127. package/src/version.js +1 -1
  128. package/src/app/viewPort/CenterViewController.js +0 -158
@@ -0,0 +1,610 @@
1
+ Ext.define('Coon.util.VisualLinker', {
2
+ xtype: 'VisualLinker',
3
+ singleton: true,
4
+
5
+ /**
6
+ * хранилище пар соединённых компонентов и их конфиг-параметров
7
+ * в качестве ключей - строка leadComponent-id + secondaryComponent-id
8
+ */
9
+ linkedElementList: new Map(),
10
+
11
+ /**
12
+ * CSS StyleSheet с правилами, исправляющими стили border у leadElement
13
+ * тэг <style#linkedStyleSheet> создаётся при первой записи в linkedElementList
14
+ * потом при добавлении новой пары создаются CSS правила для leadElement'a
15
+ * можно добавить опциональный параметр в конфиге для создания новых CSS-правил
16
+ */
17
+ linkedStyleSheet: null,
18
+
19
+ /**
20
+ * регистрация новой пары
21
+ */
22
+ createLinkedPair(leadComponent, secondaryComponent, options = {}) {
23
+ const parameters = this.processInputArguments(leadComponent, secondaryComponent, options);
24
+
25
+ const key = leadComponent.id + secondaryComponent.id;
26
+
27
+ if (this.linkedElementList.has(key)) {
28
+ return;
29
+ }
30
+
31
+ Object.assign(parameters, this.getLeadStyles(leadComponent));
32
+
33
+ this.linkedElementList.set(key, parameters);
34
+
35
+ if (!this.linkedStyleSheet) {
36
+ this.linkedStyleSheet = this.createLinkedStyleSheet();
37
+ }
38
+
39
+ this.setLinkedStyleSheetRules(parameters);
40
+ },
41
+
42
+ /**
43
+ * принимает ключ [leadComponent, secondaryComponent] для linkedElementList
44
+ * получает по ключу параметры для линковки
45
+ * соединяет элементы
46
+ */
47
+ link(leadComponent, secondaryComponent) {
48
+ const key = leadComponent.id + secondaryComponent.id;
49
+ const parameters = this.linkedElementList.get(key);
50
+
51
+ if (!parameters) {
52
+ console.error('No registred pair found');
53
+ return;
54
+ }
55
+
56
+ const {
57
+ leadComponentClass,
58
+ align,
59
+ outerBgColor,
60
+ verticalOffset,
61
+ roundCorners,
62
+ leadBgColor,
63
+ leadBorderColor,
64
+ } = parameters;
65
+
66
+ const {elemLead, elemSecondary} = this.getDomElements(leadComponent, secondaryComponent);
67
+
68
+ if (!elemLead) {
69
+ console.error('No lead DOM element found.');
70
+ return;
71
+ }
72
+ if (!elemSecondary) {
73
+ console.error('No secondary DOM element found. Make sure it is added to DOM before "link" call.');
74
+ return;
75
+ }
76
+
77
+ this.handleLeadClassName(leadComponent, leadComponentClass, align, 'add');
78
+
79
+ this.handleSecondaryClassName(secondaryComponent, leadComponentClass, align, 'add');
80
+
81
+ this.setSecondaryCssVariables(elemSecondary, leadBgColor, leadBorderColor);
82
+
83
+ this.setPositionSecondaryElement(secondaryComponent, elemLead, align, verticalOffset);
84
+
85
+ const linkerElements = this.createLinkerElements(
86
+ elemLead,
87
+ elemSecondary,
88
+ verticalOffset,
89
+ align,
90
+ outerBgColor,
91
+ roundCorners,
92
+ leadBgColor,
93
+ leadBorderColor
94
+ );
95
+
96
+ linkerElements.forEach((el) => {
97
+ if (el) {
98
+ document.body.append(el);
99
+ }
100
+ });
101
+
102
+ this.setLinkersRects(elemLead, elemSecondary, linkerElements, align);
103
+
104
+ const onLeadDestroyListener = leadComponent.on('beforedestroy', this.onLeadDestroy, this, {
105
+ args: [
106
+ secondaryComponent,
107
+ this.removeLinkers
108
+ ],
109
+ destroyable: true,
110
+ });
111
+
112
+ this.linkedElementList.set(key, Object.assign(parameters, {onLeadDestroyListener}));
113
+ },
114
+
115
+ /**
116
+ * принимает ключ [leadComponent, secondaryComponent] для linkedElementList
117
+ * получает по ключу параметры для линковки
118
+ * разъединяет элементы
119
+ */
120
+ unlink(leadComponent, secondaryComponent) {
121
+ const key = leadComponent.id + secondaryComponent.id;
122
+ const parameters = this.linkedElementList.get(key);
123
+
124
+ if (!parameters) {
125
+ console.error('No registred pair found');
126
+ return;
127
+ }
128
+
129
+ const {
130
+ leadComponentClass,
131
+ align,
132
+ onLeadDestroyListener,
133
+ } = parameters;
134
+
135
+ this.handleLeadClassName(leadComponent, leadComponentClass, align, 'remove');
136
+ this.removeLinkers();
137
+ if (onLeadDestroyListener) {
138
+ onLeadDestroyListener.destroy();
139
+ }
140
+ },
141
+
142
+ /**
143
+ * Before destroy event handler. Removes linkers from DOM
144
+ */
145
+ onLeadDestroy(secondaryComponent, removeLinkers) {
146
+ secondaryComponent.destroy();
147
+ removeLinkers();
148
+ },
149
+
150
+ /**
151
+ * @param {*} args - input arguments of createLinkedPair function
152
+ */
153
+ processInputArguments(leadComponent, secondaryComponent, options) {
154
+ if (!this.validateParameters(leadComponent, secondaryComponent, options)) {
155
+ console.error(`Check function's input parameters!`);
156
+ return;
157
+ }
158
+
159
+ const newOptions = this.setDefaultParameters(leadComponent, options);
160
+
161
+ const align = this.setAlign(options.alignment);
162
+
163
+ return ({...newOptions, align});
164
+ },
165
+
166
+ validateParameters(leadComponent, secondaryComponent, options) {
167
+ if (leadComponent && secondaryComponent) {
168
+ if (!leadComponent.isComponent || !secondaryComponent.isComponent) {
169
+ console.error('Some of input elements are not instantiated Components');
170
+ return false;
171
+ }
172
+ } else {
173
+ console.error('Not all required input components found.');
174
+ return false;
175
+ }
176
+
177
+ if (options.alignment) {
178
+ const validAlignment = {
179
+ horizontal: ['t', 'b'],
180
+ vertical: ['l', 'r', 'f'],
181
+ };
182
+ if (
183
+ !validAlignment.horizontal.includes(options.alignment[0]) ||
184
+ !validAlignment.vertical.includes(options.alignment[1])
185
+ ) {
186
+ console.error('Not valid "alignment" parameter.');
187
+ return false;
188
+ }
189
+ }
190
+
191
+ if (options.leadComponentClass && typeof options.leadComponentClass !== 'string') {
192
+ console.error('Class of the Lead element argument(leadComponentClass) must be of string type.');
193
+ return false;
194
+ }
195
+
196
+ if (options.outerBgColor && typeof options.outerBgColor !== 'string') {
197
+ console.error('Outer background color argument(outerBgColor) must be of string type.');
198
+ return false;
199
+ }
200
+
201
+ if (options.verticalOffset && !Number.isInteger(options.verticalOffset)) {
202
+ console.error('Vertical offset argument (verticalOffset) must be of integer type.');
203
+ return false;
204
+ }
205
+
206
+ if (options.roundCorners && typeof options.roundCorners !== 'boolean') {
207
+ console.error('Round corners argument (roundCorners) must be of boolean type.');
208
+ return false;
209
+ }
210
+
211
+ return true;
212
+ },
213
+
214
+ setDefaultParameters(leadComponent, options) {
215
+ const leadComponentClass = options.leadComponentClass || leadComponent.cls || 'VisualLinkerLead';
216
+ const alignment = options.alignment || 'bl';
217
+ const outerBgColor = options.outerBgColor || 'white';
218
+ const verticalOffset = options.verticalOffset || 8;
219
+ const roundCorners = options.roundCorners || false;
220
+
221
+ return {
222
+ leadComponentClass,
223
+ alignment,
224
+ outerBgColor,
225
+ verticalOffset,
226
+ roundCorners,
227
+ };
228
+ },
229
+
230
+ setAlign(alignment) {
231
+ const align = {
232
+ top: (alignment[0] === 't'),
233
+ bottom: (alignment[0] === 'b'),
234
+ left: (alignment[1] === 'l'),
235
+ right: (alignment[1] === 'r'),
236
+ full: (alignment[1] === 'f'),
237
+ };
238
+
239
+ const horizontal = Object.keys(align).filter((key) => (key === 'left' || key === 'right' || key === 'full') && align[key]);
240
+ const vertical = Object.keys(align).filter((key) => (key === 'top' || key === 'bottom') && align[key]);
241
+
242
+ return {...align, horizontal, vertical};
243
+ },
244
+
245
+ createLinkedStyleSheet() {
246
+ const el = document.createElement('style');
247
+ el.id = 'linkedStyleSheet';
248
+ document.head.appendChild(el);
249
+ return el;
250
+ },
251
+
252
+ getLeadStyles(leadComponent) {
253
+ const elemLead = leadComponent.getEl().dom;
254
+
255
+ const leadStyles = getComputedStyle(elemLead);
256
+ const borderColor = leadStyles.borderLeftColor ||
257
+ leadStyles.borderRightColor;
258
+ const bgColor = this.getEffectiveBgColor(elemLead);
259
+
260
+ return {leadBorderColor: borderColor, leadBgColor: bgColor};
261
+ },
262
+
263
+ /**
264
+ * Определяет цвет фона элемента, рекурсивно проходясь по родительским элементам, если цвет фона прозрачный.
265
+ * @param {DOM element} elem
266
+ * @returns color value
267
+ */
268
+ getEffectiveBgColor(elem) {
269
+ const elemStyles = getComputedStyle(elem);
270
+ const bgColor = elemStyles.backgroundColor;
271
+
272
+ if (bgColor && bgColor !== 'transparent' && bgColor !== 'rgba(0, 0, 0, 0)') {
273
+ return bgColor;
274
+ }
275
+
276
+ if (elem.parentElement) {
277
+ return this.getEffectiveBgColor(elem.parentElement);
278
+ }
279
+
280
+ // default white if no background found
281
+ return 'rgba(255, 255, 255, 1)';
282
+ },
283
+
284
+ /**
285
+ * Создаёт новые CSS правила в stylesheet, созданном этим классом.
286
+ * Это нужно для соединения селекторов исходного класса ведущего элемента и класса активации соединения.
287
+ * По данному селектору изменяются стили ведущего элемента - выпрямляются скруглённые границы.
288
+ */
289
+ setLinkedStyleSheetRules(options) {
290
+ const {leadComponentClass, align} = options;
291
+
292
+ const styleSheetRules = this.linkedStyleSheet.sheet.cssRules;
293
+
294
+ const leadRules = [
295
+ `border-${align.vertical}: none;`,
296
+ `border-${align.vertical}-left-radius: 0;`,
297
+ `border-${align.vertical}-right-radius: 0;`
298
+ ];
299
+
300
+ const contentRules = [
301
+ 'border: 1px solid var(--border-color);',
302
+ 'backround-color: var(--bd-color);'
303
+ ];
304
+
305
+ // Check if we already have this selector in our styleSheet
306
+ for (let i = 0; i < styleSheetRules.length; i++) {
307
+ if (styleSheetRules[i].selectorText.includes(leadComponentClass)) {
308
+ return;
309
+ }
310
+ }
311
+
312
+ this.linkedStyleSheet.sheet.insertRule(
313
+ `.${leadComponentClass}.${leadComponentClass}--active {${leadRules.join('')}}`
314
+ );
315
+
316
+ this.linkedStyleSheet.sheet.insertRule(
317
+ `.${leadComponentClass}-content {${contentRules.join('')}}`
318
+ );
319
+ },
320
+
321
+ /**
322
+ * Добавляет или убирает активный класс у ведущего элемента при активации/деактивации модального окна
323
+ * @param {*} leadComponent - ведущий компонент
324
+ * @param {*} leadComponentClass - главный класс ведущего компонента
325
+ * @param {*} alignment - позиция модалки относительно ведущего элемента
326
+ * @param {*} method - добавить класс или удалить (add/remove)
327
+ */
328
+ handleLeadClassName(leadComponent, leadComponentClass, align, method) {
329
+ const classNameActive = `${leadComponentClass}--active`;
330
+ const alignClassName = `${leadComponentClass}--${align.vertical}`;
331
+
332
+ if (method === 'add') {
333
+ leadComponent.addCls([classNameActive, alignClassName]);
334
+ } else if (method === 'remove') {
335
+ leadComponent.removeCls([classNameActive, alignClassName]);
336
+ }
337
+ },
338
+
339
+ /**
340
+ * Добавляет или убирает класс у модального окна при активации/деактивации
341
+ * @param {*} elemLead - ведущий элемент
342
+ * @param {*} leadComponentClass - главный класс ведущего компонента
343
+ * @param {*} alignment - позиция модалки относительно ведущего элемента
344
+ * @param {*} method - добавить класс или удалить (add/remove)
345
+ */
346
+ handleSecondaryClassName(secondaryComponent, leadComponentClass, align, method) {
347
+ const classNameSecondary = `${leadComponentClass}-content`;
348
+ const verticalAlignClassName = `${classNameSecondary}--${align.vertical}`;
349
+ const horizontalAlignClassName = `${classNameSecondary}--${align.horizontal}`;
350
+
351
+ if (method === 'add') {
352
+ secondaryComponent.addCls([classNameSecondary, verticalAlignClassName, horizontalAlignClassName]);
353
+ } else if (method === 'remove') {
354
+ secondaryComponent.removeCls([classNameSecondary, verticalAlignClassName, horizontalAlignClassName]);
355
+ }
356
+ },
357
+
358
+ /**
359
+ * Определение CSS переменных для контент-панели
360
+ */
361
+ setSecondaryCssVariables(elemSecondary, leadBgColor, leadBorderColor) {
362
+ elemSecondary.style.setProperty('--border-color', leadBorderColor);
363
+ // elemSecondary.style.setProperty('--bg-color', leadBgColor);
364
+ elemSecondary.style.setProperty('--bg-color', '#fff');
365
+ elemSecondary.style.setProperty('background-color', leadBgColor);
366
+ },
367
+
368
+ /**
369
+ * Позиционирование модалки (secondary элемент)
370
+ */
371
+ setPositionSecondaryElement(secondaryComponent, elemLead, align, verticalOffset) {
372
+ const elemLeadRect = elemLead.getBoundingClientRect();
373
+ const elemSecondary = secondaryComponent.getEl()?.dom;
374
+ if (!elemSecondary) {
375
+ return;
376
+ }
377
+ const elemSecondaryRect = elemSecondary.getBoundingClientRect();
378
+
379
+ if (align.full) {
380
+ this.setSecondaryElementRect(secondaryComponent, elemLeadRect, verticalOffset, align);
381
+ }
382
+
383
+ const elemSecondaryCoords = this.getElemSecondaryCoords(elemLeadRect, elemSecondaryRect, align, verticalOffset);
384
+
385
+ secondaryComponent.showAt(elemSecondaryCoords);
386
+ },
387
+
388
+ /**
389
+ * Если у нас фулл-скрин alignment='bf',
390
+ * то определяем размеры контент-части по всей ширине окна,
391
+ * а также определить высоту элемента как вся высота экрана за вычетом высоты кнопки и офсета
392
+ */
393
+ setSecondaryElementRect(secondaryComponent, elemLeadRect, verticalOffset, align) {
394
+ let height;
395
+ if (align.bottom) {
396
+ height = innerHeight - verticalOffset - elemLeadRect.bottom;
397
+ }
398
+ if (align.top) {
399
+ height = elemLeadRect.top - verticalOffset;
400
+ }
401
+ secondaryComponent.setHeight(`${height}px`);
402
+ secondaryComponent.setWidth('100%');
403
+ },
404
+
405
+ /**
406
+ * Calculates coords for elemSecondary
407
+ */
408
+ getElemSecondaryCoords(elemLeadRect, elemSecondaryRect, align, verticalOffset) {
409
+ let x = 0;
410
+ let y = 0;
411
+ if (align.bottom) {
412
+ y = elemLeadRect.bottom + verticalOffset;
413
+ } else if (align.top && !align.full) {
414
+ y = elemLeadRect.top - verticalOffset - elemSecondaryRect.height;
415
+ }
416
+
417
+ if (align.right) {
418
+ x = elemLeadRect.right - elemSecondaryRect.width;
419
+ } else if (align.left) {
420
+ x = elemLeadRect.x;
421
+ } else if (align.full) {
422
+ x = 0;
423
+ }
424
+
425
+ return [x, y];
426
+ },
427
+
428
+ /**
429
+ * Creates linker elements
430
+ * Sets element's classes, CSS variables and styles
431
+ * @param {*} elemLead - takes it's width, x/y coords and background color
432
+ * @param {*} elemSecondary - takes it's z-index
433
+ * @param {*} verticalOffset - used for sizes of linkers
434
+ * @param {*} alignment - alignments for linked elements
435
+ * @param {*} outerBgColor - outer background color around lead component
436
+ * @param {*} roundCorners - if we need roun corners in the connection of linkers and content element
437
+ * @returns array with linkers. [0] - Line Linker; [1] - Corner LInker
438
+ */
439
+ createLinkerElements(elemLead, elemSecondary, verticalOffset, align, outerBgColor, roundCorners, leadBgColor, leadBorderColor) {
440
+ let linkerLine = document.querySelector('.visualLinker-linkerLine');
441
+ let linkerCorner = document.querySelector('.visualLinker-linkerCorner');
442
+ if (linkerLine || linkerCorner) {
443
+ this.removeLinkers();
444
+ }
445
+
446
+ const elemLeadRect = elemLead.getBoundingClientRect();
447
+ const linkerZIndex = elemSecondary.style.zIndex + 10;
448
+
449
+ linkerLine = this.createLinkerLine(elemLeadRect, verticalOffset, linkerZIndex, leadBorderColor, roundCorners, align, leadBgColor);
450
+ if (roundCorners) {
451
+ linkerCorner = this.createLinkerCorner(align, verticalOffset, linkerZIndex, leadBorderColor, outerBgColor);
452
+ } else {
453
+ linkerCorner = null;
454
+ }
455
+
456
+ return [linkerLine, linkerCorner];
457
+ },
458
+
459
+ /**
460
+ * Creates line linker element with CSS variables and classes
461
+ */
462
+ createLinkerLine(elemLeadRect, verticalOffset, linkerZIndex, linkerBorderColor, roundCorners, align, bgColor) {
463
+ const linker = document.createElement('div');
464
+ linker.classList.add('visualLinker-linkerLine');
465
+
466
+ linker.style.setProperty('--width', `${elemLeadRect.width}`);
467
+ linker.style.setProperty('--size', `${verticalOffset + 2}px`);
468
+ linker.style.setProperty('--z-index', linkerZIndex);
469
+ linker.style.setProperty('--border-color', linkerBorderColor);
470
+ linker.style.setProperty('--bg-color', bgColor);
471
+
472
+ linker.style.setProperty('border', 'none');
473
+ linker.style.setProperty('border-left', `1px solid ${linkerBorderColor}`);
474
+ linker.style.setProperty('border-right', `1px solid ${linkerBorderColor}`);
475
+
476
+ linker.classList.add(`linker-${align.vertical}`, `linker-${align.horizontal}`);
477
+
478
+ if (!roundCorners || align.full) {
479
+ linker.classList.add('linker-full');
480
+ } else {
481
+ linker.classList.add(`linker-${align.horizontal}`);
482
+ }
483
+
484
+ return linker;
485
+ },
486
+
487
+ /**
488
+ * Creates corner linker element with CSS variables and classes
489
+ */
490
+ createLinkerCorner(align, verticalOffset, linkerZIndex, linkerBorderColor, outerBgColor) {
491
+ if (align.full) {
492
+ return null;
493
+ };
494
+
495
+ const linkerCorner = document.createElement('div');
496
+ linkerCorner.classList.add('visualLinker-linkerCorner');
497
+
498
+ linkerCorner.style.setProperty('--size', `${verticalOffset + 4}px`);
499
+ linkerCorner.style.setProperty('--z-index', linkerZIndex + 1);
500
+ linkerCorner.style.setProperty('--border-color', linkerBorderColor);
501
+ linkerCorner.style.setProperty('--outer-bg-color', outerBgColor);
502
+
503
+ linkerCorner.classList.add(`linkerCorner-${align.vertical}`, `linkerCorner-${align.horizontal}`);
504
+
505
+ return linkerCorner;
506
+ },
507
+
508
+ /**
509
+ * Рассчёт размеров и позиционирование линкеров
510
+ */
511
+ setLinkersRects(elemLead, elemSecondary, linkerElements, align) {
512
+ this.setLinkerLineElementRect(elemLead, elemSecondary, linkerElements[0], align);
513
+ if (linkerElements[1]) {
514
+ this.setLinkerCornerElementRect(elemLead, elemSecondary, linkerElements[1], align);
515
+ }
516
+ },
517
+
518
+ /**
519
+ * Позиционирование line linker'a
520
+ */
521
+ setLinkerLineElementRect(elemLead, elemSecondary, linkerLineElement, align) {
522
+ const elemLeadRect = elemLead.getBoundingClientRect();
523
+ const elemSecondaryRect = elemSecondary.getBoundingClientRect();
524
+ const linkerLineCoords = this.getLinkerLineCoords(elemLeadRect, elemSecondaryRect, align, linkerLineElement);
525
+
526
+ linkerLineElement.style.width = `${elemLeadRect.width}px`;
527
+ this.positionElem(linkerLineElement, linkerLineCoords);
528
+ },
529
+
530
+ /**
531
+ * Позиционирование corner linker'a
532
+ */
533
+ setLinkerCornerElementRect(elemLead, elemSecondary, linkerCornerElement, align) {
534
+ const elemLeadRect = elemLead.getBoundingClientRect();
535
+ const elemSecondaryRect = elemSecondary.getBoundingClientRect();
536
+ const linkerCornerCoords = this.getLinkerCornerCoords(elemLeadRect, elemSecondaryRect, align, linkerCornerElement);
537
+
538
+ this.positionElem(linkerCornerElement, linkerCornerCoords);
539
+ },
540
+
541
+ /**
542
+ * Calculates coords for line linker element
543
+ */
544
+ getLinkerLineCoords(elemLeadRect, elemSecondaryRect, align, linkerElement) {
545
+ let x = 0;
546
+ let y = 0;
547
+ const linkerRect = linkerElement.getBoundingClientRect();
548
+ if (align.bottom) {
549
+ x = elemLeadRect.x;
550
+ y = elemSecondaryRect.top - linkerRect.height;
551
+ } else if (align.top) {
552
+ x = elemLeadRect.x;
553
+ y = elemSecondaryRect.bottom;
554
+ }
555
+ return [x, y];
556
+ },
557
+
558
+ /**
559
+ * Calculates coords for corner linker element
560
+ */
561
+ getLinkerCornerCoords(elemLeadRect, elemSecondaryRect, align, linkerCornerElement) {
562
+ let x = 0;
563
+ let y = 0;
564
+ const linkerRect = linkerCornerElement.getBoundingClientRect();
565
+ if (align.bottom) {
566
+ y = elemSecondaryRect.top - linkerRect.height;
567
+ } else if (align.top) {
568
+ y = elemSecondaryRect.bottom;
569
+ }
570
+
571
+ if (align.left) {
572
+ x = elemLeadRect.right;
573
+ } else if (align.right) {
574
+ x = elemLeadRect.left - linkerRect.width;
575
+ }
576
+
577
+ return [x, y];
578
+ },
579
+
580
+ getDomElements(leadComponent, secondaryComponent) {
581
+ const elemLead = leadComponent?.getEl()?.dom;
582
+ const elemSecondary = secondaryComponent?.getEl()?.dom;
583
+
584
+ return {elemLead, elemSecondary};
585
+ },
586
+
587
+ /**
588
+ * Remove linker elements from the DOM
589
+ */
590
+ removeLinkers() {
591
+ const linkerElement = document.querySelector('.visualLinker-linkerLine');
592
+ const linkerCornerElement = document.querySelector('.visualLinker-linkerCorner');
593
+ if (linkerElement) {
594
+ linkerElement.remove();
595
+ }
596
+ if (linkerCornerElement) {
597
+ linkerCornerElement.remove();
598
+ }
599
+ },
600
+
601
+ /**
602
+ * Position DOM element by coordinates
603
+ * @param {*} elem
604
+ * @param {*} coords
605
+ */
606
+ positionElem(elem, coords) {
607
+ elem.style.left = `${coords[0]}px`;
608
+ elem.style.top = `${coords[1]}px`;
609
+ },
610
+ });