@wix/web5-core 1.56.0 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/dist/cjs/client/wixAuthFetch.js +2 -2
  2. package/dist/cjs/client/wixAuthFetch.js.map +1 -1
  3. package/dist/cjs/component/componentDefinitions/HeroEntitySectionDefinition.js +20 -15
  4. package/dist/cjs/component/componentDefinitions/HeroEntitySectionDefinition.js.map +1 -1
  5. package/dist/cjs/component/componentDefinitions/HeroSectionDefinition.js +12 -4
  6. package/dist/cjs/component/componentDefinitions/HeroSectionDefinition.js.map +1 -1
  7. package/dist/cjs/component/componentDefinitions/listItemsSectionDefinition.js +24 -29
  8. package/dist/cjs/component/componentDefinitions/listItemsSectionDefinition.js.map +1 -1
  9. package/dist/cjs/component/componentParser.js +8 -1
  10. package/dist/cjs/component/componentParser.js.map +1 -1
  11. package/dist/cjs/component/types.js.map +1 -1
  12. package/dist/cjs/components/placement/PlacementResponseRenderer.css +0 -4
  13. package/dist/cjs/components/placement/PlacementResponseRenderer.js +11 -33
  14. package/dist/cjs/components/placement/PlacementResponseRenderer.js.map +1 -1
  15. package/dist/cjs/components/placement/buildPlacementDependencies.js.map +1 -1
  16. package/dist/cjs/components/ui/OptimizedImage.js +59 -14
  17. package/dist/cjs/components/ui/OptimizedImage.js.map +1 -1
  18. package/dist/cjs/components/ui/SectionSkeleton.css +19 -0
  19. package/dist/cjs/components/ui/SectionSkeleton.js +8 -4
  20. package/dist/cjs/components/ui/SectionSkeleton.js.map +1 -1
  21. package/dist/cjs/components/ui/UserQuery.css +72 -0
  22. package/dist/cjs/components/ui/UserQuery.js +131 -37
  23. package/dist/cjs/components/ui/UserQuery.js.map +1 -1
  24. package/dist/cjs/context/UserQueryContext.js +34 -0
  25. package/dist/cjs/context/UserQueryContext.js.map +1 -0
  26. package/dist/cjs/entity/defaultExtractor.js +9 -2
  27. package/dist/cjs/entity/defaultExtractor.js.map +1 -1
  28. package/dist/cjs/entity/fetchEntityListData.js +13 -26
  29. package/dist/cjs/entity/fetchEntityListData.js.map +1 -1
  30. package/dist/cjs/entity/index.js +5 -1
  31. package/dist/cjs/entity/index.js.map +1 -1
  32. package/dist/cjs/entity/listEntityItems.js +90 -0
  33. package/dist/cjs/entity/listEntityItems.js.map +1 -0
  34. package/dist/cjs/hostScope.js +63 -0
  35. package/dist/cjs/hostScope.js.map +1 -0
  36. package/dist/cjs/index.js +38 -13
  37. package/dist/cjs/index.js.map +1 -1
  38. package/dist/cjs/patternValidator/validator.test.js +61 -61
  39. package/dist/cjs/patternValidator/validator.test.js.map +1 -1
  40. package/dist/cjs/registry/ComponentRegistry.js +22 -2
  41. package/dist/cjs/registry/ComponentRegistry.js.map +1 -1
  42. package/dist/cjs/registry/index.js +1 -3
  43. package/dist/cjs/registry/index.js.map +1 -1
  44. package/dist/cjs/registry/types.js.map +1 -1
  45. package/dist/cjs/styles/base-utilities.css +35 -0
  46. package/dist/cjs/styles/components.css +1 -0
  47. package/dist/cjs/styles/host-reset.css +81 -0
  48. package/dist/cjs/styles/tailwind-theme.css +6 -6
  49. package/dist/cjs/utils/backendEnvironment.js +78 -0
  50. package/dist/cjs/utils/backendEnvironment.js.map +1 -0
  51. package/dist/cjs/utils/entityLinkParser.js +3 -1
  52. package/dist/cjs/utils/entityLinkParser.js.map +1 -1
  53. package/dist/cjs/utils/imageBackdrop.js +269 -0
  54. package/dist/cjs/utils/imageBackdrop.js.map +1 -0
  55. package/dist/cjs/utils/intentExtractor.js +20 -9
  56. package/dist/cjs/utils/intentExtractor.js.map +1 -1
  57. package/dist/cjs/utils/productBackHandoff.js +106 -0
  58. package/dist/cjs/utils/productBackHandoff.js.map +1 -0
  59. package/dist/cjs/utils/refreshPrompts.js +72 -0
  60. package/dist/cjs/utils/refreshPrompts.js.map +1 -0
  61. package/dist/esm/client/wixAuthFetch.js +2 -2
  62. package/dist/esm/client/wixAuthFetch.js.map +1 -1
  63. package/dist/esm/component/componentDefinitions/HeroEntitySectionDefinition.js +20 -15
  64. package/dist/esm/component/componentDefinitions/HeroEntitySectionDefinition.js.map +1 -1
  65. package/dist/esm/component/componentDefinitions/HeroSectionDefinition.js +12 -4
  66. package/dist/esm/component/componentDefinitions/HeroSectionDefinition.js.map +1 -1
  67. package/dist/esm/component/componentDefinitions/listItemsSectionDefinition.js +25 -30
  68. package/dist/esm/component/componentDefinitions/listItemsSectionDefinition.js.map +1 -1
  69. package/dist/esm/component/componentParser.js +8 -1
  70. package/dist/esm/component/componentParser.js.map +1 -1
  71. package/dist/esm/component/types.js.map +1 -1
  72. package/dist/esm/components/placement/PlacementResponseRenderer.css +0 -4
  73. package/dist/esm/components/placement/PlacementResponseRenderer.js +1 -16
  74. package/dist/esm/components/placement/PlacementResponseRenderer.js.map +1 -1
  75. package/dist/esm/components/placement/buildPlacementDependencies.js.map +1 -1
  76. package/dist/esm/components/ui/OptimizedImage.js +50 -5
  77. package/dist/esm/components/ui/OptimizedImage.js.map +1 -1
  78. package/dist/esm/components/ui/SectionSkeleton.css +19 -0
  79. package/dist/esm/components/ui/SectionSkeleton.js +5 -1
  80. package/dist/esm/components/ui/SectionSkeleton.js.map +1 -1
  81. package/dist/esm/components/ui/UserQuery.css +72 -0
  82. package/dist/esm/components/ui/UserQuery.js +52 -6
  83. package/dist/esm/components/ui/UserQuery.js.map +1 -1
  84. package/dist/esm/context/UserQueryContext.js +21 -0
  85. package/dist/esm/context/UserQueryContext.js.map +1 -0
  86. package/dist/esm/entity/defaultExtractor.js +9 -2
  87. package/dist/esm/entity/defaultExtractor.js.map +1 -1
  88. package/dist/esm/entity/fetchEntityListData.js +14 -26
  89. package/dist/esm/entity/fetchEntityListData.js.map +1 -1
  90. package/dist/esm/entity/index.js +1 -0
  91. package/dist/esm/entity/index.js.map +1 -1
  92. package/dist/esm/entity/listEntityItems.js +85 -0
  93. package/dist/esm/entity/listEntityItems.js.map +1 -0
  94. package/dist/esm/hostScope.js +59 -0
  95. package/dist/esm/hostScope.js.map +1 -0
  96. package/dist/esm/index.js +13 -4
  97. package/dist/esm/index.js.map +1 -1
  98. package/dist/esm/patternValidator/validator.test.js +61 -61
  99. package/dist/esm/patternValidator/validator.test.js.map +1 -1
  100. package/dist/esm/registry/ComponentRegistry.js +22 -2
  101. package/dist/esm/registry/ComponentRegistry.js.map +1 -1
  102. package/dist/esm/registry/index.js +0 -1
  103. package/dist/esm/registry/index.js.map +1 -1
  104. package/dist/esm/registry/types.js.map +1 -1
  105. package/dist/esm/styles/base-utilities.css +35 -0
  106. package/dist/esm/styles/components.css +1 -0
  107. package/dist/esm/styles/host-reset.css +81 -0
  108. package/dist/esm/styles/tailwind-theme.css +6 -6
  109. package/dist/esm/utils/backendEnvironment.js +71 -0
  110. package/dist/esm/utils/backendEnvironment.js.map +1 -0
  111. package/dist/esm/utils/entityLinkParser.js +3 -1
  112. package/dist/esm/utils/entityLinkParser.js.map +1 -1
  113. package/dist/esm/utils/imageBackdrop.js +262 -0
  114. package/dist/esm/utils/imageBackdrop.js.map +1 -0
  115. package/dist/esm/utils/intentExtractor.js +21 -12
  116. package/dist/esm/utils/intentExtractor.js.map +1 -1
  117. package/dist/esm/utils/productBackHandoff.js +100 -0
  118. package/dist/esm/utils/productBackHandoff.js.map +1 -0
  119. package/dist/esm/utils/refreshPrompts.js +67 -0
  120. package/dist/esm/utils/refreshPrompts.js.map +1 -0
  121. package/dist/types/component/componentDefinitions/HeroEntitySectionDefinition.d.ts.map +1 -1
  122. package/dist/types/component/componentDefinitions/HeroSectionDefinition.d.ts.map +1 -1
  123. package/dist/types/component/componentDefinitions/listItemsSectionDefinition.d.ts +2 -2
  124. package/dist/types/component/componentDefinitions/listItemsSectionDefinition.d.ts.map +1 -1
  125. package/dist/types/component/componentParser.d.ts.map +1 -1
  126. package/dist/types/component/types.d.ts +1 -5
  127. package/dist/types/component/types.d.ts.map +1 -1
  128. package/dist/types/components/placement/PlacementResponseRenderer.d.ts +1 -1
  129. package/dist/types/components/placement/PlacementResponseRenderer.d.ts.map +1 -1
  130. package/dist/types/components/placement/buildPlacementDependencies.d.ts +1 -2
  131. package/dist/types/components/placement/buildPlacementDependencies.d.ts.map +1 -1
  132. package/dist/types/components/ui/OptimizedImage.d.ts +9 -0
  133. package/dist/types/components/ui/OptimizedImage.d.ts.map +1 -1
  134. package/dist/types/components/ui/SectionSkeleton.d.ts.map +1 -1
  135. package/dist/types/components/ui/UserQuery.d.ts +21 -0
  136. package/dist/types/components/ui/UserQuery.d.ts.map +1 -1
  137. package/dist/types/context/UserQueryContext.d.ts +12 -0
  138. package/dist/types/context/UserQueryContext.d.ts.map +1 -0
  139. package/dist/types/entity/defaultExtractor.d.ts.map +1 -1
  140. package/dist/types/entity/fetchEntityListData.d.ts +0 -2
  141. package/dist/types/entity/fetchEntityListData.d.ts.map +1 -1
  142. package/dist/types/entity/index.d.ts +1 -0
  143. package/dist/types/entity/index.d.ts.map +1 -1
  144. package/dist/types/entity/listEntityItems.d.ts +40 -0
  145. package/dist/types/entity/listEntityItems.d.ts.map +1 -0
  146. package/dist/types/hostScope.d.ts +83 -0
  147. package/dist/types/hostScope.d.ts.map +1 -0
  148. package/dist/types/index.d.ts +11 -7
  149. package/dist/types/index.d.ts.map +1 -1
  150. package/dist/types/registry/ComponentRegistry.d.ts +8 -0
  151. package/dist/types/registry/ComponentRegistry.d.ts.map +1 -1
  152. package/dist/types/registry/index.d.ts +0 -1
  153. package/dist/types/registry/index.d.ts.map +1 -1
  154. package/dist/types/registry/types.d.ts +5 -6
  155. package/dist/types/registry/types.d.ts.map +1 -1
  156. package/dist/types/utils/backendEnvironment.d.ts +30 -0
  157. package/dist/types/utils/backendEnvironment.d.ts.map +1 -0
  158. package/dist/types/utils/entityLinkParser.d.ts.map +1 -1
  159. package/dist/types/utils/imageBackdrop.d.ts +102 -0
  160. package/dist/types/utils/imageBackdrop.d.ts.map +1 -0
  161. package/dist/types/utils/intentExtractor.d.ts +21 -4
  162. package/dist/types/utils/intentExtractor.d.ts.map +1 -1
  163. package/dist/types/utils/productBackHandoff.d.ts +43 -0
  164. package/dist/types/utils/productBackHandoff.d.ts.map +1 -0
  165. package/dist/types/utils/refreshPrompts.d.ts +32 -0
  166. package/dist/types/utils/refreshPrompts.d.ts.map +1 -0
  167. package/package.json +4 -3
  168. package/src/components/placement/PlacementResponseRenderer.css +265 -0
  169. package/src/components/ui/Disclaimer.css +35 -0
  170. package/src/components/ui/FeedbackBar.css +267 -0
  171. package/src/components/ui/PlacementLoader.css +101 -0
  172. package/src/components/ui/PromptEntryEmptyState.css +172 -0
  173. package/src/components/ui/SearchSection.css +538 -0
  174. package/src/components/ui/SectionSkeleton.css +128 -0
  175. package/src/components/ui/UserQuery.css +72 -0
  176. package/src/styles/base-utilities.css +35 -0
  177. package/src/styles/components.css +1 -0
  178. package/src/styles/host-reset.css +81 -0
  179. package/src/styles/tailwind-theme.css +6 -6
  180. package/dist/cjs/registry/Intent.js +0 -19
  181. package/dist/cjs/registry/Intent.js.map +0 -1
  182. package/dist/cjs/utils/conversationApi.js +0 -52
  183. package/dist/cjs/utils/conversationApi.js.map +0 -1
  184. package/dist/cjs/utils/conversationMode.js +0 -23
  185. package/dist/cjs/utils/conversationMode.js.map +0 -1
  186. package/dist/esm/registry/Intent.js +0 -15
  187. package/dist/esm/registry/Intent.js.map +0 -1
  188. package/dist/esm/utils/conversationApi.js +0 -45
  189. package/dist/esm/utils/conversationApi.js.map +0 -1
  190. package/dist/esm/utils/conversationMode.js +0 -18
  191. package/dist/esm/utils/conversationMode.js.map +0 -1
  192. package/dist/types/registry/Intent.d.ts +0 -12
  193. package/dist/types/registry/Intent.d.ts.map +0 -1
  194. package/dist/types/utils/conversationApi.d.ts +0 -26
  195. package/dist/types/utils/conversationApi.d.ts.map +0 -1
  196. package/dist/types/utils/conversationMode.d.ts +0 -16
  197. package/dist/types/utils/conversationMode.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"entityLinkParser.d.ts","sourceRoot":"","sources":["../../../src/utils/entityLinkParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EACL,WAAW,EAEX,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,gBAAgB,GAChB,gBAAgB,CAAC;AAIrB;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA6E9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,YAAY,GAAG,SAAS,CA8B1B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GACV;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA0BjD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW/D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,GAAG,GAAG,YAAY,GAAG,IAAI,CAgClE"}
1
+ {"version":3,"file":"entityLinkParser.d.ts","sourceRoot":"","sources":["../../../src/utils/entityLinkParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EACL,WAAW,EAEX,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,gBAAgB,GAChB,gBAAgB,CAAC;AAIrB;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA+E9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,YAAY,GAAG,SAAS,CA8B1B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GACV;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA0BjD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW/D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,GAAG,GAAG,YAAY,GAAG,IAAI,CAgClE"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Result of inspecting an image's edges to decide how it should sit in a slot
3
+ * whose aspect ratio differs from the image's own.
4
+ *
5
+ * The problem: a single CSS `object-fit` can't serve both kinds of imagery a
6
+ * conversational page surfaces. Product cutouts (subject on a seamless white
7
+ * sweep, or a transparent PNG) must never be cropped — `cover` chops the
8
+ * product. Full-bleed scenes (a model in a street, a flat-lay that fills the
9
+ * frame) look broken when letterboxed — they want `cover`.
10
+ *
11
+ * We can't tell these apart from the resolver metadata (it only exposes url +
12
+ * optional dimensions), so we sniff the pixels: sample the image's border ring
13
+ * and ask "is there a consistent backdrop colour behind the subject?".
14
+ * - Consistent border → seamless backdrop → render `contain` and paint the
15
+ * slot that backdrop colour, so the "letterbox" becomes an invisible
16
+ * extension of the image's own sweep (white shoe → white fill; green
17
+ * sweater sweep → green fill). The whole subject is always visible.
18
+ * - Noisy border → edge-to-edge scene → render `cover`; cropping the
19
+ * margins is safe and letterboxing would look wrong.
20
+ */
21
+ export interface BackdropAnalysis {
22
+ /** True when the border reads as a seamless backdrop (uniform or transparent). */
23
+ hasBackdrop: boolean;
24
+ /**
25
+ * CSS colour to paint behind a `contain`ed image so the letterbox blends.
26
+ * `'transparent'` for cutouts with an alpha border (the page background then
27
+ * shows through). Undefined when `hasBackdrop` is false.
28
+ */
29
+ backgroundColor?: string;
30
+ }
31
+ /**
32
+ * Inspect the 1px border ring of an RGBA buffer and classify the backdrop.
33
+ * Pure and synchronous so it can be unit-tested without a DOM.
34
+ */
35
+ export declare function analyzeBackdrop(data: Uint8ClampedArray, width: number, height: number): BackdropAnalysis;
36
+ /**
37
+ * Bounding box of the non-background content in a probed image, in sample-grid
38
+ * coordinates (0..size-1), plus the sampled background colour. Used by callers
39
+ * that need *where the subject sits* (e.g. crop-safety in a fixed-aspect slot),
40
+ * which is a different question from `analyzeBackdrop`'s "is there a backdrop".
41
+ */
42
+ export interface ContentBBox {
43
+ top: number;
44
+ bottom: number;
45
+ left: number;
46
+ right: number;
47
+ /** Background colour, sampled from the top-left pixel. */
48
+ background: {
49
+ r: number;
50
+ g: number;
51
+ b: number;
52
+ };
53
+ }
54
+ /**
55
+ * Find the bounding box of the subject by treating the top-left pixel as the
56
+ * background colour and flagging every pixel that differs from it (or is
57
+ * transparent). Pure and synchronous. Returns null for an all-background frame.
58
+ *
59
+ * `backgroundTolerance`/`alphaThreshold` default to the values tuned for
60
+ * uniform studio catalog shots; callers can override.
61
+ */
62
+ export declare function computeContentBBox(data: Uint8ClampedArray, size: number, options?: {
63
+ backgroundTolerance?: number;
64
+ alphaThreshold?: number;
65
+ }): ContentBBox | null;
66
+ /**
67
+ * Build the URL of a tiny, aspect-preserving (`fit`) version of an image so we
68
+ * can read its true edges. Wix media is downscaled by the CDN; other URLs are
69
+ * probed at full size (still drawn onto a small canvas).
70
+ */
71
+ export declare function buildProbeUrl(effectiveFilename: string): string;
72
+ /** RGBA pixels of a probed image, drawn onto a `size`×`size` grid, alongside the
73
+ * source's true intrinsic dimensions (needed for aspect-aware crop math). */
74
+ export interface ImagePixels {
75
+ data: Uint8ClampedArray;
76
+ size: number;
77
+ naturalWidth: number;
78
+ naturalHeight: number;
79
+ }
80
+ /**
81
+ * Shared probe plumbing: load a (downscaled, for Wix) version of the image
82
+ * cross-origin, draw it onto a `size`×`size` canvas, and return its pixels plus
83
+ * intrinsic dimensions. Resolves to `null` on any failure — missing DOM, a
84
+ * data/blob source, a load error, or a tainted canvas (if CORS ever regresses)
85
+ * — so every caller can fall back to its own default. Browser-only.
86
+ *
87
+ * Both the backdrop classifier (`loadBackdropAnalysis`) and bounding-box callers
88
+ * build on this so the canvas/CORS/taint handling lives in exactly one place.
89
+ */
90
+ export declare function loadImagePixels(effectiveFilename: string, options?: {
91
+ size?: number;
92
+ }, signal?: {
93
+ aborted: boolean;
94
+ }): Promise<ImagePixels | null>;
95
+ /**
96
+ * Load a probe image and analyze its backdrop. Resolves to `NO_BACKDROP` on any
97
+ * failure so callers fall back to their default fit. Browser-only.
98
+ */
99
+ export declare function loadBackdropAnalysis(effectiveFilename: string, signal?: {
100
+ aborted: boolean;
101
+ }): Promise<BackdropAnalysis>;
102
+ //# sourceMappingURL=imageBackdrop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageBackdrop.d.ts","sourceRoot":"","sources":["../../../src/utils/imageBackdrop.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAwBD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,gBAAgB,CAkElB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,UAAU,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE,WAAW,GAAG,IAAI,CAmCpB;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAa/D;AAED;8EAC8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3B,MAAM,CAAC,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAC5B,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA+C7B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,iBAAiB,EAAE,MAAM,EACzB,MAAM,CAAC,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAO3B"}
@@ -1,11 +1,28 @@
1
- import { Intent } from '../registry/Intent';
2
1
  export type ResponseState = 'full' | 'partial';
3
2
  export interface IntentInfo {
4
- intent: Intent;
3
+ intent: string;
5
4
  stage?: string;
6
5
  reason?: string;
7
6
  state?: ResponseState;
8
7
  }
9
- export declare function extractIntentFromMarkdown(markdown: string): IntentInfo | null;
10
- export declare function getIntentFromMarkdown(markdown: string, defaultIntent?: Intent): IntentInfo;
8
+ /**
9
+ * Controls how a raw intent string is validated / defaulted during extraction.
10
+ * Core holds NO intent list of its own — the taxonomy is client-specific. A
11
+ * caller supplies the client's list (typically `registry.getKnownIntents()`) to
12
+ * make the FE honour that client's intents; with no list, any emitted intent is
13
+ * accepted verbatim (resolution then falls back to the section default when the
14
+ * intent has no registered variant).
15
+ */
16
+ export interface IntentExtractionOptions {
17
+ /**
18
+ * The intents to accept (matched case-insensitively). An emitted intent
19
+ * outside this list is treated as absent. When omitted, no filtering is
20
+ * applied and the emitted intent passes through as-is.
21
+ */
22
+ validIntents?: readonly string[];
23
+ /** Intent assumed when the markdown carries no intent annotation. Defaults to ''. */
24
+ defaultIntent?: string;
25
+ }
26
+ export declare function extractIntentFromMarkdown(markdown: string, options?: IntentExtractionOptions): IntentInfo | null;
27
+ export declare function getIntentFromMarkdown(markdown: string, options?: IntentExtractionOptions): IntentInfo;
11
28
  //# sourceMappingURL=intentExtractor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"intentExtractor.d.ts","sourceRoot":"","sources":["../../../src/utils/intentExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAiBD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAwB7E;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,GAAE,MAAyB,GACvC,UAAU,CAOZ"}
1
+ {"version":3,"file":"intentExtractor.d.ts","sourceRoot":"","sources":["../../../src/utils/intentExtractor.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAsBD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,uBAAuB,GAChC,UAAU,GAAG,IAAI,CAwBnB;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,uBAAuB,GAChC,UAAU,CAOZ"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Product-page → full-app "back" context hand-off (DL #114).
3
+ *
4
+ * A PDP placement writes the product context to `sessionStorage` immediately
5
+ * before redirecting the visitor to the full Web5 page; the app reads it once
6
+ * on load and renders a back-to-product badge in the conversation header.
7
+ *
8
+ * The context never enters the URL, so there is no shareable/tamperable link
9
+ * that could spoof the header (the security driver in DL #114). The hand-off
10
+ * relies on the redirect being a same-origin, same-tab top-level navigation
11
+ * (`searchRedirectUrl`, e.g. `/ai`), which is what keeps `sessionStorage`
12
+ * readable on the other side. Cross-origin → nothing is read → no badge.
13
+ */
14
+ export declare const PRODUCT_BACK_SESSION_KEY = "web5:productBack";
15
+ export interface ProductBackHandoff {
16
+ /** Product display name (first-party; e.g. the PDP `og:title`). */
17
+ title?: string;
18
+ /** Product thumbnail URL (first-party; e.g. the PDP `og:image`). */
19
+ imageUrl?: string;
20
+ /** The product page to return to — the PDP's own URL. */
21
+ backUrl?: string;
22
+ /** Epoch ms when written; the reader drops stale entries. */
23
+ ts?: number;
24
+ }
25
+ /**
26
+ * Write the back-context just before navigating away from a product page.
27
+ * Values default to the page's own first-party Open Graph tags and URL, so a
28
+ * standard PDP needs no extra wiring; pass `overrides` to supply exact data.
29
+ * No-op outside the browser or when no product title can be determined.
30
+ */
31
+ export declare function writeProductBackHandoff(overrides?: {
32
+ title?: string;
33
+ imageUrl?: string;
34
+ backUrl?: string;
35
+ }): void;
36
+ /**
37
+ * Read and immediately delete the back-context (consume-once: survives exactly
38
+ * one page load, so a reload or bfcache restore won't replay it). Returns null
39
+ * when absent or unparseable. Callers must still validate the values before use
40
+ * (freshness window, allowed-domain check on `backUrl`, `https:` on `imageUrl`).
41
+ */
42
+ export declare function readProductBackHandoff(): ProductBackHandoff | null;
43
+ //# sourceMappingURL=productBackHandoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"productBackHandoff.d.ts","sourceRoot":"","sources":["../../../src/utils/productBackHandoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAoCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,CAAC,EAAE;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CAuBP;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,kBAAkB,GAAG,IAAI,CAmBlE"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Refresh-prompts flag (debug-only).
3
+ *
4
+ * When active, the Turn RPC request (`POST /v1/turn`, DL #110) carries
5
+ * `additionalData.refresh_prompts: 'true'`, asking the BE to re-pull prompts
6
+ * instead of serving cached ones.
7
+ *
8
+ * Keeping it on slows the app, so the flag self-expires: rather than a bare
9
+ * boolean we persist an expiry timestamp in
10
+ * `localStorage["web5_refresh_prompts_until"]`. `shouldRefreshPrompts()` is
11
+ * true only while now < expiry, so the cap holds even across reloads or if a
12
+ * UI timer never fires. Lives in web5-core so the request builder and any
13
+ * surface honor the same toggle.
14
+ */
15
+ export declare const REFRESH_PROMPTS_UNTIL_KEY = "web5_refresh_prompts_until";
16
+ /** How long the flag stays active once enabled (2 minutes). */
17
+ export declare const REFRESH_PROMPTS_WINDOW_MS: number;
18
+ /**
19
+ * Read the expiry timestamp (ms epoch) from localStorage. Returns 0 when
20
+ * unset, invalid, or storage is unavailable.
21
+ */
22
+ export declare const getRefreshPromptsExpiry: () => number;
23
+ /** Whether the refresh-prompts flag is currently active (within its window). */
24
+ export declare const shouldRefreshPrompts: () => boolean;
25
+ /**
26
+ * Activate the flag for `windowMs` from now and return the new expiry
27
+ * timestamp. Re-enabling restarts the window.
28
+ */
29
+ export declare const enableRefreshPrompts: (windowMs?: number) => number;
30
+ /** Deactivate the flag immediately (proactive off). */
31
+ export declare const disableRefreshPrompts: () => void;
32
+ //# sourceMappingURL=refreshPrompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refreshPrompts.d.ts","sourceRoot":"","sources":["../../../src/utils/refreshPrompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,yBAAyB,+BAA+B,CAAC;AAEtE,+DAA+D;AAC/D,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAO,MAY1C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,QAAO,OACA,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,cACrB,MAAM,KACf,MAQF,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,qBAAqB,QAAO,IAMxC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wix/web5-core",
3
3
  "license": "MIT",
4
- "version": "1.56.0",
4
+ "version": "1.57.0",
5
5
  "author": {
6
6
  "name": "tsachis",
7
7
  "email": "tsachis@wix.com"
@@ -14,7 +14,8 @@
14
14
  "dist/cjs",
15
15
  "dist/esm",
16
16
  "dist/types",
17
- "src/styles"
17
+ "src/styles",
18
+ "src/components/**/*.css"
18
19
  ],
19
20
  "scripts": {
20
21
  "build": "yoshi-library build && node scripts/fix-esm-extensions.js",
@@ -99,5 +100,5 @@
99
100
  "wallaby": {
100
101
  "autoDetect": true
101
102
  },
102
- "falconPackageHash": "85aa415503e1949c89b77d043271b71ca3bd64f50d7027e8d8b1e0c8"
103
+ "falconPackageHash": "d81e7d4252b50b94d46bdb6c4a55696d95b2787761303c708cb8bf9e"
103
104
  }
@@ -0,0 +1,265 @@
1
+ /* PlacementResponseRenderer — placement card chrome (DL #097 —
2
+ Figma 128:5251 framing / 128:5258 conversation).
3
+ Renders the streamed answer as a warm card with a FormAI eyebrow and a
4
+ gradient highlight ring (accent → transparent, top-left → bottom-right)
5
+ that holds while the answer streams, spins twice once it settles, and then
6
+ stays put. The conversation variant additionally shows the user's question
7
+ as a chip.
8
+ Re-skin via the `--w5-placement-*` tokens below.
9
+ The loading skeleton's styles live in `../ui/PlacementLoader.css`. */
10
+
11
+ /* Outer host-page spacing — matches the loader's `--w5-placement-spacing` so
12
+ the gap to surrounding content doesn't change at swap time. */
13
+ [data-w5-placement-renderer] {
14
+ margin-block: var(--w5-placement-spacing, 24px);
15
+ }
16
+
17
+ /* The loader→content swap is height-animated by the PlacementSmoothHeight
18
+ wrapper (`.w5-placement__body` below); this fade-in covers the paint swap
19
+ itself so the card doesn't pop in while the height glides. Plays once per
20
+ renderer mount (so again after each re-submit). */
21
+ [data-w5-placement-renderer] {
22
+ animation: w5-placement-content-in 240ms ease-out both;
23
+ }
24
+
25
+ @keyframes w5-placement-content-in {
26
+ from {
27
+ opacity: 0;
28
+ }
29
+ to {
30
+ opacity: 1;
31
+ }
32
+ }
33
+
34
+ [data-w5-placement-renderer].w5-placement {
35
+ box-sizing: border-box;
36
+ padding: var(--w5-placement-card-padding, 30px);
37
+ border-radius: var(--w5-placement-card-radius, 4px);
38
+ background: var(--w5-placement-card-bg, #f1f0ee);
39
+ /* Section components inside the answer use `bg-background`
40
+ (= var(--color-background), white), which would paint a white block over
41
+ the card. Re-point that token within the placement so those sections
42
+ inherit the card colour instead — one shared background across the whole
43
+ placement. Change --w5-placement-card-bg to re-theme card + sections. */
44
+ --color-background: var(--w5-placement-card-bg, #f1f0ee);
45
+ /* Reserve the border box so the conversation highlight ring (the
46
+ `::before` gradient below) doesn't shift layout when it fades in/out. */
47
+ border: 2px solid transparent;
48
+ }
49
+
50
+ /* Height smoothing for the whole placement slot: PlacementSmoothHeight
51
+ (mounted around the loader/content swap in embed-placement) measures the
52
+ current child (ResizeObserver) and sets an explicit `height` here, so the
53
+ loader→content swap and each streamed section appending animate instead
54
+ of snapping. Until the first measurement lands there's no inline height
55
+ and the box sizes naturally. */
56
+ .w5-placement__body {
57
+ overflow: clip;
58
+ transition: height var(--w5-placement-grow-duration, 350ms) ease-out;
59
+ }
60
+
61
+ /* flow-root so children's top/bottom margins can't collapse out of the
62
+ measured inner box (they'd be clipped by the wrapper otherwise). */
63
+ .w5-placement__body-inner {
64
+ display: flow-root;
65
+ }
66
+
67
+ /* Height clamp + "Show more" (DL #113) — Google-AI-Overview style. Opt-in via
68
+ the slot's `data-clamp` attribute; the renderer adds `--clamped` to the card
69
+ ROOT and caps it directly (no inner wrapper), so the answer sections stay
70
+ direct children of the placement root — clients lay them out with
71
+ `:has(> …)` direct-child grids (feature-com's search-overview two-column
72
+ layout) that a wrapper would break. The cap is also what
73
+ `PlacementSmoothHeight` then measures, so the slot animates to the capped
74
+ height rather than the full content. */
75
+ .w5-placement--clamped {
76
+ position: relative;
77
+ max-height: var(--w5-placement-clamp-height, 220px);
78
+ overflow: hidden;
79
+ }
80
+
81
+ /* The variant highlight ring is a `::before` at `inset: -2px` (outside the
82
+ padding box) — `overflow: hidden` above would clip it to a stub. Drop it on
83
+ clamped cards; the clamp + fade is its own treatment. */
84
+ .w5-placement--clamped::before {
85
+ content: none;
86
+ }
87
+
88
+ /* Fade the cut-off bottom edge to the card background (a wash, like Google —
89
+ not a mask that makes text vanish). Rendered only when the content overflows
90
+ (the renderer omits it otherwise), pinned to the bottom of the capped root. */
91
+ .w5-placement__fade {
92
+ position: absolute;
93
+ inset-inline: 0;
94
+ bottom: 0;
95
+ height: var(--w5-placement-fade-height, 96px);
96
+ background: linear-gradient(
97
+ to bottom,
98
+ transparent,
99
+ var(--w5-placement-card-bg, #f1f0ee)
100
+ );
101
+ pointer-events: none;
102
+ }
103
+
104
+ /* "Show more" pill, pinned over the fade. Re-skins via the shared
105
+ `--w5-placement-*` tokens. */
106
+ .w5-placement__show-more {
107
+ position: absolute;
108
+ bottom: 14px;
109
+ left: 50%;
110
+ transform: translateX(-50%);
111
+ display: inline-flex;
112
+ align-items: center;
113
+ gap: 6px;
114
+ padding: 8px 18px;
115
+ border-radius: 999px;
116
+ border: 1px solid var(--w5-placement-show-more-border, #d8d5cf);
117
+ background: var(--w5-placement-show-more-bg, #fff);
118
+ color: var(--w5-placement-show-more-color, #000);
119
+ font-size: 14px;
120
+ line-height: 15px;
121
+ font-weight: 500;
122
+ text-decoration: none;
123
+ cursor: pointer;
124
+ white-space: nowrap;
125
+ }
126
+
127
+ .w5-placement__show-more:hover {
128
+ background: var(--w5-placement-show-more-bg-hover, #f6f5f3);
129
+ }
130
+
131
+ .w5-placement__show-more:focus-visible {
132
+ outline: 2px solid var(--w5-placement-accent, #ef1b28);
133
+ outline-offset: 2px;
134
+ }
135
+
136
+ .w5-placement__eyebrow {
137
+ display: flex;
138
+ align-items: center;
139
+ gap: 10px;
140
+ margin-bottom: 20px;
141
+ }
142
+
143
+ .w5-placement__eyebrow-icon {
144
+ flex: none;
145
+ color: var(--w5-placement-accent, #ef1b28);
146
+ }
147
+
148
+ .w5-placement__eyebrow-label {
149
+ font-size: 14px;
150
+ line-height: 15px;
151
+ font-weight: 500;
152
+ color: var(--w5-placement-eyebrow-color, #000);
153
+ }
154
+
155
+ /* The user's question (conversation variant). */
156
+ .w5-placement__query {
157
+ display: inline-block;
158
+ margin: 0 0 20px;
159
+ padding: 7px 10px;
160
+ border-radius: 3px;
161
+ background: var(--w5-placement-query-bg, #e2dfd9);
162
+ font-size: 14px;
163
+ line-height: 15px;
164
+ color: var(--w5-placement-query-color, #000);
165
+ }
166
+
167
+ /* Placement highlight (conversation + informational): a gradient ring — fully
168
+ opaque accent at the top-left corner fading to transparent toward the
169
+ bottom-right. A solid `border-color` can't render a gradient, so the ring
170
+ is a masked pseudo-element: the gradient paints the whole box, and the
171
+ mask punches out the padding box so only the 2px border area remains.
172
+ The ring shows as soon as the placement starts to render, holds for the
173
+ whole streamed render (the `--streaming` modifier below); once the answer
174
+ settles the modifier drops and the animation plays — the gradient spins
175
+ two full counter-clockwise turns, then the ring stays in place. Replays
176
+ after each re-submit since the renderer remounts via the loader. */
177
+ .w5-placement--conversation,
178
+ .w5-placement--informational {
179
+ position: relative;
180
+ }
181
+
182
+ /* Registered so the gradient angle interpolates in the keyframes below.
183
+ Browsers without `@property` (Firefox < 128) apply custom-property
184
+ keyframes discretely — harmless here, since -585deg ≡ 135deg (mod 360°)
185
+ the jump is invisible and only the hold + fade-out remains. */
186
+ @property --w5-placement-highlight-angle {
187
+ syntax: '<angle>';
188
+ inherits: false;
189
+ initial-value: 135deg;
190
+ }
191
+
192
+ .w5-placement--conversation::before,
193
+ .w5-placement--informational::before {
194
+ content: '';
195
+ position: absolute;
196
+ /* Cover the reserved 2px transparent border (absolute positioning is
197
+ relative to the padding box, which excludes it). */
198
+ inset: -2px;
199
+ padding: 2px;
200
+ /* Outer radius of the card's border box: card radius + border width. */
201
+ border-radius: calc(var(--w5-placement-card-radius, 4px) + 2px);
202
+ background: linear-gradient(
203
+ var(--w5-placement-highlight-angle, 135deg),
204
+ var(--w5-placement-accent, #ef1b28),
205
+ transparent
206
+ );
207
+ /* Keep only the ring: padding-box ⊖ full box. */
208
+ -webkit-mask:
209
+ linear-gradient(#fff 0 0) content-box,
210
+ linear-gradient(#fff 0 0);
211
+ -webkit-mask-composite: xor;
212
+ mask:
213
+ linear-gradient(#fff 0 0) content-box,
214
+ linear-gradient(#fff 0 0);
215
+ mask-composite: exclude;
216
+ pointer-events: none;
217
+ /* ~9.4s default for the 2.5 counter-clockwise turns (same angular speed as
218
+ the original 2 turns in 7.5s); the ring then holds its final state
219
+ (`both` fill mode) and stays visible. */
220
+ animation: w5-placement-highlight
221
+ var(--w5-placement-highlight-duration, 9375ms) linear both;
222
+ }
223
+
224
+ /* Still streaming: hold the ring fully visible; the spin only starts
225
+ when this class is removed (answer settled) and the animation kicks in. */
226
+ .w5-placement--conversation.w5-placement--streaming::before,
227
+ .w5-placement--informational.w5-placement--streaming::before {
228
+ animation: none;
229
+ opacity: 1;
230
+ }
231
+
232
+ @keyframes w5-placement-highlight {
233
+ /* Two and a half counter-clockwise turns (135° → -765° ≡ 315°) at constant
234
+ speed, so the accent settles on the opposite side (bottom-right); the
235
+ ring stays fully visible throughout and after. */
236
+ 0% {
237
+ --w5-placement-highlight-angle: 135deg;
238
+ opacity: 1;
239
+ }
240
+ 100% {
241
+ --w5-placement-highlight-angle: -765deg;
242
+ opacity: 1;
243
+ }
244
+ }
245
+
246
+ @media (prefers-reduced-motion: reduce) {
247
+ /* No spin — show the ring statically in its settled position
248
+ (accent at the bottom-right). */
249
+ .w5-placement--conversation::before,
250
+ .w5-placement--informational::before,
251
+ .w5-placement--conversation.w5-placement--streaming::before,
252
+ .w5-placement--informational.w5-placement--streaming::before {
253
+ animation: none;
254
+ opacity: 1;
255
+ --w5-placement-highlight-angle: 315deg;
256
+ }
257
+
258
+ .w5-placement__body {
259
+ transition: none;
260
+ }
261
+
262
+ [data-w5-placement-renderer] {
263
+ animation: none;
264
+ }
265
+ }
@@ -0,0 +1,35 @@
1
+ /* "AI can make mistakes. Learn more" footer. Mounted by the host app
2
+ alongside the FeedbackBar; clients can override the whole component via
3
+ the DisclaimerComponent UI slot.
4
+
5
+ Typography defaults mirror `.web5-feedback-bar` so a single client-side
6
+ override (`--web5-feedback-bar-color`) re-skins both together. The
7
+ disclaimer-specific vars stay as escape hatches when divergence is
8
+ needed. */
9
+
10
+ .web5-disclaimer {
11
+ margin: 0;
12
+ font-size: var(
13
+ --web5-disclaimer-font-size,
14
+ var(--web5-feedback-bar-font-size, 13px)
15
+ );
16
+ font-weight: 400;
17
+ line-height: normal;
18
+ color: var(
19
+ --web5-disclaimer-color,
20
+ var(--web5-feedback-bar-color, var(--web5-feedback-label-color, #6b7280))
21
+ );
22
+ text-align: var(--web5-disclaimer-text-align, left);
23
+ }
24
+
25
+ .web5-disclaimer__link {
26
+ color: inherit;
27
+ text-decoration: underline;
28
+ text-decoration-skip-ink: none;
29
+ cursor: pointer;
30
+ }
31
+
32
+ .web5-disclaimer__link:hover,
33
+ .web5-disclaimer__link:focus-visible {
34
+ color: var(--web5-disclaimer-link-hover-color, inherit);
35
+ }