@formixru/b2b-ui 1.0.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 (73) hide show
  1. package/CONTRIBUTING.md +61 -0
  2. package/README.md +30 -0
  3. package/package.json +110 -0
  4. package/src/base.scss +89 -0
  5. package/src/components/action-list/index.scss +38 -0
  6. package/src/components/banner/index.scss +30 -0
  7. package/src/components/breadcrumbs/index.js +8 -0
  8. package/src/components/breadcrumbs/index.scss +55 -0
  9. package/src/components/button/index.scss +223 -0
  10. package/src/components/checkbox/index.scss +94 -0
  11. package/src/components/color-input/index.scss +88 -0
  12. package/src/components/color-input/index.vue +156 -0
  13. package/src/components/date-input/index.scss +126 -0
  14. package/src/components/date-input/index.vue +240 -0
  15. package/src/components/delete-all/index.scss +44 -0
  16. package/src/components/dialog/index.js +221 -0
  17. package/src/components/dialog/index.scss +198 -0
  18. package/src/components/empty-list/index.scss +97 -0
  19. package/src/components/file-input/index.scss +119 -0
  20. package/src/components/file-input/index.vue +333 -0
  21. package/src/components/font-input/index.scss +47 -0
  22. package/src/components/font-input/index.vue +154 -0
  23. package/src/components/form/index.js +228 -0
  24. package/src/components/form/index.scss +398 -0
  25. package/src/components/header-announcement/index.scss +48 -0
  26. package/src/components/input/index.js +85 -0
  27. package/src/components/input/index.scss +87 -0
  28. package/src/components/link/index.scss +266 -0
  29. package/src/components/loader/index.js +65 -0
  30. package/src/components/loader/index.scss +99 -0
  31. package/src/components/nobr/index.scss +5 -0
  32. package/src/components/overlay/index.js +82 -0
  33. package/src/components/overlay/index.scss +29 -0
  34. package/src/components/pagination/index.scss +59 -0
  35. package/src/components/pagination-group/index.js +5 -0
  36. package/src/components/pagination-group/index.scss +86 -0
  37. package/src/components/quantity-input/index.scss +179 -0
  38. package/src/components/quantity-input/index.vue +141 -0
  39. package/src/components/radio/index.scss +80 -0
  40. package/src/components/radio-list/index.scss +79 -0
  41. package/src/components/range-input/index.scss +109 -0
  42. package/src/components/range-input/index.vue +185 -0
  43. package/src/components/rating-input/index.js +32 -0
  44. package/src/components/rating-input/index.scss +36 -0
  45. package/src/components/select/index.js +6 -0
  46. package/src/components/select/index.scss +84 -0
  47. package/src/components/sidebar/index.js +174 -0
  48. package/src/components/sidebar/index.scss +398 -0
  49. package/src/components/simple-page/index.scss +32 -0
  50. package/src/components/slider-nav/index.scss +82 -0
  51. package/src/components/slider-pagination/index.scss +130 -0
  52. package/src/components/spinner/index.scss +35 -0
  53. package/src/components/sr-only/index.scss +25 -0
  54. package/src/components/steps/index.scss +155 -0
  55. package/src/components/suggest-input/index.scss +141 -0
  56. package/src/components/suggest-input/index.vue +324 -0
  57. package/src/components/tabs/index.js +192 -0
  58. package/src/components/tabs/index.scss +137 -0
  59. package/src/components/time-select/index.scss +27 -0
  60. package/src/components/toggle/index.scss +76 -0
  61. package/src/components/tooltip/index.js +69 -0
  62. package/src/components/tooltip/index.scss +112 -0
  63. package/src/components/total/index.scss +162 -0
  64. package/src/components/warning-message/index.scss +170 -0
  65. package/src/components/warning-message/index.vue +94 -0
  66. package/src/components/wysiwyg/index.scss +344 -0
  67. package/src/helpers/css-var.js +8 -0
  68. package/src/helpers/error-handler.js +61 -0
  69. package/src/helpers/get-smart-captcha.js +7 -0
  70. package/src/helpers/is-in-viewport.js +10 -0
  71. package/src/helpers/mm.js +52 -0
  72. package/src/helpers/scroll-to.js +21 -0
  73. package/src/variables.scss +1295 -0
@@ -0,0 +1,228 @@
1
+ /* globals BX, SmartCaptcha, SMART_CAPTCHA_KEY */
2
+
3
+ import { is } from '@advdominion/is';
4
+
5
+ import { errorHandler } from '../../helpers/error-handler.js';
6
+ import { getSmartCaptcha } from '../../helpers/get-smart-captcha.js';
7
+ import { scrollTo } from '../../helpers/scroll-to.js';
8
+ import { hide as hideDialog, initDialogContent, show as showDialog } from '../dialog/index.js';
9
+ import { clearLoaderTimeout, hide as hideLoader, show as showLoader } from '../loader/index.js';
10
+
11
+ const initFormContent = ($b) => {
12
+ try {
13
+ window.__FORMIX__FORM__INIT_CONTENT($b);
14
+ } catch {
15
+ console.warn('Функция __FORMIX__FORM__INIT_CONTENT не установлена');
16
+ }
17
+ };
18
+
19
+ export const send = async ($b, url, method, data) => {
20
+ url = new URL(url || $b.action, location.origin);
21
+ method = method || $b.method;
22
+ data = data || new FormData($b);
23
+ const options = {
24
+ method,
25
+ headers: {
26
+ 'X-Requested-With': 'XMLHttpRequest',
27
+ 'X-Session-Id': BX.message('bitrix_sessid'),
28
+ },
29
+ };
30
+ if (method === 'GET') {
31
+ for (const [name, value] of data) {
32
+ url.searchParams.append(name, value);
33
+ }
34
+ } else {
35
+ options.body = data;
36
+ }
37
+ showLoader();
38
+ try {
39
+ const response = await fetch(url, options);
40
+ if (!response.ok) {
41
+ throw response;
42
+ }
43
+ const data = await response.json().catch(() => {
44
+ console.warn('Ошибка при попытке преобразования ответа в JSON.');
45
+ return {};
46
+ });
47
+ if (data.success) {
48
+ $b.dispatchEvent(new CustomEvent('form-success', { bubbles: true }));
49
+ }
50
+ if (data.dialog) {
51
+ const $dialog = document.querySelector(data.dialog.id);
52
+ $dialog.querySelector('.dialog__container').innerHTML = data.dialog.content;
53
+ showDialog($dialog);
54
+ }
55
+ if (data.reloadOnHideDialog) {
56
+ $b.closest('.dialog').addEventListener('dialog-hide', () => {
57
+ location.reload();
58
+ });
59
+ }
60
+ if (data.hideDialog) {
61
+ hideDialog($b.closest('.dialog'));
62
+ }
63
+ try {
64
+ await window.__FORMIX__FORM__INTERCEPT_DATA(data);
65
+ } catch {
66
+ console.warn('Функция __FORMIX__FORM__INTERCEPT_DATA не установлена');
67
+ }
68
+ if (data.content) {
69
+ hideLoader();
70
+ const $dialog = $b.closest('.dialog');
71
+ if ($dialog) {
72
+ $dialog.querySelector('.dialog__container').innerHTML = data.content;
73
+ initDialogContent($dialog);
74
+ setTimeout(() => {
75
+ scrollToError($dialog);
76
+ });
77
+ } else {
78
+ const $parent = $b.parentElement;
79
+ $b.outerHTML = data.content;
80
+ const $form = $parent.querySelector('.form');
81
+ if ($form) {
82
+ init($form);
83
+ initFormContent($form);
84
+ setTimeout(() => {
85
+ scrollToError($form);
86
+ });
87
+ }
88
+ }
89
+ } else if (is(data.redirect, 'String')) {
90
+ if (data.redirect) {
91
+ location.assign(data.redirect);
92
+ if (data.redirect.startsWith('tg:')) {
93
+ hideLoader();
94
+ } else {
95
+ clearLoaderTimeout();
96
+ }
97
+ } else {
98
+ location.reload();
99
+ }
100
+ } else {
101
+ hideLoader();
102
+ }
103
+ } catch (error) {
104
+ if (error.status === 401) {
105
+ location.reload();
106
+ } else {
107
+ hideLoader();
108
+ errorHandler(error);
109
+ }
110
+ }
111
+ };
112
+
113
+ const scrollToError = ($b = document.body) => {
114
+ const $error = [...$b.querySelectorAll('.form__input-error, .form__submit-error')].find(($el) => {
115
+ const rect = $el.getBoundingClientRect();
116
+ return rect.x && rect.y;
117
+ });
118
+ if ($error) {
119
+ if ($error.closest('.dialog')) {
120
+ $error.scrollIntoView({ block: 'center', behavior: 'smooth' });
121
+ } else {
122
+ scrollTo($error, 50);
123
+ }
124
+ }
125
+ };
126
+
127
+ scrollToError();
128
+
129
+ const initCaptcha = ($b) => {
130
+ if (window.smartCaptcha) {
131
+ $b.insertAdjacentHTML('beforeend', '<div class="form__captcha"></div>');
132
+
133
+ $b.dataset.smartCaptchaId = window.smartCaptcha.render($b.querySelector('.form__captcha'), {
134
+ sitekey: SMART_CAPTCHA_KEY,
135
+ invisible: true,
136
+ hideShield: true,
137
+ test: process.env.NODE_ENV !== 'production',
138
+ });
139
+
140
+ window.smartCaptcha.subscribe($b.dataset.smartCaptchaId, 'success', () => {
141
+ $b.requestSubmit();
142
+ });
143
+
144
+ window.smartCaptcha.subscribe($b.dataset.smartCaptchaId, 'challenge-hidden', () => {
145
+ const $submitButton = $b.querySelector('.form__submit-button[type="submit"]');
146
+ if ($submitButton) {
147
+ $submitButton.disabled = false;
148
+ }
149
+ });
150
+ }
151
+ };
152
+
153
+ export const init = ($b) => {
154
+ if ($b.classList.contains('form_captcha')) {
155
+ if (window.smartCaptcha) {
156
+ if (SmartCaptcha.state) {
157
+ initCaptcha($b);
158
+ } else {
159
+ SmartCaptcha.addListener(() => {
160
+ initCaptcha($b);
161
+ });
162
+ }
163
+ } else {
164
+ getSmartCaptcha();
165
+ SmartCaptcha.addListener(() => {
166
+ initCaptcha($b);
167
+ });
168
+ }
169
+ }
170
+ };
171
+
172
+ document.body.addEventListener('submit', (event) => {
173
+ const { target } = event;
174
+ const $b = target.closest('.form');
175
+ if ($b) {
176
+ const $submitButton = $b.querySelector('.form__submit-button[type="submit"]');
177
+ if ($submitButton) {
178
+ $submitButton.disabled = true;
179
+ }
180
+ if ($b.classList.contains('form_captcha') && window.smartCaptcha) {
181
+ const $token = $b.querySelector('input[name="smart-token"]');
182
+ if ($token && $token.value) {
183
+ if ($b.classList.contains('form_ajax')) {
184
+ event.preventDefault();
185
+ send($b);
186
+ }
187
+ } else {
188
+ event.preventDefault();
189
+ window.smartCaptcha.execute($b.dataset.smartCaptchaId);
190
+ }
191
+ } else if ($b.classList.contains('form_ajax')) {
192
+ event.preventDefault();
193
+ send($b);
194
+ }
195
+ }
196
+ });
197
+
198
+ document.body.addEventListener('input', (event) => {
199
+ const { target } = event;
200
+ if (target.classList.contains('form__input')) {
201
+ const $error = target.closest('.form__input-wrapper').querySelector('.form__input-error');
202
+ if ($error) {
203
+ $error.textContent = '';
204
+ }
205
+ }
206
+ });
207
+
208
+ document.body.addEventListener('change', (event) => {
209
+ const { target } = event;
210
+ const $form = target.closest('.form');
211
+ if (target.classList.contains('form__trigger')) {
212
+ $form.requestSubmit();
213
+ } else if (target.dataset.request) {
214
+ const { name, value } = target.dataset.request;
215
+ $form.insertAdjacentHTML('afterbegin', `<input type="hidden" name="${name}" value="${value}">`);
216
+ $form.requestSubmit();
217
+ } else if (target.closest('.form__option')) {
218
+ const $error = target.closest('.form__option').querySelector('.form__input-error');
219
+ if ($error) {
220
+ $error.textContent = '';
221
+ }
222
+ } else if (target.closest('.select') || target.closest('.rating__input')) {
223
+ const $error = target.closest('.form__input-wrapper').querySelector('.form__input-error');
224
+ if ($error) {
225
+ $error.textContent = '';
226
+ }
227
+ }
228
+ });
@@ -0,0 +1,398 @@
1
+ @use '../../variables' as *;
2
+
3
+ $b: '.form';
4
+
5
+ #{$b} {
6
+ position: relative;
7
+
8
+ & + & {
9
+ margin-top: 4px * 10;
10
+ }
11
+
12
+ .sidebar & {
13
+ margin: 4px * 4;
14
+ }
15
+
16
+ .sidebar_l &,
17
+ .sidebar_xl & {
18
+ @media (--tablet-landscape-up) {
19
+ margin-left: 4px * 6;
20
+ margin-right: 4px * 6;
21
+ }
22
+
23
+ &:last-child {
24
+ margin-bottom: 4px * 10;
25
+ }
26
+ }
27
+
28
+ &_ajax {
29
+ }
30
+
31
+ &_captcha {
32
+ }
33
+
34
+ &_vertical {
35
+ }
36
+
37
+ &__group {
38
+ display: flex;
39
+ flex-direction: column;
40
+ max-width: 4px * 96;
41
+ width: 100%;
42
+
43
+ @media (--tablet-landscape-up) {
44
+ max-width: 4px * 146;
45
+ }
46
+
47
+ &:not(:first-of-type) {
48
+ margin-top: 4px * 10;
49
+ }
50
+
51
+ &_fluid {
52
+ max-width: none;
53
+ }
54
+ }
55
+
56
+ &__group-title {
57
+ color: $form-group-title-color;
58
+
59
+ @include font($form-group-title-font);
60
+ }
61
+
62
+ &__item {
63
+ display: flex;
64
+ flex-direction: column;
65
+
66
+ #{$b}:not(#{$b}_vertical) & {
67
+ @media (--tablet-landscape-up) {
68
+ align-items: flex-start;
69
+ flex-direction: row;
70
+ }
71
+ }
72
+
73
+ &:not(:first-child) {
74
+ margin-top: 4px * 6;
75
+ }
76
+
77
+ &_value {
78
+ }
79
+
80
+ &_option-list {
81
+ }
82
+
83
+ &_submit {
84
+ }
85
+
86
+ &_toggle {
87
+ }
88
+ }
89
+
90
+ &__label {
91
+ color: $form-label-color;
92
+ display: flex;
93
+ margin-bottom: 4px * 2;
94
+
95
+ @include font($form-label-font);
96
+
97
+ @media (--tablet-landscape-up) {
98
+ flex-shrink: 0;
99
+ margin-bottom: 0;
100
+ margin-right: 4px * 8;
101
+ position: relative;
102
+ top: 4px * 3;
103
+ width: 4px * 46;
104
+ }
105
+
106
+ &:empty {
107
+ @media (--tablet-portrait-down) {
108
+ display: none;
109
+ }
110
+ }
111
+
112
+ #{$b}_vertical & {
113
+ @media (--tablet-landscape-up) {
114
+ margin-bottom: 4px * 2;
115
+ margin-right: 0;
116
+ top: 0;
117
+ width: auto;
118
+ }
119
+ }
120
+
121
+ #{$b}__item_value & {
122
+ @media (--tablet-landscape-up) {
123
+ top: 0;
124
+ }
125
+ }
126
+
127
+ #{$b}__item_option-list & {
128
+ margin-bottom: 4px * 3;
129
+
130
+ @media (--tablet-landscape-up) {
131
+ margin-bottom: 0;
132
+ top: 0;
133
+ }
134
+
135
+ #{$b}_vertical & {
136
+ @media (--tablet-landscape-up) {
137
+ margin-bottom: 4px * 3;
138
+ }
139
+ }
140
+ }
141
+
142
+ #{$b}__item_submit & {
143
+ @media (--tablet-portrait-down) {
144
+ margin-bottom: 0;
145
+ margin-top: 4px * 4;
146
+ order: 2;
147
+ }
148
+
149
+ #{$b}_vertical & {
150
+ @media (--tablet-landscape-up) {
151
+ margin-bottom: 0;
152
+ margin-top: 4px * 4;
153
+ order: 2;
154
+ }
155
+ }
156
+ }
157
+
158
+ #{$b}__item_toggle & {
159
+ @media (--desktop-up) {
160
+ top: 0;
161
+ }
162
+ }
163
+ }
164
+
165
+ &__required {
166
+ color: $form-required-color;
167
+ left: -4px;
168
+ position: relative;
169
+ top: 0;
170
+
171
+ @include font($form-required-font);
172
+ }
173
+
174
+ &__help {
175
+ display: inline-block;
176
+ margin-left: 4px;
177
+ transform: translateY(4px);
178
+ transition-duration: var(--duration-micro-s);
179
+ transition-property: fill;
180
+ transition-timing-function: var(--easing-standard);
181
+
182
+ #{$b}__group-title & {
183
+ transform: none;
184
+ }
185
+
186
+ #{$b}__item_toggle & {
187
+ margin-left: 4px * 2;
188
+ transform: none;
189
+ }
190
+ }
191
+
192
+ &__help-icon {
193
+ display: block;
194
+ fill: $form-help-icon-color;
195
+ height: 4px * 5;
196
+ width: 4px * 5;
197
+
198
+ #{$b}__help:hover &,
199
+ #{$b}__help:focus-visible & {
200
+ fill: $form-help-icon-active-color;
201
+ }
202
+
203
+ #{$b}__item_toggle & {
204
+ height: 4px * 6;
205
+ width: 4px * 6;
206
+ }
207
+ }
208
+
209
+ &__input-wrapper {
210
+ @media (--tablet-landscape-up) {
211
+ flex-grow: 1;
212
+ }
213
+
214
+ #{$b}__item_submit & {
215
+ @media (--tablet-portrait-down) {
216
+ display: flex;
217
+ flex-direction: column;
218
+ margin-top: 0;
219
+ order: 1;
220
+ }
221
+
222
+ #{$b}_vertical & {
223
+ @media (--tablet-landscape-up) {
224
+ display: flex;
225
+ flex-direction: column;
226
+ order: 1;
227
+ }
228
+ }
229
+ }
230
+
231
+ #{$b}__item_toggle & {
232
+ align-items: center;
233
+ display: flex;
234
+ }
235
+ }
236
+
237
+ &__value {
238
+ color: $form-value-color;
239
+ display: block;
240
+ word-break: break-word;
241
+
242
+ @include font($form-value-font);
243
+ }
244
+
245
+ &__input {
246
+ width: 100%;
247
+ }
248
+
249
+ &__input-error {
250
+ color: $form-input-error-color;
251
+ display: block;
252
+ margin-top: 4px * 2;
253
+
254
+ @include font($form-input-error-font);
255
+
256
+ &:empty {
257
+ display: none;
258
+ }
259
+
260
+ #{$b}__item_option-list & {
261
+ margin-top: 4px * 4;
262
+ }
263
+
264
+ #{$b}__option & {
265
+ margin-top: 4px;
266
+ }
267
+ }
268
+
269
+ &__input-descr {
270
+ color: $form-input-descr-color;
271
+ display: block;
272
+ margin-top: 4px * 2;
273
+
274
+ @include font($form-input-descr-font);
275
+
276
+ #{$b}__item_option-list & {
277
+ margin-top: 4px * 4;
278
+ }
279
+
280
+ #{$b}__option & {
281
+ margin-top: 4px;
282
+ }
283
+
284
+ #{$b}__input-error:not(:empty) + & {
285
+ display: none;
286
+ }
287
+ }
288
+
289
+ &__option {
290
+ align-items: baseline;
291
+ display: flex;
292
+ justify-content: space-between;
293
+
294
+ &:not(:first-child) {
295
+ margin-top: 4px * 4;
296
+ }
297
+
298
+ &_extra {
299
+ &:not(:first-child) {
300
+ margin-top: 4px * 2;
301
+ }
302
+ }
303
+ }
304
+
305
+ &__link {
306
+ }
307
+
308
+ &__submit-descr {
309
+ color: $form-submit-descr-color;
310
+ text-align: center;
311
+ width: 100%;
312
+
313
+ @include font($form-submit-descr-font);
314
+
315
+ @media (--tablet-landscape-up) {
316
+ text-align: left;
317
+ }
318
+ }
319
+
320
+ &__submit-wrapper {
321
+ align-items: center;
322
+ display: flex;
323
+ flex-direction: column;
324
+
325
+ @media (--tablet-portrait-down) {
326
+ order: 2;
327
+ }
328
+
329
+ @media (--tablet-landscape-up) {
330
+ flex-direction: row;
331
+ }
332
+
333
+ #{$b}_vertical & {
334
+ @media (--tablet-landscape-up) {
335
+ order: 2;
336
+ }
337
+ }
338
+ }
339
+
340
+ &__submit-button {
341
+ flex-shrink: 0;
342
+
343
+ &:not(:first-child) {
344
+ margin-top: 4px * 4;
345
+
346
+ @media (--tablet-landscape-up) {
347
+ margin-left: 4px * 6;
348
+ margin-top: 0;
349
+ }
350
+ }
351
+
352
+ .dialog & {
353
+ @media (--tablet-portrait-down) {
354
+ max-width: none;
355
+ width: 100%;
356
+ }
357
+ }
358
+ }
359
+
360
+ &__submit-error {
361
+ background-color: $form-submit-error-bg;
362
+ border-radius: $form-submit-error-radius;
363
+ box-shadow: $form-submit-error-shadow;
364
+ color: $form-submit-error-color;
365
+ margin-bottom: 4px * 4;
366
+ padding: $form-submit-error-padding;
367
+ text-align: center;
368
+
369
+ @include font($form-submit-error-mobile-font);
370
+ @include dark-border;
371
+
372
+ @media (--tablet-portrait-down) {
373
+ order: 1;
374
+ }
375
+
376
+ @media (--tablet-landscape-up) {
377
+ margin-bottom: 0;
378
+ margin-top: 4px * 8;
379
+ text-align: left;
380
+
381
+ @include font($form-submit-error-desktop-font);
382
+ }
383
+
384
+ #{$b}_vertical & {
385
+ @media (--tablet-landscape-up) {
386
+ margin-bottom: 4px * 8;
387
+ margin-top: 0;
388
+ order: 1;
389
+ }
390
+ }
391
+ }
392
+
393
+ &__trigger {
394
+ }
395
+
396
+ &__captcha {
397
+ }
398
+ }
@@ -0,0 +1,48 @@
1
+ @use '../../variables' as *;
2
+
3
+ $b: '.header-announcement';
4
+
5
+ #{$b} {
6
+ align-items: center;
7
+ background-color: $header-announcement-bg;
8
+ color: $header-announcement-color;
9
+ display: flex;
10
+ justify-content: center;
11
+ min-height: 4px * 9;
12
+ padding-bottom: 4px * 2;
13
+ padding-left: 4px * 4;
14
+ padding-right: 4px * 4;
15
+ padding-top: calc(4px * 2 + env(safe-area-inset-top));
16
+ position: fixed;
17
+ text-align: center;
18
+ text-decoration: none;
19
+ top: 0;
20
+ width: 100%;
21
+ z-index: 105;
22
+
23
+ @include font($header-announcement-font);
24
+
25
+ @media (--tablet-landscape-up) {
26
+ position: sticky;
27
+ }
28
+
29
+ &_secondary {
30
+ background-color: $header-announcement-secondary-bg;
31
+ color: $header-announcement-secondary-color;
32
+ }
33
+
34
+ &_error {
35
+ background-color: $header-announcement-error-bg;
36
+ color: $header-announcement-error-color;
37
+ }
38
+
39
+ &_warning {
40
+ background-color: $header-announcement-warning-bg;
41
+ color: $header-announcement-warning-color;
42
+ }
43
+
44
+ &_success {
45
+ background-color: $header-announcement-success-bg;
46
+ color: $header-announcement-success-color;
47
+ }
48
+ }