@akinon/next 1.13.0 → 1.14.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 (133) hide show
  1. package/.editorconfig +7 -0
  2. package/.eslintrc.js +40 -40
  3. package/.prettierrc +13 -13
  4. package/CHANGELOG.md +19 -0
  5. package/api/auth.ts +231 -231
  6. package/api/cache.ts +44 -44
  7. package/api/client.ts +174 -174
  8. package/api/logout.ts +42 -42
  9. package/assets/styles/index.scss +28 -28
  10. package/bin/pz-check-dependencies.js +98 -98
  11. package/bin/pz-install-plugins.js +33 -33
  12. package/bin/pz-install-theme.js +58 -58
  13. package/bin/pz-postbuild.js +1 -1
  14. package/bin/pz-postdev.js +1 -1
  15. package/bin/pz-postinstall.js +6 -6
  16. package/bin/pz-poststart.js +1 -1
  17. package/bin/pz-prebuild.js +4 -4
  18. package/bin/pz-predev.js +4 -4
  19. package/bin/pz-prestart.js +1 -1
  20. package/bin/run-script.js +44 -44
  21. package/components/accordion.tsx +52 -0
  22. package/components/button.tsx +46 -0
  23. package/components/client-root.tsx +19 -19
  24. package/components/icon.tsx +18 -18
  25. package/components/image.tsx +133 -133
  26. package/components/index.ts +17 -1
  27. package/components/input.tsx +110 -0
  28. package/components/lazy-component.tsx +33 -33
  29. package/components/loader-spinner.tsx +23 -23
  30. package/components/mobile-app-toggler.tsx +26 -26
  31. package/components/oauth-login.tsx +24 -24
  32. package/components/plugin-module.tsx +11 -8
  33. package/components/price.tsx +55 -0
  34. package/components/pz-providers.tsx +24 -24
  35. package/components/pz-root.tsx +21 -21
  36. package/components/radio.tsx +18 -18
  37. package/components/react-portal.tsx +45 -45
  38. package/components/redirect-three-d/content/index.tsx +74 -74
  39. package/components/redirect-three-d/index.tsx +17 -17
  40. package/components/selected-payment-option-view.tsx +7 -0
  41. package/components/trans.tsx +39 -39
  42. package/data/client/account.ts +208 -208
  43. package/data/client/address.ts +107 -107
  44. package/data/client/api.ts +85 -84
  45. package/data/client/b2b.ts +106 -106
  46. package/data/client/basket.ts +82 -82
  47. package/data/client/checkout.ts +516 -479
  48. package/data/client/misc.ts +101 -101
  49. package/data/client/product.ts +89 -89
  50. package/data/client/user.ts +99 -99
  51. package/data/client/wishlist.ts +118 -88
  52. package/data/server/category.ts +132 -128
  53. package/data/server/flatpage.ts +21 -21
  54. package/data/server/form.ts +22 -22
  55. package/data/server/index.ts +10 -10
  56. package/data/server/landingpage.ts +24 -24
  57. package/data/server/list.ts +67 -62
  58. package/data/server/menu.ts +35 -35
  59. package/data/server/product.ts +86 -86
  60. package/data/server/seo.ts +48 -48
  61. package/data/server/special-page.ts +47 -47
  62. package/data/server/widget.ts +27 -27
  63. package/data/urls.ts +221 -210
  64. package/hocs/client/index.ts +1 -1
  65. package/hocs/client/with-segment-defaults.tsx +25 -25
  66. package/hocs/server/index.ts +1 -1
  67. package/hocs/server/with-segment-defaults.tsx +85 -85
  68. package/hooks/index.ts +10 -10
  69. package/hooks/use-captcha.tsx +76 -76
  70. package/hooks/use-common-product-attributes.ts +36 -36
  71. package/hooks/use-debounce.ts +20 -20
  72. package/hooks/use-localization.ts +78 -78
  73. package/hooks/use-media-query.ts +36 -36
  74. package/hooks/use-mobile-iframe-handler.ts +23 -23
  75. package/hooks/use-on-click-outside.tsx +28 -28
  76. package/hooks/use-payment-options.ts +12 -16
  77. package/hooks/use-router.ts +45 -45
  78. package/hooks/use-translation.ts +14 -14
  79. package/lib/cache.ts +215 -215
  80. package/localization/index.ts +5 -5
  81. package/localization/provider.tsx +58 -58
  82. package/middlewares/currency.ts +100 -100
  83. package/middlewares/default.ts +256 -256
  84. package/middlewares/index.ts +29 -29
  85. package/middlewares/locale.ts +68 -68
  86. package/middlewares/oauth-login.ts +79 -79
  87. package/middlewares/pretty-url.ts +104 -104
  88. package/middlewares/redirection-payment.ts +160 -160
  89. package/middlewares/three-d-redirection.ts +159 -159
  90. package/middlewares/url-redirection.ts +65 -65
  91. package/package.json +2 -2
  92. package/plugins.js +2 -1
  93. package/redux/hooks.ts +7 -7
  94. package/redux/middlewares/checkout.ts +265 -260
  95. package/redux/middlewares/index.ts +50 -50
  96. package/redux/reducers/checkout.ts +184 -171
  97. package/redux/reducers/config.ts +28 -28
  98. package/redux/reducers/header.ts +59 -59
  99. package/redux/reducers/index.ts +14 -14
  100. package/redux/reducers/root.ts +61 -61
  101. package/sentry/index.ts +27 -27
  102. package/tailwind/rtl.js +137 -137
  103. package/types/commerce/account.ts +64 -64
  104. package/types/commerce/address.ts +94 -94
  105. package/types/commerce/b2b.ts +117 -117
  106. package/types/commerce/basket.ts +43 -43
  107. package/types/commerce/category.ts +114 -114
  108. package/types/commerce/checkout.ts +143 -136
  109. package/types/commerce/flatpage.ts +7 -7
  110. package/types/commerce/form.ts +66 -66
  111. package/types/commerce/index.ts +12 -12
  112. package/types/commerce/landingpage.ts +7 -7
  113. package/types/commerce/misc.ts +127 -127
  114. package/types/commerce/order.ts +119 -119
  115. package/types/commerce/product.ts +109 -109
  116. package/types/commerce/widget.ts +28 -28
  117. package/types/gtm.ts +16 -16
  118. package/types/index.ts +274 -237
  119. package/types/metadata.ts +7 -7
  120. package/types/next-auth.d.ts +24 -24
  121. package/utils/app-fetch.ts +69 -69
  122. package/utils/deep-merge.js +24 -24
  123. package/utils/generate-commerce-search-params.ts +22 -22
  124. package/utils/get-currency.ts +29 -29
  125. package/utils/image-loader.ts +31 -31
  126. package/utils/index.ts +150 -150
  127. package/utils/localization.ts +29 -29
  128. package/utils/log.ts +138 -138
  129. package/utils/menu-generator.ts +27 -27
  130. package/utils/mobile-3d-iframe.ts +77 -77
  131. package/utils/server-translation.ts +57 -57
  132. package/utils/server-variables.ts +9 -9
  133. package/with-pz-config.js +94 -94
package/api/cache.ts CHANGED
@@ -1,44 +1,44 @@
1
- import { Cache } from '../lib/cache';
2
- import { NextResponse } from 'next/server';
3
- import logger from '@akinon/next/utils/log';
4
-
5
- export async function POST(...args) {
6
- return handleRequest(...args);
7
- }
8
-
9
- export async function PUT(...args) {
10
- return handleRequest(...args);
11
- }
12
-
13
- async function handleRequest(...args) {
14
- const [req] = args as [req: Request];
15
-
16
- if (
17
- !req.headers.get('authorization') ||
18
- req.headers.get('authorization') !== process.env.CACHE_SECRET
19
- ) {
20
- return NextResponse.next({ status: 403 });
21
- }
22
-
23
- const formData = await req.formData();
24
- const body = {} as { key: string; value?: string; expire?: number };
25
-
26
- formData.forEach((value, key) => {
27
- body[key] = value;
28
- });
29
-
30
- const { key, value, expire } = body;
31
- let response: string | boolean;
32
-
33
- try {
34
- if (req.method === 'POST') {
35
- response = await Cache.get(key);
36
- } else if (req.method === 'PUT') {
37
- response = await Cache.set(key, value, expire);
38
- }
39
- } catch (error) {
40
- logger.error(error);
41
- }
42
-
43
- return NextResponse.json(response);
44
- }
1
+ import { Cache } from '../lib/cache';
2
+ import { NextResponse } from 'next/server';
3
+ import logger from '@akinon/next/utils/log';
4
+
5
+ export async function POST(...args) {
6
+ return handleRequest(...args);
7
+ }
8
+
9
+ export async function PUT(...args) {
10
+ return handleRequest(...args);
11
+ }
12
+
13
+ async function handleRequest(...args) {
14
+ const [req] = args as [req: Request];
15
+
16
+ if (
17
+ !req.headers.get('authorization') ||
18
+ req.headers.get('authorization') !== process.env.CACHE_SECRET
19
+ ) {
20
+ return NextResponse.next({ status: 403 });
21
+ }
22
+
23
+ const formData = await req.formData();
24
+ const body = {} as { key: string; value?: string; expire?: number };
25
+
26
+ formData.forEach((value, key) => {
27
+ body[key] = value;
28
+ });
29
+
30
+ const { key, value, expire } = body;
31
+ let response: string | boolean;
32
+
33
+ try {
34
+ if (req.method === 'POST') {
35
+ response = await Cache.get(key);
36
+ } else if (req.method === 'PUT') {
37
+ response = await Cache.set(key, value, expire);
38
+ }
39
+ } catch (error) {
40
+ logger.error(error);
41
+ }
42
+
43
+ return NextResponse.json(response);
44
+ }
package/api/client.ts CHANGED
@@ -1,174 +1,174 @@
1
- import { ClientRequestOptions } from '../types';
2
- import { NextResponse } from 'next/server';
3
- import settings from 'settings';
4
- import logger from '../utils/log';
5
-
6
- interface RouteParams {
7
- params: {
8
- slug: string[];
9
- };
10
- }
11
-
12
- async function proxyRequest(...args) {
13
- const [req, { params }] = args as [req: Request, params: RouteParams];
14
- const { searchParams } = new URL(req.url);
15
- const commerceUrl = settings.commerceUrl;
16
-
17
- if (commerceUrl === 'default') {
18
- return NextResponse.json(
19
- { error: 'Commerce URL not found' },
20
- { status: 404 }
21
- );
22
- }
23
-
24
- const options: ClientRequestOptions = {
25
- useTrailingSlash: true,
26
- useFormData: false,
27
- contentType: null,
28
- accept: 'application/json',
29
- responseType: 'json'
30
- };
31
-
32
- const slug = `${params.slug.join('/')}/`;
33
- const options_ = JSON.parse(
34
- decodeURIComponent((searchParams.get('options') as string) ?? '{}')
35
- );
36
- const urlSearchParams = new URLSearchParams();
37
-
38
- Object.assign(options, options_);
39
-
40
- Array.from(searchParams.keys())
41
- .filter((key) => !['slug', 'options'].includes(key))
42
- .forEach((key) => {
43
- urlSearchParams.append(key, `${searchParams.get(key)}`);
44
- });
45
-
46
- const extraHeaders = Object.fromEntries(req.headers.entries());
47
-
48
- [
49
- 'x-forwarded-host',
50
- 'x-forwarded-for',
51
- 'x-forwarded-proto',
52
- 'x-forwarded-port',
53
- 'origin',
54
- 'host',
55
- 'referer',
56
- 'accept',
57
- 'content-length',
58
- 'content-type'
59
- ].forEach((header) => delete extraHeaders[header]);
60
-
61
- const fetchOptions = {
62
- method: req.method,
63
- headers: {
64
- ...extraHeaders,
65
- 'X-Requested-With': 'XMLHttpRequest',
66
- Referer: commerceUrl,
67
- Accept: options.accept
68
- }
69
- } as RequestInit;
70
-
71
- if (options.contentType) {
72
- fetchOptions.headers['Content-Type'] = options.contentType;
73
- }
74
-
75
- if (req.method !== 'GET') {
76
- const formData = new URLSearchParams();
77
- let body = {};
78
-
79
- try {
80
- body = await req.json();
81
- } catch (error) {
82
- logger.error(
83
- `Client Proxy Request - Error while parsing request body to JSON`,
84
- {
85
- url: req.url,
86
- error
87
- }
88
- );
89
- }
90
-
91
- Object.keys(body ?? {}).forEach((key) => {
92
- if (body[key]) {
93
- formData.append(key, body[key]);
94
- }
95
- });
96
-
97
- fetchOptions.body = !options.useFormData ? JSON.stringify(body) : formData;
98
- }
99
-
100
- let url = `${commerceUrl}/${slug.replace(/,/g, '/')}`;
101
-
102
- if (!options.useTrailingSlash) {
103
- url = url.replace(/\/$/, '');
104
- }
105
-
106
- if (urlSearchParams.toString().length) {
107
- url += `?${urlSearchParams.toString()}`;
108
- }
109
-
110
- try {
111
- const request = await fetch(url, fetchOptions);
112
- let response = {} as any;
113
-
114
- try {
115
- response = await (options.responseType === 'text'
116
- ? request.text()
117
- : request.json());
118
- } catch (error) {
119
- logger.error(
120
- `Client Proxy Request - Error while parsing response body to ${options.responseType}`,
121
- {
122
- url,
123
- status: request.status,
124
- fetchOptions: JSON.stringify(fetchOptions),
125
- error
126
- }
127
- );
128
- }
129
-
130
- const setCookieHeader = request.headers.get('set-cookie');
131
- const responseHeaders: any = {};
132
-
133
- if (setCookieHeader) {
134
- responseHeaders['set-cookie'] = setCookieHeader;
135
- }
136
-
137
- const statusCode = new RegExp(/^20./).test(request.status.toString())
138
- ? 200
139
- : request.status;
140
-
141
- return NextResponse.json(
142
- options.responseType === 'text' ? { result: response } : response,
143
- { status: statusCode, headers: responseHeaders }
144
- );
145
- } catch (error) {
146
- logger.error('Client proxy request failed', error);
147
-
148
- return NextResponse.json({ error }, { status: 500 });
149
- }
150
- }
151
-
152
- export async function GET(...args) {
153
- return proxyRequest(...args);
154
- }
155
-
156
- export async function POST(...args) {
157
- return proxyRequest(...args);
158
- }
159
-
160
- export async function PUT(...args) {
161
- return proxyRequest(...args);
162
- }
163
-
164
- export async function PATCH(...args) {
165
- return proxyRequest(...args);
166
- }
167
-
168
- export async function DELETE(...args) {
169
- return proxyRequest(...args);
170
- }
171
-
172
- export async function HEAD(...args) {
173
- return proxyRequest(...args);
174
- }
1
+ import { ClientRequestOptions } from '../types';
2
+ import { NextResponse } from 'next/server';
3
+ import settings from 'settings';
4
+ import logger from '../utils/log';
5
+
6
+ interface RouteParams {
7
+ params: {
8
+ slug: string[];
9
+ };
10
+ }
11
+
12
+ async function proxyRequest(...args) {
13
+ const [req, { params }] = args as [req: Request, params: RouteParams];
14
+ const { searchParams } = new URL(req.url);
15
+ const commerceUrl = settings.commerceUrl;
16
+
17
+ if (commerceUrl === 'default') {
18
+ return NextResponse.json(
19
+ { error: 'Commerce URL not found' },
20
+ { status: 404 }
21
+ );
22
+ }
23
+
24
+ const options: ClientRequestOptions = {
25
+ useTrailingSlash: true,
26
+ useFormData: false,
27
+ contentType: null,
28
+ accept: 'application/json',
29
+ responseType: 'json'
30
+ };
31
+
32
+ const slug = `${params.slug.join('/')}/`;
33
+ const options_ = JSON.parse(
34
+ decodeURIComponent((searchParams.get('options') as string) ?? '{}')
35
+ );
36
+ const urlSearchParams = new URLSearchParams();
37
+
38
+ Object.assign(options, options_);
39
+
40
+ Array.from(searchParams.keys())
41
+ .filter((key) => !['slug', 'options'].includes(key))
42
+ .forEach((key) => {
43
+ urlSearchParams.append(key, `${searchParams.get(key)}`);
44
+ });
45
+
46
+ const extraHeaders = Object.fromEntries(req.headers.entries());
47
+
48
+ [
49
+ 'x-forwarded-host',
50
+ 'x-forwarded-for',
51
+ 'x-forwarded-proto',
52
+ 'x-forwarded-port',
53
+ 'origin',
54
+ 'host',
55
+ 'referer',
56
+ 'accept',
57
+ 'content-length',
58
+ 'content-type'
59
+ ].forEach((header) => delete extraHeaders[header]);
60
+
61
+ const fetchOptions = {
62
+ method: req.method,
63
+ headers: {
64
+ ...extraHeaders,
65
+ 'X-Requested-With': 'XMLHttpRequest',
66
+ Referer: commerceUrl,
67
+ Accept: options.accept
68
+ }
69
+ } as RequestInit;
70
+
71
+ if (options.contentType) {
72
+ fetchOptions.headers['Content-Type'] = options.contentType;
73
+ }
74
+
75
+ if (req.method !== 'GET') {
76
+ const formData = new URLSearchParams();
77
+ let body = {};
78
+
79
+ try {
80
+ body = await req.json();
81
+ } catch (error) {
82
+ logger.error(
83
+ `Client Proxy Request - Error while parsing request body to JSON`,
84
+ {
85
+ url: req.url,
86
+ error
87
+ }
88
+ );
89
+ }
90
+
91
+ Object.keys(body ?? {}).forEach((key) => {
92
+ if (body[key]) {
93
+ formData.append(key, body[key]);
94
+ }
95
+ });
96
+
97
+ fetchOptions.body = !options.useFormData ? JSON.stringify(body) : formData;
98
+ }
99
+
100
+ let url = `${commerceUrl}/${slug.replace(/,/g, '/')}`;
101
+
102
+ if (!options.useTrailingSlash) {
103
+ url = url.replace(/\/$/, '');
104
+ }
105
+
106
+ if (urlSearchParams.toString().length) {
107
+ url += `?${urlSearchParams.toString()}`;
108
+ }
109
+
110
+ try {
111
+ const request = await fetch(url, fetchOptions);
112
+ let response = {} as any;
113
+
114
+ try {
115
+ response = await (options.responseType === 'text'
116
+ ? request.text()
117
+ : request.json());
118
+ } catch (error) {
119
+ logger.error(
120
+ `Client Proxy Request - Error while parsing response body to ${options.responseType}`,
121
+ {
122
+ url,
123
+ status: request.status,
124
+ fetchOptions: JSON.stringify(fetchOptions),
125
+ error
126
+ }
127
+ );
128
+ }
129
+
130
+ const setCookieHeader = request.headers.get('set-cookie');
131
+ const responseHeaders: any = {};
132
+
133
+ if (setCookieHeader) {
134
+ responseHeaders['set-cookie'] = setCookieHeader;
135
+ }
136
+
137
+ const statusCode = new RegExp(/^20./).test(request.status.toString())
138
+ ? 200
139
+ : request.status;
140
+
141
+ return NextResponse.json(
142
+ options.responseType === 'text' ? { result: response } : response,
143
+ { status: statusCode, headers: responseHeaders }
144
+ );
145
+ } catch (error) {
146
+ logger.error('Client proxy request failed', error);
147
+
148
+ return NextResponse.json({ error }, { status: 500 });
149
+ }
150
+ }
151
+
152
+ export async function GET(...args) {
153
+ return proxyRequest(...args);
154
+ }
155
+
156
+ export async function POST(...args) {
157
+ return proxyRequest(...args);
158
+ }
159
+
160
+ export async function PUT(...args) {
161
+ return proxyRequest(...args);
162
+ }
163
+
164
+ export async function PATCH(...args) {
165
+ return proxyRequest(...args);
166
+ }
167
+
168
+ export async function DELETE(...args) {
169
+ return proxyRequest(...args);
170
+ }
171
+
172
+ export async function HEAD(...args) {
173
+ return proxyRequest(...args);
174
+ }
package/api/logout.ts CHANGED
@@ -1,42 +1,42 @@
1
- import { URLS } from '../data/urls';
2
- import { NextResponse } from 'next/server';
3
-
4
- export async function POST(req: Request) {
5
- const regexText1 = /name=['|"]csrfmiddlewaretoken['|"] value=['|"]\w+/gi;
6
- const regexText2 = /name=['|"]csrfmiddlewaretoken['|"] value=['|"]/gi;
7
- let sessionCookie;
8
-
9
- if (req.headers.get('osessionid')) {
10
- sessionCookie = `osessionid=${req.headers.get('osessionid')}`;
11
- }
12
-
13
- const requestLogoutStep1 = await fetch(URLS.user.logout, {
14
- method: 'POST',
15
- headers: {
16
- Cookie: `${sessionCookie}`
17
- }
18
- });
19
-
20
- const responseHtml = await requestLogoutStep1.text();
21
- const csrfTokenMatch = responseHtml.match(regexText1);
22
- const csrfToken = csrfTokenMatch?.[0].replace(regexText2, '') || '';
23
- const formData = new URLSearchParams();
24
-
25
- formData.append('csrfmiddlewaretoken', csrfToken);
26
-
27
- try {
28
- const requestLogoutStep2 = await fetch(URLS.user.logout, {
29
- method: 'POST',
30
- headers: {
31
- Cookie: `csrftoken=${csrfToken}; ${sessionCookie}`
32
- },
33
- body: formData
34
- });
35
-
36
- return NextResponse.json(requestLogoutStep2, {
37
- status: requestLogoutStep2.status
38
- });
39
- } catch (error) {
40
- return NextResponse.json(error, { status: 500 });
41
- }
42
- }
1
+ import { URLS } from '../data/urls';
2
+ import { NextResponse } from 'next/server';
3
+
4
+ export async function POST(req: Request) {
5
+ const regexText1 = /name=['|"]csrfmiddlewaretoken['|"] value=['|"]\w+/gi;
6
+ const regexText2 = /name=['|"]csrfmiddlewaretoken['|"] value=['|"]/gi;
7
+ let sessionCookie;
8
+
9
+ if (req.headers.get('osessionid')) {
10
+ sessionCookie = `osessionid=${req.headers.get('osessionid')}`;
11
+ }
12
+
13
+ const requestLogoutStep1 = await fetch(URLS.user.logout, {
14
+ method: 'POST',
15
+ headers: {
16
+ Cookie: `${sessionCookie}`
17
+ }
18
+ });
19
+
20
+ const responseHtml = await requestLogoutStep1.text();
21
+ const csrfTokenMatch = responseHtml.match(regexText1);
22
+ const csrfToken = csrfTokenMatch?.[0].replace(regexText2, '') || '';
23
+ const formData = new URLSearchParams();
24
+
25
+ formData.append('csrfmiddlewaretoken', csrfToken);
26
+
27
+ try {
28
+ const requestLogoutStep2 = await fetch(URLS.user.logout, {
29
+ method: 'POST',
30
+ headers: {
31
+ Cookie: `csrftoken=${csrfToken}; ${sessionCookie}`
32
+ },
33
+ body: formData
34
+ });
35
+
36
+ return NextResponse.json(requestLogoutStep2, {
37
+ status: requestLogoutStep2.status
38
+ });
39
+ } catch (error) {
40
+ return NextResponse.json(error, { status: 500 });
41
+ }
42
+ }
@@ -1,29 +1,29 @@
1
- .checkout-payment-iframe-wrapper {
2
- position: fixed;
3
- top: 0;
4
- left: 0;
5
- width: 100%;
6
- height: 100%;
7
- border: none;
8
- z-index: 1000;
9
- background-color: white;
10
-
11
- iframe {
12
- width: 100%;
13
- height: 100%;
14
- border: none;
15
- background-color: white;
16
- }
17
-
18
- .close-button {
19
- position: fixed;
20
- top: 16px;
21
- right: 16px;
22
- width: 32px;
23
- height: 32px;
24
- display: flex;
25
- align-items: center;
26
- justify-content: center;
27
- z-index: 1001;
28
- }
1
+ .checkout-payment-iframe-wrapper {
2
+ position: fixed;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ border: none;
8
+ z-index: 1000;
9
+ background-color: white;
10
+
11
+ iframe {
12
+ width: 100%;
13
+ height: 100%;
14
+ border: none;
15
+ background-color: white;
16
+ }
17
+
18
+ .close-button {
19
+ position: fixed;
20
+ top: 16px;
21
+ right: 16px;
22
+ width: 32px;
23
+ height: 32px;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ z-index: 1001;
28
+ }
29
29
  }