@redneckz/wildless-cms-uni-blocks 0.2.54 → 0.2.57

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 (97) hide show
  1. package/dist/ContentPage.d.ts +4 -1
  2. package/dist/ContentPage.js +3 -4
  3. package/dist/ContentPage.js.map +1 -1
  4. package/dist/ContentPageContext.d.ts +2 -0
  5. package/dist/Footer/Footer.mobile.d.ts +5 -0
  6. package/dist/Footer/Footer.mobile.js +7 -0
  7. package/dist/Footer/Footer.mobile.js.map +1 -0
  8. package/dist/Header/Header.js +2 -2
  9. package/dist/Header/Header.js.map +1 -1
  10. package/dist/Header/HeaderContent.d.ts +1 -1
  11. package/dist/Header/HeaderSecondaryMenu.d.ts +5 -2
  12. package/dist/Header/HeaderSecondaryMenu.js +3 -2
  13. package/dist/Header/HeaderSecondaryMenu.js.map +1 -1
  14. package/dist/MobileBlocks.d.ts +13 -0
  15. package/dist/MobileBlocks.js +27 -0
  16. package/dist/MobileBlocks.js.map +1 -0
  17. package/dist/api/DaDataAPI.d.ts +3 -0
  18. package/dist/api/DaDataAPI.js +33 -0
  19. package/dist/api/DaDataAPI.js.map +1 -0
  20. package/dist/api/LikeAPI.d.ts +1 -1
  21. package/dist/api/LikeAPI.js +2 -2
  22. package/dist/api/LikeAPI.js.map +1 -1
  23. package/dist/content-page-repository/ContentPageRepository.d.ts +1 -0
  24. package/dist/content-page-repository/ContentPageRepository.js +6 -0
  25. package/dist/content-page-repository/ContentPageRepository.js.map +1 -1
  26. package/dist/content-page-repository/index.d.ts +1 -0
  27. package/dist/content-page-repository/index.js +3 -1
  28. package/dist/content-page-repository/index.js.map +1 -1
  29. package/dist/content-page-repository/toMobilePage.d.ts +2 -0
  30. package/dist/content-page-repository/toMobilePage.js +23 -0
  31. package/dist/content-page-repository/toMobilePage.js.map +1 -0
  32. package/dist/index.d.ts +5 -2
  33. package/dist/index.js +7 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/types.d.ts +14 -0
  36. package/dist/utils/getCurrentPosition.d.ts +1 -0
  37. package/dist/utils/getCurrentPosition.js +5 -0
  38. package/dist/utils/getCurrentPosition.js.map +1 -0
  39. package/lib/ContentPage.d.ts +4 -1
  40. package/lib/ContentPage.js +3 -4
  41. package/lib/ContentPage.js.map +1 -1
  42. package/lib/ContentPageContext.d.ts +2 -0
  43. package/lib/Footer/Footer.mobile.d.ts +5 -0
  44. package/lib/Footer/Footer.mobile.js +5 -0
  45. package/lib/Footer/Footer.mobile.js.map +1 -0
  46. package/lib/Header/Header.js +2 -2
  47. package/lib/Header/Header.js.map +1 -1
  48. package/lib/Header/HeaderContent.d.ts +1 -1
  49. package/lib/Header/HeaderSecondaryMenu.d.ts +5 -2
  50. package/lib/Header/HeaderSecondaryMenu.js +3 -2
  51. package/lib/Header/HeaderSecondaryMenu.js.map +1 -1
  52. package/lib/MobileBlocks.d.ts +13 -0
  53. package/lib/MobileBlocks.js +25 -0
  54. package/lib/MobileBlocks.js.map +1 -0
  55. package/lib/api/DaDataAPI.d.ts +3 -0
  56. package/lib/api/DaDataAPI.js +30 -0
  57. package/lib/api/DaDataAPI.js.map +1 -0
  58. package/lib/api/LikeAPI.d.ts +1 -1
  59. package/lib/api/LikeAPI.js +2 -2
  60. package/lib/api/LikeAPI.js.map +1 -1
  61. package/lib/common.css +1 -1
  62. package/lib/content-page-repository/ContentPageRepository.d.ts +1 -0
  63. package/lib/content-page-repository/ContentPageRepository.js +6 -0
  64. package/lib/content-page-repository/ContentPageRepository.js.map +1 -1
  65. package/lib/content-page-repository/index.d.ts +1 -0
  66. package/lib/content-page-repository/index.js +1 -0
  67. package/lib/content-page-repository/index.js.map +1 -1
  68. package/lib/content-page-repository/toMobilePage.d.ts +2 -0
  69. package/lib/content-page-repository/toMobilePage.js +20 -0
  70. package/lib/content-page-repository/toMobilePage.js.map +1 -0
  71. package/lib/index.d.ts +5 -2
  72. package/lib/index.js +3 -1
  73. package/lib/index.js.map +1 -1
  74. package/lib/types.d.ts +14 -0
  75. package/lib/utils/getCurrentPosition.d.ts +1 -0
  76. package/lib/utils/getCurrentPosition.js +2 -0
  77. package/lib/utils/getCurrentPosition.js.map +1 -0
  78. package/package.json +7 -4
  79. package/src/ContentPage.fixture.tsx +23 -3
  80. package/src/ContentPage.page.json +43 -1
  81. package/src/ContentPage.tsx +10 -5
  82. package/src/ContentPageContext.tsx +3 -0
  83. package/src/Footer/Footer.mobile.tsx +12 -0
  84. package/src/Header/Header.fixture.tsx +1 -1
  85. package/src/Header/Header.tsx +6 -2
  86. package/src/Header/HeaderContent.ts +1 -1
  87. package/src/Header/HeaderSecondaryMenu.tsx +48 -34
  88. package/src/MobileBlocks.ts +25 -0
  89. package/src/api/DaDataAPI.ts +34 -0
  90. package/src/api/LikeAPI.ts +12 -9
  91. package/src/content-page-repository/ContentPageRepository.ts +7 -0
  92. package/src/content-page-repository/index.ts +1 -0
  93. package/src/content-page-repository/toMobilePage.ts +21 -0
  94. package/src/index.ts +14 -2
  95. package/src/setup-fixture.ts +15 -0
  96. package/src/types.ts +17 -0
  97. package/src/utils/getCurrentPosition.ts +4 -0
@@ -192,6 +192,9 @@
192
192
  "height": 220
193
193
  }
194
194
  }
195
+ },
196
+ "mobile": {
197
+ "style": ["col-span-12"]
195
198
  }
196
199
  },
197
200
  {
@@ -209,6 +212,9 @@
209
212
  }
210
213
  ],
211
214
  "promo": true
215
+ },
216
+ "mobile": {
217
+ "style": ["col-span-12"]
212
218
  }
213
219
  },
214
220
  {
@@ -233,6 +239,9 @@
233
239
  "height": 220
234
240
  }
235
241
  }
242
+ },
243
+ "mobile": {
244
+ "style": ["col-span-12"]
236
245
  }
237
246
  },
238
247
  {
@@ -257,6 +266,9 @@
257
266
  "height": 220
258
267
  }
259
268
  }
269
+ },
270
+ "mobile": {
271
+ "style": ["col-span-12"]
260
272
  }
261
273
  },
262
274
  {
@@ -301,6 +313,9 @@
301
313
  "version": "secondary"
302
314
  }
303
315
  ]
316
+ },
317
+ "mobile": {
318
+ "style": ["col-span-12"]
304
319
  }
305
320
  },
306
321
  {
@@ -316,6 +331,9 @@
316
331
  "version": "secondary"
317
332
  }
318
333
  ]
334
+ },
335
+ "mobile": {
336
+ "style": ["col-span-12"]
319
337
  }
320
338
  },
321
339
  {
@@ -335,6 +353,9 @@
335
353
  "version": "secondary"
336
354
  }
337
355
  ]
356
+ },
357
+ "mobile": {
358
+ "style": ["col-span-12"]
338
359
  }
339
360
  },
340
361
  {
@@ -351,11 +372,17 @@
351
372
  "version": "secondary"
352
373
  }
353
374
  ]
375
+ },
376
+ "mobile": {
377
+ "hidden": true
354
378
  }
355
379
  },
356
380
  {
357
381
  "type": "ExchangeRateTile",
358
- "style": ["col-span-4"]
382
+ "style": ["col-span-4"],
383
+ "mobile": {
384
+ "style": ["col-span-12"]
385
+ }
359
386
  },
360
387
  {
361
388
  "type": "MobileAppTile",
@@ -365,6 +392,9 @@
365
392
  "href": "https://rshbnaturaldbo.onelink.me/qhkF/f182074f?af_qr=true",
366
393
  "src": "data:image/png;base64,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"
367
394
  }
395
+ },
396
+ "mobile": {
397
+ "style": ["col-span-12"]
368
398
  }
369
399
  },
370
400
  {
@@ -471,6 +501,9 @@
471
501
  "height": 220
472
502
  }
473
503
  }
504
+ },
505
+ "mobile": {
506
+ "style": ["col-span-12"]
474
507
  }
475
508
  },
476
509
  {
@@ -510,6 +543,9 @@
510
543
  "height": 220
511
544
  }
512
545
  }
546
+ },
547
+ "mobile": {
548
+ "style": ["col-span-12"]
513
549
  }
514
550
  },
515
551
  {
@@ -549,6 +585,9 @@
549
585
  "height": 220
550
586
  }
551
587
  }
588
+ },
589
+ "mobile": {
590
+ "style": ["col-span-12"]
552
591
  }
553
592
  },
554
593
  {
@@ -580,6 +619,9 @@
580
619
  "version": "secondary"
581
620
  }
582
621
  ]
622
+ },
623
+ "mobile": {
624
+ "style": ["col-span-12"]
583
625
  }
584
626
  },
585
627
  {
@@ -1,5 +1,5 @@
1
- import { JSX } from '@redneckz/uni-jsx';
2
- import { Blocks } from './Blocks'; // TODO Lazy load
1
+ import { JSX, PropsWithChildren } from '@redneckz/uni-jsx';
2
+ import type { BlockContent } from './Blocks';
3
3
  import { LikeControl } from './LikeControl';
4
4
  import { Placeholder } from './Placeholder';
5
5
  import type { BlockDef, ContentPageDef, UniBlockProps } from './types';
@@ -16,6 +16,10 @@ export type BlockDecorator<VNode = any> = (
16
16
  ) => any;
17
17
 
18
18
  export interface ContentPageProps extends UniBlockProps {
19
+ blocksRegistry: Record<
20
+ string,
21
+ (props: PropsWithChildren<UniBlockProps & BlockContent, any>, context?: any) => any
22
+ >;
19
23
  data: ContentPageDef;
20
24
  blockDecorator?: BlockDecorator;
21
25
  }
@@ -26,8 +30,9 @@ const defaultBlockDecorator: BlockDecorator = ({ blockClassName, block, render }
26
30
  export const ContentPage = JSX<ContentPageProps>(
27
31
  ({
28
32
  className,
29
- data: { style: pageStyle, blocks, likeControl, colorPalette = 'pc' },
30
33
  context,
34
+ blocksRegistry,
35
+ data: { style: pageStyle, blocks, likeControl, colorPalette = 'pc' },
31
36
  blockDecorator = defaultBlockDecorator,
32
37
  }) => {
33
38
  return (
@@ -48,11 +53,11 @@ export const ContentPage = JSX<ContentPageProps>(
48
53
 
49
54
  function renderBlock(block: BlockDef, i: number) {
50
55
  const { type } = block;
51
- if (!(type in Blocks)) {
56
+ if (!(type in blocksRegistry)) {
52
57
  console.warn(`No block with "${type}" is registered`);
53
58
  }
54
59
 
55
- const BlockComponent = Blocks[type as keyof typeof Blocks] || Placeholder;
60
+ const BlockComponent = blocksRegistry[type] || Placeholder;
56
61
  return blockDecorator(
57
62
  {
58
63
  blockClassName: style2className(block.style),
@@ -24,10 +24,13 @@ export type AsyncDataHook = <Data, Error = any>(
24
24
  fetcher: () => Promise<Data>,
25
25
  ) => { data?: Data; error?: Error };
26
26
 
27
+ export type GeolocationHook = (defaultLocation: string) => [string, () => void];
28
+
27
29
  export interface ContentPageContext {
28
30
  useRouter: () => Router;
29
31
  useState: <State>(initialState: State) => [State, (_: State) => void];
30
32
  useAsyncData: AsyncDataHook;
33
+ useGeolocation: GeolocationHook;
31
34
  useLikeService: () => LikeService;
32
35
  useSearch: () => Search;
33
36
  handlerDecorator?: HandlerDecorator;
@@ -0,0 +1,12 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { UniBlockProps } from '../types';
3
+ import type { FooterContent } from './Footer';
4
+ import { TextInformation } from './TextInformation';
5
+
6
+ export interface FooterProps extends FooterContent, UniBlockProps {}
7
+
8
+ export const Footer = JSX<FooterProps>(({ className, context }) => (
9
+ <footer className={`${className} px-9 py-2 bg-white rounded-bl-3xl rounded-br-3xl`}>
10
+ <TextInformation context={context} />
11
+ </footer>
12
+ ));
@@ -4,7 +4,7 @@ import { Header } from './Header';
4
4
  export default (
5
5
  <Header
6
6
  context={context}
7
- location="Москва"
7
+ defaultLocation="Москва"
8
8
  topItems={[
9
9
  {
10
10
  href: 'https://rshb.ru/',
@@ -13,7 +13,7 @@ import { isTopItemActive } from './isTopItemActive';
13
13
 
14
14
  export interface HeaderProps extends HeaderContent, UniBlockProps {}
15
15
 
16
- export const Header = JSX<HeaderProps>(({ className, location, context, topItems }) => {
16
+ export const Header = JSX<HeaderProps>(({ className, defaultLocation, context, topItems }) => {
17
17
  const router = context.useRouter();
18
18
  const sitemap = useSitemap(context.useAsyncData);
19
19
  const { handlerDecorator } = context;
@@ -46,7 +46,11 @@ export const Header = JSX<HeaderProps>(({ className, location, context, topItems
46
46
  <div className="flex items-center">
47
47
  <Logo className="mr-8" />
48
48
  {topMenu}
49
- <HeaderSecondaryMenu location={location} className="ml-auto" />
49
+ <HeaderSecondaryMenu
50
+ context={context}
51
+ className="ml-auto"
52
+ defaultLocation={defaultLocation}
53
+ />
50
54
  </div>
51
55
  <div className="mt-5 h-[1px] bg-main-divider" />
52
56
  <nav className="mt-5">{subMenu}</nav>
@@ -1,6 +1,6 @@
1
1
  import type { TopMenuItem } from '../types';
2
2
 
3
3
  export interface HeaderContent {
4
- location?: string;
4
+ defaultLocation?: string;
5
5
  topItems?: TopMenuItem[];
6
6
  }
@@ -2,41 +2,55 @@ import { JSX } from '@redneckz/uni-jsx';
2
2
  import { GridIcon, LoupeIcon, ProfileIcon } from '../Icons/index';
3
3
  import { TopItem } from '../ui-kit/TopItem';
4
4
  import { HeaderSecondaryMenuButton } from './HeaderSecondaryMenuButton';
5
+ import type { UniBlockProps } from '../types';
5
6
 
6
- interface HeaderSecondaryMenuProps {
7
- location?: string;
7
+ interface HeaderSecondaryMenuContent {
8
+ defaultLocation?: string;
8
9
  className?: string;
9
10
  }
10
11
 
11
- export const HeaderSecondaryMenu = JSX<HeaderSecondaryMenuProps>(({ location, className }) => {
12
- return (
13
- <div className={`flex items-center ${className || ''}`}>
14
- <TopItem className="mr-5" flat={true} href="#" text={location} ariaLabel="Местоположение" />
15
- <TopItem
16
- className="mr-7"
17
- flat={true}
18
- href="#"
19
- text="Офисы и банкоматы"
20
- ariaLabel="Список всех доступных офисов и банкоматов"
21
- />
22
- <HeaderSecondaryMenuButton
23
- className="mr-5 text-primary-text hover:text-primary-main"
24
- ariaLabel="Поиск по сайту"
25
- >
26
- {LoupeIcon({ 'aria-hidden': true })}
27
- </HeaderSecondaryMenuButton>
28
- <HeaderSecondaryMenuButton
29
- className="mr-5 text-primary-text hover:text-primary-main"
30
- ariaLabel="Профиль"
31
- >
32
- {ProfileIcon({ 'aria-hidden': true })}
33
- </HeaderSecondaryMenuButton>
34
- <HeaderSecondaryMenuButton
35
- className="mr-5 text-secondary-light hover:text-secondary-active min-w-[32px] min-h-[32px]"
36
- ariaLabel="Дополнительные ссылки"
37
- >
38
- {GridIcon({ 'aria-hidden': true })}
39
- </HeaderSecondaryMenuButton>
40
- </div>
41
- );
42
- });
12
+ export interface HeaderSecondaryMenuProps extends HeaderSecondaryMenuContent, UniBlockProps {}
13
+
14
+ export const HeaderSecondaryMenu = JSX<HeaderSecondaryMenuProps>(
15
+ ({ context, className, defaultLocation = '' }) => {
16
+ const [city, getCity] = context.useGeolocation(defaultLocation);
17
+
18
+ return (
19
+ <div className={`flex items-center ${className || ''}`}>
20
+ <TopItem
21
+ className="mr-5"
22
+ flat={true}
23
+ href="#"
24
+ text={city}
25
+ ariaLabel="Местоположение"
26
+ onClick={getCity}
27
+ />
28
+ <TopItem
29
+ className="mr-7"
30
+ flat={true}
31
+ href="#"
32
+ text="Офисы и банкоматы"
33
+ ariaLabel="Список всех доступных офисов и банкоматов"
34
+ />
35
+ <HeaderSecondaryMenuButton
36
+ className="mr-5 text-primary-text hover:text-primary-main"
37
+ ariaLabel="Поиск по сайту"
38
+ >
39
+ {LoupeIcon({ 'aria-hidden': true })}
40
+ </HeaderSecondaryMenuButton>
41
+ <HeaderSecondaryMenuButton
42
+ className="mr-5 text-primary-text hover:text-primary-main"
43
+ ariaLabel="Профиль"
44
+ >
45
+ {ProfileIcon({ 'aria-hidden': true })}
46
+ </HeaderSecondaryMenuButton>
47
+ <HeaderSecondaryMenuButton
48
+ className="mr-5 text-secondary-light hover:text-secondary-active min-w-[32px] min-h-[32px]"
49
+ ariaLabel="Дополнительные ссылки"
50
+ >
51
+ {GridIcon({ 'aria-hidden': true })}
52
+ </HeaderSecondaryMenuButton>
53
+ </div>
54
+ );
55
+ },
56
+ );
@@ -0,0 +1,25 @@
1
+ import { BenefitsBlock } from './BenefitsBlock';
2
+ import { ExchangeRateTile } from './ExchangeRateTile';
3
+ import { Footer } from './Footer/Footer.mobile';
4
+ import { Header } from './Header/index';
5
+ import { MobileAppTile } from './MobileAppTile';
6
+ import { Placeholder } from './Placeholder';
7
+ import { ProductBlock } from './ProductBlock';
8
+ import { ProductGallery } from './ProductGallery';
9
+ import { ProductTile } from './ProductTile';
10
+ import { StepsBlock } from './StepsBlock';
11
+ import { Tile } from './Tile';
12
+
13
+ export const MobileBlocks = {
14
+ Header,
15
+ Footer,
16
+ Placeholder,
17
+ Tile,
18
+ ProductTile,
19
+ ProductBlock,
20
+ StepsBlock,
21
+ BenefitsBlock,
22
+ ProductGallery,
23
+ ExchangeRateTile,
24
+ MobileAppTile,
25
+ };
@@ -0,0 +1,34 @@
1
+ import { getCurrentPosition } from '../utils/getCurrentPosition';
2
+
3
+ import type { DaDataResult } from '../types';
4
+
5
+ export function DaDataAPI(baseURL = '') {
6
+ async function getFetcherAddress() {
7
+ if (!('geolocation' in navigator)) {
8
+ return null;
9
+ }
10
+
11
+ try {
12
+ const coords = await getCurrentPosition();
13
+ const response = await fetch(`${baseURL}/geolocate`, {
14
+ method: 'POST',
15
+ mode: 'cors',
16
+ body: JSON.stringify({
17
+ lat: coords.latitude,
18
+ lon: coords.longitude,
19
+ count: 1,
20
+ }),
21
+ });
22
+
23
+ const data = (await response.json()) as DaDataResult;
24
+ return data?.suggestions?.[0]?.data?.city;
25
+ } catch (e) {
26
+ console.error(e);
27
+ return null;
28
+ }
29
+ }
30
+
31
+ return {
32
+ getFetcherAddress,
33
+ };
34
+ }
@@ -10,7 +10,7 @@ export interface LikeData {
10
10
  const AUTH_PREFIX = 'guest';
11
11
  const STORAGE_KEY = 'likesToken';
12
12
 
13
- export function LikeAPI(projectId: string, baseURL: string) {
13
+ export function LikeAPI(projectId: string, baseURL = '') {
14
14
  async function getLikeCount(...nodeIds: string[]): Promise<LikeData[]> {
15
15
  if (!nodeIds.length) {
16
16
  return [];
@@ -19,14 +19,17 @@ export function LikeAPI(projectId: string, baseURL: string) {
19
19
  const { token: Authorization } = await auth();
20
20
 
21
21
  try {
22
- const response = await fetch(`/assist/v1/public/projects/${projectId}/nodes/likes`, {
23
- method: 'POST',
24
- mode: 'cors',
25
- headers: { 'Content-Type': 'application/json', Authorization },
26
- body: JSON.stringify({
27
- node_ids: nodeIds,
28
- }),
29
- });
22
+ const response = await fetch(
23
+ `${baseURL}/assist/v1/public/projects/${projectId}/nodes/likes`,
24
+ {
25
+ method: 'POST',
26
+ mode: 'cors',
27
+ headers: { 'Content-Type': 'application/json', Authorization },
28
+ body: JSON.stringify({
29
+ node_ids: nodeIds,
30
+ }),
31
+ },
32
+ );
30
33
 
31
34
  const { likes } = await response.json();
32
35
 
@@ -1,6 +1,7 @@
1
1
  import glob from 'glob';
2
2
  import util from 'util';
3
3
  import type { ContentPageDef } from '../types';
4
+ import { toMobilePage } from './toMobilePage';
4
5
  import type { TransformationOptions } from './TransformationOptions';
5
6
  import { transformContentPage } from './transformContentPage';
6
7
 
@@ -20,6 +21,11 @@ export function ContentPageRepository({
20
21
  return pages.find((content) => content.slug === slug);
21
22
  }
22
23
 
24
+ async function getMobilePageBySlug(slug: string): Promise<ContentPageDef | undefined> {
25
+ const page = await getContentPageBySlug(slug);
26
+ return page && toMobilePage(page);
27
+ }
28
+
23
29
  const cache: Record<string, ContentPageDef> = {};
24
30
  async function readPage(filePath: string): Promise<ContentPageDef> {
25
31
  if (!(filePath in cache)) {
@@ -34,5 +40,6 @@ export function ContentPageRepository({
34
40
  return {
35
41
  getAllContentPages,
36
42
  getContentPageBySlug,
43
+ getMobilePageBySlug,
37
44
  };
38
45
  }
@@ -1 +1,2 @@
1
1
  export { ContentPageRepository } from './ContentPageRepository';
2
+ export { toMobilePage } from './toMobilePage';
@@ -0,0 +1,21 @@
1
+ import type { BlockDef, ContentPageDef } from '../types';
2
+
3
+ export function toMobilePage(contentPage: ContentPageDef): ContentPageDef {
4
+ const blocks = contentPage.blocks?.filter(({ mobile }) => !mobile?.hidden).map(toMobileBlock);
5
+ return {
6
+ ...contentPage,
7
+ blocks,
8
+ };
9
+ }
10
+
11
+ function toMobileBlock(block: BlockDef): BlockDef {
12
+ const { mobile } = block;
13
+ if (mobile) {
14
+ return {
15
+ ...block,
16
+ style: mobile.style?.length ? mobile.style : block.style,
17
+ };
18
+ } else {
19
+ return block;
20
+ }
21
+ }
package/src/index.ts CHANGED
@@ -1,7 +1,18 @@
1
1
  export type { ProjectSettings } from './ProjectSettings';
2
2
  export { projectSettings } from './ProjectSettings';
3
3
 
4
- export type { BlockDef, ContentPageMeta, ContentPageDef, Img, ImgSource, Picture } from './types';
4
+ export { LikeAPI } from './api/LikeAPI';
5
+ export { DaDataAPI } from './api/DaDataAPI';
6
+
7
+ export type {
8
+ BlockDef,
9
+ UniBlockProps,
10
+ ContentPageMeta,
11
+ ContentPageDef,
12
+ Img,
13
+ ImgSource,
14
+ Picture,
15
+ } from './types';
5
16
  export type {
6
17
  ContentPageContext,
7
18
  Router,
@@ -14,7 +25,8 @@ export { ContentPageHead } from './ContentPageHead';
14
25
  export { ContentPage } from './ContentPage';
15
26
 
16
27
  export { Blocks } from './Blocks';
17
- export { LikeAPI } from './api/LikeAPI';
28
+ export type { BlockContent } from './Blocks';
29
+ export { MobileBlocks } from './MobileBlocks';
18
30
 
19
31
  export * as url from './utils/url';
20
32
  export { joinList } from './utils/joinList';
@@ -1,6 +1,8 @@
1
1
  import { setup } from '@redneckz/uni-jsx';
2
+
2
3
  import runtime from 'react/jsx-runtime';
3
4
  import { useState, useEffect } from 'react';
5
+ import { DaDataAPI } from './api/DaDataAPI';
4
6
  import type { ContentPageContext } from './ContentPageContext';
5
7
 
6
8
  const { jsx, jsxs } = runtime as any;
@@ -8,6 +10,8 @@ setup(jsx, jsxs);
8
10
 
9
11
  const TEST_ORIGIN = 'http://localhost:5001';
10
12
 
13
+ const DaData = DaDataAPI('https://10.80.4.9');
14
+
11
15
  export const context: ContentPageContext = {
12
16
  useState,
13
17
  useRouter: () => ({
@@ -27,6 +31,17 @@ export const context: ContentPageContext = {
27
31
  }, [key, fetcher]);
28
32
  return { data };
29
33
  },
34
+ useGeolocation: (defaultLocation) => {
35
+ const [city, setCity] = useState(defaultLocation);
36
+
37
+ const getCity = () => {
38
+ DaData.getFetcherAddress().then((_) => {
39
+ setCity(_ || defaultLocation);
40
+ });
41
+ };
42
+
43
+ return [city, getCity];
44
+ },
30
45
  useLikeService: () => ({
31
46
  likeCount: 0,
32
47
  like: () => {
package/src/types.ts CHANGED
@@ -22,6 +22,9 @@ export interface BlockDef {
22
22
  version?: BlockVersion;
23
23
  content?: BlockContent;
24
24
  blocks?: BlockDef[];
25
+ mobile?: Pick<BlockDef, 'content' | 'style'> & {
26
+ hidden?: boolean;
27
+ };
25
28
  }
26
29
 
27
30
  export interface ContentPageMeta {
@@ -92,3 +95,17 @@ export interface Benefit {
92
95
  description?: string;
93
96
  icon?: string;
94
97
  }
98
+
99
+ export interface DaDataResult {
100
+ suggestions?: DaDataSuggestion<DaDataAddress>[];
101
+ }
102
+
103
+ export interface DaDataSuggestion<T> {
104
+ value?: string;
105
+ unrestricted_value?: string;
106
+ data?: T;
107
+ }
108
+
109
+ export interface DaDataAddress {
110
+ city?: string | null;
111
+ }
@@ -0,0 +1,4 @@
1
+ export const getCurrentPosition = async () =>
2
+ new Promise<GeolocationCoordinates>((resolve) =>
3
+ navigator.geolocation.getCurrentPosition(({ coords }) => resolve(coords)),
4
+ );