orionplace-nuxt 0.1.2 → 0.2.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 (520) hide show
  1. package/README.md +711 -24
  2. package/bin/orionplace-nuxt.mjs +39 -11
  3. package/package.json +26 -6
  4. package/runtime/api.mjs +4 -1
  5. package/runtime/domain.mjs +4 -2
  6. package/runtime/marketplace.mjs +287 -211
  7. package/src/asset-loading-plugin.mjs +10 -0
  8. package/src/module.mjs +44 -14
  9. package/src/project-readme.mjs +507 -35
  10. package/src/setup.mjs +100 -51
  11. package/src/update.mjs +36 -0
  12. package/src/validation.mjs +6 -0
  13. package/templates/.vscode/settings.json +5 -0
  14. package/templates/app/app.vue +48 -0
  15. package/templates/app/assets/css/orionplace-tokens.css +21 -0
  16. package/templates/app/assets/css/orionplace.css +28 -0
  17. package/templates/app/components/orionplace/account/AccountActivity.README.md +31 -0
  18. package/templates/app/components/orionplace/account/AccountActivity.vue +61 -0
  19. package/templates/app/components/orionplace/account/AccountPromocodes.README.md +50 -0
  20. package/templates/app/components/orionplace/account/AccountPromocodes.vue +267 -0
  21. package/templates/app/components/orionplace/account/AccountSection.README.md +31 -0
  22. package/templates/app/components/orionplace/account/AccountSection.vue +132 -0
  23. package/templates/app/components/orionplace/account/ProfileAvatar.vue +139 -0
  24. package/templates/app/components/orionplace/account/ProfileDeleteAccount.vue +161 -0
  25. package/templates/app/components/orionplace/account/ProfileDetailsForm.vue +172 -0
  26. package/templates/app/components/orionplace/account/ProfileEmailSettings.vue +269 -0
  27. package/templates/app/components/orionplace/account/ProfilePasswordForm.vue +201 -0
  28. package/templates/app/components/orionplace/account/ProfileSignIn.vue +446 -0
  29. package/templates/app/components/orionplace/account/SignInHistory.README.md +27 -0
  30. package/templates/app/components/orionplace/account/SignInHistory.vue +218 -0
  31. package/templates/app/components/orionplace/account/StorefrontLogout.README.md +15 -0
  32. package/templates/app/components/orionplace/account/StorefrontLogout.vue +109 -0
  33. package/templates/app/components/orionplace/account/StorefrontProfile.README.md +145 -0
  34. package/templates/app/components/orionplace/account/StorefrontProfile.vue +168 -0
  35. package/templates/app/components/orionplace/account/account.css +1047 -0
  36. package/templates/app/components/orionplace/account/profile.css +696 -0
  37. package/templates/app/components/orionplace/address/AddressForm.README.md +67 -0
  38. package/templates/app/components/orionplace/address/AddressForm.vue +537 -0
  39. package/templates/app/components/orionplace/address/StorefrontAddresses.README.md +44 -0
  40. package/templates/app/components/orionplace/address/StorefrontAddresses.vue +438 -0
  41. package/templates/app/components/orionplace/banners/MainBanner.vue +171 -0
  42. package/templates/app/components/orionplace/banners/examples/BannerExample.vue +6 -0
  43. package/templates/app/components/orionplace/blog/BlogArticle.README.md +44 -0
  44. package/templates/app/components/orionplace/blog/BlogArticle.vue +829 -0
  45. package/templates/app/components/orionplace/blog/BlogCommentForm.README.md +28 -0
  46. package/templates/app/components/orionplace/blog/BlogCommentForm.vue +129 -0
  47. package/templates/app/components/orionplace/blog/BlogComments.README.md +36 -0
  48. package/templates/app/components/orionplace/blog/BlogComments.vue +373 -0
  49. package/templates/app/components/orionplace/blog/BlogPostCard.vue +307 -0
  50. package/templates/app/components/orionplace/blog/BlogPostGroup.vue +108 -0
  51. package/templates/app/components/orionplace/blog/StorefrontJournal.README.md +42 -0
  52. package/templates/app/components/orionplace/blog/StorefrontJournal.vue +669 -0
  53. package/templates/app/components/orionplace/branding/BrandLogos.vue +25 -0
  54. package/templates/app/components/orionplace/branding/examples/BrandLogosExample.vue +6 -0
  55. package/templates/app/components/orionplace/cart/CartCheckoutDetails.README.md +81 -0
  56. package/templates/app/components/orionplace/cart/CartCheckoutDetails.vue +367 -0
  57. package/templates/app/components/orionplace/cart/CartDeliverySelector.README.md +95 -0
  58. package/templates/app/components/orionplace/cart/CartDeliverySelector.vue +724 -0
  59. package/templates/app/components/orionplace/cart/CartItemOptions.README.md +98 -0
  60. package/templates/app/components/orionplace/cart/CartItemOptions.vue +693 -0
  61. package/templates/app/components/orionplace/cart/CartLineItem.README.md +70 -0
  62. package/templates/app/components/orionplace/cart/CartLineItem.vue +271 -0
  63. package/templates/app/components/orionplace/cart/CartPreview.README.md +43 -0
  64. package/templates/app/components/orionplace/cart/CartPreview.vue +263 -0
  65. package/templates/app/components/orionplace/cart/DeliveryMap.README.md +48 -0
  66. package/templates/app/components/orionplace/cart/DeliveryMap.vue +155 -0
  67. package/templates/app/components/orionplace/cart/StorefrontCart.README.md +89 -0
  68. package/templates/app/components/orionplace/cart/StorefrontCart.vue +689 -0
  69. package/templates/app/components/orionplace/catalog/CatalogHeader.vue +681 -0
  70. package/templates/app/components/orionplace/catalog/CatalogRepresentative.vue +59 -0
  71. package/templates/app/components/orionplace/catalog/StorefrontCatalog.README.md +35 -0
  72. package/templates/app/components/orionplace/catalog/StorefrontCatalog.vue +179 -0
  73. package/templates/app/components/orionplace/catalog/examples/CatalogHeaderExample.vue +6 -0
  74. package/templates/app/components/orionplace/categories/CategoryGroup.vue +125 -0
  75. package/templates/app/components/orionplace/categories/StorefrontCategory.README.md +60 -0
  76. package/templates/app/components/orionplace/categories/StorefrontCategory.vue +277 -0
  77. package/templates/app/components/orionplace/categories/examples/CategoryGroupExample.vue +7 -0
  78. package/templates/app/components/orionplace/contact/AboutPage.README.md +23 -0
  79. package/templates/app/components/orionplace/contact/AboutPage.vue +409 -0
  80. package/templates/app/components/orionplace/contact/ContactForm.README.md +29 -0
  81. package/templates/app/components/orionplace/contact/ContactForm.vue +289 -0
  82. package/templates/app/components/orionplace/contact/EmailUnsubscribe.README.md +27 -0
  83. package/templates/app/components/orionplace/contact/EmailUnsubscribe.vue +95 -0
  84. package/templates/app/components/orionplace/contact/StorefrontContact.README.md +18 -0
  85. package/templates/app/components/orionplace/contact/StorefrontContact.vue +89 -0
  86. package/templates/app/components/orionplace/contact/examples/ContactExample.vue +6 -0
  87. package/templates/app/components/orionplace/currencies/MainCurrencySwitcher.vue +80 -0
  88. package/templates/app/components/orionplace/currencies/examples/CurrencyExample.vue +6 -0
  89. package/templates/app/components/orionplace/events/EventEnrollmentDialog.README.md +58 -0
  90. package/templates/app/components/orionplace/events/EventEnrollmentDialog.vue +294 -0
  91. package/templates/app/components/orionplace/events/EventsBlock.vue +138 -0
  92. package/templates/app/components/orionplace/events/examples/EventsExample.vue +6 -0
  93. package/templates/app/components/orionplace/locale/MainLanguageSwitcher.vue +506 -0
  94. package/templates/app/components/orionplace/locale/examples/LocaleExample.vue +6 -0
  95. package/templates/app/components/orionplace/manufacturers/ManufacturerIndex.README.md +36 -0
  96. package/templates/app/components/orionplace/manufacturers/ManufacturerIndex.vue +495 -0
  97. package/templates/app/components/orionplace/manufacturers/StorefrontManufacturers.README.md +30 -0
  98. package/templates/app/components/orionplace/manufacturers/StorefrontManufacturers.vue +263 -0
  99. package/templates/app/components/orionplace/orders/OrderDetails.README.md +39 -0
  100. package/templates/app/components/orionplace/orders/OrderDetails.vue +1074 -0
  101. package/templates/app/components/orionplace/orders/OrderPaymentForm.README.md +59 -0
  102. package/templates/app/components/orionplace/orders/OrderPaymentForm.vue +73 -0
  103. package/templates/app/components/orionplace/orders/StorefrontOrders.README.md +39 -0
  104. package/templates/app/components/orionplace/orders/StorefrontOrders.vue +869 -0
  105. package/templates/app/components/orionplace/orders/orders.css +612 -0
  106. package/templates/app/components/orionplace/payments/PaymentPanel.README.md +76 -0
  107. package/templates/app/components/orionplace/payments/PaymentPanel.vue +108 -0
  108. package/templates/app/components/orionplace/products/HoverImageViewer.vue +190 -0
  109. package/templates/app/components/orionplace/products/ProductCard.README.md +63 -0
  110. package/templates/app/components/orionplace/products/ProductCard.vue +897 -0
  111. package/templates/app/components/orionplace/products/ProductCardActions.README.md +33 -0
  112. package/templates/app/components/orionplace/products/ProductCardActions.vue +412 -0
  113. package/templates/app/components/orionplace/products/ProductCardBadges.vue +83 -0
  114. package/templates/app/components/orionplace/products/ProductCardDescription.vue +46 -0
  115. package/templates/app/components/orionplace/products/ProductCardFavorite.vue +99 -0
  116. package/templates/app/components/orionplace/products/ProductCardPrice.vue +66 -0
  117. package/templates/app/components/orionplace/products/ProductCardRating.vue +65 -0
  118. package/templates/app/components/orionplace/products/ProductCardSeller.vue +66 -0
  119. package/templates/app/components/orionplace/products/ProductCardStockNotice.vue +43 -0
  120. package/templates/app/components/orionplace/products/ProductCardTitle.vue +46 -0
  121. package/templates/app/components/orionplace/products/ProductCardVariants.vue +388 -0
  122. package/templates/app/components/orionplace/products/ProductGroup.vue +257 -0
  123. package/templates/app/components/orionplace/products/ProductPreorderDialog.README.md +22 -0
  124. package/templates/app/components/orionplace/products/ProductPreorderDialog.vue +471 -0
  125. package/templates/app/components/orionplace/products/ProductReviewForm.README.md +39 -0
  126. package/templates/app/components/orionplace/products/ProductReviewForm.vue +312 -0
  127. package/templates/app/components/orionplace/products/ProductReviewGallery.README.md +28 -0
  128. package/templates/app/components/orionplace/products/ProductReviewGallery.vue +141 -0
  129. package/templates/app/components/orionplace/products/ProductReviewImageViewer.README.md +51 -0
  130. package/templates/app/components/orionplace/products/ProductReviewImageViewer.vue +351 -0
  131. package/templates/app/components/orionplace/products/ProductReviews.README.md +70 -0
  132. package/templates/app/components/orionplace/products/ProductReviews.vue +1025 -0
  133. package/templates/app/components/orionplace/products/ProductSecondaryVariantModal.vue +460 -0
  134. package/templates/app/components/orionplace/products/ProductSpecificationsDialog.README.md +65 -0
  135. package/templates/app/components/orionplace/products/ProductSpecificationsDialog.vue +174 -0
  136. package/templates/app/components/orionplace/products/StorefrontProduct.README.md +52 -0
  137. package/templates/app/components/orionplace/products/StorefrontProduct.vue +1466 -0
  138. package/templates/app/components/orionplace/products/StorefrontWishlist.README.md +33 -0
  139. package/templates/app/components/orionplace/products/StorefrontWishlist.vue +290 -0
  140. package/templates/app/components/orionplace/products/examples/FeaturedExample.vue +6 -0
  141. package/templates/app/components/orionplace/products/examples/FeaturedHoverImageViewerExample.vue +14 -0
  142. package/templates/app/components/orionplace/products/examples/FeaturedProductCardActionsExample.vue +14 -0
  143. package/templates/app/components/orionplace/products/examples/FeaturedProductCardBadgesExample.vue +14 -0
  144. package/templates/app/components/orionplace/products/examples/FeaturedProductCardDescriptionExample.vue +14 -0
  145. package/templates/app/components/orionplace/products/examples/FeaturedProductCardExample.vue +14 -0
  146. package/templates/app/components/orionplace/products/examples/FeaturedProductCardFavoriteExample.vue +14 -0
  147. package/templates/app/components/orionplace/products/examples/FeaturedProductCardPriceExample.vue +14 -0
  148. package/templates/app/components/orionplace/products/examples/FeaturedProductCardRatingExample.vue +14 -0
  149. package/templates/app/components/orionplace/products/examples/FeaturedProductCardSellerExample.vue +14 -0
  150. package/templates/app/components/orionplace/products/examples/FeaturedProductCardStockNoticeExample.vue +14 -0
  151. package/templates/app/components/orionplace/products/examples/FeaturedProductCardTitleExample.vue +14 -0
  152. package/templates/app/components/orionplace/products/examples/FeaturedProductCardVariantsExample.vue +14 -0
  153. package/templates/app/components/orionplace/products/examples/ProductsExample.vue +6 -0
  154. package/templates/app/components/orionplace/products/examples/ProductsHoverImageViewerExample.vue +13 -0
  155. package/templates/app/components/orionplace/products/examples/ProductsProductCardActionsExample.vue +13 -0
  156. package/templates/app/components/orionplace/products/examples/ProductsProductCardBadgesExample.vue +13 -0
  157. package/templates/app/components/orionplace/products/examples/ProductsProductCardDescriptionExample.vue +13 -0
  158. package/templates/app/components/orionplace/products/examples/ProductsProductCardExample.vue +13 -0
  159. package/templates/app/components/orionplace/products/examples/ProductsProductCardFavoriteExample.vue +13 -0
  160. package/templates/app/components/orionplace/products/examples/ProductsProductCardPriceExample.vue +13 -0
  161. package/templates/app/components/orionplace/products/examples/ProductsProductCardRatingExample.vue +13 -0
  162. package/templates/app/components/orionplace/products/examples/ProductsProductCardSellerExample.vue +13 -0
  163. package/templates/app/components/orionplace/products/examples/ProductsProductCardStockNoticeExample.vue +13 -0
  164. package/templates/app/components/orionplace/products/examples/ProductsProductCardTitleExample.vue +13 -0
  165. package/templates/app/components/orionplace/products/examples/ProductsProductCardVariantsExample.vue +13 -0
  166. package/templates/app/components/orionplace/promo/PromoProducts.README.md +45 -0
  167. package/templates/app/components/orionplace/promo/PromoProducts.vue +287 -0
  168. package/templates/app/components/orionplace/search/MainSearch.vue +342 -0
  169. package/templates/app/components/orionplace/search/ProductSearchResults.README.md +81 -0
  170. package/templates/app/components/orionplace/search/ProductSearchResults.vue +458 -0
  171. package/templates/app/components/orionplace/search/SearchFilters.vue +546 -0
  172. package/templates/app/components/orionplace/search/examples/MainSearchExample.vue +6 -0
  173. package/templates/app/components/orionplace/sellers/SellerFilters.README.md +32 -0
  174. package/templates/app/components/orionplace/sellers/SellerFilters.vue +317 -0
  175. package/templates/app/components/orionplace/sellers/SellerPhotoGallery.README.md +45 -0
  176. package/templates/app/components/orionplace/sellers/SellerPhotoGallery.vue +406 -0
  177. package/templates/app/components/orionplace/sellers/SellerSummary.README.md +33 -0
  178. package/templates/app/components/orionplace/sellers/SellerSummary.vue +162 -0
  179. package/templates/app/components/orionplace/sellers/StorefrontSellers.README.md +73 -0
  180. package/templates/app/components/orionplace/sellers/StorefrontSellers.vue +300 -0
  181. package/templates/app/components/orionplace/shared/OrionplaceAvatar.README.md +30 -0
  182. package/templates/app/components/orionplace/shared/OrionplaceAvatar.vue +83 -0
  183. package/templates/app/components/orionplace/shared/OrionplaceBreadcrumbs.README.md +65 -0
  184. package/templates/app/components/orionplace/shared/OrionplaceBreadcrumbs.vue +118 -0
  185. package/templates/app/components/orionplace/shared/OrionplaceEmptyState.README.md +38 -0
  186. package/templates/app/components/orionplace/shared/OrionplaceEmptyState.vue +143 -0
  187. package/templates/app/components/orionplace/shared/OrionplaceImage.vue +84 -0
  188. package/templates/app/components/orionplace/shared/OrionplaceInfoHint.README.md +32 -0
  189. package/templates/app/components/orionplace/shared/OrionplaceInfoHint.vue +158 -0
  190. package/templates/app/components/orionplace/shared/OrionplacePasswordInput.README.md +30 -0
  191. package/templates/app/components/orionplace/shared/OrionplacePasswordInput.vue +197 -0
  192. package/templates/app/components/orionplace/shared/OrionplaceSearchSelect.README.md +38 -0
  193. package/templates/app/components/orionplace/shared/OrionplaceSearchSelect.vue +411 -0
  194. package/templates/app/components/orionplace/shared/OrionplaceSelect.README.md +31 -0
  195. package/templates/app/components/orionplace/shared/OrionplaceSelect.vue +525 -0
  196. package/templates/app/components/orionplace/shared/StorefrontErrorPage.README.md +55 -0
  197. package/templates/app/components/orionplace/shared/StorefrontErrorPage.vue +151 -0
  198. package/templates/app/components/orionplace/shared/StorefrontPagination.README.md +45 -0
  199. package/templates/app/components/orionplace/shared/StorefrontPagination.vue +101 -0
  200. package/templates/app/components/orionplace/shared/dialogs.css +36 -0
  201. package/templates/app/components/orionplace/shared/features.css +364 -0
  202. package/templates/app/components/orionplace/social/SocialLinks.vue +72 -0
  203. package/templates/app/components/orionplace/social/examples/SocialLinksExample.vue +6 -0
  204. package/templates/app/components/orionplace/storefront/StorefrontAccount.README.md +47 -0
  205. package/templates/app/components/orionplace/storefront/StorefrontAccount.vue +332 -0
  206. package/templates/app/components/orionplace/storefront/StorefrontCartButton.vue +68 -0
  207. package/templates/app/components/orionplace/storefront/StorefrontFooter.README.md +26 -0
  208. package/templates/app/components/orionplace/storefront/StorefrontFooter.vue +222 -0
  209. package/templates/app/components/orionplace/storefront/StorefrontHeader.README.md +93 -0
  210. package/templates/app/components/orionplace/storefront/StorefrontHeader.vue +509 -0
  211. package/templates/app/components/orionplace/storefront/StorefrontHome.README.md +79 -0
  212. package/templates/app/components/orionplace/storefront/StorefrontHome.vue +315 -0
  213. package/templates/app/components/orionplace/storefront/StorefrontWishlistButton.vue +105 -0
  214. package/templates/app/components/orionplace/storefront/examples/StorefrontAccountExample.vue +7 -0
  215. package/templates/app/components/orionplace/stores/StorefrontStores.README.md +41 -0
  216. package/templates/app/components/orionplace/stores/StorefrontStores.vue +345 -0
  217. package/templates/app/components/orionplace/subscriptions/StorefrontSubscriptions.README.md +151 -0
  218. package/templates/app/components/orionplace/subscriptions/StorefrontSubscriptions.vue +851 -0
  219. package/templates/app/components/orionplace/subscriptions/StorefrontTariff.README.md +38 -0
  220. package/templates/app/components/orionplace/subscriptions/StorefrontTariff.vue +535 -0
  221. package/templates/app/components/orionplace/subscriptions/StorefrontTariffs.README.md +36 -0
  222. package/templates/app/components/orionplace/subscriptions/StorefrontTariffs.vue +395 -0
  223. package/templates/app/components/orionplace/subscriptions/SubscriptionCancelDialog.README.md +39 -0
  224. package/templates/app/components/orionplace/subscriptions/SubscriptionCancelDialog.vue +292 -0
  225. package/templates/app/components/orionplace/subscriptions/SubscriptionChangeDialog.README.md +85 -0
  226. package/templates/app/components/orionplace/subscriptions/SubscriptionChangeDialog.vue +874 -0
  227. package/templates/app/components/orionplace/subscriptions/SubscriptionExtendDialog.README.md +53 -0
  228. package/templates/app/components/orionplace/subscriptions/SubscriptionExtendDialog.vue +536 -0
  229. package/templates/app/components/orionplace/subscriptions/SubscriptionPlanSummary.README.md +101 -0
  230. package/templates/app/components/orionplace/subscriptions/SubscriptionPlanSummary.vue +286 -0
  231. package/templates/app/components/orionplace/subscriptions/SubscriptionRemoteDetails.README.md +138 -0
  232. package/templates/app/components/orionplace/subscriptions/SubscriptionRemoteDetails.vue +134 -0
  233. package/templates/app/components/orionplace/subscriptions/SubscriptionRenewalDialog.README.md +85 -0
  234. package/templates/app/components/orionplace/subscriptions/SubscriptionRenewalDialog.vue +364 -0
  235. package/templates/app/components/orionplace/support/StorefrontSupport.README.md +39 -0
  236. package/templates/app/components/orionplace/support/StorefrontSupport.vue +484 -0
  237. package/templates/app/components/orionplace/support/TicketConversation.README.md +38 -0
  238. package/templates/app/components/orionplace/support/TicketConversation.vue +524 -0
  239. package/templates/app/components/orionplace/support/TicketImage.README.md +27 -0
  240. package/templates/app/components/orionplace/support/TicketImage.vue +186 -0
  241. package/templates/app/components/orionplace/support/TicketItemCard.README.md +59 -0
  242. package/templates/app/components/orionplace/support/TicketItemCard.vue +177 -0
  243. package/templates/app/components/orionplace/support/TicketMessageForm.README.md +35 -0
  244. package/templates/app/components/orionplace/support/TicketMessageForm.vue +258 -0
  245. package/templates/app/components/orionplace/support/TicketSubscriptionCard.README.md +40 -0
  246. package/templates/app/components/orionplace/support/TicketSubscriptionCard.vue +154 -0
  247. package/templates/app/components/orionplace/tariffs/TariffCard.README.md +12 -0
  248. package/templates/app/components/orionplace/tariffs/TariffCard.vue +241 -0
  249. package/templates/app/components/orionplace/tariffs/TariffCardDescription.README.md +12 -0
  250. package/templates/app/components/orionplace/tariffs/TariffCardDescription.vue +97 -0
  251. package/templates/app/components/orionplace/tariffs/TariffCardFeatures.README.md +14 -0
  252. package/templates/app/components/orionplace/tariffs/TariffCardFeatures.vue +172 -0
  253. package/templates/app/components/orionplace/tariffs/TariffCardImage.README.md +12 -0
  254. package/templates/app/components/orionplace/tariffs/TariffCardImage.vue +33 -0
  255. package/templates/app/components/orionplace/tariffs/TariffCardPrices.README.md +12 -0
  256. package/templates/app/components/orionplace/tariffs/TariffCardPrices.vue +280 -0
  257. package/templates/app/components/orionplace/tariffs/TariffCardTitle.README.md +12 -0
  258. package/templates/app/components/orionplace/tariffs/TariffCardTitle.vue +30 -0
  259. package/templates/app/components/orionplace/tariffs/TariffCards.README.md +12 -0
  260. package/templates/app/components/orionplace/tariffs/TariffCards.vue +94 -0
  261. package/templates/app/components/orionplace/tariffs/TariffSubscriptionModal.README.md +31 -0
  262. package/templates/app/components/orionplace/tariffs/TariffSubscriptionModal.vue +411 -0
  263. package/templates/app/components/orionplace/tariffs/examples/TariffCardDescriptionExample.vue +13 -0
  264. package/templates/app/components/orionplace/tariffs/examples/TariffCardExample.vue +13 -0
  265. package/templates/app/components/orionplace/tariffs/examples/TariffCardFeaturesExample.vue +14 -0
  266. package/templates/app/components/orionplace/tariffs/examples/TariffCardImageExample.vue +13 -0
  267. package/templates/app/components/orionplace/tariffs/examples/TariffCardPricesExample.vue +13 -0
  268. package/templates/app/components/orionplace/tariffs/examples/TariffCardTitleExample.vue +13 -0
  269. package/templates/app/components/orionplace/tariffs/examples/TariffCardsExample.vue +6 -0
  270. package/templates/app/components/orionplace/theme/OrionplaceThemeProvider.vue +38 -0
  271. package/templates/app/components/orionplace/units/UnitSwitcher.vue +71 -0
  272. package/templates/app/components/orionplace/units/examples/LengthExample.vue +6 -0
  273. package/templates/app/components/orionplace/units/examples/WeightExample.vue +6 -0
  274. package/templates/app/components/orionplace/wallet/StorefrontWallet.README.md +117 -0
  275. package/templates/app/components/orionplace/wallet/StorefrontWallet.vue +863 -0
  276. package/templates/app/components/orionplace/wallet/WalletBalance.vue +47 -0
  277. package/templates/app/components/orionplace/wallet/WalletTopUpForm.README.md +32 -0
  278. package/templates/app/components/orionplace/wallet/WalletTopUpForm.vue +224 -0
  279. package/templates/app/components/orionplace/wallet/examples/WalletExample.vue +6 -0
  280. package/templates/app/composables/useOrionplaceActionMenu.ts +126 -0
  281. package/templates/app/composables/useOrionplaceAddressEditor.ts +343 -0
  282. package/templates/app/composables/useOrionplaceAddresses.ts +75 -0
  283. package/templates/app/composables/useOrionplaceApi.ts +174 -0
  284. package/templates/app/composables/useOrionplaceAppLoad.ts +74 -0
  285. package/templates/app/composables/useOrionplaceBlogComments.ts +325 -0
  286. package/templates/app/composables/useOrionplaceBlogReading.ts +270 -0
  287. package/templates/app/composables/useOrionplaceCart.ts +226 -0
  288. package/templates/app/composables/useOrionplaceCartPreview.ts +142 -0
  289. package/templates/app/composables/useOrionplaceCategoryLink.ts +24 -0
  290. package/templates/app/composables/useOrionplaceCategoryProducts.ts +16 -0
  291. package/templates/app/composables/useOrionplaceFeature.ts +100 -0
  292. package/templates/app/composables/useOrionplaceFeaturedProducts.ts +14 -0
  293. package/templates/app/composables/useOrionplaceGeolocation.ts +28 -0
  294. package/templates/app/composables/useOrionplaceHomeProducts.ts +90 -0
  295. package/templates/app/composables/useOrionplaceManufacturerIndex.ts +83 -0
  296. package/templates/app/composables/useOrionplaceMap.ts +240 -0
  297. package/templates/app/composables/useOrionplaceMediaFormat.ts +24 -0
  298. package/templates/app/composables/useOrionplaceMissingPage.ts +67 -0
  299. package/templates/app/composables/useOrionplaceOrders.ts +185 -0
  300. package/templates/app/composables/useOrionplacePageSeo.ts +38 -0
  301. package/templates/app/composables/useOrionplaceProductActions.ts +116 -0
  302. package/templates/app/composables/useOrionplaceProductLink.ts +24 -0
  303. package/templates/app/composables/useOrionplaceProductSearch.ts +259 -0
  304. package/templates/app/composables/useOrionplaceProductVariants.ts +176 -0
  305. package/templates/app/composables/useOrionplaceProfile.ts +309 -0
  306. package/templates/app/composables/useOrionplaceProgress.ts +89 -0
  307. package/templates/app/composables/useOrionplaceReviews.ts +242 -0
  308. package/templates/app/composables/useOrionplaceSearchHistory.ts +23 -0
  309. package/templates/app/composables/useOrionplaceSearchScopeNames.ts +99 -0
  310. package/templates/app/composables/useOrionplaceServerData.ts +72 -0
  311. package/templates/app/composables/useOrionplaceSignIn.ts +66 -0
  312. package/templates/app/composables/useOrionplaceStableHeight.ts +69 -0
  313. package/templates/app/composables/useOrionplaceStorefront.ts +29 -0
  314. package/templates/app/composables/useOrionplaceSubscriptions.ts +217 -0
  315. package/templates/app/composables/useOrionplaceTheme.ts +27 -0
  316. package/templates/app/composables/useOrionplaceTicketSubject.ts +180 -0
  317. package/templates/app/composables/useOrionplaceTickets.ts +335 -0
  318. package/templates/app/composables/useOrionplaceWallet.ts +166 -0
  319. package/templates/app/error.vue +108 -0
  320. package/templates/app/interfaces/orionplace/accounts/IContact.ts +21 -0
  321. package/templates/app/interfaces/orionplace/accounts/IEmailNotificationLocale.ts +17 -0
  322. package/templates/app/interfaces/orionplace/accounts/IEmailVerification.ts +59 -0
  323. package/templates/app/interfaces/orionplace/accounts/IProfileActions.ts +38 -0
  324. package/templates/app/interfaces/orionplace/accounts/IProfileData.ts +123 -0
  325. package/templates/app/interfaces/orionplace/accounts/IProfileMedia.ts +17 -0
  326. package/templates/app/interfaces/orionplace/accounts/IStorefrontProfile.ts +54 -0
  327. package/templates/app/interfaces/orionplace/address/IAddressCitySuggestion.ts +19 -0
  328. package/templates/app/interfaces/orionplace/address/IAddressEditor.ts +9 -0
  329. package/templates/app/interfaces/orionplace/address/IAddressLocationSuggestion.ts +22 -0
  330. package/templates/app/interfaces/orionplace/address/IAddressRegionSearch.ts +30 -0
  331. package/templates/app/interfaces/orionplace/address/IAddressSuggestion.ts +20 -0
  332. package/templates/app/interfaces/orionplace/address/IUserAddress.ts +87 -0
  333. package/templates/app/interfaces/orionplace/apiBase/TMethod.ts +1 -0
  334. package/templates/app/interfaces/orionplace/appBase/IAppLoad.ts +16 -0
  335. package/templates/app/interfaces/orionplace/appBase/IAppLoadCommon.ts +45 -0
  336. package/templates/app/interfaces/orionplace/appBase/IApploadUserProfile.ts +13 -0
  337. package/templates/app/interfaces/orionplace/appBase/IForm.ts +21 -0
  338. package/templates/app/interfaces/orionplace/appBase/ISEO.ts +21 -0
  339. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonBanner.ts +11 -0
  340. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonContact.ts +8 -0
  341. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonCurrency.ts +15 -0
  342. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonEvents.ts +18 -0
  343. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonLocale.ts +14 -0
  344. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonLogos.ts +6 -0
  345. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonPath.ts +22 -0
  346. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonSEO.ts +26 -0
  347. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonSocial.ts +15 -0
  348. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonTariff.ts +7 -0
  349. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonUnit.ts +12 -0
  350. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonVariables.ts +8 -0
  351. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonVisualSettings.ts +11 -0
  352. package/templates/app/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonWalletValue.ts +3 -0
  353. package/templates/app/interfaces/orionplace/blog/IBlogApi.ts +247 -0
  354. package/templates/app/interfaces/orionplace/blog/IBlogPostPreview.ts +30 -0
  355. package/templates/app/interfaces/orionplace/cart/ICartActions.ts +67 -0
  356. package/templates/app/interfaces/orionplace/cart/ICartData.ts +382 -0
  357. package/templates/app/interfaces/orionplace/cart/ICartDeliveryActions.ts +68 -0
  358. package/templates/app/interfaces/orionplace/cart/ICartModal.ts +22 -0
  359. package/templates/app/interfaces/orionplace/cart/IDeliveryMap.ts +29 -0
  360. package/templates/app/interfaces/orionplace/catalog/ICatalogDirectory.ts +75 -0
  361. package/templates/app/interfaces/orionplace/category/ICategory.ts +41 -0
  362. package/templates/app/interfaces/orionplace/domains/IDomain.ts +13 -0
  363. package/templates/app/interfaces/orionplace/forms/ICustomerSubfilter.ts +19 -0
  364. package/templates/app/interfaces/orionplace/index.ts +57 -0
  365. package/templates/app/interfaces/orionplace/marketing/IPromoActions.ts +51 -0
  366. package/templates/app/interfaces/orionplace/orders/IOrderActions.ts +99 -0
  367. package/templates/app/interfaces/orionplace/orders/IOrderHistory.ts +259 -0
  368. package/templates/app/interfaces/orionplace/orders/IProductPreorder.ts +31 -0
  369. package/templates/app/interfaces/orionplace/payments/IInvoice.ts +147 -0
  370. package/templates/app/interfaces/orionplace/products/IProduct.ts +262 -0
  371. package/templates/app/interfaces/orionplace/products/IProductFeedbackApi.ts +218 -0
  372. package/templates/app/interfaces/orionplace/products/IProductSearchApi.ts +146 -0
  373. package/templates/app/interfaces/orionplace/products/IProductSearchFacets.ts +35 -0
  374. package/templates/app/interfaces/orionplace/products/IProductSecondaryVariantRequest.ts +15 -0
  375. package/templates/app/interfaces/orionplace/products/IProductSpecification.ts +14 -0
  376. package/templates/app/interfaces/orionplace/products/IWishlist.ts +22 -0
  377. package/templates/app/interfaces/orionplace/sellers/ISellerDirectory.ts +70 -0
  378. package/templates/app/interfaces/orionplace/shared/IBreadcrumb.ts +10 -0
  379. package/templates/app/interfaces/orionplace/shared/IGeoCoordinates.ts +4 -0
  380. package/templates/app/interfaces/orionplace/shared/IStorefrontControls.ts +13 -0
  381. package/templates/app/interfaces/orionplace/shared/ITransformValue.ts +3 -0
  382. package/templates/app/interfaces/orionplace/state.ts +4 -0
  383. package/templates/app/interfaces/orionplace/stores/IStoreDirectory.ts +63 -0
  384. package/templates/app/interfaces/orionplace/subscribeOptions/ISubscribeOption.ts +9 -0
  385. package/templates/app/interfaces/orionplace/subscribeTariff/ISubscribeTariff.ts +56 -0
  386. package/templates/app/interfaces/orionplace/subscribeTariff/ITariffSelection.ts +11 -0
  387. package/templates/app/interfaces/orionplace/subscribes/ISubscribe.ts +28 -0
  388. package/templates/app/interfaces/orionplace/subscribes/ISubscriptionApi.ts +125 -0
  389. package/templates/app/interfaces/orionplace/tickets/ICustomerTicketApi.ts +223 -0
  390. package/templates/app/interfaces/orionplace/transport.ts +34 -0
  391. package/templates/app/layouts/default.vue +376 -0
  392. package/templates/app/middleware/00.orionplace.global.ts +27 -0
  393. package/templates/app/middleware/01.orionplace-sellers.global.ts +15 -0
  394. package/templates/app/middleware/orionplace-account.ts +40 -0
  395. package/templates/app/pages/activity.vue +19 -0
  396. package/templates/app/pages/addresses.vue +23 -0
  397. package/templates/app/pages/browse.vue +246 -0
  398. package/templates/app/pages/cart.vue +20 -0
  399. package/templates/app/pages/catalog.vue +17 -0
  400. package/templates/app/pages/category/[id].vue +142 -0
  401. package/templates/app/pages/contact.vue +17 -0
  402. package/templates/app/pages/featured.vue +144 -0
  403. package/templates/app/pages/index.vue +194 -0
  404. package/templates/app/pages/journal/[id].vue +128 -0
  405. package/templates/app/pages/journal/index.vue +67 -0
  406. package/templates/app/pages/logout.vue +71 -0
  407. package/templates/app/pages/manufacturers.vue +33 -0
  408. package/templates/app/pages/orders.vue +40 -0
  409. package/templates/app/pages/product/[id].vue +126 -0
  410. package/templates/app/pages/profile.vue +118 -0
  411. package/templates/app/pages/promo/[id].vue +67 -0
  412. package/templates/app/pages/promocodes.vue +21 -0
  413. package/templates/app/pages/sellers.vue +203 -0
  414. package/templates/app/pages/stores.vue +36 -0
  415. package/templates/app/pages/subscriptions.vue +21 -0
  416. package/templates/app/pages/tariffs/[slug]/[id].vue +126 -0
  417. package/templates/app/pages/tariffs/index.vue +50 -0
  418. package/templates/app/pages/tickets.vue +56 -0
  419. package/templates/app/pages/unsubscribe.vue +32 -0
  420. package/templates/app/pages/wallet.vue +23 -0
  421. package/templates/app/pages/wishlist.vue +48 -0
  422. package/templates/app/stores/orionplace.ts +493 -0
  423. package/templates/app/stores/orionplaceBrowse.ts +79 -0
  424. package/templates/app/stores/orionplaceCatalog.ts +121 -0
  425. package/templates/app/stores/orionplaceDomainAccess.ts +55 -0
  426. package/templates/app/stores/orionplaceProducts.ts +249 -0
  427. package/templates/app/stores/orionplaceSelections.ts +132 -0
  428. package/templates/app/themes/orionplace.ts +108 -0
  429. package/templates/app/utils/orionplace/accountLabels.ts +22 -0
  430. package/templates/app/utils/orionplace/activityLabels.ts +65 -0
  431. package/templates/app/utils/orionplace/activityPresentation.ts +16 -0
  432. package/templates/app/utils/orionplace/addressChanges.ts +26 -0
  433. package/templates/app/utils/orionplace/addressRegions.ts +17 -0
  434. package/templates/app/utils/orionplace/api.ts +333 -0
  435. package/templates/app/utils/orionplace/blogArticleHtml.ts +318 -0
  436. package/templates/app/utils/orionplace/blogComments.ts +133 -0
  437. package/templates/app/utils/orionplace/blogLabels.ts +111 -0
  438. package/templates/app/utils/orionplace/blogLayout.ts +95 -0
  439. package/templates/app/utils/orionplace/breadcrumbLabels.ts +11 -0
  440. package/templates/app/utils/orionplace/browseLabels.ts +98 -0
  441. package/templates/app/utils/orionplace/cartAddress.ts +94 -0
  442. package/templates/app/utils/orionplace/cartLabels.ts +261 -0
  443. package/templates/app/utils/orionplace/cartOptions.ts +143 -0
  444. package/templates/app/utils/orionplace/cartPreview.ts +108 -0
  445. package/templates/app/utils/orionplace/cartPromo.ts +150 -0
  446. package/templates/app/utils/orionplace/cartShipment.ts +74 -0
  447. package/templates/app/utils/orionplace/cartSnapshot.ts +20 -0
  448. package/templates/app/utils/orionplace/catalog.ts +106 -0
  449. package/templates/app/utils/orionplace/category.ts +52 -0
  450. package/templates/app/utils/orionplace/categoryLabels.ts +31 -0
  451. package/templates/app/utils/orionplace/contactLabels.ts +102 -0
  452. package/templates/app/utils/orionplace/currency.ts +128 -0
  453. package/templates/app/utils/orionplace/deliveryMap.ts +89 -0
  454. package/templates/app/utils/orionplace/directoryLabels.ts +131 -0
  455. package/templates/app/utils/orionplace/emptyStateArt.ts +231 -0
  456. package/templates/app/utils/orionplace/errorPageLabels.ts +80 -0
  457. package/templates/app/utils/orionplace/featureData.ts +25 -0
  458. package/templates/app/utils/orionplace/featureLabels.ts +271 -0
  459. package/templates/app/utils/orionplace/featuredLabels.ts +28 -0
  460. package/templates/app/utils/orionplace/files.ts +71 -0
  461. package/templates/app/utils/orionplace/footerLabels.ts +35 -0
  462. package/templates/app/utils/orionplace/guestSession.ts +50 -0
  463. package/templates/app/utils/orionplace/headerLabels.ts +68 -0
  464. package/templates/app/utils/orionplace/homeContent.ts +129 -0
  465. package/templates/app/utils/orionplace/homeLabels.ts +52 -0
  466. package/templates/app/utils/orionplace/htmlText.ts +59 -0
  467. package/templates/app/utils/orionplace/links.ts +14 -0
  468. package/templates/app/utils/orionplace/manufacturerIndex.ts +91 -0
  469. package/templates/app/utils/orionplace/modalWindow.ts +109 -0
  470. package/templates/app/utils/orionplace/nativeApp.ts +361 -0
  471. package/templates/app/utils/orionplace/notice.ts +22 -0
  472. package/templates/app/utils/orionplace/orderLabels.ts +309 -0
  473. package/templates/app/utils/orionplace/orderPresentation.ts +586 -0
  474. package/templates/app/utils/orionplace/pageSeo.ts +274 -0
  475. package/templates/app/utils/orionplace/paginationScroll.ts +131 -0
  476. package/templates/app/utils/orionplace/phone.ts +22 -0
  477. package/templates/app/utils/orionplace/presentation.ts +72 -0
  478. package/templates/app/utils/orionplace/productActionLabels.ts +60 -0
  479. package/templates/app/utils/orionplace/productActions.ts +547 -0
  480. package/templates/app/utils/orionplace/productAvailability.ts +36 -0
  481. package/templates/app/utils/orionplace/productGallery.ts +72 -0
  482. package/templates/app/utils/orionplace/productLabels.ts +82 -0
  483. package/templates/app/utils/orionplace/productManufacturer.ts +30 -0
  484. package/templates/app/utils/orionplace/productPage.ts +46 -0
  485. package/templates/app/utils/orionplace/productPhotos.ts +67 -0
  486. package/templates/app/utils/orionplace/productSearchScope.ts +237 -0
  487. package/templates/app/utils/orionplace/productSeller.ts +51 -0
  488. package/templates/app/utils/orionplace/profile.ts +136 -0
  489. package/templates/app/utils/orionplace/profileLabels.ts +151 -0
  490. package/templates/app/utils/orionplace/promoLabels.ts +75 -0
  491. package/templates/app/utils/orionplace/promoPresentation.ts +381 -0
  492. package/templates/app/utils/orionplace/reviewLabels.ts +172 -0
  493. package/templates/app/utils/orionplace/reviewScope.ts +41 -0
  494. package/templates/app/utils/orionplace/richText.ts +13 -0
  495. package/templates/app/utils/orionplace/searchFilters.ts +99 -0
  496. package/templates/app/utils/orionplace/searchHistory.ts +144 -0
  497. package/templates/app/utils/orionplace/sellerDirectory.ts +134 -0
  498. package/templates/app/utils/orionplace/seo.ts +52 -0
  499. package/templates/app/utils/orionplace/serverCookies.ts +88 -0
  500. package/templates/app/utils/orionplace/sessionLabels.ts +27 -0
  501. package/templates/app/utils/orionplace/signInReturn.ts +89 -0
  502. package/templates/app/utils/orionplace/storeDirectory.ts +50 -0
  503. package/templates/app/utils/orionplace/subscriptionChanges.ts +167 -0
  504. package/templates/app/utils/orionplace/subscriptionLabels.ts +67 -0
  505. package/templates/app/utils/orionplace/subscriptionManageLabels.ts +307 -0
  506. package/templates/app/utils/orionplace/subscriptionPlans.ts +162 -0
  507. package/templates/app/utils/orionplace/subscriptionRemote.ts +110 -0
  508. package/templates/app/utils/orionplace/subscriptionUsage.ts +82 -0
  509. package/templates/app/utils/orionplace/tariffLabels.ts +130 -0
  510. package/templates/app/utils/orionplace/tariffPage.ts +77 -0
  511. package/templates/app/utils/orionplace/tariffVariables.ts +165 -0
  512. package/templates/app/utils/orionplace/tariffs.ts +284 -0
  513. package/templates/app/utils/orionplace/ticketItems.ts +87 -0
  514. package/templates/app/utils/orionplace/ticketLabels.ts +335 -0
  515. package/templates/app/utils/orionplace/ticketLocation.ts +79 -0
  516. package/templates/app/utils/orionplace/walletTransaction.ts +135 -0
  517. package/templates/app/utils/orionplaceAppLoad.ts +73 -0
  518. package/templates/orionplace/COMPONENT-DOWNLOAD.md +40 -0
  519. package/templates/orionplace/COMPONENTS.md +1983 -0
  520. package/templates/orionplace/THEMES.md +94 -0
@@ -0,0 +1,874 @@
1
+ <script setup lang="ts">
2
+ import '@/components/orionplace/shared/dialogs.css';
3
+ import {
4
+ computed,
5
+ nextTick,
6
+ onBeforeUnmount,
7
+ onMounted,
8
+ ref,
9
+ useId,
10
+ watch,
11
+ } from 'vue';
12
+ import { useOrionplaceStore } from '@/stores/orionplace';
13
+ import { useOrionplaceCatalogStore } from '@/stores/orionplaceCatalog';
14
+ import { useOrionplaceSelectionsStore } from '@/stores/orionplaceSelections';
15
+ import { tariffMoney } from '@/utils/orionplace/tariffs';
16
+ import { getAvailableNestedValueFromObject } from '@/utils/orionplace/presentation';
17
+ import {
18
+ subscriptionChangeIsAboveBalance,
19
+ subscriptionChangePeriods,
20
+ subscriptionChangeTotal,
21
+ subscriptionOptionChoices,
22
+ subscriptionPlanChoices,
23
+ subscriptionRefundAmount,
24
+ } from '@/utils/orionplace/subscriptionChanges';
25
+ import {
26
+ subscriptionDays,
27
+ subscriptionManageLabels,
28
+ } from '@/utils/orionplace/subscriptionManageLabels';
29
+ import {
30
+ createPageScrollLock,
31
+ focusedElement,
32
+ restoreFocus,
33
+ } from '@/utils/orionplace/modalWindow';
34
+ import type {
35
+ ISubscribeTariff,
36
+ ISubscribeTariffOption,
37
+ } from '@/interfaces/orionplace/subscribeTariff/ISubscribeTariff';
38
+ import type {
39
+ ICustomerSubscription,
40
+ ISubscriptionChangeRequest,
41
+ } from '@/interfaces/orionplace/subscribes/ISubscriptionApi';
42
+ import '@/components/orionplace/shared/features.css';
43
+ import OrionplaceSelect from '@/components/orionplace/shared/OrionplaceSelect.vue';
44
+ import SubscriptionPlanSummary from '@/components/orionplace/subscriptions/SubscriptionPlanSummary.vue';
45
+ import OrionplaceInfoHint from '@/components/orionplace/shared/OrionplaceInfoHint.vue';
46
+
47
+ const props = withDefaults(
48
+ defineProps<{
49
+ subscription?: ICustomerSubscription;
50
+ mode?: 'plan' | 'option';
51
+ plan?: ISubscribeTariff;
52
+ pending?: boolean;
53
+ error?: string;
54
+ fields?: Record<string, string>;
55
+ modal?: boolean;
56
+ }>(),
57
+ {
58
+ mode: 'plan',
59
+ pending: false,
60
+ error: '',
61
+ fields: () => ({}),
62
+ modal: true,
63
+ },
64
+ );
65
+ const emit = defineEmits<{
66
+ submit: [request: ISubscriptionChangeRequest];
67
+ close: [];
68
+ }>();
69
+ const store = useOrionplaceStore();
70
+ const catalogStore = useOrionplaceCatalogStore();
71
+ const selectionStore = useOrionplaceSelectionsStore();
72
+ const id = useId();
73
+ const dialog = ref<HTMLDialogElement>();
74
+ const planChoice = ref('');
75
+ const optionChoice = ref('');
76
+ const period = ref<number>();
77
+ const renewalChoice = ref('');
78
+ const promo = ref('');
79
+ const confirming = ref(false);
80
+ const copy = computed(() =>
81
+ subscriptionManageLabels(selectionStore.localeCode),
82
+ );
83
+ const changingPlan = computed(() => props.mode === 'plan');
84
+
85
+ /*
86
+ * Application Load carries the plans of the storefront with their paid
87
+ * periods and the price of every service option for each period, so the
88
+ * dialog offers the same pairs the backend accepts and shows the amounts
89
+ * the backend returned for them.
90
+ */
91
+ const plans = computed(() => {
92
+ const subscription = props.subscription;
93
+
94
+ if (!subscription || !changingPlan.value) {
95
+ return [];
96
+ }
97
+
98
+ return subscriptionPlanChoices(
99
+ subscription,
100
+ catalogStore.storeTariffs?.data ?? [],
101
+ catalogStore.storeTariffs?.subscriptions ?? [],
102
+ );
103
+ });
104
+ const targetPlan = computed(() => {
105
+ if (!changingPlan.value) {
106
+ return props.plan;
107
+ }
108
+
109
+ return plans.value.find((item) => String(item.id) === planChoice.value);
110
+ });
111
+ const options = computed(() =>
112
+ subscriptionOptionChoices(targetPlan.value),
113
+ );
114
+ const targetOption = computed(() =>
115
+ options.value.find((item) => String(item.id) === optionChoice.value),
116
+ );
117
+ const periods = computed(() =>
118
+ subscriptionChangePeriods(
119
+ targetPlan.value,
120
+ targetOption.value,
121
+ selectionStore.currencyId,
122
+ ).map((choice) => ({
123
+ ...choice,
124
+ length: subscriptionDays(choice.days, selectionStore.localeCode),
125
+ price: money(choice.amount),
126
+ })),
127
+ );
128
+ const chosen = computed(() =>
129
+ periods.value.find((choice) => choice.id === period.value),
130
+ );
131
+ /*
132
+ * A list with one entry is not a choice: a plan change keeps the plan's
133
+ * only option and a single period is selected without showing the list.
134
+ * An option change always lists the options, because choosing one is the
135
+ * purpose of the dialog.
136
+ */
137
+ const showOptions = computed(
138
+ () => options.value.length > (changingPlan.value ? 1 : 0),
139
+ );
140
+ const showPeriods = computed(() => periods.value.length > 1);
141
+ const planOptions = computed(() => {
142
+ const entries: Record<string, string> = {};
143
+
144
+ for (const item of plans.value) {
145
+ entries[String(item.id)] = planName(item);
146
+ }
147
+
148
+ return entries;
149
+ });
150
+ const optionOptions = computed(() => {
151
+ const entries: Record<string, string> = {};
152
+
153
+ for (const item of options.value) {
154
+ entries[String(item.id)] = optionName(item);
155
+ }
156
+
157
+ return entries;
158
+ });
159
+ const renewOptions = computed(() => {
160
+ const entries: Record<string, string> = { '': copy.value.renewalOff };
161
+
162
+ for (const choice of periods.value) {
163
+ entries[String(choice.id)] = `${choice.length} · ${choice.price}`;
164
+ }
165
+
166
+ return entries;
167
+ });
168
+ const renewal = computed(() =>
169
+ periods.value.find((choice) => String(choice.id) === renewalChoice.value),
170
+ );
171
+ const currentPlan = computed(() =>
172
+ copy.value.changeCurrentPlan.replace('{plan}', planName(props.plan)),
173
+ );
174
+ const currentOption = computed(() => {
175
+ const current = options.value.find(
176
+ (item) => item.id === props.subscription?.option,
177
+ );
178
+
179
+ return copy.value.changeCurrentOption.replace(
180
+ '{option}',
181
+ current ? optionName(current) : copy.value.changeNoOption,
182
+ );
183
+ });
184
+ const balance = computed(
185
+ () => store.init?.wallet?.[selectionStore.currencyId]?.transform_value,
186
+ );
187
+ /*
188
+ * The refund for the unused days arrives with the subscription itself in
189
+ * `returned_amount`, so the dialog shows the amount the storefront backend
190
+ * will credit and counts it towards what this change can cost. A response
191
+ * without the field leaves the refund unknown.
192
+ */
193
+ const refund = computed(() =>
194
+ subscriptionRefundAmount(props.subscription, selectionStore.currencyId),
195
+ );
196
+ const available = computed(() => {
197
+ if (balance.value === undefined || refund.value === undefined) {
198
+ return undefined;
199
+ }
200
+
201
+ return balance.value + refund.value;
202
+ });
203
+ const low = computed(() =>
204
+ subscriptionChangeIsAboveBalance(
205
+ chosen.value,
206
+ balance.value,
207
+ refund.value,
208
+ ),
209
+ );
210
+ const lowNotice = computed(() =>
211
+ refund.value === undefined
212
+ ? copy.value.changeInsufficient
213
+ : copy.value.changeShort,
214
+ );
215
+ const unavailable = computed(() => {
216
+ if (changingPlan.value && !plans.value.length) {
217
+ return copy.value.changeNoPlans;
218
+ }
219
+ if (!changingPlan.value && !options.value.length) {
220
+ return copy.value.changeNoOptions;
221
+ }
222
+ if (targetPlan.value && !periods.value.length) {
223
+ return copy.value.changeNoPeriods;
224
+ }
225
+
226
+ return '';
227
+ });
228
+ const after = computed(() => {
229
+ const known = refund.value !== undefined;
230
+ const forPlan = known
231
+ ? copy.value.changeAfterPlanRefund
232
+ : copy.value.changeAfterPlan;
233
+ const forOption = known
234
+ ? copy.value.changeAfterOptionRefund
235
+ : copy.value.changeAfterOption;
236
+ const template = changingPlan.value ? forPlan : forOption;
237
+
238
+ return template
239
+ .replace('{plan}', planName(targetPlan.value))
240
+ .replace(
241
+ '{option}',
242
+ targetOption.value
243
+ ? optionName(targetOption.value)
244
+ : copy.value.changeNoOption,
245
+ )
246
+ .replace('{period}', chosen.value?.length || '—')
247
+ .replace('{refund}', money(refund.value))
248
+ .replace('{price}', money(subscriptionChangeTotal(chosen.value)));
249
+ });
250
+ const renewalNote = computed(() => {
251
+ if (!renewal.value) {
252
+ return copy.value.renewalEffectOff;
253
+ }
254
+
255
+ return copy.value.renewalEffectOn
256
+ .replace('{price}', renewal.value.price)
257
+ .replace('{days}', renewal.value.length);
258
+ });
259
+ const hasFieldError = computed(() =>
260
+ Object.entries(props.fields ?? {}).some(
261
+ ([name, message]) => name !== '__all__' && Boolean(message),
262
+ ),
263
+ );
264
+ const ready = computed(() => {
265
+ if (!props.subscription || !chosen.value) {
266
+ return false;
267
+ }
268
+ if (changingPlan.value && !targetPlan.value) {
269
+ return false;
270
+ }
271
+ /*
272
+ * The option change needs an option the subscription is not on yet: the
273
+ * backend refuses a request that repeats the current one.
274
+ */
275
+ if (!changingPlan.value) {
276
+ return Boolean(
277
+ targetOption.value &&
278
+ targetOption.value.id !== props.subscription.option,
279
+ );
280
+ }
281
+
282
+ return !(options.value.length > 0 && !targetOption.value);
283
+ });
284
+ /*
285
+ * A failure that names a field is shown beside that field. The banner then
286
+ * carries only the general message of the response, or the host's own text
287
+ * when the request did not reach the storefront backend at all.
288
+ */
289
+ const generalError = computed(
290
+ () => props.fields?.__all__ || (hasFieldError.value ? '' : props.error),
291
+ );
292
+ const submitLabel = computed(() => {
293
+ if (props.pending) {
294
+ return copy.value.changePending;
295
+ }
296
+
297
+ return confirming.value
298
+ ? copy.value.changeSubmit
299
+ : copy.value.changeConfirm;
300
+ });
301
+ let opener: HTMLElement | undefined;
302
+ const pageScroll = createPageScrollLock();
303
+
304
+ function money(amount: number | undefined) {
305
+ return tariffMoney(amount, selectionStore.localeCode, selectionStore.currentCurrency);
306
+ }
307
+ function planName(item: ISubscribeTariff | undefined) {
308
+ return (
309
+ getAvailableNestedValueFromObject(
310
+ item?.locales,
311
+ selectionStore.localeCode,
312
+ 'tariff_name',
313
+ ) || copy.value.manage
314
+ );
315
+ }
316
+ function optionName(item: ISubscribeTariffOption | undefined) {
317
+ return (
318
+ getAvailableNestedValueFromObject(
319
+ item?.locale,
320
+ selectionStore.localeCode,
321
+ 'option_name',
322
+ ) || copy.value.optionPrice
323
+ );
324
+ }
325
+ function fieldError(name: string) {
326
+ return props.fields?.[name] || '';
327
+ }
328
+ // The window is open while it has a subscription. The element with the
329
+ // focus outside the window is its opener: a modal window gives it the
330
+ // focus back when it closes. An open window that switches between the
331
+ // modal and the inline mode leaves the focus on the field the visitor is
332
+ // in.
333
+ async function syncDialog() {
334
+ await nextTick();
335
+ const element = dialog.value;
336
+
337
+ if (!element) {
338
+ return;
339
+ }
340
+ if (!props.subscription) {
341
+ element.close();
342
+ if (pageScroll.locked) {
343
+ pageScroll.unlock();
344
+ restoreFocus(opener);
345
+ }
346
+
347
+ return;
348
+ }
349
+
350
+ const switching = element.open && pageScroll.locked !== props.modal;
351
+ const focused = focusedElement();
352
+ const inside =
353
+ focused && element.contains(focused) ? focused : undefined;
354
+
355
+ if (!inside) {
356
+ opener = focused;
357
+ }
358
+ if (element.open) {
359
+ element.close();
360
+ }
361
+ if (props.modal) {
362
+ pageScroll.lock();
363
+ element.showModal();
364
+ } else {
365
+ // The page scrolls again once the window leaves the modal mode.
366
+ // Opened by its attribute, not show(): an inline dialog leaves focus
367
+ // where it is.
368
+ pageScroll.unlock();
369
+ element.setAttribute('open', '');
370
+ }
371
+ if (switching) {
372
+ restoreFocus(inside, { reveal: true });
373
+ }
374
+ }
375
+ /*
376
+ * A plan change keeps the service option the subscription runs on when the
377
+ * selected plan also sells it, so the customer only picks what is really
378
+ * changing. An option change starts on another option instead, because the
379
+ * backend refuses a request that repeats the current one.
380
+ */
381
+ function startFrom(plan: ISubscribeTariff | undefined) {
382
+ const current = props.subscription?.option;
383
+ const available = plan?.options ?? [];
384
+ const kept = available.find((item) => item.id === current);
385
+ const selected = changingPlan.value
386
+ ? kept ?? available[0]
387
+ : available.find((item) => item.id !== current) ?? available[0];
388
+
389
+ optionChoice.value = selected ? String(selected.id) : '';
390
+ }
391
+ watch(
392
+ () => [props.subscription?.id, props.mode],
393
+ () => {
394
+ const first = changingPlan.value ? plans.value[0] : props.plan;
395
+
396
+ planChoice.value = changingPlan.value && first ? String(first.id) : '';
397
+ promo.value = '';
398
+ confirming.value = false;
399
+ startFrom(first);
400
+ void syncDialog();
401
+ },
402
+ { immediate: true },
403
+ );
404
+ /*
405
+ * Changing the plan or the option changes which paid periods can be bought,
406
+ * so the period and the automatic renewal are selected again from the
407
+ * periods of the new pair instead of keeping an identifier the backend
408
+ * would refuse.
409
+ */
410
+ watch(
411
+ () => [planChoice.value, optionChoice.value],
412
+ () => {
413
+ if (changingPlan.value) {
414
+ const plan = plans.value.find(
415
+ (item) => String(item.id) === planChoice.value,
416
+ );
417
+
418
+ if (plan && !plan.options.some(
419
+ (item) => String(item.id) === optionChoice.value,
420
+ )) {
421
+ startFrom(plan);
422
+ }
423
+ }
424
+ },
425
+ );
426
+ watch(
427
+ () => periods.value.map((choice) => choice.id).join(','),
428
+ () => {
429
+ const current = props.subscription?.renew_period?.days;
430
+ const matching = periods.value.find(
431
+ (choice) => choice.days === current,
432
+ );
433
+ const preselected = matching ?? periods.value[0];
434
+
435
+ period.value = preselected?.id;
436
+ // Automatic renewal stays as it was: off stays off, on moves to the
437
+ // same length of the new plan, else to its first period.
438
+ renewalChoice.value = current && preselected ? String(preselected.id) : '';
439
+ },
440
+ { immediate: true },
441
+ );
442
+ /*
443
+ * A failure that names a field is answered in the form, not on the
444
+ * confirmation step, so the dialog steps back to the fields and shows the
445
+ * message beside the one the storefront backend refused.
446
+ */
447
+ watch(hasFieldError, (present) => {
448
+ if (present) {
449
+ confirming.value = false;
450
+ }
451
+ });
452
+ // The host can switch between the modal and the inline window while it is
453
+ // open.
454
+ watch(() => props.modal, syncDialog);
455
+ onMounted(syncDialog);
456
+ onBeforeUnmount(() => {
457
+ dialog.value?.close();
458
+ if (pageScroll.locked) {
459
+ pageScroll.unlock();
460
+ restoreFocus(opener);
461
+ }
462
+ });
463
+ function close() {
464
+ if (!props.pending) {
465
+ emit('close');
466
+ }
467
+ }
468
+ function submit() {
469
+ const subscription = props.subscription;
470
+
471
+ if (props.pending || !ready.value || !subscription || !chosen.value) {
472
+ return;
473
+ }
474
+ if (!confirming.value) {
475
+ confirming.value = true;
476
+
477
+ return;
478
+ }
479
+
480
+ const common = {
481
+ existed_subscription: subscription.id,
482
+ period: chosen.value.id,
483
+ ...(renewal.value ? { renew_period: renewal.value.id } : {}),
484
+ ...(promo.value.trim() ? { attach_issue: promo.value.trim() } : {}),
485
+ };
486
+
487
+ if (changingPlan.value) {
488
+ emit('submit', {
489
+ ...common,
490
+ new_tariff: targetPlan.value!.id,
491
+ ...(targetOption.value ? { option: targetOption.value.id } : {}),
492
+ });
493
+
494
+ return;
495
+ }
496
+ emit('submit', { ...common, option: targetOption.value!.id });
497
+ }
498
+ function back() {
499
+ if (confirming.value) {
500
+ confirming.value = false;
501
+
502
+ return;
503
+ }
504
+ close();
505
+ }
506
+ function backdrop(event: MouseEvent) {
507
+ if (!props.modal || event.target !== dialog.value) {
508
+ return;
509
+ }
510
+
511
+ const bounds = dialog.value!.getBoundingClientRect();
512
+
513
+ if (
514
+ event.clientX < bounds.left ||
515
+ event.clientX > bounds.right ||
516
+ event.clientY < bounds.top ||
517
+ event.clientY > bounds.bottom
518
+ ) {
519
+ close();
520
+ }
521
+ }
522
+ </script>
523
+ <template>
524
+ <dialog
525
+ data-stable-modal="wide"
526
+ ref="dialog"
527
+ :aria-labelledby="`${id}-title`"
528
+ :aria-describedby="`${id}-summary`"
529
+ :aria-busy="pending"
530
+ :class="
531
+ modal
532
+ ? 'm-auto w-[880px] max-h-[calc(100dvh-32px)] max-w-[calc(100vw-32px)]'
533
+ : 'relative m-0 w-full max-w-full'
534
+ "
535
+ class="
536
+ @container box-border overflow-auto rounded-none p-0
537
+ border border-solid border-orionplace-border
538
+ bg-orionplace-surface font-orionplace text-orionplace-text
539
+ backdrop:bg-black/35 backdrop:backdrop-blur-[2px]
540
+ "
541
+ data-subscription-change-dialog
542
+ @cancel.prevent="close"
543
+ @keydown.esc.stop
544
+ @click="backdrop"
545
+ >
546
+ <form
547
+ class="grid gap-5 p-5 @min-[600px]:p-6"
548
+ @submit.prevent="submit"
549
+ >
550
+ <header class="flex items-start justify-between gap-4">
551
+ <div class="grid gap-1">
552
+ <p class="op-feature-muted m-0">
553
+ {{ changingPlan ? currentPlan : currentOption }}
554
+ </p>
555
+ <h2
556
+ :id="`${id}-title`"
557
+ class="m-0 text-lg uppercase tracking-[0.04em] @min-[600px]:text-2xl"
558
+ >
559
+ {{ changingPlan ? copy.changePlanTitle : copy.changeOptionTitle }}
560
+ </h2>
561
+ </div>
562
+ <button
563
+ type="button"
564
+ :disabled="pending"
565
+ :aria-label="copy.close"
566
+ class="
567
+ grid h-10 w-10 shrink-0 place-items-center
568
+ cursor-pointer border-0 bg-transparent p-0
569
+ text-2xl text-orionplace-text
570
+ outline-none transition-colors motion-reduce:transition-none
571
+ hover:bg-orionplace-hover focus-visible:bg-orionplace-hover
572
+ disabled:cursor-wait
573
+ "
574
+ @click="close"
575
+ >
576
+ ×
577
+ </button>
578
+ </header>
579
+ <!--
580
+ Two columns from 48rem: the choices on the left, the target plan and
581
+ the amounts on the right, so the dialog fits a laptop screen without
582
+ scrolling. Narrow screens stack them and scroll inside the dialog.
583
+ -->
584
+ <div
585
+ class="
586
+ grid min-w-0 gap-5
587
+ @min-[720px]:grid-cols-[minmax(0,1fr)_minmax(0,320px)] @min-[720px]:gap-6
588
+ "
589
+ >
590
+ <div class="grid min-w-0 content-start gap-4">
591
+ <p
592
+ :id="`${id}-summary`"
593
+ class="m-0 text-sm leading-6 text-orionplace-muted"
594
+ >
595
+ {{
596
+ changingPlan ? copy.changePlanSummary : copy.changeOptionSummary
597
+ }}
598
+ </p>
599
+ <p
600
+ v-if="unavailable"
601
+ class="op-notice op-notice-attention m-0"
602
+ role="status"
603
+ >
604
+ {{ unavailable }}
605
+ </p>
606
+ <div
607
+ v-if="changingPlan && !confirming && plans.length"
608
+ class="grid gap-2"
609
+ >
610
+ <OrionplaceSelect
611
+ v-model="planChoice"
612
+ :options="planOptions"
613
+ :label="copy.changePlanField"
614
+ :disabled="pending"
615
+ />
616
+ <span
617
+ v-if="fieldError('new_tariff')"
618
+ role="alert"
619
+ class="op-feature-error"
620
+ >
621
+ {{ fieldError('new_tariff') }}
622
+ </span>
623
+ </div>
624
+ <!--
625
+ A hidden single option still shows the backend's message about
626
+ it, so the customer learns why the change was refused.
627
+ -->
628
+ <div
629
+ v-if="!confirming && (showOptions || fieldError('option'))"
630
+ class="grid gap-2"
631
+ >
632
+ <OrionplaceSelect
633
+ v-if="showOptions"
634
+ v-model="optionChoice"
635
+ :options="optionOptions"
636
+ :label="copy.changeOptionField"
637
+ :disabled="pending"
638
+ />
639
+ <span
640
+ v-if="fieldError('option')"
641
+ role="alert"
642
+ class="op-feature-error"
643
+ >
644
+ {{ fieldError('option') }}
645
+ </span>
646
+ </div>
647
+ <fieldset
648
+ v-if="!confirming && showPeriods"
649
+ class="m-0 grid gap-2 border-0 p-0 @min-[600px]:grid-cols-2"
650
+ >
651
+ <legend class="op-feature-muted mb-2 p-0">{{ copy.period }}</legend>
652
+ <label
653
+ v-for="choice in periods"
654
+ :key="choice.id"
655
+ class="
656
+ flex cursor-pointer items-baseline justify-between gap-3
657
+ px-3 py-2
658
+ border border-solid border-orionplace-border
659
+ transition-colors motion-reduce:transition-none
660
+ hover:bg-orionplace-hover
661
+ has-[:focus-visible]:bg-orionplace-hover
662
+ has-[:checked]:border-orionplace-text
663
+ "
664
+ >
665
+ <span class="flex items-baseline gap-2">
666
+ <input
667
+ v-model="period"
668
+ type="radio"
669
+ name="period"
670
+ :value="choice.id"
671
+ :disabled="pending"
672
+ class="accent-orionplace-accent"
673
+ />
674
+ <span class="text-sm">{{ choice.length }}</span>
675
+ </span>
676
+ <span class="text-sm tabular-nums">{{ choice.price }}</span>
677
+ </label>
678
+ </fieldset>
679
+ <span
680
+ v-if="!confirming && fieldError('period')"
681
+ role="alert"
682
+ class="op-feature-error"
683
+ >
684
+ {{ fieldError('period') }}
685
+ </span>
686
+ <label
687
+ v-if="!confirming && periods.length"
688
+ class="op-feature-label"
689
+ >
690
+ <span>{{ copy.promo }}</span>
691
+ <input
692
+ v-model="promo"
693
+ class="op-feature-input"
694
+ type="text"
695
+ maxlength="20"
696
+ autocomplete="off"
697
+ :placeholder="copy.promoHint"
698
+ :disabled="pending"
699
+ />
700
+ <span
701
+ v-if="fieldError('attach_issue')"
702
+ role="alert"
703
+ class="op-feature-error"
704
+ >
705
+ {{ fieldError('attach_issue') }}
706
+ </span>
707
+ </label>
708
+ <div
709
+ v-if="!confirming && periods.length"
710
+ class="grid gap-2"
711
+ >
712
+ <OrionplaceSelect
713
+ v-model="renewalChoice"
714
+ :options="renewOptions"
715
+ :label="copy.renewalSettings"
716
+ :disabled="pending"
717
+ />
718
+ <span class="op-feature-muted leading-5">{{ renewalNote }}</span>
719
+ <span
720
+ v-if="fieldError('renew_period')"
721
+ role="alert"
722
+ class="op-feature-error"
723
+ >
724
+ {{ fieldError('renew_period') }}
725
+ </span>
726
+ </div>
727
+ </div>
728
+ <aside
729
+ class="grid min-w-0 content-start gap-4"
730
+ data-subscription-change-plan
731
+ >
732
+ <SubscriptionPlanSummary
733
+ :plan="targetPlan"
734
+ class="p-4 border border-solid border-orionplace-border"
735
+ />
736
+ <dl
737
+ v-if="periods.length"
738
+ class="
739
+ m-0 grid gap-3 p-4 text-sm
740
+ bg-orionplace-muted-surface
741
+ "
742
+ >
743
+ <div class="flex justify-between gap-3">
744
+ <dt>{{ copy.period }}</dt>
745
+ <dd class="m-0">{{ chosen?.length || '—' }}</dd>
746
+ </div>
747
+ <div class="flex justify-between gap-3">
748
+ <dt>{{ copy.planPrice }}</dt>
749
+ <dd class="m-0 tabular-nums">{{ chosen?.price || '—' }}</dd>
750
+ </div>
751
+ <div
752
+ v-if="targetOption"
753
+ class="flex justify-between gap-3"
754
+ >
755
+ <dt>{{ optionName(targetOption) }}</dt>
756
+ <dd class="m-0 tabular-nums">
757
+ {{ money(chosen?.optionAmount) }}
758
+ </dd>
759
+ </div>
760
+ <div class="flex justify-between gap-3">
761
+ <dt>
762
+ {{ copy.changeRefund
763
+ }}<OrionplaceInfoHint
764
+ :label="copy.changeRefund"
765
+ :text="
766
+ refund === undefined
767
+ ? copy.changeRefundUnknown
768
+ : copy.changeRefundHint
769
+ "
770
+ class="ml-1"
771
+ />
772
+ </dt>
773
+ <dd class="m-0 tabular-nums">{{ money(refund) }}</dd>
774
+ </div>
775
+ <div
776
+ class="
777
+ flex justify-between gap-3 pt-3
778
+ border-0 border-t border-solid border-orionplace-border
779
+ "
780
+ >
781
+ <dt>{{ copy.balance }}</dt>
782
+ <dd class="m-0 grid justify-items-end gap-1">
783
+ <span class="tabular-nums">{{ money(balance) }}</span>
784
+ <NuxtLink
785
+ v-if="low"
786
+ class="
787
+ w-fit pb-0.5 text-xs uppercase tracking-[0.08em]
788
+ text-orionplace-text no-underline
789
+ border-0 border-b border-solid border-current
790
+ outline-none hover:opacity-70 focus-visible:opacity-70
791
+ "
792
+ :to="{ path: '/wallet', query: { locale: selectionStore.localeCode } }"
793
+ >
794
+ {{ copy.topUp }}
795
+ </NuxtLink>
796
+ </dd>
797
+ </div>
798
+ <div
799
+ v-if="available !== undefined"
800
+ class="flex justify-between gap-3"
801
+ >
802
+ <dt>{{ copy.changeAvailable }}</dt>
803
+ <dd class="m-0 tabular-nums">{{ money(available) }}</dd>
804
+ </div>
805
+ </dl>
806
+ </aside>
807
+ </div>
808
+ <p
809
+ v-if="confirming"
810
+ class="op-notice m-0"
811
+ role="status"
812
+ >
813
+ {{ after }}
814
+ </p>
815
+ <p
816
+ v-if="low"
817
+ class="op-notice op-notice-attention m-0"
818
+ >
819
+ {{ lowNotice }}
820
+ </p>
821
+ <p
822
+ v-if="generalError"
823
+ role="alert"
824
+ class="op-notice op-notice-error m-0 whitespace-pre-line"
825
+ >
826
+ {{ generalError }}
827
+ </p>
828
+ <div class="grid grid-cols-[auto_1fr] gap-2">
829
+ <button
830
+ type="button"
831
+ :disabled="pending"
832
+ class="
833
+ h-11 px-6
834
+ cursor-pointer border border-solid border-orionplace-text
835
+ bg-transparent
836
+ text-xs uppercase tracking-[0.08em] text-orionplace-text
837
+ [font-family:inherit]
838
+ outline-none transition-colors motion-reduce:transition-none
839
+ hover:bg-orionplace-hover focus-visible:bg-orionplace-hover
840
+ disabled:cursor-wait
841
+ "
842
+ @click="back"
843
+ >
844
+ {{ confirming ? copy.cancel : copy.close }}
845
+ </button>
846
+ <button
847
+ type="submit"
848
+ :disabled="pending || !ready"
849
+ class="
850
+ flex h-11 items-center justify-center gap-2 px-6
851
+ cursor-pointer border border-solid border-orionplace-accent
852
+ bg-orionplace-accent
853
+ text-xs uppercase tracking-[0.08em] text-orionplace-surface
854
+ [font-family:inherit]
855
+ outline-none transition-opacity motion-reduce:transition-none
856
+ hover:opacity-85 focus-visible:opacity-85
857
+ disabled:cursor-not-allowed disabled:opacity-40
858
+ "
859
+ >
860
+ <span
861
+ v-if="pending"
862
+ aria-hidden="true"
863
+ class="
864
+ h-4 w-4 animate-spin rounded-full
865
+ border-2 border-solid border-current border-t-transparent
866
+ motion-reduce:animate-none
867
+ "
868
+ />
869
+ {{ submitLabel }}
870
+ </button>
871
+ </div>
872
+ </form>
873
+ </dialog>
874
+ </template>