@gudhub/ssg-web-components-library 1.0.114 → 1.0.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/faq-component/config.js +6 -0
- package/src/components/faq-component/faq-component-data.json +42 -0
- package/src/components/faq-component/faq-component.html +53 -0
- package/src/components/faq-component/faq-component.js +83 -0
- package/src/components/faq-component/faq-component.md +48 -0
- package/src/components/faq-component/faq-component.scss +123 -0
- package/src/components/get-in-touch-form/get-in-touch-form.html +3 -0
- package/src/components/get-in-touch-form/get-in-touch-form.js +72 -16
- package/src/components/get-in-touch-form/get-in-touch-form.scss +12 -0
- package/src/components/info-table/config.js +6 -0
- package/src/components/info-table/info-table.html +79 -0
- package/src/components/info-table/info-table.js +23 -0
- package/src/components/info-table/info-table.json +41 -0
- package/src/components/info-table/info-table.readme.md +176 -0
- package/src/components/info-table/info-table.scss +144 -0
- package/src/config.js +2 -0
package/package.json
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "faq-component",
|
|
3
|
+
"subtitle": "subtitle",
|
|
4
|
+
"items": [
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"title": "Expandable-vertical",
|
|
8
|
+
"text": "Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request. Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request.",
|
|
9
|
+
"list": {
|
|
10
|
+
"tag": "ul",
|
|
11
|
+
"items": ["List item 1", "List item 2", "List item 3"]
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"title": "Expandable-vertical",
|
|
16
|
+
"text": "Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request. Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"title": "Expandable-vertical",
|
|
20
|
+
"text": "Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request. Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
{
|
|
25
|
+
"title": "Expandable-vertical",
|
|
26
|
+
"text": "Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request. Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request.",
|
|
27
|
+
"list": {
|
|
28
|
+
"tag": "ol",
|
|
29
|
+
"items": ["List item 1", "List item 2", "List item 3"]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"title": "Expandable-vertical",
|
|
34
|
+
"text": "Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request. Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "Expandable-vertical",
|
|
38
|
+
"text": "Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request. Be certain that our website development agency will provide only first-rate web-based software and website programming. With constantly advancing progress and great competition in the web development field Quality Assurance (QA) became one of the important traits that clients seek in web development firms, and Atlasiko Inc. enables this feature. We also offer you our testing services to ensure that all developed solutions have functionalities adequate to your initial request."
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<section itemscope="" itemtype="https://schema.org/FAQPage">
|
|
2
|
+
<div class="container">
|
|
3
|
+
<div class="top-wrapper">
|
|
4
|
+
${json.title ? `
|
|
5
|
+
<h2 gh-id="${ghId}.title"> TITLE </h2>
|
|
6
|
+
` : ''}
|
|
7
|
+
${json.subtitle ? `
|
|
8
|
+
<p class="subtitle" gh-id="${ghId}.subtitle"> SUBTITLE </p>
|
|
9
|
+
` : ''}
|
|
10
|
+
</div>
|
|
11
|
+
<div class="flex-wrapper">
|
|
12
|
+
${json.items.reduce((acc, itemsColumn, indexColumn) => acc + `
|
|
13
|
+
<div class="accordion-column">
|
|
14
|
+
${itemsColumn.reduce((acc, item, index) => acc + `
|
|
15
|
+
<div class="primary-block" itemscope="" itemprop="mainEntity" itemtype="https://schema.org/Question">
|
|
16
|
+
<div class="visible-content">
|
|
17
|
+
${item.title ? `<h3 class="title" gh-id="${ghId}.items.${indexColumn}.${index}.title" itemprop="name"></h3>` : ''}
|
|
18
|
+
<div class="icon">
|
|
19
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17" fill="none"><path d="M1 8.33333L8.5 14.8148L16 8.33333M8.5 15L8.5 0" stroke="none" stroke-width="2"></path></svg>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="expandable-wrapper" itemscope="" itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
|
|
23
|
+
<div class="content" itemprop="text">
|
|
24
|
+
${item.text ? `<p class="text" gh-id="${ghId}.items.${indexColumn}.${index}.text"></p>` : ''}
|
|
25
|
+
${item.list ? `
|
|
26
|
+
<div class="list">
|
|
27
|
+
${(() => {
|
|
28
|
+
let tag = 'ul';
|
|
29
|
+
if (item.list.tag === 'ul' || item.list.tag === 'ol') {
|
|
30
|
+
tag = item.list.tag;
|
|
31
|
+
}
|
|
32
|
+
return `
|
|
33
|
+
<${tag}>
|
|
34
|
+
${item.list.items.reduce((acc, listItem, itemIndex) => acc + `
|
|
35
|
+
<li gh-id="${ghId}.items.${indexColumn}.${index}.list.items.${itemIndex}"></li>
|
|
36
|
+
`, '')}
|
|
37
|
+
</${tag}>
|
|
38
|
+
`
|
|
39
|
+
})()}
|
|
40
|
+
</div>
|
|
41
|
+
` : ''}
|
|
42
|
+
${item.button ? `
|
|
43
|
+
<button-component class="btn" data-link="${item.button.link}" data-popup-id="${item.button.popupId}" data-placement="${item.button.placement}">${item.button.text}</button-component>
|
|
44
|
+
` : ''}
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
`, '')}
|
|
49
|
+
</div>
|
|
50
|
+
`, '')}
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</section>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import html from './faq-component.html';
|
|
2
|
+
import './faq-component.scss';
|
|
3
|
+
import jsonTemplate from './faq-component-data.json';
|
|
4
|
+
|
|
5
|
+
class FaqComponent extends GHComponent {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
super.setDefaultData(jsonTemplate);
|
|
9
|
+
this.openedElement = null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async onServerRender() {
|
|
13
|
+
this.ghId = this.getAttribute('data-gh-id') || null;
|
|
14
|
+
|
|
15
|
+
const getCurrentChapter = await window?.getCurrentChapter();
|
|
16
|
+
this.chapter = getCurrentChapter ? getCurrentChapter : 'pages';
|
|
17
|
+
|
|
18
|
+
this.json = await super.getGhData(this.ghId, this.chapter);
|
|
19
|
+
|
|
20
|
+
if (this.ghId) {
|
|
21
|
+
await super.render(html);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onClientReady() {
|
|
26
|
+
this.attachEventListeners();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getBindedCallback(element) {
|
|
30
|
+
const expandableFunction = (event) => {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
|
|
33
|
+
const checkIsTargetInteractive = (target) => {
|
|
34
|
+
const preventedTagsForInteractive = ['button', 'a'];
|
|
35
|
+
const checkInteractiveTagNames = (target) => preventedTagsForInteractive.includes(target.tagName.toLowerCase());
|
|
36
|
+
const checkClassNames = (target) => target.classList.contains('btn');
|
|
37
|
+
|
|
38
|
+
const checkers = [checkInteractiveTagNames, checkClassNames];
|
|
39
|
+
const result = checkers.some((checker) => checker(target));
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (checkIsTargetInteractive(event.target)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const isOpening = element.classList.toggle('expand');
|
|
49
|
+
|
|
50
|
+
const toggleOverflow = (element, bool) => {
|
|
51
|
+
const action = bool ? 'add' : 'remove';
|
|
52
|
+
element.classList[action]('overflow');
|
|
53
|
+
};
|
|
54
|
+
if (isOpening) {
|
|
55
|
+
if (this.openedElement && this.openedElement !== element) {
|
|
56
|
+
this.openedElement.classList.remove('expand');
|
|
57
|
+
toggleOverflow(this.openedElement, false);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.openedElement = element;
|
|
61
|
+
|
|
62
|
+
setTimeout(() => toggleOverflow(element, true), 0);
|
|
63
|
+
} else {
|
|
64
|
+
toggleOverflow(element, false);
|
|
65
|
+
if (this.openedElement === element) {
|
|
66
|
+
this.openedElement = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return expandableFunction;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
attachEventListeners() {
|
|
75
|
+
const items = this.querySelectorAll('.primary-block');
|
|
76
|
+
for (const item of items) {
|
|
77
|
+
const boundCallback = this.getBindedCallback(item);
|
|
78
|
+
item.addEventListener('click', boundCallback);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
window.customElements.define('faq-component', FaqComponent);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Attributes:
|
|
2
|
+
|
|
3
|
+
None
|
|
4
|
+
|
|
5
|
+
# Component data-object:
|
|
6
|
+
|
|
7
|
+
("?" means "unnecessary")
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"title?": "string",
|
|
12
|
+
"subtitle?": "string",
|
|
13
|
+
"items": [
|
|
14
|
+
[
|
|
15
|
+
{
|
|
16
|
+
"title": "string",
|
|
17
|
+
"text": "string",
|
|
18
|
+
"button?": {
|
|
19
|
+
"link": "/link/",
|
|
20
|
+
"popupId": "form",
|
|
21
|
+
"placement": "faq-component",
|
|
22
|
+
"text": "Button Text"
|
|
23
|
+
},
|
|
24
|
+
"list?": {
|
|
25
|
+
"tag?": "string", // "ol" or "ul"
|
|
26
|
+
"items": ["string", "string", "string"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
{
|
|
32
|
+
"title": "string",
|
|
33
|
+
"text": "string",
|
|
34
|
+
"button?": {
|
|
35
|
+
"link": "/link/",
|
|
36
|
+
"popupId": "form",
|
|
37
|
+
"placement": "faq-component",
|
|
38
|
+
"text": "Button Text"
|
|
39
|
+
},
|
|
40
|
+
"list?": {
|
|
41
|
+
"tag?": "string", // "ol" or "ul"
|
|
42
|
+
"items": ["string", "string", "string"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
faq-component {
|
|
2
|
+
--hover-transition-duration: .2s;
|
|
3
|
+
--expand-transition-duration: .5s;
|
|
4
|
+
--gap: 20px;
|
|
5
|
+
background: var(--bg-color);
|
|
6
|
+
.subtitle {
|
|
7
|
+
max-width: 940px;
|
|
8
|
+
margin-left: auto;
|
|
9
|
+
margin-right: auto;
|
|
10
|
+
text-align: center;
|
|
11
|
+
}
|
|
12
|
+
.flex-wrapper {
|
|
13
|
+
display: flex;
|
|
14
|
+
gap: var(--gap);
|
|
15
|
+
}
|
|
16
|
+
.accordion-column {
|
|
17
|
+
width: calc(50% - (var(--gap) / 2));
|
|
18
|
+
& > *:not(:last-child) {
|
|
19
|
+
margin-bottom: 20px;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
.primary-block {
|
|
23
|
+
width: 100%;
|
|
24
|
+
background: var(--block-primary-bg-color);
|
|
25
|
+
border-radius: var(--block-primary-border-radius);
|
|
26
|
+
box-shadow: var(--block-primary-box-shadow);
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
transition: all var(--hover-transition-duration) ease;
|
|
29
|
+
&:hover, &.expand {
|
|
30
|
+
background-color: var(--block-primary-bg-hover-color);
|
|
31
|
+
}
|
|
32
|
+
.visible-content {
|
|
33
|
+
display: flex;
|
|
34
|
+
justify-content: space-between;
|
|
35
|
+
align-items: center;
|
|
36
|
+
padding: 16px;
|
|
37
|
+
.title {
|
|
38
|
+
margin-bottom: 0;
|
|
39
|
+
transition: color var(--hover-transition-duration) ease;
|
|
40
|
+
}
|
|
41
|
+
.icon {
|
|
42
|
+
width: 24px;
|
|
43
|
+
height: 24px;
|
|
44
|
+
display: flex;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
align-items: center;
|
|
47
|
+
svg {
|
|
48
|
+
width: 16px;
|
|
49
|
+
height: auto;
|
|
50
|
+
transition: transform var(--hover-transition-duration) linear;
|
|
51
|
+
path {
|
|
52
|
+
stroke: var(--h-color);
|
|
53
|
+
transition: stroke var(--hover-transition-duration) ease;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
.expandable-wrapper {
|
|
59
|
+
max-height: 0;
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
gap: 12px;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
transition: max-height var(--expand-transition-duration) ease;
|
|
65
|
+
.content {
|
|
66
|
+
padding: 20px 15px;
|
|
67
|
+
.text, li {
|
|
68
|
+
font-size: var(--text-font-size);
|
|
69
|
+
font-weight: var(--text-font-weight);
|
|
70
|
+
color: var(--block-primary-text-color);
|
|
71
|
+
line-height: 140%;
|
|
72
|
+
letter-spacing: 0.01em;
|
|
73
|
+
text-align: inherit;
|
|
74
|
+
}
|
|
75
|
+
ul {
|
|
76
|
+
padding-top: 10px;
|
|
77
|
+
padding-left: 18px;
|
|
78
|
+
list-style: disc;
|
|
79
|
+
}
|
|
80
|
+
ol {
|
|
81
|
+
padding-top: 10px;
|
|
82
|
+
padding-left: 18px;
|
|
83
|
+
list-style: decimal;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
&.expand {
|
|
88
|
+
.expandable-wrapper {
|
|
89
|
+
max-height: 200px;
|
|
90
|
+
}
|
|
91
|
+
.icon {
|
|
92
|
+
svg {
|
|
93
|
+
transform: rotate(180deg);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
&.overflow {
|
|
98
|
+
.expandable-wrapper {
|
|
99
|
+
overflow: auto;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
&:hover, &.expand {
|
|
103
|
+
.title {
|
|
104
|
+
color: var(--block-primary-accent-color);
|
|
105
|
+
}
|
|
106
|
+
.icon {
|
|
107
|
+
svg {
|
|
108
|
+
path {
|
|
109
|
+
stroke: var(--block-primary-accent-color);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
@media screen and (max-width: 800px) {
|
|
116
|
+
.flex-wrapper {
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
}
|
|
119
|
+
.accordion-column {
|
|
120
|
+
width: 100%;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
<button type="submit" class="btn">${buttonText ? buttonText : 'Get in touch'}</button>
|
|
11
11
|
<div class="loader"></div>
|
|
12
12
|
</div>
|
|
13
|
+
<div class="recaptcha-notice">
|
|
14
|
+
This site is protected by reCAPTCHA.
|
|
15
|
+
</div>
|
|
13
16
|
</form>
|
|
14
17
|
<div class="overflow success">
|
|
15
18
|
<div class="icon_wrapper">
|
|
@@ -5,6 +5,7 @@ import defaultConfigs from './get-in-touch-form-data.json';
|
|
|
5
5
|
import { checkInputsValidations } from './inputsValidation.js';
|
|
6
6
|
|
|
7
7
|
let recaptchaPromise = null;
|
|
8
|
+
let recaptchaBadgeObserver = null;
|
|
8
9
|
|
|
9
10
|
function loadRecaptcha(siteKey) {
|
|
10
11
|
if (!siteKey) {
|
|
@@ -35,16 +36,41 @@ function loadRecaptcha(siteKey) {
|
|
|
35
36
|
return recaptchaPromise;
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
function hideRecaptchaBadge() {
|
|
40
|
+
const badge = document.querySelector('.grecaptcha-badge');
|
|
41
|
+
|
|
42
|
+
if (!badge) return;
|
|
43
|
+
|
|
44
|
+
badge.style.setProperty('visibility', 'hidden', 'important');
|
|
45
|
+
badge.style.setProperty('opacity', '0', 'important');
|
|
46
|
+
badge.style.setProperty('pointer-events', 'none', 'important');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function observeRecaptchaBadge() {
|
|
50
|
+
hideRecaptchaBadge();
|
|
51
|
+
|
|
52
|
+
if (recaptchaBadgeObserver) return;
|
|
53
|
+
|
|
54
|
+
recaptchaBadgeObserver = new MutationObserver(() => {
|
|
55
|
+
hideRecaptchaBadge();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
recaptchaBadgeObserver.observe(document.body, {
|
|
59
|
+
childList: true,
|
|
60
|
+
subtree: true
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
38
64
|
class GetInTouchForm extends GHComponent {
|
|
39
65
|
constructor() {
|
|
40
66
|
super();
|
|
41
67
|
|
|
42
|
-
this.formId = this.getAttribute(
|
|
68
|
+
this.formId = this.getAttribute('data-form-id');
|
|
43
69
|
this.defaultConfigs = defaultConfigs;
|
|
44
70
|
|
|
45
71
|
this.generateInput = this.generateInput;
|
|
46
72
|
this.isFormSubmitted = false;
|
|
47
|
-
|
|
73
|
+
|
|
48
74
|
this.placement = 'main';
|
|
49
75
|
this.config = window.getConfig()?.componentsConfigs?.formConfig || window.getConfig()?.formConfig;
|
|
50
76
|
|
|
@@ -66,7 +92,11 @@ class GetInTouchForm extends GHComponent {
|
|
|
66
92
|
this.attachEventListeners();
|
|
67
93
|
|
|
68
94
|
if (this.recaptcha_site_key) {
|
|
69
|
-
loadRecaptcha(this.recaptcha_site_key)
|
|
95
|
+
loadRecaptcha(this.recaptcha_site_key)
|
|
96
|
+
.then(() => {
|
|
97
|
+
observeRecaptchaBadge();
|
|
98
|
+
})
|
|
99
|
+
.catch(console.error);
|
|
70
100
|
}
|
|
71
101
|
}
|
|
72
102
|
}
|
|
@@ -76,15 +106,26 @@ class GetInTouchForm extends GHComponent {
|
|
|
76
106
|
super.render(html);
|
|
77
107
|
this.attachEventListeners();
|
|
78
108
|
|
|
79
|
-
|
|
109
|
+
if (this.recaptcha_site_key) {
|
|
110
|
+
loadRecaptcha(this.recaptcha_site_key)
|
|
111
|
+
.then(() => {
|
|
112
|
+
observeRecaptchaBadge();
|
|
113
|
+
})
|
|
114
|
+
.catch(console.error);
|
|
115
|
+
}
|
|
80
116
|
}
|
|
81
117
|
|
|
82
118
|
attachEventListeners() {
|
|
83
|
-
this.getElementsByTagName('form')[0]
|
|
84
|
-
|
|
119
|
+
const form = this.getElementsByTagName('form')[0];
|
|
120
|
+
const restartButton = this.getElementsByClassName('restart_button')[0];
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
.addEventListener('
|
|
122
|
+
if (form) {
|
|
123
|
+
form.addEventListener('submit', (e) => this.handleSubmit(e));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (restartButton) {
|
|
127
|
+
restartButton.addEventListener('click', () => this.hideFail());
|
|
128
|
+
}
|
|
88
129
|
}
|
|
89
130
|
|
|
90
131
|
onParentPopupClose() {
|
|
@@ -99,7 +140,7 @@ class GetInTouchForm extends GHComponent {
|
|
|
99
140
|
initConfig(formConfigs) {
|
|
100
141
|
try {
|
|
101
142
|
this.config = formConfigs.find(({ id }) => id === this.formId);
|
|
102
|
-
if (!this.config) throw new Error(
|
|
143
|
+
if (!this.config) throw new Error('Config not found');
|
|
103
144
|
} catch {
|
|
104
145
|
const defaultId = this.isInPopup ? 'default popup' : 'default';
|
|
105
146
|
this.config = defaultConfigs.find(({ id }) => id === defaultId);
|
|
@@ -107,7 +148,7 @@ class GetInTouchForm extends GHComponent {
|
|
|
107
148
|
|
|
108
149
|
this.titleName = this.getAttribute('data-form-title') || this.config.title;
|
|
109
150
|
this.subtitleName = this.getAttribute('data-form-subtitle') || this.config.subtitle;
|
|
110
|
-
this.placement = this.getAttribute('data-form-placement') ||
|
|
151
|
+
this.placement = this.getAttribute('data-form-placement') || 'main';
|
|
111
152
|
this.buttonText = this.getAttribute('data-form-button-text') || this.config.button_text;
|
|
112
153
|
}
|
|
113
154
|
|
|
@@ -121,6 +162,8 @@ class GetInTouchForm extends GHComponent {
|
|
|
121
162
|
|
|
122
163
|
return new Promise((resolve, reject) => {
|
|
123
164
|
grecaptcha.ready(() => {
|
|
165
|
+
hideRecaptchaBadge();
|
|
166
|
+
|
|
124
167
|
grecaptcha.execute(this.recaptcha_site_key, { action })
|
|
125
168
|
.then(resolve)
|
|
126
169
|
.catch(reject);
|
|
@@ -146,7 +189,6 @@ class GetInTouchForm extends GHComponent {
|
|
|
146
189
|
}
|
|
147
190
|
|
|
148
191
|
this.handleSuccessFormValidation(form, token);
|
|
149
|
-
|
|
150
192
|
} catch (error) {
|
|
151
193
|
console.error(error);
|
|
152
194
|
this.showFail();
|
|
@@ -179,7 +221,7 @@ class GetInTouchForm extends GHComponent {
|
|
|
179
221
|
inputsValidation = async (form) => {
|
|
180
222
|
const inputs = Array.from(form.querySelectorAll('input'));
|
|
181
223
|
return checkInputsValidations(inputs);
|
|
182
|
-
}
|
|
224
|
+
};
|
|
183
225
|
|
|
184
226
|
verifyRecaptcha = async (recaptchaToken) => {
|
|
185
227
|
const response = await fetch('/api/verify-recaptcha', {
|
|
@@ -200,7 +242,7 @@ class GetInTouchForm extends GHComponent {
|
|
|
200
242
|
}
|
|
201
243
|
|
|
202
244
|
return data;
|
|
203
|
-
}
|
|
245
|
+
};
|
|
204
246
|
|
|
205
247
|
createDataObject(form, placement, recaptchaToken) {
|
|
206
248
|
const inputs = {};
|
|
@@ -230,13 +272,24 @@ class GetInTouchForm extends GHComponent {
|
|
|
230
272
|
|
|
231
273
|
addLoader() {
|
|
232
274
|
this.classList.add('loading');
|
|
233
|
-
|
|
275
|
+
|
|
276
|
+
const btn = this.querySelector('button[type="submit"]');
|
|
277
|
+
|
|
278
|
+
if (btn) {
|
|
279
|
+
btn.disabled = true;
|
|
280
|
+
}
|
|
234
281
|
}
|
|
235
282
|
|
|
236
283
|
removeLoader() {
|
|
237
284
|
this.classList.remove('loading');
|
|
285
|
+
|
|
238
286
|
const btn = this.querySelector('button[type="submit"]');
|
|
239
|
-
|
|
287
|
+
|
|
288
|
+
if (btn) {
|
|
289
|
+
setTimeout(() => {
|
|
290
|
+
btn.disabled = false;
|
|
291
|
+
}, 500);
|
|
292
|
+
}
|
|
240
293
|
}
|
|
241
294
|
|
|
242
295
|
showSuccess({ email, phone }) {
|
|
@@ -278,6 +331,9 @@ class GetInTouchForm extends GHComponent {
|
|
|
278
331
|
|
|
279
332
|
hideFail() {
|
|
280
333
|
const el = this.querySelector('.overflow.fail');
|
|
334
|
+
|
|
335
|
+
if (!el) return;
|
|
336
|
+
|
|
281
337
|
el.style.opacity = 0;
|
|
282
338
|
|
|
283
339
|
setTimeout(() => {
|
|
@@ -315,4 +371,4 @@ class GetInTouchForm extends GHComponent {
|
|
|
315
371
|
|
|
316
372
|
if (!customElements.get('get-in-touch-form')) {
|
|
317
373
|
customElements.define('get-in-touch-form', GetInTouchForm);
|
|
318
|
-
}
|
|
374
|
+
}
|
|
@@ -271,6 +271,12 @@ get-in-touch-form {
|
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
|
+
.recaptcha-notice {
|
|
275
|
+
margin-top: 10px;
|
|
276
|
+
font-size: 12px;
|
|
277
|
+
line-height: 1.4;
|
|
278
|
+
opacity: 0.7;
|
|
279
|
+
}
|
|
274
280
|
&[data-in-popup] {
|
|
275
281
|
.get-in-touch-form {
|
|
276
282
|
padding-top: 0;
|
|
@@ -368,4 +374,10 @@ popup-container[data-position="bottom-right"] {
|
|
|
368
374
|
}
|
|
369
375
|
}
|
|
370
376
|
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
body .grecaptcha-badge {
|
|
380
|
+
visibility: hidden !important;
|
|
381
|
+
opacity: 0 !important;
|
|
382
|
+
pointer-events: none !important;
|
|
371
383
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<section class="info-table">
|
|
2
|
+
<div class="container">
|
|
3
|
+
<div class="top-wrapper">
|
|
4
|
+
${json.title ? `<h2 class="title" gh-id="${ghId}.title"></h2>` : ''}
|
|
5
|
+
${json.subtitle ? `<p class="subtitle" gh-id="${ghId}.subtitle"></p>` : ''}
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div class="blocks-wrapper">
|
|
9
|
+
<table
|
|
10
|
+
class="block"
|
|
11
|
+
itemscope
|
|
12
|
+
itemtype="${json.schema?.tableType || 'https://schema.org/Table'}"
|
|
13
|
+
>
|
|
14
|
+
${json.headers?.length ? `
|
|
15
|
+
<thead>
|
|
16
|
+
<tr class="table-head" gh-array="${ghId}.headers">
|
|
17
|
+
${json.headers.reduce((acc, item, index) => {
|
|
18
|
+
return acc + `
|
|
19
|
+
<th gh-item>
|
|
20
|
+
<span gh-id="${ghId}.headers.${index}"></span>
|
|
21
|
+
</th>
|
|
22
|
+
`
|
|
23
|
+
}, '')}
|
|
24
|
+
</tr>
|
|
25
|
+
</thead>
|
|
26
|
+
` : ''}
|
|
27
|
+
|
|
28
|
+
<tbody gh-array="${ghId}.items">
|
|
29
|
+
${json.items.reduce((acc, item, index) => {
|
|
30
|
+
return acc + `
|
|
31
|
+
<tr
|
|
32
|
+
class="item"
|
|
33
|
+
gh-item
|
|
34
|
+
itemprop="${json.schema?.rowProp || 'about'}"
|
|
35
|
+
itemscope
|
|
36
|
+
itemtype="${json.schema?.rowType || 'https://schema.org/Thing'}"
|
|
37
|
+
>
|
|
38
|
+
<td>
|
|
39
|
+
<p
|
|
40
|
+
class="item-title"
|
|
41
|
+
gh-id="${ghId}.items.${index}.title"
|
|
42
|
+
itemprop="${json.schema?.titleProp || 'name'}"
|
|
43
|
+
></p>
|
|
44
|
+
</td>
|
|
45
|
+
|
|
46
|
+
${json.schema?.valueType === 'offer' ? `
|
|
47
|
+
<td
|
|
48
|
+
itemprop="${json.schema?.offerProp || 'offers'}"
|
|
49
|
+
itemscope
|
|
50
|
+
itemtype="${json.schema?.offerType || 'https://schema.org/Offer'}"
|
|
51
|
+
>
|
|
52
|
+
<p class="item-price">
|
|
53
|
+
$<span
|
|
54
|
+
gh-id="${ghId}.items.${index}.price"
|
|
55
|
+
itemprop="${json.schema?.priceProp || 'price'}"
|
|
56
|
+
></span>
|
|
57
|
+
<span
|
|
58
|
+
gh-id="${ghId}.items.${index}.currency"
|
|
59
|
+
itemprop="${json.schema?.currencyProp || 'priceCurrency'}"
|
|
60
|
+
></span>
|
|
61
|
+
</p>
|
|
62
|
+
</td>
|
|
63
|
+
` : `
|
|
64
|
+
<td>
|
|
65
|
+
<p
|
|
66
|
+
class="item-price"
|
|
67
|
+
gh-id="${ghId}.items.${index}.price"
|
|
68
|
+
itemprop="${json.schema?.valueProp || 'description'}"
|
|
69
|
+
></p>
|
|
70
|
+
</td>
|
|
71
|
+
`}
|
|
72
|
+
</tr>
|
|
73
|
+
`
|
|
74
|
+
}, '')}
|
|
75
|
+
</tbody>
|
|
76
|
+
</table>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</section>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import html from './info-table.html';
|
|
2
|
+
import './info-table.scss';
|
|
3
|
+
import jsonTemplate from './info-table.json';
|
|
4
|
+
|
|
5
|
+
class InfoTable extends window.GHComponent {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
super.setDefaultData(jsonTemplate);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async onServerRender() {
|
|
12
|
+
this.ghId = this.getAttribute('data-gh-id') || null;
|
|
13
|
+
this.json = await super.getGhData(this.ghId, 'areas');
|
|
14
|
+
|
|
15
|
+
console.log("AAAAAAAAAAAAAAAAAAAAAAAA", this.json);
|
|
16
|
+
|
|
17
|
+
if (this.json) {
|
|
18
|
+
super.render(html);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
window.customElements.define('info-table', InfoTable);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Lorem Ipsum Pricing",
|
|
3
|
+
"subtitle": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
4
|
+
"schema": {
|
|
5
|
+
"tableType": "https://schema.org/Table",
|
|
6
|
+
"rowProp": "about",
|
|
7
|
+
"rowType": "https://schema.org/Service",
|
|
8
|
+
"titleProp": "name",
|
|
9
|
+
"valueType": "offer",
|
|
10
|
+
"offerProp": "offers",
|
|
11
|
+
"offerType": "https://schema.org/Offer",
|
|
12
|
+
"priceProp": "price",
|
|
13
|
+
"currencyProp": "priceCurrency"
|
|
14
|
+
},
|
|
15
|
+
"headers": [
|
|
16
|
+
"Service Name",
|
|
17
|
+
"Price Starts at"
|
|
18
|
+
],
|
|
19
|
+
"items": [
|
|
20
|
+
{
|
|
21
|
+
"title": "Lorem Ipsum Service",
|
|
22
|
+
"price": "120",
|
|
23
|
+
"currency": "USD"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"title": "Dolor Sit Service",
|
|
27
|
+
"price": "240",
|
|
28
|
+
"currency": "USD"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"title": "Consectetur Service",
|
|
32
|
+
"price": "360",
|
|
33
|
+
"currency": "USD"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"title": "Adipiscing Service",
|
|
37
|
+
"price": "480",
|
|
38
|
+
"currency": "USD"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Ось оновлений README під твій новий динамічний компонент з `headers` та `schema`.
|
|
2
|
+
|
|
3
|
+
````md
|
|
4
|
+
# Component data-object
|
|
5
|
+
|
|
6
|
+
`("?": means "unnecessary")`
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"title?": "Lorem Ipsum Overview",
|
|
11
|
+
"subtitle?": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
12
|
+
"schema?": {
|
|
13
|
+
"tableType": "https://schema.org/Table",
|
|
14
|
+
"rowProp": "about",
|
|
15
|
+
"rowType": "https://schema.org/Thing",
|
|
16
|
+
"titleProp": "name",
|
|
17
|
+
"valueProp": "description"
|
|
18
|
+
},
|
|
19
|
+
"headers?": [
|
|
20
|
+
"Feature Name",
|
|
21
|
+
"Description"
|
|
22
|
+
],
|
|
23
|
+
"items": [
|
|
24
|
+
{
|
|
25
|
+
"title": "Lorem Ipsum Feature",
|
|
26
|
+
"price": "Lorem ipsum dolor sit amet"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"title": "Dolor Sit Amet",
|
|
30
|
+
"price": "Consectetur adipiscing elit"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"title": "Sed Do Eiusmod",
|
|
34
|
+
"price": "Tempor incididunt ut labore"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "Ut Enim Ad Minim",
|
|
38
|
+
"price": "Veniam quis nostrud exercitation"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
````
|
|
43
|
+
|
|
44
|
+
## Fields description
|
|
45
|
+
|
|
46
|
+
`title` - component title. If the field does not exist, the title will not be rendered.
|
|
47
|
+
|
|
48
|
+
`subtitle` - component subtitle. If the field does not exist, the subtitle will not be rendered.
|
|
49
|
+
|
|
50
|
+
`schema` - optional object for configuring microdata markup.
|
|
51
|
+
|
|
52
|
+
`schema.tableType` - Schema.org type for the table. Default value is `https://schema.org/Table`.
|
|
53
|
+
|
|
54
|
+
`schema.rowProp` - item property used for each table row. Default value is `about`.
|
|
55
|
+
|
|
56
|
+
`schema.rowType` - Schema.org type for each table row. Default value is `https://schema.org/Thing`.
|
|
57
|
+
|
|
58
|
+
`schema.titleProp` - item property for the first column value. Default value is `name`.
|
|
59
|
+
|
|
60
|
+
`schema.valueProp` - item property for the second column value. Default value is `description`.
|
|
61
|
+
|
|
62
|
+
`headers` - optional array of table header labels. If the field does not exist or is empty, the table header will not be rendered.
|
|
63
|
+
|
|
64
|
+
`items` - array of table rows.
|
|
65
|
+
|
|
66
|
+
`items.title` - item title. Usually rendered in the first table column.
|
|
67
|
+
|
|
68
|
+
`items.price` - item price/value/description. Usually rendered in the second table column.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
# Pricing table example
|
|
73
|
+
|
|
74
|
+
Use this structure when the table contains services and prices.
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"title": "3D Rendering Services Pricing",
|
|
79
|
+
"subtitle": "Explore starting prices for different 3D rendering services.",
|
|
80
|
+
"schema": {
|
|
81
|
+
"tableType": "https://schema.org/Table",
|
|
82
|
+
"rowProp": "about",
|
|
83
|
+
"rowType": "https://schema.org/Service",
|
|
84
|
+
"titleProp": "name",
|
|
85
|
+
"valueType": "offer",
|
|
86
|
+
"offerProp": "offers",
|
|
87
|
+
"offerType": "https://schema.org/Offer",
|
|
88
|
+
"priceProp": "price",
|
|
89
|
+
"currencyProp": "priceCurrency"
|
|
90
|
+
},
|
|
91
|
+
"headers": [
|
|
92
|
+
"Service Name",
|
|
93
|
+
"Price Starts at"
|
|
94
|
+
],
|
|
95
|
+
"items": [
|
|
96
|
+
{
|
|
97
|
+
"title": "Interior 3D Rendering",
|
|
98
|
+
"price": "547",
|
|
99
|
+
"currency": "CAD"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"title": "Exterior 3D Rendering",
|
|
103
|
+
"price": "683",
|
|
104
|
+
"currency": "CAD"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"title": "Commercial Interior 3D Rendering",
|
|
108
|
+
"price": "820",
|
|
109
|
+
"currency": "CAD"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"title": "Commercial Exterior 3D Rendering",
|
|
113
|
+
"price": "957",
|
|
114
|
+
"currency": "CAD"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Additional fields for pricing table
|
|
121
|
+
|
|
122
|
+
`schema.valueType` - defines how the second column should be rendered. If the value is `offer`, the component renders the second column as a Schema.org `Offer`.
|
|
123
|
+
|
|
124
|
+
`schema.offerProp` - item property for the offer object. Default value is `offers`.
|
|
125
|
+
|
|
126
|
+
`schema.offerType` - Schema.org type for the offer. Default value is `https://schema.org/Offer`.
|
|
127
|
+
|
|
128
|
+
`schema.priceProp` - item property for the price value. Default value is `price`.
|
|
129
|
+
|
|
130
|
+
`schema.currencyProp` - item property for the currency value. Default value is `priceCurrency`.
|
|
131
|
+
|
|
132
|
+
`items.currency` - price currency. Required when `schema.valueType` is set to `offer`.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
# Explanation
|
|
137
|
+
|
|
138
|
+
The component supports two table formats.
|
|
139
|
+
|
|
140
|
+
The first format is a regular informational table. In this case, each row is marked as a Schema.org `Thing`, the first column is marked as `name`, and the second column is marked as `description`.
|
|
141
|
+
|
|
142
|
+
Example output structure:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
Table
|
|
146
|
+
└── about: Thing
|
|
147
|
+
├── name: Lorem Ipsum Feature
|
|
148
|
+
└── description: Lorem ipsum dolor sit amet
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The second format is a pricing table. In this case, each row is marked as a Schema.org `Service`, and the second column is rendered as an `Offer` with separate `price` and `priceCurrency` values.
|
|
152
|
+
|
|
153
|
+
Example output structure:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
Table
|
|
157
|
+
└── about: Service
|
|
158
|
+
├── name: Interior 3D Rendering
|
|
159
|
+
└── offers: Offer
|
|
160
|
+
├── price: 547
|
|
161
|
+
└── priceCurrency: CAD
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For regular text tables, use:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
"valueProp": "description"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
For pricing tables, use:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
"valueType": "offer"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This allows the same component to be reused for simple informational tables and for service pricing tables with more correct microdata markup.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
info-table {
|
|
2
|
+
section {
|
|
3
|
+
padding: 0 375px 80px 375px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.top-wrapper {
|
|
7
|
+
margin-bottom: 30px;
|
|
8
|
+
|
|
9
|
+
.title {
|
|
10
|
+
color: #05183A;
|
|
11
|
+
font-weight: 700;
|
|
12
|
+
font-size: 30px;
|
|
13
|
+
line-height: 136%;
|
|
14
|
+
letter-spacing: 0%;
|
|
15
|
+
text-align: center;
|
|
16
|
+
text-transform: uppercase;
|
|
17
|
+
margin-bottom: 12px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.subtitle {
|
|
21
|
+
font-weight: 400;
|
|
22
|
+
font-size: 18px;
|
|
23
|
+
line-height: 136%;
|
|
24
|
+
letter-spacing: 0%;
|
|
25
|
+
text-align: justify;
|
|
26
|
+
color: #63636F;
|
|
27
|
+
text-align: center;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.block {
|
|
32
|
+
width: 100%;
|
|
33
|
+
margin-bottom: 25px;
|
|
34
|
+
border: 1px solid #C8C8C8;
|
|
35
|
+
border-collapse: collapse;
|
|
36
|
+
table-layout: fixed;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.table-head {
|
|
40
|
+
th {
|
|
41
|
+
width: 50%;
|
|
42
|
+
height: 52px;
|
|
43
|
+
padding: 0 15px;
|
|
44
|
+
border-bottom: 1px solid #C8C8C8;
|
|
45
|
+
vertical-align: middle;
|
|
46
|
+
text-align: center;
|
|
47
|
+
font-size: 18px;
|
|
48
|
+
font-weight: 700;
|
|
49
|
+
color: black;
|
|
50
|
+
line-height: 120%;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
th:not(:last-child) {
|
|
54
|
+
border-right: 1px solid #C8C8C8;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.item {
|
|
59
|
+
&:nth-child(even) {
|
|
60
|
+
background-color: #F6F6F6;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
td {
|
|
64
|
+
width: 50%;
|
|
65
|
+
height: 48px;
|
|
66
|
+
padding: 0 15px;
|
|
67
|
+
border-bottom: 1px solid #C8C8C8;
|
|
68
|
+
vertical-align: middle;
|
|
69
|
+
text-align: center;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
td:not(:last-child) {
|
|
73
|
+
border-right: 1px solid #C8C8C8;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
&:last-child {
|
|
77
|
+
td {
|
|
78
|
+
border-bottom: none;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&-title,
|
|
83
|
+
&-price {
|
|
84
|
+
width: 100%;
|
|
85
|
+
margin: 0;
|
|
86
|
+
font-size: 16px;
|
|
87
|
+
font-weight: 400;
|
|
88
|
+
color: black;
|
|
89
|
+
line-height: 140%;
|
|
90
|
+
text-align: center;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@media (max-width: 1900px) {
|
|
95
|
+
section {
|
|
96
|
+
padding-left: calc(100vw / 15);
|
|
97
|
+
padding-right: calc(100vw / 15);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@media (max-width: 1000px) {
|
|
102
|
+
section {
|
|
103
|
+
padding-bottom: 70px;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@media (max-width: 700px) {
|
|
108
|
+
section {
|
|
109
|
+
padding-bottom: 40px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.top-wrapper {
|
|
113
|
+
margin-bottom: 24px;
|
|
114
|
+
|
|
115
|
+
.title {
|
|
116
|
+
font-size: 26px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.subtitle {
|
|
120
|
+
font-size: 16px;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.table-head {
|
|
125
|
+
th {
|
|
126
|
+
height: 48px;
|
|
127
|
+
padding: 0 10px;
|
|
128
|
+
font-size: 16px;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.item {
|
|
133
|
+
td {
|
|
134
|
+
height: 46px;
|
|
135
|
+
padding: 0 10px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
&-title,
|
|
139
|
+
&-price {
|
|
140
|
+
font-size: 15px;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
package/src/config.js
CHANGED
|
@@ -66,6 +66,8 @@ export { PageBannerImageAndMenu } from './components/page-banner-image-and-menu/
|
|
|
66
66
|
export { GoogleAnalytics } from './components/google-analytics/config.js';
|
|
67
67
|
export { GoogleTag } from './components/google-tag/config.js';
|
|
68
68
|
export { cookiesPopup } from './components/cookies-popup/config.js';
|
|
69
|
+
export { infoTable } from './components/info-table/config.js';
|
|
70
|
+
export { faqComponent } from './components/faq-component/config.js';
|
|
69
71
|
|
|
70
72
|
// export { liqPayComponent } from './components/liqpay-component/config.js';
|
|
71
73
|
// export { htmlTextFromEditorJs } from './components/html-text-from-editor-js/config.js';
|