@wix/web5-core 1.63.6 → 1.63.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/component/componentDefinitions/CalloutSectionDefinition.js +102 -5
  2. package/dist/cjs/component/componentDefinitions/CalloutSectionDefinition.js.map +1 -1
  3. package/dist/cjs/component/componentDefinitions/index.js +8 -2
  4. package/dist/cjs/component/componentDefinitions/index.js.map +1 -1
  5. package/dist/cjs/component/componentDefinitions/parse-utils.js +14 -6
  6. package/dist/cjs/component/componentDefinitions/parse-utils.js.map +1 -1
  7. package/dist/cjs/component/types.js.map +1 -1
  8. package/dist/cjs/hooks/useResolveSearchSpringEntityData.js +17 -1
  9. package/dist/cjs/hooks/useResolveSearchSpringEntityData.js.map +1 -1
  10. package/dist/cjs/hooks/useResolveShopifyEntityData.js +30 -9
  11. package/dist/cjs/hooks/useResolveShopifyEntityData.js.map +1 -1
  12. package/dist/cjs/index.js +4 -3
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/services/shopify/transformShopifyEntity.js +27 -6
  15. package/dist/cjs/services/shopify/transformShopifyEntity.js.map +1 -1
  16. package/dist/cjs/types/callout.js +11 -1
  17. package/dist/cjs/types/callout.js.map +1 -1
  18. package/dist/esm/component/componentDefinitions/CalloutSectionDefinition.js +104 -6
  19. package/dist/esm/component/componentDefinitions/CalloutSectionDefinition.js.map +1 -1
  20. package/dist/esm/component/componentDefinitions/index.js +8 -2
  21. package/dist/esm/component/componentDefinitions/index.js.map +1 -1
  22. package/dist/esm/component/componentDefinitions/parse-utils.js +14 -6
  23. package/dist/esm/component/componentDefinitions/parse-utils.js.map +1 -1
  24. package/dist/esm/component/types.js.map +1 -1
  25. package/dist/esm/hooks/useResolveSearchSpringEntityData.js +17 -1
  26. package/dist/esm/hooks/useResolveSearchSpringEntityData.js.map +1 -1
  27. package/dist/esm/hooks/useResolveShopifyEntityData.js +30 -9
  28. package/dist/esm/hooks/useResolveShopifyEntityData.js.map +1 -1
  29. package/dist/esm/index.js +1 -1
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/services/shopify/transformShopifyEntity.js +27 -6
  32. package/dist/esm/services/shopify/transformShopifyEntity.js.map +1 -1
  33. package/dist/esm/types/callout.js +10 -0
  34. package/dist/esm/types/callout.js.map +1 -1
  35. package/dist/types/component/componentDefinitions/CalloutSectionDefinition.d.ts +37 -2
  36. package/dist/types/component/componentDefinitions/CalloutSectionDefinition.d.ts.map +1 -1
  37. package/dist/types/component/componentDefinitions/index.d.ts.map +1 -1
  38. package/dist/types/component/componentDefinitions/parse-utils.d.ts +8 -1
  39. package/dist/types/component/componentDefinitions/parse-utils.d.ts.map +1 -1
  40. package/dist/types/component/types.d.ts +8 -0
  41. package/dist/types/component/types.d.ts.map +1 -1
  42. package/dist/types/hooks/useResolveSearchSpringEntityData.d.ts +11 -0
  43. package/dist/types/hooks/useResolveSearchSpringEntityData.d.ts.map +1 -1
  44. package/dist/types/hooks/useResolveShopifyEntityData.d.ts +11 -0
  45. package/dist/types/hooks/useResolveShopifyEntityData.d.ts.map +1 -1
  46. package/dist/types/index.d.ts +3 -3
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/dist/types/services/shopify/transformShopifyEntity.d.ts +2 -2
  49. package/dist/types/services/shopify/transformShopifyEntity.d.ts.map +1 -1
  50. package/dist/types/types/callout.d.ts +11 -0
  51. package/dist/types/types/callout.d.ts.map +1 -1
  52. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["../../../src/component/types.ts"],"sourcesContent":["import type { FC } from 'react';\nimport type { Callout } from '../types/callout';\n\n/** Props extracted from markdown (base layer). */\nexport interface BaseCompProps {}\nexport interface SlotCompProps extends BaseCompProps {\n callout?: Callout;\n}\n\nexport interface SectionCompProps extends BaseCompProps {\n callout?: Callout;\n}\n\n/** Section props with a slot. TSlot enforces which slot component this section accepts. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface SectionCompPropsWithSlot<TSlot extends FC<any> = FC<any>>\n extends SectionCompProps {\n slot?: TSlot;\n}\n\n// ----------------------\n// Base Components\n// ----------------------\n\nexport interface TextCompProps extends BaseCompProps {\n content: string;\n variant?: 'h1' | 'h2' | 'body' | 'caption';\n}\n\nexport interface ButtonCompProps extends BaseCompProps {\n label: string;\n variant?: 'primary' | 'secondary' | 'ghost';\n onClick?: string;\n}\n\nexport interface ImageCompProps extends BaseCompProps {\n src: string;\n alt: string;\n ratio?: '16:9' | '4:3' | '1:1' | '9:16' | '3:4';\n}\n\nexport interface BadgeCompProps extends BaseCompProps {\n label: string;\n color?: 'primary' | 'secondary' | 'success' | 'warning' | 'error';\n}\n\n// ----------------------\n// Hero Button (aligned to HeroSection1Button)\n// ----------------------\n\nexport interface HeroButton {\n id: string;\n text: string;\n variant?: 'primary' | 'secondary';\n onClick?: string;\n}\n\n// ----------------------\n// Slot Components\n// ----------------------\n\nexport interface KpiItemCompProps extends SlotCompProps {\n title: string;\n description: string;\n icon?: string;\n}\n\n/** Feature item — aligned to web50-server-ui Feature interface */\nexport interface FeatureItemCompProps extends SlotCompProps {\n title?: string;\n description?: string;\n icon?: string;\n}\n\n/** Feature card — aligned to web50-server-ui FeatureCard */\nexport interface FeatureCardCompProps extends SlotCompProps {\n title: string;\n description: string;\n imageUrl?: string;\n imageFromText?: boolean;\n linkText?: string;\n linkHref?: string;\n callout?: Callout;\n}\n\n/** Resolved entity data (populated at runtime via useResolveGenericEntityData) */\nexport interface EntityItemData {\n url: string;\n title: string;\n type: string;\n description?: string;\n excerpt?: string;\n imageUrl?: string;\n date?: string;\n publishDate?: string;\n author?: string;\n cmsItemId?: string;\n usage?: number;\n tags?: string[];\n /** Product vendor / brand name (e.g. \"HOKA\") */\n vendor?: string;\n /**\n * The `{ name, value }` pairs of the one variant a search matched, in the\n * store's own order. Present only when retrieval resolved the product down\n * to a single variant. The names are the store's own, so read this by\n * iterating it — never by looking a name up.\n */\n matchedOptions?: { name: string; value: string }[];\n /** Formatted lowest price across the product's variants (e.g. \"$107.95\") */\n priceMin?: string;\n /** Formatted highest price across the product's variants */\n priceMax?: string;\n /** Formatted price string (e.g. \"542.00 NIS\") */\n price?: string;\n /** Secondary product image URL — shown on hover */\n secondaryImageUrl?: string;\n /** Available sizes for the product */\n sizes?: string[];\n /** Original price before discount (formatted, e.g. \"494.00 NIS\") — shown with strikethrough */\n compareAtPrice?: string;\n /** Discount percentage (e.g. \"30% OFF\") */\n discountPercent?: string;\n /** Product variants with IDs and availability — used for add-to-cart and size display */\n variants?: {\n label: string;\n variantId: string;\n available: boolean;\n selectedOptions?: { name: string; value: string }[];\n price?: string;\n compareAtPrice?: string;\n }[];\n /** All product image URLs (not just featured + secondary) */\n allImages?: string[];\n /** Product option groups (e.g. Size, Color) with their available values */\n options?: { name: string; values: string[] }[];\n}\n\n/** Single entity item within an entity section */\nexport interface EntityItem {\n entityId: string;\n linkText?: string;\n entityType: string;\n entityUrl: string;\n description?: string;\n imageUrl?: string;\n /** Per-item callout from a blockquote inside the list item */\n callout?: Callout;\n /** Resolved at runtime via useResolveGenericEntityData hook; not produced by parse() */\n data?: EntityItemData;\n}\n\n// ---------------------------------------------------------------------------\n// Deprecated aliases — kept for seed-components compilation\n// ---------------------------------------------------------------------------\n/** @deprecated Use EntityItemData */\nexport type GenericEntityData = EntityItemData;\n/** @deprecated Use EntityItemData */\nexport type SolutionEntityData = EntityItemData;\n/** @deprecated Use EntityItemData */\nexport type BlogEntityData = EntityItemData;\n/** @deprecated Use EntityItem */\nexport type GenericEntityCompProps = EntityItem;\n\n/** Comparison row — aligned to web50-server-ui ComparisonRow */\nexport interface ComparisonRow {\n feature: string;\n iconHint?: string;\n values: (boolean | string)[];\n}\n\nexport interface ComparisonColumn {\n label: string;\n href?: string;\n entityId?: string;\n entityType?: string;\n}\n\n/** @deprecated Use Callout from types/callout instead */\nexport interface AiNarrativeCompProps extends SlotCompProps {\n content: string;\n}\n\n// ----------------------\n// Section Components\n// ----------------------\n\n/** Hero — aligned to HeroSection1Props */\nexport interface HeroCompProps extends SectionCompProps {\n headline: string;\n badge?: string | { text: string; showIndicator?: boolean };\n content?: string;\n buttons?: HeroButton[];\n image?: string;\n trailingList?: string;\n leadingQuote?: string;\n}\n\n/**\n * Entity hero — a hero section whose body carries one or more web5 entity\n * links (`web5://entity/...`). Shares the hero framing fields with\n * {@link HeroCompProps} but, instead of CTA buttons, surfaces the entities as\n * resolvable {@link EntityItem}s for rich rendering.\n */\nexport interface HeroEntityCompProps extends SectionCompProps {\n headline: string;\n badge?: string | { text: string; showIndicator?: boolean };\n content?: string;\n image?: string;\n leadingQuote?: string;\n items: EntityItem[];\n}\n\n/** KPI — aligned to KpiSectionProps */\nexport interface KpiCompProps\n extends SectionCompPropsWithSlot<KpiItemComponent> {\n title: string;\n items: KpiItemCompProps[];\n}\n\n/** Feature cards — aligned to FeatureCardsSectionProps */\nexport interface FeatureCardsCompProps extends SectionCompProps {\n cards: FeatureCardCompProps[];\n}\n\n/** Unified entity section — replaces EntityCompProps, SolutionEntityCompProps, BlogEntityCompProps */\nexport interface EntityCompProps extends SectionCompProps {\n title: string;\n description?: string;\n items: EntityItem[];\n}\n\n/** Comparison — aligned to ComparisonSection1Props */\nexport interface ComparisonCompProps extends SectionCompProps {\n title: string;\n description?: string;\n columnLabels: string[];\n columns?: ComparisonColumn[];\n rows: ComparisonRow[];\n featureColumnLabel?: string;\n ctaText?: string;\n ctaHref?: string;\n}\n\n/** General text — aligned to GeneralTextSectionProps (used by Fallback) */\nexport interface GeneralTextCompProps extends SectionCompProps {\n markdown: string;\n}\n\n/** Callout — aligned to CalloutSectionProps */\nexport interface CalloutCompProps extends SectionCompProps {\n callouts: Callout[];\n title?: string;\n relatedLinks?: { text: string; url: string }[];\n}\n\n/** Next steps — aligned to NextStepsSectionProps */\nexport interface NextStepsCompProps extends SectionCompProps {\n title: string;\n body?: string;\n /**\n * True when the chips are already rendered inline inside `body`. Renderers\n * must show `body` alone in that case — listing `steps` as well repeats every\n * chip. `steps` stays populated either way; it is the machine-readable chip\n * list (the scroll chips under the answer are built from it).\n */\n chipsInlineInBody?: boolean;\n backgroundImage?: string;\n steps: { content: string; iconHint?: string }[];\n}\n\n/** Feature section 9+ — aligned to FeatureSection9PlusProps */\nexport interface FeatureSection9PlusCompProps extends SectionCompProps {\n title: string;\n description?: string;\n features: { title?: string; description: string; iconHint?: string }[];\n}\n\n/** List items section — title + a list of feature items. */\nexport interface ListItemsSectionCompProps extends SectionCompProps {\n title: string;\n features: { title?: string; description: string }[];\n}\n\nexport type ListItemsSectionComponent = FC<ListItemsSectionCompProps>;\n\n/** Error — aligned to ErrorSection */\nexport interface ErrorCompProps extends SectionCompProps {\n type: import('../errors/conversationErrorTypes').ConversationErrorType;\n}\n\n/** Skip/HTML/Search — null-component parsers */\nexport interface NullCompProps extends SectionCompProps {}\n\n/** @deprecated Use EntityCompProps */\nexport type SolutionEntityCompProps = EntityCompProps;\n/** @deprecated Use EntityCompProps */\nexport type BlogEntityCompProps = EntityCompProps;\n\n/** CTA Banner — dark purple gradient card with headline, description, and pill link buttons */\nexport interface CtaBannerCompProps extends SectionCompProps {\n headline: string;\n description?: string;\n links: { text: string; href: string }[];\n /** Contextual background image — resolved from allowed keywords during parse() */\n imageUrl?: string;\n imageFromText?: boolean;\n}\n\nexport type CtaBannerSectionComponent = FC<CtaBannerCompProps>;\n\n/** Text block — heading + body with an optional pullquote callout on the side */\nexport interface TextBlockCompProps extends SectionCompProps {\n title: string;\n description: string;\n}\n\n/** Personalized narrative — standalone section with no parse() definition */\nexport interface PersonalizedNarrativeCompProps extends SectionCompProps {\n title: string;\n content?: string;\n}\n\n// --------------------------------\n// Types of component - all components\n// --------------------------------\n\nexport type Component = BaseComponent | SlotComponent | SectionComponent;\n\nexport type BaseComponent = FC<BaseCompProps>;\nexport type SlotComponent = FC<SlotCompProps>;\nexport type SectionComponent = FC<SectionCompProps>;\n\n// Base Components\nexport type TextComponent = FC<TextCompProps>;\nexport type ButtonComponent = FC<ButtonCompProps>;\nexport type ImageComponent = FC<ImageCompProps>;\nexport type BadgeComponent = FC<BadgeCompProps>;\n\n// Slot Components\nexport type KpiItemComponent = FC<KpiItemCompProps>;\nexport type FeatureItemComponent = FC<FeatureItemCompProps>;\nexport type FeatureCardComponent = FC<FeatureCardCompProps>;\n/** @deprecated Use FC<EntityItem> */\nexport type GenericEntityComponent = FC<EntityItem>;\nexport type AiNarrativeComponent = FC<AiNarrativeCompProps>;\n\n// Section Components\nexport type ComparisonSectionComponent = FC<ComparisonCompProps>;\nexport type GeneralTextSectionComponent = FC<GeneralTextCompProps>;\nexport type TextBlockSectionComponent = FC<TextBlockCompProps>;\nexport type HeroSectionComponent = FC<HeroCompProps>;\nexport type HeroEntitySectionComponent = FC<HeroEntityCompProps>;\n\n// section components with slots\nexport type KpiSectionComponent = FC<KpiCompProps>;\nexport type FeatureCardsSectionComponent = FC<FeatureCardsCompProps>;\nexport type EntitySectionComponent = FC<EntityCompProps>;\n\n// New section component types for Phase 4\nexport type CalloutSectionComponent = FC<CalloutCompProps>;\nexport type NextStepsSectionComponent = FC<NextStepsCompProps>;\nexport type FeatureSection9PlusSectionComponent =\n FC<FeatureSection9PlusCompProps>;\nexport type NullSectionComponent = FC<NullCompProps>;\nexport type ErrorSectionComponent = FC<ErrorCompProps>;\nexport type SolutionEntitySectionComponent = FC<SolutionEntityCompProps>;\nexport type BlogEntitySectionComponent = FC<BlogEntityCompProps>;\nexport type PersonalizedNarrativeSectionComponent =\n FC<PersonalizedNarrativeCompProps>;\n\nexport type PropsOf<T> = T extends (props: infer P) => unknown ? P : never;\n\nexport interface SectionFixture<TProps> {\n markdown: string;\n expected: Partial<TProps>;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["../../../src/component/types.ts"],"sourcesContent":["import type { FC } from 'react';\nimport type { Callout } from '../types/callout';\n\n/** Props extracted from markdown (base layer). */\nexport interface BaseCompProps {}\nexport interface SlotCompProps extends BaseCompProps {\n callout?: Callout;\n}\n\nexport interface SectionCompProps extends BaseCompProps {\n callout?: Callout;\n}\n\n/** Section props with a slot. TSlot enforces which slot component this section accepts. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface SectionCompPropsWithSlot<TSlot extends FC<any> = FC<any>>\n extends SectionCompProps {\n slot?: TSlot;\n}\n\n// ----------------------\n// Base Components\n// ----------------------\n\nexport interface TextCompProps extends BaseCompProps {\n content: string;\n variant?: 'h1' | 'h2' | 'body' | 'caption';\n}\n\nexport interface ButtonCompProps extends BaseCompProps {\n label: string;\n variant?: 'primary' | 'secondary' | 'ghost';\n onClick?: string;\n}\n\nexport interface ImageCompProps extends BaseCompProps {\n src: string;\n alt: string;\n ratio?: '16:9' | '4:3' | '1:1' | '9:16' | '3:4';\n}\n\nexport interface BadgeCompProps extends BaseCompProps {\n label: string;\n color?: 'primary' | 'secondary' | 'success' | 'warning' | 'error';\n}\n\n// ----------------------\n// Hero Button (aligned to HeroSection1Button)\n// ----------------------\n\nexport interface HeroButton {\n id: string;\n text: string;\n variant?: 'primary' | 'secondary';\n onClick?: string;\n}\n\n// ----------------------\n// Slot Components\n// ----------------------\n\nexport interface KpiItemCompProps extends SlotCompProps {\n title: string;\n description: string;\n icon?: string;\n}\n\n/** Feature item — aligned to web50-server-ui Feature interface */\nexport interface FeatureItemCompProps extends SlotCompProps {\n title?: string;\n description?: string;\n icon?: string;\n}\n\n/** Feature card — aligned to web50-server-ui FeatureCard */\nexport interface FeatureCardCompProps extends SlotCompProps {\n title: string;\n description: string;\n imageUrl?: string;\n imageFromText?: boolean;\n linkText?: string;\n linkHref?: string;\n callout?: Callout;\n}\n\n/** Resolved entity data (populated at runtime via useResolveGenericEntityData) */\nexport interface EntityItemData {\n url: string;\n title: string;\n type: string;\n description?: string;\n excerpt?: string;\n imageUrl?: string;\n date?: string;\n publishDate?: string;\n author?: string;\n cmsItemId?: string;\n usage?: number;\n tags?: string[];\n /** Product vendor / brand name (e.g. \"HOKA\") */\n vendor?: string;\n /**\n * The `{ name, value }` pairs of the one variant a search matched, in the\n * store's own order. Present only when retrieval resolved the product down\n * to a single variant. The names are the store's own, so read this by\n * iterating it — never by looking a name up.\n */\n matchedOptions?: { name: string; value: string }[];\n /**\n * Id of the one variant a search matched — the same variant `imageUrl`,\n * `url` and `matchedOptions` describe. Bare store id, no `gid://` prefix.\n * A live enricher reads this to price that variant rather than the product.\n */\n variantId?: string;\n /** Whether the matched variant is in stock, as of the last live fetch */\n available?: boolean;\n /** Formatted lowest price across the product's variants (e.g. \"$107.95\") */\n priceMin?: string;\n /** Formatted highest price across the product's variants */\n priceMax?: string;\n /** Formatted price string (e.g. \"542.00 NIS\") */\n price?: string;\n /** Secondary product image URL — shown on hover */\n secondaryImageUrl?: string;\n /** Available sizes for the product */\n sizes?: string[];\n /** Original price before discount (formatted, e.g. \"494.00 NIS\") — shown with strikethrough */\n compareAtPrice?: string;\n /** Discount percentage (e.g. \"30% OFF\") */\n discountPercent?: string;\n /** Product variants with IDs and availability — used for add-to-cart and size display */\n variants?: {\n label: string;\n variantId: string;\n available: boolean;\n selectedOptions?: { name: string; value: string }[];\n price?: string;\n compareAtPrice?: string;\n }[];\n /** All product image URLs (not just featured + secondary) */\n allImages?: string[];\n /** Product option groups (e.g. Size, Color) with their available values */\n options?: { name: string; values: string[] }[];\n}\n\n/** Single entity item within an entity section */\nexport interface EntityItem {\n entityId: string;\n linkText?: string;\n entityType: string;\n entityUrl: string;\n description?: string;\n imageUrl?: string;\n /** Per-item callout from a blockquote inside the list item */\n callout?: Callout;\n /** Resolved at runtime via useResolveGenericEntityData hook; not produced by parse() */\n data?: EntityItemData;\n}\n\n// ---------------------------------------------------------------------------\n// Deprecated aliases — kept for seed-components compilation\n// ---------------------------------------------------------------------------\n/** @deprecated Use EntityItemData */\nexport type GenericEntityData = EntityItemData;\n/** @deprecated Use EntityItemData */\nexport type SolutionEntityData = EntityItemData;\n/** @deprecated Use EntityItemData */\nexport type BlogEntityData = EntityItemData;\n/** @deprecated Use EntityItem */\nexport type GenericEntityCompProps = EntityItem;\n\n/** Comparison row — aligned to web50-server-ui ComparisonRow */\nexport interface ComparisonRow {\n feature: string;\n iconHint?: string;\n values: (boolean | string)[];\n}\n\nexport interface ComparisonColumn {\n label: string;\n href?: string;\n entityId?: string;\n entityType?: string;\n}\n\n/** @deprecated Use Callout from types/callout instead */\nexport interface AiNarrativeCompProps extends SlotCompProps {\n content: string;\n}\n\n// ----------------------\n// Section Components\n// ----------------------\n\n/** Hero — aligned to HeroSection1Props */\nexport interface HeroCompProps extends SectionCompProps {\n headline: string;\n badge?: string | { text: string; showIndicator?: boolean };\n content?: string;\n buttons?: HeroButton[];\n image?: string;\n trailingList?: string;\n leadingQuote?: string;\n}\n\n/**\n * Entity hero — a hero section whose body carries one or more web5 entity\n * links (`web5://entity/...`). Shares the hero framing fields with\n * {@link HeroCompProps} but, instead of CTA buttons, surfaces the entities as\n * resolvable {@link EntityItem}s for rich rendering.\n */\nexport interface HeroEntityCompProps extends SectionCompProps {\n headline: string;\n badge?: string | { text: string; showIndicator?: boolean };\n content?: string;\n image?: string;\n leadingQuote?: string;\n items: EntityItem[];\n}\n\n/** KPI — aligned to KpiSectionProps */\nexport interface KpiCompProps\n extends SectionCompPropsWithSlot<KpiItemComponent> {\n title: string;\n items: KpiItemCompProps[];\n}\n\n/** Feature cards — aligned to FeatureCardsSectionProps */\nexport interface FeatureCardsCompProps extends SectionCompProps {\n cards: FeatureCardCompProps[];\n}\n\n/** Unified entity section — replaces EntityCompProps, SolutionEntityCompProps, BlogEntityCompProps */\nexport interface EntityCompProps extends SectionCompProps {\n title: string;\n description?: string;\n items: EntityItem[];\n}\n\n/** Comparison — aligned to ComparisonSection1Props */\nexport interface ComparisonCompProps extends SectionCompProps {\n title: string;\n description?: string;\n columnLabels: string[];\n columns?: ComparisonColumn[];\n rows: ComparisonRow[];\n featureColumnLabel?: string;\n ctaText?: string;\n ctaHref?: string;\n}\n\n/** General text — aligned to GeneralTextSectionProps (used by Fallback) */\nexport interface GeneralTextCompProps extends SectionCompProps {\n markdown: string;\n}\n\n/** Callout — aligned to CalloutSectionProps */\nexport interface CalloutCompProps extends SectionCompProps {\n callouts: Callout[];\n title?: string;\n relatedLinks?: { text: string; url: string }[];\n}\n\n/** Next steps — aligned to NextStepsSectionProps */\nexport interface NextStepsCompProps extends SectionCompProps {\n title: string;\n body?: string;\n /**\n * True when the chips are already rendered inline inside `body`. Renderers\n * must show `body` alone in that case — listing `steps` as well repeats every\n * chip. `steps` stays populated either way; it is the machine-readable chip\n * list (the scroll chips under the answer are built from it).\n */\n chipsInlineInBody?: boolean;\n backgroundImage?: string;\n steps: { content: string; iconHint?: string }[];\n}\n\n/** Feature section 9+ — aligned to FeatureSection9PlusProps */\nexport interface FeatureSection9PlusCompProps extends SectionCompProps {\n title: string;\n description?: string;\n features: { title?: string; description: string; iconHint?: string }[];\n}\n\n/** List items section — title + a list of feature items. */\nexport interface ListItemsSectionCompProps extends SectionCompProps {\n title: string;\n features: { title?: string; description: string }[];\n}\n\nexport type ListItemsSectionComponent = FC<ListItemsSectionCompProps>;\n\n/** Error — aligned to ErrorSection */\nexport interface ErrorCompProps extends SectionCompProps {\n type: import('../errors/conversationErrorTypes').ConversationErrorType;\n}\n\n/** Skip/HTML/Search — null-component parsers */\nexport interface NullCompProps extends SectionCompProps {}\n\n/** @deprecated Use EntityCompProps */\nexport type SolutionEntityCompProps = EntityCompProps;\n/** @deprecated Use EntityCompProps */\nexport type BlogEntityCompProps = EntityCompProps;\n\n/** CTA Banner — dark purple gradient card with headline, description, and pill link buttons */\nexport interface CtaBannerCompProps extends SectionCompProps {\n headline: string;\n description?: string;\n links: { text: string; href: string }[];\n /** Contextual background image — resolved from allowed keywords during parse() */\n imageUrl?: string;\n imageFromText?: boolean;\n}\n\nexport type CtaBannerSectionComponent = FC<CtaBannerCompProps>;\n\n/** Text block — heading + body with an optional pullquote callout on the side */\nexport interface TextBlockCompProps extends SectionCompProps {\n title: string;\n description: string;\n}\n\n/** Personalized narrative — standalone section with no parse() definition */\nexport interface PersonalizedNarrativeCompProps extends SectionCompProps {\n title: string;\n content?: string;\n}\n\n// --------------------------------\n// Types of component - all components\n// --------------------------------\n\nexport type Component = BaseComponent | SlotComponent | SectionComponent;\n\nexport type BaseComponent = FC<BaseCompProps>;\nexport type SlotComponent = FC<SlotCompProps>;\nexport type SectionComponent = FC<SectionCompProps>;\n\n// Base Components\nexport type TextComponent = FC<TextCompProps>;\nexport type ButtonComponent = FC<ButtonCompProps>;\nexport type ImageComponent = FC<ImageCompProps>;\nexport type BadgeComponent = FC<BadgeCompProps>;\n\n// Slot Components\nexport type KpiItemComponent = FC<KpiItemCompProps>;\nexport type FeatureItemComponent = FC<FeatureItemCompProps>;\nexport type FeatureCardComponent = FC<FeatureCardCompProps>;\n/** @deprecated Use FC<EntityItem> */\nexport type GenericEntityComponent = FC<EntityItem>;\nexport type AiNarrativeComponent = FC<AiNarrativeCompProps>;\n\n// Section Components\nexport type ComparisonSectionComponent = FC<ComparisonCompProps>;\nexport type GeneralTextSectionComponent = FC<GeneralTextCompProps>;\nexport type TextBlockSectionComponent = FC<TextBlockCompProps>;\nexport type HeroSectionComponent = FC<HeroCompProps>;\nexport type HeroEntitySectionComponent = FC<HeroEntityCompProps>;\n\n// section components with slots\nexport type KpiSectionComponent = FC<KpiCompProps>;\nexport type FeatureCardsSectionComponent = FC<FeatureCardsCompProps>;\nexport type EntitySectionComponent = FC<EntityCompProps>;\n\n// New section component types for Phase 4\nexport type CalloutSectionComponent = FC<CalloutCompProps>;\nexport type NextStepsSectionComponent = FC<NextStepsCompProps>;\nexport type FeatureSection9PlusSectionComponent =\n FC<FeatureSection9PlusCompProps>;\nexport type NullSectionComponent = FC<NullCompProps>;\nexport type ErrorSectionComponent = FC<ErrorCompProps>;\nexport type SolutionEntitySectionComponent = FC<SolutionEntityCompProps>;\nexport type BlogEntitySectionComponent = FC<BlogEntityCompProps>;\nexport type PersonalizedNarrativeSectionComponent =\n FC<PersonalizedNarrativeCompProps>;\n\nexport type PropsOf<T> = T extends (props: infer P) => unknown ? P : never;\n\nexport interface SectionFixture<TProps> {\n markdown: string;\n expected: Partial<TProps>;\n}\n"],"mappings":"","ignoreList":[]}
@@ -26,8 +26,20 @@ function getSearchSpringHandle(entity) {
26
26
  var _entity$data;
27
27
  return extractProductHandle((_entity$data = entity.data) == null ? void 0 : _entity$data.url) || entity.entityId;
28
28
  }
29
+
30
+ /**
31
+ * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about
32
+ * it.
33
+ *
34
+ * Only the turn saw the shopper's question, so only it knows that the brown
35
+ * variant was the one asked for — its `title`, `imageUrl`, `url`,
36
+ * `matchedOptions` and `variantId` all describe that one variant and must
37
+ * survive enrichment. Everything SearchSpring answers with that can go stale
38
+ * between the turn and the render — `price`, `compareAtPrice`, `available`,
39
+ * `priceMin`, `priceMax` — comes from `resolved`.
40
+ */
29
41
  export function mergeSearchSpringEntityData(existing, resolved) {
30
- var _existing$sizes, _existing$variants, _existing$options, _existing$allImages;
42
+ var _existing$matchedOpti, _existing$sizes, _existing$variants, _existing$options, _existing$allImages;
31
43
  if (!existing) {
32
44
  return resolved;
33
45
  }
@@ -35,6 +47,10 @@ export function mergeSearchSpringEntityData(existing, resolved) {
35
47
  ...existing,
36
48
  ...resolved,
37
49
  url: existing.url || resolved.url,
50
+ title: existing.title || resolved.title,
51
+ imageUrl: existing.imageUrl || resolved.imageUrl,
52
+ variantId: existing.variantId || resolved.variantId,
53
+ matchedOptions: (_existing$matchedOpti = existing.matchedOptions) != null && _existing$matchedOpti.length ? existing.matchedOptions : resolved.matchedOptions,
38
54
  sizes: (_existing$sizes = existing.sizes) != null && _existing$sizes.length ? existing.sizes : resolved.sizes,
39
55
  variants: (_existing$variants = existing.variants) != null && _existing$variants.length ? existing.variants : resolved.variants,
40
56
  options: (_existing$options = existing.options) != null && _existing$options.length ? existing.options : resolved.options,
@@ -1 +1 @@
1
- {"version":3,"names":["useState","useEffect","useMemo","fetchProductsByHandlesMap","transformSSProductToEntityItemData","ssEntityCache","Map","extractProductHandle","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","handle","slice","length","getSearchSpringHandle","entity","_entity$data","data","entityId","mergeSearchSpringEntityData","existing","resolved","_existing$sizes","_existing$variants","_existing$options","_existing$allImages","sizes","variants","options","allImages","useResolveSearchSpringEntityData","entities","config","resolvedMap","setResolvedMap","settled","setSettled","entityKey","map","e","entityType","join","ignore","siteId","productEntityHandles","filter","toLowerCase","includes","handlesToFetch","Set","_ref","has","cached","forEach","_ref2","item","get","set","fetchAll","productMap","product","itemData","finalMap","_ref3","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveSearchSpringEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { fetchProductsByHandlesMap } from '../services/searchspring/searchSpringClient';\nimport { transformSSProductToEntityItemData } from '../services/searchspring/transformSSProduct';\nimport type { SearchSpringConfig } from '../services/searchspring/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: handle → resolved EntityItemData\nconst ssEntityCache = new Map<string, EntityItemData>();\n\nfunction extractProductHandle(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n const handle =\n productsIndex >= 0\n ? withoutLeadingSlash.slice(productsIndex + 'products/'.length)\n : withoutLeadingSlash;\n\n return handle || undefined;\n}\n\nfunction getSearchSpringHandle(entity: {\n entityId: string;\n data?: EntityItemData;\n}): string {\n return extractProductHandle(entity.data?.url) || entity.entityId;\n}\n\nexport function mergeSearchSpringEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n sizes: existing.sizes?.length ? existing.sizes : resolved.sizes,\n variants: existing.variants?.length ? existing.variants : resolved.variants,\n options: existing.options?.length ? existing.options : resolved.options,\n allImages: existing.allImages?.length\n ? existing.allImages\n : resolved.allImages,\n };\n}\n\n/**\n * SearchSpring-backed entity resolution hook.\n *\n * Fetches product data from the SearchSpring Search API by handle\n * and transforms it to EntityItemData. Uses a single batched API call\n * for all products (bgfilter.handle supports OR).\n */\nexport function useResolveSearchSpringEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n config: SearchSpringConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable key for dependency tracking\n const entityKey = useMemo(\n () =>\n entities\n .map((e) => `${e.entityType}:${e.entityId}:${getSearchSpringHandle(e)}`)\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n\n if (!entities.length || !config.siteId) {\n setSettled(true);\n return;\n }\n\n const productEntityHandles = entities\n .filter((e) => e.entityType.toLowerCase().includes('product'))\n .map((entity) => ({\n entity,\n handle: getSearchSpringHandle(entity),\n }));\n\n // Collect handles that need fetching. CMS payload IDs use payload url as the handle.\n const handlesToFetch = [\n ...new Set(\n productEntityHandles\n .map(({ handle }) => handle)\n .filter((handle) => !ssEntityCache.has(handle)),\n ),\n ];\n\n // If everything is cached, resolve immediately\n if (handlesToFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n productEntityHandles.forEach(({ entity, handle }) => {\n const item = ssEntityCache.get(handle);\n if (item) {\n cached.set(entity.entityId, item);\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n const productMap = await fetchProductsByHandlesMap(\n config.siteId,\n handlesToFetch,\n );\n\n // Transform and cache\n for (const [handle, product] of productMap) {\n const itemData = transformSSProductToEntityItemData(product);\n ssEntityCache.set(handle, itemData);\n }\n\n if (ignore) {\n return;\n }\n\n // Build the final map\n const finalMap = new Map<string, EntityItemData>();\n productEntityHandles.forEach(({ entity, handle }) => {\n const item = ssEntityCache.get(handle);\n if (item) {\n finalMap.set(entity.entityId, item);\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityKey, config.siteId]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return {\n ...entity,\n data: mergeSearchSpringEntityData(entity.data, resolved),\n };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useState","useEffect","useMemo","fetchProductsByHandlesMap","transformSSProductToEntityItemData","ssEntityCache","Map","extractProductHandle","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","handle","slice","length","getSearchSpringHandle","entity","_entity$data","data","entityId","mergeSearchSpringEntityData","existing","resolved","_existing$matchedOpti","_existing$sizes","_existing$variants","_existing$options","_existing$allImages","title","imageUrl","variantId","matchedOptions","sizes","variants","options","allImages","useResolveSearchSpringEntityData","entities","config","resolvedMap","setResolvedMap","settled","setSettled","entityKey","map","e","entityType","join","ignore","siteId","productEntityHandles","filter","toLowerCase","includes","handlesToFetch","Set","_ref","has","cached","forEach","_ref2","item","get","set","fetchAll","productMap","product","itemData","finalMap","_ref3","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveSearchSpringEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { fetchProductsByHandlesMap } from '../services/searchspring/searchSpringClient';\nimport { transformSSProductToEntityItemData } from '../services/searchspring/transformSSProduct';\nimport type { SearchSpringConfig } from '../services/searchspring/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: handle → resolved EntityItemData\nconst ssEntityCache = new Map<string, EntityItemData>();\n\nfunction extractProductHandle(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n const handle =\n productsIndex >= 0\n ? withoutLeadingSlash.slice(productsIndex + 'products/'.length)\n : withoutLeadingSlash;\n\n return handle || undefined;\n}\n\nfunction getSearchSpringHandle(entity: {\n entityId: string;\n data?: EntityItemData;\n}): string {\n return extractProductHandle(entity.data?.url) || entity.entityId;\n}\n\n/**\n * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about\n * it.\n *\n * Only the turn saw the shopper's question, so only it knows that the brown\n * variant was the one asked for — its `title`, `imageUrl`, `url`,\n * `matchedOptions` and `variantId` all describe that one variant and must\n * survive enrichment. Everything SearchSpring answers with that can go stale\n * between the turn and the render — `price`, `compareAtPrice`, `available`,\n * `priceMin`, `priceMax` — comes from `resolved`.\n */\nexport function mergeSearchSpringEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n title: existing.title || resolved.title,\n imageUrl: existing.imageUrl || resolved.imageUrl,\n variantId: existing.variantId || resolved.variantId,\n matchedOptions: existing.matchedOptions?.length\n ? existing.matchedOptions\n : resolved.matchedOptions,\n sizes: existing.sizes?.length ? existing.sizes : resolved.sizes,\n variants: existing.variants?.length ? existing.variants : resolved.variants,\n options: existing.options?.length ? existing.options : resolved.options,\n allImages: existing.allImages?.length\n ? existing.allImages\n : resolved.allImages,\n };\n}\n\n/**\n * SearchSpring-backed entity resolution hook.\n *\n * Fetches product data from the SearchSpring Search API by handle\n * and transforms it to EntityItemData. Uses a single batched API call\n * for all products (bgfilter.handle supports OR).\n */\nexport function useResolveSearchSpringEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n config: SearchSpringConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable key for dependency tracking\n const entityKey = useMemo(\n () =>\n entities\n .map((e) => `${e.entityType}:${e.entityId}:${getSearchSpringHandle(e)}`)\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n\n if (!entities.length || !config.siteId) {\n setSettled(true);\n return;\n }\n\n const productEntityHandles = entities\n .filter((e) => e.entityType.toLowerCase().includes('product'))\n .map((entity) => ({\n entity,\n handle: getSearchSpringHandle(entity),\n }));\n\n // Collect handles that need fetching. CMS payload IDs use payload url as the handle.\n const handlesToFetch = [\n ...new Set(\n productEntityHandles\n .map(({ handle }) => handle)\n .filter((handle) => !ssEntityCache.has(handle)),\n ),\n ];\n\n // If everything is cached, resolve immediately\n if (handlesToFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n productEntityHandles.forEach(({ entity, handle }) => {\n const item = ssEntityCache.get(handle);\n if (item) {\n cached.set(entity.entityId, item);\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n const productMap = await fetchProductsByHandlesMap(\n config.siteId,\n handlesToFetch,\n );\n\n // Transform and cache\n for (const [handle, product] of productMap) {\n const itemData = transformSSProductToEntityItemData(product);\n ssEntityCache.set(handle, itemData);\n }\n\n if (ignore) {\n return;\n }\n\n // Build the final map\n const finalMap = new Map<string, EntityItemData>();\n productEntityHandles.forEach(({ entity, handle }) => {\n const item = ssEntityCache.get(handle);\n if (item) {\n finalMap.set(entity.entityId, item);\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityKey, config.siteId]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return {\n ...entity,\n data: mergeSearchSpringEntityData(entity.data, resolved),\n };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -2,10 +2,10 @@ import { useState, useEffect, useMemo, useRef } from 'react';
2
2
  import { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient.js';
3
3
  import { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver.js';
4
4
  import { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity.js';
5
- // Session-level cache: entityType:entityId → resolved EntityItemData
5
+ // Session-level cache: entityType:entityId:variantId → resolved EntityItemData
6
6
  const shopifyEntityCache = new Map();
7
- function cacheKey(entityType, entityId) {
8
- return `${entityType}:${entityId}`;
7
+ function cacheKey(entityType, entityId, variantId) {
8
+ return `${entityType}:${entityId}:${variantId || ''}`;
9
9
  }
10
10
  function normalizeShopifyEntityType(entityType) {
11
11
  const lower = entityType.toLowerCase();
@@ -46,23 +46,41 @@ function extractHandleFromUrl(url) {
46
46
  return withoutLeadingSlash || undefined;
47
47
  }
48
48
  function getShopifyLookup(entity) {
49
- var _entity$data;
49
+ var _entity$data, _entity$data2;
50
50
  const entityType = normalizeShopifyEntityType(entity.entityType);
51
51
  const urlHandle = extractHandleFromUrl((_entity$data = entity.data) == null ? void 0 : _entity$data.url);
52
52
  const entityId = (entityType === 'product' || entityType === 'collection') && urlHandle ? urlHandle : entity.entityId;
53
53
  return {
54
54
  entityType,
55
- entityId
55
+ entityId,
56
+ variantId: (_entity$data2 = entity.data) == null ? void 0 : _entity$data2.variantId
56
57
  };
57
58
  }
59
+
60
+ /**
61
+ * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about
62
+ * it.
63
+ *
64
+ * Only the turn saw the shopper's question, so only it knows that the brown
65
+ * variant was the one asked for — its `title`, `imageUrl`, `url`,
66
+ * `matchedOptions` and `variantId` all describe that one variant and must
67
+ * survive enrichment. Everything the Storefront answers with that can go stale
68
+ * between the turn and the render — `price`, `compareAtPrice`, `available`,
69
+ * `priceMin`, `priceMax` — comes from `resolved`.
70
+ */
58
71
  export function mergeShopifyEntityData(existing, resolved) {
72
+ var _existing$matchedOpti;
59
73
  if (!existing) {
60
74
  return resolved;
61
75
  }
62
76
  return {
63
77
  ...existing,
64
78
  ...resolved,
65
- url: existing.url || resolved.url
79
+ url: existing.url || resolved.url,
80
+ title: existing.title || resolved.title,
81
+ imageUrl: existing.imageUrl || resolved.imageUrl,
82
+ variantId: existing.variantId || resolved.variantId,
83
+ matchedOptions: (_existing$matchedOpti = existing.matchedOptions) != null && _existing$matchedOpti.length ? existing.matchedOptions : resolved.matchedOptions
66
84
  };
67
85
  }
68
86
 
@@ -88,7 +106,7 @@ export function useResolveShopifyEntityData(entities, shopifyConfig) {
88
106
  }
89
107
  const entityIds = useMemo(() => entities.map(e => {
90
108
  const lookup = getShopifyLookup(e);
91
- return `${e.entityType}:${e.entityId}:${lookup.entityType}:${lookup.entityId}`;
109
+ return `${e.entityType}:${e.entityId}:${cacheKey(lookup.entityType, lookup.entityId, lookup.variantId)}`;
92
110
  }).join(','), [entities]);
93
111
  useEffect(() => {
94
112
  let ignore = false;
@@ -102,7 +120,10 @@ export function useResolveShopifyEntityData(entities, shopifyConfig) {
102
120
  return {
103
121
  entity,
104
122
  lookup,
105
- key: cacheKey(lookup.entityType, lookup.entityId)
123
+ // The variant is part of the key: the cached entry carries that
124
+ // variant's live price, so two entities on the same product but
125
+ // different variants must not share it.
126
+ key: cacheKey(lookup.entityType, lookup.entityId, lookup.variantId)
106
127
  };
107
128
  });
108
129
 
@@ -141,7 +162,7 @@ export function useResolveShopifyEntityData(entities, shopifyConfig) {
141
162
  } = _ref3;
142
163
  const resolved = await resolveShopifyEntity(client, lookup.entityType, lookup.entityId, shopifyConfig);
143
164
  if (resolved) {
144
- const itemData = transformShopifyEntityToItemData(resolved, lookup.entityType);
165
+ const itemData = transformShopifyEntityToItemData(resolved, lookup.entityType, lookup.variantId);
145
166
  shopifyEntityCache.set(key, mergeShopifyEntityData(entity.data, itemData));
146
167
  }
147
168
  }));
@@ -1 +1 @@
1
- {"version":3,"names":["useState","useEffect","useMemo","useRef","ShopifyStorefrontClient","resolveShopifyEntity","transformShopifyEntityToItemData","shopifyEntityCache","Map","cacheKey","entityType","entityId","normalizeShopifyEntityType","lower","toLowerCase","includes","extractHandleFromUrl","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","slice","length","collectionsIndex","getShopifyLookup","entity","_entity$data","urlHandle","data","mergeShopifyEntityData","existing","resolved","useResolveShopifyEntityData","entities","shopifyConfig","resolvedMap","setResolvedMap","settled","setSettled","clientRef","configKeyRef","configKey","storeDomain","apiVersion","current","entityIds","map","e","lookup","join","ignore","client","entityLookups","key","toFetch","filter","_ref","has","cached","forEach","_ref2","item","get","set","fetchAll","Promise","allSettled","_ref3","itemData","finalMap","_ref4","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef } from 'react';\nimport { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient';\nimport { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver';\nimport { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity';\nimport type { ShopifyStorefrontConfig } from '../services/shopify/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: entityType:entityId → resolved EntityItemData\nconst shopifyEntityCache = new Map<string, EntityItemData>();\n\nfunction cacheKey(entityType: string, entityId: string): string {\n return `${entityType}:${entityId}`;\n}\n\nfunction normalizeShopifyEntityType(entityType: string): string {\n const lower = entityType.toLowerCase();\n if (lower.includes('product')) {\n return 'product';\n }\n if (lower.includes('collection')) {\n return 'collection';\n }\n if (lower.includes('article') || lower.includes('blog')) {\n return 'article';\n }\n return entityType;\n}\n\nfunction extractHandleFromUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n if (productsIndex >= 0) {\n return withoutLeadingSlash.slice(productsIndex + 'products/'.length);\n }\n\n const collectionsIndex = withoutLeadingSlash.indexOf('collections/');\n if (collectionsIndex >= 0) {\n return withoutLeadingSlash.slice(\n collectionsIndex + 'collections/'.length,\n );\n }\n\n return withoutLeadingSlash || undefined;\n}\n\nfunction getShopifyLookup(entity: {\n entityId: string;\n entityType: string;\n data?: EntityItemData;\n}) {\n const entityType = normalizeShopifyEntityType(entity.entityType);\n const urlHandle = extractHandleFromUrl(entity.data?.url);\n const entityId =\n (entityType === 'product' || entityType === 'collection') && urlHandle\n ? urlHandle\n : entity.entityId;\n return { entityType, entityId };\n}\n\nexport function mergeShopifyEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n };\n}\n\n/**\n * Shopify-specific implementation of the entity resolution pattern.\n *\n * Fetches entity data from the Shopify Storefront API (tokenless) and\n * transforms it to the standard EntityItemData shape.\n *\n * Designed to be plugged into ComponentDependencies.useResolveGenericEntityData.\n */\nexport function useResolveShopifyEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n shopifyConfig: ShopifyStorefrontConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable client reference — recreated only when config changes\n const clientRef = useRef<ShopifyStorefrontClient | null>(null);\n const configKeyRef = useRef('');\n const configKey = `${shopifyConfig.storeDomain}|${\n shopifyConfig.apiVersion || ''\n }`;\n\n if (!clientRef.current || configKeyRef.current !== configKey) {\n clientRef.current = new ShopifyStorefrontClient(shopifyConfig);\n configKeyRef.current = configKey;\n }\n\n const entityIds = useMemo(\n () =>\n entities\n .map((e) => {\n const lookup = getShopifyLookup(e);\n return `${e.entityType}:${e.entityId}:${lookup.entityType}:${lookup.entityId}`;\n })\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n const client = clientRef.current;\n\n if (!entities.length || !client || !shopifyConfig.storeDomain) {\n setSettled(true);\n return;\n }\n\n const entityLookups = entities.map((entity) => {\n const lookup = getShopifyLookup(entity);\n return {\n entity,\n lookup,\n key: cacheKey(lookup.entityType, lookup.entityId),\n };\n });\n\n // Identify entities that need fetching. Payload data can provide the handle.\n const toFetch = entityLookups.filter(\n ({ key }) => !shopifyEntityCache.has(key),\n );\n\n // If everything is cached, resolve immediately\n if (toFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n cached.set(entity.entityId, mergeShopifyEntityData(entity.data, item));\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n await Promise.allSettled(\n toFetch.map(async ({ entity, lookup, key }) => {\n const resolved = await resolveShopifyEntity(\n client,\n lookup.entityType,\n lookup.entityId,\n shopifyConfig,\n );\n if (resolved) {\n const itemData = transformShopifyEntityToItemData(\n resolved,\n lookup.entityType,\n );\n shopifyEntityCache.set(\n key,\n mergeShopifyEntityData(entity.data, itemData),\n );\n }\n }),\n );\n\n if (ignore) {\n return;\n }\n\n // Build the resolved map from cache\n const finalMap = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n finalMap.set(\n entity.entityId,\n mergeShopifyEntityData(entity.data, item),\n );\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityIds, shopifyConfig.storeDomain]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return { ...entity, data: resolved };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useState","useEffect","useMemo","useRef","ShopifyStorefrontClient","resolveShopifyEntity","transformShopifyEntityToItemData","shopifyEntityCache","Map","cacheKey","entityType","entityId","variantId","normalizeShopifyEntityType","lower","toLowerCase","includes","extractHandleFromUrl","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","slice","length","collectionsIndex","getShopifyLookup","entity","_entity$data","_entity$data2","urlHandle","data","mergeShopifyEntityData","existing","resolved","_existing$matchedOpti","title","imageUrl","matchedOptions","useResolveShopifyEntityData","entities","shopifyConfig","resolvedMap","setResolvedMap","settled","setSettled","clientRef","configKeyRef","configKey","storeDomain","apiVersion","current","entityIds","map","e","lookup","join","ignore","client","entityLookups","key","toFetch","filter","_ref","has","cached","forEach","_ref2","item","get","set","fetchAll","Promise","allSettled","_ref3","itemData","finalMap","_ref4","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef } from 'react';\nimport { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient';\nimport { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver';\nimport { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity';\nimport type { ShopifyStorefrontConfig } from '../services/shopify/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: entityType:entityId:variantId → resolved EntityItemData\nconst shopifyEntityCache = new Map<string, EntityItemData>();\n\nfunction cacheKey(\n entityType: string,\n entityId: string,\n variantId?: string,\n): string {\n return `${entityType}:${entityId}:${variantId || ''}`;\n}\n\nfunction normalizeShopifyEntityType(entityType: string): string {\n const lower = entityType.toLowerCase();\n if (lower.includes('product')) {\n return 'product';\n }\n if (lower.includes('collection')) {\n return 'collection';\n }\n if (lower.includes('article') || lower.includes('blog')) {\n return 'article';\n }\n return entityType;\n}\n\nfunction extractHandleFromUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n if (productsIndex >= 0) {\n return withoutLeadingSlash.slice(productsIndex + 'products/'.length);\n }\n\n const collectionsIndex = withoutLeadingSlash.indexOf('collections/');\n if (collectionsIndex >= 0) {\n return withoutLeadingSlash.slice(\n collectionsIndex + 'collections/'.length,\n );\n }\n\n return withoutLeadingSlash || undefined;\n}\n\nfunction getShopifyLookup(entity: {\n entityId: string;\n entityType: string;\n data?: EntityItemData;\n}) {\n const entityType = normalizeShopifyEntityType(entity.entityType);\n const urlHandle = extractHandleFromUrl(entity.data?.url);\n const entityId =\n (entityType === 'product' || entityType === 'collection') && urlHandle\n ? urlHandle\n : entity.entityId;\n return { entityType, entityId, variantId: entity.data?.variantId };\n}\n\n/**\n * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about\n * it.\n *\n * Only the turn saw the shopper's question, so only it knows that the brown\n * variant was the one asked for — its `title`, `imageUrl`, `url`,\n * `matchedOptions` and `variantId` all describe that one variant and must\n * survive enrichment. Everything the Storefront answers with that can go stale\n * between the turn and the render — `price`, `compareAtPrice`, `available`,\n * `priceMin`, `priceMax` — comes from `resolved`.\n */\nexport function mergeShopifyEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n title: existing.title || resolved.title,\n imageUrl: existing.imageUrl || resolved.imageUrl,\n variantId: existing.variantId || resolved.variantId,\n matchedOptions: existing.matchedOptions?.length\n ? existing.matchedOptions\n : resolved.matchedOptions,\n };\n}\n\n/**\n * Shopify-specific implementation of the entity resolution pattern.\n *\n * Fetches entity data from the Shopify Storefront API (tokenless) and\n * transforms it to the standard EntityItemData shape.\n *\n * Designed to be plugged into ComponentDependencies.useResolveGenericEntityData.\n */\nexport function useResolveShopifyEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n shopifyConfig: ShopifyStorefrontConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable client reference — recreated only when config changes\n const clientRef = useRef<ShopifyStorefrontClient | null>(null);\n const configKeyRef = useRef('');\n const configKey = `${shopifyConfig.storeDomain}|${\n shopifyConfig.apiVersion || ''\n }`;\n\n if (!clientRef.current || configKeyRef.current !== configKey) {\n clientRef.current = new ShopifyStorefrontClient(shopifyConfig);\n configKeyRef.current = configKey;\n }\n\n const entityIds = useMemo(\n () =>\n entities\n .map((e) => {\n const lookup = getShopifyLookup(e);\n return `${e.entityType}:${e.entityId}:${cacheKey(\n lookup.entityType,\n lookup.entityId,\n lookup.variantId,\n )}`;\n })\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n const client = clientRef.current;\n\n if (!entities.length || !client || !shopifyConfig.storeDomain) {\n setSettled(true);\n return;\n }\n\n const entityLookups = entities.map((entity) => {\n const lookup = getShopifyLookup(entity);\n return {\n entity,\n lookup,\n // The variant is part of the key: the cached entry carries that\n // variant's live price, so two entities on the same product but\n // different variants must not share it.\n key: cacheKey(lookup.entityType, lookup.entityId, lookup.variantId),\n };\n });\n\n // Identify entities that need fetching. Payload data can provide the handle.\n const toFetch = entityLookups.filter(\n ({ key }) => !shopifyEntityCache.has(key),\n );\n\n // If everything is cached, resolve immediately\n if (toFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n cached.set(entity.entityId, mergeShopifyEntityData(entity.data, item));\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n await Promise.allSettled(\n toFetch.map(async ({ entity, lookup, key }) => {\n const resolved = await resolveShopifyEntity(\n client,\n lookup.entityType,\n lookup.entityId,\n shopifyConfig,\n );\n if (resolved) {\n const itemData = transformShopifyEntityToItemData(\n resolved,\n lookup.entityType,\n lookup.variantId,\n );\n shopifyEntityCache.set(\n key,\n mergeShopifyEntityData(entity.data, itemData),\n );\n }\n }),\n );\n\n if (ignore) {\n return;\n }\n\n // Build the resolved map from cache\n const finalMap = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n finalMap.set(\n entity.entityId,\n mergeShopifyEntityData(entity.data, item),\n );\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityIds, shopifyConfig.storeDomain]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return { ...entity, data: resolved };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
package/dist/esm/index.js CHANGED
@@ -60,7 +60,7 @@ export { ChipsProvider, useChips } from './context/ChipsContext.js';
60
60
  // DI types
61
61
 
62
62
  export { defaultExtractor, enrichEntitiesFromPayload, fetchEntityListData, listEntityItems, LIST_ITEMS_ENDPOINT, getEntityExtractor, registerEntityExtractor, transformToSolutionEntityData, transformToBlogPostEntityData, transformToGenericEntityData, toMatchedOptions, formatMoney, readCurrencyCode, formatPriceField, formatProductPriceLabel } from './entity/index.js';
63
- export { CALLOUT_KINDS } from './types/callout.js';
63
+ export { CALLOUT_KINDS, CALLOUT_SEMANTICS } from './types/callout.js';
64
64
 
65
65
  // Wrapper hooks
66
66
  export { useWeb5Link } from './hooks/useWeb5Link.js';
@@ -1 +1 @@
1
- {"version":3,"names":["CLIENT_IDS","EXPERIMENT_IDS","createFeatureToggleReader","FeatureToggleProvider","useFeatureToggles","useFeatureToggle","getPartsByType","getPartByRole","getAllByRole","getHeading","getImages","getLinks","extractContent","extractContentMarkdown","deriveRole","DROP_SECTION","DIAGNOSTIC_TYPES","buildImageSearchFilter","ImageSearchFilterToken","backgroundFilter","HeroSectionDefinition","HeroEntitySectionDefinition","KpiSectionDefinition","FeatureCardsSectionDefinition","EntitySectionDefinition","EntityCollectionSectionDefinition","ComparisonSectionDefinition","TextBlockSectionDefinition","CtaBannerSectionDefinition","CalloutSectionDefinition","NextStepsSectionDefinition","FeatureSection9PlusDefinition","ListItemsSectionDefinition","SkipNodesSectionDefinition","HtmlCommentSectionDefinition","SearchSectionDefinition","ErrorSectionDefinition","FallbackSectionDefinition","createSdkRegistry","ComponentRegistry","validatePattern","validatePatternSyntax","validatePatternWithBlocks","convertToBlockElements","convertToBlockElementsWithMapping","Web5UrlType","isWeb5AskUrl","isWeb5EntityUrl","isWeb5ImageUrl","isWeb5IconUrl","isWeb5ActionUrl","isWeb5SearchUrl","isWeb5Url","isNavigableUrl","isValidLinkUrl","isLegacyUrl","parseWeb5Url","isValidWeb5Url","validateLinkUrl","isEntityLink","parseEntityLink","extractProtocol","extractLinkMetadata","findInvalidWeb5Links","hasImage","isHtmlComment","matchMarkdown","matchAllSections","nodesToParts","ComponentDependenciesProvider","useComponentDependencies","UserQueryProvider","useUserQuery","ChipsProvider","useChips","defaultExtractor","enrichEntitiesFromPayload","fetchEntityListData","listEntityItems","LIST_ITEMS_ENDPOINT","getEntityExtractor","registerEntityExtractor","transformToSolutionEntityData","transformToBlogPostEntityData","transformToGenericEntityData","toMatchedOptions","formatMoney","readCurrencyCode","formatPriceField","formatProductPriceLabel","CALLOUT_KINDS","useWeb5Link","useConversation","useDebugImageContext","useResolvedImageSources","useResolveGenericEntityData","useEntityTransforms","useMarkdownUtils","useResolveShopifyEntityData","useResolveSearchSpringEntityData","fetchProductsByHandles","fetchProductsByHandlesMap","transformSSProductToEntityItemData","addToCart","ShopifyStorefrontClient","resolveShopifyConfig","resolveShopifyEntity","transformShopifyProduct","transformShopifyCollection","transformShopifyArticle","transformShopifyEntityToItemData","PRODUCT_BY_HANDLE_QUERY","COLLECTION_BY_HANDLE_QUERY","ARTICLE_BY_HANDLE_QUERY","cn","normalizeImageUrl","getResizedImageUrl","analyzeBackdrop","computeContentBBox","buildProbeUrl","loadImagePixels","loadBackdropAnalysis","stripMarkdown","rgbToHsl","hslToRgb","ensureMinLightness","toRgb","deriveDarkColor","deriveDarkGradient","deriveLightColor","pushEvent","pushPromptSubmit","pushLinkClick","pushError","pushExit","pushEntityFiltered","hasAnalyticsConsent","ERROR_MARKDOWN","getErrorTypeFromStatus","createErrorMarkdown","STREAMING_TIMEOUT_MS","DEFAULT_ERROR_TEMPLATES","resolveErrorTemplate","getForwardStack","setForwardStack","clearForwardStack","pushToForwardStack","popFromForwardStack","UserQuery","PRODUCT_BACK_SESSION_KEY","writeProductBackHandoff","readProductBackHandoff","PromptEntryEmptyState","SearchSection","FeedbackBar","Disclaimer","BottomContainer","MarkdownText","CalloutBlock","OptimizedImage","SectionSkeleton","SmartIcon","Loader","PlacementLoader","UnifiedLink","detectLinkType","LinkType","Table","TableHeader","TableBody","TableFooter","TableHead","TableRow","TableCell","TableCaption","WEB5_USER_QUERY_EVENT","WEB5_ANSWER_UPDATED_EVENT","WEB5_REDIRECT_EVENT","loadClientBundle","getClientBundleOverride","isTrustedBundleHost","TEMPLATES_CDN_BASE","TEMPLATES_MANIFEST_URL","getTemplateOverride","isTemplatePickerRequested","isValidTemplateId","resolveClientBundleUrl","mergeClientConfig","applyThemeOverrides","THEME_OVERRIDE_TOKENS","THEME_TOKEN_CONTRACT","BRAND_TOKENS","EDITABLE_TOKENS","TOKEN_NAME_PATTERN","bucketOf","hostAliasFor","isThemeDebugEnabled","THEME_DEBUG_KEY","THEME_DEBUG_QUERY_PARAM","hexToHslTriplet","hslTripletToHex","isHslTriplet","PlacementResponseRenderer","PlacementSmoothHeight","buildPlacementDependencies","PlacementPayloadProvider","usePlacementPayload","UnifiedMarkdownParser","parseMarkdownToAst","parseAstToMarkdown","escapeWeb5Links","fixMalformedLinks","trimTrailingWhitespace","normalizeIconUrls","decodeLinkText","preprocessMarkdown","ComponentTracking","findKeywordsInContent","getContextualImageFilename","extractIntentFromMarkdown","getIntentFromMarkdown","createPageSection","generateSectionId","generateId","findImageInNode","findImageInChildren","DiagnosticsCollector","REFRESH_PROMPTS_UNTIL_KEY","REFRESH_PROMPTS_WINDOW_MS","getRefreshPromptsExpiry","shouldRefreshPrompts","enableRefreshPrompts","disableRefreshPrompts","BACKEND_ENVIRONMENT_KEY","BACKEND_ENVIRONMENT_QUERY_PARAM","DEFAULT_BACKEND_ENVIRONMENT","getBackendEnvironment","setBackendEnvironment","usesStagingBackend","isSimulationTraffic","MATCH_DEBUG_KEY","MATCH_DEBUG_QUERY_PARAM","isMatchDebugEnabled","setMatchDebug","resetMatchDebugCache","logMatchDebug","createWixAuthFetch","getOrCreateSessionId","getSessionId","getChatId","startNewChatId","setChatId","resetChatIdForTests","parseMarkdownToComponents","tryParseComponent","mergeSectionsWithStableReferences","WEB5_ROOT_ID","WEB5_ROOT_CLASS","WEB5_SCOPES","WEB5_SCOPE","WEB5_GLOBAL_TOKENS"],"sources":["../../src/index.ts"],"sourcesContent":["// Client IDs and experiment IDs\nexport { CLIENT_IDS, EXPERIMENT_IDS } from './clients';\n\nexport {\n type EmbedFeatureToggleResult,\n type FeatureToggleReader,\n createFeatureToggleReader,\n FeatureToggleProvider,\n useFeatureToggles,\n useFeatureToggle,\n} from './featureToggles/FeatureToggleContext';\n\n// Dev-only chrome injection contract for client packages\nexport type { DevEnvironment } from './client/devEnvironment';\n\n// Part types and helpers\nexport {\n type PartType,\n type Part,\n type HeadingPart,\n type ImagePart,\n type LinkPart,\n type ListPart,\n type ListItemPart,\n type KpiItemPart,\n type CardPart,\n type IconPart,\n type CalloutPart,\n type EntityPart,\n getPartsByType,\n getPartByRole,\n getAllByRole,\n getHeading,\n getImages,\n getLinks,\n extractContent,\n extractContentMarkdown,\n deriveRole,\n} from './parts/parts';\n\n// Component types\nexport type {\n BaseCompProps,\n SlotCompProps,\n SectionCompProps,\n SectionCompPropsWithSlot,\n TextCompProps,\n ButtonCompProps,\n ImageCompProps,\n BadgeCompProps,\n HeroButton,\n KpiItemCompProps,\n FeatureItemCompProps,\n FeatureCardCompProps,\n EntityItemData,\n EntityItem,\n GenericEntityData,\n GenericEntityCompProps,\n ComparisonRow,\n ComparisonColumn,\n AiNarrativeCompProps,\n HeroCompProps,\n HeroEntityCompProps,\n KpiCompProps,\n FeatureCardsCompProps,\n EntityCompProps,\n ComparisonCompProps,\n TextBlockCompProps,\n Component,\n BaseComponent,\n SlotComponent,\n SectionComponent,\n TextComponent,\n ButtonComponent,\n ImageComponent,\n BadgeComponent,\n KpiItemComponent,\n FeatureItemComponent,\n FeatureCardComponent,\n GenericEntityComponent,\n AiNarrativeComponent,\n ComparisonSectionComponent,\n TextBlockSectionComponent,\n HeroSectionComponent,\n HeroEntitySectionComponent,\n KpiSectionComponent,\n FeatureCardsSectionComponent,\n EntitySectionComponent,\n PropsOf,\n SectionFixture,\n CtaBannerCompProps,\n CtaBannerSectionComponent,\n CalloutCompProps,\n CalloutSectionComponent,\n NextStepsCompProps,\n NextStepsSectionComponent,\n FeatureSection9PlusCompProps,\n FeatureSection9PlusSectionComponent,\n ListItemsSectionCompProps,\n ListItemsSectionComponent,\n ErrorCompProps,\n ErrorSectionComponent,\n NullCompProps,\n NullSectionComponent,\n SolutionEntityCompProps,\n SolutionEntitySectionComponent,\n SolutionEntityData,\n BlogEntityCompProps,\n BlogEntitySectionComponent,\n BlogEntityData,\n GeneralTextCompProps,\n GeneralTextSectionComponent,\n PersonalizedNarrativeCompProps,\n PersonalizedNarrativeSectionComponent,\n} from './component/types';\n\n// Section definition\nexport type {\n SectionDefinition,\n ParseContext,\n ContextualImageResult,\n DropSection,\n} from './component/section-definition';\nexport { DROP_SECTION } from './component/section-definition';\n\n// Diagnostic types\nexport { DIAGNOSTIC_TYPES } from './component/diagnosticTypes';\nexport type { DiagnosticType } from './component/diagnosticTypes';\n\n// Image search filters\nexport {\n buildImageSearchFilter,\n type ImageSearchFilterString,\n} from './image/imageSearchFilterTypes';\nexport {\n ImageSearchFilterToken,\n backgroundFilter,\n} from './image/imageSearchFilters';\nexport type {\n ContextualImageAsset,\n ImageSourceInput,\n ResolvedImageSource,\n ResolvedImageSourceKind,\n} from './image/contextualImageTypes';\n\n// Section definition classes + createSdkRegistry\nexport {\n HeroSectionDefinition,\n HeroEntitySectionDefinition,\n KpiSectionDefinition,\n FeatureCardsSectionDefinition,\n EntitySectionDefinition,\n EntityCollectionSectionDefinition,\n ComparisonSectionDefinition,\n TextBlockSectionDefinition,\n CtaBannerSectionDefinition,\n CalloutSectionDefinition,\n NextStepsSectionDefinition,\n FeatureSection9PlusDefinition,\n ListItemsSectionDefinition,\n SkipNodesSectionDefinition,\n HtmlCommentSectionDefinition,\n SearchSectionDefinition,\n ErrorSectionDefinition,\n FallbackSectionDefinition,\n createSdkRegistry,\n} from './component/componentDefinitions';\n\n// Registry\nexport { ComponentRegistry } from './registry';\nexport type {\n SlotOptions,\n SectionOptions,\n SectionRegistration,\n SlotNode,\n SlotIntentNode,\n SectionIntentNode,\n SectionNode,\n SlotVariant,\n SectionVariant,\n RegistryCatalog,\n ActionResult,\n ActionHandler,\n} from './registry';\n\n// Pattern validator\nexport {\n validatePattern,\n validatePatternSyntax,\n validatePatternWithBlocks,\n type PatternValidationResult,\n type BlockElement,\n type EnrichedBlockElement,\n type LinkMetadata,\n type LinkAttribute,\n} from './patternValidator';\n\n// Markdown blocks\nexport {\n convertToBlockElements,\n convertToBlockElementsWithMapping,\n type BlockElementsWithMapping,\n} from './markdownBlocks';\n\n// Link types, enum & guards\nexport {\n Web5UrlType,\n type Web5AskUrl,\n type Web5EntityUrl,\n type Web5ImageUrl,\n type Web5IconUrl,\n type Web5ActionUrl,\n type Web5SearchUrl,\n type Web5Url,\n type HttpsUrl,\n type HttpUrl,\n type MailtoUrl,\n type RelativeUrl,\n type NavigableUrl,\n type ValidLinkUrl,\n type AnyKnownUrl,\n type LegacyUrl,\n isWeb5AskUrl,\n isWeb5EntityUrl,\n isWeb5ImageUrl,\n isWeb5IconUrl,\n isWeb5ActionUrl,\n isWeb5SearchUrl,\n isWeb5Url,\n isNavigableUrl,\n isValidLinkUrl,\n isLegacyUrl,\n} from './types/link-types';\n\n// Entity/URL parsing\nexport {\n parseWeb5Url,\n isValidWeb5Url,\n validateLinkUrl,\n type Web5UrlParsed,\n type Web5AskParsed,\n type Web5EntityParsed,\n type Web5ImageParsed,\n type Web5IconParsed,\n type Web5ActionParsed,\n type Web5SearchParsed,\n isEntityLink,\n parseEntityLink,\n extractProtocol,\n extractLinkMetadata,\n} from './utils/entityLinkParser';\n\n// Web5 link validation\nexport {\n findInvalidWeb5Links,\n type InvalidWeb5Link,\n} from './utils/web5LinkValidator';\n\n// Node matchers\nexport { hasImage, isHtmlComment } from './utils/nodeMatchers';\n\n// Match API\nexport {\n matchMarkdown,\n type MarkdownMatchResult,\n matchAllSections,\n type MatchAllSectionsResult,\n nodesToParts,\n} from './match';\n\n// ---------------------------------------------------------------------------\n// DI Infrastructure (moved from @wix/w5-client-circana)\n// ---------------------------------------------------------------------------\n\n// DI context and provider\nexport {\n ComponentDependenciesProvider,\n useComponentDependencies,\n type ComponentDependenciesProviderProps,\n} from './context/ComponentDependenciesContext';\n\n// Raw user query for the current response page\nexport {\n UserQueryProvider,\n useUserQuery,\n type UserQueryProviderProps,\n} from './context/UserQueryContext';\n\n// Chips context (suggestion chips shared between SearchSection and error states)\nexport {\n ChipsProvider,\n useChips,\n type SuggestionChip,\n} from './context/ChipsContext';\n\n// DI types\nexport type {\n ComponentDependencies,\n Web5LinkApi,\n ConversationApi,\n SendMessageTrackingOptions,\n SendMessageOptions,\n ComparisonSubmitPayload,\n ComparisonSelectedProduct,\n ProductComparisonSelectionState,\n ProductComparisonApi,\n EntityTransforms,\n MarkdownUtils,\n ResolveGenericEntityDataOptions,\n} from './types/dependencies';\nexport type {\n ApiPayloadItem,\n EntityTypeConfig,\n EntityConfig,\n EntityExtractionContext,\n} from './types/entity';\nexport {\n defaultExtractor,\n enrichEntitiesFromPayload,\n fetchEntityListData,\n listEntityItems,\n LIST_ITEMS_ENDPOINT,\n getEntityExtractor,\n registerEntityExtractor,\n transformToSolutionEntityData,\n transformToBlogPostEntityData,\n transformToGenericEntityData,\n toMatchedOptions,\n formatMoney,\n readCurrencyCode,\n formatPriceField,\n formatProductPriceLabel,\n} from './entity';\nexport type {\n EntityExtractor,\n FetchEntityListDataOptions,\n ListEntityItemsOptions,\n MatchedOption,\n ProductPriceFields,\n} from './entity';\nexport { CALLOUT_KINDS, type CalloutKind, type Callout } from './types/callout';\n\n// Wrapper hooks\nexport { useWeb5Link } from './hooks/useWeb5Link';\nexport { useConversation } from './hooks/useConversation';\nexport { useDebugImageContext } from './hooks/useDebugImageContext';\nexport { useResolvedImageSources } from './hooks/useResolvedImageSources';\nexport { useResolveGenericEntityData } from './hooks/useResolveGenericEntityData';\nexport { useEntityTransforms } from './hooks/useEntityTransforms';\nexport { useMarkdownUtils } from './hooks/useMarkdownUtils';\nexport { useResolveShopifyEntityData } from './hooks/useResolveShopifyEntityData';\nexport { useResolveSearchSpringEntityData } from './hooks/useResolveSearchSpringEntityData';\n\n// SearchSpring\nexport {\n fetchProductsByHandles,\n fetchProductsByHandlesMap,\n transformSSProductToEntityItemData,\n} from './services/searchspring';\nexport type {\n SearchSpringConfig,\n SSProduct,\n SSSearchResponse,\n SSSizeData,\n} from './services/searchspring';\n\n// Shopify Storefront API\n// Cart actions\nexport { addToCart } from './services/cart';\n\nexport {\n ShopifyStorefrontClient,\n resolveShopifyConfig,\n resolveShopifyEntity,\n transformShopifyProduct,\n transformShopifyCollection,\n transformShopifyArticle,\n transformShopifyEntityToItemData,\n PRODUCT_BY_HANDLE_QUERY,\n COLLECTION_BY_HANDLE_QUERY,\n ARTICLE_BY_HANDLE_QUERY,\n} from './services/shopify';\nexport type {\n ShopifyStorefrontConfig,\n ShopifyProduct,\n ShopifyCollection,\n ShopifyArticle,\n ShopifyImage,\n ShopifyMoneyV2,\n} from './services/shopify';\n\n// Utilities\nexport { cn } from './lib/utils';\nexport { normalizeImageUrl, getResizedImageUrl } from './utils/image-utils';\nexport {\n analyzeBackdrop,\n computeContentBBox,\n buildProbeUrl,\n loadImagePixels,\n loadBackdropAnalysis,\n type BackdropAnalysis,\n type ContentBBox,\n type ImagePixels,\n} from './utils/imageBackdrop';\nexport { stripMarkdown } from './component/componentDefinitions/parse-utils';\n\n// Color utilities\nexport {\n type RGB,\n rgbToHsl,\n hslToRgb,\n ensureMinLightness,\n toRgb,\n deriveDarkColor,\n deriveDarkGradient,\n deriveLightColor,\n} from './color/colorUtils';\n\n// Analytics\nexport {\n pushEvent,\n pushPromptSubmit,\n pushLinkClick,\n pushError,\n pushExit,\n pushEntityFiltered,\n hasAnalyticsConsent,\n type EntityFilteredReason,\n} from './utils/analyticsEvents';\n\n// Error handling types and utilities\nexport {\n type ConversationErrorType,\n ERROR_MARKDOWN,\n getErrorTypeFromStatus,\n createErrorMarkdown,\n STREAMING_TIMEOUT_MS,\n type ErrorActionType,\n type ErrorIconType,\n type ErrorTemplateButton,\n type ErrorTemplate,\n type ErrorTemplateOverrides,\n DEFAULT_ERROR_TEMPLATES,\n resolveErrorTemplate,\n} from './errors';\n\n// Navigation utilities\nexport {\n getForwardStack,\n setForwardStack,\n clearForwardStack,\n pushToForwardStack,\n popFromForwardStack,\n} from './utils/navigationStack';\n\n// UI components\nexport {\n UserQuery,\n type UserQueryProps,\n type ProductBackContext,\n} from './components/ui/UserQuery';\nexport {\n PRODUCT_BACK_SESSION_KEY,\n writeProductBackHandoff,\n readProductBackHandoff,\n type ProductBackHandoff,\n} from './utils/productBackHandoff';\nexport {\n PromptEntryEmptyState,\n type PromptEntryEmptyStateProps,\n} from './components/ui/PromptEntryEmptyState';\nexport {\n SearchSection,\n type SearchSectionProps,\n type SearchSectionHandle,\n type ScrollChip,\n} from './components/ui/SearchSection';\nexport {\n FeedbackBar,\n type FeedbackBarProps,\n type FeedbackCategoryOption,\n type FeedbackSentiment,\n type FeedbackSubmitInput,\n} from './components/ui/FeedbackBar';\nexport {\n Disclaimer,\n type DisclaimerProps,\n} from './components/ui/Disclaimer';\nexport {\n BottomContainer,\n type BottomContainerProps,\n} from './components/ui/BottomContainer';\nexport { MarkdownText } from './components/ui/MarkdownText';\nexport {\n CalloutBlock,\n type CalloutBlockProps,\n} from './components/ui/CalloutBlock';\nexport {\n OptimizedImage,\n type OptimizedImageProps,\n} from './components/ui/OptimizedImage';\nexport {\n SectionSkeleton,\n type SectionSkeletonProps,\n} from './components/ui/SectionSkeleton';\nexport { SmartIcon, type SmartIconProps } from './components/ui/SmartIcon';\nexport { Loader, type LoaderProps } from './components/ui/Loader';\nexport {\n PlacementLoader,\n type PlacementLoaderProps,\n} from './components/ui/PlacementLoader';\nexport {\n UnifiedLink,\n detectLinkType,\n type UnifiedLinkProps,\n LinkType,\n type LinkVariant,\n} from './components/ui/UnifiedLink';\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from './components/ui/table';\n\n// Placement (DL #088, DL #102 behavior declarations)\nexport type {\n PlacementBehaviorConfig,\n PlacementConfig,\n PlacementPrompts,\n} from './types/placement';\n\n// Cross-bundle user-query broadcast event (DL #097 D2)\nexport {\n WEB5_USER_QUERY_EVENT,\n type Web5UserQueryEventDetail,\n type Web5UserQueryEvent,\n} from './types/userQueryEvent';\n\n// Cross-bundle answer-updated broadcast event (B2B-4121)\nexport {\n WEB5_ANSWER_UPDATED_EVENT,\n type Web5AnswerUpdatedEventDetail,\n type Web5AnswerUpdatedEvent,\n} from './types/answerUpdatedEvent';\n\n// Cross-bundle redirect broadcast event (DL #098 D3)\nexport {\n WEB5_REDIRECT_EVENT,\n type Web5RedirectEventDetail,\n type Web5RedirectEvent,\n type Web5RedirectReason,\n} from './types/redirectEvent';\n// `placementFilter` was removed — hero/next-steps exclusion is the prompt's job\n// and placement-specific designs belong as `{ placement: true }` registry\n// variants (resolved automatically via `resolveSection(type, { placement: true })`).\n\n// Client bundle loader (DL #088 D3.3)\nexport { loadClientBundle } from './client/loadClientBundle';\n\n// `?clientBundleUrl=` dev override — shared by `web50-server-ui` and\n// `embed-placement` so the trusted-host gate can't drift between them.\nexport {\n getClientBundleOverride,\n isTrustedBundleHost,\n} from './client/clientBundleOverride';\n\n// Client-UMD URL resolution (DL #094 per-msid, DL #129 per-template) and the\n// universal bundle←backend config merge (DL #129 Q3/Q7) — shared by\n// `web50-server-ui` and `embed-placement`, the two client-bundle load sites.\nexport {\n TEMPLATES_CDN_BASE,\n TEMPLATES_MANIFEST_URL,\n getTemplateOverride,\n isTemplatePickerRequested,\n isValidTemplateId,\n resolveClientBundleUrl,\n} from './client/clientBundleUrl';\nexport { mergeClientConfig, type DeepPartial } from './client/mergeClientConfig';\nexport {\n applyThemeOverrides,\n THEME_OVERRIDE_TOKENS,\n type ThemeOverrideKey,\n type ThemeOverrides,\n} from './client/applyThemeOverrides';\nexport {\n THEME_TOKEN_CONTRACT,\n BRAND_TOKENS,\n EDITABLE_TOKENS,\n TOKEN_NAME_PATTERN,\n bucketOf,\n hostAliasFor,\n type TokenBucket,\n type TokenContractEntry,\n type TokenType,\n} from './theme/tokenContract';\nexport {\n isThemeDebugEnabled,\n THEME_DEBUG_KEY,\n THEME_DEBUG_QUERY_PARAM,\n type AppliedToken,\n type ThemeOverrideSource,\n} from './client/themeDebug';\nexport {\n hexToHslTriplet,\n hslTripletToHex,\n isHslTriplet,\n} from './theme/colorFormat';\n\n// Placement renderer + DI helper (DL #088 D3.2, D3.4)\nexport {\n PlacementResponseRenderer,\n PlacementSmoothHeight,\n type PlacementResponseRendererProps,\n type PlacementSection,\n type PlacementVariant,\n} from './components/placement/PlacementResponseRenderer';\nexport {\n buildPlacementDependencies,\n type BuildPlacementDependenciesOptions,\n} from './components/placement/buildPlacementDependencies';\nexport {\n PlacementPayloadProvider,\n usePlacementPayload,\n type PlacementPayloadContextValue,\n} from './components/placement/PlacementPayloadContext';\n\n// Markdown parsing utilities — lifted from web50-server-ui (DL #088 B9.1)\nexport {\n UnifiedMarkdownParser,\n parseMarkdownToAst,\n parseAstToMarkdown,\n} from './utils/unifiedMarkdownParser';\nexport {\n escapeWeb5Links,\n fixMalformedLinks,\n trimTrailingWhitespace,\n normalizeIconUrls,\n decodeLinkText,\n preprocessMarkdown,\n type PreprocessorDiagnostic,\n type PreprocessResult,\n} from './utils/markdownPreprocessor';\nexport {\n ComponentTracking,\n type ComponentNodeRange,\n} from './utils/componentTracking';\nexport {\n findKeywordsInContent,\n getContextualImageFilename,\n} from './utils/contentKeywordMatcher';\nexport {\n extractIntentFromMarkdown,\n getIntentFromMarkdown,\n type IntentInfo,\n type IntentExtractionOptions,\n type ResponseState,\n} from './utils/intentExtractor';\nexport type { PageSection } from './types/page-section';\nexport {\n createPageSection,\n generateSectionId,\n generateId,\n findImageInNode,\n findImageInChildren,\n type Product,\n type ComparisonProduct,\n type ProductComparisonSectionProps,\n} from './utils/propsExtractor';\nexport {\n DiagnosticsCollector,\n type DiagnosticEntry,\n} from './utils/diagnosticsCollector';\nexport {\n REFRESH_PROMPTS_UNTIL_KEY,\n REFRESH_PROMPTS_WINDOW_MS,\n getRefreshPromptsExpiry,\n shouldRefreshPrompts,\n enableRefreshPrompts,\n disableRefreshPrompts,\n} from './utils/refreshPrompts';\nexport {\n type BackendEnvironment,\n BACKEND_ENVIRONMENT_KEY,\n BACKEND_ENVIRONMENT_QUERY_PARAM,\n DEFAULT_BACKEND_ENVIRONMENT,\n getBackendEnvironment,\n setBackendEnvironment,\n usesStagingBackend,\n} from './utils/backendEnvironment';\nexport { isSimulationTraffic } from './utils/simulation';\nexport {\n MATCH_DEBUG_KEY,\n MATCH_DEBUG_QUERY_PARAM,\n isMatchDebugEnabled,\n setMatchDebug,\n resetMatchDebugCache,\n logMatchDebug,\n} from './utils/matchDebug';\nexport { createWixAuthFetch } from './client/wixAuthFetch';\nexport {\n getOrCreateSessionId,\n getSessionId,\n getChatId,\n startNewChatId,\n setChatId,\n resetChatIdForTests,\n} from './utils/sessionManager';\n\n// Component parser orchestrator — lifted from web50-server-ui (DL #088 B9.5)\nexport {\n parseMarkdownToComponents,\n tryParseComponent,\n mergeSectionsWithStableReferences,\n type ParseMarkdownOptions,\n type ParseMarkdownResult,\n type ComponentMatch,\n type ParserContext,\n} from './component/componentParser';\nexport type {\n ParserClientConfig,\n EnrichEntityProps,\n} from './component/parser-types';\n\n// Host-mount scope contract — shared by web50-server-ui (which stamps the\n// class and mounts), embed-placement (which mounts the same bundle elsewhere),\n// and the client CDN build (which compiles every selector against it).\nexport {\n WEB5_ROOT_ID,\n WEB5_ROOT_CLASS,\n WEB5_SCOPES,\n WEB5_SCOPE,\n WEB5_GLOBAL_TOKENS,\n type HostFitConfig,\n} from './hostScope';\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["CLIENT_IDS","EXPERIMENT_IDS","createFeatureToggleReader","FeatureToggleProvider","useFeatureToggles","useFeatureToggle","getPartsByType","getPartByRole","getAllByRole","getHeading","getImages","getLinks","extractContent","extractContentMarkdown","deriveRole","DROP_SECTION","DIAGNOSTIC_TYPES","buildImageSearchFilter","ImageSearchFilterToken","backgroundFilter","HeroSectionDefinition","HeroEntitySectionDefinition","KpiSectionDefinition","FeatureCardsSectionDefinition","EntitySectionDefinition","EntityCollectionSectionDefinition","ComparisonSectionDefinition","TextBlockSectionDefinition","CtaBannerSectionDefinition","CalloutSectionDefinition","NextStepsSectionDefinition","FeatureSection9PlusDefinition","ListItemsSectionDefinition","SkipNodesSectionDefinition","HtmlCommentSectionDefinition","SearchSectionDefinition","ErrorSectionDefinition","FallbackSectionDefinition","createSdkRegistry","ComponentRegistry","validatePattern","validatePatternSyntax","validatePatternWithBlocks","convertToBlockElements","convertToBlockElementsWithMapping","Web5UrlType","isWeb5AskUrl","isWeb5EntityUrl","isWeb5ImageUrl","isWeb5IconUrl","isWeb5ActionUrl","isWeb5SearchUrl","isWeb5Url","isNavigableUrl","isValidLinkUrl","isLegacyUrl","parseWeb5Url","isValidWeb5Url","validateLinkUrl","isEntityLink","parseEntityLink","extractProtocol","extractLinkMetadata","findInvalidWeb5Links","hasImage","isHtmlComment","matchMarkdown","matchAllSections","nodesToParts","ComponentDependenciesProvider","useComponentDependencies","UserQueryProvider","useUserQuery","ChipsProvider","useChips","defaultExtractor","enrichEntitiesFromPayload","fetchEntityListData","listEntityItems","LIST_ITEMS_ENDPOINT","getEntityExtractor","registerEntityExtractor","transformToSolutionEntityData","transformToBlogPostEntityData","transformToGenericEntityData","toMatchedOptions","formatMoney","readCurrencyCode","formatPriceField","formatProductPriceLabel","CALLOUT_KINDS","CALLOUT_SEMANTICS","useWeb5Link","useConversation","useDebugImageContext","useResolvedImageSources","useResolveGenericEntityData","useEntityTransforms","useMarkdownUtils","useResolveShopifyEntityData","useResolveSearchSpringEntityData","fetchProductsByHandles","fetchProductsByHandlesMap","transformSSProductToEntityItemData","addToCart","ShopifyStorefrontClient","resolveShopifyConfig","resolveShopifyEntity","transformShopifyProduct","transformShopifyCollection","transformShopifyArticle","transformShopifyEntityToItemData","PRODUCT_BY_HANDLE_QUERY","COLLECTION_BY_HANDLE_QUERY","ARTICLE_BY_HANDLE_QUERY","cn","normalizeImageUrl","getResizedImageUrl","analyzeBackdrop","computeContentBBox","buildProbeUrl","loadImagePixels","loadBackdropAnalysis","stripMarkdown","rgbToHsl","hslToRgb","ensureMinLightness","toRgb","deriveDarkColor","deriveDarkGradient","deriveLightColor","pushEvent","pushPromptSubmit","pushLinkClick","pushError","pushExit","pushEntityFiltered","hasAnalyticsConsent","ERROR_MARKDOWN","getErrorTypeFromStatus","createErrorMarkdown","STREAMING_TIMEOUT_MS","DEFAULT_ERROR_TEMPLATES","resolveErrorTemplate","getForwardStack","setForwardStack","clearForwardStack","pushToForwardStack","popFromForwardStack","UserQuery","PRODUCT_BACK_SESSION_KEY","writeProductBackHandoff","readProductBackHandoff","PromptEntryEmptyState","SearchSection","FeedbackBar","Disclaimer","BottomContainer","MarkdownText","CalloutBlock","OptimizedImage","SectionSkeleton","SmartIcon","Loader","PlacementLoader","UnifiedLink","detectLinkType","LinkType","Table","TableHeader","TableBody","TableFooter","TableHead","TableRow","TableCell","TableCaption","WEB5_USER_QUERY_EVENT","WEB5_ANSWER_UPDATED_EVENT","WEB5_REDIRECT_EVENT","loadClientBundle","getClientBundleOverride","isTrustedBundleHost","TEMPLATES_CDN_BASE","TEMPLATES_MANIFEST_URL","getTemplateOverride","isTemplatePickerRequested","isValidTemplateId","resolveClientBundleUrl","mergeClientConfig","applyThemeOverrides","THEME_OVERRIDE_TOKENS","THEME_TOKEN_CONTRACT","BRAND_TOKENS","EDITABLE_TOKENS","TOKEN_NAME_PATTERN","bucketOf","hostAliasFor","isThemeDebugEnabled","THEME_DEBUG_KEY","THEME_DEBUG_QUERY_PARAM","hexToHslTriplet","hslTripletToHex","isHslTriplet","PlacementResponseRenderer","PlacementSmoothHeight","buildPlacementDependencies","PlacementPayloadProvider","usePlacementPayload","UnifiedMarkdownParser","parseMarkdownToAst","parseAstToMarkdown","escapeWeb5Links","fixMalformedLinks","trimTrailingWhitespace","normalizeIconUrls","decodeLinkText","preprocessMarkdown","ComponentTracking","findKeywordsInContent","getContextualImageFilename","extractIntentFromMarkdown","getIntentFromMarkdown","createPageSection","generateSectionId","generateId","findImageInNode","findImageInChildren","DiagnosticsCollector","REFRESH_PROMPTS_UNTIL_KEY","REFRESH_PROMPTS_WINDOW_MS","getRefreshPromptsExpiry","shouldRefreshPrompts","enableRefreshPrompts","disableRefreshPrompts","BACKEND_ENVIRONMENT_KEY","BACKEND_ENVIRONMENT_QUERY_PARAM","DEFAULT_BACKEND_ENVIRONMENT","getBackendEnvironment","setBackendEnvironment","usesStagingBackend","isSimulationTraffic","MATCH_DEBUG_KEY","MATCH_DEBUG_QUERY_PARAM","isMatchDebugEnabled","setMatchDebug","resetMatchDebugCache","logMatchDebug","createWixAuthFetch","getOrCreateSessionId","getSessionId","getChatId","startNewChatId","setChatId","resetChatIdForTests","parseMarkdownToComponents","tryParseComponent","mergeSectionsWithStableReferences","WEB5_ROOT_ID","WEB5_ROOT_CLASS","WEB5_SCOPES","WEB5_SCOPE","WEB5_GLOBAL_TOKENS"],"sources":["../../src/index.ts"],"sourcesContent":["// Client IDs and experiment IDs\nexport { CLIENT_IDS, EXPERIMENT_IDS } from './clients';\n\nexport {\n type EmbedFeatureToggleResult,\n type FeatureToggleReader,\n createFeatureToggleReader,\n FeatureToggleProvider,\n useFeatureToggles,\n useFeatureToggle,\n} from './featureToggles/FeatureToggleContext';\n\n// Dev-only chrome injection contract for client packages\nexport type { DevEnvironment } from './client/devEnvironment';\n\n// Part types and helpers\nexport {\n type PartType,\n type Part,\n type HeadingPart,\n type ImagePart,\n type LinkPart,\n type ListPart,\n type ListItemPart,\n type KpiItemPart,\n type CardPart,\n type IconPart,\n type CalloutPart,\n type EntityPart,\n getPartsByType,\n getPartByRole,\n getAllByRole,\n getHeading,\n getImages,\n getLinks,\n extractContent,\n extractContentMarkdown,\n deriveRole,\n} from './parts/parts';\n\n// Component types\nexport type {\n BaseCompProps,\n SlotCompProps,\n SectionCompProps,\n SectionCompPropsWithSlot,\n TextCompProps,\n ButtonCompProps,\n ImageCompProps,\n BadgeCompProps,\n HeroButton,\n KpiItemCompProps,\n FeatureItemCompProps,\n FeatureCardCompProps,\n EntityItemData,\n EntityItem,\n GenericEntityData,\n GenericEntityCompProps,\n ComparisonRow,\n ComparisonColumn,\n AiNarrativeCompProps,\n HeroCompProps,\n HeroEntityCompProps,\n KpiCompProps,\n FeatureCardsCompProps,\n EntityCompProps,\n ComparisonCompProps,\n TextBlockCompProps,\n Component,\n BaseComponent,\n SlotComponent,\n SectionComponent,\n TextComponent,\n ButtonComponent,\n ImageComponent,\n BadgeComponent,\n KpiItemComponent,\n FeatureItemComponent,\n FeatureCardComponent,\n GenericEntityComponent,\n AiNarrativeComponent,\n ComparisonSectionComponent,\n TextBlockSectionComponent,\n HeroSectionComponent,\n HeroEntitySectionComponent,\n KpiSectionComponent,\n FeatureCardsSectionComponent,\n EntitySectionComponent,\n PropsOf,\n SectionFixture,\n CtaBannerCompProps,\n CtaBannerSectionComponent,\n CalloutCompProps,\n CalloutSectionComponent,\n NextStepsCompProps,\n NextStepsSectionComponent,\n FeatureSection9PlusCompProps,\n FeatureSection9PlusSectionComponent,\n ListItemsSectionCompProps,\n ListItemsSectionComponent,\n ErrorCompProps,\n ErrorSectionComponent,\n NullCompProps,\n NullSectionComponent,\n SolutionEntityCompProps,\n SolutionEntitySectionComponent,\n SolutionEntityData,\n BlogEntityCompProps,\n BlogEntitySectionComponent,\n BlogEntityData,\n GeneralTextCompProps,\n GeneralTextSectionComponent,\n PersonalizedNarrativeCompProps,\n PersonalizedNarrativeSectionComponent,\n} from './component/types';\n\n// Section definition\nexport type {\n SectionDefinition,\n ParseContext,\n ContextualImageResult,\n DropSection,\n} from './component/section-definition';\nexport { DROP_SECTION } from './component/section-definition';\n\n// Diagnostic types\nexport { DIAGNOSTIC_TYPES } from './component/diagnosticTypes';\nexport type { DiagnosticType } from './component/diagnosticTypes';\n\n// Image search filters\nexport {\n buildImageSearchFilter,\n type ImageSearchFilterString,\n} from './image/imageSearchFilterTypes';\nexport {\n ImageSearchFilterToken,\n backgroundFilter,\n} from './image/imageSearchFilters';\nexport type {\n ContextualImageAsset,\n ImageSourceInput,\n ResolvedImageSource,\n ResolvedImageSourceKind,\n} from './image/contextualImageTypes';\n\n// Section definition classes + createSdkRegistry\nexport {\n HeroSectionDefinition,\n HeroEntitySectionDefinition,\n KpiSectionDefinition,\n FeatureCardsSectionDefinition,\n EntitySectionDefinition,\n EntityCollectionSectionDefinition,\n ComparisonSectionDefinition,\n TextBlockSectionDefinition,\n CtaBannerSectionDefinition,\n CalloutSectionDefinition,\n NextStepsSectionDefinition,\n FeatureSection9PlusDefinition,\n ListItemsSectionDefinition,\n SkipNodesSectionDefinition,\n HtmlCommentSectionDefinition,\n SearchSectionDefinition,\n ErrorSectionDefinition,\n FallbackSectionDefinition,\n createSdkRegistry,\n} from './component/componentDefinitions';\n\n// Registry\nexport { ComponentRegistry } from './registry';\nexport type {\n SlotOptions,\n SectionOptions,\n SectionRegistration,\n SlotNode,\n SlotIntentNode,\n SectionIntentNode,\n SectionNode,\n SlotVariant,\n SectionVariant,\n RegistryCatalog,\n ActionResult,\n ActionHandler,\n} from './registry';\n\n// Pattern validator\nexport {\n validatePattern,\n validatePatternSyntax,\n validatePatternWithBlocks,\n type PatternValidationResult,\n type BlockElement,\n type EnrichedBlockElement,\n type LinkMetadata,\n type LinkAttribute,\n} from './patternValidator';\n\n// Markdown blocks\nexport {\n convertToBlockElements,\n convertToBlockElementsWithMapping,\n type BlockElementsWithMapping,\n} from './markdownBlocks';\n\n// Link types, enum & guards\nexport {\n Web5UrlType,\n type Web5AskUrl,\n type Web5EntityUrl,\n type Web5ImageUrl,\n type Web5IconUrl,\n type Web5ActionUrl,\n type Web5SearchUrl,\n type Web5Url,\n type HttpsUrl,\n type HttpUrl,\n type MailtoUrl,\n type RelativeUrl,\n type NavigableUrl,\n type ValidLinkUrl,\n type AnyKnownUrl,\n type LegacyUrl,\n isWeb5AskUrl,\n isWeb5EntityUrl,\n isWeb5ImageUrl,\n isWeb5IconUrl,\n isWeb5ActionUrl,\n isWeb5SearchUrl,\n isWeb5Url,\n isNavigableUrl,\n isValidLinkUrl,\n isLegacyUrl,\n} from './types/link-types';\n\n// Entity/URL parsing\nexport {\n parseWeb5Url,\n isValidWeb5Url,\n validateLinkUrl,\n type Web5UrlParsed,\n type Web5AskParsed,\n type Web5EntityParsed,\n type Web5ImageParsed,\n type Web5IconParsed,\n type Web5ActionParsed,\n type Web5SearchParsed,\n isEntityLink,\n parseEntityLink,\n extractProtocol,\n extractLinkMetadata,\n} from './utils/entityLinkParser';\n\n// Web5 link validation\nexport {\n findInvalidWeb5Links,\n type InvalidWeb5Link,\n} from './utils/web5LinkValidator';\n\n// Node matchers\nexport { hasImage, isHtmlComment } from './utils/nodeMatchers';\n\n// Match API\nexport {\n matchMarkdown,\n type MarkdownMatchResult,\n matchAllSections,\n type MatchAllSectionsResult,\n nodesToParts,\n} from './match';\n\n// ---------------------------------------------------------------------------\n// DI Infrastructure (moved from @wix/w5-client-circana)\n// ---------------------------------------------------------------------------\n\n// DI context and provider\nexport {\n ComponentDependenciesProvider,\n useComponentDependencies,\n type ComponentDependenciesProviderProps,\n} from './context/ComponentDependenciesContext';\n\n// Raw user query for the current response page\nexport {\n UserQueryProvider,\n useUserQuery,\n type UserQueryProviderProps,\n} from './context/UserQueryContext';\n\n// Chips context (suggestion chips shared between SearchSection and error states)\nexport {\n ChipsProvider,\n useChips,\n type SuggestionChip,\n} from './context/ChipsContext';\n\n// DI types\nexport type {\n ComponentDependencies,\n Web5LinkApi,\n ConversationApi,\n SendMessageTrackingOptions,\n SendMessageOptions,\n ComparisonSubmitPayload,\n ComparisonSelectedProduct,\n ProductComparisonSelectionState,\n ProductComparisonApi,\n EntityTransforms,\n MarkdownUtils,\n ResolveGenericEntityDataOptions,\n} from './types/dependencies';\nexport type {\n ApiPayloadItem,\n EntityTypeConfig,\n EntityConfig,\n EntityExtractionContext,\n} from './types/entity';\nexport {\n defaultExtractor,\n enrichEntitiesFromPayload,\n fetchEntityListData,\n listEntityItems,\n LIST_ITEMS_ENDPOINT,\n getEntityExtractor,\n registerEntityExtractor,\n transformToSolutionEntityData,\n transformToBlogPostEntityData,\n transformToGenericEntityData,\n toMatchedOptions,\n formatMoney,\n readCurrencyCode,\n formatPriceField,\n formatProductPriceLabel,\n} from './entity';\nexport type {\n EntityExtractor,\n FetchEntityListDataOptions,\n ListEntityItemsOptions,\n MatchedOption,\n ProductPriceFields,\n} from './entity';\nexport {\n CALLOUT_KINDS,\n CALLOUT_SEMANTICS,\n type CalloutKind,\n type CalloutSemantic,\n type Callout,\n} from './types/callout';\n\n// Wrapper hooks\nexport { useWeb5Link } from './hooks/useWeb5Link';\nexport { useConversation } from './hooks/useConversation';\nexport { useDebugImageContext } from './hooks/useDebugImageContext';\nexport { useResolvedImageSources } from './hooks/useResolvedImageSources';\nexport { useResolveGenericEntityData } from './hooks/useResolveGenericEntityData';\nexport { useEntityTransforms } from './hooks/useEntityTransforms';\nexport { useMarkdownUtils } from './hooks/useMarkdownUtils';\nexport { useResolveShopifyEntityData } from './hooks/useResolveShopifyEntityData';\nexport { useResolveSearchSpringEntityData } from './hooks/useResolveSearchSpringEntityData';\n\n// SearchSpring\nexport {\n fetchProductsByHandles,\n fetchProductsByHandlesMap,\n transformSSProductToEntityItemData,\n} from './services/searchspring';\nexport type {\n SearchSpringConfig,\n SSProduct,\n SSSearchResponse,\n SSSizeData,\n} from './services/searchspring';\n\n// Shopify Storefront API\n// Cart actions\nexport { addToCart } from './services/cart';\n\nexport {\n ShopifyStorefrontClient,\n resolveShopifyConfig,\n resolveShopifyEntity,\n transformShopifyProduct,\n transformShopifyCollection,\n transformShopifyArticle,\n transformShopifyEntityToItemData,\n PRODUCT_BY_HANDLE_QUERY,\n COLLECTION_BY_HANDLE_QUERY,\n ARTICLE_BY_HANDLE_QUERY,\n} from './services/shopify';\nexport type {\n ShopifyStorefrontConfig,\n ShopifyProduct,\n ShopifyCollection,\n ShopifyArticle,\n ShopifyImage,\n ShopifyMoneyV2,\n} from './services/shopify';\n\n// Utilities\nexport { cn } from './lib/utils';\nexport { normalizeImageUrl, getResizedImageUrl } from './utils/image-utils';\nexport {\n analyzeBackdrop,\n computeContentBBox,\n buildProbeUrl,\n loadImagePixels,\n loadBackdropAnalysis,\n type BackdropAnalysis,\n type ContentBBox,\n type ImagePixels,\n} from './utils/imageBackdrop';\nexport { stripMarkdown } from './component/componentDefinitions/parse-utils';\n\n// Color utilities\nexport {\n type RGB,\n rgbToHsl,\n hslToRgb,\n ensureMinLightness,\n toRgb,\n deriveDarkColor,\n deriveDarkGradient,\n deriveLightColor,\n} from './color/colorUtils';\n\n// Analytics\nexport {\n pushEvent,\n pushPromptSubmit,\n pushLinkClick,\n pushError,\n pushExit,\n pushEntityFiltered,\n hasAnalyticsConsent,\n type EntityFilteredReason,\n} from './utils/analyticsEvents';\n\n// Error handling types and utilities\nexport {\n type ConversationErrorType,\n ERROR_MARKDOWN,\n getErrorTypeFromStatus,\n createErrorMarkdown,\n STREAMING_TIMEOUT_MS,\n type ErrorActionType,\n type ErrorIconType,\n type ErrorTemplateButton,\n type ErrorTemplate,\n type ErrorTemplateOverrides,\n DEFAULT_ERROR_TEMPLATES,\n resolveErrorTemplate,\n} from './errors';\n\n// Navigation utilities\nexport {\n getForwardStack,\n setForwardStack,\n clearForwardStack,\n pushToForwardStack,\n popFromForwardStack,\n} from './utils/navigationStack';\n\n// UI components\nexport {\n UserQuery,\n type UserQueryProps,\n type ProductBackContext,\n} from './components/ui/UserQuery';\nexport {\n PRODUCT_BACK_SESSION_KEY,\n writeProductBackHandoff,\n readProductBackHandoff,\n type ProductBackHandoff,\n} from './utils/productBackHandoff';\nexport {\n PromptEntryEmptyState,\n type PromptEntryEmptyStateProps,\n} from './components/ui/PromptEntryEmptyState';\nexport {\n SearchSection,\n type SearchSectionProps,\n type SearchSectionHandle,\n type ScrollChip,\n} from './components/ui/SearchSection';\nexport {\n FeedbackBar,\n type FeedbackBarProps,\n type FeedbackCategoryOption,\n type FeedbackSentiment,\n type FeedbackSubmitInput,\n} from './components/ui/FeedbackBar';\nexport { Disclaimer, type DisclaimerProps } from './components/ui/Disclaimer';\nexport {\n BottomContainer,\n type BottomContainerProps,\n} from './components/ui/BottomContainer';\nexport { MarkdownText } from './components/ui/MarkdownText';\nexport {\n CalloutBlock,\n type CalloutBlockProps,\n} from './components/ui/CalloutBlock';\nexport {\n OptimizedImage,\n type OptimizedImageProps,\n} from './components/ui/OptimizedImage';\nexport {\n SectionSkeleton,\n type SectionSkeletonProps,\n} from './components/ui/SectionSkeleton';\nexport { SmartIcon, type SmartIconProps } from './components/ui/SmartIcon';\nexport { Loader, type LoaderProps } from './components/ui/Loader';\nexport {\n PlacementLoader,\n type PlacementLoaderProps,\n} from './components/ui/PlacementLoader';\nexport {\n UnifiedLink,\n detectLinkType,\n type UnifiedLinkProps,\n LinkType,\n type LinkVariant,\n} from './components/ui/UnifiedLink';\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from './components/ui/table';\n\n// Placement (DL #088, DL #102 behavior declarations)\nexport type {\n PlacementBehaviorConfig,\n PlacementConfig,\n PlacementPrompts,\n} from './types/placement';\n\n// Cross-bundle user-query broadcast event (DL #097 D2)\nexport {\n WEB5_USER_QUERY_EVENT,\n type Web5UserQueryEventDetail,\n type Web5UserQueryEvent,\n} from './types/userQueryEvent';\n\n// Cross-bundle answer-updated broadcast event (B2B-4121)\nexport {\n WEB5_ANSWER_UPDATED_EVENT,\n type Web5AnswerUpdatedEventDetail,\n type Web5AnswerUpdatedEvent,\n} from './types/answerUpdatedEvent';\n\n// Cross-bundle redirect broadcast event (DL #098 D3)\nexport {\n WEB5_REDIRECT_EVENT,\n type Web5RedirectEventDetail,\n type Web5RedirectEvent,\n type Web5RedirectReason,\n} from './types/redirectEvent';\n// `placementFilter` was removed — hero/next-steps exclusion is the prompt's job\n// and placement-specific designs belong as `{ placement: true }` registry\n// variants (resolved automatically via `resolveSection(type, { placement: true })`).\n\n// Client bundle loader (DL #088 D3.3)\nexport { loadClientBundle } from './client/loadClientBundle';\n\n// `?clientBundleUrl=` dev override — shared by `web50-server-ui` and\n// `embed-placement` so the trusted-host gate can't drift between them.\nexport {\n getClientBundleOverride,\n isTrustedBundleHost,\n} from './client/clientBundleOverride';\n\n// Client-UMD URL resolution (DL #094 per-msid, DL #129 per-template) and the\n// universal bundle←backend config merge (DL #129 Q3/Q7) — shared by\n// `web50-server-ui` and `embed-placement`, the two client-bundle load sites.\nexport {\n TEMPLATES_CDN_BASE,\n TEMPLATES_MANIFEST_URL,\n getTemplateOverride,\n isTemplatePickerRequested,\n isValidTemplateId,\n resolveClientBundleUrl,\n} from './client/clientBundleUrl';\nexport {\n mergeClientConfig,\n type DeepPartial,\n} from './client/mergeClientConfig';\nexport {\n applyThemeOverrides,\n THEME_OVERRIDE_TOKENS,\n type ThemeOverrideKey,\n type ThemeOverrides,\n} from './client/applyThemeOverrides';\nexport {\n THEME_TOKEN_CONTRACT,\n BRAND_TOKENS,\n EDITABLE_TOKENS,\n TOKEN_NAME_PATTERN,\n bucketOf,\n hostAliasFor,\n type TokenBucket,\n type TokenContractEntry,\n type TokenType,\n} from './theme/tokenContract';\nexport {\n isThemeDebugEnabled,\n THEME_DEBUG_KEY,\n THEME_DEBUG_QUERY_PARAM,\n type AppliedToken,\n type ThemeOverrideSource,\n} from './client/themeDebug';\nexport {\n hexToHslTriplet,\n hslTripletToHex,\n isHslTriplet,\n} from './theme/colorFormat';\n\n// Placement renderer + DI helper (DL #088 D3.2, D3.4)\nexport {\n PlacementResponseRenderer,\n PlacementSmoothHeight,\n type PlacementResponseRendererProps,\n type PlacementSection,\n type PlacementVariant,\n} from './components/placement/PlacementResponseRenderer';\nexport {\n buildPlacementDependencies,\n type BuildPlacementDependenciesOptions,\n} from './components/placement/buildPlacementDependencies';\nexport {\n PlacementPayloadProvider,\n usePlacementPayload,\n type PlacementPayloadContextValue,\n} from './components/placement/PlacementPayloadContext';\n\n// Markdown parsing utilities — lifted from web50-server-ui (DL #088 B9.1)\nexport {\n UnifiedMarkdownParser,\n parseMarkdownToAst,\n parseAstToMarkdown,\n} from './utils/unifiedMarkdownParser';\nexport {\n escapeWeb5Links,\n fixMalformedLinks,\n trimTrailingWhitespace,\n normalizeIconUrls,\n decodeLinkText,\n preprocessMarkdown,\n type PreprocessorDiagnostic,\n type PreprocessResult,\n} from './utils/markdownPreprocessor';\nexport {\n ComponentTracking,\n type ComponentNodeRange,\n} from './utils/componentTracking';\nexport {\n findKeywordsInContent,\n getContextualImageFilename,\n} from './utils/contentKeywordMatcher';\nexport {\n extractIntentFromMarkdown,\n getIntentFromMarkdown,\n type IntentInfo,\n type IntentExtractionOptions,\n type ResponseState,\n} from './utils/intentExtractor';\nexport type { PageSection } from './types/page-section';\nexport {\n createPageSection,\n generateSectionId,\n generateId,\n findImageInNode,\n findImageInChildren,\n type Product,\n type ComparisonProduct,\n type ProductComparisonSectionProps,\n} from './utils/propsExtractor';\nexport {\n DiagnosticsCollector,\n type DiagnosticEntry,\n} from './utils/diagnosticsCollector';\nexport {\n REFRESH_PROMPTS_UNTIL_KEY,\n REFRESH_PROMPTS_WINDOW_MS,\n getRefreshPromptsExpiry,\n shouldRefreshPrompts,\n enableRefreshPrompts,\n disableRefreshPrompts,\n} from './utils/refreshPrompts';\nexport {\n type BackendEnvironment,\n BACKEND_ENVIRONMENT_KEY,\n BACKEND_ENVIRONMENT_QUERY_PARAM,\n DEFAULT_BACKEND_ENVIRONMENT,\n getBackendEnvironment,\n setBackendEnvironment,\n usesStagingBackend,\n} from './utils/backendEnvironment';\nexport { isSimulationTraffic } from './utils/simulation';\nexport {\n MATCH_DEBUG_KEY,\n MATCH_DEBUG_QUERY_PARAM,\n isMatchDebugEnabled,\n setMatchDebug,\n resetMatchDebugCache,\n logMatchDebug,\n} from './utils/matchDebug';\nexport { createWixAuthFetch } from './client/wixAuthFetch';\nexport {\n getOrCreateSessionId,\n getSessionId,\n getChatId,\n startNewChatId,\n setChatId,\n resetChatIdForTests,\n} from './utils/sessionManager';\n\n// Component parser orchestrator — lifted from web50-server-ui (DL #088 B9.5)\nexport {\n parseMarkdownToComponents,\n tryParseComponent,\n mergeSectionsWithStableReferences,\n type ParseMarkdownOptions,\n type ParseMarkdownResult,\n type ComponentMatch,\n type ParserContext,\n} from './component/componentParser';\nexport type {\n ParserClientConfig,\n EnrichEntityProps,\n} from './component/parser-types';\n\n// Host-mount scope contract — shared by web50-server-ui (which stamps the\n// class and mounts), embed-placement (which mounts the same bundle elsewhere),\n// and the client CDN build (which compiles every selector against it).\nexport {\n WEB5_ROOT_ID,\n WEB5_ROOT_CLASS,\n WEB5_SCOPES,\n WEB5_SCOPE,\n WEB5_GLOBAL_TOKENS,\n type HostFitConfig,\n} from './hostScope';\n"],"mappings":"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","ignoreList":[]}
@@ -64,8 +64,25 @@ function getCompareAtPrice(product) {
64
64
  }
65
65
  return formatPrice(compare);
66
66
  }
67
- export function transformShopifyProduct(product) {
67
+
68
+ /**
69
+ * The live entry for the variant the turn resolved, if the store still has it.
70
+ * Both sides carry the bare numeric id — `extractVariants` strips the
71
+ * `gid://shopify/ProductVariant/` prefix, and the turn never adds one.
72
+ */
73
+ function findLiveVariant(variants, variantId) {
74
+ if (!variantId) {
75
+ return undefined;
76
+ }
77
+ return variants == null ? void 0 : variants.find(variant => variant.variantId === variantId);
78
+ }
79
+ export function transformShopifyProduct(product, variantId) {
68
80
  var _product$featuredImag, _product$options;
81
+ const variants = extractVariants(product);
82
+ // The turn decided WHICH variant to show; the live fetch is here for what is
83
+ // true about it right now. With no matched variant — or one the store has
84
+ // since dropped — the product-level range is still the only answer we have.
85
+ const matchedVariant = findLiveVariant(variants, variantId);
69
86
  return {
70
87
  url: product.onlineStoreUrl || '',
71
88
  title: product.title,
@@ -74,10 +91,14 @@ export function transformShopifyProduct(product) {
74
91
  imageUrl: (_product$featuredImag = product.featuredImage) == null ? void 0 : _product$featuredImag.url,
75
92
  secondaryImageUrl: getSecondaryImage(product),
76
93
  vendor: product.vendor,
77
- price: formatPrice(product.priceRange.minVariantPrice),
78
- compareAtPrice: getCompareAtPrice(product),
94
+ price: (matchedVariant == null ? void 0 : matchedVariant.price) || formatPrice(product.priceRange.minVariantPrice),
95
+ // Keyed on the variant, not on its value: an unmatched product falls back
96
+ // to the product-level compare-at, but a matched variant that is simply
97
+ // not on sale must not inherit one and print a false strikethrough.
98
+ compareAtPrice: matchedVariant ? matchedVariant.compareAtPrice : getCompareAtPrice(product),
99
+ available: matchedVariant == null ? void 0 : matchedVariant.available,
79
100
  sizes: extractSizes(product),
80
- variants: extractVariants(product),
101
+ variants,
81
102
  allImages: getAllImages(product),
82
103
  options: (_product$options = product.options) != null && _product$options.length ? product.options : undefined,
83
104
  tags: product.tags.length ? product.tags : undefined
@@ -111,10 +132,10 @@ export function transformShopifyArticle(article) {
111
132
  * Transform any resolved Shopify entity to the standard EntityItemData shape.
112
133
  * Detects the entity type by checking for type-specific fields.
113
134
  */
114
- export function transformShopifyEntityToItemData(entity, entityType) {
135
+ export function transformShopifyEntityToItemData(entity, entityType, variantId) {
115
136
  switch (entityType.toLowerCase()) {
116
137
  case 'product':
117
- return transformShopifyProduct(entity);
138
+ return transformShopifyProduct(entity, variantId);
118
139
  case 'collection':
119
140
  return transformShopifyCollection(entity);
120
141
  case 'article':