@zenky/storefront-vue 0.9.47 → 0.10.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 (94) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +163 -6
  3. package/dist/cart/index.d.ts +559 -0
  4. package/dist/cart/index.js +13 -0
  5. package/dist/cart/index.js.map +1 -0
  6. package/dist/catalog/index.d.ts +73 -0
  7. package/dist/catalog/index.js +4 -0
  8. package/dist/catalog/index.js.map +1 -0
  9. package/dist/chunk-2OD7CLKD.js +102 -0
  10. package/dist/chunk-2OD7CLKD.js.map +1 -0
  11. package/dist/chunk-4MJKN7PL.js +111 -0
  12. package/dist/chunk-4MJKN7PL.js.map +1 -0
  13. package/dist/chunk-5QCUH3FF.js +15 -0
  14. package/dist/chunk-5QCUH3FF.js.map +1 -0
  15. package/dist/chunk-AL5W5JSD.js +41 -0
  16. package/dist/chunk-AL5W5JSD.js.map +1 -0
  17. package/dist/chunk-BIGTKVC6.js +38 -0
  18. package/dist/chunk-BIGTKVC6.js.map +1 -0
  19. package/dist/chunk-BWUKMWHL.js +45 -0
  20. package/dist/chunk-BWUKMWHL.js.map +1 -0
  21. package/dist/chunk-DKWDKVXQ.js +91 -0
  22. package/dist/chunk-DKWDKVXQ.js.map +1 -0
  23. package/dist/chunk-EMGQXBU3.js +3 -0
  24. package/dist/chunk-EMGQXBU3.js.map +1 -0
  25. package/dist/chunk-EYRCAUUP.js +45 -0
  26. package/dist/chunk-EYRCAUUP.js.map +1 -0
  27. package/dist/chunk-GW2QNTAD.js +327 -0
  28. package/dist/chunk-GW2QNTAD.js.map +1 -0
  29. package/dist/chunk-IGDDWGS4.js +557 -0
  30. package/dist/chunk-IGDDWGS4.js.map +1 -0
  31. package/dist/chunk-OQLU7FSR.js +1841 -0
  32. package/dist/chunk-OQLU7FSR.js.map +1 -0
  33. package/dist/chunk-PJ2LEKW6.js +229 -0
  34. package/dist/chunk-PJ2LEKW6.js.map +1 -0
  35. package/dist/chunk-PWHIDGKW.js +97 -0
  36. package/dist/chunk-PWHIDGKW.js.map +1 -0
  37. package/dist/chunk-RO25KNM5.js +36 -0
  38. package/dist/chunk-RO25KNM5.js.map +1 -0
  39. package/dist/chunk-V3VVDQIR.js +27 -0
  40. package/dist/chunk-V3VVDQIR.js.map +1 -0
  41. package/dist/chunk-VL3T36VM.js +386 -0
  42. package/dist/chunk-VL3T36VM.js.map +1 -0
  43. package/dist/chunk-XUGXLJZB.js +14 -0
  44. package/dist/chunk-XUGXLJZB.js.map +1 -0
  45. package/dist/chunk-Z3IW4ODZ.js +36 -0
  46. package/dist/chunk-Z3IW4ODZ.js.map +1 -0
  47. package/dist/index.d.ts +26 -0
  48. package/dist/index.js +21 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/layout/index.d.ts +54 -0
  51. package/dist/layout/index.js +102 -0
  52. package/dist/layout/index.js.map +1 -0
  53. package/dist/money/index.d.ts +26 -0
  54. package/dist/money/index.js +3 -0
  55. package/dist/money/index.js.map +1 -0
  56. package/dist/order/index.d.ts +34 -0
  57. package/dist/order/index.js +209 -0
  58. package/dist/order/index.js.map +1 -0
  59. package/dist/pagination/index.d.ts +87 -0
  60. package/dist/pagination/index.js +97 -0
  61. package/dist/pagination/index.js.map +1 -0
  62. package/dist/ports/index.d.ts +124 -0
  63. package/dist/ports/index.js +3 -0
  64. package/dist/ports/index.js.map +1 -0
  65. package/dist/products/index.d.ts +105 -0
  66. package/dist/products/index.js +7 -0
  67. package/dist/products/index.js.map +1 -0
  68. package/dist/promotions/index.d.ts +10 -0
  69. package/dist/promotions/index.js +7 -0
  70. package/dist/promotions/index.js.map +1 -0
  71. package/dist/schedule-Dd3zwHEb.d.ts +27 -0
  72. package/dist/seo/index.d.ts +91 -0
  73. package/dist/seo/index.js +289 -0
  74. package/dist/seo/index.js.map +1 -0
  75. package/dist/snippets/index.d.ts +17 -0
  76. package/dist/snippets/index.js +3 -0
  77. package/dist/snippets/index.js.map +1 -0
  78. package/dist/snippets-BC5bkSjm.d.ts +23 -0
  79. package/dist/stores/index.d.ts +196 -0
  80. package/dist/stores/index.js +8 -0
  81. package/dist/stores/index.js.map +1 -0
  82. package/dist/theme/index.d.ts +60 -0
  83. package/dist/theme/index.js +3 -0
  84. package/dist/theme/index.js.map +1 -0
  85. package/dist/utils/index.d.ts +66 -0
  86. package/dist/utils/index.js +4 -0
  87. package/dist/utils/index.js.map +1 -0
  88. package/dist/website-settings/index.d.ts +38 -0
  89. package/dist/website-settings/index.js +3 -0
  90. package/dist/website-settings/index.js.map +1 -0
  91. package/package.json +121 -47
  92. package/dist/cjs/index.cjs +0 -3742
  93. package/dist/esm/index.mjs +0 -3642
  94. package/dist/zenky.d.ts +0 -10377
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pagination/usePaginatedList.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { computed, ref, type ComputedRef, type Ref } from 'vue'\n\nimport type { PaginatedResponse } from '@zenky/storefront-api'\n\n/**\n * Pure composable пагинации списка (товары, статьи блога и т.д.).\n *\n * Универсальный — фетчер и тип элемента передаются снаружи через дженерик `T` и\n * замыкание, поэтому можно использовать для категории, коллекции, блога и т.п.\n * Не зависит от Nuxt — можно вынести в библиотеку.\n *\n * Поддерживает два режима навигации:\n * - `loadPage(N)` — заменяет всё содержимое элементами N-й страницы (для прямого\n * ?page=N и для классической пагинации цифрами)\n * - `loadMore()` — добавляет следующую страницу к текущему списку (load-more / infinite)\n *\n * Хранит данные не как плоский массив, а как **чанки по страницам** (`pageChunks`).\n * Это позволяет UI рендерить каждую страницу отдельной секцией с `data-page` атрибутом,\n * что нужно для `content-visibility: auto` (оптимизация рендера скрытых секций).\n *\n * Параллельные вызовы игнорируются (одна загрузка за раз).\n */\n\nexport type PaginatedFetcher<T> = (page: number, count: number) => Promise<PaginatedResponse<T>>\n\nexport interface PageChunk<T> {\n page: number\n items: T[]\n}\n\nexport interface UsePaginatedListOptions<T> {\n /** Размер страницы. По умолчанию 20 — баланс для 2/4/5-колоночных сеток. */\n perPage?: number\n /** С какой страницы начинать. Используется для инициализации из ?page=N. */\n initialPage?: number\n /**\n * Готовые данные первой загрузки (для SSR-friendly инициализации без повторного\n * запроса на клиенте). Если переданы — composable не делает первичный fetch.\n */\n initialData?: PaginatedResponse<T> | null\n /** Функция загрузки страницы. Замыкание родителя — может включать фильтры, категорию и т.д. */\n fetcher: PaginatedFetcher<T>\n}\n\nexport interface UsePaginatedList<T> {\n /**\n * Чанки страниц — основной источник данных. Каждый элемент — это загруженная\n * страница со своими элементами. При `loadPage` — массив заменяется одним чанком.\n * При `loadMore` — новый чанк добавляется в конец.\n */\n pageChunks: Ref<PageChunk<T>[]>\n /** Плоский массив всех загруженных элементов (computed из pageChunks для удобства). */\n items: ComputedRef<T[]>\n /** Самая последняя загруженная страница (не обязательно «текущая» для пагинации). */\n currentPage: Ref<number>\n /** Диапазон страниц, чьи элементы сейчас в `pageChunks`. */\n pageWindow: Ref<{ from: number; to: number }>\n /** Всего страниц по данным API. */\n totalPages: Ref<number>\n /** Всего элементов по данным API. */\n totalItems: Ref<number>\n /** Есть ли следующая страница для load-more. */\n hasMore: Ref<boolean>\n /** Идёт ли запрос. */\n loading: Ref<boolean>\n /** Произошла ли ошибка при последнем запросе. */\n error: Ref<unknown | null>\n\n /** Заменить state элементами страницы N. Используется для прямого перехода и кликов на цифру. */\n loadPage(page: number): Promise<void>\n /** Догрузить следующую страницу (append). */\n loadMore(): Promise<void>\n /**\n * Применить готовые данные страницы без запроса (используется когда initialData\n * приходит асинхронно через `useAsyncData({ lazy: true })` на клиенте).\n */\n applyInitialData(response: PaginatedResponse<T>, page: number): void\n /**\n * Принудительно включить loading-флаг и очистить pageChunks. Используется\n * когда SSR вернул пустые initialData и мы ждём клиентскую загрузку.\n */\n startLoading(): void\n /**\n * Выключить loading-флаг без применения данных (при ошибке, чтобы скрыть скелетоны).\n */\n stopLoading(): void\n}\n\nconst DEFAULT_PER_PAGE = 20\n\nexport function usePaginatedList<T>(options: UsePaginatedListOptions<T>): UsePaginatedList<T> {\n const perPage = options.perPage ?? DEFAULT_PER_PAGE\n const fetcher = options.fetcher\n\n const pageChunks = ref<PageChunk<T>[]>([]) as Ref<PageChunk<T>[]>\n const currentPage = ref<number>(options.initialPage ?? 1)\n const pageWindow = ref<{ from: number; to: number }>({\n from: options.initialPage ?? 1,\n to: options.initialPage ?? 1,\n })\n const totalPages = ref<number>(1)\n const totalItems = ref<number>(0)\n const hasMore = ref<boolean>(false)\n const loading = ref<boolean>(false)\n const error = ref<unknown | null>(null)\n\n /** Плоский массив для обратной совместимости — просто flatMap по чанкам. */\n const items = computed<T[]>(() => pageChunks.value.flatMap(chunk => chunk.items))\n\n /**\n * Применить ответ API в replace-режиме (loadPage) — один чанк заменяет всё.\n */\n function applyReplaceResponse(response: PaginatedResponse<T>, page: number): void {\n pageChunks.value = [{ page, items: response.items }]\n currentPage.value = page\n pageWindow.value = { from: page, to: page }\n totalPages.value = response.pagination.total_pages\n totalItems.value = response.pagination.total\n hasMore.value = response.pagination.has_next_page\n }\n\n // Если переданы готовые данные первой страницы — заиспользуем без запроса\n if (options.initialData) {\n applyReplaceResponse(options.initialData, options.initialPage ?? 1)\n }\n\n async function loadPage(page: number): Promise<void> {\n if (loading.value) return\n\n loading.value = true\n error.value = null\n // Очищаем старые данные, чтобы UI показал skeleton вместо застывшей старой страницы.\n pageChunks.value = []\n\n try {\n const response = await fetcher(page, perPage)\n applyReplaceResponse(response, page)\n } catch (e) {\n error.value = e\n console.error('[paginated-list] loadPage failed', e)\n } finally {\n loading.value = false\n }\n }\n\n async function loadMore(): Promise<void> {\n if (loading.value || !hasMore.value) return\n\n const nextPage = currentPage.value + 1\n loading.value = true\n error.value = null\n\n try {\n const response = await fetcher(nextPage, perPage)\n\n // Append — добавляем новый чанк вместо мержа в плоский массив\n pageChunks.value = [...pageChunks.value, { page: nextPage, items: response.items }]\n currentPage.value = nextPage\n pageWindow.value = { from: pageWindow.value.from, to: nextPage }\n totalPages.value = response.pagination.total_pages\n totalItems.value = response.pagination.total\n hasMore.value = response.pagination.has_next_page\n } catch (e) {\n error.value = e\n console.error('[paginated-list] loadMore failed', e)\n } finally {\n loading.value = false\n }\n }\n\n function applyInitialData(response: PaginatedResponse<T>, page: number): void {\n applyReplaceResponse(response, page)\n loading.value = false\n }\n\n function startLoading(): void {\n loading.value = true\n pageChunks.value = []\n }\n\n function stopLoading(): void {\n loading.value = false\n }\n\n return {\n pageChunks,\n items,\n currentPage,\n pageWindow,\n totalPages,\n totalItems,\n hasMore,\n loading,\n error,\n loadPage,\n loadMore,\n applyInitialData,\n startLoading,\n stopLoading,\n }\n}\n"]}
@@ -0,0 +1,124 @@
1
+ import { Ref } from 'vue';
2
+ import { ZenkyIntegrationsSDK } from '@zenky/integrations-sdk';
3
+ import { RemoteCatalog, ZenkyStorefront } from '@zenky/storefront-api';
4
+
5
+ interface StorageOptions {
6
+ /** Время жизни в секундах. */
7
+ maxAge?: number;
8
+ sameSite?: 'strict' | 'lax' | 'none';
9
+ secure?: boolean;
10
+ path?: string;
11
+ }
12
+ /** Персистентное key-value хранилище (куки / localStorage / память). */
13
+ interface StorageAdapter {
14
+ get(key: string): string | null;
15
+ set(key: string, value: string, options?: StorageOptions): void;
16
+ remove(key: string, options?: StorageOptions): void;
17
+ }
18
+ /** Конфиг рантайма, который ядро не должно знать откуда берётся. */
19
+ interface StorefrontConfig {
20
+ baseUrl: string;
21
+ baseAuthUrl: string;
22
+ /** Опциональный sales channel для креативов/каналов. */
23
+ salesChannelId?: string;
24
+ }
25
+ /** Уведомления пользователю (тосты). Реализация — на стороне потребителя. */
26
+ interface Notifier {
27
+ error(message: string): void;
28
+ success(message: string): void;
29
+ warning(message: string): void;
30
+ message(title: string, options?: {
31
+ description?: string;
32
+ }): void;
33
+ }
34
+ /** Репортер активности (busy-индикаторы, длительные операции). */
35
+ interface ActivityReporter {
36
+ begin(kind: string): void;
37
+ end(kind: string): void;
38
+ }
39
+ /** Realtime-канал: подписка на события (WebSocket). Ядро не знает про pusher/транспорт. */
40
+ interface RealtimeChannel {
41
+ bind(event: string, handler: (data?: unknown) => void): void;
42
+ }
43
+ interface RealtimeAdapter {
44
+ subscribe(channelName: string): RealtimeChannel | null;
45
+ unsubscribe(channelName: string): void;
46
+ isReady: Ref<boolean>;
47
+ }
48
+ interface RealtimePort {
49
+ get(): RealtimeAdapter | null;
50
+ }
51
+ interface EventsPort {
52
+ get(): ZenkyIntegrationsSDK | null;
53
+ }
54
+ /** Перезагрузка каталога при смене склада. Транспорт (fetch) — на стороне потребителя. */
55
+ interface CatalogReloader {
56
+ reload(storeId: string, remoteCatalog: RemoteCatalog): Promise<void>;
57
+ }
58
+ /** RUM-репортер производительности (performance-marks). Реализация — у потребителя. */
59
+ interface RumReporter {
60
+ mark(name: string): void;
61
+ measure(metric: string, startMark: string): void;
62
+ }
63
+ /** Идентификаторы commerce-события (session/anonymous) — попадают в checkout-request. */
64
+ interface CommerceEventIdentity {
65
+ session_id?: string;
66
+ anonymous_id?: string;
67
+ }
68
+ interface CommerceAddedToCartPayload {
69
+ productId: string;
70
+ productVariantId: string;
71
+ quantity?: number;
72
+ unitPrice?: number;
73
+ totalPrice?: number;
74
+ }
75
+ interface CommerceRemovedFromCartPayload {
76
+ productId: string;
77
+ productVariantId: string;
78
+ quantity?: number;
79
+ }
80
+ /** Commerce-event трекинг (#29). Реализация/очередь/транспорт — у потребителя. */
81
+ interface CommerceEventsPort {
82
+ trackAddedToCart(orderId: string, payload: CommerceAddedToCartPayload): void;
83
+ trackRemovedFromCart(orderId: string, payload: CommerceRemovedFromCartPayload): void;
84
+ getIdentity(): CommerceEventIdentity;
85
+ }
86
+ /**
87
+ * Railway-style результат: компилятор не даст прочитать `.value`,
88
+ * пока потребитель не проверил `.ok`. Замена throw на публичной границе.
89
+ */
90
+ type Result<T = void, E = unknown> = {
91
+ ok: true;
92
+ value: T;
93
+ } | {
94
+ ok: false;
95
+ error: E;
96
+ };
97
+ declare const ok: <T>(value: T) => Result<T, never>;
98
+ declare const err: <E>(error: E) => Result<never, E>;
99
+ /** Полный рантайм, который потребитель собирает и отдаёт в createStorefront(). */
100
+ interface StorefrontRuntime {
101
+ /** SDK-клиент Zenky. Потребитель создаёт один инстанс и отдаёт сюда. */
102
+ sdk: ZenkyStorefront;
103
+ storage: StorageAdapter;
104
+ config: StorefrontConfig;
105
+ notifier: Notifier;
106
+ activity: ActivityReporter;
107
+ /** Ленивый провайдер analytics-интеграции, которая может появиться после setup. */
108
+ events?: EventsPort | null;
109
+ /** Ленивый провайдер realtime-транспорта (WebSocket). */
110
+ realtime?: RealtimePort | null;
111
+ /** Перезагрузка каталога при смене склада. Нет — reload пропускается. */
112
+ catalogReloader?: CatalogReloader | null;
113
+ /** RUM-метрики. Нет — инструментирование пропускается. */
114
+ rum?: RumReporter | null;
115
+ /** Commerce-event трекинг (#29). Нет — трекинг пропускается. */
116
+ commerceEvents?: CommerceEventsPort | null;
117
+ }
118
+ declare const NOOP_NOTIFIER: Notifier;
119
+ declare const NOOP_ACTIVITY_REPORTER: ActivityReporter;
120
+ declare const NOOP_RUM: RumReporter;
121
+ /** In-memory storage — для SSR/тестов, без побочных эффектов на реальные куки. */
122
+ declare function createMemoryStorage(): StorageAdapter;
123
+
124
+ export { type ActivityReporter, type CatalogReloader, type CommerceAddedToCartPayload, type CommerceEventIdentity, type CommerceEventsPort, type CommerceRemovedFromCartPayload, type EventsPort, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, type Notifier, type RealtimeAdapter, type RealtimeChannel, type RealtimePort, type Result, type RumReporter, type StorageAdapter, type StorageOptions, type StorefrontConfig, type StorefrontRuntime, createMemoryStorage, err, ok };
@@ -0,0 +1,3 @@
1
+ export { NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from '../chunk-AL5W5JSD.js';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,105 @@
1
+ import { UnitType, Product, ProductVariant, NestedCategory, ProductModifiersRequest, Discount, ProductVariantOptionValue, CatalogItem } from '@zenky/storefront-api';
2
+ import { ComputedRef, Ref } from 'vue';
3
+
4
+ declare function getVariantWeight(variant: ProductVariant | null | undefined): number | null;
5
+ declare function getProductWeight(product: Product): number | null;
6
+ declare function toGrams(weight: number | null, unitType: UnitType): number | null;
7
+ declare function formatWeight(weight: number | null, unitType: UnitType): string | null;
8
+
9
+ interface CategoryWithProducts {
10
+ id: string;
11
+ shortId: string;
12
+ slug: string | null;
13
+ name: string | null;
14
+ products: Product[];
15
+ }
16
+ declare function useProductsByCategory(products: ComputedRef<Product[]>, categories: ComputedRef<NestedCategory[]>): {
17
+ grouped: ComputedRef<CategoryWithProducts[]>;
18
+ };
19
+
20
+ declare function useProductVariantModifiers(variant: ComputedRef<ProductVariant | null>): {
21
+ modifiersModel: Ref<ProductModifiersRequest[]>;
22
+ selectedModifiersHash: Ref<string | null>;
23
+ hasAnyModifier: ComputedRef<boolean>;
24
+ };
25
+
26
+ interface ResolvedPrice {
27
+ price: number;
28
+ originalPrice: number | null;
29
+ discount: Discount | null;
30
+ }
31
+ /**
32
+ * Определяет цену варианта с учётом склада.
33
+ * Приоритет: prices[stockId] → prices[null] → top-level price.
34
+ */
35
+ declare function resolveVariantPrice(variant: ProductVariant, stockId?: string | null): ResolvedPrice;
36
+ declare function useProductPricing(product: ComputedRef<Product>, stockId?: ComputedRef<string | null | undefined>): {
37
+ displayPrice: ComputedRef<number>;
38
+ originalDisplayPrice: ComputedRef<number | null>;
39
+ hasDifferentPrices: ComputedRef<boolean>;
40
+ needsSelection: ComputedRef<boolean>;
41
+ };
42
+
43
+ interface ProductVariantOptionListItem {
44
+ id: string;
45
+ name: string | null;
46
+ values: ProductVariantOptionValue[];
47
+ }
48
+ declare function useProductVariant(product: ComputedRef<Product>): {
49
+ optionsModel: Ref<Record<string, string>>;
50
+ optionsList: Ref<ProductVariantOptionListItem[]>;
51
+ selectedVariant: ComputedRef<ProductVariant | null>;
52
+ disabledValues: ComputedRef<Record<string, Set<string>>>;
53
+ };
54
+
55
+ interface PriceRecalculationOptions {
56
+ product: ComputedRef<Product>;
57
+ selectedVariant: ComputedRef<ProductVariant | null>;
58
+ modifiersModel: Ref<ProductModifiersRequest[]>;
59
+ requiredModifiersGroupIsMissing: ComputedRef<boolean>;
60
+ selectedModifiersHash: Ref<string | null>;
61
+ }
62
+ declare function usePriceRecalculation({ product, selectedVariant, modifiersModel, requiredModifiersGroupIsMissing, selectedModifiersHash, }: PriceRecalculationOptions): {
63
+ price: ComputedRef<number>;
64
+ originalPrice: ComputedRef<number | null>;
65
+ priceWasModified: ComputedRef<boolean>;
66
+ priceIsRecalculating: Ref<boolean>;
67
+ };
68
+
69
+ declare function useProductVariantSelector(product: ComputedRef<Product>): {
70
+ optionsModel: Ref<Record<string, string>>;
71
+ optionsList: Ref<ProductVariantOptionListItem[]>;
72
+ disabledValues: ComputedRef<Record<string, Set<string>>>;
73
+ modifiersModel: Ref<ProductModifiersRequest[]>;
74
+ selectedVariant: ComputedRef<ProductVariant | null>;
75
+ price: ComputedRef<number>;
76
+ originalPrice: ComputedRef<number | null>;
77
+ priceWasModified: ComputedRef<boolean>;
78
+ priceIsRecalculating: Ref<boolean>;
79
+ selectedModifiersHash: Ref<string | null>;
80
+ requiredModifiersGroupIsMissing: ComputedRef<boolean>;
81
+ };
82
+
83
+ interface OrderCredentials {
84
+ id: string;
85
+ token: string;
86
+ }
87
+ interface UseRelatedProductsApi {
88
+ fetchForProduct: (productId: string, orderCredentials: OrderCredentials | null, signal?: AbortSignal) => Promise<Product[]>;
89
+ fetchForOrder: (orderId: string, orderToken: string, signal?: AbortSignal) => Promise<Product[]>;
90
+ }
91
+ /**
92
+ * Один из вариантов товара и ни одного модификатора — такой товар можно класть
93
+ * в корзину одним кликом по рекомендации, минуя открытие карточки.
94
+ */
95
+ declare function canAddDirectly(product: Product): boolean;
96
+ declare function useRelatedProducts(): UseRelatedProductsApi;
97
+
98
+ interface CatalogProductMatch {
99
+ product: Product;
100
+ catalogItem: CatalogItem;
101
+ }
102
+ /** Поиск товара по short_id в статичном каталоге. null — если не найден. */
103
+ declare function findProductInCatalog(catalog: CatalogItem[], shortId: string): CatalogProductMatch | null;
104
+
105
+ export { type CatalogProductMatch, type CategoryWithProducts, type OrderCredentials, type ProductVariantOptionListItem, type ResolvedPrice, canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts };
@@ -0,0 +1,7 @@
1
+ export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from '../chunk-IGDDWGS4.js';
2
+ import '../chunk-5QCUH3FF.js';
3
+ import '../chunk-PWHIDGKW.js';
4
+ import '../chunk-XUGXLJZB.js';
5
+ import '../chunk-V3VVDQIR.js';
6
+ //# sourceMappingURL=index.js.map
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,10 @@
1
+ interface PromotionsChecker {
2
+ dispatchCheck: () => Promise<void>;
3
+ }
4
+ /**
5
+ * Проверка промо-акций. Вызывает dispatchPromotionsChecker после изменения корзины.
6
+ * Результат приходит через WebSocket (обрабатывается в useOrderChannel).
7
+ */
8
+ declare function usePromotionsChecker(): PromotionsChecker;
9
+
10
+ export { type PromotionsChecker, usePromotionsChecker };
@@ -0,0 +1,7 @@
1
+ export { usePromotionsChecker } from '../chunk-4MJKN7PL.js';
2
+ import '../chunk-BWUKMWHL.js';
3
+ import '../chunk-PWHIDGKW.js';
4
+ import '../chunk-VL3T36VM.js';
5
+ import '../chunk-V3VVDQIR.js';
6
+ //# sourceMappingURL=index.js.map
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,27 @@
1
+ import { ContactType, Contact, Schedule } from '@zenky/storefront-api';
2
+
3
+ interface SocialLink {
4
+ type: ContactType;
5
+ url: string;
6
+ label: string;
7
+ }
8
+ declare function getSocialLinks(contacts: Contact[]): SocialLink[];
9
+ declare function getEmailLink(contacts: Contact[]): string | null;
10
+ declare function getWebsiteLink(contacts: Contact[]): string | null;
11
+
12
+ interface DayScheduleInfo {
13
+ dayKey: string;
14
+ name: string;
15
+ hours: string | null;
16
+ }
17
+ interface TodayScheduleInfo {
18
+ isOpenNow: boolean;
19
+ todayHours: string | null;
20
+ openingAt: string | null;
21
+ closingAt: string | null;
22
+ }
23
+ declare function getTodayInfo(schedule: Schedule | null | undefined): TodayScheduleInfo | null;
24
+ declare function getWeeklySchedule(schedule: Schedule | null | undefined, locale?: string): DayScheduleInfo[];
25
+ declare function formatScheduleStatus(schedule: Schedule | null | undefined, locale?: string): string | null;
26
+
27
+ export { type DayScheduleInfo as D, type SocialLink as S, type TodayScheduleInfo as T, getSocialLinks as a, getTodayInfo as b, getWebsiteLink as c, getWeeklySchedule as d, formatScheduleStatus as f, getEmailLink as g };
@@ -0,0 +1,91 @@
1
+ import { Media, Store, Product, NestedCategory, Article, OfferArticle, Seo, SeoMetaTag as SeoMetaTag$1 } from '@zenky/storefront-api';
2
+
3
+ /**
4
+ * Shared SEO types used across storefront composables.
5
+ * Kept framework-agnostic for future extraction to a standalone library.
6
+ */
7
+ interface BreadcrumbItem {
8
+ label: string;
9
+ to?: string;
10
+ }
11
+
12
+ declare const SEO_META_TAG_PRIORITY = "critical";
13
+ type SeoMetaTag = Record<string, string>;
14
+ declare function withSeoMetaPriority<T extends SeoMetaTag>(tag: T): T & {
15
+ tagPriority: typeof SEO_META_TAG_PRIORITY;
16
+ };
17
+
18
+ /**
19
+ * Resolves the best available URL from a Media object.
20
+ */
21
+ declare function resolveMediaUrl(media: Media): string | null;
22
+ /**
23
+ * Resolves store logo URL, preferring square logo over rectangular.
24
+ * Tries all available size variants so CDN assets with only hd/xlarge are found too.
25
+ */
26
+ declare function resolveStoreLogoUrl(store: Store | null | undefined): string | null;
27
+ /**
28
+ * Strips HTML tags from a string.
29
+ */
30
+ declare function stripHtml(html: string): string;
31
+ /**
32
+ * Prepares a string for use as og:description or meta description:
33
+ * strips HTML tags and truncates to maxLength (default 160).
34
+ */
35
+ declare function prepareOgDescription(text: string | null | undefined, maxLength?: number): string | null;
36
+
37
+ /**
38
+ * Каноничный публичный origin сайта из `store.domain`. Fallback (хост запроса)
39
+ * приносит потребитель — ядро не знает про useRequestURL.
40
+ */
41
+ declare function resolveSiteOrigin(storeDomain: string | null | undefined, fallbackOrigin: string): string;
42
+
43
+ /**
44
+ * JSON-LD schema.org/Product. Google → Rich Results (цена/наличие/рейтинг в выдаче).
45
+ * Возвращает массив (0 или 1 объект) — потребитель оборачивает в `<script ld+json>`.
46
+ * Spec: https://schema.org/Product
47
+ */
48
+ declare function buildProductSchema(product: Product, currency: string): Record<string, unknown>[];
49
+
50
+ /**
51
+ * JSON-LD для страницы категории: BreadcrumbList (хлебные крошки) + ItemList
52
+ * (первые 10 товаров). Возвращает массив JSON-LD объектов (0–2).
53
+ * Spec: https://schema.org/ItemList · https://schema.org/BreadcrumbList
54
+ */
55
+ declare function buildCategorySchemas(category: NestedCategory, products: Product[], breadcrumbs: BreadcrumbItem[], origin: string): Record<string, unknown>[];
56
+
57
+ /**
58
+ * JSON-LD schema.org/Article для страницы акции (редакционный контент).
59
+ * Spec: https://schema.org/Article
60
+ */
61
+ declare function buildOfferArticleSchema(article: OfferArticle, storeName: string, origin: string): Record<string, unknown>[];
62
+ /**
63
+ * JSON-LD schema.org/BlogPosting для статьи блога (Google Rich Results).
64
+ * Spec: https://schema.org/BlogPosting
65
+ */
66
+ declare function buildBlogPostSchema(article: Article, storeName: string, origin: string): Record<string, unknown>[];
67
+
68
+ /**
69
+ * JSON-LD schema.org/Organization (или LocalBusiness при наличии физической точки)
70
+ * для главной. Google → Knowledge Panel. Все данные из уже загруженного профиля.
71
+ * Spec: https://schema.org/Organization · https://schema.org/LocalBusiness
72
+ */
73
+ declare function buildOrganizationSchema(store: Store, origin: string): Record<string, unknown>[];
74
+
75
+ /** Уже разрешённые (с учётом дефолтов потребителя) значения OG/Twitter-тегов. */
76
+ interface OgTagsInput {
77
+ title: string | null;
78
+ description?: string | null;
79
+ image?: string | null;
80
+ type?: string;
81
+ url?: string | null;
82
+ }
83
+ /** OG + Twitter meta-теги (critical-приоритет). Telegram читает twitter:image. */
84
+ declare function buildOgTags(input: OgTagsInput): Record<string, string>[];
85
+
86
+ /** SDK-теги `Seo.meta` → head-meta records (с critical-приоритетом для og/twitter/description). */
87
+ declare function mapSeoMetaTags(tags: SeoMetaTag$1[]): Record<string, string>[];
88
+ /** meta-теги из `Seo`-сущности (description + маппинг `Seo.meta`). Title резолвит потребитель. */
89
+ declare function buildEntitySeoMeta(seo: Seo | null | undefined): Record<string, string>[];
90
+
91
+ export { type BreadcrumbItem, type OgTagsInput, buildBlogPostSchema, buildCategorySchemas, buildEntitySeoMeta, buildOfferArticleSchema, buildOgTags, buildOrganizationSchema, buildProductSchema, mapSeoMetaTags, prepareOgDescription, resolveMediaUrl, resolveSiteOrigin, resolveStoreLogoUrl, stripHtml, withSeoMetaPriority };