@automattic/plans-grid-next 1.0.2 → 1.0.3

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 (298) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/dist/cjs/_shared.scss +4 -3
  3. package/dist/cjs/components/comparison-grid/index.js +99 -92
  4. package/dist/cjs/components/comparison-grid/index.js.map +1 -1
  5. package/dist/cjs/components/comparison-grid/style.scss +10 -2
  6. package/dist/cjs/components/features-grid/client-logo-list/client-list.js +0 -12
  7. package/dist/cjs/components/features-grid/client-logo-list/client-list.js.map +1 -1
  8. package/dist/cjs/components/features-grid/index.js +9 -6
  9. package/dist/cjs/components/features-grid/index.js.map +1 -1
  10. package/dist/cjs/components/features-grid/plan-features-list.js +10 -3
  11. package/dist/cjs/components/features-grid/plan-features-list.js.map +1 -1
  12. package/dist/cjs/components/features-grid/plan-headers.js +2 -2
  13. package/dist/cjs/components/features-grid/plan-headers.js.map +1 -1
  14. package/dist/cjs/components/features-grid/plan-tagline.js +1 -1
  15. package/dist/cjs/components/features-grid/plan-tagline.js.map +1 -1
  16. package/dist/cjs/components/features-grid/style.scss +107 -19
  17. package/dist/cjs/components/features-grid/table.js +1 -1
  18. package/dist/cjs/components/features-grid/table.js.map +1 -1
  19. package/dist/cjs/components/features.js +43 -4
  20. package/dist/cjs/components/features.js.map +1 -1
  21. package/dist/cjs/components/item.js +1 -1
  22. package/dist/cjs/components/item.js.map +1 -1
  23. package/dist/cjs/components/plan-button/index.js +5 -3
  24. package/dist/cjs/components/plan-button/index.js.map +1 -1
  25. package/dist/cjs/components/plan-button/style.scss +75 -51
  26. package/dist/cjs/components/plan-div-td-container.js +4 -1
  27. package/dist/cjs/components/plan-div-td-container.js.map +1 -1
  28. package/dist/cjs/components/plan-logo.js +6 -3
  29. package/dist/cjs/components/plan-logo.js.map +1 -1
  30. package/dist/cjs/components/plan-type-selector/components/interval-type-dropdown.js +12 -1
  31. package/dist/cjs/components/plan-type-selector/components/interval-type-dropdown.js.map +1 -1
  32. package/dist/cjs/components/plan-type-selector/hooks/use-max-discount.js +4 -33
  33. package/dist/cjs/components/plan-type-selector/hooks/use-max-discount.js.map +1 -1
  34. package/dist/cjs/components/plan-type-selector/hooks/use-max-discounts-for-plan-terms.js +11 -13
  35. package/dist/cjs/components/plan-type-selector/hooks/use-max-discounts-for-plan-terms.js.map +1 -1
  36. package/dist/cjs/components/plans-2023-tooltip.js +16 -5
  37. package/dist/cjs/components/plans-2023-tooltip.js.map +1 -1
  38. package/dist/cjs/components/shared/action-button/index.js +22 -7
  39. package/dist/cjs/components/shared/action-button/index.js.map +1 -1
  40. package/dist/cjs/components/shared/action-button/style.scss +4 -0
  41. package/dist/cjs/components/shared/billing-timeframe/index.js +8 -4
  42. package/dist/cjs/components/shared/billing-timeframe/index.js.map +1 -1
  43. package/dist/cjs/components/shared/header-price/index.js +60 -15
  44. package/dist/cjs/components/shared/header-price/index.js.map +1 -1
  45. package/dist/cjs/components/shared/header-price/style.scss +9 -3
  46. package/dist/cjs/components/shared/storage/components/plan-storage.js +2 -2
  47. package/dist/cjs/components/shared/storage/components/plan-storage.js.map +1 -1
  48. package/dist/cjs/components/shared/storage/components/storage-dropdown.js +29 -6
  49. package/dist/cjs/components/shared/storage/components/storage-dropdown.js.map +1 -1
  50. package/dist/cjs/components/shared/storage/components/storage-feature-label.js +2 -1
  51. package/dist/cjs/components/shared/storage/components/storage-feature-label.js.map +1 -1
  52. package/dist/cjs/components/shared/storage/hooks/use-plan-storage.js +2 -0
  53. package/dist/cjs/components/shared/storage/hooks/use-plan-storage.js.map +1 -1
  54. package/dist/cjs/fixtures/sites-purchases.js +2 -4
  55. package/dist/cjs/fixtures/sites-purchases.js.map +1 -1
  56. package/dist/cjs/grid-context.js +4 -1
  57. package/dist/cjs/grid-context.js.map +1 -1
  58. package/dist/cjs/hooks/data-store/get-renewal-pricing-text.js +50 -0
  59. package/dist/cjs/hooks/data-store/get-renewal-pricing-text.js.map +1 -0
  60. package/dist/cjs/hooks/data-store/use-grid-plans-for-comparison-grid.js +6 -1
  61. package/dist/cjs/hooks/data-store/use-grid-plans-for-comparison-grid.js.map +1 -1
  62. package/dist/cjs/hooks/data-store/use-grid-plans-for-features-grid.js +6 -1
  63. package/dist/cjs/hooks/data-store/use-grid-plans-for-features-grid.js.map +1 -1
  64. package/dist/cjs/hooks/data-store/use-grid-plans.js +175 -21
  65. package/dist/cjs/hooks/data-store/use-grid-plans.js.map +1 -1
  66. package/dist/cjs/hooks/data-store/use-highlight-labels.js +13 -4
  67. package/dist/cjs/hooks/data-store/use-highlight-labels.js.map +1 -1
  68. package/dist/cjs/hooks/data-store/use-plan-billing-description.js +68 -13
  69. package/dist/cjs/hooks/data-store/use-plan-billing-description.js.map +1 -1
  70. package/dist/cjs/hooks/data-store/use-plan-features-for-grid-plans.js +76 -2
  71. package/dist/cjs/hooks/data-store/use-plan-features-for-grid-plans.js.map +1 -1
  72. package/dist/cjs/hooks/data-store/use-restructured-plan-features-for-comparison-grid.js +60 -12
  73. package/dist/cjs/hooks/data-store/use-restructured-plan-features-for-comparison-grid.js.map +1 -1
  74. package/dist/cjs/hooks/data-store/use-title-badges.js +19 -0
  75. package/dist/cjs/hooks/data-store/use-title-badges.js.map +1 -0
  76. package/dist/cjs/hooks/use-is-large-currency.js +2 -2
  77. package/dist/cjs/hooks/use-is-large-currency.js.map +1 -1
  78. package/dist/cjs/hooks/use-visible-grid-plans.js +70 -0
  79. package/dist/cjs/hooks/use-visible-grid-plans.js.map +1 -0
  80. package/dist/cjs/index.js +6 -1
  81. package/dist/cjs/index.js.map +1 -1
  82. package/dist/cjs/lib/get-plan-features-object.js +15 -2
  83. package/dist/cjs/lib/get-plan-features-object.js.map +1 -1
  84. package/dist/cjs/lib/plan-pricing-utils.js +135 -0
  85. package/dist/cjs/lib/plan-pricing-utils.js.map +1 -0
  86. package/dist/esm/_shared.scss +4 -3
  87. package/dist/esm/components/comparison-grid/index.js +100 -93
  88. package/dist/esm/components/comparison-grid/index.js.map +1 -1
  89. package/dist/esm/components/comparison-grid/style.scss +10 -2
  90. package/dist/esm/components/features-grid/client-logo-list/client-list.js +0 -12
  91. package/dist/esm/components/features-grid/client-logo-list/client-list.js.map +1 -1
  92. package/dist/esm/components/features-grid/index.js +9 -6
  93. package/dist/esm/components/features-grid/index.js.map +1 -1
  94. package/dist/esm/components/features-grid/plan-features-list.js +10 -3
  95. package/dist/esm/components/features-grid/plan-features-list.js.map +1 -1
  96. package/dist/esm/components/features-grid/plan-headers.js +3 -3
  97. package/dist/esm/components/features-grid/plan-headers.js.map +1 -1
  98. package/dist/esm/components/features-grid/plan-tagline.js +1 -1
  99. package/dist/esm/components/features-grid/plan-tagline.js.map +1 -1
  100. package/dist/esm/components/features-grid/style.scss +107 -19
  101. package/dist/esm/components/features-grid/table.js +1 -1
  102. package/dist/esm/components/features-grid/table.js.map +1 -1
  103. package/dist/esm/components/features.js +44 -5
  104. package/dist/esm/components/features.js.map +1 -1
  105. package/dist/esm/components/item.js +1 -1
  106. package/dist/esm/components/item.js.map +1 -1
  107. package/dist/esm/components/plan-button/index.js +5 -3
  108. package/dist/esm/components/plan-button/index.js.map +1 -1
  109. package/dist/esm/components/plan-button/style.scss +75 -51
  110. package/dist/esm/components/plan-div-td-container.js +4 -1
  111. package/dist/esm/components/plan-div-td-container.js.map +1 -1
  112. package/dist/esm/components/plan-logo.js +7 -4
  113. package/dist/esm/components/plan-logo.js.map +1 -1
  114. package/dist/esm/components/plan-type-selector/components/interval-type-dropdown.js +12 -1
  115. package/dist/esm/components/plan-type-selector/components/interval-type-dropdown.js.map +1 -1
  116. package/dist/esm/components/plan-type-selector/hooks/use-max-discount.js +3 -33
  117. package/dist/esm/components/plan-type-selector/hooks/use-max-discount.js.map +1 -1
  118. package/dist/esm/components/plan-type-selector/hooks/use-max-discounts-for-plan-terms.js +11 -13
  119. package/dist/esm/components/plan-type-selector/hooks/use-max-discounts-for-plan-terms.js.map +1 -1
  120. package/dist/esm/components/plans-2023-tooltip.js +16 -5
  121. package/dist/esm/components/plans-2023-tooltip.js.map +1 -1
  122. package/dist/esm/components/shared/action-button/index.js +22 -7
  123. package/dist/esm/components/shared/action-button/index.js.map +1 -1
  124. package/dist/esm/components/shared/action-button/style.scss +4 -0
  125. package/dist/esm/components/shared/billing-timeframe/index.js +8 -4
  126. package/dist/esm/components/shared/billing-timeframe/index.js.map +1 -1
  127. package/dist/esm/components/shared/header-price/index.js +60 -15
  128. package/dist/esm/components/shared/header-price/index.js.map +1 -1
  129. package/dist/esm/components/shared/header-price/style.scss +9 -3
  130. package/dist/esm/components/shared/storage/components/plan-storage.js +2 -2
  131. package/dist/esm/components/shared/storage/components/plan-storage.js.map +1 -1
  132. package/dist/esm/components/shared/storage/components/storage-dropdown.js +30 -7
  133. package/dist/esm/components/shared/storage/components/storage-dropdown.js.map +1 -1
  134. package/dist/esm/components/shared/storage/components/storage-feature-label.js +2 -1
  135. package/dist/esm/components/shared/storage/components/storage-feature-label.js.map +1 -1
  136. package/dist/esm/components/shared/storage/hooks/use-plan-storage.js +3 -1
  137. package/dist/esm/components/shared/storage/hooks/use-plan-storage.js.map +1 -1
  138. package/dist/esm/fixtures/sites-purchases.js +2 -4
  139. package/dist/esm/fixtures/sites-purchases.js.map +1 -1
  140. package/dist/esm/grid-context.js +4 -1
  141. package/dist/esm/grid-context.js.map +1 -1
  142. package/dist/esm/hooks/data-store/get-renewal-pricing-text.js +47 -0
  143. package/dist/esm/hooks/data-store/get-renewal-pricing-text.js.map +1 -0
  144. package/dist/esm/hooks/data-store/use-grid-plans-for-comparison-grid.js +6 -1
  145. package/dist/esm/hooks/data-store/use-grid-plans-for-comparison-grid.js.map +1 -1
  146. package/dist/esm/hooks/data-store/use-grid-plans-for-features-grid.js +6 -1
  147. package/dist/esm/hooks/data-store/use-grid-plans-for-features-grid.js.map +1 -1
  148. package/dist/esm/hooks/data-store/use-grid-plans.js +176 -22
  149. package/dist/esm/hooks/data-store/use-grid-plans.js.map +1 -1
  150. package/dist/esm/hooks/data-store/use-highlight-labels.js +14 -5
  151. package/dist/esm/hooks/data-store/use-highlight-labels.js.map +1 -1
  152. package/dist/esm/hooks/data-store/use-plan-billing-description.js +66 -11
  153. package/dist/esm/hooks/data-store/use-plan-billing-description.js.map +1 -1
  154. package/dist/esm/hooks/data-store/use-plan-features-for-grid-plans.js +77 -3
  155. package/dist/esm/hooks/data-store/use-plan-features-for-grid-plans.js.map +1 -1
  156. package/dist/esm/hooks/data-store/use-restructured-plan-features-for-comparison-grid.js +59 -11
  157. package/dist/esm/hooks/data-store/use-restructured-plan-features-for-comparison-grid.js.map +1 -1
  158. package/dist/esm/hooks/data-store/use-title-badges.js +17 -0
  159. package/dist/esm/hooks/data-store/use-title-badges.js.map +1 -0
  160. package/dist/esm/hooks/use-is-large-currency.js +1 -1
  161. package/dist/esm/hooks/use-is-large-currency.js.map +1 -1
  162. package/dist/esm/hooks/use-visible-grid-plans.js +66 -0
  163. package/dist/esm/hooks/use-visible-grid-plans.js.map +1 -0
  164. package/dist/esm/index.js +2 -0
  165. package/dist/esm/index.js.map +1 -1
  166. package/dist/esm/lib/get-plan-features-object.js +15 -2
  167. package/dist/esm/lib/get-plan-features-object.js.map +1 -1
  168. package/dist/esm/lib/plan-pricing-utils.js +129 -0
  169. package/dist/esm/lib/plan-pricing-utils.js.map +1 -0
  170. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  171. package/dist/tsconfig.tsbuildinfo +1 -1
  172. package/dist/types/components/comparison-grid/index.d.ts +1 -1
  173. package/dist/types/components/comparison-grid/index.d.ts.map +1 -1
  174. package/dist/types/components/features-grid/client-logo-list/client-list.d.ts.map +1 -1
  175. package/dist/types/components/features-grid/index.d.ts.map +1 -1
  176. package/dist/types/components/features-grid/plan-features-list.d.ts.map +1 -1
  177. package/dist/types/components/features-grid/plan-headers.d.ts +2 -0
  178. package/dist/types/components/features-grid/plan-headers.d.ts.map +1 -1
  179. package/dist/types/components/features-grid/table.d.ts.map +1 -1
  180. package/dist/types/components/features.d.ts.map +1 -1
  181. package/dist/types/components/item.d.ts +2 -1
  182. package/dist/types/components/item.d.ts.map +1 -1
  183. package/dist/types/components/plan-button/index.d.ts +2 -1
  184. package/dist/types/components/plan-button/index.d.ts.map +1 -1
  185. package/dist/types/components/plan-div-td-container.d.ts +2 -0
  186. package/dist/types/components/plan-div-td-container.d.ts.map +1 -1
  187. package/dist/types/components/plan-logo.d.ts.map +1 -1
  188. package/dist/types/components/plan-type-selector/components/interval-type-dropdown.d.ts.map +1 -1
  189. package/dist/types/components/plan-type-selector/hooks/use-max-discount.d.ts.map +1 -1
  190. package/dist/types/components/plan-type-selector/hooks/use-max-discounts-for-plan-terms.d.ts.map +1 -1
  191. package/dist/types/components/plans-2023-tooltip.d.ts.map +1 -1
  192. package/dist/types/components/shared/action-button/index.d.ts +2 -1
  193. package/dist/types/components/shared/action-button/index.d.ts.map +1 -1
  194. package/dist/types/components/shared/billing-timeframe/index.d.ts.map +1 -1
  195. package/dist/types/components/shared/header-price/index.d.ts.map +1 -1
  196. package/dist/types/components/shared/storage/components/storage-dropdown.d.ts.map +1 -1
  197. package/dist/types/components/shared/storage/components/storage-feature-label.d.ts.map +1 -1
  198. package/dist/types/components/shared/storage/hooks/use-plan-storage.d.ts +1 -1
  199. package/dist/types/components/shared/storage/hooks/use-plan-storage.d.ts.map +1 -1
  200. package/dist/types/fixtures/sites-purchases.d.ts +2 -4
  201. package/dist/types/fixtures/sites-purchases.d.ts.map +1 -1
  202. package/dist/types/grid-context.d.ts +4 -1
  203. package/dist/types/grid-context.d.ts.map +1 -1
  204. package/dist/types/hooks/data-store/get-renewal-pricing-text.d.ts +14 -0
  205. package/dist/types/hooks/data-store/get-renewal-pricing-text.d.ts.map +1 -0
  206. package/dist/types/hooks/data-store/types.d.ts +21 -0
  207. package/dist/types/hooks/data-store/types.d.ts.map +1 -1
  208. package/dist/types/hooks/data-store/use-grid-plans-for-comparison-grid.d.ts +1 -1
  209. package/dist/types/hooks/data-store/use-grid-plans-for-comparison-grid.d.ts.map +1 -1
  210. package/dist/types/hooks/data-store/use-grid-plans-for-features-grid.d.ts +1 -1
  211. package/dist/types/hooks/data-store/use-grid-plans-for-features-grid.d.ts.map +1 -1
  212. package/dist/types/hooks/data-store/use-grid-plans.d.ts.map +1 -1
  213. package/dist/types/hooks/data-store/use-highlight-labels.d.ts.map +1 -1
  214. package/dist/types/hooks/data-store/use-plan-billing-description.d.ts.map +1 -1
  215. package/dist/types/hooks/data-store/use-plan-features-for-grid-plans.d.ts +4 -1
  216. package/dist/types/hooks/data-store/use-plan-features-for-grid-plans.d.ts.map +1 -1
  217. package/dist/types/hooks/data-store/use-restructured-plan-features-for-comparison-grid.d.ts +4 -1
  218. package/dist/types/hooks/data-store/use-restructured-plan-features-for-comparison-grid.d.ts.map +1 -1
  219. package/dist/types/hooks/data-store/use-title-badges.d.ts +9 -0
  220. package/dist/types/hooks/data-store/use-title-badges.d.ts.map +1 -0
  221. package/dist/types/hooks/use-visible-grid-plans.d.ts +14 -0
  222. package/dist/types/hooks/use-visible-grid-plans.d.ts.map +1 -0
  223. package/dist/types/index.d.ts +7 -0
  224. package/dist/types/index.d.ts.map +1 -1
  225. package/dist/types/lib/get-plan-features-object.d.ts +1 -1
  226. package/dist/types/lib/get-plan-features-object.d.ts.map +1 -1
  227. package/dist/types/lib/plan-pricing-utils.d.ts +105 -0
  228. package/dist/types/lib/plan-pricing-utils.d.ts.map +1 -0
  229. package/dist/types/types.d.ts +29 -2
  230. package/dist/types/types.d.ts.map +1 -1
  231. package/package.json +38 -28
  232. package/src/_shared.scss +4 -3
  233. package/src/components/comparison-grid/index.tsx +258 -181
  234. package/src/components/comparison-grid/style.scss +10 -2
  235. package/src/components/features-grid/client-logo-list/client-list.tsx +0 -25
  236. package/src/components/features-grid/index.tsx +35 -18
  237. package/src/components/features-grid/plan-features-list.tsx +15 -4
  238. package/src/components/features-grid/plan-headers.tsx +10 -3
  239. package/src/components/features-grid/plan-tagline.tsx +1 -1
  240. package/src/components/features-grid/style.scss +107 -19
  241. package/src/components/features-grid/table.tsx +4 -2
  242. package/src/components/features.tsx +66 -6
  243. package/src/components/item.tsx +6 -3
  244. package/src/components/plan-button/index.tsx +7 -1
  245. package/src/components/plan-button/style.scss +75 -51
  246. package/src/components/plan-div-td-container.tsx +6 -2
  247. package/src/components/plan-logo.tsx +16 -9
  248. package/src/components/plan-type-selector/components/interval-type-dropdown.tsx +14 -1
  249. package/src/components/plan-type-selector/hooks/use-max-discount.ts +8 -47
  250. package/src/components/plan-type-selector/hooks/use-max-discounts-for-plan-terms.ts +19 -17
  251. package/src/components/plans-2023-tooltip.tsx +17 -5
  252. package/src/components/shared/action-button/index.tsx +46 -5
  253. package/src/components/shared/action-button/style.scss +4 -0
  254. package/src/components/shared/billing-timeframe/index.tsx +12 -7
  255. package/src/components/shared/header-price/index.tsx +129 -27
  256. package/src/components/shared/header-price/style.scss +9 -3
  257. package/src/components/shared/storage/components/plan-storage.tsx +2 -2
  258. package/src/components/shared/storage/components/storage-dropdown.tsx +36 -15
  259. package/src/components/shared/storage/components/storage-feature-label.tsx +2 -1
  260. package/src/components/shared/storage/hooks/use-plan-storage.ts +3 -0
  261. package/src/components/test/actions-button.tsx +5 -0
  262. package/src/components/test/billing-timeframe.tsx +1 -1
  263. package/src/components/test/header-price.tsx +342 -4
  264. package/src/fixtures/sites-purchases.ts +2 -4
  265. package/src/grid-context.tsx +9 -0
  266. package/src/hooks/data-store/get-renewal-pricing-text.ts +73 -0
  267. package/src/hooks/data-store/types.ts +21 -0
  268. package/src/hooks/data-store/use-grid-plans-for-comparison-grid.ts +10 -0
  269. package/src/hooks/data-store/use-grid-plans-for-features-grid.ts +10 -0
  270. package/src/hooks/data-store/use-grid-plans.tsx +189 -23
  271. package/src/hooks/data-store/use-highlight-labels.ts +12 -3
  272. package/src/hooks/data-store/use-plan-billing-description.tsx +80 -15
  273. package/src/hooks/data-store/use-plan-features-for-grid-plans.ts +135 -1
  274. package/src/hooks/data-store/use-restructured-plan-features-for-comparison-grid.ts +93 -20
  275. package/src/hooks/data-store/use-title-badges.ts +31 -0
  276. package/src/hooks/test/use-visible-grid-plans.tsx +116 -0
  277. package/src/hooks/use-is-large-currency.ts +1 -1
  278. package/src/hooks/use-visible-grid-plans.tsx +102 -0
  279. package/src/index.tsx +18 -0
  280. package/src/lib/get-plan-features-object.ts +23 -2
  281. package/src/lib/plan-pricing-utils.ts +211 -0
  282. package/src/lib/test/plan-pricing-utils.ts +594 -0
  283. package/src/style-imports.d.ts +3 -0
  284. package/src/types.ts +41 -0
  285. package/dist/cjs/components/features-grid/mobile-free-domain.js +0 -25
  286. package/dist/cjs/components/features-grid/mobile-free-domain.js.map +0 -1
  287. package/dist/cjs/lib/get-plan-pricing-info-from-grid-plans.js +0 -15
  288. package/dist/cjs/lib/get-plan-pricing-info-from-grid-plans.js.map +0 -1
  289. package/dist/esm/components/features-grid/mobile-free-domain.js +0 -23
  290. package/dist/esm/components/features-grid/mobile-free-domain.js.map +0 -1
  291. package/dist/esm/lib/get-plan-pricing-info-from-grid-plans.js +0 -12
  292. package/dist/esm/lib/get-plan-pricing-info-from-grid-plans.js.map +0 -1
  293. package/dist/types/components/features-grid/mobile-free-domain.d.ts +0 -8
  294. package/dist/types/components/features-grid/mobile-free-domain.d.ts.map +0 -1
  295. package/dist/types/lib/get-plan-pricing-info-from-grid-plans.d.ts +0 -9
  296. package/dist/types/lib/get-plan-pricing-info-from-grid-plans.d.ts.map +0 -1
  297. package/src/components/features-grid/mobile-free-domain.tsx +0 -51
  298. package/src/lib/get-plan-pricing-info-from-grid-plans.ts +0 -31
@@ -1,11 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  // TODO: Temporary until feature definitions are ported to calypso-products package
4
- const getPlanFeaturesObject = (featuresList, planFeatures) => {
4
+ const getPlanFeaturesObject = (featuresList, planFeatures, isExperimentVariant) => {
5
5
  if (!planFeatures) {
6
6
  return [];
7
7
  }
8
- return planFeatures.map((featuresConst) => featuresList[featuresConst]);
8
+ return planFeatures.map((featuresConst) => {
9
+ const feature = featuresList[featuresConst];
10
+ if (!feature || !isExperimentVariant) {
11
+ return feature;
12
+ }
13
+ // Wrap feature methods to pass isExperimentVariant parameter
14
+ return {
15
+ ...feature,
16
+ getTitle: (params) => feature.getTitle({ ...params, isExperimentVariant }),
17
+ ...(feature.getDescription && {
18
+ getDescription: (params) => feature.getDescription({ ...params, isExperimentVariant }),
19
+ }),
20
+ };
21
+ });
9
22
  };
10
23
  exports.default = getPlanFeaturesObject;
11
24
  //# sourceMappingURL=get-plan-features-object.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-plan-features-object.js","sourceRoot":"","sources":["../../../src/lib/get-plan-features-object.ts"],"names":[],"mappings":";;AAEA,mFAAmF;AACnF,MAAM,qBAAqB,GAAG,CAAE,YAAyB,EAAE,YAA8B,EAAG,EAAE;IAC7F,IAAK,CAAE,YAAY,EAAG,CAAC;QACtB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,OAAO,YAAY,CAAC,GAAG,CAAE,CAAE,aAAa,EAAG,EAAE,CAAC,YAAY,CAAE,aAAa,CAAE,CAAE,CAAC;AAC/E,CAAC,CAAC;AAEF,kBAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"get-plan-features-object.js","sourceRoot":"","sources":["../../../src/lib/get-plan-features-object.ts"],"names":[],"mappings":";;AAIA,mFAAmF;AACnF,MAAM,qBAAqB,GAAG,CAC7B,YAAyB,EACzB,YAA8B,EAC9B,mBAA6B,EAC5B,EAAE;IACH,IAAK,CAAE,YAAY,EAAG,CAAC;QACtB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,OAAO,YAAY,CAAC,GAAG,CAAE,CAAE,aAAa,EAAG,EAAE;QAC5C,MAAM,OAAO,GAAG,YAAY,CAAE,aAAa,CAAE,CAAC;QAC9C,IAAK,CAAE,OAAO,IAAI,CAAE,mBAAmB,EAAG,CAAC;YAC1C,OAAO,OAAO,CAAC;QAChB,CAAC;QACD,6DAA6D;QAC7D,OAAO;YACN,GAAG,OAAO;YACV,QAAQ,EAAE,CAAE,MAA4B,EAAG,EAAE,CAC5C,OAAO,CAAC,QAAQ,CAAE,EAAE,GAAG,MAAM,EAAE,mBAAmB,EAAE,CAAE;YACvD,GAAG,CAAE,OAAO,CAAC,cAAc,IAAI;gBAC9B,cAAc,EAAE,CAAE,MAA4B,EAAG,EAAE,CAClD,OAAO,CAAC,cAAe,CAAE,EAAE,GAAG,MAAM,EAAE,mBAAmB,EAAE,CAAE;aAC9D,CAAE;SACH,CAAC;IACH,CAAC,CAAE,CAAC;AACL,CAAC,CAAC;AAEF,kBAAe,qBAAqB,CAAC"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPlanPriceForDuration = getPlanPriceForDuration;
4
+ exports.calculateDiscountPercentage = calculateDiscountPercentage;
5
+ exports.fromPricingMetaForGridPlan = fromPricingMetaForGridPlan;
6
+ exports.fromVariantPriceData = fromVariantPriceData;
7
+ // billingPeriod values are in days (from PERIOD_LIST in calypso-products)
8
+ const BILLING_PERIOD_DAYS_TO_MONTHS = {
9
+ 31: 1,
10
+ 365: 12,
11
+ 730: 24,
12
+ 1095: 36,
13
+ };
14
+ function billingPeriodDaysToMonths(billingPeriod) {
15
+ if (billingPeriod === undefined || billingPeriod === null) {
16
+ return null;
17
+ }
18
+ return BILLING_PERIOD_DAYS_TO_MONTHS[billingPeriod] ?? null;
19
+ }
20
+ /**
21
+ * Calculates the total cost of a plan over `durationMonths` months.
22
+ *
23
+ * Handles partial billing periods via pro-ration (e.g. a yearly plan priced at
24
+ * $200/year costs $100 for 6 months).
25
+ *
26
+ * When `useIntroOffer` is true (default) and an active intro offer exists, the
27
+ * intro price is applied for the first `introOffer.durationMonths` months, and
28
+ * the regular (or discounted) price for the remainder.
29
+ *
30
+ * @example
31
+ * // Monthly plan: $10 intro for 1 month, then $20/month; cost for 6 months:
32
+ * // 1×$10 + 5×$20 = $110 (in cents: 1100 + 10000 = 11000)
33
+ * getPlanPriceForDuration( info, 6, { useIntroOffer: true } ) // 11000
34
+ *
35
+ * @example
36
+ * // Yearly plan: $100/yr intro, $200/yr regular; cost for 6 months:
37
+ * // useIntroOffer=true → 6×($100/12) = $50 (5000 cents)
38
+ * // useIntroOffer=false → 6×($200/12) = $100 (10000 cents)
39
+ */
40
+ function getPlanPriceForDuration(info, durationMonths, { useIntroOffer = true } = {}) {
41
+ const basePricePerMonth = info.discountedPricePerMonth ?? info.regularPricePerMonth;
42
+ if (useIntroOffer && info.introOffer?.isActive) {
43
+ const introMonths = Math.min(durationMonths, info.introOffer.durationMonths);
44
+ const regularMonths = Math.max(0, durationMonths - info.introOffer.durationMonths);
45
+ return introMonths * info.introOffer.pricePerMonth + regularMonths * basePricePerMonth;
46
+ }
47
+ return durationMonths * basePricePerMonth;
48
+ }
49
+ /**
50
+ * Calculates the percentage discount between a reference price and a cheaper price.
51
+ *
52
+ * Always uses Math.floor — conservative, never overstates savings.
53
+ *
54
+ * Returns `undefined` (not 0) when there is no saving, allowing callers to
55
+ * distinguish "no discount" from a computed "0% discount".
56
+ */
57
+ function calculateDiscountPercentage(referencePrice, cheaperPrice) {
58
+ if (cheaperPrice >= referencePrice || referencePrice <= 0) {
59
+ return undefined;
60
+ }
61
+ return Math.floor((100 * (referencePrice - cheaperPrice)) / referencePrice);
62
+ }
63
+ /**
64
+ * Converts a `PricingMetaForGridPlan` (from @automattic/data-stores Plans hooks)
65
+ * into a `PlanPriceInfo` suitable for use with `getPlanPriceForDuration` and
66
+ * `calculateDiscountPercentage`.
67
+ *
68
+ * Returns null when required pricing data is absent (e.g. free/enterprise plans
69
+ * that have no monthly price, or plans whose billing period is unknown).
70
+ */
71
+ function fromPricingMetaForGridPlan(meta) {
72
+ const termMonths = billingPeriodDaysToMonths(meta.billingPeriod);
73
+ if (termMonths === null || meta.originalPrice.monthly === null) {
74
+ return null;
75
+ }
76
+ const isIntroActive = !!meta.introOffer && !meta.introOffer.isOfferComplete;
77
+ return {
78
+ termMonths,
79
+ regularPricePerMonth: meta.originalPrice.monthly,
80
+ // The API sometimes sets discountedPrice.monthly to the intro offer price rather than
81
+ // a genuine site-level discount (e.g. currency conversion, proration credit). When an
82
+ // intro offer is active the intro structure already captures the discounted period, so
83
+ // using discountedPrice here would contaminate the post-intro "regular" rate used by
84
+ // getPlanPriceForDuration — producing incorrect totals for the non-intro months.
85
+ discountedPricePerMonth: isIntroActive ? undefined : meta.discountedPrice.monthly ?? undefined,
86
+ introOffer: meta.introOffer
87
+ ? {
88
+ pricePerMonth: meta.introOffer.rawPrice.monthly,
89
+ durationMonths: meta.introOffer.intervalCount * (meta.introOffer.intervalUnit === 'year' ? 12 : 1),
90
+ isActive: isIntroActive,
91
+ }
92
+ : undefined,
93
+ };
94
+ }
95
+ /**
96
+ * Converts a variant price data object (structurally compatible with
97
+ * `WPCOMProductVariant`) into a `PlanPriceInfo`.
98
+ *
99
+ * `discountedPricePerMonth` is intentionally not set: `WPCOMProductVariant`
100
+ * does not separate site-level discounts from the intro price. Coupon discounts
101
+ * in checkout are tracked separately via `product.coupon_savings_integer`.
102
+ *
103
+ * Per-month values are derived by dividing full-term prices (integers in the
104
+ * smallest currency unit) by the number of months. The result is rounded to the
105
+ * nearest integer (Math.round) so that all fields in the returned `PlanPriceInfo`
106
+ * remain whole-cent values safe for use with currency formatters. The rounding
107
+ * error is at most 0.5¢ per month and is negligible for percentage comparisons.
108
+ */
109
+ function fromVariantPriceData(variant) {
110
+ const { termIntervalInMonths: termMonths, priceBeforeDiscounts, priceInteger, introductoryInterval, introductoryTerm, } = variant;
111
+ const regularPricePerMonth = Math.round(priceBeforeDiscounts / termMonths);
112
+ const introDurationMonths = introductoryInterval > 0 ? introductoryInterval * (introductoryTerm === 'year' ? 12 : 1) : 0;
113
+ let introOffer;
114
+ if (introDurationMonths > 0 && priceInteger < priceBeforeDiscounts) {
115
+ // When the intro spans the full term (introDurationMonths >= termMonths), all of
116
+ // priceInteger is at the intro rate and there are zero non-intro months.
117
+ // When the intro is shorter than the term (introDurationMonths < termMonths), we
118
+ // subtract the non-intro portion (billed at the regular rate) to isolate the intro cost.
119
+ const nonIntroMonths = Math.max(0, termMonths - introDurationMonths);
120
+ const introPriceTotal = priceInteger - nonIntroMonths * regularPricePerMonth;
121
+ // A non-positive introPriceTotal means inconsistent data (e.g. a sub-term intro
122
+ // with a priceInteger that is less than the non-intro months at the regular rate).
123
+ if (introPriceTotal > 0) {
124
+ // When introDurationMonths > termMonths the whole billing term is within the
125
+ // intro period, so we spread introPriceTotal over termMonths (not introDurationMonths).
126
+ introOffer = {
127
+ pricePerMonth: Math.round(introPriceTotal / Math.min(introDurationMonths, termMonths)),
128
+ durationMonths: introDurationMonths,
129
+ isActive: true,
130
+ };
131
+ }
132
+ }
133
+ return { termMonths, regularPricePerMonth, introOffer };
134
+ }
135
+ //# sourceMappingURL=plan-pricing-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-pricing-utils.js","sourceRoot":"","sources":["../../../src/lib/plan-pricing-utils.ts"],"names":[],"mappings":";;AA6DA,0DAcC;AAUD,kEAQC;AAUD,gEA4BC;AAyCD,oDAsCC;AAxLD,0EAA0E;AAC1E,MAAM,6BAA6B,GAA6B;IAC/D,EAAE,EAAE,CAAC;IACL,GAAG,EAAE,EAAE;IACP,GAAG,EAAE,EAAE;IACP,IAAI,EAAE,EAAE;CACR,CAAC;AAEF,SAAS,yBAAyB,CAAE,aAAiC;IACpE,IAAK,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,IAAI,EAAG,CAAC;QAC7D,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,6BAA6B,CAAE,aAAa,CAAE,IAAI,IAAI,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,uBAAuB,CACtC,IAAmB,EACnB,cAAsB,EACtB,EAAE,aAAa,GAAG,IAAI,KAAkC,EAAE;IAE1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,uBAAuB,IAAI,IAAI,CAAC,oBAAoB,CAAC;IAEpF,IAAK,aAAa,IAAI,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAG,CAAC;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAE,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,cAAc,CAAE,CAAC;QAC/E,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAE,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAE,CAAC;QACrF,OAAO,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,GAAG,aAAa,GAAG,iBAAiB,CAAC;IACxF,CAAC;IAED,OAAO,cAAc,GAAG,iBAAiB,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,2BAA2B,CAC1C,cAAsB,EACtB,YAAoB;IAEpB,IAAK,YAAY,IAAI,cAAc,IAAI,cAAc,IAAI,CAAC,EAAG,CAAC;QAC7D,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAE,CAAE,GAAG,GAAG,CAAE,cAAc,GAAG,YAAY,CAAE,CAAE,GAAG,cAAc,CAAE,CAAC;AACnF,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,0BAA0B,CACzC,IAAkC;IAElC,MAAM,UAAU,GAAG,yBAAyB,CAAE,IAAI,CAAC,aAAa,CAAE,CAAC;IACnE,IAAK,UAAU,KAAK,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,KAAK,IAAI,EAAG,CAAC;QAClE,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,CAAE,IAAI,CAAC,UAAU,IAAI,CAAE,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;IAE9E,OAAO;QACN,UAAU;QACV,oBAAoB,EAAE,IAAI,CAAC,aAAa,CAAC,OAAO;QAChD,sFAAsF;QACtF,sFAAsF;QACtF,uFAAuF;QACvF,qFAAqF;QACrF,iFAAiF;QACjF,uBAAuB,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,IAAI,SAAS;QAC9F,UAAU,EAAE,IAAI,CAAC,UAAU;YAC1B,CAAC,CAAC;gBACA,aAAa,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO;gBAC/C,cAAc,EACb,IAAI,CAAC,UAAU,CAAC,aAAa,GAAG,CAAE,IAAI,CAAC,UAAU,CAAC,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE;gBACrF,QAAQ,EAAE,aAAa;aACtB;YACH,CAAC,CAAC,SAAS;KACZ,CAAC;AACH,CAAC;AA2BD;;;;;;;;;;;;;GAaG;AACH,SAAgB,oBAAoB,CAAE,OAAyB;IAC9D,MAAM,EACL,oBAAoB,EAAE,UAAU,EAChC,oBAAoB,EACpB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,GAChB,GAAG,OAAO,CAAC;IAEZ,MAAM,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAE,oBAAoB,GAAG,UAAU,CAAE,CAAC;IAE7E,MAAM,mBAAmB,GACxB,oBAAoB,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB,GAAG,CAAE,gBAAgB,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhG,IAAI,UAAqD,CAAC;IAE1D,IAAK,mBAAmB,GAAG,CAAC,IAAI,YAAY,GAAG,oBAAoB,EAAG,CAAC;QACtE,iFAAiF;QACjF,yEAAyE;QACzE,iFAAiF;QACjF,yFAAyF;QACzF,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAE,CAAC,EAAE,UAAU,GAAG,mBAAmB,CAAE,CAAC;QACvE,MAAM,eAAe,GAAG,YAAY,GAAG,cAAc,GAAG,oBAAoB,CAAC;QAE7E,gFAAgF;QAChF,mFAAmF;QACnF,IAAK,eAAe,GAAG,CAAC,EAAG,CAAC;YAC3B,6EAA6E;YAC7E,wFAAwF;YACxF,UAAU,GAAG;gBACZ,aAAa,EAAE,IAAI,CAAC,KAAK,CAAE,eAAe,GAAG,IAAI,CAAC,GAAG,CAAE,mBAAmB,EAAE,UAAU,CAAE,CAAE;gBAC1F,cAAc,EAAE,mBAAmB;gBACnC,QAAQ,EAAE,IAAI;aACd,CAAC;QACH,CAAC;IACF,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,UAAU,EAAE,CAAC;AACzD,CAAC"}
@@ -47,10 +47,11 @@ $mobile-card-max-width: 440px;
47
47
  }
48
48
 
49
49
  .plans-grid-next-storage-dropdown__option {
50
- display: inline-block;
50
+ display: flex;
51
+ align-items: center;
52
+ flex-wrap: wrap;
51
53
  line-height: 20px;
52
54
  min-height: 30px;
53
- padding-top: 5px;
54
55
  font-size: 0.75rem;
55
56
  text-align: start;
56
57
  }
@@ -130,7 +131,7 @@ $storage-feature-label-y-padding: 4px;
130
131
  font-size: 0.75rem;
131
132
 
132
133
  /**************
133
- * 1. General *
134
+ * 1. General *
134
135
  **************/
135
136
 
136
137
  .components-custom-select-control__label {
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { getPlanClass, FEATURE_GROUP_ESSENTIAL_FEATURES, FEATURE_GROUP_PAYMENT_TRANSACTION_FEES, getPlans, } from '@automattic/calypso-products';
2
+ import { getPlanClass, FEATURE_GROUP_ESSENTIAL_FEATURES, FEATURE_GROUP_PAYMENT_TRANSACTION_FEES, getPlans, FEATURE_AI_WRITER_DESIGNER, FEATURE_AI_WRITER_DESIGNER_LIMITED, FEATURE_REALTIME_BACKUPS_JP, } from '@automattic/calypso-products';
3
3
  import { Gridicon, JetpackLogo } from '@automattic/components';
4
- import { Plans } from '@automattic/data-stores';
5
4
  import { css } from '@emotion/react';
6
5
  import styled from '@emotion/styled';
7
6
  import { useRef, useMemo } from '@wordpress/element';
@@ -12,10 +11,10 @@ import { useState, useCallback, useEffect, forwardRef, } from 'react';
12
11
  import { useInView } from 'react-intersection-observer';
13
12
  import { plansGridMediumLarge } from '../../css-mixins';
14
13
  import PlansGridContextProvider, { usePlansGridContext } from '../../grid-context';
15
- import usePlanBillingPeriod from '../../hooks/data-store/use-plan-billing-period';
16
14
  import useGridSize from '../../hooks/use-grid-size';
17
15
  import useHighlightAdjacencyMatrix from '../../hooks/use-highlight-adjacency-matrix';
18
16
  import { useManageTooltipToggle } from '../../hooks/use-manage-tooltip-toggle';
17
+ import { useVisibleGridPlans } from '../../hooks/use-visible-grid-plans';
19
18
  import filterUnusedFeaturesObject from '../../lib/filter-unused-features-object';
20
19
  import getPlanFeaturesObject from '../../lib/get-plan-features-object';
21
20
  import PlanTypeSelector from '../plan-type-selector';
@@ -28,14 +27,29 @@ import HeaderPriceContextProvider from '../shared/header-price/header-price-cont
28
27
  import { PlanStorage } from '../shared/storage';
29
28
  import { StickyContainer } from '../sticky-container';
30
29
  import './style.scss';
30
+ // Plans Differentiators Experiment: treat feature variants (e.g., _LIMITED) as the same row
31
+ const FEATURE_ALIASES = {
32
+ [FEATURE_AI_WRITER_DESIGNER]: [FEATURE_AI_WRITER_DESIGNER_LIMITED],
33
+ };
34
+ // Finds a matching feature, checking both the base slug and any aliases
35
+ const findFeatureWithAlias = (featureSlug, planFeatures) => {
36
+ if (!featureSlug) {
37
+ return undefined;
38
+ }
39
+ const slugsToCheck = [featureSlug, ...(FEATURE_ALIASES[featureSlug] ?? [])];
40
+ return planFeatures.find((f) => slugsToCheck.includes(f.getSlug()));
41
+ };
31
42
  const featureGroupRowTitleCellMaxWidth = 450;
32
43
  const rowCellMaxWidth = 290;
33
44
  const JetpackIconContainer = styled.div `
34
- padding-inline-start: 6px;
45
+ padding-inline-start: 3px;
35
46
  display: inline-block;
36
47
  vertical-align: middle;
37
48
  line-height: 1;
38
49
  `;
50
+ const TitlePreventOrphans = styled.span `
51
+ white-space: nowrap;
52
+ `;
39
53
  const Title = styled.div `
40
54
  font-weight: 500;
41
55
  font-size: 20px;
@@ -64,11 +78,10 @@ const Title = styled.div `
64
78
  }
65
79
  `)}
66
80
  `;
67
- const Grid = styled.div `
81
+ const StickyGrid = styled(StickyContainer) `
68
82
  display: grid;
69
83
  margin: 0 auto;
70
84
  background: #fff;
71
- border: solid 1px #e0e0e0;
72
85
  ${(props) => props.visiblePlans &&
73
86
  css `
74
87
  max-width: ${rowCellMaxWidth * props.visiblePlans + featureGroupRowTitleCellMaxWidth}px;
@@ -77,11 +90,19 @@ const Grid = styled.div `
77
90
  ${plansGridMediumLarge(css `
78
91
  border-radius: 5px;
79
92
  `)}
93
+ `;
94
+ const Grid = styled.div `
95
+ display: ${(props) => (props.as === 'tbody' ? 'table-row-group' : 'grid')};
96
+ margin: 0 auto;
97
+ background: #fff;
98
+ ${(props) => props.visiblePlans &&
99
+ css `
100
+ max-width: ${rowCellMaxWidth * props.visiblePlans + featureGroupRowTitleCellMaxWidth}px;
101
+ `}
80
102
 
81
- > .is-sticky-header-row {
82
- border-bottom: solid 1px #e0e0e0;
83
- background: #fff;
84
- }
103
+ ${plansGridMediumLarge(css `
104
+ border-radius: 5px;
105
+ `)}
85
106
  `;
86
107
  const Row = styled.div `
87
108
  justify-content: space-between;
@@ -176,7 +197,7 @@ const Cell = styled.div `
176
197
  border-right: none;
177
198
  justify-content: center;
178
199
 
179
- &:first-of-type {
200
+ &:first-of-type:not( .popular-plan-parent-class ) {
180
201
  padding-inline-start: 0;
181
202
  }
182
203
  &:last-of-type {
@@ -189,7 +210,23 @@ const Cell = styled.div `
189
210
  }
190
211
  `)}
191
212
  `;
192
- const RowTitleCell = styled.div `
213
+ const RowTitleCell = styled.td `
214
+ display: none;
215
+ font-size: 14px;
216
+ padding-right: 10px;
217
+ ${plansGridMediumLarge(css `
218
+ display: block;
219
+ flex: 1;
220
+ min-width: 290px;
221
+ `)}
222
+ max-width: ${(props) => {
223
+ if (props.isPlaceholderHeaderCell || props.isFeatureGroupRowTitleCell) {
224
+ return `${featureGroupRowTitleCellMaxWidth}px`;
225
+ }
226
+ return `${rowCellMaxWidth}px`;
227
+ }};
228
+ `;
229
+ const RowHeaderCell = styled.th `
193
230
  display: none;
194
231
  font-size: 14px;
195
232
  padding-right: 10px;
@@ -272,7 +309,7 @@ const FeatureFootnote = styled.span `
272
309
  }
273
310
  `;
274
311
  const ComparisonGridHeaderCell = ({ planSlug, allVisible, isLastInRow, isFooter, isInSignup, visibleGridPlans, onPlanChange, displayedGridPlans, currentSitePlanSlug, planActionOverrides, showRefundPeriod, isStuck, }) => {
275
- const { gridPlansIndex } = usePlansGridContext();
312
+ const { gridPlansIndex, showBillingDescriptionForIncreasedRenewalPrice } = usePlansGridContext();
276
313
  const gridPlan = gridPlansIndex[planSlug];
277
314
  const highlightAdjacencyMatrix = useHighlightAdjacencyMatrix({
278
315
  renderedGridPlans: visibleGridPlans,
@@ -295,13 +332,13 @@ const ComparisonGridHeaderCell = ({ planSlug, allVisible, isLastInRow, isFooter,
295
332
  'popular-badge-is-stuck': isStuck,
296
333
  });
297
334
  const showPlanSelect = !allVisible && !gridPlan.current;
298
- return (_jsxs(Cell, { className: headerClasses, textAlign: "start", children: [_jsx(PopularBadge, { isInSignup: isInSignup, planSlug: planSlug, additionalClassName: popularBadgeClasses }), _jsxs(PlanSelector, { children: [_jsxs("h4", { className: clsx('plan-comparison-grid__title', showPlanSelect && 'is-select-trigger'), children: [_jsx("span", { className: "plan-comparison-grid__title-label", children: gridPlan.planTitle }), showPlanSelect && (_jsx("span", { className: "plan-comparison-grid__title-icon", children: _jsx(Icon, { icon: chevronRightSmall, size: 30 }) }))] }), showPlanSelect && (_jsx("select", { onChange: (event) => onPlanChange(planSlug, event), className: "plan-comparison-grid__title-select", value: planSlug, children: displayedGridPlans.map(({ planSlug: otherPlan, planTitle }) => {
335
+ return (_jsxs(Cell, { as: "th", className: headerClasses, textAlign: "start", scope: 'col', "aria-label": gridPlan.planTitle, children: [_jsx(PopularBadge, { isInSignup: isInSignup, planSlug: planSlug, additionalClassName: popularBadgeClasses }), _jsxs(PlanSelector, { children: [_jsxs("h4", { className: clsx('plan-comparison-grid__title', showPlanSelect && 'is-select-trigger'), children: [_jsx("span", { className: "plan-comparison-grid__title-label", children: gridPlan.planTitle }), showPlanSelect && (_jsx("span", { className: "plan-comparison-grid__title-icon", children: _jsx(Icon, { icon: chevronRightSmall, size: 30 }) }))] }), showPlanSelect && (_jsx("select", { onChange: (event) => onPlanChange(planSlug, event), className: "plan-comparison-grid__title-select", value: planSlug, children: displayedGridPlans.map(({ planSlug: otherPlan, planTitle }) => {
299
336
  const isVisiblePlan = visibleGridPlans.find(({ planSlug }) => planSlug === otherPlan);
300
337
  if (isVisiblePlan && otherPlan !== planSlug) {
301
338
  return null;
302
339
  }
303
340
  return (_jsx("option", { value: otherPlan, children: planTitle }, otherPlan));
304
- }) }))] }), _jsx(HeaderPrice, { planSlug: planSlug, currentSitePlanSlug: currentSitePlanSlug, visibleGridPlans: visibleGridPlans }), _jsx("div", { className: "plan-comparison-grid__billing-info", children: _jsx(BillingTimeframe, { planSlug: planSlug, showRefundPeriod: showRefundPeriod }) }), _jsx(ActionButton, { currentSitePlanSlug: currentSitePlanSlug, availableForPurchase: gridPlan.availableForPurchase, isInSignup: isInSignup, planSlug: planSlug, planActionOverrides: planActionOverrides, showMonthlyPrice: false, isStuck: false, visibleGridPlans: visibleGridPlans })] }));
341
+ }) }))] }), _jsx(HeaderPrice, { planSlug: planSlug, currentSitePlanSlug: currentSitePlanSlug, visibleGridPlans: visibleGridPlans }), _jsx("div", { className: "plan-comparison-grid__billing-info", children: _jsx(BillingTimeframe, { planSlug: planSlug, showRefundPeriod: showRefundPeriod }) }), _jsx(ActionButton, { currentSitePlanSlug: currentSitePlanSlug, availableForPurchase: gridPlan.availableForPurchase, isInSignup: isInSignup, planSlug: planSlug, planActionOverrides: planActionOverrides, showMonthlyPrice: false, isStuck: false, visibleGridPlans: visibleGridPlans, showPostButtonText: showBillingDescriptionForIncreasedRenewalPrice ? false : true })] }));
305
342
  };
306
343
  const PlanTypeSelectorWrapper = styled.div `
307
344
  display: none;
@@ -313,8 +350,9 @@ const ComparisonGridHeader = forwardRef(({ displayedGridPlans, visibleGridPlans,
313
350
  const translate = useTranslate();
314
351
  const allVisible = visibleGridPlans.length === displayedGridPlans.length;
315
352
  const { coupon } = usePlansGridContext();
316
- return (_jsxs(PlanRow, { isHiddenInMobile: isHiddenInMobile, ref: ref, children: [_jsx(RowTitleCell, { className: "plan-comparison-grid__header-cell is-placeholder-header-cell", isPlaceholderHeaderCell: true, children: isStuck && planTypeSelectorProps && (_jsx(PlanTypeSelectorWrapper, { children: _jsx(PlanTypeSelector, { ...planTypeSelectorProps, title: translate('Billing Cycle'), hideDiscount: true, coupon: coupon }) })) }, "feature-name"), _jsx(HeaderPriceContextProvider, { children: visibleGridPlans.map(({ planSlug }, index) => (_jsx(ComparisonGridHeaderCell, { planSlug: planSlug, isLastInRow: index === visibleGridPlans.length - 1, isFooter: isFooter, allVisible: allVisible, isInSignup: isInSignup, visibleGridPlans: visibleGridPlans, onPlanChange: onPlanChange, displayedGridPlans: displayedGridPlans, currentSitePlanSlug: currentSitePlanSlug, planActionOverrides: planActionOverrides, selectedPlan: selectedPlan, showRefundPeriod: showRefundPeriod, isStuck: isStuck }, planSlug))) })] }));
353
+ return (_jsxs(PlanRow, { as: "tr", isHiddenInMobile: isHiddenInMobile, ref: ref, children: [_jsx(RowTitleCell, { className: "plan-comparison-grid__header-cell is-placeholder-header-cell", isPlaceholderHeaderCell: true, children: isStuck && planTypeSelectorProps && (_jsx(PlanTypeSelectorWrapper, { children: _jsx(PlanTypeSelector, { ...planTypeSelectorProps, title: translate('Billing Cycle'), hideDiscount: true, coupon: coupon }) })) }, "feature-name"), _jsx(HeaderPriceContextProvider, { children: visibleGridPlans.map(({ planSlug }, index) => (_jsx(ComparisonGridHeaderCell, { planSlug: planSlug, isLastInRow: index === visibleGridPlans.length - 1, isFooter: isFooter, allVisible: allVisible, isInSignup: isInSignup, visibleGridPlans: visibleGridPlans, onPlanChange: onPlanChange, displayedGridPlans: displayedGridPlans, currentSitePlanSlug: currentSitePlanSlug, planActionOverrides: planActionOverrides, selectedPlan: selectedPlan, showRefundPeriod: showRefundPeriod, isStuck: isStuck }, planSlug))) })] }));
317
354
  });
355
+ ComparisonGridHeader.displayName = 'ComparisonGridHeader';
318
356
  const ComparisonGridFeatureGroupRowCell = ({ feature, visibleGridPlans, planSlug, isStorageFeature, intervalType, activeTooltipId, setActiveTooltipId, showUpgradeableStorage, onStorageAddOnClick, }) => {
319
357
  const { gridPlansIndex, enableFeatureTooltips, hideUnsupportedFeatures } = usePlansGridContext();
320
358
  const gridPlan = gridPlansIndex[planSlug];
@@ -326,14 +364,18 @@ const ComparisonGridFeatureGroupRowCell = ({ feature, visibleGridPlans, planSlug
326
364
  return null;
327
365
  }
328
366
  const featureSlug = feature?.getSlug();
329
- const hasFeature = isStorageFeature ||
330
- (featureSlug
331
- ? [...gridPlan.features.wpcomFeatures, ...gridPlan.features.jetpackFeatures]
332
- .filter((feature) => 'monthly' === intervalType ? !feature.availableOnlyForAnnualPlans : true)
333
- .some((feature) => feature.getSlug() === featureSlug)
334
- : false);
335
- const featureLabel = featureSlug
336
- ? gridPlan?.features?.comparisonGridFeatureLabels?.[featureSlug]
367
+ const comparisonGridTitle = featureSlug === FEATURE_REALTIME_BACKUPS_JP
368
+ ? translate('Real-time backups', { textOnly: true })
369
+ : feature?.getAlternativeTitle?.() || feature?.getTitle();
370
+ const planFeatures = [
371
+ ...gridPlan.features.wpcomFeatures,
372
+ ...gridPlan.features.jetpackFeatures,
373
+ ].filter((feature) => 'monthly' === intervalType ? !feature.availableOnlyForAnnualPlans : true);
374
+ const matchingFeature = findFeatureWithAlias(featureSlug, planFeatures);
375
+ const hasFeature = isStorageFeature || !!matchingFeature;
376
+ const featureLabelSlug = matchingFeature?.getSlug() ?? featureSlug;
377
+ const featureLabel = featureLabelSlug
378
+ ? gridPlan?.features?.comparisonGridFeatureLabels?.[featureLabelSlug]
337
379
  : undefined;
338
380
  const cellClasses = clsx('plan-comparison-grid__feature-group-row-cell', 'plan-comparison-grid__plan', getPlanClass(planSlug), {
339
381
  'popular-plan-parent-class': gridPlan.highlightLabel,
@@ -346,29 +388,34 @@ const ComparisonGridFeatureGroupRowCell = ({ feature, visibleGridPlans, planSlug
346
388
  'is-only-highlight': highlightAdjacencyMatrix[planSlug]?.isOnlyHighlight,
347
389
  });
348
390
  const planPaymentTransactionFees = gridPlan.features.wpcomFeatures?.find((feature) => feature?.getFeatureGroup?.() === FEATURE_GROUP_PAYMENT_TRANSACTION_FEES);
349
- return (_jsx(Cell, { className: cellClasses, textAlign: "center", children: isStorageFeature ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "plan-comparison-grid__plan-title", children: translate('Storage') }), _jsx(PlanStorage, { planSlug: planSlug, onStorageAddOnClick: onStorageAddOnClick, showUpgradeableStorage: showUpgradeableStorage })] })) : (_jsx(_Fragment, { children: FEATURE_GROUP_PAYMENT_TRANSACTION_FEES === featureSlug ? (_jsx(_Fragment, { children: planPaymentTransactionFees ? (_jsxs(_Fragment, { children: [_jsx(Plans2023Tooltip, { text: enableFeatureTooltips ? feature?.getDescription?.() : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: `${planSlug}-${featureSlug}`, children: _jsx("span", { className: "plan-comparison-grid__plan-title", children: feature?.getAlternativeTitle?.() || feature?.getTitle() }) }), _jsx("span", { className: "plan-comparison-grid__plan-conditional-title", children: planPaymentTransactionFees?.getAlternativeTitle?.() })] })) : (_jsx(Gridicon, { icon: "minus-small", color: "#C3C4C7" })) })) : (_jsxs(_Fragment, { children: [feature?.getIcon && (_jsx("span", { className: "plan-comparison-grid__plan-image", children: feature.getIcon() })), _jsx(Plans2023Tooltip, { text: enableFeatureTooltips ? feature?.getDescription?.() : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: `${planSlug}-${featureSlug}`, children: _jsx("span", { className: "plan-comparison-grid__plan-title", children: feature?.getAlternativeTitle?.() || feature?.getTitle() }) }), feature?.getCompareTitle && (_jsx("span", { className: "plan-comparison-grid__plan-subtitle", children: feature.getCompareTitle() })), featureLabel && (_jsx("span", { className: "plan-comparison-grid__plan-conditional-title", children: featureLabel })), hasFeature && feature?.getCompareSubtitle && (_jsx("span", { className: "plan-comparison-grid__plan-subtitle", children: feature.getCompareSubtitle() })), hasFeature && !featureLabel && (_jsx(Gridicon, { icon: "checkmark", color: "var(--studio-wordpress-blue-50)" })), !hasFeature && !featureLabel && _jsx(Gridicon, { icon: "minus-small", color: "#C3C4C7" })] })) })) }));
391
+ return (_jsx(Cell, { as: "td", className: cellClasses, textAlign: "center", children: isStorageFeature ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "plan-comparison-grid__plan-title", children: translate('Storage') }), _jsx(PlanStorage, { planSlug: planSlug, onStorageAddOnClick: onStorageAddOnClick, showUpgradeableStorage: showUpgradeableStorage })] })) : (_jsx(_Fragment, { children: FEATURE_GROUP_PAYMENT_TRANSACTION_FEES === featureSlug ? (_jsx(_Fragment, { children: planPaymentTransactionFees ? (_jsxs(_Fragment, { children: [_jsx(Plans2023Tooltip, { text: enableFeatureTooltips ? feature?.getDescription?.() : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: `${planSlug}-${featureSlug}`, children: _jsx("span", { className: "plan-comparison-grid__plan-title", children: comparisonGridTitle }) }), _jsx("span", { className: "plan-comparison-grid__plan-conditional-title", children: planPaymentTransactionFees?.getAlternativeTitle?.() })] })) : (_jsx(Gridicon, { icon: "minus-small", color: "#C3C4C7" })) })) : (_jsxs(_Fragment, { children: [feature?.getIcon && (_jsx("span", { className: "plan-comparison-grid__plan-image", children: feature.getIcon() })), _jsx(Plans2023Tooltip, { text: enableFeatureTooltips ? feature?.getDescription?.() : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: `${planSlug}-${featureSlug}`, children: _jsx("span", { className: "plan-comparison-grid__plan-title", children: comparisonGridTitle }) }), feature?.getCompareTitle && (_jsx("span", { className: "plan-comparison-grid__plan-subtitle", children: feature.getCompareTitle() })), featureLabel && (_jsx("span", { className: "plan-comparison-grid__plan-conditional-title", children: featureLabel })), hasFeature && feature?.getCompareSubtitle && (_jsx("span", { className: "plan-comparison-grid__plan-subtitle", children: feature.getCompareSubtitle() })), hasFeature && !featureLabel && (_jsx(Gridicon, { icon: "checkmark", color: "var(--studio-wordpress-blue-50)", "aria-label": translate('Feature available') })), !hasFeature && !featureLabel && (_jsx(Gridicon, { icon: "minus-small", color: "#C3C4C7", "aria-label": translate('Feature not available') }))] })) })) }));
350
392
  };
351
- const ComparisonGridFeatureGroupRow = ({ feature, isHiddenInMobile, allJetpackFeatures, visibleGridPlans, planFeatureFootnotes, isStorageFeature, isHighlighted, intervalType, activeTooltipId, setActiveTooltipId, showUpgradeableStorage, onStorageAddOnClick, }) => {
393
+ const ComparisonGridFeatureGroupRow = ({ feature, featureGroupSlug, isHiddenInMobile, allJetpackFeatures, visibleGridPlans, planFeatureFootnotes, isStorageFeature, isHighlighted, intervalType, activeTooltipId, setActiveTooltipId, showUpgradeableStorage, onStorageAddOnClick, }) => {
352
394
  const translate = useTranslate();
353
395
  const rowClasses = clsx('plan-comparison-grid__feature-group-row', {
354
396
  'is-storage-feature': isStorageFeature,
355
397
  });
356
398
  const featureSlug = feature?.getSlug() ?? '';
357
399
  const footnote = planFeatureFootnotes?.footnotesByFeature?.[featureSlug];
358
- const tooltipId = `${feature?.getSlug()}-comparison-grid`;
400
+ const tooltipId = `${featureGroupSlug}-${feature?.getSlug()}-comparison-grid`;
401
+ const title = featureSlug === FEATURE_REALTIME_BACKUPS_JP
402
+ ? // Always display the short title for backups in comparison grid.
403
+ translate('Real-time backups', { textOnly: true })
404
+ : feature?.getTitle?.();
405
+ const headerAriaLabel = typeof title === 'string' ? title : '';
359
406
  const { enableFeatureTooltips } = usePlansGridContext();
360
- return (_jsxs(Row, { isHiddenInMobile: isHiddenInMobile, className: rowClasses, isHighlighted: isHighlighted, children: [_jsx(RowTitleCell, { className: "is-feature-group-row-title-cell", isFeatureGroupRowTitleCell: true, children: isStorageFeature ? (_jsx(Plans2023Tooltip, { text: enableFeatureTooltips
407
+ return (_jsxs(Row, { as: "tr", isHiddenInMobile: isHiddenInMobile, className: rowClasses, isHighlighted: isHighlighted, children: [_jsx(RowHeaderCell, { className: "is-feature-group-row-title-cell", isFeatureGroupRowTitleCell: true, scope: "row", "aria-label": headerAriaLabel, children: isStorageFeature ? (_jsx(Plans2023Tooltip, { text: enableFeatureTooltips
361
408
  ? translate('Space to store your photos, media, and more.')
362
- : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: tooltipId, children: translate('Storage') })) : (_jsx(_Fragment, { children: feature && (_jsxs(_Fragment, { children: [_jsxs(Plans2023Tooltip, { text: enableFeatureTooltips ? feature.getDescription?.() : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: tooltipId, children: [feature.getTitle(), footnote && (_jsx(FeatureFootnote, { children: _jsx("sup", { children: footnote }) }))] }), allJetpackFeatures.has(feature.getSlug()) ? (_jsx(JetpackIconContainer, { children: _jsx(Plans2023Tooltip, { text: translate('Security, performance, and growth tools—powered by Jetpack.'), setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: `jp-${tooltipId}`, children: _jsx(JetpackLogo, { size: 16 }) }) })) : null] })) })) }, "feature-name"), visibleGridPlans.map(({ planSlug }) => (_jsx(ComparisonGridFeatureGroupRowCell, { feature: feature, allJetpackFeatures: allJetpackFeatures, visibleGridPlans: visibleGridPlans, planSlug: planSlug, isStorageFeature: isStorageFeature, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick }, planSlug)))] }));
409
+ : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: tooltipId, children: translate('Storage') })) : (_jsx(_Fragment, { children: feature && (_jsx(_Fragment, { children: _jsx(Plans2023Tooltip, { text: enableFeatureTooltips ? feature.getDescription?.() : undefined, setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: tooltipId, children: typeof title === 'string' ? (_jsxs(_Fragment, { children: [title.split(' ').slice(0, -1).join(' '), title.includes(' ') ? ' ' : null, _jsxs(TitlePreventOrphans, { children: [title.split(' ').slice(-1), footnote && (_jsx(FeatureFootnote, { children: _jsx("sup", { children: footnote }) })), allJetpackFeatures.has(feature.getSlug()) ? (_jsxs(_Fragment, { children: ['\u00A0', _jsx(JetpackIconContainer, { children: _jsx(Plans2023Tooltip, { text: translate('Security, performance, and growth tools—powered by Jetpack.'), setActiveTooltipId: setActiveTooltipId, activeTooltipId: activeTooltipId, id: `jp-${tooltipId}`, children: _jsx(JetpackLogo, { size: 16 }) }) })] })) : null] })] })) : (_jsxs(_Fragment, { children: [feature.getTitle(), footnote && (_jsx(FeatureFootnote, { children: _jsx("sup", { children: footnote }) }))] })) }) })) })) }, "feature-name"), visibleGridPlans.map(({ planSlug }) => (_jsx(ComparisonGridFeatureGroupRowCell, { feature: feature, allJetpackFeatures: allJetpackFeatures, visibleGridPlans: visibleGridPlans, planSlug: planSlug, isStorageFeature: isStorageFeature, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick }, planSlug)))] }));
363
410
  };
364
- const FeatureGroup = ({ featureGroup, selectedFeature, intervalType, activeTooltipId, setActiveTooltipId, showUpgradeableStorage, onStorageAddOnClick, featureGroupMap, visibleGridPlans, planFeatureFootnotes, }) => {
365
- const { allFeaturesList } = usePlansGridContext();
411
+ const FeatureGroup = ({ featureGroup, selectedFeature, intervalType, activeTooltipId, setActiveTooltipId, showUpgradeableStorage, onStorageAddOnClick, featureGroupMap, visibleGridPlans, planFeatureFootnotes, plansLength, }) => {
412
+ const { allFeaturesList, isExperimentVariant } = usePlansGridContext();
366
413
  const [firstSetOfFeatures] = Object.keys(featureGroupMap);
367
414
  const [visibleFeatureGroups, setVisibleFeatureGroups] = useState([
368
415
  firstSetOfFeatures,
369
416
  ]);
370
417
  const features = featureGroup.getFeatures();
371
- const featureObjects = filterUnusedFeaturesObject(visibleGridPlans, getPlanFeaturesObject(allFeaturesList, features));
418
+ const featureObjects = filterUnusedFeaturesObject(visibleGridPlans, getPlanFeaturesObject(allFeaturesList, features, isExperimentVariant));
372
419
  const isHiddenInMobile = !visibleFeatureGroups.includes(featureGroup.slug);
373
420
  const allJetpackFeatures = useMemo(() => {
374
421
  const allPlans = getPlans();
@@ -399,67 +446,20 @@ const FeatureGroup = ({ featureGroup, selectedFeature, intervalType, activeToolt
399
446
  if (featureGroup.slug !== FEATURE_GROUP_ESSENTIAL_FEATURES && !featureObjects.length) {
400
447
  return null;
401
448
  }
402
- return (_jsxs("div", { className: "plan-comparison-grid__feature-group", children: [_jsx(TitleRow, { className: "plan-comparison-grid__feature-group-title-row", onClick: handleFeatureGroupToggle, children: _jsxs(Title, { isHiddenInMobile: isHiddenInMobile, children: [_jsx(Gridicon, { icon: "chevron-up", size: 12, color: "#1E1E1E" }), _jsx("span", { children: featureGroup.getTitle() })] }) }), featureObjects.map((feature) => (_jsx(ComparisonGridFeatureGroupRow, { feature: feature, isHiddenInMobile: isHiddenInMobile, allJetpackFeatures: allJetpackFeatures, visibleGridPlans: visibleGridPlans, planFeatureFootnotes: planFeatureFootnotes, isStorageFeature: false, isHighlighted: feature.getSlug() === selectedFeature, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick }, feature.getSlug()))), featureGroup.slug === FEATURE_GROUP_ESSENTIAL_FEATURES ? (_jsx(ComparisonGridFeatureGroupRow, { isHiddenInMobile: isHiddenInMobile, allJetpackFeatures: allJetpackFeatures, visibleGridPlans: visibleGridPlans, planFeatureFootnotes: planFeatureFootnotes, isStorageFeature: true, isHighlighted: false, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick }, "feature-storage")) : null] }, featureGroup.slug));
449
+ return (_jsxs(Grid, { as: "tbody", visiblePlans: plansLength, className: "plan-comparison-grid__feature-group", children: [_jsx(TitleRow, { as: "tr", className: "plan-comparison-grid__feature-group-title-row", onClick: handleFeatureGroupToggle, children: _jsxs(Title, { as: "td", isHiddenInMobile: isHiddenInMobile, children: [_jsx(Gridicon, { icon: "chevron-up", size: 12, color: "#1E1E1E" }), _jsx("span", { children: featureGroup.getTitle() })] }) }), featureObjects.map((feature) => (_jsx(ComparisonGridFeatureGroupRow, { feature: feature, featureGroupSlug: featureGroup.slug, isHiddenInMobile: isHiddenInMobile, allJetpackFeatures: allJetpackFeatures, visibleGridPlans: visibleGridPlans, planFeatureFootnotes: planFeatureFootnotes, isStorageFeature: false, isHighlighted: feature.getSlug() === selectedFeature, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick }, feature.getSlug()))), featureGroup.slug === FEATURE_GROUP_ESSENTIAL_FEATURES ? (_jsx(ComparisonGridFeatureGroupRow, { featureGroupSlug: featureGroup.slug, isHiddenInMobile: isHiddenInMobile, allJetpackFeatures: allJetpackFeatures, visibleGridPlans: visibleGridPlans, planFeatureFootnotes: planFeatureFootnotes, isStorageFeature: true, isHighlighted: false, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick }, "feature-storage")) : null] }, featureGroup.slug));
403
450
  };
404
- const ComparisonGrid = ({ intervalType, isInSignup, currentSitePlanSlug, planActionOverrides, selectedPlan, selectedFeature, showUpgradeableStorage, stickyRowOffset, onStorageAddOnClick, showRefundPeriod, planTypeSelectorProps, gridSize, siteId, }) => {
405
- const { gridPlans, gridPlansIndex, featureGroupMap } = usePlansGridContext();
451
+ const ComparisonGrid = ({ intervalType, isInSignup, currentSitePlanSlug, planActionOverrides, selectedPlan, selectedFeature, showUpgradeableStorage, stickyRowOffset, onStorageAddOnClick, showRefundPeriod, planTypeSelectorProps, gridSize, siteId, onVisiblePlansCountChange, }) => {
452
+ const { gridPlans, featureGroupMap } = usePlansGridContext();
406
453
  const [activeTooltipId, setActiveTooltipId] = useManageTooltipToggle();
407
- const [visiblePlans, setVisiblePlans] = useState([]);
408
- const currentPlanTerm = Plans.useCurrentPlanTerm({ siteId });
409
- const selectedPlanTerm = usePlanBillingPeriod({ intervalType });
410
- useEffect(() => {
411
- let numPlansToDisplay = gridPlans.length;
412
- switch (gridSize) {
413
- case 'large':
414
- numPlansToDisplay = 4;
415
- break;
416
- case 'medium':
417
- numPlansToDisplay = 3;
418
- break;
419
- case 'smedium':
420
- case 'small':
421
- numPlansToDisplay = 2;
422
- break;
423
- }
424
- let visiblePlanSlugs = gridPlans
425
- .slice(0, numPlansToDisplay)
426
- .map(({ planSlug }) => planSlug);
427
- const isCurrentPlanVisible = !!currentSitePlanSlug && visiblePlanSlugs.includes(currentSitePlanSlug);
428
- /**
429
- * Plans are sorted by least to most expensive unless:
430
- * - a current plan exists and
431
- * - the current plan's term matches the selected term and
432
- * - the current plan would not be displayed due to the number of plans that can be visible at once
433
- *
434
- * If those conditions are met:
435
- * - the current plan is placed at the start of the grid and
436
- * - the last plan is removed to maintain the expected number of visible plans
437
- */
438
- if (currentSitePlanSlug && !isCurrentPlanVisible && currentPlanTerm === selectedPlanTerm) {
439
- visiblePlanSlugs = [currentSitePlanSlug, ...visiblePlanSlugs].slice(0, numPlansToDisplay);
440
- }
441
- setVisiblePlans(visiblePlanSlugs);
442
- }, [
454
+ const { visibleGridPlans, setVisibleGridPlans } = useVisibleGridPlans({
443
455
  gridSize,
444
- gridPlansIndex,
445
456
  currentSitePlanSlug,
446
- gridPlans,
447
- currentPlanTerm,
448
- selectedPlanTerm,
457
+ siteId,
449
458
  intervalType,
450
- ]);
451
- const visibleGridPlans = useMemo(() => visiblePlans.reduce((acc, planSlug) => {
452
- const gridPlan = gridPlans.find((gridPlan) => getPlanClass(gridPlan.planSlug) === getPlanClass(planSlug));
453
- if (gridPlan) {
454
- acc.push(gridPlan);
455
- }
456
- return acc;
457
- }, []), [visiblePlans, gridPlans]);
458
- const onPlanChange = useCallback((currentPlan, event) => {
459
- const newPlan = event.currentTarget.value;
460
- const newVisiblePlans = visiblePlans.map((plan) => plan === currentPlan ? newPlan : plan);
461
- setVisiblePlans(newVisiblePlans);
462
- }, [visiblePlans]);
459
+ });
460
+ useEffect(() => {
461
+ onVisiblePlansCountChange?.(visibleGridPlans.length);
462
+ }, [visibleGridPlans.length, onVisiblePlansCountChange]);
463
463
  const planFeatureFootnotes = useMemo(() => {
464
464
  // This is the main list of all footnotes. It is displayed at the bottom of the comparison grid.
465
465
  const footnoteList = [];
@@ -486,6 +486,13 @@ const ComparisonGrid = ({ intervalType, isInSignup, currentSitePlanSlug, planAct
486
486
  footnotesByFeature,
487
487
  };
488
488
  }, [featureGroupMap]);
489
+ const onPlanChange = useCallback((currentPlan, event) => {
490
+ const newPlanSlug = event.currentTarget.value;
491
+ const newPlan = gridPlans.find((plan) => plan.planSlug === newPlanSlug);
492
+ if (newPlan) {
493
+ setVisibleGridPlans((previousGridPlans) => previousGridPlans.map((plan) => (plan.planSlug === currentPlan ? newPlan : plan)));
494
+ }
495
+ }, [gridPlans, setVisibleGridPlans]);
489
496
  // 100px is the padding of the footer row
490
497
  const [bottomHeaderRef, isBottomHeaderInView] = useInView({ rootMargin: '-100px' });
491
498
  /**
@@ -497,14 +504,14 @@ const ComparisonGrid = ({ intervalType, isInSignup, currentSitePlanSlug, planAct
497
504
  const classes = clsx('plans-grid-next-comparison-grid', {
498
505
  'has-highlighted-plan': hasHighlightedPlan,
499
506
  });
500
- return (_jsxs("div", { className: classes, children: [_jsxs(Grid, { visiblePlans: visiblePlans.length, children: [_jsx(StickyContainer, { disabled: isBottomHeaderInView, stickyClass: "is-sticky-header-row", stickyOffset: stickyRowOffset, zIndex: 1, children: (isStuck) => (_jsx(ComparisonGridHeader, { displayedGridPlans: gridPlans, visibleGridPlans: visibleGridPlans, isInSignup: isInSignup, onPlanChange: onPlanChange, currentSitePlanSlug: currentSitePlanSlug, planActionOverrides: planActionOverrides, selectedPlan: selectedPlan, showRefundPeriod: showRefundPeriod, isStuck: isStuck, planTypeSelectorProps: planTypeSelectorProps })) }), Object.values(featureGroupMap).map((featureGroup) => (_jsx(FeatureGroup, { featureGroup: featureGroup, visibleGridPlans: visibleGridPlans, featureGroupMap: featureGroupMap, selectedFeature: selectedFeature, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick, planFeatureFootnotes: planFeatureFootnotes }, featureGroup.slug))), _jsx(ComparisonGridHeader, { displayedGridPlans: gridPlans, visibleGridPlans: visibleGridPlans, isInSignup: isInSignup, isFooter: true, onPlanChange: onPlanChange, currentSitePlanSlug: currentSitePlanSlug, planActionOverrides: planActionOverrides, selectedPlan: selectedPlan, showRefundPeriod: showRefundPeriod, isStuck: false, isHiddenInMobile: true, ref: bottomHeaderRef, planTypeSelectorProps: planTypeSelectorProps })] }), _jsx("div", { className: "plan-comparison-grid__footer", children: planFeatureFootnotes?.footnoteList && (_jsx(FeatureFootnotes, { children: _jsx("ol", { children: planFeatureFootnotes?.footnoteList?.map((footnote, index) => {
501
- return _jsx("li", { children: footnote }, `${footnote}-${index}`);
502
- }) }) })) })] }));
507
+ return (_jsxs("table", { className: classes, children: [_jsx(StickyGrid, { visiblePlans: visibleGridPlans.length, element: "thead", disabled: isBottomHeaderInView, stickyClass: "is-sticky-header-row", stickyOffset: stickyRowOffset, zIndex: 1, children: (isStuck) => (_jsx(ComparisonGridHeader, { displayedGridPlans: gridPlans, visibleGridPlans: visibleGridPlans, isInSignup: isInSignup, onPlanChange: onPlanChange, currentSitePlanSlug: currentSitePlanSlug, planActionOverrides: planActionOverrides, selectedPlan: selectedPlan, showRefundPeriod: showRefundPeriod, isStuck: isStuck, planTypeSelectorProps: planTypeSelectorProps })) }), Object.values(featureGroupMap).map((featureGroup) => (_jsx(FeatureGroup, { featureGroup: featureGroup, visibleGridPlans: visibleGridPlans, featureGroupMap: featureGroupMap, selectedFeature: selectedFeature, intervalType: intervalType, activeTooltipId: activeTooltipId, setActiveTooltipId: setActiveTooltipId, showUpgradeableStorage: showUpgradeableStorage, onStorageAddOnClick: onStorageAddOnClick, planFeatureFootnotes: planFeatureFootnotes, plansLength: visibleGridPlans.length }, featureGroup.slug))), _jsx("tbody", { children: _jsx(ComparisonGridHeader, { displayedGridPlans: gridPlans, visibleGridPlans: visibleGridPlans, isInSignup: isInSignup, isFooter: true, onPlanChange: onPlanChange, currentSitePlanSlug: currentSitePlanSlug, planActionOverrides: planActionOverrides, selectedPlan: selectedPlan, showRefundPeriod: showRefundPeriod, isStuck: false, isHiddenInMobile: true, ref: bottomHeaderRef, planTypeSelectorProps: planTypeSelectorProps }) }), _jsx("tfoot", { className: "plan-comparison-grid__footer", children: planFeatureFootnotes?.footnoteList && (_jsx(FeatureFootnotes, { as: "tr", children: _jsx("td", { children: _jsx("ol", { children: planFeatureFootnotes?.footnoteList?.map((footnote, index) => {
508
+ return _jsx("li", { children: footnote }, `${footnote}-${index}`);
509
+ }) }) }) })) })] }));
503
510
  };
504
511
  // TODO
505
512
  // Now that everything under is functional component, we can deprecate this wrapper and only keep ComparisonGrid instead.
506
513
  // More details can be found in https://github.com/Automattic/wp-calypso/issues/87047
507
- const WrappedComparisonGrid = ({ siteId, intent, gridPlans, useCheckPlanAvailabilityForPurchase, useAction, recordTracksEvent, allFeaturesList, intervalType, isInSiteDashboard, isInSignup, currentSitePlanSlug, selectedPlan, selectedFeature, showUpgradeableStorage, onStorageAddOnClick, stickyRowOffset, coupon, className, hideUnsupportedFeatures, enableFeatureTooltips, featureGroupMap, enableTermSavingsPriceDisplay, reflectStorageSelectionInPlanPrices, ...otherProps }) => {
514
+ const WrappedComparisonGrid = ({ siteId, intent, gridPlans, useCheckPlanAvailabilityForPurchase, useAction, recordTracksEvent, allFeaturesList, intervalType, isInSiteDashboard, isInSignup, currentSitePlanSlug, selectedPlan, selectedFeature, showUpgradeableStorage, onStorageAddOnClick, stickyRowOffset, coupon, className, hideUnsupportedFeatures, enableFeatureTooltips, featureGroupMap, enableTermSavingsPriceDisplay, reflectStorageSelectionInPlanPrices, showSimplifiedBillingDescription, showBillingDescriptionForIncreasedRenewalPrice, isExperimentVariant, ...otherProps }) => {
508
515
  const gridContainerRef = useRef(null);
509
516
  const gridBreakpoints = useMemo(() => {
510
517
  // we want to fit up to the Commerce plan in this breakpoint
@@ -530,7 +537,7 @@ const WrappedComparisonGrid = ({ siteId, intent, gridPlans, useCheckPlanAvailabi
530
537
  'is-xlarge': 'xlarge' === gridSize,
531
538
  'is-visible': true,
532
539
  });
533
- return (_jsx("div", { ref: gridContainerRef, className: classNames, children: _jsx(PlansGridContextProvider, { intent: intent, siteId: siteId, gridPlans: gridPlans, useCheckPlanAvailabilityForPurchase: useCheckPlanAvailabilityForPurchase, useAction: useAction, recordTracksEvent: recordTracksEvent, allFeaturesList: allFeaturesList, coupon: coupon, enableFeatureTooltips: enableFeatureTooltips, featureGroupMap: featureGroupMap, hideUnsupportedFeatures: hideUnsupportedFeatures, enableTermSavingsPriceDisplay: enableTermSavingsPriceDisplay, reflectStorageSelectionInPlanPrices: reflectStorageSelectionInPlanPrices, children: _jsx(ComparisonGrid, { intervalType: intervalType, isInSiteDashboard: isInSiteDashboard, isInSignup: isInSignup, currentSitePlanSlug: currentSitePlanSlug, siteId: siteId, selectedPlan: selectedPlan, selectedFeature: selectedFeature, showUpgradeableStorage: showUpgradeableStorage, stickyRowOffset: stickyRowOffset, onStorageAddOnClick: onStorageAddOnClick, gridSize: gridSize ?? undefined, ...otherProps }) }) }));
540
+ return (_jsx("div", { ref: gridContainerRef, className: classNames, children: _jsx(PlansGridContextProvider, { intent: intent, siteId: siteId, gridPlans: gridPlans, useCheckPlanAvailabilityForPurchase: useCheckPlanAvailabilityForPurchase, useAction: useAction, recordTracksEvent: recordTracksEvent, allFeaturesList: allFeaturesList, coupon: coupon, enableFeatureTooltips: enableFeatureTooltips, featureGroupMap: featureGroupMap, hideUnsupportedFeatures: hideUnsupportedFeatures, enableTermSavingsPriceDisplay: enableTermSavingsPriceDisplay, reflectStorageSelectionInPlanPrices: reflectStorageSelectionInPlanPrices, showSimplifiedBillingDescription: showSimplifiedBillingDescription, showBillingDescriptionForIncreasedRenewalPrice: showBillingDescriptionForIncreasedRenewalPrice, isExperimentVariant: isExperimentVariant, children: _jsx(ComparisonGrid, { intervalType: intervalType, isInSiteDashboard: isInSiteDashboard, isInSignup: isInSignup, currentSitePlanSlug: currentSitePlanSlug, siteId: siteId, selectedPlan: selectedPlan, selectedFeature: selectedFeature, showUpgradeableStorage: showUpgradeableStorage, stickyRowOffset: stickyRowOffset, onStorageAddOnClick: onStorageAddOnClick, gridSize: gridSize ?? undefined, ...otherProps }) }, intent) }));
534
541
  };
535
542
  export default WrappedComparisonGrid;
536
543
  //# sourceMappingURL=index.js.map