@zenky/storefront-vue 0.11.0 → 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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/seo/utils.ts","../../src/seo/siteOrigin.ts","../../src/seo/productSchema.ts","../../src/seo/listingSchema.ts","../../src/seo/articleSchema.ts","../../src/seo/organizationSchema.ts","../../src/seo/ogTags.ts","../../src/seo/entitySeo.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Media, Store } from '@zenky/storefront-api'\n\n/**\n * Resolves the best available URL from a Media object.\n */\nexport function resolveMediaUrl(media: Media): string | null {\n return (\n media.hd?.url ||\n media.xlarge?.url ||\n media.large?.url ||\n media.medium?.url ||\n media.placeholder?.url ||\n null\n )\n}\n\n/**\n * Resolves store logo URL, preferring square logo over rectangular.\n * Tries all available size variants so CDN assets with only hd/xlarge are found too.\n */\nexport function resolveStoreLogoUrl(store: Store | null | undefined): string | null {\n if (!store) return null\n if (store.square_logo) {\n const url = resolveMediaUrl(store.square_logo)\n if (url) return url\n }\n if (store.logo) {\n return resolveMediaUrl(store.logo)\n }\n return null\n}\n\n/**\n * Strips HTML tags from a string.\n */\nexport function stripHtml(html: string): string {\n return html.replace(/<[^>]*>/g, '').trim()\n}\n\n/**\n * Prepares a string for use as og:description or meta description:\n * strips HTML tags and truncates to maxLength (default 160).\n */\nexport function prepareOgDescription(\n text: string | null | undefined,\n maxLength = 160\n): string | null {\n if (!text) return null\n const plain = stripHtml(text)\n if (!plain) return null\n return plain.length > maxLength ? `${plain.slice(0, maxLength - 3)}...` : plain\n}\n","/**\n * Canonical public origin of the site, from `store.domain`. The fallback (request host)\n * is supplied by the consumer — the core doesn't know about `useRequestURL`.\n */\nexport function resolveSiteOrigin(\n storeDomain: string | null | undefined,\n fallbackOrigin: string\n): string {\n const domain = storeDomain?.trim()\n if (domain) {\n const host = domain.replace(/^https?:\\/\\//, '').replace(/\\/+$/, '')\n return `https://${host}`\n }\n return fallbackOrigin\n}\n","import type { Product, ProductVariant } from '@zenky/storefront-api'\n\nimport { minorToMajorString } from '../money'\nimport { resolveVariantPrice } from '../products'\nimport { resolveMediaUrl } from './utils'\n\nfunction isProductInStock(variants: ProductVariant[]): boolean {\n if (!variants.length) return false\n return variants.some((variant) => {\n const remainders = variant.remainders\n if (!remainders?.length) return true\n return remainders.some((remainder) => remainder.quantity > 0)\n })\n}\n\n/**\n * JSON-LD schema.org/Product. Google uses it for Rich Results (price, availability,\n * rating in search listings).\n * Returns an array of 0 or 1 objects — the consumer wraps it in a `<script ld+json>` tag.\n * Spec: https://schema.org/Product\n */\nexport function buildProductSchema(product: Product, currency: string): Record<string, unknown>[] {\n const variants = product.variants ?? []\n\n const firstVariant = variants[0]\n let offerBlock: Record<string, unknown> | undefined\n\n if (firstVariant) {\n const resolved = resolveVariantPrice(firstVariant)\n\n offerBlock = {\n '@type': 'Offer',\n price: minorToMajorString(resolved.price, currency),\n priceCurrency: currency,\n availability: isProductInStock(variants)\n ? 'https://schema.org/InStock'\n : 'https://schema.org/OutOfStock',\n ...(firstVariant.sku ? { sku: firstVariant.sku } : {}),\n }\n }\n\n const images = (product.images ?? []).map(resolveMediaUrl).filter((url): url is string => !!url)\n\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': 'Product',\n name: product.name,\n }\n\n if (product.description) schema.description = product.description\n if (images.length) schema.image = images\n if (offerBlock) schema.offers = offerBlock\n\n return [schema]\n}\n","import type { NestedCategory, Product, ProductsCollection } from '@zenky/storefront-api'\n\nimport { resolveMediaUrl } from './utils'\nimport type { BreadcrumbItem } from './types'\n\n/**\n * JSON-LD for a product listing page: BreadcrumbList + ItemList (first 10 products).\n * Returns an array of 0-2 JSON-LD objects. Category and collection pages differ only\n * in the list name, so both go through here.\n * Spec: https://schema.org/ItemList · https://schema.org/BreadcrumbList\n */\nfunction buildListingSchemas(\n name: string | null,\n products: Product[],\n breadcrumbs: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n const schemas: Record<string, unknown>[] = []\n\n if (breadcrumbs.length) {\n schemas.push({\n '@context': 'https://schema.org',\n '@type': 'BreadcrumbList',\n itemListElement: breadcrumbs.map((crumb, index) => ({\n '@type': 'ListItem',\n position: index + 1,\n name: crumb.label,\n ...(crumb.to ? { item: `${origin}${crumb.to}` } : {}),\n })),\n })\n }\n\n const items = products.slice(0, 10)\n if (items.length) {\n schemas.push({\n '@context': 'https://schema.org',\n '@type': 'ItemList',\n name,\n numberOfItems: items.length,\n itemListElement: items.map((product, index) => {\n const url = `${origin}/products/${product.short_id}/${product.slug || product.short_id}`\n const firstImage = product.images?.[0]\n const image = firstImage ? resolveMediaUrl(firstImage) : null\n\n const item: Record<string, unknown> = {\n '@type': 'ListItem',\n position: index + 1,\n url,\n name: product.name,\n }\n\n if (image) item.image = image\n\n return item\n }),\n })\n }\n\n return schemas\n}\n\n/** JSON-LD for a category page. */\nexport function buildCategorySchemas(\n category: NestedCategory,\n products: Product[],\n breadcrumbs: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n return buildListingSchemas(category.name, products, breadcrumbs, origin)\n}\n\n/** JSON-LD for a products collection page. */\nexport function buildCollectionSchemas(\n collection: ProductsCollection,\n products: Product[],\n breadcrumbs: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n return buildListingSchemas(collection.name, products, breadcrumbs, origin)\n}\n","import type { Article, Media, OfferArticle } from '@zenky/storefront-api'\n\nimport { prepareOgDescription, resolveMediaUrl } from './utils'\n\nfunction articleSchema(\n type: 'Article' | 'BlogPosting',\n opts: {\n title: string | null | undefined\n intro: string | null | undefined\n cover: Media | null | undefined\n storeName: string\n origin: string\n }\n): Record<string, unknown> {\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': type,\n headline: opts.title ?? '',\n author: {\n '@type': 'Organization',\n name: opts.storeName,\n url: opts.origin,\n },\n }\n\n const description = prepareOgDescription(opts.intro)\n if (description) schema.description = description\n\n const image = opts.cover ? resolveMediaUrl(opts.cover) : null\n if (image) schema.image = image\n\n return schema\n}\n\n/**\n * JSON-LD schema.org/Article for the offer page's editorial copy.\n * Spec: https://schema.org/Article\n */\nexport function buildOfferArticleSchema(\n article: OfferArticle,\n storeName: string,\n origin: string\n): Record<string, unknown>[] {\n if (!article.title) return []\n\n return [\n articleSchema('Article', {\n title: article.title,\n intro: article.intro,\n cover: article.cover,\n storeName,\n origin,\n }),\n ]\n}\n\n/**\n * JSON-LD schema.org/BlogPosting for a blog article — enables Google Rich Results.\n * Spec: https://schema.org/BlogPosting\n */\nexport function buildBlogPostSchema(\n article: Article,\n storeName: string,\n origin: string\n): Record<string, unknown>[] {\n const schema = articleSchema('BlogPosting', {\n title: article.title,\n intro: article.intro,\n cover: article.cover,\n storeName,\n origin,\n })\n\n if (article.updated_at) {\n schema.dateModified = article.updated_at\n // No separate datePublished field is available — reuse updated_at.\n schema.datePublished = article.updated_at\n }\n\n return [schema]\n}\n","import { ContactType } from '@zenky/storefront-api'\n\nimport type { Schedule, Store } from '@zenky/storefront-api'\n\nimport { getSocialLinks } from '../utils'\n\n/** Schedule.days key → schema.org DayOfWeek. */\nconst SCHEMA_DAY: Record<string, string> = {\n monday: 'Monday',\n tuesday: 'Tuesday',\n wednesday: 'Wednesday',\n thursday: 'Thursday',\n friday: 'Friday',\n saturday: 'Saturday',\n sunday: 'Sunday',\n}\n\n/**\n * Schedule (per-day `hours` string like \"10:00-22:00\") → array of schema.org/OpeningHoursSpecification.\n * Days without a recognizable interval (day off / 24 hours / empty) are skipped.\n */\nfunction buildOpeningHours(schedule: Schedule | null | undefined): Record<string, unknown>[] {\n if (!schedule) return []\n\n const result: Record<string, unknown>[] = []\n for (const key of Object.keys(SCHEMA_DAY)) {\n const day = schedule.days[key as keyof typeof schedule.days]\n const match = day?.hours?.match(/(\\d{1,2}:\\d{2}).*?(\\d{1,2}:\\d{2})/)\n if (!match) continue\n\n result.push({\n '@type': 'OpeningHoursSpecification',\n dayOfWeek: SCHEMA_DAY[key],\n opens: match[1],\n closes: match[2],\n })\n }\n\n return result\n}\n\n/**\n * JSON-LD schema.org/Organization (or LocalBusiness if there's a physical location)\n * for the homepage. Feeds Google's Knowledge Panel. All data comes from the\n * already-loaded profile.\n * Spec: https://schema.org/Organization · https://schema.org/LocalBusiness\n */\nexport function buildOrganizationSchema(store: Store, origin: string): Record<string, unknown>[] {\n const logoUrl =\n store.square_logo?.medium?.url ||\n store.square_logo?.large?.url ||\n store.logo?.medium?.url ||\n store.logo?.large?.url ||\n null\n\n const phones = (store.phones ?? []).map((p) => p.number).filter((n): n is string => !!n)\n const email = store.links?.find((c) => c.type === ContactType.Email)?.value ?? null\n const socialLinks = getSocialLinks(store.links ?? []).map((l) => l.url)\n\n const city = (store.cities ?? []).find((c) => c.is_default) ?? store.cities?.[0] ?? null\n const stock = city?.stocks?.find((st) => st.address) ?? city?.stocks?.[0] ?? null\n\n const streetAddress = stock?.address ?? null\n const geo = stock?.coordinates ?? city?.coordinates ?? null\n const openingHours = buildOpeningHours(stock?.schedule ?? city?.schedule)\n\n const isLocalBusiness = Boolean(streetAddress || geo || openingHours.length)\n\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': isLocalBusiness ? 'LocalBusiness' : 'Organization',\n name: store.name,\n url: origin,\n }\n\n if (logoUrl) {\n schema.logo = logoUrl\n schema.image = logoUrl\n }\n\n if (phones.length) schema.telephone = phones.length === 1 ? phones[0] : phones\n if (email) schema.email = email\n if (socialLinks.length) schema.sameAs = socialLinks\n\n if (streetAddress || city?.name) {\n schema.address = {\n '@type': 'PostalAddress',\n ...(streetAddress ? { streetAddress } : {}),\n ...(city?.name ? { addressLocality: city.name } : {}),\n addressCountry: 'RU',\n }\n }\n\n if (geo) {\n schema.geo = {\n '@type': 'GeoCoordinates',\n latitude: geo.latitude,\n longitude: geo.longitude,\n }\n }\n\n if (openingHours.length) schema.openingHoursSpecification = openingHours\n\n return [schema]\n}\n","/** Already-resolved OG/Twitter tag values (with the consumer's defaults applied). */\nexport interface OgTagsInput {\n title: string | null\n description?: string | null\n image?: string | null\n type?: string\n url?: string | null\n}\n\n/** Framework-neutral OG + Twitter meta records. The consumer controls head priority. */\nexport function buildOgTags(input: OgTagsInput): Record<string, string>[] {\n const tags: Record<string, string>[] = []\n\n if (input.title) {\n tags.push({ property: 'og:title', content: input.title })\n tags.push({ name: 'twitter:title', content: input.title })\n }\n\n if (input.description) {\n tags.push({ property: 'og:description', content: input.description })\n tags.push({ name: 'twitter:description', content: input.description })\n }\n\n if (input.image) {\n tags.push({ property: 'og:image', content: input.image })\n tags.push({ name: 'twitter:image', content: input.image })\n }\n\n tags.push({ property: 'og:type', content: input.type ?? 'website' })\n\n if (input.url) {\n tags.push({ property: 'og:url', content: input.url })\n }\n\n return tags\n}\n","import type { Seo, SeoMetaTag } from '@zenky/storefront-api'\n\n/** SDK `Seo.meta` tags mapped to framework-neutral head meta records. */\nexport function mapSeoMetaTags(tags: SeoMetaTag[]): Record<string, string>[] {\n return tags.map((tag) => {\n const attrs: Record<string, string> = {\n [tag.name.attribute]: tag.name.value,\n [tag.value.attribute]: tag.value.value,\n }\n\n for (const additional of tag.additional) {\n attrs[additional.attribute] = additional.value\n }\n\n return attrs\n })\n}\n\n/** Meta tags from a `Seo` entity (description + `Seo.meta` mapping). The consumer resolves the title. */\nexport function buildEntitySeoMeta(seo: Seo | null | undefined): Record<string, string>[] {\n const tags: Record<string, string>[] = []\n\n if (seo?.description) {\n tags.push({ name: 'description', content: seo.description })\n }\n\n if (seo?.meta?.length) {\n tags.push(...mapSeoMetaTags(seo.meta))\n }\n\n return tags\n}\n"]}
1
+ {"version":3,"sources":["../../src/seo/utils.ts","../../src/seo/siteOrigin.ts","../../src/seo/ids.ts","../../src/seo/businessType.ts","../../src/seo/productSchema.ts","../../src/seo/breadcrumbSchema.ts","../../src/seo/listingSchema.ts","../../src/seo/articleSchema.ts","../../src/seo/openingHours.ts","../../src/seo/locationSchema.ts","../../src/seo/organizationSchema.ts","../../src/seo/ogTags.ts","../../src/seo/entitySeo.ts"],"names":[],"mappings":";;;;;;AAKO,SAAS,gBAAgB,KAAA,EAA6B;AACzD,EAAA,OACI,KAAA,CAAM,EAAA,EAAI,GAAA,IACV,KAAA,CAAM,QAAQ,GAAA,IACd,KAAA,CAAM,KAAA,EAAO,GAAA,IACb,KAAA,CAAM,MAAA,EAAQ,GAAA,IACd,KAAA,CAAM,aAAa,GAAA,IACnB,IAAA;AAER;AAMO,SAAS,oBAAoB,KAAA,EAAgD;AAChF,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,IAAI,MAAM,WAAA,EAAa;AACnB,IAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,KAAA,CAAM,WAAW,CAAA;AAC7C,IAAA,IAAI,KAAK,OAAO,GAAA;AAAA,EACpB;AACA,EAAA,IAAI,MAAM,IAAA,EAAM;AACZ,IAAA,OAAO,eAAA,CAAgB,MAAM,IAAI,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,IAAA;AACX;AAKO,SAAS,UAAU,IAAA,EAAsB;AAC5C,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,EAAE,EAAE,IAAA,EAAK;AAC7C;AAEA,IAAM,oBAAA,GAAuB,oCAAA;AAC7B,IAAM,SAAA,GACF,oGAAA;AACJ,IAAM,OAAA,GAAU,UAAA;AAChB,IAAM,WAAA,GAAc,+BAAA;AACpB,IAAM,cAAA,GAAyC;AAAA,EAC3C,GAAA,EAAK,GAAA;AAAA,EACL,EAAA,EAAI,GAAA;AAAA,EACJ,EAAA,EAAI,GAAA;AAAA,EACJ,IAAA,EAAM,GAAA;AAAA,EACN,IAAA,EAAM,GAAA;AAAA,EACN,IAAA,EAAM,GAAA;AAAA,EACN,KAAA,EAAO,MAAA;AAAA,EACP,KAAA,EAAO,MAAA;AAAA,EACP,KAAA,EAAO,QAAA;AAAA,EACP,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ;AACZ,CAAA;AAEA,SAAS,YAAA,CAAa,QAAgB,IAAA,EAAsB;AACxD,EAAA,MAAM,KAAA,GAAQ,KAAK,WAAA,EAAY;AAC/B,EAAA,IAAI,KAAA,CAAM,UAAA,CAAW,GAAG,CAAA,EAAG;AACvB,IAAA,MAAM,OAAO,KAAA,CAAM,UAAA,CAAW,IAAI,CAAA,GAC5B,MAAA,CAAO,SAAS,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,IAClC,MAAA,CAAO,QAAA,CAAS,MAAM,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACxC,IAAA,OAAO,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA,IAAK,IAAA,GAAO,CAAA,IAAK,IAAA,IAAQ,OAAA,GAC/C,MAAA,CAAO,aAAA,CAAc,IAAI,CAAA,GACzB,MAAA;AAAA,EACV;AACA,EAAA,OAAO,cAAA,CAAe,KAAK,CAAA,IAAK,MAAA;AACpC;AAEO,SAAS,oBAAoB,KAAA,EAA0C;AAC1E,EAAA,IAAI,CAAC,OAAO,OAAO,EAAA;AACnB,EAAA,OAAO,KAAA,CAAM,QAAQ,oBAAA,EAAsB,EAAE,EAAE,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,CAAE,IAAA,EAAK;AAC7E;AAEO,SAAS,gBAAgB,IAAA,EAAyC;AACrE,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,EAAA,MAAM,OAAO,IAAA,CACR,OAAA,CAAQ,WAAW,GAAG,CAAA,CACtB,QAAQ,OAAA,EAAS,EAAE,CAAA,CACnB,OAAA,CAAQ,aAAa,CAAC,MAAA,EAAQ,SAAiB,YAAA,CAAa,MAAA,EAAQ,IAAI,CAAC,CAAA;AAC9E,EAAA,OAAO,oBAAoB,IAAI,CAAA;AACnC;AAMO,SAAS,oBAAA,CACZ,IAAA,EACA,SAAA,GAAY,GAAA,EACC;AACb,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,MAAM,KAAA,GAAQ,UAAU,IAAI,CAAA;AAC5B,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,OAAO,KAAA,CAAM,MAAA,GAAS,SAAA,GAAY,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAG,SAAA,GAAY,CAAC,CAAC,CAAA,GAAA,CAAA,GAAQ,KAAA;AAC9E;;;AC7FO,SAAS,iBAAA,CACZ,aACA,cAAA,EACM;AACN,EAAA,MAAM,MAAA,GAAS,aAAa,IAAA,EAAK;AACjC,EAAA,IAAI,MAAA,EAAQ;AACR,IAAA,MAAM,IAAA,GAAO,OAAO,OAAA,CAAQ,cAAA,EAAgB,EAAE,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAClE,IAAA,OAAO,WAAW,IAAI,CAAA,CAAA;AAAA,EAC1B;AACA,EAAA,OAAO,cAAA;AACX;;;ACdO,SAAS,qBAAqB,MAAA,EAAwB;AACzD,EAAA,OAAO,GAAG,MAAM,CAAA,cAAA,CAAA;AACpB;AAEO,SAAS,gBAAgB,MAAA,EAAwB;AACpD,EAAA,OAAO,GAAG,MAAM,CAAA,SAAA,CAAA;AACpB;AAEO,SAAS,iBAAiB,OAAA,EAAyB;AACtD,EAAA,OAAO,YAAY,OAAO,CAAA,CAAA;AAC9B;AAEO,SAAS,gBAAA,CAAiB,QAAgB,OAAA,EAAyB;AACtE,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAA,EAAK,gBAAA,CAAiB,OAAO,CAAC,CAAA,CAAA;AAClD;AAEO,SAAS,gBAAgB,UAAA,EAA4B;AACxD,EAAA,OAAO,GAAG,UAAU,CAAA,QAAA,CAAA;AACxB;;;ACdO,IAAM,cAAA,GAAiB;AAAA,EAC1B,YAAA;AAAA,EACA,kBAAA;AAAA,EACA,oBAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,cAAA;AAAA,EACA,kBAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA;AACJ;AAIA,IAAM,UAAA,GACF,0LAAA;AACJ,IAAM,YAAA,GAAe,4BAAA;AAEd,SAAS,eAAe,KAAA,EAAuC;AAClE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAa,cAAA,CAAqC,SAAS,KAAK,CAAA;AAC5F;AAEO,SAAS,mBAAA,CACZ,OACA,YAAA,EACY;AACZ,EAAA,MAAM,IAAA,GAAO,mBAAA,CAAoB,KAAA,CAAM,IAAI,CAAA;AAC3C,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAExC,EAAA,IAAI,CAAC,YAAA,EAAc,OAAO,WAAA,GAAc,YAAA,GAAe,eAAA;AACvD,EAAA,IAAI,CAAC,WAAA,IAAe,YAAA,CAAa,IAAA,CAAK,IAAI,GAAG,OAAO,eAAA;AAEpD,EAAA,OAAO,YAAA;AACX;ACdA,IAAM,QAAA,GAAW,4BAAA;AAEjB,IAAM,iBAAA,GAAuD;AAAA,EACzD,CAAC,QAAA,CAAS,KAAK,GAAG,KAAA;AAAA,EAClB,CAAC,QAAA,CAAS,IAAI,GAAG,KAAA;AAAA,EACjB,CAAC,QAAA,CAAS,QAAQ,GAAG;AACzB,CAAA;AAEA,SAAS,YAAY,OAAA,EAAkD;AACnE,EAAA,MAAM,MAAA,GAAS,iBAAiB,OAAO,CAAA;AACvC,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,OAAA,CAAQ,SAAS,CAAA;AACpD,EAAA,IAAI,CAAC,MAAA,IAAU,MAAA,GAAS,CAAA,IAAK,CAAC,UAAU,OAAO,IAAA;AAE/C,EAAA,OAAO,EAAE,OAAA,EAAS,mBAAA,EAAqB,KAAA,EAAO,QAAQ,QAAA,EAAS;AACnE;AAEO,SAAS,iBAAA,CACZ,OAAA,EACA,QAAA,EACA,OAAA,EACmB;AACnB,EAAA,MAAM,qBAAA,GAAwB,4BAA4B,OAAO,CAAA;AACjE,EAAA,MAAM,UAAU,OAAA,CAAQ,QAAA,IAAY,EAAC,EAChC,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,IACf,OAAA;AAAA,IACA,KAAA,EAAO,mBAAA,CAAoB,OAAA,EAAS,OAAO,EAAE,KAAA,GAAQ;AAAA,GACzD,CAAE,EACD,MAAA,CAAO,CAAC,EAAE,KAAA,EAAM,KAAM,QAAQ,CAAC,CAAA;AAEpC,EAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAA;AAChB,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACnB,IAAA,MAAM,SAAS,MAAA,CAAO,GAAA,CAAI,CAAC,EAAE,KAAA,OAAY,KAAK,CAAA;AAC9C,IAAA,OAAO;AAAA,MACH,OAAA,EAAS,gBAAA;AAAA,MACT,UAAU,kBAAA,CAAmB,IAAA,CAAK,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAA;AAAA,MAC1D,WAAW,kBAAA,CAAmB,IAAA,CAAK,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAA;AAAA,MAC3D,YAAY,MAAA,CAAO,MAAA;AAAA,MACnB,aAAA,EAAe,QAAA;AAAA,MACf,YAAA,EAAc;AAAA,KAClB;AAAA,EACJ;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA;AAC1B,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,OAAA;AAAA,IACT,KAAA,EAAO,kBAAA,CAAmB,KAAA,CAAM,KAAA,EAAO,QAAQ,CAAA;AAAA,IAC/C,aAAA,EAAe,QAAA;AAAA,IACf,YAAA,EAAc,QAAA;AAAA,IACd,GAAI,GAAA,GAAM,EAAE,GAAA,KAAQ;AAAC,GACzB;AACJ;AAEO,SAAS,kBAAA,CACZ,OAAA,EACA,QAAA,EACA,OAAA,GAAgC,EAAC,EACR;AACzB,EAAA,MAAM,MAAA,GAAkC;AAAA,IACpC,UAAA,EAAY,oBAAA;AAAA,IACZ,OAAA,EAAS;AAAA,GACb;AAEA,EAAA,IAAI,QAAQ,GAAA,EAAK;AACb,IAAA,MAAA,CAAO,KAAK,CAAA,GAAI,eAAA,CAAgB,OAAA,CAAQ,GAAG,CAAA;AAC3C,IAAA,MAAA,CAAO,MAAM,OAAA,CAAQ,GAAA;AAAA,EACzB;AAEA,EAAA,MAAA,CAAO,IAAA,GAAO,mBAAA,CAAoB,OAAA,CAAQ,IAAI,CAAA;AAE9C,EAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,OAAA,CAAQ,WAAW,CAAA;AACvD,EAAA,IAAI,WAAA,SAAoB,WAAA,GAAc,WAAA;AAEtC,EAAA,MAAM,MAAA,GAAA,CAAU,OAAA,CAAQ,MAAA,IAAU,EAAC,EAAG,GAAA,CAAI,eAAe,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAuB,CAAC,CAAC,GAAG,CAAA;AAC/F,EAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,KAAA,GAAQ,MAAA;AAElC,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,EAAC;AACtC,EAAA,MAAM,MAAM,QAAA,CAAS,MAAA,KAAW,IAAI,QAAA,CAAS,CAAC,GAAG,GAAA,GAAM,IAAA;AACvD,EAAA,IAAI,GAAA,SAAY,GAAA,GAAM,GAAA;AAEtB,EAAA,MAAM,WAAW,mBAAA,CAAoB,OAAA,CAAQ,UAAA,GAAa,CAAC,GAAG,IAAI,CAAA;AAClE,EAAA,IAAI,QAAA,SAAiB,QAAA,GAAW,QAAA;AAEhC,EAAA,MAAM,MAAA,GAAS,YAAY,OAAO,CAAA;AAClC,EAAA,IAAI,MAAA,SAAe,MAAA,GAAS,MAAA;AAE5B,EAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,OAAA,EAAS,QAAA,EAAU,QAAQ,OAAO,CAAA;AAClE,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,MAAA,CAAO,MAAA,GAAS;AAAA,MACZ,GAAG,KAAA;AAAA,MACH,GAAI,QAAQ,GAAA,GAAM,EAAE,KAAK,OAAA,CAAQ,GAAA,KAAQ,EAAC;AAAA,MAC1C,GAAI,QAAQ,MAAA,GAAS,EAAE,QAAQ,OAAA,CAAQ,MAAA,KAAW;AAAC,KACvD;AAAA,EACJ;AAEA,EAAA,OAAO,CAAC,MAAM,CAAA;AAClB;;;ACzHA,SAAS,aAAA,CAAc,MAAc,MAAA,EAAwB;AACzD,EAAA,OAAO,eAAA,CAAgB,KAAK,IAAI,CAAA,GAAI,OAAO,CAAA,EAAG,MAAM,GAAG,IAAI,CAAA,CAAA;AAC/D;AAEO,SAAS,yBAAA,CACZ,OACA,MAAA,EACyB;AACzB,EAAA,MAAM,MAAA,GAAS,MACV,GAAA,CAAI,CAAC,UAAU,EAAE,IAAA,EAAM,oBAAoB,IAAA,CAAK,KAAK,GAAG,EAAA,EAAI,IAAA,CAAK,IAAG,CAAE,CAAA,CACtE,OAAO,CAAC,KAAA,KAAU,MAAM,IAAI,CAAA;AAEjC,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,EAAC;AAE5B,EAAA,OAAO;AAAA,IACH;AAAA,MACI,UAAA,EAAY,oBAAA;AAAA,MACZ,OAAA,EAAS,gBAAA;AAAA,MACT,eAAA,EAAiB,MAAA,CAAO,GAAA,CAAI,CAAC,OAAO,KAAA,MAAW;AAAA,QAC3C,OAAA,EAAS,UAAA;AAAA,QACT,UAAU,KAAA,GAAQ,CAAA;AAAA,QAClB,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,GAAI,KAAA,CAAM,EAAA,GAAK,EAAE,IAAA,EAAM,aAAA,CAAc,KAAA,CAAM,EAAA,EAAI,MAAM,CAAA,EAAE,GAAI;AAAC,OAChE,CAAE;AAAA;AACN,GACJ;AACJ;;;ACjBA,SAAS,mBAAA,CACL,IAAA,EACA,QAAA,EACA,WAAA,EACA,MAAA,EACyB;AACzB,EAAA,MAAM,OAAA,GAAU,yBAAA,CAA0B,WAAA,EAAa,MAAM,CAAA;AAE7D,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAClC,EAAA,IAAI,MAAM,MAAA,EAAQ;AACd,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACT,UAAA,EAAY,oBAAA;AAAA,MACZ,OAAA,EAAS,UAAA;AAAA,MACT,IAAA;AAAA,MACA,eAAe,KAAA,CAAM,MAAA;AAAA,MACrB,eAAA,EAAiB,KAAA,CAAM,GAAA,CAAI,CAAC,SAAS,KAAA,KAAU;AAC3C,QAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,CAAA,UAAA,EAAa,OAAA,CAAQ,QAAQ,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,QAAQ,CAAA,CAAA;AACtF,QAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA;AACrC,QAAA,MAAM,KAAA,GAAQ,UAAA,GAAa,eAAA,CAAgB,UAAU,CAAA,GAAI,IAAA;AAEzD,QAAA,MAAM,IAAA,GAAgC;AAAA,UAClC,OAAA,EAAS,UAAA;AAAA,UACT,UAAU,KAAA,GAAQ,CAAA;AAAA,UAClB,GAAA;AAAA,UACA,IAAA,EAAM,mBAAA,CAAoB,OAAA,CAAQ,IAAI;AAAA,SAC1C;AAEA,QAAA,IAAI,KAAA,OAAY,KAAA,GAAQ,KAAA;AAExB,QAAA,OAAO,IAAA;AAAA,MACX,CAAC;AAAA,KACJ,CAAA;AAAA,EACL;AAEA,EAAA,OAAO,OAAA;AACX;AAGO,SAAS,oBAAA,CACZ,QAAA,EACA,QAAA,EACA,WAAA,EACA,MAAA,EACyB;AACzB,EAAA,OAAO,mBAAA,CAAoB,QAAA,CAAS,IAAA,EAAM,QAAA,EAAU,aAAa,MAAM,CAAA;AAC3E;AAGO,SAAS,sBAAA,CACZ,UAAA,EACA,QAAA,EACA,WAAA,EACA,MAAA,EACyB;AACzB,EAAA,OAAO,mBAAA,CAAoB,UAAA,CAAW,IAAA,EAAM,QAAA,EAAU,aAAa,MAAM,CAAA;AAC7E;;;AC/DA,SAAS,aAAA,CACL,MACA,IAAA,EAOuB;AACvB,EAAA,MAAM,MAAA,GAAkC;AAAA,IACpC,UAAA,EAAY,oBAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA,IACT,QAAA,EAAU,KAAK,KAAA,IAAS,EAAA;AAAA,IACxB,MAAA,EAAQ;AAAA,MACJ,OAAA,EAAS,cAAA;AAAA,MACT,MAAM,IAAA,CAAK,SAAA;AAAA,MACX,KAAK,IAAA,CAAK;AAAA;AACd,GACJ;AAEA,EAAA,MAAM,WAAA,GAAc,oBAAA,CAAqB,IAAA,CAAK,KAAK,CAAA;AACnD,EAAA,IAAI,WAAA,SAAoB,WAAA,GAAc,WAAA;AAEtC,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,KAAK,CAAA,GAAI,IAAA;AACzD,EAAA,IAAI,KAAA,SAAc,KAAA,GAAQ,KAAA;AAE1B,EAAA,OAAO,MAAA;AACX;AAMO,SAAS,uBAAA,CACZ,OAAA,EACA,SAAA,EACA,MAAA,EACyB;AACzB,EAAA,IAAI,CAAC,OAAA,CAAQ,KAAA,EAAO,OAAO,EAAC;AAE5B,EAAA,OAAO;AAAA,IACH,cAAc,SAAA,EAAW;AAAA,MACrB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,SAAA;AAAA,MACA;AAAA,KACH;AAAA,GACL;AACJ;AAMO,SAAS,mBAAA,CACZ,OAAA,EACA,SAAA,EACA,MAAA,EACyB;AACzB,EAAA,MAAM,MAAA,GAAS,cAAc,aAAA,EAAe;AAAA,IACxC,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,SAAA;AAAA,IACA;AAAA,GACH,CAAA;AAED,EAAA,IAAI,QAAQ,UAAA,EAAY;AACpB,IAAA,MAAA,CAAO,eAAe,OAAA,CAAQ,UAAA;AAE9B,IAAA,MAAA,CAAO,gBAAgB,OAAA,CAAQ,UAAA;AAAA,EACnC;AAEA,EAAA,OAAO,CAAC,MAAM,CAAA;AAClB;;;AC9EA,IAAM,WAAA,GAAc;AAAA,EAChB,CAAC,UAAU,QAAQ,CAAA;AAAA,EACnB,CAAC,WAAW,SAAS,CAAA;AAAA,EACrB,CAAC,aAAa,WAAW,CAAA;AAAA,EACzB,CAAC,YAAY,UAAU,CAAA;AAAA,EACvB,CAAC,UAAU,QAAQ,CAAA;AAAA,EACnB,CAAC,YAAY,UAAU,CAAA;AAAA,EACvB,CAAC,UAAU,QAAQ;AACvB,CAAA;AAEA,IAAM,eAAA,GAAkB,sEAAA;AACxB,IAAM,KAAA,GAAQ,yCAAA;AAQd,SAAS,UAAA,CAAW,OAAe,OAAA,EAAgC;AAC/D,EAAA,MAAM,IAAA,GAAO,OAAO,KAAK,CAAA;AACzB,EAAA,MAAM,MAAA,GAAS,OAAO,OAAO,CAAA;AAC7B,EAAA,IAAI,IAAA,GAAO,MAAM,MAAA,GAAS,EAAA,IAAO,SAAS,EAAA,IAAM,MAAA,GAAS,GAAI,OAAO,IAAA;AACpE,EAAA,IAAI,IAAA,KAAS,IAAI,OAAO,OAAA;AACxB,EAAA,OAAO,CAAA,EAAG,OAAO,IAAI,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACtD;AAEA,SAAS,YAAY,KAAA,EAAmC;AACpD,EAAA,IAAI,eAAA,CAAgB,KAAK,KAAK,CAAA,SAAU,CAAC,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AAE3D,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,GAAG,QAAA,EAAU,UAAA,EAAY,SAAA,EAAW,WAAW,CAAA,IAAK,KAAA,CAAM,QAAA,CAAS,KAAK,CAAA,EAAG;AAClF,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,QAAA,IAAY,EAAA,EAAI,cAAc,EAAE,CAAA;AACzD,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,SAAA,IAAa,EAAA,EAAI,eAAe,EAAE,CAAA;AAC5D,IAAA,IAAI,SAAS,MAAA,EAAQ,MAAA,CAAO,KAAK,CAAC,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,EACpD;AACA,EAAA,OAAO,MAAA;AACX;AAEO,SAAS,+BACZ,QAAA,EACyB;AACzB,EAAA,IAAI,CAAC,QAAA,EAAU,IAAA,EAAM,OAAO,EAAC;AAE7B,EAAA,MAAM,SAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,SAAS,CAAA,IAAK,WAAA,EAAa;AACxC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA,EAAG,KAAA;AAClC,IAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,CAAA,IAAK,WAAA,CAAY,KAAK,CAAA,EAAG;AAC9C,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,IAAA,KAAS,KAAK,KAAA,KAAU,KAAA,IAAS,IAAA,CAAK,MAAA,KAAW,MAAM,CAAA;AAClF,MAAA,IAAI,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA;AAAA,WAC/B,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,QAAQ,IAAA,EAAM,CAAC,SAAS,CAAA,EAAG,CAAA;AAAA,IACzD;AAAA,EACJ;AAEA,EAAA,OAAO,OAAO,GAAA,CAAI,CAAC,EAAE,KAAA,EAAO,MAAA,EAAQ,MAAK,MAAO;AAAA,IAC5C,OAAA,EAAS,2BAAA;AAAA,IACT,SAAA,EAAW,IAAA;AAAA,IACX,KAAA;AAAA,IACA;AAAA,GACJ,CAAE,CAAA;AACN;;;ACpDA,SAAS,aAAa,KAAA,EAAuB;AACzC,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,qBAAA,EAAuB,MAAM,CAAA;AACtD;AAEA,SAAS,sBAAA,CAAuB,SAAoC,QAAA,EAA0B;AAC1F,EAAA,MAAM,MAAA,GAAS,oBAAoB,OAAO,CAAA;AAC1C,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,QAAA,EAAU,OAAO,MAAA;AAEjC,EAAA,MAAM,IAAA,GAAO,CAAA,kDAAA,EAAuB,YAAA,CAAa,QAAQ,CAAC,CAAA,CAAA;AAC1D,EAAA,MAAM,aAAa,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,IAAI,aAAa,IAAI,CAAA;AACvD,EAAA,MAAM,aAAa,IAAI,MAAA,CAAO,CAAA,SAAA,EAAY,IAAI,KAAK,IAAI,CAAA;AACvD,EAAA,OAAO,MAAA,CAAO,QAAQ,UAAA,EAAY,EAAE,EAAE,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,IAAK,MAAA;AACrE;AAEA,SAAS,eAAe,WAAA,EAAyE;AAC7F,EAAA,IAAI,CAAC,aAAa,OAAO,KAAA;AAEzB,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,WAAA;AAChC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,EAAG,OAAO,KAAA;AAEtE,EAAA,OAAO,QAAA,KAAa,KAAK,SAAA,KAAc,CAAA;AAC3C;AAEA,SAAS,iBAAA,CACL,KAAA,EACA,IAAA,EACA,KAAA,EACA,QACA,OAAA,EAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAC9C,EAAA,MAAM,aAAA,GAAgB,sBAAA,CAAuB,KAAA,CAAM,OAAA,EAAS,QAAQ,CAAA;AACpE,EAAA,IAAI,CAAC,eAAe,OAAO,IAAA;AAE3B,EAAA,MAAM,IAAA,GAAgC;AAAA,IAClC,OAAA,EAAS,mBAAA,CAAoB,KAAA,EAAO,OAAA,CAAQ,YAAY,CAAA;AAAA,IACxD,KAAA,EAAO,gBAAA,CAAiB,MAAA,EAAQ,KAAA,CAAM,EAAE,CAAA;AAAA,IACxC,MAAM,mBAAA,CAAoB,KAAA,CAAM,IAAI,CAAA,IAAK,mBAAA,CAAoB,MAAM,IAAI;AAAA,GAC3E;AAEA,EAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,KAAA,CAAM,WAAW,CAAA;AACrD,EAAA,IAAI,WAAA,OAAkB,WAAA,GAAc,WAAA;AAEpC,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,WAAA,GAAc,KAAK,CAAA;AACvC,EAAA,IAAI,GAAA,OAAU,GAAA,GAAM,GAAA;AAEpB,EAAA,MAAM,KAAA,GAAQ,oBAAoB,KAAK,CAAA;AACvC,EAAA,IAAI,KAAA,OAAY,KAAA,GAAQ,KAAA;AAExB,EAAA,MAAM,SAAA,GACF,KAAA,CAAM,MAAA,GAAS,CAAC,GAAG,MAAA,IAAU,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,EAAG,MAAA,IAAU,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA,EAAG,MAAA;AAChF,EAAA,IAAI,SAAA,OAAgB,SAAA,GAAY,SAAA;AAEhC,EAAA,IAAA,CAAK,OAAA,GAAU;AAAA,IACX,OAAA,EAAS,eAAA;AAAA,IACT,aAAA;AAAA,IACA,GAAI,QAAA,GAAW,EAAE,eAAA,EAAiB,QAAA,KAAa,EAAC;AAAA,IAChD,cAAA,EAAgB,KAAA,CAAM,QAAA,EAAU,OAAA,IAAW;AAAA,GAC/C;AAEA,EAAA,IAAI,cAAA,CAAe,KAAA,CAAM,WAAW,CAAA,EAAG;AACnC,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,KAAA,CAAM,WAAA;AACtC,IAAA,IAAA,CAAK,GAAA,GAAM,EAAE,OAAA,EAAS,gBAAA,EAAkB,UAAU,SAAA,EAAU;AAC5D,IAAA,IAAA,CAAK,MAAA,GAAS,CAAA,2BAAA,EAA8B,SAAS,CAAA,CAAA,EAAI,QAAQ,CAAA,WAAA,CAAA;AAAA,EACrE;AAEA,EAAA,MAAM,YAAA,GAAe,8BAAA,CAA+B,KAAA,CAAM,QAAQ,CAAA;AAClE,EAAA,IAAI,YAAA,CAAa,MAAA,EAAQ,IAAA,CAAK,yBAAA,GAA4B,YAAA;AAE1D,EAAA,IAAA,CAAK,kBAAA,GAAqB,EAAE,KAAA,EAAO,oBAAA,CAAqB,MAAM,CAAA,EAAE;AAEhE,EAAA,OAAO,IAAA;AACX;AAEO,SAAS,kBAAA,CACZ,KAAA,EACA,MAAA,EACA,OAAA,GAAiC,EAAC,EACT;AACzB,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,QAAmC,EAAC;AAE1C,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,MAAA,IAAU,EAAC,EAAG;AACnC,IAAA,KAAA,MAAW,KAAA,IAAS,IAAA,CAAK,MAAA,IAAU,EAAC,EAAG;AACnC,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EAAG;AAExB,MAAA,MAAM,OAAO,iBAAA,CAAkB,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,QAAQ,OAAO,CAAA;AAClE,MAAA,IAAI,CAAC,IAAA,EAAM;AAEX,MAAA,IAAA,CAAK,GAAA,CAAI,MAAM,EAAE,CAAA;AACjB,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACnB;AAAA,EACJ;AAEA,EAAA,OAAO,KAAA;AACX;;;AChGA,SAAS,OAAO,MAAA,EAA4B;AACxC,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,OAAO,MAAA,CAAO,OAAO,CAAC,CAAC,CAAA;AAC9C;AAEO,SAAS,0BAAA,CAA2B,OAAc,MAAA,EAAyC;AAC9F,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,cAAA;AAAA,IACT,KAAA,EAAO,qBAAqB,MAAM,CAAA;AAAA,IAClC,IAAA,EAAM,mBAAA,CAAoB,KAAA,CAAM,IAAI,CAAA;AAAA,IACpC,GAAA,EAAK,GAAG,MAAM,CAAA,CAAA;AAAA,GAClB;AACJ;AAEA,SAAS,qBAAA,CAAsB,OAAc,MAAA,EAAyC;AAClF,EAAA,MAAM,IAAA,GAAO,0BAAA,CAA2B,KAAA,EAAO,MAAM,CAAA;AAErD,EAAA,MAAM,IAAA,GAAO,oBAAoB,KAAK,CAAA;AACtC,EAAA,IAAI,IAAA,OAAW,IAAA,GAAO,IAAA;AAEtB,EAAA,MAAM,MAAA,GAAS,MAAA,CAAA,CAAQ,KAAA,CAAM,MAAA,IAAU,EAAC,EAAG,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,CAAC,CAAA;AACvE,EAAA,IAAI,MAAA,CAAO,QAAQ,IAAA,CAAK,SAAA,GAAY,OAAO,MAAA,KAAW,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA,GAAI,MAAA;AAEtE,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,KAAA,IAAS,EAAE,CAAA;AAC5C,EAAA,IAAI,KAAA,OAAY,KAAA,GAAQ,KAAA;AAExB,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,cAAA,CAAe,KAAA,CAAM,KAAA,IAAS,EAAE,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,GAAG,CAAC,CAAA;AAC/E,EAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,MAAA,GAAS,MAAA;AAEjC,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,IAAU,EAAC;AAChC,EAAA,MAAM,QAAA,GAAW,OAAO,MAAA,KAAW,CAAA,GAAI,oBAAoB,MAAA,CAAO,CAAC,CAAA,EAAG,IAAI,CAAA,GAAI,EAAA;AAC9E,EAAA,IAAI,QAAA,EAAU;AACV,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACX,OAAA,EAAS,eAAA;AAAA,MACT,eAAA,EAAiB,QAAA;AAAA,MACjB,cAAA,EAAgB,KAAA,CAAM,QAAA,EAAU,OAAA,IAAW;AAAA,KAC/C;AAAA,EACJ;AAEA,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,gBAAA,CACL,KAAA,EACA,MAAA,EACA,UAAA,EACuB;AACvB,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,SAAA;AAAA,IACT,KAAA,EAAO,gBAAgB,MAAM,CAAA;AAAA,IAC7B,GAAA,EAAK,GAAG,MAAM,CAAA,CAAA,CAAA;AAAA,IACd,IAAA,EAAM,mBAAA,CAAoB,KAAA,CAAM,IAAI,CAAA;AAAA,IACpC,GAAI,UAAA,GAAa,EAAE,UAAA,KAAe,EAAC;AAAA,IACnC,SAAA,EAAW,EAAE,KAAA,EAAO,oBAAA,CAAqB,MAAM,CAAA;AAAE,GACrD;AACJ;AAEO,SAAS,uBAAA,CACZ,KAAA,EACA,MAAA,EACA,OAAA,GAAqC,EAAC,EACb;AACzB,EAAA,OAAO;AAAA,IACH;AAAA,MACI,UAAA,EAAY,oBAAA;AAAA,MACZ,QAAA,EAAU;AAAA,QACN,qBAAA,CAAsB,OAAO,MAAM,CAAA;AAAA,QACnC,gBAAA,CAAiB,KAAA,EAAO,MAAA,EAAQ,OAAA,CAAQ,UAAU,CAAA;AAAA,QAClD,GAAG,kBAAA,CAAmB,KAAA,EAAO,MAAA,EAAQ,OAAO;AAAA;AAChD;AACJ,GACJ;AACJ;AAEO,SAAS,oBAAA,CACZ,KAAA,EACA,MAAA,EACA,OAAA,GAAiC,EAAC,EACT;AACzB,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,KAAA,EAAO,MAAA,EAAQ,OAAO,CAAA;AAC3D,EAAA,IAAI,CAAC,SAAA,CAAU,MAAA,EAAQ,OAAO,EAAC;AAE/B,EAAA,OAAO;AAAA,IACH;AAAA,MACI,UAAA,EAAY,oBAAA;AAAA,MACZ,UAAU,CAAC,qBAAA,CAAsB,OAAO,MAAM,CAAA,EAAG,GAAG,SAAS;AAAA;AACjE,GACJ;AACJ;;;ACxFO,SAAS,YAAY,KAAA,EAA8C;AACtE,EAAA,MAAM,OAAiC,EAAC;AAExC,EAAA,IAAI,MAAM,KAAA,EAAO;AACb,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,YAAY,OAAA,EAAS,KAAA,CAAM,OAAO,CAAA;AACxD,IAAA,IAAA,CAAK,KAAK,EAAE,IAAA,EAAM,iBAAiB,OAAA,EAAS,KAAA,CAAM,OAAO,CAAA;AAAA,EAC7D;AAEA,EAAA,IAAI,MAAM,WAAA,EAAa;AACnB,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,kBAAkB,OAAA,EAAS,KAAA,CAAM,aAAa,CAAA;AACpE,IAAA,IAAA,CAAK,KAAK,EAAE,IAAA,EAAM,uBAAuB,OAAA,EAAS,KAAA,CAAM,aAAa,CAAA;AAAA,EACzE;AAEA,EAAA,IAAI,MAAM,KAAA,EAAO;AACb,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,YAAY,OAAA,EAAS,KAAA,CAAM,OAAO,CAAA;AACxD,IAAA,IAAA,CAAK,KAAK,EAAE,IAAA,EAAM,iBAAiB,OAAA,EAAS,KAAA,CAAM,OAAO,CAAA;AAAA,EAC7D;AAEA,EAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,SAAA,EAAW,SAAS,KAAA,CAAM,IAAA,IAAQ,WAAW,CAAA;AAEnE,EAAA,IAAI,MAAM,GAAA,EAAK;AACX,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,UAAU,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA;AAAA,EACxD;AAEA,EAAA,OAAO,IAAA;AACX;;;AChCO,SAAS,eAAe,IAAA,EAA8C;AACzE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AACrB,IAAA,MAAM,KAAA,GAAgC;AAAA,MAClC,CAAC,GAAA,CAAI,IAAA,CAAK,SAAS,GAAG,IAAI,IAAA,CAAK,KAAA;AAAA,MAC/B,CAAC,GAAA,CAAI,KAAA,CAAM,SAAS,GAAG,IAAI,KAAA,CAAM;AAAA,KACrC;AAEA,IAAA,KAAA,MAAW,UAAA,IAAc,IAAI,UAAA,EAAY;AACrC,MAAA,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA,GAAI,UAAA,CAAW,KAAA;AAAA,IAC7C;AAEA,IAAA,OAAO,KAAA;AAAA,EACX,CAAC,CAAA;AACL;AAGO,SAAS,mBAAmB,GAAA,EAAuD;AACtF,EAAA,MAAM,OAAiC,EAAC;AAExC,EAAA,IAAI,KAAK,WAAA,EAAa;AAClB,IAAA,IAAA,CAAK,KAAK,EAAE,IAAA,EAAM,eAAe,OAAA,EAAS,GAAA,CAAI,aAAa,CAAA;AAAA,EAC/D;AAEA,EAAA,IAAI,GAAA,EAAK,MAAM,MAAA,EAAQ;AACnB,IAAA,IAAA,CAAK,IAAA,CAAK,GAAG,cAAA,CAAe,GAAA,CAAI,IAAI,CAAC,CAAA;AAAA,EACzC;AAEA,EAAA,OAAO,IAAA;AACX","file":"index.js","sourcesContent":["import type { Media, Store } from '@zenky/storefront-api'\n\n/**\n * Resolves the best available URL from a Media object.\n */\nexport function resolveMediaUrl(media: Media): string | null {\n return (\n media.hd?.url ||\n media.xlarge?.url ||\n media.large?.url ||\n media.medium?.url ||\n media.placeholder?.url ||\n null\n )\n}\n\n/**\n * Resolves store logo URL, preferring square logo over rectangular.\n * Tries all available size variants so CDN assets with only hd/xlarge are found too.\n */\nexport function resolveStoreLogoUrl(store: Store | null | undefined): string | null {\n if (!store) return null\n if (store.square_logo) {\n const url = resolveMediaUrl(store.square_logo)\n if (url) return url\n }\n if (store.logo) {\n return resolveMediaUrl(store.logo)\n }\n return null\n}\n\n/**\n * Strips HTML tags from a string.\n */\nexport function stripHtml(html: string): string {\n return html.replace(/<[^>]*>/g, '').trim()\n}\n\nconst INVISIBLE_CHARACTERS = /[\\u00ad\\u200b-\\u200d\\u2060\\ufeff]/g\nconst BLOCK_TAG =\n /<\\/?(?:p|div|br|li|ul|ol|h[1-6]|tr|td|th|table|blockquote|section|article|header|footer)\\b[^>]*>/gi\nconst ANY_TAG = /<[^>]*>/g\nconst HTML_ENTITY = /&(#x[0-9a-f]+|#\\d+|[a-z]+);/gi\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n laquo: '«',\n raquo: '»',\n ndash: '–',\n mdash: '—',\n hellip: '…',\n}\n\nfunction decodeEntity(entity: string, body: string): string {\n const lower = body.toLowerCase()\n if (lower.startsWith('#')) {\n const code = lower.startsWith('#x')\n ? Number.parseInt(lower.slice(2), 16)\n : Number.parseInt(lower.slice(1), 10)\n return Number.isInteger(code) && code > 0 && code <= 0x10ffff\n ? String.fromCodePoint(code)\n : entity\n }\n return NAMED_ENTITIES[lower] ?? entity\n}\n\nexport function normalizeSchemaText(value: string | null | undefined): string {\n if (!value) return ''\n return value.replace(INVISIBLE_CHARACTERS, '').replace(/\\s+/g, ' ').trim()\n}\n\nexport function htmlToPlainText(html: string | null | undefined): string {\n if (!html) return ''\n const text = html\n .replace(BLOCK_TAG, ' ')\n .replace(ANY_TAG, '')\n .replace(HTML_ENTITY, (entity, body: string) => decodeEntity(entity, body))\n return normalizeSchemaText(text)\n}\n\n/**\n * Prepares a string for use as og:description or meta description:\n * strips HTML tags and truncates to maxLength (default 160).\n */\nexport function prepareOgDescription(\n text: string | null | undefined,\n maxLength = 160\n): string | null {\n if (!text) return null\n const plain = stripHtml(text)\n if (!plain) return null\n return plain.length > maxLength ? `${plain.slice(0, maxLength - 3)}...` : plain\n}\n","/**\n * Canonical public origin of the site, from `store.domain`. The fallback (request host)\n * is supplied by the consumer — the core doesn't know about `useRequestURL`.\n */\nexport function resolveSiteOrigin(\n storeDomain: string | null | undefined,\n fallbackOrigin: string\n): string {\n const domain = storeDomain?.trim()\n if (domain) {\n const host = domain.replace(/^https?:\\/\\//, '').replace(/\\/+$/, '')\n return `https://${host}`\n }\n return fallbackOrigin\n}\n","export function organizationSchemaId(origin: string): string {\n return `${origin}/#organization`\n}\n\nexport function webSiteSchemaId(origin: string): string {\n return `${origin}/#website`\n}\n\nexport function locationAnchorId(stockId: string): string {\n return `location-${stockId}`\n}\n\nexport function locationSchemaId(origin: string, stockId: string): string {\n return `${origin}/#${locationAnchorId(stockId)}`\n}\n\nexport function productSchemaId(productUrl: string): string {\n return `${productUrl}#product`\n}\n","import type { Stock } from '@zenky/storefront-api'\n\nimport { normalizeSchemaText } from './utils'\n\nexport const BUSINESS_TYPES = [\n 'Restaurant',\n 'CafeOrCoffeeShop',\n 'FastFoodRestaurant',\n 'Bakery',\n 'BarOrPub',\n 'GroceryStore',\n 'ConvenienceStore',\n 'Florist',\n 'Pharmacy',\n 'PetStore',\n 'ClothingStore',\n 'Store',\n 'LocalBusiness',\n] as const\n\nexport type BusinessType = (typeof BUSINESS_TYPES)[number]\n\nconst FOOD_VENUE =\n /(?:^|[^\\p{L}])(?:ресторан\\p{L}*|кафе|кофейн\\p{L}*|бистро|пиццери\\p{L}*|бар(?:а|у|ом|е|ы|ов)?|паб(?:а|у|ом|е|ы|ов)?|restaurants?|caf[eé]s?|coffee|bistro|pizzeria|bars?|pubs?)(?!\\p{L})/iu\nconst PICKUP_POINT = /самовывоз|выдач|pick-?up/iu\n\nexport function isBusinessType(value: unknown): value is BusinessType {\n return typeof value === 'string' && (BUSINESS_TYPES as readonly string[]).includes(value)\n}\n\nexport function resolveLocationType(\n stock: Pick<Stock, 'name'>,\n businessType?: BusinessType | null\n): BusinessType {\n const name = normalizeSchemaText(stock.name)\n const isFoodVenue = FOOD_VENUE.test(name)\n\n if (!businessType) return isFoodVenue ? 'Restaurant' : 'LocalBusiness'\n if (!isFoodVenue && PICKUP_POINT.test(name)) return 'LocalBusiness'\n\n return businessType\n}\n","import { UnitType } from '@zenky/storefront-api'\n\nimport type { Product } from '@zenky/storefront-api'\n\nimport { minorToMajorString } from '../money'\nimport { getProductWeight } from '../products/formatWeight'\nimport { getRequiredModifiersMinCost, resolveVariantPrice } from '../products/useProductPricing'\nimport { productSchemaId } from './ids'\nimport { htmlToPlainText, normalizeSchemaText, resolveMediaUrl } from './utils'\n\nexport interface ProductSchemaOptions {\n url?: string | null\n stockId?: string | null\n seller?: Record<string, unknown> | null\n}\n\nexport interface ProductOffer {\n '@type': 'Offer' | 'AggregateOffer'\n price?: string\n lowPrice?: string\n highPrice?: string\n offerCount?: number\n priceCurrency: string\n availability: string\n sku?: string\n}\n\nconst IN_STOCK = 'https://schema.org/InStock'\n\nconst WEIGHT_UNIT_CODES: Partial<Record<UnitType, string>> = {\n [UnitType.Piece]: 'GRM',\n [UnitType.Gram]: 'GRM',\n [UnitType.Kilogram]: 'KGM',\n}\n\nfunction buildWeight(product: Product): Record<string, unknown> | null {\n const weight = getProductWeight(product)\n const unitCode = WEIGHT_UNIT_CODES[product.unit_type]\n if (!weight || weight < 0 || !unitCode) return null\n\n return { '@type': 'QuantitativeValue', value: weight, unitCode }\n}\n\nexport function buildProductOffer(\n product: Product,\n currency: string,\n stockId?: string | null\n): ProductOffer | null {\n const requiredModifiersCost = getRequiredModifiersMinCost(product)\n const priced = (product.variants ?? [])\n .map((variant) => ({\n variant,\n price: resolveVariantPrice(variant, stockId).price + requiredModifiersCost,\n }))\n .filter(({ price }) => price > 0)\n\n const [first] = priced\n if (!first) return null\n\n if (priced.length > 1) {\n const prices = priced.map(({ price }) => price)\n return {\n '@type': 'AggregateOffer',\n lowPrice: minorToMajorString(Math.min(...prices), currency),\n highPrice: minorToMajorString(Math.max(...prices), currency),\n offerCount: priced.length,\n priceCurrency: currency,\n availability: IN_STOCK,\n }\n }\n\n const sku = first.variant.sku\n return {\n '@type': 'Offer',\n price: minorToMajorString(first.price, currency),\n priceCurrency: currency,\n availability: IN_STOCK,\n ...(sku ? { sku } : {}),\n }\n}\n\nexport function buildProductSchema(\n product: Product,\n currency: string,\n options: ProductSchemaOptions = {}\n): Record<string, unknown>[] {\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': 'Product',\n }\n\n if (options.url) {\n schema['@id'] = productSchemaId(options.url)\n schema.url = options.url\n }\n\n schema.name = normalizeSchemaText(product.name)\n\n const description = htmlToPlainText(product.description)\n if (description) schema.description = description\n\n const images = (product.images ?? []).map(resolveMediaUrl).filter((url): url is string => !!url)\n if (images.length) schema.image = images\n\n const variants = product.variants ?? []\n const sku = variants.length === 1 ? variants[0]?.sku : null\n if (sku) schema.sku = sku\n\n const category = normalizeSchemaText(product.categories?.[0]?.name)\n if (category) schema.category = category\n\n const weight = buildWeight(product)\n if (weight) schema.weight = weight\n\n const offer = buildProductOffer(product, currency, options.stockId)\n if (offer) {\n schema.offers = {\n ...offer,\n ...(options.url ? { url: options.url } : {}),\n ...(options.seller ? { seller: options.seller } : {}),\n }\n }\n\n return [schema]\n}\n","import type { BreadcrumbItem } from './types'\nimport { normalizeSchemaText } from './utils'\n\nfunction toAbsoluteUrl(path: string, origin: string): string {\n return /^https?:\\/\\//i.test(path) ? path : `${origin}${path}`\n}\n\nexport function buildBreadcrumbListSchema(\n items: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n const crumbs = items\n .map((item) => ({ name: normalizeSchemaText(item.label), to: item.to }))\n .filter((crumb) => crumb.name)\n\n if (!crumbs.length) return []\n\n return [\n {\n '@context': 'https://schema.org',\n '@type': 'BreadcrumbList',\n itemListElement: crumbs.map((crumb, index) => ({\n '@type': 'ListItem',\n position: index + 1,\n name: crumb.name,\n ...(crumb.to ? { item: toAbsoluteUrl(crumb.to, origin) } : {}),\n })),\n },\n ]\n}\n","import type { NestedCategory, Product, ProductsCollection } from '@zenky/storefront-api'\n\nimport { buildBreadcrumbListSchema } from './breadcrumbSchema'\nimport type { BreadcrumbItem } from './types'\nimport { normalizeSchemaText, resolveMediaUrl } from './utils'\n\n/**\n * JSON-LD for a product listing page: BreadcrumbList + ItemList (first 10 products).\n * Returns an array of 0-2 JSON-LD objects. Category and collection pages differ only\n * in the list name, so both go through here.\n * Spec: https://schema.org/ItemList · https://schema.org/BreadcrumbList\n */\nfunction buildListingSchemas(\n name: string | null,\n products: Product[],\n breadcrumbs: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n const schemas = buildBreadcrumbListSchema(breadcrumbs, origin)\n\n const items = products.slice(0, 10)\n if (items.length) {\n schemas.push({\n '@context': 'https://schema.org',\n '@type': 'ItemList',\n name,\n numberOfItems: items.length,\n itemListElement: items.map((product, index) => {\n const url = `${origin}/products/${product.short_id}/${product.slug || product.short_id}`\n const firstImage = product.images?.[0]\n const image = firstImage ? resolveMediaUrl(firstImage) : null\n\n const item: Record<string, unknown> = {\n '@type': 'ListItem',\n position: index + 1,\n url,\n name: normalizeSchemaText(product.name),\n }\n\n if (image) item.image = image\n\n return item\n }),\n })\n }\n\n return schemas\n}\n\n/** JSON-LD for a category page. */\nexport function buildCategorySchemas(\n category: NestedCategory,\n products: Product[],\n breadcrumbs: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n return buildListingSchemas(category.name, products, breadcrumbs, origin)\n}\n\n/** JSON-LD for a products collection page. */\nexport function buildCollectionSchemas(\n collection: ProductsCollection,\n products: Product[],\n breadcrumbs: BreadcrumbItem[],\n origin: string\n): Record<string, unknown>[] {\n return buildListingSchemas(collection.name, products, breadcrumbs, origin)\n}\n","import type { Article, Media, OfferArticle } from '@zenky/storefront-api'\n\nimport { prepareOgDescription, resolveMediaUrl } from './utils'\n\nfunction articleSchema(\n type: 'Article' | 'BlogPosting',\n opts: {\n title: string | null | undefined\n intro: string | null | undefined\n cover: Media | null | undefined\n storeName: string\n origin: string\n }\n): Record<string, unknown> {\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': type,\n headline: opts.title ?? '',\n author: {\n '@type': 'Organization',\n name: opts.storeName,\n url: opts.origin,\n },\n }\n\n const description = prepareOgDescription(opts.intro)\n if (description) schema.description = description\n\n const image = opts.cover ? resolveMediaUrl(opts.cover) : null\n if (image) schema.image = image\n\n return schema\n}\n\n/**\n * JSON-LD schema.org/Article for the offer page's editorial copy.\n * Spec: https://schema.org/Article\n */\nexport function buildOfferArticleSchema(\n article: OfferArticle,\n storeName: string,\n origin: string\n): Record<string, unknown>[] {\n if (!article.title) return []\n\n return [\n articleSchema('Article', {\n title: article.title,\n intro: article.intro,\n cover: article.cover,\n storeName,\n origin,\n }),\n ]\n}\n\n/**\n * JSON-LD schema.org/BlogPosting for a blog article — enables Google Rich Results.\n * Spec: https://schema.org/BlogPosting\n */\nexport function buildBlogPostSchema(\n article: Article,\n storeName: string,\n origin: string\n): Record<string, unknown>[] {\n const schema = articleSchema('BlogPosting', {\n title: article.title,\n intro: article.intro,\n cover: article.cover,\n storeName,\n origin,\n })\n\n if (article.updated_at) {\n schema.dateModified = article.updated_at\n // No separate datePublished field is available — reuse updated_at.\n schema.datePublished = article.updated_at\n }\n\n return [schema]\n}\n","import type { Schedule } from '@zenky/storefront-api'\n\nconst SCHEMA_DAYS = [\n ['monday', 'Monday'],\n ['tuesday', 'Tuesday'],\n ['wednesday', 'Wednesday'],\n ['thursday', 'Thursday'],\n ['friday', 'Friday'],\n ['saturday', 'Saturday'],\n ['sunday', 'Sunday'],\n] as const\n\nconst ROUND_THE_CLOCK = /^\\s*0?0:00\\s*[-–—]\\s*0?0:00\\s*$|круглосуточно|24\\s*\\/\\s*7|24\\s*час/iu\nconst SHIFT = /(\\d{1,2}):(\\d{2})\\D+?(\\d{1,2}):(\\d{2})/g\n\ninterface OpeningHoursGroup {\n opens: string\n closes: string\n days: string[]\n}\n\nfunction formatTime(hours: string, minutes: string): string | null {\n const hour = Number(hours)\n const minute = Number(minutes)\n if (hour > 24 || minute > 59 || (hour === 24 && minute > 0)) return null\n if (hour === 24) return '23:59'\n return `${String(hour).padStart(2, '0')}:${minutes}`\n}\n\nfunction parseShifts(hours: string): [string, string][] {\n if (ROUND_THE_CLOCK.test(hours)) return [['00:00', '23:59']]\n\n const shifts: [string, string][] = []\n for (const [, openHour, openMinute, closeHour, closeMinute] of hours.matchAll(SHIFT)) {\n const opens = formatTime(openHour ?? '', openMinute ?? '')\n const closes = formatTime(closeHour ?? '', closeMinute ?? '')\n if (opens && closes) shifts.push([opens, closes])\n }\n return shifts\n}\n\nexport function buildOpeningHoursSpecification(\n schedule: Schedule | null | undefined\n): Record<string, unknown>[] {\n if (!schedule?.days) return []\n\n const groups: OpeningHoursGroup[] = []\n for (const [key, dayOfWeek] of SCHEMA_DAYS) {\n const hours = schedule.days[key]?.hours\n if (!hours) continue\n\n for (const [opens, closes] of parseShifts(hours)) {\n const group = groups.find((item) => item.opens === opens && item.closes === closes)\n if (group) group.days.push(dayOfWeek)\n else groups.push({ opens, closes, days: [dayOfWeek] })\n }\n }\n\n return groups.map(({ opens, closes, days }) => ({\n '@type': 'OpeningHoursSpecification',\n dayOfWeek: days,\n opens,\n closes,\n }))\n}\n","import type { City, GeoLocation, Stock, Store } from '@zenky/storefront-api'\n\nimport { type BusinessType, resolveLocationType } from './businessType'\nimport { locationSchemaId, organizationSchemaId } from './ids'\nimport { buildOpeningHoursSpecification } from './openingHours'\nimport { htmlToPlainText, normalizeSchemaText, resolveStoreLogoUrl } from './utils'\n\nexport interface LocationSchemaOptions {\n businessType?: BusinessType | null\n locationUrl?: ((stock: Stock) => string | null | undefined) | null\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction normalizeStreetAddress(address: string | null | undefined, cityName: string): string {\n const street = normalizeSchemaText(address)\n if (!street || !cityName) return street\n\n const city = `(?:г\\\\.?|город)?\\\\s*${escapeRegExp(cityName)}`\n const cityPrefix = new RegExp(`^${city}\\\\s*,\\\\s*`, 'iu')\n const citySuffix = new RegExp(`\\\\s*,\\\\s*${city}$`, 'iu')\n return street.replace(cityPrefix, '').replace(citySuffix, '') || street\n}\n\nfunction hasCoordinates(coordinates: GeoLocation | null | undefined): coordinates is GeoLocation {\n if (!coordinates) return false\n\n const { latitude, longitude } = coordinates\n if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) return false\n\n return latitude !== 0 || longitude !== 0\n}\n\nfunction buildLocationNode(\n stock: Stock,\n city: City,\n store: Store,\n origin: string,\n options: LocationSchemaOptions\n): Record<string, unknown> | null {\n const cityName = normalizeSchemaText(city.name)\n const streetAddress = normalizeStreetAddress(stock.address, cityName)\n if (!streetAddress) return null\n\n const node: Record<string, unknown> = {\n '@type': resolveLocationType(stock, options.businessType),\n '@id': locationSchemaId(origin, stock.id),\n name: normalizeSchemaText(stock.name) || normalizeSchemaText(store.name),\n }\n\n const description = htmlToPlainText(stock.description)\n if (description) node.description = description\n\n const url = options.locationUrl?.(stock)\n if (url) node.url = url\n\n const image = resolveStoreLogoUrl(store)\n if (image) node.image = image\n\n const telephone =\n stock.phones?.[0]?.number || city.phones?.[0]?.number || store.phones?.[0]?.number\n if (telephone) node.telephone = telephone\n\n node.address = {\n '@type': 'PostalAddress',\n streetAddress,\n ...(cityName ? { addressLocality: cityName } : {}),\n addressCountry: store.settings?.country || 'RU',\n }\n\n if (hasCoordinates(stock.coordinates)) {\n const { latitude, longitude } = stock.coordinates\n node.geo = { '@type': 'GeoCoordinates', latitude, longitude }\n node.hasMap = `https://yandex.ru/maps/?pt=${longitude},${latitude}&z=17&l=map`\n }\n\n const openingHours = buildOpeningHoursSpecification(stock.schedule)\n if (openingHours.length) node.openingHoursSpecification = openingHours\n\n node.parentOrganization = { '@id': organizationSchemaId(origin) }\n\n return node\n}\n\nexport function buildLocationNodes(\n store: Store,\n origin: string,\n options: LocationSchemaOptions = {}\n): Record<string, unknown>[] {\n const seen = new Set<string>()\n const nodes: Record<string, unknown>[] = []\n\n for (const city of store.cities ?? []) {\n for (const stock of city.stocks ?? []) {\n if (seen.has(stock.id)) continue\n\n const node = buildLocationNode(stock, city, store, origin, options)\n if (!node) continue\n\n seen.add(stock.id)\n nodes.push(node)\n }\n }\n\n return nodes\n}\n","import type { Store } from '@zenky/storefront-api'\n\nimport { getEmailLink, getSocialLinks } from '../utils/contacts'\nimport { organizationSchemaId, webSiteSchemaId } from './ids'\nimport { buildLocationNodes, type LocationSchemaOptions } from './locationSchema'\nimport { normalizeSchemaText, resolveStoreLogoUrl } from './utils'\n\nexport interface OrganizationSchemaOptions extends LocationSchemaOptions {\n inLanguage?: string | null\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values.filter(Boolean))]\n}\n\nexport function buildOrganizationReference(store: Store, origin: string): Record<string, unknown> {\n return {\n '@type': 'Organization',\n '@id': organizationSchemaId(origin),\n name: normalizeSchemaText(store.name),\n url: `${origin}/`,\n }\n}\n\nfunction buildOrganizationNode(store: Store, origin: string): Record<string, unknown> {\n const node = buildOrganizationReference(store, origin)\n\n const logo = resolveStoreLogoUrl(store)\n if (logo) node.logo = logo\n\n const phones = unique((store.phones ?? []).map((phone) => phone.number))\n if (phones.length) node.telephone = phones.length === 1 ? phones[0] : phones\n\n const email = getEmailLink(store.links ?? [])\n if (email) node.email = email\n\n const sameAs = unique(getSocialLinks(store.links ?? []).map((link) => link.url))\n if (sameAs.length) node.sameAs = sameAs\n\n const cities = store.cities ?? []\n const cityName = cities.length === 1 ? normalizeSchemaText(cities[0]?.name) : ''\n if (cityName) {\n node.address = {\n '@type': 'PostalAddress',\n addressLocality: cityName,\n addressCountry: store.settings?.country || 'RU',\n }\n }\n\n return node\n}\n\nfunction buildWebSiteNode(\n store: Store,\n origin: string,\n inLanguage: string | null | undefined\n): Record<string, unknown> {\n return {\n '@type': 'WebSite',\n '@id': webSiteSchemaId(origin),\n url: `${origin}/`,\n name: normalizeSchemaText(store.name),\n ...(inLanguage ? { inLanguage } : {}),\n publisher: { '@id': organizationSchemaId(origin) },\n }\n}\n\nexport function buildOrganizationSchema(\n store: Store,\n origin: string,\n options: OrganizationSchemaOptions = {}\n): Record<string, unknown>[] {\n return [\n {\n '@context': 'https://schema.org',\n '@graph': [\n buildOrganizationNode(store, origin),\n buildWebSiteNode(store, origin, options.inLanguage),\n ...buildLocationNodes(store, origin, options),\n ],\n },\n ]\n}\n\nexport function buildLocationsSchema(\n store: Store,\n origin: string,\n options: LocationSchemaOptions = {}\n): Record<string, unknown>[] {\n const locations = buildLocationNodes(store, origin, options)\n if (!locations.length) return []\n\n return [\n {\n '@context': 'https://schema.org',\n '@graph': [buildOrganizationNode(store, origin), ...locations],\n },\n ]\n}\n","/** Already-resolved OG/Twitter tag values (with the consumer's defaults applied). */\nexport interface OgTagsInput {\n title: string | null\n description?: string | null\n image?: string | null\n type?: string\n url?: string | null\n}\n\n/** Framework-neutral OG + Twitter meta records. The consumer controls head priority. */\nexport function buildOgTags(input: OgTagsInput): Record<string, string>[] {\n const tags: Record<string, string>[] = []\n\n if (input.title) {\n tags.push({ property: 'og:title', content: input.title })\n tags.push({ name: 'twitter:title', content: input.title })\n }\n\n if (input.description) {\n tags.push({ property: 'og:description', content: input.description })\n tags.push({ name: 'twitter:description', content: input.description })\n }\n\n if (input.image) {\n tags.push({ property: 'og:image', content: input.image })\n tags.push({ name: 'twitter:image', content: input.image })\n }\n\n tags.push({ property: 'og:type', content: input.type ?? 'website' })\n\n if (input.url) {\n tags.push({ property: 'og:url', content: input.url })\n }\n\n return tags\n}\n","import type { Seo, SeoMetaTag } from '@zenky/storefront-api'\n\n/** SDK `Seo.meta` tags mapped to framework-neutral head meta records. */\nexport function mapSeoMetaTags(tags: SeoMetaTag[]): Record<string, string>[] {\n return tags.map((tag) => {\n const attrs: Record<string, string> = {\n [tag.name.attribute]: tag.name.value,\n [tag.value.attribute]: tag.value.value,\n }\n\n for (const additional of tag.additional) {\n attrs[additional.attribute] = additional.value\n }\n\n return attrs\n })\n}\n\n/** Meta tags from a `Seo` entity (description + `Seo.meta` mapping). The consumer resolves the title. */\nexport function buildEntitySeoMeta(seo: Seo | null | undefined): Record<string, string>[] {\n const tags: Record<string, string>[] = []\n\n if (seo?.description) {\n tags.push({ name: 'description', content: seo.description })\n }\n\n if (seo?.meta?.length) {\n tags.push(...mapSeoMetaTags(seo.meta))\n }\n\n return tags\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  export { RESEND_TIMER_SECONDS, useAuthFlowStore, useProductsStore, useStore, useStorefrontProfile } from '../chunk-PBBVWWMI.js';
2
2
  import '../chunk-5B2P5W3E.js';
3
3
  import '../chunk-TE42OCFK.js';
4
- export { useCatalogStore } from '../chunk-4JCJHAL3.js';
5
- import '../chunk-TIQ7AJLY.js';
6
4
  export { usePromotionsStore } from '../chunk-544USTPB.js';
5
+ import '../chunk-TIQ7AJLY.js';
6
+ export { useCatalogStore } from '../chunk-4JCJHAL3.js';
7
7
  export { useAuthStore, useCartStore, useOrderSettingsStore } from '../chunk-TXR76IDL.js';
8
8
  export { useStoreProfileStore } from '../chunk-IOYYCA75.js';
9
9
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,5 @@
1
- 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';
1
+ export { buildQrCodeUrl, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, formatScheduleStatus, getApiErrorMessage, getApiFieldErrors, getPhoneTelLink, getTodayInfo, getWeeklySchedule, groupScheduleDays, pluralize, toDateInputValue, todayInTimezone } from '../chunk-UJKWKD3W.js';
2
+ export { getEmailLink, getSocialLinks, getWebsiteLink } from '../chunk-JY3UJRMF.js';
2
3
  export { createDebounce } from '../chunk-XUGXLJZB.js';
3
4
  //# sourceMappingURL=index.js.map
4
5
  //# sourceMappingURL=index.js.map
@@ -34,9 +34,11 @@ section). This list says what each one owns.
34
34
  (`useProductDetail`, `useProductList`), and related-product recommendations.
35
35
  - **`promotions/`** — checking whether the cart still qualifies for a promotion reward
36
36
  after it changes.
37
- - **`seo/`** — JSON-LD builders (`Product`, `Organization`, `BreadcrumbList` + `ItemList`,
38
- `BlogPosting`/`Article`) and OG-tag records. These return plain data; turning that data
39
- into `<head>` tags is the consumer's job (see the README's note on `useHead`).
37
+ - **`seo/`** — JSON-LD builders (the store graph: `Organization` + `WebSite` + one node per
38
+ location with stable `@id`s; `Product` with a stock-aware `Offer`; `BreadcrumbList` +
39
+ `ItemList`; `BlogPosting`/`Article`) and OG-tag records. These return plain data;
40
+ turning that data into `<head>` tags is the consumer's job (see the README's note on
41
+ `useHead`).
40
42
  - **`snippets/`** — normalizing the snippet records a website carries (tracking scripts,
41
43
  custom CSS) into a consistent shape.
42
44
  - **`stores/`** — the eight Pinia stores: `auth`, `authFlow`, `cart`, `catalog`,
@@ -11,7 +11,7 @@ Use an exact version while integrating or testing a prerelease. Upgrade delibera
11
11
  after the consumer quality gate is green.
12
12
 
13
13
  ```bash
14
- npm install --save-exact @zenky/storefront-vue@0.11.0
14
+ npm install --save-exact @zenky/storefront-vue@0.12.0
15
15
  ```
16
16
 
17
17
  The consumer must also provide compatible peer dependencies:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenky/storefront-vue",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Zenky Storefront SDK for Vue 3.",
5
5
  "keywords": [
6
6
  "zenky",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/products/formatWeight.ts","../src/products/useProductsByCategory.ts","../src/products/useProductVariantModifiers.ts","../src/products/useProductPricing.ts","../src/products/useProductVariant.ts","../src/products/usePriceRecalculation.ts","../src/products/useProductVariantSelector.ts","../src/products/useRelatedProducts.ts","../src/products/findProductInCatalog.ts","../src/products/useProductDetail.ts","../src/products/useProductList.ts","../src/utils/color.ts","../src/products/badges.ts"],"names":["computed","ref","watch","channel"],"mappings":"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","file":"chunk-KK645XNR.js","sourcesContent":["import { UnitType } from '@zenky/storefront-api'\n\nimport type { Product, ProductVariant } from '@zenky/storefront-api'\n\nconst UNIT_LABELS: Record<UnitType, string> = {\n [UnitType.Gram]: 'г',\n [UnitType.Kilogram]: 'кг',\n [UnitType.Meter]: 'м',\n [UnitType.Piece]: 'г',\n} as const\n\nfunction getWeightFromDimensions(variants: ProductVariant[] | undefined): number | null {\n if (!variants?.length) return null\n\n const dimension = variants[0]?.dimensions?.find((d) => d.dimension === 'weight')\n\n return dimension?.value ?? null\n}\n\nexport function getVariantWeight(variant: ProductVariant | null | undefined): number | null {\n if (!variant) return null\n\n return variant.dimensions?.find((d) => d.dimension === 'weight')?.value ?? null\n}\n\nexport function getProductWeight(product: Product): number | null {\n return product.weight ?? getWeightFromDimensions(product.variants) ?? null\n}\n\nexport function toGrams(weight: number | null, unitType: UnitType): number | null {\n if (!weight) {\n return null\n }\n\n if (unitType === UnitType.Kilogram) {\n return weight * 1000\n }\n\n if (unitType === UnitType.Meter) {\n return null\n }\n\n return weight\n}\n\nexport function formatWeight(weight: number | null, unitType: UnitType): string | null {\n if (!weight) {\n return null\n }\n\n const label = UNIT_LABELS[unitType]\n\n return `${weight} ${label}`\n}\n","import { computed, type ComputedRef } from 'vue'\n\nimport type { NestedCategory, Product } from '@zenky/storefront-api'\n\nexport interface CategoryWithProducts {\n id: string\n shortId: string\n slug: string | null\n name: string | null\n products: Product[]\n}\n\nexport function useProductsByCategory(\n products: ComputedRef<Product[]>,\n categories: ComputedRef<NestedCategory[]>\n): {\n grouped: ComputedRef<CategoryWithProducts[]>\n} {\n const grouped = computed<CategoryWithProducts[]>(() => {\n if (!categories.value.length || !products.value.length) {\n return []\n }\n\n const productsByCategory = new Map<string, Product[]>()\n\n for (const product of products.value) {\n for (const category of product.categories) {\n const existing = productsByCategory.get(category.id) ?? []\n existing.push(product)\n productsByCategory.set(category.id, existing)\n }\n }\n\n return flattenCategories(categories.value)\n .filter((category) => productsByCategory.has(category.id))\n .map((category) => ({\n id: category.id,\n shortId: category.short_id,\n slug: category.slug,\n name: category.name,\n products: productsByCategory.get(category.id) ?? [],\n }))\n })\n\n return { grouped }\n}\n\nfunction flattenCategories(categories: NestedCategory[]): NestedCategory[] {\n const result: NestedCategory[] = []\n\n for (const category of categories) {\n result.push(category)\n\n if (category.children?.length) {\n result.push(...flattenCategories(category.children))\n }\n }\n\n return result\n}\n","import { computed, ref, watch, type ComputedRef, type Ref } from 'vue'\n\nimport type { ProductModifiersRequest, ProductVariant } from '@zenky/storefront-api'\n\nfunction getInitialModifiersModel(variant: ProductVariant | null): ProductModifiersRequest[] {\n if (!variant?.default_modifiers?.modifiers.length) {\n return []\n }\n\n return variant.default_modifiers.modifiers.map((modifier) => ({\n modifier_id: modifier.modifier_id,\n modifiers_group_id: modifier.modifiers_group_id,\n quantity: modifier.quantity,\n }))\n}\n\nexport function useProductVariantModifiers(variant: ComputedRef<ProductVariant | null>): {\n modifiersModel: Ref<ProductModifiersRequest[]>\n selectedModifiersHash: Ref<string | null>\n hasAnyModifier: ComputedRef<boolean>\n} {\n const modifiersModel: Ref<ProductModifiersRequest[]> = ref([\n ...getInitialModifiersModel(variant.value),\n ])\n const selectedModifiersHash: Ref<string | null> = ref(null)\n const hasAnyModifier = computed<boolean>(() => modifiersModel.value.length > 0)\n\n watch(variant, () => {\n const newDefaults = getInitialModifiersModel(variant.value)\n\n // Keep standalone modifiers (no group) — they belong to the product, not the variant.\n // Group modifiers reset to the new variant's defaults.\n const userStandalone = modifiersModel.value.filter((m) => !m.modifiers_group_id)\n const defaultStandaloneIds = new Set(\n newDefaults.filter((d) => !d.modifiers_group_id).map((d) => d.modifier_id)\n )\n const preservedStandalone = userStandalone.filter(\n (m) => !defaultStandaloneIds.has(m.modifier_id)\n )\n\n modifiersModel.value = [...preservedStandalone, ...newDefaults]\n })\n\n return { modifiersModel, selectedModifiersHash, hasAnyModifier }\n}\n","import { computed, type ComputedRef } from 'vue'\n\nimport type { Discount, Product, ProductVariant } from '@zenky/storefront-api'\n\nexport interface ResolvedPrice {\n price: number\n originalPrice: number | null\n discount: Discount | null\n}\n\n/**\n * Resolves a variant's price, accounting for stock.\n * Priority: prices[stockId] → prices[null] → top-level price.\n */\nexport function resolveVariantPrice(\n variant: ProductVariant,\n stockId?: string | null\n): ResolvedPrice {\n if (variant.prices?.length) {\n // 1. Exact match by stock\n if (stockId) {\n const stockEntry = variant.prices.find((p) => p.stock_id === stockId)\n\n if (stockEntry) {\n return {\n price: stockEntry.price,\n originalPrice: stockEntry.original_price,\n discount: stockEntry.discount,\n }\n }\n }\n\n // 2. Global price (stock_id = null)\n const globalEntry = variant.prices.find((p) => p.stock_id === null)\n\n if (globalEntry) {\n return {\n price: globalEntry.price,\n originalPrice: globalEntry.original_price,\n discount: globalEntry.discount,\n }\n }\n }\n\n // 3. Fallback — the variant's top-level fields\n return {\n price: variant.price,\n originalPrice: variant.original_price ?? null,\n discount: variant.discount ?? null,\n }\n}\n\nexport function useProductPricing(\n product: ComputedRef<Product>,\n stockId?: ComputedRef<string | null | undefined>\n): {\n displayPrice: ComputedRef<number>\n originalDisplayPrice: ComputedRef<number | null>\n hasDifferentPrices: ComputedRef<boolean>\n needsSelection: ComputedRef<boolean>\n} {\n const variants = computed(() => product.value.variants ?? [])\n const currentStockId = computed(() => stockId?.value ?? null)\n\n const resolvedPrices = computed(() =>\n variants.value.map((v) => resolveVariantPrice(v, currentStockId.value))\n )\n\n // Minimum required modifier cost that's always added to the price:\n // 1. modEntry.is_required — the modifier is always sent to the API (can't be removed)\n // 2. groupEntry.is_required — the user must pick at least one from the group →\n // add the cheapest price in the group (if no is_required modifier already covers it)\n const minRequiredModifiersCost = computed<number>(() => {\n let total = 0\n\n for (const groupEntry of product.value.modifiers_groups ?? []) {\n const group = groupEntry.group\n\n for (const modEntry of group.modifiers) {\n if (modEntry.is_required && modEntry.modifier.price) {\n total += modEntry.modifier.price * Math.max(modEntry.min_quantity ?? 0, 1)\n }\n }\n\n if (\n groupEntry.is_required &&\n group.modifiers.length &&\n !group.modifiers.some((m) => m.is_required)\n ) {\n const cheapest = group.modifiers.reduce((min, m) =>\n (m.modifier.price ?? 0) < (min.modifier.price ?? 0) ? m : min\n )\n total += (cheapest.modifier.price ?? 0) * Math.max(cheapest.min_quantity ?? 0, 1)\n }\n }\n\n return total\n })\n\n const displayPrice = computed<number>(() => {\n if (!resolvedPrices.value.length) {\n return 0\n }\n\n return (\n Math.min(...resolvedPrices.value.map((r) => r.price)) + minRequiredModifiersCost.value\n )\n })\n\n // Price without the discount: original_price of the cheapest variant + required modifiers.\n // null if there is no discount.\n // original_price can be null even when a discount exists — then compute it via discount.difference.\n const originalDisplayPrice = computed<number | null>(() => {\n if (!resolvedPrices.value.length) return null\n\n // Find the variant with the minimum price (the same one that determines displayPrice)\n const cheapest = resolvedPrices.value.reduce((min, r) => (r.price < min.price ? r : min))\n\n // Priority: original_price, then compute via discount\n let originalVariantPrice: number | null = null\n\n if (cheapest.originalPrice && cheapest.originalPrice > cheapest.price) {\n originalVariantPrice = cheapest.originalPrice\n } else if (cheapest.discount && cheapest.discount.difference > 0) {\n originalVariantPrice = cheapest.price + cheapest.discount.difference\n }\n\n if (!originalVariantPrice) return null\n\n return originalVariantPrice + minRequiredModifiersCost.value\n })\n\n const hasDifferentPrices = computed<boolean>(() => {\n if (resolvedPrices.value.length <= 1) {\n return false\n }\n\n const prices = new Set(resolvedPrices.value.map((r) => r.price))\n\n return prices.size > 1\n })\n\n const needsSelection = computed<boolean>(() => {\n if (variants.value.length > 1) {\n return true\n }\n\n const mods = product.value.modifiers\n const groups = product.value.modifiers_groups\n\n return (\n (Array.isArray(mods) && mods.length > 0) || (Array.isArray(groups) && groups.length > 0)\n )\n })\n\n return { displayPrice, originalDisplayPrice, hasDifferentPrices, needsSelection }\n}\n","import { computed, ref, watch, type ComputedRef, type Ref } from 'vue'\n\nimport type {\n Product,\n ProductVariant,\n ProductVariantOption,\n ProductVariantOptionValue,\n} from '@zenky/storefront-api'\n\nexport interface ProductVariantOptionListItem {\n id: string\n name: string | null\n values: ProductVariantOptionValue[]\n}\n\nfunction getDefaultOptionsModel(product: Product): Record<string, string> {\n const model: Record<string, string> = {}\n\n if (!product.variants?.length) {\n return model\n }\n\n const firstVariantOptions = product.variants.find(\n (variant: ProductVariant) => variant.options?.length\n )?.options\n\n if (!firstVariantOptions) {\n return model\n }\n\n firstVariantOptions.forEach((option: ProductVariantOption) => {\n model[option.id] = option.value.id\n })\n\n return model\n}\n\nfunction getProductVariantOptionsList(product: Product): ProductVariantOptionListItem[] {\n const list: ProductVariantOptionListItem[] = []\n\n if (!product.variants?.length) {\n return list\n }\n\n product.variants.forEach((variant: ProductVariant) => {\n if (!variant.options?.length) {\n return\n }\n\n variant.options.forEach((option: ProductVariantOption) => {\n let index = list.findIndex(\n (item: ProductVariantOptionListItem) => item.id === option.id\n )\n\n if (index === -1) {\n index = list.push({\n id: option.id,\n name: option.name,\n values: [],\n })\n\n index--\n }\n\n const valueIndex = list[index]!.values.findIndex(\n (value: ProductVariantOptionValue) => value.id === option.value.id\n )\n\n if (valueIndex === -1) {\n list[index]!.values.push(option.value)\n }\n })\n })\n\n return list\n}\n\nfunction computeDisabledValues(\n variants: ProductVariant[],\n optionsList: ProductVariantOptionListItem[],\n optionsModel: Record<string, string>\n): Record<string, Set<string>> {\n if (!variants.length) return {}\n\n const result: Record<string, Set<string>> = {}\n\n for (const option of optionsList) {\n const disabled = new Set<string>()\n\n for (const value of option.values) {\n const hasMatch = variants.some((variant) => {\n if (!variant.options?.length) return false\n\n const variantMap: Record<string, string> = {}\n for (const opt of variant.options) {\n variantMap[opt.id] = opt.value.id\n }\n\n // Variant must have this specific value for this option\n if (variantMap[option.id] !== value.id) return false\n\n // Variant must match all OTHER currently-selected values\n for (const [otherId, selectedId] of Object.entries(optionsModel)) {\n if (otherId === option.id) continue\n if (variantMap[otherId] !== selectedId) return false\n }\n\n return true\n })\n\n if (!hasMatch) {\n disabled.add(value.id)\n }\n }\n\n result[option.id] = disabled\n }\n\n return result\n}\n\nexport function useProductVariant(product: ComputedRef<Product>): {\n optionsModel: Ref<Record<string, string>>\n optionsList: Ref<ProductVariantOptionListItem[]>\n selectedVariant: ComputedRef<ProductVariant | null>\n disabledValues: ComputedRef<Record<string, Set<string>>>\n} {\n const optionsModel = ref({ ...getDefaultOptionsModel(product.value) })\n const optionsList = ref([...getProductVariantOptionsList(product.value)])\n\n const selectedVariant = computed<ProductVariant | null>(() => {\n if (!product.value.variants?.length) {\n return null\n } else if (product.value.variants.length === 1 || !Object.keys(optionsModel.value).length) {\n return product.value.variants[0] ?? null\n }\n\n return (\n product.value.variants.find((variant: ProductVariant) => {\n if (!variant.options?.length) {\n return false\n }\n\n return variant.options.every(\n (option: ProductVariantOption) =>\n optionsModel.value[option.id] === option.value.id\n )\n }) ?? null\n )\n })\n\n const disabledValues = computed<Record<string, Set<string>>>(() =>\n computeDisabledValues(product.value.variants ?? [], optionsList.value, optionsModel.value)\n )\n\n watch(product, () => {\n optionsModel.value = { ...getDefaultOptionsModel(product.value) }\n optionsList.value = [...getProductVariantOptionsList(product.value)]\n })\n\n return { optionsModel, optionsList, selectedVariant, disabledValues }\n}\n","import { computed, ref, watch, type ComputedRef, type Ref } from 'vue'\n\nimport type { Product, ProductModifiersRequest, ProductVariant } from '@zenky/storefront-api'\n\nimport { useRuntime } from '../ports/runtime'\nimport { useStoreProfileStore } from '../stores/store-profile'\nimport { createDebounce } from '../utils/debounce'\nimport { resolveVariantPrice } from './useProductPricing'\n\ninterface PriceRecalculationOptions {\n product: ComputedRef<Product>\n selectedVariant: ComputedRef<ProductVariant | null>\n modifiersModel: Ref<ProductModifiersRequest[]>\n requiredModifiersGroupIsMissing: ComputedRef<boolean>\n selectedModifiersHash: Ref<string | null>\n}\n\nexport function usePriceRecalculation({\n product,\n selectedVariant,\n modifiersModel,\n requiredModifiersGroupIsMissing,\n selectedModifiersHash,\n}: PriceRecalculationOptions): {\n price: ComputedRef<number>\n originalPrice: ComputedRef<number | null>\n priceWasModified: ComputedRef<boolean>\n priceIsRecalculating: Ref<boolean>\n} {\n // Get the SDK from the runtime (DI port), not from the Nuxt-specific useStorefrontApi().\n const sdk = useRuntime().sdk\n const profileStore = useStoreProfileStore()\n\n // -------------------------------------------------------------------------\n // Computed: stock-aware variant pricing\n // -------------------------------------------------------------------------\n\n const currentStockId = computed(() => profileStore.stock?.id ?? null)\n\n const resolvedVariant = computed(() => {\n if (!selectedVariant.value) return null\n\n return resolveVariantPrice(selectedVariant.value, currentStockId.value)\n })\n\n // -------------------------------------------------------------------------\n // Computed: modifier price helpers\n // -------------------------------------------------------------------------\n\n const modifierPriceMap = computed<Map<string, number>>(() => {\n const map = new Map<string, number>()\n\n for (const item of product.value.modifiers ?? []) {\n if (item.modifier.price) {\n map.set(item.modifier.id, item.modifier.price)\n }\n }\n\n for (const group of product.value.modifiers_groups ?? []) {\n for (const item of group.group.modifiers ?? []) {\n if (item.modifier.price) {\n map.set(item.modifier.id, item.modifier.price)\n }\n }\n }\n\n return map\n })\n\n // Sum of selected modifier prices (includes defaults — they're already in modifiersModel)\n const selectedModifierTotal = computed<number>(() =>\n modifiersModel.value.reduce(\n (sum, req) => sum + (modifierPriceMap.value.get(req.modifier_id) ?? 0) * req.quantity,\n 0\n )\n )\n\n // -------------------------------------------------------------------------\n // Computed: optimistic price (instant, without hitting the API)\n // -------------------------------------------------------------------------\n\n // variant.price is the variant's base price (stock-specific or fallback);\n // it does NOT include modifiers. selectedModifierTotal adds all selected\n // modifiers (default + required + custom).\n const optimisticPrice = computed<number>(() => {\n if (!resolvedVariant.value) return 0\n\n return resolvedVariant.value.price + selectedModifierTotal.value\n })\n\n const optimisticOriginalPrice = computed<number | null>(() => {\n if (!resolvedVariant.value) return null\n\n const r = resolvedVariant.value\n\n if (r.originalPrice && r.originalPrice > r.price) return r.originalPrice\n if (r.discount && r.discount.difference > 0) return r.price + r.discount.difference\n\n return null\n })\n\n // -------------------------------------------------------------------------\n // API-confirmed price (overrides the optimistic price once the response arrives)\n // -------------------------------------------------------------------------\n\n const apiPrice = ref<number | null>(null)\n const apiOriginalPrice = ref<number | null>(null)\n const priceIsRecalculating = ref(false)\n let requestId = 0\n\n // -------------------------------------------------------------------------\n // Final displayed price: API > optimistic\n // -------------------------------------------------------------------------\n\n const price = computed<number>(() => apiPrice.value ?? optimisticPrice.value)\n const originalPrice = computed<number | null>(\n () => apiOriginalPrice.value ?? optimisticOriginalPrice.value\n )\n const priceWasModified = computed<boolean>(() => apiPrice.value !== null)\n\n // -------------------------------------------------------------------------\n // API recalculation (confirms / corrects the optimistic price)\n // -------------------------------------------------------------------------\n\n async function recalculatePrice(): Promise<void> {\n if (requiredModifiersGroupIsMissing.value) return\n if (!modifiersModel.value.length || !selectedVariant.value) return\n\n const currentRequestId = ++requestId\n priceIsRecalculating.value = true\n\n try {\n const response = await sdk.products.getProductVariantPrice(\n profileStore.store!.id,\n product.value.id,\n selectedVariant.value.id,\n {\n modifiers: modifiersModel.value,\n // exactOptionalPropertyTypes: only include stock_id when it's set\n ...(currentStockId.value ? { stock_id: currentStockId.value } : {}),\n }\n )\n\n if (currentRequestId !== requestId) return\n\n apiPrice.value = response.price\n apiOriginalPrice.value = response.original_price\n selectedModifiersHash.value = response.modifiers_hash\n } catch (e) {\n console.error('[usePriceRecalculation] price recalculation failed', e)\n } finally {\n if (currentRequestId === requestId) {\n priceIsRecalculating.value = false\n }\n }\n }\n\n const debouncedRecalculate = createDebounce(() => recalculatePrice(), 300)\n\n // -------------------------------------------------------------------------\n // Watcher: reset the API price + recalculate when the variant/modifiers change\n // -------------------------------------------------------------------------\n\n watch(selectedVariant, () => {\n apiPrice.value = null\n apiOriginalPrice.value = null\n requestId++\n selectedModifiersHash.value = selectedVariant.value?.default_modifiers?.hash ?? null\n })\n\n watch(\n modifiersModel,\n () => {\n apiPrice.value = null\n apiOriginalPrice.value = null\n requestId++\n\n if (modifiersModel.value.length && selectedVariant.value) {\n debouncedRecalculate()\n } else {\n selectedModifiersHash.value = selectedVariant.value?.default_modifiers?.hash ?? null\n }\n },\n { deep: true }\n )\n\n return { price, originalPrice, priceWasModified, priceIsRecalculating }\n}\n","import { computed, watch, type ComputedRef, type Ref } from 'vue'\n\nimport type { Product, ProductModifiersRequest, ProductVariant } from '@zenky/storefront-api'\n\nimport { usePriceRecalculation } from './usePriceRecalculation'\nimport { useProductVariant, type ProductVariantOptionListItem } from './useProductVariant'\nimport { useProductVariantModifiers } from './useProductVariantModifiers'\n\n// The SDK's min_quantity field is optional (number | null); normalize it to a positive quantity.\nfunction resolveQuantity(minQuantity: number | null): number {\n return minQuantity && minQuantity > 0 ? minQuantity : 1\n}\n\nexport function useProductVariantSelector(product: ComputedRef<Product>): {\n optionsModel: Ref<Record<string, string>>\n optionsList: Ref<ProductVariantOptionListItem[]>\n disabledValues: ComputedRef<Record<string, Set<string>>>\n modifiersModel: Ref<ProductModifiersRequest[]>\n selectedVariant: ComputedRef<ProductVariant | null>\n price: ComputedRef<number>\n originalPrice: ComputedRef<number | null>\n priceWasModified: ComputedRef<boolean>\n priceIsRecalculating: Ref<boolean>\n selectedModifiersHash: Ref<string | null>\n requiredModifiersGroupIsMissing: ComputedRef<boolean>\n} {\n const { optionsModel, optionsList, selectedVariant, disabledValues } =\n useProductVariant(product)\n const { modifiersModel, selectedModifiersHash } = useProductVariantModifiers(selectedVariant)\n\n // Required modifiers must always be present in the model.\n // 1) modEntry.is_required — an individually required modifier\n // 2) groupEntry.is_required — a required group: if it has no is_required modifiers,\n // auto-select the cheapest one (mirrors minRequiredModifiersCost in useProductPricing)\n const requiredModifierEntries = computed<ProductModifiersRequest[]>(() => {\n const result: ProductModifiersRequest[] = []\n\n for (const groupEntry of product.value.modifiers_groups ?? []) {\n const group = groupEntry.group\n const hasIndividualRequired = group.modifiers.some((m) => m.is_required)\n\n // 1. Individually required modifiers\n for (const modEntry of group.modifiers) {\n if (modEntry.is_required) {\n result.push({\n modifier_id: modEntry.modifier.id,\n modifiers_group_id: group.id,\n quantity: resolveQuantity(modEntry.min_quantity),\n })\n }\n }\n\n // 2. A required group with no is_required modifiers →\n // the user must pick at least one; take the cheapest\n if (groupEntry.is_required && !hasIndividualRequired) {\n const sorted = [...group.modifiers].sort(\n (a, b) => (a.modifier.price ?? 0) - (b.modifier.price ?? 0)\n )\n const cheapest = sorted[0]\n\n if (cheapest) {\n result.push({\n modifier_id: cheapest.modifier.id,\n modifiers_group_id: group.id,\n quantity: resolveQuantity(cheapest.min_quantity),\n })\n }\n }\n }\n\n return result\n })\n\n // Adds required modifiers to the model (for both UI and API).\n // Single mutation — avoids extra reactive recalculations.\n function seedRequiredModifiers(): void {\n const missing = requiredModifierEntries.value.filter(\n (req) => !modifiersModel.value.some((m) => m.modifier_id === req.modifier_id)\n )\n\n if (missing.length) {\n modifiersModel.value = [...modifiersModel.value, ...missing]\n }\n }\n\n // Synchronous initialization — runs before any watchers are registered in\n // usePriceRecalculation, so the first render already sees the correct price.\n seedRequiredModifiers()\n\n // On variant change: the useProductVariantModifiers watcher resets the model to defaults,\n // then we add the required ones back. Both watchers use flush: 'pre' — they run in\n // registration order, before the render.\n watch(selectedVariant, seedRequiredModifiers)\n\n const requiredModifiersGroupIsMissing = computed<boolean>(() => {\n const requiredGroups = (product.value.modifiers_groups ?? [])\n .filter((group) => group.is_required)\n .map((group) => group.group.id)\n\n if (!requiredGroups.length) return false\n\n return requiredGroups.some(\n (groupId) =>\n !modifiersModel.value.find(\n (m) => m.modifiers_group_id === groupId && m.quantity > 0\n )\n )\n })\n\n const { price, originalPrice, priceWasModified, priceIsRecalculating } = usePriceRecalculation({\n product,\n selectedVariant,\n modifiersModel,\n requiredModifiersGroupIsMissing,\n selectedModifiersHash,\n })\n\n return {\n optionsModel,\n optionsList,\n disabledValues,\n modifiersModel,\n selectedVariant,\n price,\n originalPrice,\n priceWasModified,\n priceIsRecalculating,\n selectedModifiersHash,\n requiredModifiersGroupIsMissing,\n }\n}\n","// Requests for recommended products. The SDK has no typed related.products.list\n// method, so this goes through the public sdk.client.request instead.\nimport type { Product } from '@zenky/storefront-api'\n\nimport { useRuntime } from '../ports/runtime'\nimport { createRuntimeState } from '../ports/runtimeState'\nimport { useAuthStore } from '../stores/auth'\nimport { useStoreProfileStore } from '../stores/store-profile'\n\nexport interface OrderCredentials {\n id: string\n token: string\n}\n\ninterface UseRelatedProductsApi {\n fetchForProduct: (\n productId: string,\n orderCredentials: OrderCredentials | null,\n signal?: AbortSignal\n ) => Promise<Product[]>\n fetchForOrder: (orderId: string, orderToken: string, signal?: AbortSignal) => Promise<Product[]>\n}\n\n/**\n * A single variant and no modifiers — such a product can be added to the cart\n * directly with one click from a recommendation, without opening the product card.\n */\nexport function canAddDirectly(product: Product): boolean {\n const variantsCount = product.variants?.length ?? 0\n const hasModifiers = (product.modifiers?.length ?? 0) > 0\n const hasModifierGroups = (product.modifiers_groups?.length ?? 0) > 0\n return variantsCount === 1 && !hasModifiers && !hasModifierGroups\n}\n\n// Without `variants.prices` prices come back as 0 (prices live on variants). Without\n// modifiers/groups, canAddDirectly breaks — it treats the product as \"direct add\"\n// even though it has modifiers.\nconst RELATED_PRODUCT_INCLUDES = 'variants.prices,modifiers,modifiers_groups'\n\ninterface RelatedProductsState {\n productInFlight: Map<string, Promise<Product[]>>\n}\n\nconst getRelatedProductsState = createRuntimeState<RelatedProductsState>(() => ({\n productInFlight: new Map<string, Promise<Product[]>>(),\n}))\n\nexport function useRelatedProducts(): UseRelatedProductsApi {\n const runtime = useRuntime()\n const { sdk } = runtime\n const { productInFlight } = getRelatedProductsState(runtime)\n const profileStore = useStoreProfileStore()\n const authStore = useAuthStore()\n\n function getStoreId(): string {\n const id = profileStore.store?.id\n if (!id) throw new Error('Store is not initialized')\n return id\n }\n\n async function fetchForProduct(\n productId: string,\n orderCredentials: OrderCredentials | null,\n signal?: AbortSignal\n ): Promise<Product[]> {\n if (signal?.aborted) return []\n\n const key = orderCredentials ? `${productId}:${orderCredentials.id}` : productId\n\n let promise = productInFlight.get(key)\n if (!promise) {\n promise = (async (): Promise<Product[]> => {\n try {\n const storeId = getStoreId()\n const query: Record<string, string> = { with: RELATED_PRODUCT_INCLUDES }\n if (orderCredentials) {\n query.order_id = orderCredentials.id\n query.order_token = orderCredentials.token\n }\n const url = sdk.client.getStoreUrl(\n storeId,\n `/products/${productId}/related/products`,\n query\n )\n const response = await sdk.client.request(\n 'GET',\n url,\n undefined,\n authStore.token\n )\n return (response?.data as Product[] | undefined) ?? []\n } catch (e: unknown) {\n // Per spec: on error or empty response, show nothing to the customer —\n // the block just doesn't appear. The log is for developers.\n console.warn('[recommendations:product] fetch failed', e)\n return []\n }\n })().finally(() => productInFlight.delete(key))\n productInFlight.set(key, promise)\n }\n\n const result = await promise\n return signal?.aborted ? [] : result\n }\n\n async function fetchForOrder(\n orderId: string,\n orderToken: string,\n signal?: AbortSignal\n ): Promise<Product[]> {\n if (signal?.aborted) return []\n\n try {\n const storeId = getStoreId()\n const url = sdk.client.getStoreUrl(storeId, `/orders/${orderId}/related/products`, {\n token: orderToken,\n with: RELATED_PRODUCT_INCLUDES,\n })\n const response = await sdk.client.request('GET', url, undefined, authStore.token)\n if (signal?.aborted) return []\n return (response?.data as Product[] | undefined) ?? []\n } catch (e: unknown) {\n console.warn('[recommendations:order] fetch failed', e)\n return []\n }\n }\n\n return { fetchForProduct, fetchForOrder }\n}\n","import type { Product } from '@zenky/storefront-api'\n\nimport type { StaticCatalogItem } from '../catalog/catalogEntity'\n\nexport interface CatalogProductMatch {\n product: Product\n catalogItem: StaticCatalogItem\n}\n\nexport function findProductInCatalog(\n catalog: StaticCatalogItem[],\n shortId: string\n): CatalogProductMatch | null {\n for (const item of catalog) {\n if (!item.products.length) continue\n\n const found = item.products.find((p) => p.short_id === shortId)\n if (found) return { product: found, catalogItem: item }\n }\n\n return null\n}\n","import { useRuntime } from '../ports/runtime'\nimport { useCatalogStore } from '../stores/catalog'\nimport { useStoreProfileStore } from '../stores/store-profile'\nimport { findProductInCatalog, type CatalogProductMatch } from './findProductInCatalog'\n\nimport type { Product } from '@zenky/storefront-api'\n\n// images — cover and OG image; variants.options — without it the variant selector\n// collapses to the first variant; variants.prices — the variant's own price, not 0;\n// custom_fields — extra product attributes.\nconst PRODUCT_DETAIL_INCLUDES =\n 'images,variants.prices,variants.options,categories,modifiers,modifiers.cover,modifiers_groups,modifiers_groups.cover,custom_fields'\n\nexport interface UseProductDetailApi {\n /** Synchronous search against the already-loaded static catalog. */\n findInCatalog: (shortId: string) => CatalogProductMatch | null\n /** API fallback for when the product isn't in the catalog. */\n fetchProduct: (shortId: string) => Promise<Product | null>\n}\n\nexport function useProductDetail(): UseProductDetailApi {\n const { sdk } = useRuntime()\n const catalogStore = useCatalogStore()\n const profileStore = useStoreProfileStore()\n\n function findInCatalog(shortId: string): CatalogProductMatch | null {\n return findProductInCatalog(catalogStore.catalog, shortId)\n }\n\n async function fetchProduct(shortId: string): Promise<Product | null> {\n const storeId = profileStore.store?.id\n if (!storeId) return null\n\n try {\n return await sdk.products.getProduct(storeId, shortId, {\n with: PRODUCT_DETAIL_INCLUDES,\n })\n } catch (e) {\n console.error('[product-detail] getProduct failed', e)\n return null\n }\n }\n\n return { findInCatalog, fetchProduct }\n}\n","import { useRuntime } from '../ports/runtime'\nimport { useCartStore } from '../stores/cart'\nimport { useStoreProfileStore } from '../stores/store-profile'\n\nimport type { PaginatedResponse, Product } from '@zenky/storefront-api'\n\n// images — cover image; variants.prices — price per stock (see resolveVariantPrice);\n// modifiers/modifiers_groups — the card shows \"from X ₽\" when these are present.\nconst PRODUCT_LIST_INCLUDES =\n 'images,variants.prices,variants.options,modifiers,modifiers.cover,modifiers_groups,modifiers_groups.cover'\n\nexport interface ProductListParams {\n categoryId?: string\n collectionId?: string\n orderBy?: string\n page?: number\n count?: number\n}\n\nexport interface UseProductListApi {\n fetchProducts: (params: ProductListParams) => Promise<PaginatedResponse<Product>>\n}\n\nfunction emptyPage(page: number, count: number): PaginatedResponse<Product> {\n return {\n items: [],\n pagination: {\n total: 0,\n count: 0,\n per_page: count,\n current_page: page,\n total_pages: 0,\n links: {},\n has_previous_page: false,\n has_next_page: false,\n elements: [],\n },\n }\n}\n\nexport function useProductList(): UseProductListApi {\n const { sdk } = useRuntime()\n const profileStore = useStoreProfileStore()\n const cartStore = useCartStore()\n\n async function fetchProducts(params: ProductListParams): Promise<PaginatedResponse<Product>> {\n const storeId = profileStore.store?.id\n const stockId = cartStore.order?.stock?.id\n const cityId = stockId ? undefined : profileStore.city?.id\n\n if (!storeId || (!stockId && !cityId)) {\n return emptyPage(params.page ?? 1, params.count ?? 0)\n }\n\n return sdk.products.getProducts(storeId, {\n category_id: params.categoryId,\n collection_id: params.collectionId,\n with: PRODUCT_LIST_INCLUDES,\n order_by: params.orderBy,\n page: params.page,\n count: params.count,\n stock_id: stockId,\n city_id: cityId,\n })\n }\n\n return { fetchProducts }\n}\n","/**\n * Internal color math for derived badge palettes. Not part of the public API: only the\n * helpers built on top of it (see `products/badges.ts`) are exported from the package.\n */\n\nexport type Rgb = [number, number, number]\n\nexport interface HueRotationOptions {\n lightnessBoost?: number\n maxLightness?: number\n}\n\nexport const WHITE = '#ffffff'\nexport const BLACK = '#000000'\n\nconst CONTRAST_STEPS = 14\nconst CONTRAST_STEP_WEIGHT = 0.1\n\nexport function parseHex(hex: string): Rgb {\n const digits = hex.slice(1)\n const full =\n digits.length <= 4\n ? digits\n .split('')\n .map((char) => char + char)\n .join('')\n : digits\n\n return [0, 2, 4].map((offset) => parseInt(full.slice(offset, offset + 2), 16)) as Rgb\n}\n\nexport function toHex([r, g, b]: Rgb): string {\n return `#${[r, g, b]\n .map((channel) =>\n Math.round(Math.max(0, Math.min(255, channel)))\n .toString(16)\n .padStart(2, '0')\n )\n .join('')}`\n}\n\nexport function luminance(hex: string): number {\n const [r, g, b] = parseHex(hex).map((channel) => {\n const value = channel / 255\n\n return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4\n }) as Rgb\n\n return 0.2126 * r + 0.7152 * g + 0.0722 * b\n}\n\nexport function contrastRatio(a: string, b: string): number {\n const first = luminance(a)\n const second = luminance(b)\n\n return (Math.max(first, second) + 0.05) / (Math.min(first, second) + 0.05)\n}\n\nexport function chroma(hex: string): number {\n const channels = parseHex(hex).map((channel) => channel / 255)\n\n return Math.max(...channels) - Math.min(...channels)\n}\n\n/** Linear RGB mix: `weightOfTo` 0 returns `from`, 1 returns `to`. */\nexport function mixColors(from: string, to: string, weightOfTo: number): string {\n const a = parseHex(from)\n const b = parseHex(to)\n\n return toHex(a.map((channel, index) => channel + (b[index]! - channel) * weightOfTo) as Rgb)\n}\n\nexport function toRgba(hex: string, alpha: number): string {\n const [r, g, b] = parseHex(hex)\n\n return `rgba(${r}, ${g}, ${b}, ${alpha})`\n}\n\n/** Rotates the hue in HSL space; `lightnessBoost` is added to lightness and capped by `maxLightness`. */\nexport function rotateHue(\n hex: string,\n degrees: number,\n { lightnessBoost = 0, maxLightness = 1 }: HueRotationOptions = {}\n): string {\n const [r, g, b] = parseHex(hex).map((channel) => channel / 255) as Rgb\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const delta = max - min\n const lightness = (max + min) / 2\n let hue = 0\n let saturation = 0\n\n if (delta) {\n saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min)\n\n if (max === r) hue = (g - b) / delta + (g < b ? 6 : 0)\n else if (max === g) hue = (b - r) / delta + 2\n else hue = (r - g) / delta + 4\n\n hue *= 60\n }\n\n const rotatedHue = (((hue + degrees) % 360) + 360) % 360\n const rotatedLightness = Math.min(lightness + lightnessBoost, maxLightness)\n const spread = ((1 - Math.abs(2 * rotatedLightness - 1)) * saturation) / 2\n const channel = (offset: number): number => {\n const position = (offset + rotatedHue / 30) % 12\n const value =\n rotatedLightness - spread * Math.max(-1, Math.min(position - 3, 9 - position, 1))\n\n return value * 255\n }\n\n return toHex([channel(0), channel(8), channel(4)])\n}\n\n/** Moves `color` toward black or white (whichever contrasts with `against`) until `minimum` is met. */\nexport function ensureContrast(color: string, against: string, minimum: number): string {\n const target = luminance(against) > 0.5 ? BLACK : WHITE\n let result = color\n\n for (let step = 0; step < CONTRAST_STEPS && contrastRatio(result, against) < minimum; step++) {\n result = mixColors(result, target, CONTRAST_STEP_WEIGHT)\n }\n\n return result\n}\n","import type { ProductBadge, ProductBadgeColors } from '@zenky/storefront-api'\n\nimport {\n BLACK,\n WHITE,\n chroma,\n contrastRatio,\n ensureContrast,\n luminance,\n rotateHue,\n toRgba,\n} from '../utils/color'\n\n/** A merchant badge validated and normalized for rendering. */\nexport interface ProductBadgeView {\n id: string\n label: string | null\n emoji: string | null\n imageUrl: string | null\n colors: ProductBadgeColors | null\n}\n\n/** `image-square`: an image without a label, drawn as a square with no background. */\nexport type ProductBadgeLayout = 'text' | 'image-square'\n\n/** Colors derived from a badge's own text/background pair, for styles other than solid. */\nexport interface ProductBadgeAccent {\n base: string\n shifted: string\n on: string\n text: string\n glass: string\n}\n\nexport interface ProductBadgeVisibility {\n showText: boolean\n showImages: boolean\n}\n\nconst ON_ACCENT_CONTRAST_MIN = 3\nconst TEXT_CONTRAST_MIN = 4.5\nconst NEUTRAL_CHROMA_GAP = 0.08\nconst HUE_SHIFT = 38\nconst HUE_SHIFT_LIGHTNESS_BOOST = 0.06\nconst HUE_SHIFT_MAX_LIGHTNESS = 0.7\nconst GLASS_ALPHA = 0.35\n\nconst HEX_COLOR = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i\nconst HTTP_URL = /^https?:\\/\\//i\n\nfunction cleanText(value: unknown): string | null {\n if (typeof value !== 'string') return null\n\n const text = value.trim()\n\n return text || null\n}\n\nfunction dropAlpha(hex: string): string {\n if (hex.length === 5) return hex.slice(0, 4)\n if (hex.length === 9) return hex.slice(0, 7)\n\n return hex\n}\n\nfunction toColors(badge: ProductBadge): ProductBadgeColors | null {\n const background = cleanText(badge.colors?.background)\n const text = cleanText(badge.colors?.text)\n\n if (!background || !text || !HEX_COLOR.test(background) || !HEX_COLOR.test(text)) {\n return null\n }\n\n return { background: dropAlpha(background), text: dropAlpha(text) }\n}\n\nfunction toView(badge: ProductBadge): ProductBadgeView | null {\n const label = cleanText(badge.label)\n const iconValue = cleanText(badge.icon?.value)\n const emoji = badge.icon?.type === 'emoji' ? iconValue : null\n const imageUrl =\n badge.icon?.type === 'image' && iconValue && HTTP_URL.test(iconValue) ? iconValue : null\n\n if (!label && !emoji && !imageUrl) return null\n\n return { id: badge.id, label, emoji, imageUrl, colors: toColors(badge) }\n}\n\n/**\n * Validates the backend `Product.badges` list: drops badges with nothing to show, repeated\n * ids and unusable icons, accepts only hex colors (alpha is ignored) and http(s) image urls.\n * `colors` is `null` when either color is missing or invalid, so the consumer can fall back\n * to its own theme.\n */\nexport function toProductBadgeViews(badges: ProductBadge[] | null | undefined): ProductBadgeView[] {\n if (!Array.isArray(badges)) return []\n\n const result: ProductBadgeView[] = []\n const seen = new Set<string>()\n\n for (const badge of badges) {\n if (!badge || typeof badge.id !== 'string' || !badge.id || seen.has(badge.id)) continue\n\n const view = toView(badge)\n if (!view) continue\n\n seen.add(badge.id)\n result.push(view)\n }\n\n return result\n}\n\nexport function getProductBadgeLayout(badge: ProductBadgeView): ProductBadgeLayout {\n return !badge.label && badge.imageUrl ? 'image-square' : 'text'\n}\n\nfunction pickAccent(colors: ProductBadgeColors): string {\n const textChroma = chroma(colors.text)\n const backgroundChroma = chroma(colors.background)\n\n if (Math.abs(textChroma - backgroundChroma) > NEUTRAL_CHROMA_GAP) {\n return textChroma > backgroundChroma ? colors.text : colors.background\n }\n\n return luminance(colors.text) <= luminance(colors.background) ? colors.text : colors.background\n}\n\n/**\n * Derives a palette from the badge's own colors: the more chromatic of text/background\n * becomes the accent (darker one when both are neutral), `on` is white or black, whichever\n * stays readable on it, `shifted` is the hue-rotated gradient end and `glass` is a\n * translucent fill. Pure JS math, no CSS color functions, so it works for any hex input.\n */\nexport function getProductBadgeAccent(colors: ProductBadgeColors): ProductBadgeAccent {\n const base = pickAccent(colors)\n const on = contrastRatio(WHITE, base) >= ON_ACCENT_CONTRAST_MIN ? WHITE : BLACK\n\n return {\n base,\n shifted: ensureContrast(\n rotateHue(base, HUE_SHIFT, {\n lightnessBoost: HUE_SHIFT_LIGHTNESS_BOOST,\n maxLightness: HUE_SHIFT_MAX_LIGHTNESS,\n }),\n on,\n ON_ACCENT_CONTRAST_MIN\n ),\n on,\n text: ensureContrast(base, WHITE, TEXT_CONTRAST_MIN),\n glass: toRgba(base, GLASS_ALPHA),\n }\n}\n\nexport function filterProductBadges(\n badges: ProductBadgeView[],\n visibility: ProductBadgeVisibility\n): ProductBadgeView[] {\n return badges.filter((badge) =>\n getProductBadgeLayout(badge) === 'image-square'\n ? visibility.showImages\n : visibility.showText\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/createOperationChain.ts","../src/utils/phone.ts","../src/utils/contacts.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-RURXGVWW.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 { ContactType } from '@zenky/storefront-api'\n\nimport type { Contact } from '@zenky/storefront-api'\n\nexport interface SocialLink {\n type: ContactType\n url: string\n label: string\n}\n\nconst SOCIAL_TYPES = new Set<ContactType>([\n ContactType.Vk,\n ContactType.Instagram,\n ContactType.Facebook,\n ContactType.Twitter,\n ContactType.Ok,\n ContactType.Tiktok,\n ContactType.Telegram,\n ContactType.Max,\n])\n\nconst SOCIAL_LABELS: Record<string, string> = {\n [ContactType.Vk]: 'ВКонтакте',\n [ContactType.Instagram]: 'Instagram',\n [ContactType.Facebook]: 'Facebook',\n [ContactType.Twitter]: 'Twitter',\n [ContactType.Ok]: 'Одноклассники',\n [ContactType.Tiktok]: 'TikTok',\n [ContactType.Telegram]: 'Telegram',\n [ContactType.Max]: 'Max',\n} as const\n\nfunction buildSocialUrl(type: ContactType, value: string): string {\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return value\n }\n\n const bases: Partial<Record<ContactType, string>> = {\n [ContactType.Vk]: 'https://vk.com/',\n [ContactType.Instagram]: 'https://instagram.com/',\n [ContactType.Facebook]: 'https://facebook.com/',\n [ContactType.Twitter]: 'https://x.com/',\n [ContactType.Ok]: 'https://ok.ru/',\n [ContactType.Tiktok]: 'https://tiktok.com/@',\n [ContactType.Telegram]: 'https://t.me/',\n [ContactType.Max]: 'https://max.ru/',\n }\n\n const base = bases[type]\n\n return base ? `${base}${value}` : value\n}\n\nexport function getSocialLinks(contacts: Contact[]): SocialLink[] {\n return contacts\n .filter((contact) => SOCIAL_TYPES.has(contact.type))\n .map((contact) => ({\n type: contact.type,\n url: buildSocialUrl(contact.type, contact.value),\n label: SOCIAL_LABELS[contact.type] ?? contact.type,\n }))\n}\n\nexport function getEmailLink(contacts: Contact[]): string | null {\n const email = contacts.find((c) => c.type === ContactType.Email)\n\n return email?.value ?? null\n}\n\nexport function getWebsiteLink(contacts: Contact[]): string | null {\n const website = contacts.find((c) => c.type === ContactType.Website)\n\n return website?.value ?? null\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"]}