@zenky/storefront-vue 0.10.18 → 0.12.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 (36) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/cart/index.js +6 -6
  3. package/dist/chunk-6HOKVW4M.js +134 -0
  4. package/dist/chunk-6HOKVW4M.js.map +1 -0
  5. package/dist/{chunk-LABBB43Q.js → chunk-CQDOEP6T.js} +163 -128
  6. package/dist/chunk-CQDOEP6T.js.map +1 -0
  7. package/dist/{chunk-6BXHWR5E.js → chunk-IEHN2WNU.js} +46 -13
  8. package/dist/chunk-IEHN2WNU.js.map +1 -0
  9. package/dist/chunk-JY3UJRMF.js +59 -0
  10. package/dist/chunk-JY3UJRMF.js.map +1 -0
  11. package/dist/{chunk-YTYCSTHP.js → chunk-PBBVWWMI.js} +3 -3
  12. package/dist/{chunk-YTYCSTHP.js.map → chunk-PBBVWWMI.js.map} +1 -1
  13. package/dist/{chunk-2DUKIVKC.js → chunk-QFKA2R6D.js} +3 -3
  14. package/dist/{chunk-2DUKIVKC.js.map → chunk-QFKA2R6D.js.map} +1 -1
  15. package/dist/{chunk-T52G6JN7.js → chunk-TXR76IDL.js} +16 -3
  16. package/dist/chunk-TXR76IDL.js.map +1 -0
  17. package/dist/{chunk-RURXGVWW.js → chunk-UJKWKD3W.js} +4 -56
  18. package/dist/chunk-UJKWKD3W.js.map +1 -0
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +13 -11
  21. package/dist/products/index.d.ts +42 -2
  22. package/dist/products/index.js +3 -2
  23. package/dist/promotions/index.js +2 -2
  24. package/dist/seo/index.d.ts +44 -16
  25. package/dist/seo/index.js +338 -104
  26. package/dist/seo/index.js.map +1 -1
  27. package/dist/stores/index.d.ts +3 -2
  28. package/dist/stores/index.js +3 -3
  29. package/dist/utils/index.js +2 -1
  30. package/docs/architecture.md +5 -3
  31. package/docs/consumer-setup.md +1 -1
  32. package/package.json +3 -3
  33. package/dist/chunk-6BXHWR5E.js.map +0 -1
  34. package/dist/chunk-LABBB43Q.js.map +0 -1
  35. package/dist/chunk-RURXGVWW.js.map +0 -1
  36. package/dist/chunk-T52G6JN7.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/createOperationChain.ts","../src/utils/phone.ts","../src/utils/schedule.ts","../src/utils/qr.ts","../src/utils/date.ts","../src/utils/pluralize.ts","../src/utils/errors.ts","../src/utils/address.ts"],"names":[],"mappings":"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","file":"chunk-UJKWKD3W.js","sourcesContent":["// Serializes async operations by key: for each key, the next operation\n// only starts after the previous one finishes. Prevents races when\n// concurrent calls target the same resource.\n\nexport interface OperationChain {\n execute: (key: string, fn: () => Promise<void>) => Promise<void>\n readonly size: number\n}\n\nexport function createOperationChain(): OperationChain {\n const chains = new Map<string, Promise<void>>()\n\n async function execute(key: string, fn: () => Promise<void>): Promise<void> {\n const prev = chains.get(key) ?? Promise.resolve()\n\n const current = prev.then(fn)\n\n // Prevents an unhandled rejection from propagating through the chain\n const safe = current.catch(() => {})\n chains.set(key, safe)\n\n // Drop the entry once nothing else chained onto it after it settled\n safe.finally(() => {\n if (chains.get(key) === safe) {\n chains.delete(key)\n }\n })\n\n return current\n }\n\n return {\n execute,\n get size() {\n return chains.size\n },\n }\n}\n","import type { Phone } from '@zenky/storefront-api'\n\nexport function formatPhoneNational(phone: Phone | null | undefined): string | null {\n if (!phone) return null\n\n return phone.national || phone.number\n}\n\nexport function getPhoneTelLink(phone: Phone | null | undefined): string | null {\n if (!phone) return null\n\n return `tel:${phone.number}`\n}\n\n/**\n * Loose-spaced phone format: `+7 (999) 999-99-99` → `+7 999 999 99 99`.\n * Parens and dashes become spaces, repeated spaces collapse to one.\n */\nexport function formatPhoneSpaced(formatted: string | null | undefined): string {\n if (!formatted) return ''\n\n return formatted.replace(/[()-]/g, ' ').replace(/\\s+/g, ' ').trim()\n}\n","import type { Schedule } from '@zenky/storefront-api'\n\nexport interface DayScheduleInfo {\n dayKey: string\n name: string\n hours: string | null\n}\n\nexport interface TodayScheduleInfo {\n isOpenNow: boolean\n todayHours: string | null\n openingAt: string | null\n closingAt: string | null\n}\n\n// API day key → JS day index (0=Sun, 1=Mon, ..., 6=Sat)\nconst DAY_TO_JS_INDEX: Record<string, number> = {\n sunday: 0,\n monday: 1,\n tuesday: 2,\n wednesday: 3,\n thursday: 4,\n friday: 5,\n saturday: 6,\n} as const\n\nconst DAY_ORDER = [\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n 'sunday',\n] as const\n\nconst MAX_CACHED_FORMATTERS = 32\nconst dayNameFormatters = new Map<string, Intl.DateTimeFormat>()\n\nfunction getDayFormatter(locale: string, weekday: 'long' | 'short'): Intl.DateTimeFormat {\n const key = `${locale}:${weekday}`\n let formatter = dayNameFormatters.get(key)\n\n if (!formatter) {\n formatter = new Intl.DateTimeFormat(locale, { weekday })\n\n if (dayNameFormatters.size >= MAX_CACHED_FORMATTERS) dayNameFormatters.clear()\n\n dayNameFormatters.set(key, formatter)\n }\n\n return formatter\n}\n\n// Reference date: January 2, 2000 is a Sunday (JS index 0).\n// For dayIndex=0 (Sun) add 0, for 1 (Mon) add 1, and so on.\nfunction getDayName(dayKey: string, locale: string, weekday: 'long' | 'short'): string {\n const index = DAY_TO_JS_INDEX[dayKey]\n\n if (index === undefined) {\n return dayKey\n }\n\n const date = new Date(2000, 0, 2 + index)\n\n return getDayFormatter(locale, weekday).format(date)\n}\n\ninterface StatusLabels {\n open: string\n closed: string\n}\n\nconst DEFAULT_STATUS_LABELS: StatusLabels = { open: 'Открыто', closed: 'Закрыто' }\n\nconst STATUS_LABELS: Record<string, StatusLabels> = {\n 'ru-RU': DEFAULT_STATUS_LABELS,\n 'en-US': { open: 'Open', closed: 'Closed' },\n}\n\nexport function getTodayInfo(schedule: Schedule | null | undefined): TodayScheduleInfo | null {\n if (!schedule) return null\n\n const todayDay = schedule.days[schedule.day_id as keyof typeof schedule.days]\n\n return {\n isOpenNow: schedule.is_open_now,\n todayHours: todayDay?.hours ?? null,\n openingAt: schedule.opening_at,\n closingAt: schedule.closing_at,\n }\n}\n\nexport function getWeeklySchedule(\n schedule: Schedule | null | undefined,\n locale = 'ru-RU'\n): DayScheduleInfo[] {\n if (!schedule) return []\n\n return DAY_ORDER.map((dayKey) => ({\n dayKey,\n name: getDayName(dayKey, locale, 'long'),\n hours: schedule.days[dayKey]?.hours ?? null,\n }))\n}\n\nexport function formatScheduleStatus(\n schedule: Schedule | null | undefined,\n locale = 'ru-RU'\n): string | null {\n if (!schedule) return null\n\n const labels = STATUS_LABELS[locale] ?? DEFAULT_STATUS_LABELS\n\n return schedule.is_open_now ? labels.open : labels.closed\n}\n\nexport interface ScheduleRow {\n label: string\n hours: string | null\n}\n\nexport function groupScheduleDays(\n schedule: Schedule | null | undefined,\n locale = 'ru-RU'\n): ScheduleRow[] {\n const days = getWeeklySchedule(schedule, locale)\n const rows: ScheduleRow[] = []\n let firstDayOfRun = ''\n\n for (let index = 0; index < days.length; index++) {\n const day = days[index]!\n const previous = index > 0 ? days[index - 1]! : null\n const short = getDayName(day.dayKey, locale, 'short')\n\n if (previous && previous.hours === day.hours) {\n rows[rows.length - 1]!.label = `${firstDayOfRun} — ${short}`\n continue\n }\n\n firstDayOfRun = short\n rows.push({ label: short, hours: day.hours })\n }\n\n return rows\n}\n","/**\n * Builds a QR code image URL through the Zenky media API.\n *\n * The content is base64-encoded and passed in the `content` query param.\n * This implementation doesn't depend on `window`, `btoa`, or Node's `Buffer`,\n * so the same code works in the browser, Node SSR, and edge runtimes.\n */\nexport function buildQrCodeUrl(target: string, apiBaseUrl: string, size = 200): string {\n if (!target) return ''\n\n const utf8 = encodeBase64(new TextEncoder().encode(target))\n\n return `${apiBaseUrl}/media/qrcode?content=${utf8}&input=base64&size=${size}`\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\nfunction encodeBase64(bytes: Uint8Array): string {\n let output = ''\n\n for (let index = 0; index < bytes.length; index += 3) {\n const first = bytes[index] ?? 0\n const second = bytes[index + 1]\n const third = bytes[index + 2]\n const group = (first << 16) | ((second ?? 0) << 8) | (third ?? 0)\n\n output += BASE64_ALPHABET[(group >> 18) & 63]\n output += BASE64_ALPHABET[(group >> 12) & 63]\n output += second === undefined ? '=' : BASE64_ALPHABET[(group >> 6) & 63]\n output += third === undefined ? '=' : BASE64_ALPHABET[group & 63]\n }\n\n return output\n}\n","export function formatDate(date: string): string {\n return new Date(date).toLocaleDateString('ru-RU', {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n })\n}\n\nexport function formatDateTime(date: string): string {\n const d = new Date(date)\n const datePart = d.toLocaleDateString('ru-RU', {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n })\n const timePart = d.toLocaleTimeString('ru-RU', {\n hour: '2-digit',\n minute: '2-digit',\n })\n return `${datePart} ${timePart}`\n}\n\n/**\n * Extracts YYYY-MM-DD from an ISO string (e.g. \"1998-06-02T03:00:00+03:00\" → \"1998-06-02\").\n * For use in `<input type=\"date\">`.\n */\nexport function toDateInputValue(value: string | null): string {\n if (!value) return ''\n return value.slice(0, 10)\n}\n\n/**\n * Today's date in the given timezone, as YYYY-MM-DD.\n * Falls back to the browser's local timezone if `timezone` is invalid or omitted.\n *\n * Use this to match \"today\" against a backend date that's relative to the\n * store's timezone, not the user's.\n */\nexport function todayInTimezone(timezone?: string | null): string {\n const now = new Date()\n\n const options: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n }\n\n // Only set timeZone when it's given: under exactOptionalPropertyTypes,\n // an optional property can't be assigned undefined.\n if (timezone) {\n options.timeZone = timezone\n }\n\n try {\n return new Intl.DateTimeFormat('en-CA', options).format(now)\n } catch {\n // Invalid timezone — fall back to the local one\n return new Intl.DateTimeFormat('en-CA').format(now)\n }\n}\n","/**\n * Noun declension by count, for Russian grammar (one/few/many forms).\n *\n * @example\n * pluralize(1, 'позиция', 'позиции', 'позиций') // 'позиция'\n * pluralize(3, 'позиция', 'позиции', 'позиций') // 'позиции'\n * pluralize(5, 'позиция', 'позиции', 'позиций') // 'позиций'\n */\nexport function pluralize(count: number, one: string, few: string, many: string): string {\n const abs = Math.abs(count)\n const mod10 = abs % 10\n const mod100 = abs % 100\n\n if (mod100 >= 11 && mod100 <= 19) return many\n if (mod10 === 1) return one\n if (mod10 >= 2 && mod10 <= 4) return few\n\n return many\n}\n","import { ZenkyError } from '@zenky/storefront-api'\n\n/** The message from a ZenkyError, or a fallback. */\nexport function getApiErrorMessage(e: unknown, fallback: string): string {\n if (e instanceof ZenkyError && e.err?.message) {\n return e.err.message\n }\n\n return fallback\n}\n\n/** Field-level errors from an API response's `meta.errors` (422 validation). */\nexport function getApiFieldErrors(e: unknown): Record<string, string[]> | null {\n if (e instanceof ZenkyError && e.err?.meta?.errors) {\n return e.err.meta.errors as Record<string, string[]>\n }\n\n return null\n}\n","/**\n * Moves the city to the end of an address string.\n * \"г Улан-Удэ, ул Ленина, д 29\" → \"ул Ленина, д 29, г Улан-Удэ\"\n */\nexport function formatAddressCityLast(raw: string): string {\n const match = raw.match(/^(г\\s[^,]+),\\s*(.+)$/)\n\n return match ? `${match[2]}, ${match[1]}` : raw\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { Plugin } from 'vue';
4
4
  export { Major, Minor, asMajor, asMinor, formatPrice, majorToMinor, minorToMajor, minorToMajorString } from './money/index.js';
5
5
  export { FontConfig, PrimaryShades, ThemeColorConfig, ThemeData, buildCssVariableMap, generatePrimaryShades, generateShades, useTheme } from './theme/index.js';
6
6
  export { DayScheduleInfo, OperationChain, ScheduleRow, SocialLink, TodayScheduleInfo, buildQrCodeUrl, createDebounce, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, formatScheduleStatus, getApiErrorMessage, getApiFieldErrors, getEmailLink, getPhoneTelLink, getSocialLinks, getTodayInfo, getWebsiteLink, getWeeklySchedule, groupScheduleDays, pluralize, toDateInputValue, todayInTimezone } from './utils/index.js';
7
- export { CatalogProductMatch, CategoryWithProducts, OrderCredentials, ProductListParams, ProductVariantOptionListItem, ResolvedPrice, UseProductDetailApi, UseProductListApi, canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductDetail, useProductList, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from './products/index.js';
7
+ export { CatalogProductMatch, CategoryWithProducts, OrderCredentials, ProductBadgeAccent, ProductBadgeLayout, ProductBadgeView, ProductBadgeVisibility, ProductListParams, ProductVariantOptionListItem, ResolvedPrice, UseProductDetailApi, UseProductListApi, canAddDirectly, filterProductBadges, findProductInCatalog, formatWeight, getProductBadgeAccent, getProductBadgeLayout, getProductWeight, getRequiredModifiersMinCost, getVariantWeight, resolveVariantPrice, toGrams, toProductBadgeViews, usePriceRecalculation, useProductDetail, useProductList, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from './products/index.js';
8
8
  export { GroupedProducts, SubcategoryGroup, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, getCity, getRemoteCatalog, getStock, groupProductsBySubcategory, useCollections } from './catalog/index.js';
9
9
  export { C as CatalogEntity, S as StaticCatalogItem, a as StaticRemoteCatalog, c as catalogItemEntity, i as isRenderableCatalogItem } from './catalogEntity-C2UxCFng.js';
10
10
  export { AttachedCustomerCache, BonusesReconciliation, BonusesReconciliationDeps, CASH_DENOMINATIONS_MAJOR, CachedCustomerView, CartCredentials, CartDependencies, CartErrorScope, CartInitialization, CartItemRequest, CartLineKeyParams, CartMutationComposable, CartOperations, CartQuantities, CartRecalculation, CartRecalculationDeps, CartStockWatcher, CashChangePresetsOptions, CheckoutFlowFlags, CustomerAttachComposable, DEFAULT_ROUND_STEPS_MAJOR, MainPaymentRequestParams, MutationKind, MutationOptions, ORDER_EVENTS, ORDER_WITH, OrderBonusesComposable, OrderBonusesDeps, OrderCredentialsLike, OrderDelivery, OrderDeliveryDeps, OrderPromocodeComposable, OrderPromocodeDeps, OrderSettingsComposable, OrderTotal, PaymentSelection, PaymentSelectionComposable, RestrictedAddToCart, RestrictionGate, RestrictionGateProduct, RetryOptions, StorefrontCart, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCredentials, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from './cart/index.js';
package/dist/index.js CHANGED
@@ -1,23 +1,25 @@
1
- export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductDetail, useProductList, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from './chunk-LABBB43Q.js';
1
+ export { KEY_MESSAGE_FORMATTER, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from './chunk-VTZYJ6OZ.js';
2
2
  export { normalizeSnippets } from './chunk-GLQXTMVW.js';
3
- export { RESEND_TIMER_SECONDS, useAuthFlowStore, useProductsStore, useStore, useStorefrontProfile } from './chunk-YTYCSTHP.js';
3
+ export { RESEND_TIMER_SECONDS, useAuthFlowStore, useProductsStore, useStore, useStorefrontProfile } from './chunk-PBBVWWMI.js';
4
4
  export { buildCssVariableMap, generatePrimaryShades, generateShades, useTheme } from './chunk-BUNI6MGH.js';
5
- export { buildQrCodeUrl, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, formatScheduleStatus, getApiErrorMessage, getApiFieldErrors, getEmailLink, getPhoneTelLink, getSocialLinks, getTodayInfo, getWebsiteLink, getWeeklySchedule, groupScheduleDays, pluralize, toDateInputValue, todayInTimezone } from './chunk-RURXGVWW.js';
6
- export { createDebounce } from './chunk-XUGXLJZB.js';
5
+ export { buildQrCodeUrl, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, formatScheduleStatus, getApiErrorMessage, getApiFieldErrors, getPhoneTelLink, getTodayInfo, getWeeklySchedule, groupScheduleDays, pluralize, toDateInputValue, todayInTimezone } from './chunk-UJKWKD3W.js';
6
+ export { getEmailLink, getSocialLinks, getWebsiteLink } from './chunk-JY3UJRMF.js';
7
7
  import './chunk-EMGQXBU3.js';
8
8
  import './chunk-5B2P5W3E.js';
9
- export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from './chunk-6BXHWR5E.js';
10
- export { useCartCredentials } from './chunk-2DUKIVKC.js';
11
- import './chunk-5QCUH3FF.js';
9
+ export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from './chunk-IEHN2WNU.js';
10
+ export { useCartCredentials } from './chunk-QFKA2R6D.js';
12
11
  export { getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getValidationErrors, logCartError } from './chunk-TE42OCFK.js';
13
12
  export { usePromotionsStore } from './chunk-544USTPB.js';
14
- export { useCatalogStore } from './chunk-4JCJHAL3.js';
15
- export { createStorefront, provideStorefront, useAuthStore, useCartStore, useOrderSettingsStore, useRuntime } from './chunk-T52G6JN7.js';
16
13
  import './chunk-TIQ7AJLY.js';
17
- export { useStoreProfileStore } from './chunk-IOYYCA75.js';
18
14
  export { catalogItemEntity, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, groupProductsBySubcategory, isRenderableCatalogItem, useCollections } from './chunk-EHARSEZT.js';
19
15
  export { getCity, getRemoteCatalog, getStock } from './chunk-FS2UNPTY.js';
20
16
  export { asMajor, asMinor, formatPrice, majorToMinor, minorToMajor, minorToMajorString } from './chunk-2Y6QTHXI.js';
21
- export { KEY_MESSAGE_FORMATTER, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from './chunk-VTZYJ6OZ.js';
17
+ export { canAddDirectly, filterProductBadges, findProductInCatalog, getProductBadgeAccent, getProductBadgeLayout, toProductBadgeViews, usePriceRecalculation, useProductDetail, useProductList, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from './chunk-CQDOEP6T.js';
18
+ export { formatWeight, getProductWeight, getRequiredModifiersMinCost, getVariantWeight, resolveVariantPrice, toGrams, useProductPricing } from './chunk-6HOKVW4M.js';
19
+ export { createDebounce } from './chunk-XUGXLJZB.js';
20
+ import './chunk-5QCUH3FF.js';
21
+ export { useCatalogStore } from './chunk-4JCJHAL3.js';
22
+ export { createStorefront, provideStorefront, useAuthStore, useCartStore, useOrderSettingsStore, useRuntime } from './chunk-TXR76IDL.js';
23
+ export { useStoreProfileStore } from './chunk-IOYYCA75.js';
22
24
  //# sourceMappingURL=index.js.map
23
25
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { UnitType, Product, ProductVariant, NestedCategory, ProductModifiersRequest, Discount, ProductVariantOptionValue, PaginatedResponse } from '@zenky/storefront-api';
1
+ import { UnitType, Product, ProductVariant, NestedCategory, ProductModifiersRequest, Discount, ProductVariantOptionValue, PaginatedResponse, ProductBadgeColors, ProductBadge } from '@zenky/storefront-api';
2
2
  import { ComputedRef, Ref } from 'vue';
3
3
  import { S as StaticCatalogItem } from '../catalogEntity-C2UxCFng.js';
4
4
 
@@ -34,6 +34,7 @@ interface ResolvedPrice {
34
34
  * Priority: prices[stockId] → prices[null] → top-level price.
35
35
  */
36
36
  declare function resolveVariantPrice(variant: ProductVariant, stockId?: string | null): ResolvedPrice;
37
+ declare function getRequiredModifiersMinCost(product: Product): number;
37
38
  declare function useProductPricing(product: ComputedRef<Product>, stockId?: ComputedRef<string | null | undefined>): {
38
39
  displayPrice: ComputedRef<number>;
39
40
  originalDisplayPrice: ComputedRef<number | null>;
@@ -122,4 +123,43 @@ interface UseProductListApi {
122
123
  }
123
124
  declare function useProductList(): UseProductListApi;
124
125
 
125
- export { type CatalogProductMatch, type CategoryWithProducts, type OrderCredentials, type ProductListParams, type ProductVariantOptionListItem, type ResolvedPrice, type UseProductDetailApi, type UseProductListApi, canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductDetail, useProductList, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts };
126
+ /** A merchant badge validated and normalized for rendering. */
127
+ interface ProductBadgeView {
128
+ id: string;
129
+ label: string | null;
130
+ emoji: string | null;
131
+ imageUrl: string | null;
132
+ colors: ProductBadgeColors | null;
133
+ }
134
+ /** `image-square`: an image without a label, drawn as a square with no background. */
135
+ type ProductBadgeLayout = 'text' | 'image-square';
136
+ /** Colors derived from a badge's own text/background pair, for styles other than solid. */
137
+ interface ProductBadgeAccent {
138
+ base: string;
139
+ shifted: string;
140
+ on: string;
141
+ text: string;
142
+ glass: string;
143
+ }
144
+ interface ProductBadgeVisibility {
145
+ showText: boolean;
146
+ showImages: boolean;
147
+ }
148
+ /**
149
+ * Validates the backend `Product.badges` list: drops badges with nothing to show, repeated
150
+ * ids and unusable icons, accepts only hex colors (alpha is ignored) and http(s) image urls.
151
+ * `colors` is `null` when either color is missing or invalid, so the consumer can fall back
152
+ * to its own theme.
153
+ */
154
+ declare function toProductBadgeViews(badges: ProductBadge[] | null | undefined): ProductBadgeView[];
155
+ declare function getProductBadgeLayout(badge: ProductBadgeView): ProductBadgeLayout;
156
+ /**
157
+ * Derives a palette from the badge's own colors: the more chromatic of text/background
158
+ * becomes the accent (darker one when both are neutral), `on` is white or black, whichever
159
+ * stays readable on it, `shifted` is the hue-rotated gradient end and `glass` is a
160
+ * translucent fill. Pure JS math, no CSS color functions, so it works for any hex input.
161
+ */
162
+ declare function getProductBadgeAccent(colors: ProductBadgeColors): ProductBadgeAccent;
163
+ declare function filterProductBadges(badges: ProductBadgeView[], visibility: ProductBadgeVisibility): ProductBadgeView[];
164
+
165
+ export { type CatalogProductMatch, type CategoryWithProducts, type OrderCredentials, type ProductBadgeAccent, type ProductBadgeLayout, type ProductBadgeView, type ProductBadgeVisibility, type ProductListParams, type ProductVariantOptionListItem, type ResolvedPrice, type UseProductDetailApi, type UseProductListApi, canAddDirectly, filterProductBadges, findProductInCatalog, formatWeight, getProductBadgeAccent, getProductBadgeLayout, getProductWeight, getRequiredModifiersMinCost, getVariantWeight, resolveVariantPrice, toGrams, toProductBadgeViews, usePriceRecalculation, useProductDetail, useProductList, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts };
@@ -1,8 +1,9 @@
1
- export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductDetail, useProductList, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from '../chunk-LABBB43Q.js';
1
+ export { canAddDirectly, filterProductBadges, findProductInCatalog, getProductBadgeAccent, getProductBadgeLayout, toProductBadgeViews, usePriceRecalculation, useProductDetail, useProductList, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from '../chunk-CQDOEP6T.js';
2
+ export { formatWeight, getProductWeight, getRequiredModifiersMinCost, getVariantWeight, resolveVariantPrice, toGrams, useProductPricing } from '../chunk-6HOKVW4M.js';
2
3
  import '../chunk-XUGXLJZB.js';
3
4
  import '../chunk-5QCUH3FF.js';
4
5
  import '../chunk-4JCJHAL3.js';
5
- import '../chunk-T52G6JN7.js';
6
+ import '../chunk-TXR76IDL.js';
6
7
  import '../chunk-IOYYCA75.js';
7
8
  //# sourceMappingURL=index.js.map
8
9
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
- export { usePromotionsChecker } from '../chunk-2DUKIVKC.js';
1
+ export { usePromotionsChecker } from '../chunk-QFKA2R6D.js';
2
2
  import '../chunk-544USTPB.js';
3
- import '../chunk-T52G6JN7.js';
3
+ import '../chunk-TXR76IDL.js';
4
4
  import '../chunk-IOYYCA75.js';
5
5
  //# sourceMappingURL=index.js.map
6
6
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { Media, Store, Product, NestedCategory, ProductsCollection, Article, OfferArticle, Seo, SeoMetaTag } from '@zenky/storefront-api';
1
+ import { Media, Store, Product, NestedCategory, ProductsCollection, Article, OfferArticle, Stock, Seo, SeoMetaTag } from '@zenky/storefront-api';
2
2
 
3
3
  /**
4
4
  * Shared SEO types used across storefront composables.
@@ -22,6 +22,8 @@ declare function resolveStoreLogoUrl(store: Store | null | undefined): string |
22
22
  * Strips HTML tags from a string.
23
23
  */
24
24
  declare function stripHtml(html: string): string;
25
+ declare function normalizeSchemaText(value: string | null | undefined): string;
26
+ declare function htmlToPlainText(html: string | null | undefined): string;
25
27
  /**
26
28
  * Prepares a string for use as og:description or meta description:
27
29
  * strips HTML tags and truncates to maxLength (default 160).
@@ -34,13 +36,35 @@ declare function prepareOgDescription(text: string | null | undefined, maxLength
34
36
  */
35
37
  declare function resolveSiteOrigin(storeDomain: string | null | undefined, fallbackOrigin: string): string;
36
38
 
37
- /**
38
- * JSON-LD schema.org/Product. Google uses it for Rich Results (price, availability,
39
- * rating in search listings).
40
- * Returns an array of 0 or 1 objects — the consumer wraps it in a `<script ld+json>` tag.
41
- * Spec: https://schema.org/Product
42
- */
43
- declare function buildProductSchema(product: Product, currency: string): Record<string, unknown>[];
39
+ declare function organizationSchemaId(origin: string): string;
40
+ declare function webSiteSchemaId(origin: string): string;
41
+ declare function locationAnchorId(stockId: string): string;
42
+ declare function locationSchemaId(origin: string, stockId: string): string;
43
+ declare function productSchemaId(productUrl: string): string;
44
+
45
+ declare const BUSINESS_TYPES: readonly ["Restaurant", "CafeOrCoffeeShop", "FastFoodRestaurant", "Bakery", "BarOrPub", "GroceryStore", "ConvenienceStore", "Florist", "Pharmacy", "PetStore", "ClothingStore", "Store", "LocalBusiness"];
46
+ type BusinessType = (typeof BUSINESS_TYPES)[number];
47
+ declare function isBusinessType(value: unknown): value is BusinessType;
48
+
49
+ interface ProductSchemaOptions {
50
+ url?: string | null;
51
+ stockId?: string | null;
52
+ seller?: Record<string, unknown> | null;
53
+ }
54
+ interface ProductOffer {
55
+ '@type': 'Offer' | 'AggregateOffer';
56
+ price?: string;
57
+ lowPrice?: string;
58
+ highPrice?: string;
59
+ offerCount?: number;
60
+ priceCurrency: string;
61
+ availability: string;
62
+ sku?: string;
63
+ }
64
+ declare function buildProductOffer(product: Product, currency: string, stockId?: string | null): ProductOffer | null;
65
+ declare function buildProductSchema(product: Product, currency: string, options?: ProductSchemaOptions): Record<string, unknown>[];
66
+
67
+ declare function buildBreadcrumbListSchema(items: BreadcrumbItem[], origin: string): Record<string, unknown>[];
44
68
 
45
69
  /** JSON-LD for a category page. */
46
70
  declare function buildCategorySchemas(category: NestedCategory, products: Product[], breadcrumbs: BreadcrumbItem[], origin: string): Record<string, unknown>[];
@@ -58,13 +82,17 @@ declare function buildOfferArticleSchema(article: OfferArticle, storeName: strin
58
82
  */
59
83
  declare function buildBlogPostSchema(article: Article, storeName: string, origin: string): Record<string, unknown>[];
60
84
 
61
- /**
62
- * JSON-LD schema.org/Organization (or LocalBusiness if there's a physical location)
63
- * for the homepage. Feeds Google's Knowledge Panel. All data comes from the
64
- * already-loaded profile.
65
- * Spec: https://schema.org/Organization · https://schema.org/LocalBusiness
66
- */
67
- declare function buildOrganizationSchema(store: Store, origin: string): Record<string, unknown>[];
85
+ interface LocationSchemaOptions {
86
+ businessType?: BusinessType | null;
87
+ locationUrl?: ((stock: Stock) => string | null | undefined) | null;
88
+ }
89
+
90
+ interface OrganizationSchemaOptions extends LocationSchemaOptions {
91
+ inLanguage?: string | null;
92
+ }
93
+ declare function buildOrganizationReference(store: Store, origin: string): Record<string, unknown>;
94
+ declare function buildOrganizationSchema(store: Store, origin: string, options?: OrganizationSchemaOptions): Record<string, unknown>[];
95
+ declare function buildLocationsSchema(store: Store, origin: string, options?: LocationSchemaOptions): Record<string, unknown>[];
68
96
 
69
97
  /** Already-resolved OG/Twitter tag values (with the consumer's defaults applied). */
70
98
  interface OgTagsInput {
@@ -82,4 +110,4 @@ declare function mapSeoMetaTags(tags: SeoMetaTag[]): Record<string, string>[];
82
110
  /** Meta tags from a `Seo` entity (description + `Seo.meta` mapping). The consumer resolves the title. */
83
111
  declare function buildEntitySeoMeta(seo: Seo | null | undefined): Record<string, string>[];
84
112
 
85
- export { type BreadcrumbItem, type OgTagsInput, buildBlogPostSchema, buildCategorySchemas, buildCollectionSchemas, buildEntitySeoMeta, buildOfferArticleSchema, buildOgTags, buildOrganizationSchema, buildProductSchema, mapSeoMetaTags, prepareOgDescription, resolveMediaUrl, resolveSiteOrigin, resolveStoreLogoUrl, stripHtml };
113
+ export { BUSINESS_TYPES, type BreadcrumbItem, type BusinessType, type LocationSchemaOptions, type OgTagsInput, type OrganizationSchemaOptions, type ProductOffer, type ProductSchemaOptions, buildBlogPostSchema, buildBreadcrumbListSchema, buildCategorySchemas, buildCollectionSchemas, buildEntitySeoMeta, buildLocationsSchema, buildOfferArticleSchema, buildOgTags, buildOrganizationReference, buildOrganizationSchema, buildProductOffer, buildProductSchema, htmlToPlainText, isBusinessType, locationAnchorId, locationSchemaId, mapSeoMetaTags, normalizeSchemaText, organizationSchemaId, prepareOgDescription, productSchemaId, resolveMediaUrl, resolveSiteOrigin, resolveStoreLogoUrl, stripHtml, webSiteSchemaId };